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

flexflow_port.c (91445B)


      1 /*
      2  * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file.
      3  * 
      4  * Copyright 2007-2019 Broadcom Inc. All rights reserved.
      5  */
      6 
      7 
      8 #include <sal/core/libc.h>
      9 #if defined(INCLUDE_L3)
     10 
     11 #include <bcm/flow.h>
     12 #include <bcm_int/esw/flow.h>
     13 #include <bcm/error.h>
     14 #include <soc/drv.h>
     15 #include <soc/format.h>
     16 #include <bcm_int/esw/vpn.h>
     17 #include <bcm_int/esw/virtual.h>
     18 #include <bcm_int/esw/trx.h>
     19 #include <bcm_int/common/multicast.h>
     20 #include <bcm_int/esw/trident2.h>
     21 #include <bcm_int/esw/trident3.h>
     22 #include <bcm_int/esw/vxlan.h>
     23 #include <bcm_int/esw/trident2plus.h>
     24 #include <bcm_int/esw/tomahawk.h>
     25 #include <bcm_int/esw/xgs5.h>
     26 #include <bcm_int/api_xlate_port.h>
     27 #include <soc/esw/flow_db.h>
     28 #include <soc/esw/cancun.h>
     29 
     30 #define VIRTUAL_INFO(_unit_)    (&_bcm_virtual_bk_info[_unit_])
     31 #define PORT_DEFAULT_ALL (BCM_FLOW_PORT_DEFAULT | BCM_FLOW_PORT_DEFAULT_L2GRE | \
     32 		BCM_FLOW_PORT_DEFAULT_GPE | BCM_FLOW_PORT_DEFAULT_GENEVE)
     33  
     34 STATIC int
     35 _bcm_td3_flow_default_port_get(int unit, int vp, bcm_flow_port_t *flow_port);
     36 STATIC int
     37 _bcmi_esw_flow_port_get(int unit, bcm_vpn_t vpn, int vp, bcm_flow_port_t  *flow_port);
     38 
     39   /* Function:
     40  *      bcmi_esw_flow_vp_is_eline
     41  * Purpose:
     42  *      Find if given FLOW VP is ELINE
     43  * Parameters:
     44  *      unit     - Device Number
     45  *      vp   - FLOW VP
     46  *      isEline  - Flag 
     47  * Returns:
     48  *      BCM_E_XXXX
     49  * Assumes:
     50  *      l2vpn is valid
     51  */
     52 
     53 int
     54 bcmi_esw_flow_vp_is_eline( int unit, int vp, uint8 *isEline)
     55 {
     56     source_vp_entry_t svp;
     57     vfi_entry_t vfi_entry;
     58     int rv = BCM_E_PARAM;
     59     int vfi_index;
     60 
     61     if (vp == -1) {
     62         return BCM_E_PARAM;
     63     }
     64 
     65     if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeFlow)) {
     66         return BCM_E_NOT_FOUND;
     67     }
     68 
     69     rv = READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp, &svp);
     70     if (rv < 0) {
     71         return rv;
     72     }
     73 
     74     vfi_index = soc_SOURCE_VPm_field32_get(unit, &svp, VFIf);
     75     BCM_IF_ERROR_RETURN
     76         (READ_VFIm(unit, MEM_BLOCK_ALL, vfi_index, &vfi_entry));
     77 
     78     /* Set the returned VPN id */
     79     if (soc_VFIm_field32_get(unit, &vfi_entry, PT2PT_ENf)) {
     80        *isEline = 0x1;
     81     }  else {
     82        *isEline = 0x0;
     83    }
     84    return BCM_E_NONE;
     85 }
     86 
     87 /*
     88  * Function:
     89  *      _bcm_td3_flow_nexthop_glp_get
     90  * Purpose:
     91  *      Get the modid, port, trunk values for a FLOW nexthop
     92  * Returns:
     93  *      BCM_E_XXX
     94  */
     95 STATIC int
     96 _bcm_td3_flow_nexthop_glp_get(int unit, int nh_idx,
     97         bcm_module_t *modid, bcm_port_t *port, bcm_trunk_t *trunk_id)
     98 
     99 {
    100     ing_l3_next_hop_entry_t ing_nh;
    101     uint32 dt, dv;
    102 
    103     BCM_IF_ERROR_RETURN (soc_mem_read(unit,
    104         ING_L3_NEXT_HOPm, MEM_BLOCK_ANY, nh_idx, &ing_nh));
    105 
    106     dv = soc_mem_field32_dest_get(unit,
    107             ING_L3_NEXT_HOPm, &ing_nh, DESTINATIONf, &dt);
    108     if (dt == SOC_MEM_FIF_DEST_LAG) {
    109         *trunk_id = dv & SOC_MEM_FIF_DGPP_TGID_MASK;
    110     } else if (dt == SOC_MEM_FIF_DEST_DGPP) {
    111         *port = (dv & SOC_MEM_FIF_DGPP_PORT_MASK);
    112         *modid = (dv & SOC_MEM_FIF_DGPP_MOD_ID_MASK) >>
    113                     SOC_MEM_FIF_DGPP_MOD_ID_SHIFT_BITS;
    114     } else if (dt == SOC_MEM_FIF_DEST_DVP) {
    115         return BCM_E_NOT_FOUND;
    116     } else {
    117         return BCM_E_INTERNAL;
    118     }
    119 
    120     return BCM_E_NONE;
    121 }
    122 
    123 /*
    124  * Function:
    125  *      _bcm_td3_flow_port_resolve
    126  * Purpose:
    127  *      Get the modid, port, trunk values for a FLOW port
    128  * Returns:
    129  *      BCM_E_XXX
    130  */
    131 int
    132 _bcm_td3_flow_port_resolve(int unit, bcm_gport_t flow_port_id, 
    133                           bcm_if_t encap_id, bcm_module_t *modid, bcm_port_t *port,
    134                           bcm_trunk_t *trunk_id, int *id)
    135 
    136 {
    137     int rv = BCM_E_NONE;
    138     egr_l3_next_hop_entry_t egr_nh;
    139     ing_dvp_table_entry_t dvp;
    140     int ecmp=0, nh_index=-1, nh_ecmp_index=-1, vp=-1;
    141     uint32 hw_buf[SOC_MAX_MEM_FIELD_WORDS]; /* Buffer to read hw entry. */
    142     int  idx, max_ent_count, base_idx;
    143 
    144     rv = bcmi_esw_flow_check_init(unit);
    145     if (rv < 0) {
    146         return rv;
    147     }
    148 
    149     if (!BCM_GPORT_IS_FLOW_PORT(flow_port_id)) {
    150         return (BCM_E_BADID);
    151     }
    152 
    153     vp = BCM_GPORT_FLOW_PORT_ID_GET(flow_port_id);
    154     if (vp == -1) {
    155        return BCM_E_PARAM;
    156     }
    157 
    158     if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeFlow)) {
    159         return BCM_E_NOT_FOUND;
    160     }
    161     BCM_IF_ERROR_RETURN (READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp, &dvp));
    162     ecmp = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, ECMPf);
    163     if (!ecmp) {
    164         nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, 
    165                                               NEXT_HOP_INDEXf);
    166         BCM_IF_ERROR_RETURN(_bcm_td3_flow_nexthop_glp_get(unit,
    167                                 nh_index, modid, port, trunk_id));
    168     } else {
    169          /* Select the desired nhop from ECMP group - pointed by encap_id */
    170          nh_ecmp_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, ECMP_PTRf);
    171          BCM_IF_ERROR_RETURN(
    172               soc_mem_read(unit, L3_ECMP_COUNTm, MEM_BLOCK_ANY, 
    173                         nh_ecmp_index, hw_buf));
    174 
    175          if (soc_feature(unit, soc_feature_l3_ecmp_1k_groups)) {
    176               max_ent_count = soc_mem_field32_get(unit, L3_ECMP_COUNTm, 
    177                                                  hw_buf, COUNTf);
    178               base_idx = soc_mem_field32_get(unit, L3_ECMP_COUNTm, 
    179                                                  hw_buf, BASE_PTRf);
    180          }  else {
    181               max_ent_count = soc_mem_field32_get(unit, L3_ECMP_COUNTm, 
    182                                                  hw_buf, COUNT_0f);
    183               base_idx = soc_mem_field32_get(unit, L3_ECMP_COUNTm, 
    184                                                  hw_buf, BASE_PTR_0f);
    185          }
    186         max_ent_count++; /* Count is zero based. */ 
    187 
    188         if(encap_id == -1) {
    189               BCM_IF_ERROR_RETURN(
    190                    soc_mem_read(unit, L3_ECMPm, MEM_BLOCK_ANY, 
    191                         base_idx, hw_buf));
    192               nh_index = soc_mem_field32_get(unit, L3_ECMPm, 
    193                    hw_buf, NEXT_HOP_INDEXf);
    194 
    195               BCM_IF_ERROR_RETURN(_bcm_td3_flow_nexthop_glp_get(unit,
    196                                     nh_index, modid, port, trunk_id));
    197         } else {
    198             for (idx = 0; idx < max_ent_count; idx++) {
    199               BCM_IF_ERROR_RETURN(
    200                    soc_mem_read(unit, L3_ECMPm, MEM_BLOCK_ANY, 
    201                         (base_idx+idx), hw_buf));
    202               nh_index = soc_mem_field32_get(unit, L3_ECMPm, 
    203                    hw_buf, NEXT_HOP_INDEXf);
    204               BCM_IF_ERROR_RETURN (soc_mem_read(unit, EGR_L3_NEXT_HOPm, 
    205                    MEM_BLOCK_ANY, nh_index, &egr_nh));
    206               if (encap_id == soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, 
    207                                                &egr_nh, INTF_NUMf)) {
    208                   BCM_IF_ERROR_RETURN(_bcm_td3_flow_nexthop_glp_get(unit,
    209                                           nh_index, modid, port, trunk_id));
    210                 break;
    211               }
    212             }
    213         }
    214     }
    215     *id = vp;
    216     return rv;
    217 }
    218 
    219 /*
    220  * Function:
    221  *      _bcm_td3_flow_port_cnt_update
    222  * Purpose:
    223  *      Update port's VP count.
    224  * Parameters:
    225  *      unit  - (IN) SOC unit number. 
    226  *      gport - (IN) GPORT ID.
    227  *      vp    - (IN) Virtual port number.
    228  *      incr  - (IN) If TRUE, increment VP count, else decrease VP count.
    229  * Returns:
    230  *      BCM_X_XXX
    231  */
    232 
    233 STATIC int
    234 _bcm_td3_flow_port_cnt_update(int unit, bcm_gport_t gport,
    235         int vp, int incr_decr_flag)
    236 {
    237     int mod_out=-1, port_out=-1, tgid_out=-1, vp_out=-1;
    238     bcm_port_t local_member_array[SOC_MAX_NUM_PORTS];
    239     int local_member_count=0;
    240     int idx=-1;
    241     int mod_local=-1;
    242     _bcm_port_info_t *port_info;
    243     uint32 port_flags;
    244 
    245     BCM_IF_ERROR_RETURN(
    246        _bcm_td3_flow_port_resolve(unit, gport, -1, &mod_out,
    247                     &port_out, &tgid_out, &vp_out));
    248 
    249     if (vp_out == -1) {
    250        return BCM_E_PARAM;
    251     }
    252 
    253     /* Update the physical port's SW state. If associated with a trunk,
    254      * update each local physical port's SW state.
    255      */
    256 
    257     if (BCM_TRUNK_INVALID != tgid_out) {
    258 
    259         BCM_IF_ERROR_RETURN(_bcm_esw_trunk_local_members_get(unit, tgid_out, 
    260                     SOC_MAX_NUM_PORTS, local_member_array, &local_member_count));
    261 
    262         for (idx = 0; idx < local_member_count; idx++) {
    263             _bcm_port_info_access(unit, local_member_array[idx], &port_info);
    264             if (incr_decr_flag) {
    265                 port_info->vp_count++;
    266             } else {
    267                 port_info->vp_count--;
    268             }
    269             BCM_IF_ERROR_RETURN(
    270                 bcm_esw_port_vlan_member_get(
    271                     unit, local_member_array[idx], &port_flags));
    272             BCM_IF_ERROR_RETURN(
    273                 bcm_esw_port_vlan_member_set(
    274                     unit, local_member_array[idx], port_flags));
    275         }
    276     } else {
    277 #if defined(BCM_HGPROXY_COE_SUPPORT)
    278         if (soc_feature(unit, soc_feature_hgproxy_subtag_coe) &&
    279             (_bcm_xgs5_subport_coe_mod_port_local(unit, mod_out, port_out))) {
    280             BCM_IF_ERROR_RETURN(
    281                 _bcmi_coe_subport_mod_port_physical_port_get(
    282                     unit, mod_out, port_out, &port_out));
    283             mod_local = 1;
    284         } else
    285 #endif
    286         {
    287             BCM_IF_ERROR_RETURN(
    288                 _bcm_esw_modid_is_local(unit, mod_out, &mod_local));
    289             if (mod_local && soc_feature(unit, soc_feature_sysport_remap)) {
    290                 BCM_XLATE_SYSPORT_S2P(unit, &port_out);
    291             }
    292         }
    293         if (mod_local) {
    294             if (soc_feature(unit, soc_feature_sysport_remap)) { 
    295                 BCM_XLATE_SYSPORT_S2P(unit, &port_out); 
    296             }
    297             _bcm_port_info_access(unit, port_out, &port_info);
    298             if (incr_decr_flag) {
    299                 port_info->vp_count++;
    300             } else {
    301                 port_info->vp_count--;
    302             }
    303             BCM_IF_ERROR_RETURN(
    304                 bcm_esw_port_vlan_member_get(
    305                     unit, port_out, &port_flags));
    306             BCM_IF_ERROR_RETURN(
    307                 bcm_esw_port_vlan_member_set(
    308                     unit, port_out, port_flags));
    309         }
    310     }
    311 
    312     return BCM_E_NONE;
    313 }
    314 
    315 /*
    316  * Function:
    317  *      _bcm_td3_flow_eline_vp_map_set
    318  * Purpose:
    319  *      Set FLOW ELINE ports from VPN
    320  * Parameters:
    321  *      unit    - (IN) Device Number
    322  *      vpn     - (IN) VPN instance ID
    323  * Returns:
    324  *      BCM_E_XXX
    325  */
    326 STATIC int
    327 _bcm_td3_flow_eline_vp_map_set(int unit, int vfi_index, int vp1, int vp2)
    328 {
    329     vfi_entry_t vfi_entry;
    330     int rv=BCM_E_NONE;
    331     int num_vp=0;
    332 
    333     if (!_bcm_vfi_used_get(unit, vfi_index, _bcmVfiTypeFlow)) {
    334         return BCM_E_NOT_FOUND;
    335     }
    336     num_vp = soc_mem_index_count(unit, SOURCE_VPm);
    337 
    338     BCM_IF_ERROR_RETURN
    339         (READ_VFIm(unit, MEM_BLOCK_ALL, vfi_index, &vfi_entry));
    340 
    341     if (soc_VFIm_field32_get(unit, &vfi_entry, PT2PT_ENf)) {
    342          if ((vp1 > 0) && (vp1 < num_vp)) {
    343               soc_VFIm_field32_set(unit, &vfi_entry, VP_0f, vp1);
    344          } else {
    345               return BCM_E_PARAM;
    346          }
    347          if ((vp2 > 0) && (vp2 < num_vp)) {
    348               soc_VFIm_field32_set(unit, &vfi_entry, VP_1f, vp2);
    349          } else {
    350               return BCM_E_PARAM;
    351          }
    352     } else {
    353          /* ELAN */
    354          return BCM_E_PARAM;
    355     }
    356 
    357     rv = WRITE_VFIm(unit, MEM_BLOCK_ALL, vfi_index, &vfi_entry);
    358     return rv;
    359 }
    360 /*
    361  * Function:
    362  *      _bcm_td3_flow_eline_vp_map_get
    363  * Purpose:
    364  *      Get FLOW ELINE ports from VPN
    365  * Parameters:
    366  *      unit    - (IN) Device Number
    367  *      vpn     - (IN) VPN instance ID
    368  * Returns:
    369  *      BCM_E_XXX
    370  */
    371 
    372 STATIC int
    373 _bcm_td3_flow_eline_vp_map_get(int unit, int vfi_index, int *vp1, int *vp2)
    374 {
    375     vfi_entry_t vfi_entry;
    376 
    377     if (!_bcm_vfi_used_get(unit, vfi_index, _bcmVfiTypeFlow)) {
    378         return BCM_E_NOT_FOUND;
    379     }
    380 
    381     BCM_IF_ERROR_RETURN
    382         (READ_VFIm(unit, MEM_BLOCK_ALL, vfi_index, &vfi_entry));
    383 
    384     if (soc_VFIm_field32_get(unit, &vfi_entry, PT2PT_ENf)) {
    385         *vp1 = soc_VFIm_field32_get(unit, &vfi_entry, VP_0f);
    386         *vp2 = soc_VFIm_field32_get(unit, &vfi_entry, VP_1f);
    387          return BCM_E_NONE;
    388     } else {
    389          return BCM_E_PARAM;
    390     }
    391 }
    392 
    393 /*
    394  * Function:
    395  *      _bcm_td3_flow_eline_vp_map_clear
    396  * Purpose:
    397  *      Clear FLOW ELINE ports from VPN
    398  * Parameters:
    399  *      unit    - (IN) Device Number
    400  *      vpn     - (IN) VPN instance ID
    401  * Returns:
    402  *      BCM_E_XXX
    403  */
    404 
    405 STATIC int
    406 _bcm_td3_flow_eline_vp_map_clear(int unit, int vfi_index, int vp1, int vp2)
    407 {
    408     vfi_entry_t vfi_entry;
    409     int rv=BCM_E_NONE;
    410     int num_vp=0;
    411 
    412     if (!_bcm_vfi_used_get(unit, vfi_index, _bcmVfiTypeFlow)) {
    413         return BCM_E_NOT_FOUND;
    414     }
    415 
    416     num_vp = soc_mem_index_count(unit, SOURCE_VPm);
    417 
    418     BCM_IF_ERROR_RETURN
    419         (READ_VFIm(unit, MEM_BLOCK_ALL, vfi_index, &vfi_entry));
    420 
    421     if (soc_VFIm_field32_get(unit, &vfi_entry, PT2PT_ENf)) {
    422         if ((vp1 > 0) && (vp1 < num_vp)) {
    423             soc_VFIm_field32_set(unit, &vfi_entry, VP_0f, 0);
    424         }
    425         if ((vp2 > 0) && (vp2 < num_vp)) {
    426             soc_VFIm_field32_set(unit, &vfi_entry, VP_1f, 0);
    427         }
    428     } else {
    429         /* ELAN */
    430         return BCM_E_PARAM;
    431     }
    432     rv = WRITE_VFIm(unit, MEM_BLOCK_ALL, vfi_index, &vfi_entry);
    433     return rv;
    434 }
    435 
    436 /*
    437  * Function:
    438  *           _bcm_td3_flow_next_hop_set
    439  * Purpose:
    440  *           Set FLOW NextHop Entry.
    441  * Parameters:
    442  *           IN :  Unit
    443  *           IN :  nh_index
    444  * Returns:
    445  *           BCM_E_XXX
    446  */
    447 
    448 int
    449 _bcm_td3_flow_next_hop_set(int unit, int nh_index, uint32 flags, int vp, int drop)
    450 {
    451     int rv = BCM_E_NONE;
    452     ing_l3_next_hop_entry_t ing_nh;
    453     bcm_port_t  port = -1;
    454     bcm_module_t modid = -1, local_modid = -1;
    455     bcm_trunk_t tgid = -1;
    456     int  num_ports=0, idx=-1;
    457     int  old_nh_index=-1;
    458     int replace=0;
    459     int gport = 0;
    460     _bcm_vp_info_t vp_info;
    461     soc_mem_t hw_mem = ING_L3_NEXT_HOPm;
    462     bcm_trunk_member_t *tmp_member_gports_array = NULL;
    463 
    464     BCM_IF_ERROR_RETURN(soc_mem_read(unit,
    465         hw_mem, MEM_BLOCK_ANY, nh_index, &ing_nh));
    466     soc_mem_field32_set(unit, hw_mem, &ing_nh,
    467         ENTRY_TYPEf, _BCM_VXLAN_INGRESS_NEXT_HOP_ENTRY_TYPE);
    468     if (SOC_MEM_FIELD_VALID(unit, hw_mem, MTU_SIZEf)) {
    469         soc_mem_field32_set(unit, hw_mem, &ing_nh, MTU_SIZEf, 0x3fff);
    470     }
    471     BCM_IF_ERROR_RETURN(
    472         soc_mem_write(unit, hw_mem, MEM_BLOCK_ALL, nh_index, &ing_nh));
    473 
    474     if (flags & BCM_L3_IPMC) {
    475         egr_l3_next_hop_entry_t egr_nh;
    476         int entry_type = 0;
    477         int hw_mem = EGR_L3_NEXT_HOPm;
    478 
    479         (void)_bcm_vp_info_get(unit, vp, &vp_info);
    480 
    481         SOC_IF_ERROR_RETURN(soc_mem_read(unit, hw_mem, MEM_BLOCK_ALL,
    482                                               nh_index, &egr_nh));
    483         entry_type = soc_mem_field32_get(unit, hw_mem, &egr_nh, DATA_TYPEf);
    484 
    485         if (vp_info.flags & _BCM_VP_INFO_NETWORK_PORT) { /* network VP */
    486 
    487             /* most should be setup already */
    488             if (entry_type == _BCM_VXLAN_EGR_NEXT_HOP_L3MC_VIEW) { 
    489                 soc_mem_field32_set(unit, hw_mem, &egr_nh, L3MC__HG_HDR_SELf, 
    490                                     1);
    491                 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
    492                                 L3MC__L3_DROPf, drop ? 1 : 0);
    493                 SOC_IF_ERROR_RETURN(soc_mem_write(unit, hw_mem,
    494                                   MEM_BLOCK_ALL, nh_index, &egr_nh));
    495             } else {
    496                 /* no change for all other views  */
    497             }
    498         } else {   /* access VP */
    499             /* fixed view should use sd_tag view for access VP */
    500             if (!BCMI_L3_NH_FLEX_VIEW(entry_type)) {
    501                 if (entry_type != _BCM_VXLAN_EGR_NEXT_HOP_SDTAG_VIEW) {
    502                     /* first time setup */
    503                     sal_memset(&egr_nh, 0, sizeof(egr_nh));
    504                     soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
    505                             DATA_TYPEf, _BCM_VXLAN_EGR_NEXT_HOP_SDTAG_VIEW);
    506                 }
    507                 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
    508                             SD_TAG__DVPf, vp);
    509                 SOC_IF_ERROR_RETURN(soc_mem_write(unit, hw_mem,
    510                                   MEM_BLOCK_ALL, nh_index, &egr_nh));
    511             } else {
    512                 /* proper process for flex views should be done already */
    513             }
    514         }
    515     } else { /* Only for FLOW Unicast Nexthops */
    516         replace = flags & BCM_L3_REPLACE;
    517 
    518         BCM_IF_ERROR_RETURN(_bcm_td3_flow_nexthop_glp_get(unit,
    519                                 nh_index, &modid, &port, &tgid));
    520 
    521         BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &local_modid));
    522         if (tgid != -1) {
    523              BCM_IF_ERROR_RETURN(_bcm_trunk_id_validate(unit, tgid));
    524              rv = bcm_esw_trunk_get(unit, tgid, NULL, 0, NULL, &num_ports);
    525              if (BCM_FAILURE(rv)) {
    526                  return BCM_E_PORT;
    527              }
    528              if (num_ports == 0) {
    529                  return BCM_E_NONE;
    530              }
    531              if(soc_feature(unit, soc_feature_egr_modport_to_nhi)) {
    532                  tmp_member_gports_array = sal_alloc(
    533                      sizeof(bcm_trunk_member_t) * num_ports, "tmp_member_gports_arry");
    534                  if (tmp_member_gports_array == NULL) {
    535                      return BCM_E_MEMORY;
    536                  }
    537                  sal_memset(tmp_member_gports_array, 0,
    538                      sizeof(bcm_trunk_member_t) * num_ports);
    539                  rv = bcm_esw_trunk_get(unit, tgid, NULL,
    540                           num_ports, tmp_member_gports_array, &num_ports);
    541                  if (BCM_FAILURE(rv)) {
    542                      goto clean_up;
    543                  }
    544              }
    545         } else {
    546             if (modid != local_modid) {
    547                 if (!soc_feature(unit, soc_feature_egr_modport_to_nhi)) {
    548                     /* Ignore EGR_PORT_TO_NHI_MAPPINGs */
    549                     return BCM_E_NONE;
    550                 }
    551             }
    552 
    553             if(soc_feature(unit, soc_feature_egr_modport_to_nhi)) {
    554                 /* Alloc one trunk member size memory */
    555                 tmp_member_gports_array = sal_alloc(
    556                     sizeof(bcm_trunk_member_t), "tmp_member_gports_arry");
    557                 if (tmp_member_gports_array == NULL) {
    558                     return BCM_E_MEMORY;
    559                 }
    560                 sal_memset(tmp_member_gports_array, 0,
    561                     sizeof(bcm_trunk_member_t));
    562                 BCM_GPORT_MODPORT_SET(gport, modid, port);
    563                 tmp_member_gports_array[num_ports++].gport = gport;
    564             }
    565         }
    566 
    567        for (idx = 0; idx < num_ports; idx++) {
    568             if(soc_feature(unit, soc_feature_egr_modport_to_nhi)) {
    569                 gport = tmp_member_gports_array[idx].gport;
    570             }
    571 
    572             rv = _bcm_trx_gport_to_nhi_get(unit, gport, &old_nh_index);
    573             if (BCM_FAILURE(rv)) {
    574                  goto clean_up;
    575             }
    576             if (old_nh_index && !replace) {
    577                 if (old_nh_index != nh_index) {
    578                     /* Limitation: For TD/TR3/TD2,
    579                        VxLAN egress port can be configured with one NHI */
    580                     rv = BCM_E_RESOURCE;
    581                     goto clean_up;
    582                 }
    583             } else {
    584                 rv = _bcm_trx_gport_to_nhi_set(unit, gport, nh_index);
    585                 if (BCM_FAILURE(rv)) {
    586                     goto clean_up;
    587                 }
    588             }
    589          }
    590     }
    591 
    592 clean_up:
    593     if (NULL != tmp_member_gports_array) {
    594         sal_free(tmp_member_gports_array);
    595     }
    596     return rv;
    597 }
    598 
    599 /*
    600  * Function:
    601  *      bcm_td3_flow_nexthop_reset
    602  * Purpose:
    603  *      Reset VXLAN NextHop entry
    604  * Parameters:
    605  *      IN :  Unit
    606  *           IN :  nh_index
    607  * Returns:
    608  *      BCM_E_XXX
    609  */
    610 
    611 STATIC int
    612 _bcm_td3_flow_nexthop_reset(int unit, int nh_index)
    613 {
    614     int rv=BCM_E_NONE;
    615     ing_l3_next_hop_entry_t ing_nh;
    616     egr_l3_next_hop_entry_t egr_nh;
    617     bcm_port_t      port=0;
    618     bcm_trunk_t tgid= BCM_TRUNK_INVALID;
    619     int  num_ports=0, idx=-1;
    620     soc_mem_t      hw_mem;
    621     bcm_module_t modid=0, local_modid=0;
    622     uint8 multicast_entry=0;
    623     int  old_nh_index=-1;
    624     int gport = 0;
    625     uint32 entry_type=0;
    626     uint32 view_id;
    627     uint32 action_set;
    628     uint32 l3_intf;
    629     int nh_index_out;
    630     bcm_trunk_member_t *tmp_member_gports_array = NULL;
    631 
    632     hw_mem = EGR_L3_NEXT_HOPm;
    633 
    634     BCM_IF_ERROR_RETURN(soc_mem_read(unit, hw_mem,
    635                                   MEM_BLOCK_ANY, nh_index, &egr_nh));
    636 
    637     if (SOC_MEM_FIELD_VALID(unit, hw_mem, DATA_TYPEf)) {
    638         entry_type = soc_mem_field32_get(unit, hw_mem, &egr_nh, DATA_TYPEf);
    639     }
    640 
    641     if (BCMI_L3_NH_FLEX_VIEW(entry_type)) {
    642         /* Get view id corresponding to the entry type. */
    643         rv = soc_flow_db_mem_to_view_id_get(unit,
    644                                      EGR_L3_NEXT_HOPm,
    645                                      SOC_FLOW_DB_KEY_TYPE_INVALID,
    646                                      entry_type,
    647                                      0,
    648                                      NULL,
    649                                      &view_id);
    650         BCM_IF_ERROR_RETURN(rv);
    651 
    652         if (SOC_MEM_FIELD_VALID(unit, view_id, INTF_ACTION_SETf)) {
    653            action_set = soc_mem_field32_get(unit, view_id, &egr_nh,
    654                                    INTF_ACTION_SETf);
    655 
    656            l3_intf = soc_format_field32_get(unit, INTF_ACTION_SETfmt,
    657                                    &action_set, INTF_PTRf); /* INTF_NUMf */
    658 
    659             /* determine if this is an IPMC entry from the l3 interface */
    660             _bcm_th_ipmc_l3_intf_next_hop_get(unit, l3_intf,
    661                                               &nh_index_out);
    662             if (nh_index_out == -2) {
    663                 multicast_entry = 1;
    664             }
    665         }
    666     }
    667     else if (_BCM_VXLAN_EGR_NEXT_HOP_L3MC_VIEW == entry_type) {
    668        if (soc_feature(unit, soc_feature_egr_l3_next_hop_next_ptr)) {
    669            if (0x1 == soc_mem_field32_get(unit, hw_mem, &egr_nh,
    670                             L3MC__NEXT_PTR_TYPEf)) {
    671                multicast_entry = 1; /* Multicast NextHop */
    672            }
    673        }
    674     }
    675 
    676     hw_mem = ING_L3_NEXT_HOPm;
    677     BCM_IF_ERROR_RETURN(soc_mem_read(unit, hw_mem,
    678                                   MEM_BLOCK_ANY, nh_index, &ing_nh));
    679     soc_mem_field32_set(unit, hw_mem, &ing_nh,
    680                                             DROPf, 0x0);
    681     soc_mem_field32_set(unit, hw_mem, &ing_nh,
    682                                             ENTRY_TYPEf, 0x0);
    683     BCM_IF_ERROR_RETURN(soc_mem_write(unit, hw_mem,
    684                                             MEM_BLOCK_ALL, nh_index, &ing_nh));
    685     rv = _bcm_td3_flow_nexthop_glp_get(unit,
    686                                 nh_index, &modid, &port, &tgid);
    687     if (BCM_FAILURE(rv)) {
    688         if (rv == BCM_E_NOT_FOUND) {
    689             /* not a GLP, could be a DVP in riot case. No further process */
    690             return BCM_E_NONE;
    691         } else {
    692             return rv;
    693         }
    694     }
    695 
    696     BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get (unit, &local_modid));
    697     if (tgid != BCM_TRUNK_INVALID) {
    698          rv = _bcm_trunk_id_validate(unit, tgid);
    699          if (BCM_FAILURE(rv)) {
    700             return BCM_E_PORT;
    701          }
    702          rv = bcm_esw_trunk_get(unit, tgid, NULL, 0, NULL, &num_ports);
    703          if (BCM_FAILURE(rv)) {
    704              return BCM_E_PORT;
    705          }
    706          if (num_ports == 0) {
    707              return BCM_E_NONE;
    708          }
    709 
    710          if(soc_feature(unit, soc_feature_egr_modport_to_nhi)) {
    711              tmp_member_gports_array = sal_alloc(
    712                  sizeof(bcm_trunk_member_t) * num_ports, "tmp_member_gports_arry");
    713              if (tmp_member_gports_array == NULL) {
    714                  return BCM_E_MEMORY;
    715              }
    716              sal_memset(tmp_member_gports_array, 0,
    717                         sizeof(bcm_trunk_member_t) * num_ports);
    718              rv = bcm_esw_trunk_get(unit, tgid, NULL,
    719                           num_ports, tmp_member_gports_array, &num_ports);
    720              if (BCM_FAILURE(rv)) {
    721                  goto clean_up;
    722              }
    723          }
    724     } else {
    725         if (modid != local_modid) {
    726             if (!soc_feature(unit, soc_feature_egr_modport_to_nhi)) {
    727                 /* Ignore EGR_PORT_TO_NHI_MAPPINGs */
    728                 return BCM_E_NONE;
    729             }
    730         }
    731         if(soc_feature(unit, soc_feature_egr_modport_to_nhi)) {
    732             /* Alloc one trunk member size memory */
    733             tmp_member_gports_array = sal_alloc(
    734                  sizeof(bcm_trunk_member_t), "tmp_member_gports_arry");
    735             if (tmp_member_gports_array == NULL) {
    736                  return BCM_E_MEMORY;
    737             }
    738             sal_memset(tmp_member_gports_array, 0,
    739                        sizeof(bcm_trunk_member_t));
    740             BCM_GPORT_MODPORT_SET(gport, modid, port);
    741             tmp_member_gports_array[num_ports++].gport = gport;
    742         }
    743     }
    744 
    745     if (!multicast_entry) {
    746         for (idx = 0; idx < num_ports; idx++) {
    747             if(soc_feature(unit, soc_feature_egr_modport_to_nhi)) {
    748                 gport = tmp_member_gports_array[idx].gport;
    749             }
    750 
    751             rv = _bcm_trx_gport_to_nhi_get(unit, gport, &old_nh_index);
    752             if (BCM_FAILURE(rv)) {
    753                  goto clean_up;
    754             }
    755             if (old_nh_index == nh_index) {
    756                 rv = _bcm_trx_gport_to_nhi_set(unit, gport, 0);
    757                 if (BCM_FAILURE(rv)) {
    758                     goto clean_up;
    759                 }
    760             }
    761         }
    762     }
    763 
    764 clean_up:
    765     if (NULL != tmp_member_gports_array) {
    766         sal_free(tmp_member_gports_array);
    767     }
    768     return rv;
    769 }
    770 /*
    771  * Function:
    772  *           _bcm_td3_flow_egress_reset
    773  * Purpose:
    774  *           Reset Flow Egress NextHop
    775  * Parameters:
    776  *           IN :  Unit
    777  *           IN :  nh_index
    778  * Returns:
    779  *           BCM_E_XXX
    780  */
    781 
    782 int
    783 _bcm_td3_flow_egress_reset(int unit, int nh_index)
    784 {
    785     ing_l3_next_hop_entry_t ing_nh;
    786     soc_mem_t      hw_mem;
    787     int rv=BCM_E_NONE;
    788 
    789     hw_mem = ING_L3_NEXT_HOPm;
    790     BCM_IF_ERROR_RETURN(soc_mem_read(unit, hw_mem,
    791                 MEM_BLOCK_ANY, nh_index, &ing_nh));
    792     soc_mem_field32_set(unit, hw_mem, &ing_nh,
    793                 ENTRY_TYPEf, 0x0);
    794     if (SOC_MEM_FIELD_VALID(unit, ING_L3_NEXT_HOPm, MTU_SIZEf)) {
    795         soc_mem_field32_set(unit, ING_L3_NEXT_HOPm,
    796                 &ing_nh, MTU_SIZEf, 0x0);
    797     }
    798     BCM_IF_ERROR_RETURN(soc_mem_write(unit, hw_mem,
    799                                   MEM_BLOCK_ALL, nh_index, &ing_nh));
    800 
    801     rv = _bcm_td3_flow_nexthop_reset(unit, nh_index);
    802     return rv;
    803 }
    804 /*
    805  * Function:
    806  *           _bcm_td3_flow_egress_get
    807  * Purpose:
    808  *           Get FLOW Egress NextHop
    809  * Parameters:
    810  *           IN :  Unit
    811  *           IN :  nh_index
    812  * Returns:
    813  *           BCM_E_XXX
    814  */
    815 
    816 int
    817 _bcm_td3_flow_egress_get(int unit, bcm_l3_egress_t *egr, int nh_index)
    818 {
    819     int int_l3_flag;
    820     int_l3_flag = BCM_XGS3_L3_ENT_FLAG(BCM_XGS3_L3_TBL_PTR(unit, next_hop),
    821                                        nh_index);
    822     if (int_l3_flag == _BCM_L3_FLOW_ONLY) {
    823          egr->flags2 |= BCM_L3_FLOW_ONLY;
    824     }
    825 
    826     return BCM_E_NONE;
    827 }
    828 
    829 /*
    830  * Function:
    831  *      _bcm_td3_flow_eline_vp_configure
    832  * Purpose:
    833  *      Configure FLOW ELINE virtual port
    834  * Parameters:
    835  *      unit    - (IN) Device Number
    836  *      vpn     - (IN) VPN instance ID
    837  * Returns:
    838  *      BCM_E_XXX
    839  */
    840 
    841 STATIC int
    842 _bcm_td3_flow_eline_vp_configure (int unit, int vfi_index, int active_vp, 
    843                   source_vp_entry_t *svp, int tpid_enable, bcm_flow_port_t  *flow_port)
    844 {
    845     int rv = BCM_E_NONE;
    846     int network_group=0;
    847 
    848     /* Set SOURCE_VP */
    849     soc_SOURCE_VPm_field32_set(unit, svp, CLASS_IDf,
    850                                 flow_port->if_class);
    851 
    852     /* Default Split Horizon Group Id
    853      * 0 - For Access Port;1 - For Network Port*/
    854     network_group = flow_port->network_group_id;
    855     rv = _bcm_validate_splithorizon_network_group(unit,
    856             flow_port->flags & BCM_FLOW_PORT_NETWORK, &network_group);
    857     BCM_IF_ERROR_RETURN(rv);
    858     if (flow_port->flags & BCM_FLOW_PORT_NETWORK) {
    859         if (soc_feature(unit, soc_feature_multiple_split_horizon_group)) {
    860             soc_SOURCE_VPm_field32_set(unit, svp, NETWORK_GROUPf,
    861                  network_group);
    862         } else {
    863             soc_SOURCE_VPm_field32_set(unit, svp, NETWORK_PORTf, 1);
    864         }
    865     } else {
    866         if (soc_feature(unit, soc_feature_multiple_split_horizon_group)) {
    867             soc_SOURCE_VPm_field32_set(unit, svp, NETWORK_GROUPf,
    868                         network_group);
    869         } else {
    870             soc_SOURCE_VPm_field32_set(unit, svp, NETWORK_PORTf, 0);
    871         }  
    872     }
    873 
    874     if (flow_port->flags & BCM_FLOW_PORT_SERVICE_TAGGED) {
    875          soc_SOURCE_VPm_field32_set(unit, svp, SD_TAG_MODEf, 1);
    876          soc_SOURCE_VPm_field32_set(unit, svp, TPID_ENABLEf, tpid_enable);
    877     } else {
    878          soc_SOURCE_VPm_field32_set(unit, svp, SD_TAG_MODEf, 0);
    879     }
    880 
    881     soc_SOURCE_VPm_field32_set(unit, svp, DISABLE_VLAN_CHECKSf, 1);
    882     soc_SOURCE_VPm_field32_set(unit, svp, 
    883                            ENTRY_TYPEf, _BCM_VXLAN_SOURCE_VP_TYPE_VFI); /* VFI Type */
    884     soc_SOURCE_VPm_field32_set(unit, svp, VFIf, vfi_index);
    885 
    886     rv = WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, active_vp, svp);
    887     if ((vfi_index != _BCM_FLOW_VFI_INVALID) &&
    888         (flow_port->flags & BCM_FLOW_PORT_NETWORK)) {
    889         if ( BCM_E_NONE != soc_cancun_app_dest_entry_set (unit, SOURCE_VPm,
    890             active_vp, ENTRY_TYPEf, CANCUN_APP__SOURCE_VP__No_Control_Word,
    891             _BCM_VXLAN_SOURCE_VP_TYPE_VFI)) {
    892             LOG_ERROR(BSL_LS_BCM_FLOW,
    893                (BSL_META_U(unit,"SOURCE_VP cancun app cfg error\n")));
    894         }
    895     }
    896 
    897     return rv;
    898 }
    899 
    900 
    901 
    902 /*
    903  * Function:
    904  *      _bcm_td3_flow_access_niv_pe_set
    905  * Purpose:
    906  *      Set VXLAN Access virtual port which is of NIV/PE type
    907  * Parameters:
    908  *      unit    - (IN) Device Number
    909  *      vp      -  (IN) Access Virtual Port
    910  *      vfi      -  (IN) Virtial forwarding instance
    911  * Returns:
    912  *      BCM_E_XXX
    913  */
    914 
    915 STATIC int
    916 _bcm_td3_flow_access_niv_pe_set (int unit, int vp, int vfi)
    917 {
    918     source_vp_entry_t svp;
    919     int  rv = BCM_E_PARAM; 
    920 
    921         rv = READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp, &svp);
    922         if (rv < 0) {
    923             return rv;
    924         }
    925 
    926         if (vfi == _BCM_FLOW_VFI_INVALID) {
    927             soc_SOURCE_VPm_field32_set(unit, &svp, 
    928                                        ENTRY_TYPEf, _BCM_VXLAN_SOURCE_VP_TYPE_INVALID);
    929         } else {
    930             /* Initialize VP parameters */
    931             soc_SOURCE_VPm_field32_set(unit, &svp, 
    932                                        ENTRY_TYPEf, _BCM_VXLAN_SOURCE_VP_TYPE_VFI);
    933         }     
    934         soc_SOURCE_VPm_field32_set(unit, &svp, VFIf, vfi);
    935         rv = WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, vp, &svp);
    936         return rv;
    937 }
    938 
    939 /*
    940  * Function:
    941  *      _bcm_td3_flow_access_niv_pe_reset
    942  * Purpose:
    943  *      Reset FLOW Access virtual port which is of NIV/PE type
    944  * Parameters:
    945  *      unit    - (IN) Device Number
    946  *      vp      -  (IN) Access Virtual Port
    947  * Returns:
    948  *      BCM_E_XXX
    949  */
    950 
    951 STATIC int
    952 _bcm_td3_flow_access_niv_pe_reset (int unit, int vp)
    953 {
    954     source_vp_entry_t svp;
    955 
    956     BCM_IF_ERROR_RETURN(READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp, &svp));
    957 
    958     /* Initialize VP parameters */
    959     soc_SOURCE_VPm_field32_set(unit, &svp,
    960         ENTRY_TYPEf, _BCM_VXLAN_SOURCE_VP_TYPE_VLAN);
    961     soc_SOURCE_VPm_field32_set(unit, &svp, VFIf, 0);
    962     BCM_IF_ERROR_RETURN(WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, vp, &svp));
    963 
    964     return BCM_E_NONE;
    965 }
    966 
    967 
    968 /*
    969  * Function:
    970  *      bcm_td3_flow_default_port_add
    971  * Purpose:
    972  *      Add FLOW port to a VPN
    973  * Parameters:
    974  *      unit    - (IN) Device Number
    975  *      vpn     - (IN) VPN instance ID
    976  *      flow_port - (IN/OUT) flow_port information (OUT : flow_port_id)
    977  * Returns:
    978  *      BCM_E_XXX
    979  */
    980 
    981 STATIC int
    982 _bcm_td3_flow_default_port_add(int unit, bcm_flow_port_t  *flow_port,
    983                                int *vp_number)
    984 {
    985     source_vp_entry_t svp;
    986     int rv = BCM_E_PARAM, vp=0, num_vp=0;
    987     int network_group=0;
    988     int cml_default_enable=0, cml_default_new=0, cml_default_move=0;
    989     _bcm_vp_info_t vp_info;
    990 
    991     _bcm_vp_info_init(&vp_info);
    992     vp_info.vp_type = _bcmVpTypeFlow;
    993     if(flow_port->flags & BCM_FLOW_PORT_NETWORK) { 
    994         vp_info.flags |= _BCM_VP_INFO_NETWORK_PORT;
    995     }
    996 
    997     num_vp = soc_mem_index_count(unit, SOURCE_VPm);
    998 
    999    /* ======== Allocate/Get Virtual_Port =============== */
   1000     if (flow_port->flags & BCM_FLOW_PORT_REPLACE) {
   1001         vp = BCM_GPORT_FLOW_PORT_ID_GET(flow_port->flow_port_id);
   1002         if (vp == -1) {
   1003             return BCM_E_PARAM;
   1004         }
   1005 
   1006         if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeFlow)) {
   1007             return BCM_E_NOT_FOUND;
   1008         }
   1009         rv = READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp, &svp);
   1010         if (rv < 0) {
   1011             return rv;
   1012         }
   1013 
   1014         /* Decrement old-port's VP count */
   1015         rv = _bcm_td3_flow_port_cnt_update(unit, flow_port->flow_port_id, vp, FALSE);
   1016         if (rv < 0) {
   1017             return rv;
   1018         }
   1019 
   1020     } else if (flow_port->flags & BCM_FLOW_PORT_WITH_ID ) {
   1021        if (!BCM_GPORT_IS_FLOW_PORT(flow_port->flow_port_id)) {
   1022             return (BCM_E_BADID);
   1023         }
   1024 
   1025         vp = BCM_GPORT_FLOW_PORT_ID_GET(flow_port->flow_port_id);
   1026         if (vp == -1) {
   1027             return BCM_E_PARAM;
   1028         }
   1029         /* Vp index zero is reserved in function _bcm_virtual_init because of 
   1030          * HW restriction. 
   1031          */
   1032         if (vp >= num_vp || vp < 1) {
   1033             return BCM_E_BADID;
   1034         } 
   1035         if (_bcm_vp_used_get(unit, vp, _bcmVpTypeFlow)) { 
   1036             return BCM_E_EXISTS;
   1037         }
   1038 
   1039         BCM_IF_ERROR_RETURN(_bcm_vp_used_set(unit, vp, vp_info));
   1040         sal_memset(&svp, 0, sizeof(source_vp_entry_t));
   1041     } else {
   1042        rv = _bcm_vp_alloc(unit, 0, (num_vp - 1), 1, SOURCE_VPm, vp_info, &vp);
   1043        if (rv < 0) {
   1044            return rv;
   1045        }
   1046         sal_memset(&svp, 0, sizeof(source_vp_entry_t));
   1047         BCM_IF_ERROR_RETURN(_bcm_vp_used_set(unit, vp, vp_info));
   1048     }
   1049 
   1050     /* ======== Configure SVP/DVP Properties ========== */
   1051     soc_SOURCE_VPm_field32_set(unit, &svp, CLASS_IDf, 
   1052                                flow_port->if_class);
   1053     if (soc_feature(unit, soc_feature_multiple_split_horizon_group)) {
   1054         network_group = flow_port->network_group_id;
   1055         rv = _bcm_validate_splithorizon_network_group(unit,
   1056                 flow_port->flags & BCM_FLOW_PORT_NETWORK, &network_group);
   1057         BCM_IF_ERROR_RETURN(rv);
   1058         soc_SOURCE_VPm_field32_set(unit, &svp, NETWORK_GROUPf,
   1059                 network_group);
   1060     } else {
   1061         soc_SOURCE_VPm_field32_set(unit, &svp, NETWORK_PORTf, 1);
   1062     }
   1063 
   1064     soc_SOURCE_VPm_field32_set(unit, &svp, 
   1065                                       ENTRY_TYPEf, _BCM_VXLAN_SOURCE_VP_TYPE_VFI);
   1066 
   1067     /* Keep CML in the replace operation. It may be set by bcm_td2_vxlan_port_learn_set before */
   1068     if (!(flow_port->flags & BCM_FLOW_PORT_REPLACE)) {
   1069         rv = _bcm_vp_default_cml_mode_get (unit, 
   1070                        &cml_default_enable, &cml_default_new, 
   1071                        &cml_default_move);
   1072         if (rv < 0) {
   1073             return rv;
   1074         }
   1075             
   1076         if (cml_default_enable) {
   1077             /* Set the CML to default values */
   1078             soc_SOURCE_VPm_field32_set(unit, &svp, CML_FLAGS_NEWf, cml_default_new);
   1079             soc_SOURCE_VPm_field32_set(unit, &svp, CML_FLAGS_MOVEf, cml_default_move);
   1080         } else {
   1081             /* Set the CML to PVP_CML_SWITCH by default (hw learn and forward) */
   1082             soc_SOURCE_VPm_field32_set(unit, &svp, CML_FLAGS_NEWf, 0x8);
   1083             soc_SOURCE_VPm_field32_set(unit, &svp, CML_FLAGS_MOVEf, 0x8);
   1084         }
   1085     }
   1086     if (soc_mem_field_valid(unit, SOURCE_VPm, DISABLE_VLAN_CHECKSf)) {
   1087         if (!soc_feature(unit, soc_feature_vlan_vfi_membership)) {
   1088             soc_SOURCE_VPm_field32_set(unit, &svp, DISABLE_VLAN_CHECKSf, 1);
   1089         }
   1090     }
   1091 
   1092     /* Configure VXLAN_DEFAULT_NETWORK_SVPr.SVP */
   1093     rv = WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, vp, &svp);
   1094     BCM_IF_ERROR_RETURN(rv);
   1095 
   1096     if ( BCM_E_NONE != soc_cancun_app_dest_entry_set (unit, SOURCE_VPm,
   1097         vp, ENTRY_TYPEf, CANCUN_APP__SOURCE_VP__No_Control_Word,
   1098          _BCM_VXLAN_SOURCE_VP_TYPE_VFI)) {
   1099          LOG_ERROR(BSL_LS_BCM_FLOW,
   1100            (BSL_META_U(unit,"SOURCE_VP cancun app cfg error\n")));
   1101     }
   1102 
   1103     BCM_GPORT_FLOW_PORT_ID_SET(flow_port->flow_port_id, vp);
   1104 
   1105     /* Increment new-port's VP count */
   1106     rv = _bcm_td3_flow_port_cnt_update(unit, flow_port->flow_port_id, vp, TRUE);
   1107     BCM_IF_ERROR_RETURN(rv);
   1108     *vp_number = vp;
   1109     return rv;
   1110 }
   1111 
   1112 /*
   1113  * Function:
   1114  *      _bcm_td3_flow_default_port_delete
   1115  * Purpose:
   1116  *      Delete FLOW Default port from a VPN
   1117  * Parameters:
   1118  *      unit       - (IN) Device Number
   1119  *      vpn        - (IN) VPN instance ID
   1120  *      flow_port_id - (IN) vxlan port information
   1121  * Returns:
   1122  *      BCM_E_XXX
   1123  */
   1124 
   1125 int
   1126 _bcm_td3_flow_default_port_delete(int unit, bcm_vpn_t vpn, int vp)
   1127 {
   1128     source_vp_entry_t svp;
   1129     int rv = BCM_E_UNAVAIL;
   1130     int vfi_index= -1;
   1131     bcm_gport_t flow_port_id;
   1132 
   1133     if ( vpn != BCM_FLOW_VPN_INVALID) {
   1134          _BCM_FLOW_VPN_GET(vfi_index, _BCM_FLOW_VPN_TYPE_ELAN,  vpn);
   1135          if (!_bcm_vfi_used_get(unit, vfi_index, _bcmVfiTypeFlow)) {
   1136             return BCM_E_NOT_FOUND;
   1137          }
   1138     }
   1139 
   1140     if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeFlow)) {
   1141         return BCM_E_NOT_FOUND;
   1142     }
   1143 
   1144     /* Set FLOW port ID */
   1145     BCM_GPORT_FLOW_PORT_ID_SET(flow_port_id, vp);
   1146 
   1147     /* Clear the SVP and DVP table entries */
   1148     sal_memset(&svp, 0, sizeof(source_vp_entry_t));
   1149     rv = WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, vp, &svp);
   1150     if (rv < 0) {
   1151         return rv;
   1152     }
   1153 
   1154     /* Decrement port's VP count */
   1155     rv = _bcm_td3_flow_port_cnt_update(unit, flow_port_id, vp, FALSE);
   1156     if (rv < 0) {
   1157         return rv;
   1158     }
   1159 
   1160     /* Free the VP */
   1161     (void) _bcm_vp_free(unit, _bcmVpTypeFlow, 1, vp);
   1162 
   1163     return rv;
   1164 
   1165 }
   1166 
   1167 /*
   1168  * Function:
   1169  *      _bcm_td3_flow_eline_port_add
   1170  * Purpose:
   1171  *      Add FLOW ELINE port to a VPN
   1172  * Parameters:
   1173  *      unit    - (IN) Device Number
   1174  *      vpn     - (IN) VPN instance ID
   1175  *      flow_port - (IN/OUT) FLOW port information (OUT : flow_port_id)
   1176  * Returns:
   1177  *      BCM_E_XXX
   1178  */
   1179 
   1180 STATIC int
   1181 _bcm_td3_flow_eline_port_add(int unit, bcm_vpn_t vpn, bcm_flow_port_t  *flow_port)
   1182 {
   1183     int active_vp = 0; /* default VP */
   1184     source_vp_entry_t svp1, svp2;
   1185     uint8 vp_valid_flag = 0;
   1186     int tpid_enable = 0, tpid_index=-1;
   1187     int  rv = BCM_E_PARAM; 
   1188     int num_vp=0;
   1189     int vp1=-1, vp2=-1, vfi_index= -1;
   1190     _bcm_vp_info_t vp_info;
   1191 
   1192     _bcm_vp_info_init(&vp_info);
   1193     vp_info.vp_type = _bcmVpTypeFlow;
   1194 
   1195         if ( vpn != BCM_FLOW_VPN_INVALID) {
   1196             _BCM_FLOW_VPN_GET(vfi_index, _BCM_FLOW_VPN_TYPE_ELINE,  vpn);
   1197              if (!_bcm_vfi_used_get(unit, vfi_index, _bcmVfiTypeFlow)) {
   1198                 return BCM_E_NOT_FOUND;
   1199              }
   1200         } else {
   1201              vfi_index = _BCM_FLOW_VFI_INVALID;
   1202         }
   1203 
   1204         num_vp = soc_mem_index_count(unit, SOURCE_VPm);
   1205         if ( vpn != BCM_FLOW_VPN_INVALID) {
   1206 
   1207              /* ---- Read in current table values for VP1 and VP2 ----- */
   1208              (void) _bcm_td3_flow_eline_vp_map_get (unit, vfi_index,  &vp1,  &vp2);
   1209 
   1210             if (_bcm_vp_used_get(unit, vp1, _bcmVpTypeFlow)) {
   1211                 BCM_IF_ERROR_RETURN (
   1212                    READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp1, &svp1));
   1213                 if (soc_SOURCE_VPm_field32_get(unit, &svp1, ENTRY_TYPEf) == 0x1) {
   1214                     vp_valid_flag |= 0x1;  /* -- VP1 Valid ----- */
   1215                 }
   1216             }
   1217 
   1218             if (_bcm_vp_used_get(unit, vp2, _bcmVpTypeFlow)) {
   1219                 BCM_IF_ERROR_RETURN (
   1220                    READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp2, &svp2));
   1221                 if (soc_SOURCE_VPm_field32_get(unit, &svp2, ENTRY_TYPEf) == 0x1) {
   1222                     vp_valid_flag |= 0x2;        /* -- VP2 Valid ----- */
   1223                 }
   1224             }
   1225 
   1226             if (flow_port->flags & BCM_FLOW_PORT_REPLACE) {
   1227                 active_vp = BCM_GPORT_FLOW_PORT_ID_GET(flow_port->flow_port_id);
   1228                 if (active_vp == -1) {
   1229                    return BCM_E_PARAM;
   1230                 }
   1231                 if (!_bcm_vp_used_get(unit, active_vp, _bcmVpTypeFlow)) {
   1232                      return BCM_E_NOT_FOUND;
   1233                 }
   1234                 /* Decrement old-port's VP count */
   1235                 rv = _bcm_td3_flow_port_cnt_update(unit, flow_port->flow_port_id,
   1236                                                      active_vp, FALSE);
   1237                 if (rv < 0) {
   1238                     return rv;
   1239                 }
   1240             }
   1241         }
   1242 
   1243         switch (vp_valid_flag) {
   1244 
   1245               case 0x0: /* No VP is valid */
   1246                              if (flow_port->flags & BCM_FLOW_PORT_REPLACE) {
   1247                                   return BCM_E_NOT_FOUND;
   1248                              }
   1249 
   1250                              if (flow_port->flags & BCM_FLOW_PORT_WITH_ID) {
   1251                                 vp1 = BCM_GPORT_FLOW_PORT_ID_GET(flow_port->flow_port_id);
   1252                                 if (vp1 == -1) {
   1253                                      return BCM_E_PARAM;
   1254                                 }
   1255 
   1256                                 if (_bcm_vp_used_get(unit, vp1, _bcmVpTypeFlow)) {
   1257                                      return BCM_E_EXISTS;
   1258                                 }
   1259                                 if (vp1 >= num_vp) {
   1260                                      return (BCM_E_BADID);
   1261                                 }
   1262                                 vp_info.flags &= ~(_BCM_VP_INFO_NETWORK_PORT);
   1263                                 BCM_IF_ERROR_RETURN(_bcm_vp_used_set(unit, vp1, vp_info));
   1264 
   1265                              } else {
   1266 
   1267                                 /* No entries are used, allocate a new VP index for VP1 */
   1268 
   1269                                 vp_info.flags &= ~(_BCM_VP_INFO_NETWORK_PORT);
   1270                                 rv = _bcm_vp_alloc(unit, 0, (num_vp - 1), 1, SOURCE_VPm, vp_info, &vp1);
   1271                                 if (rv < 0) {
   1272                                   return rv;
   1273                                 }
   1274                                 /* Allocate a new VP index for VP2 */
   1275                                 vp_info.flags |= _BCM_VP_INFO_NETWORK_PORT;
   1276                                  rv = _bcm_vp_alloc(unit, 0, (num_vp - 1), 1, SOURCE_VPm, vp_info, &vp2);
   1277                                   if (rv < 0) {
   1278                                      (void) _bcm_vp_free(unit, _bcmVpTypeFlow, 1, vp1);
   1279                                       return rv;
   1280                                   }
   1281                              }
   1282 
   1283                              active_vp = vp1;
   1284                              vp_valid_flag = 1;
   1285                              sal_memset(&svp1, 0, sizeof(source_vp_entry_t));
   1286                              sal_memset(&svp2, 0, sizeof(source_vp_entry_t));
   1287                              (void) _bcm_td3_flow_eline_vp_map_set(unit, vfi_index, vp1, vp2);
   1288                              break;
   1289 
   1290 
   1291          case 0x1:    /* Only VP1 is valid */   
   1292                              if (flow_port->flags & BCM_FLOW_PORT_REPLACE) {
   1293                                   if (active_vp != vp1) {
   1294                                        return BCM_E_NOT_FOUND;
   1295                                   }
   1296                              } else if (flow_port->flags & BCM_FLOW_PORT_WITH_ID) {
   1297                                 vp2 = BCM_GPORT_FLOW_PORT_ID_GET(flow_port->flow_port_id);
   1298                                 if (vp2 == -1) {
   1299                                      return BCM_E_PARAM;
   1300                                 }
   1301 
   1302                                 if (_bcm_vp_used_get(unit, vp2, _bcmVpTypeFlow)) {
   1303                                      return BCM_E_EXISTS;
   1304                                 }
   1305                                 if (vp2 >= num_vp) {
   1306                                      return (BCM_E_BADID);
   1307                                 }
   1308                                 vp_info.flags |= _BCM_VP_INFO_NETWORK_PORT;
   1309                                 BCM_IF_ERROR_RETURN(_bcm_vp_used_set(unit, vp2, vp_info));
   1310 
   1311                                 active_vp = vp2;
   1312                              } else {
   1313                                   active_vp = vp2;
   1314                                   vp_valid_flag = 3;
   1315                                   sal_memset(&svp2, 0, sizeof(source_vp_entry_t));
   1316                              }
   1317 
   1318                              (void) _bcm_td3_flow_eline_vp_map_set(unit, vfi_index, vp1, vp2);
   1319                              break;
   1320 
   1321 
   1322 
   1323          case 0x2: /* Only VP2 is valid */
   1324                              if (flow_port->flags & BCM_FLOW_PORT_REPLACE) {
   1325                                   if (active_vp != vp2) {
   1326                                        return BCM_E_NOT_FOUND;
   1327                                   }
   1328                              } else if (flow_port->flags & BCM_FLOW_PORT_WITH_ID) {
   1329                                 vp1 = BCM_GPORT_FLOW_PORT_ID_GET(flow_port->flow_port_id);
   1330                                 if (vp1 == -1) {
   1331                                      return BCM_E_PARAM;
   1332                                 }
   1333 
   1334                                 if (_bcm_vp_used_get(unit, vp1, _bcmVpTypeFlow)) {
   1335                                      return BCM_E_EXISTS;
   1336                                 }
   1337                                 if (vp1 >= num_vp) {
   1338                                      return (BCM_E_BADID);
   1339                                 }
   1340                                 vp_info.flags &= ~(_BCM_VP_INFO_NETWORK_PORT);
   1341                                 BCM_IF_ERROR_RETURN(_bcm_vp_used_set(unit, vp1, vp_info));
   1342                                 active_vp = vp1;
   1343 
   1344                              } else {
   1345                                   active_vp = vp1;
   1346                                   vp_valid_flag = 3;
   1347                                    sal_memset(&svp1, 0, sizeof(source_vp_entry_t));
   1348                              }
   1349 
   1350                              (void) _bcm_td3_flow_eline_vp_map_set(unit, vfi_index, vp1, vp2);
   1351                              break;
   1352 
   1353 
   1354               
   1355          case 0x3: /* VP1 and VP2 are valid */
   1356                               if (!(flow_port->flags & BCM_FLOW_PORT_REPLACE)) {
   1357                                    return BCM_E_FULL;
   1358                               }
   1359                              break;
   1360        }
   1361 
   1362        if (active_vp == -1) {
   1363            return BCM_E_CONFIG;
   1364        }
   1365 
   1366         /* Set FLOW port ID */
   1367         if (!(flow_port->flags & BCM_FLOW_PORT_REPLACE)) {
   1368             BCM_GPORT_FLOW_PORT_ID_SET(flow_port->flow_port_id, active_vp);
   1369         }
   1370 
   1371        /* ======== Configure Service-Tag Properties =========== */
   1372        if (flow_port->flags & BCM_FLOW_PORT_SERVICE_TAGGED) {
   1373             rv = _bcm_fb2_outer_tpid_lkup(unit, flow_port->egress_service_tpid,
   1374                                            &tpid_index);
   1375             if (rv < 0) {
   1376                 goto flow_cleanup;
   1377             }
   1378             tpid_enable = (1 << tpid_index);
   1379        }
   1380 
   1381        /* ======== Configure SVP Property ========== */
   1382        if (active_vp == vp1) {
   1383            rv  = _bcm_td3_flow_eline_vp_configure (unit, vfi_index, active_vp, &svp1, 
   1384                                                     tpid_enable, flow_port);
   1385        } else if (active_vp == vp2) {
   1386            rv  = _bcm_td3_flow_eline_vp_configure (unit, vfi_index, active_vp, &svp2, 
   1387                                                     tpid_enable, flow_port);
   1388        }
   1389        if (rv < 0) {
   1390             goto flow_cleanup;
   1391        }
   1392 
   1393 /* match API 
   1394         rv = _bcm_td2_vxlan_match_add(unit, vxlan_port, active_vp, vpn);
   1395         if (rv < 0) {
   1396             goto vxlan_cleanup;
   1397         }
   1398 */
   1399 
   1400         /* Increment new-port's VP count */
   1401         rv = _bcm_td3_flow_port_cnt_update(unit, flow_port->flow_port_id, active_vp, TRUE);
   1402         if (rv < 0) {
   1403             goto flow_cleanup;
   1404         }
   1405 
   1406         /* Set FLOW port ID */
   1407         if (!(flow_port->flags & BCM_FLOW_PORT_REPLACE)) {
   1408             BCM_GPORT_FLOW_PORT_ID_SET(flow_port->flow_port_id, active_vp);
   1409         }
   1410 
   1411 flow_cleanup:
   1412         if (rv < 0) {
   1413             if (tpid_enable) {
   1414                 (void) _bcm_fb2_outer_tpid_entry_delete(unit, tpid_index);
   1415             }
   1416             /* Free the VP's */
   1417             if (vp_valid_flag) {
   1418                 if (vp1 != -1) {
   1419                     (void) _bcm_vp_free(unit, _bcmVpTypeFlow, 1, vp1);
   1420                 }
   1421                 if (vp2 != -1) {
   1422                     (void) _bcm_vp_free(unit, _bcmVpTypeFlow, 1, vp2);
   1423                 }
   1424             }
   1425         }
   1426         return rv;
   1427 }
   1428 
   1429 /*
   1430  * Function:
   1431  *     _bcm_td3_flow_elan_port_add
   1432  * Purpose:
   1433  *      Add FLOW ELAN port to a VPN
   1434  * Parameters:
   1435  *   unit - (IN) Device Number
   1436  *   vpn - (IN) VPN instance ID
   1437  *   flow_port - (IN/OUT) flow port information (OUT : flow_port_id)
   1438  * Returns:
   1439  *     BCM_E_XXX
   1440  */
   1441 
   1442 STATIC int
   1443 _bcm_td3_flow_elan_port_add(int unit, bcm_vpn_t vpn, bcm_flow_port_t *flow_port)
   1444 {
   1445     int vp, num_vp, vfi=0;
   1446     source_vp_entry_t svp;
   1447     source_vp_2_entry_t svp2;
   1448     uint32 tpid_enable = 0; 
   1449     int tpid_index=-1;
   1450     int rv = BCM_E_PARAM;
   1451     int cml_default_enable=0, cml_default_new=0, cml_default_move=0;
   1452     _bcm_vp_info_t vp_info;
   1453     int network_group=0;
   1454     uint32 svp1[SOC_MAX_MEM_WORDS];
   1455 
   1456     if (vpn != BCM_FLOW_VPN_INVALID) {
   1457         _BCM_FLOW_VPN_GET(vfi, _BCM_FLOW_VPN_TYPE_ELAN,  vpn);
   1458         if (!_bcm_vfi_used_get(unit, vfi, _bcmVfiTypeFlow)) {
   1459             return BCM_E_NOT_FOUND;
   1460         }
   1461     } else {
   1462         vfi = _BCM_FLOW_VFI_INVALID;
   1463     }
   1464     num_vp = soc_mem_index_count(unit, SOURCE_VPm);
   1465 
   1466     _bcm_vp_info_init(&vp_info);
   1467     vp_info.vp_type = _bcmVpTypeFlow;
   1468     if (flow_port->flags & BCM_FLOW_PORT_NETWORK) {
   1469         vp_info.flags |= _BCM_VP_INFO_NETWORK_PORT;
   1470     }
   1471 
   1472    /* ======== Allocate/Get Virtual_Port =============== */
   1473     if (flow_port->flags & BCM_FLOW_PORT_REPLACE) {
   1474         if (BCM_GPORT_IS_NIV_PORT(flow_port->flow_port_id) ||
   1475             BCM_GPORT_IS_EXTENDER_PORT(flow_port->flow_port_id)) {
   1476             if (BCM_GPORT_IS_NIV_PORT(flow_port->flow_port_id)) {
   1477                vp = BCM_GPORT_NIV_PORT_ID_GET((flow_port->flow_port_id));
   1478             } else if (BCM_GPORT_IS_EXTENDER_PORT(flow_port->flow_port_id)) {
   1479                vp = BCM_GPORT_EXTENDER_PORT_ID_GET((flow_port->flow_port_id));
   1480             }
   1481             rv = _bcm_td3_flow_access_niv_pe_set (unit, vp, vfi);
   1482             if (BCM_SUCCESS(rv)) {
   1483                /* Set FLOW port ID */
   1484                BCM_GPORT_FLOW_PORT_ID_SET(flow_port->flow_port_id, vp);
   1485                rv = _bcm_vp_used_set(unit, vp, vp_info);
   1486             }
   1487             return rv;
   1488         } else if (BCM_GPORT_IS_TRUNK(flow_port->flow_port_id)) {
   1489             bcm_trunk_member_t trunk_member;
   1490             int                port_count = 0;
   1491             bcm_trunk_t        tid = 0;
   1492             int                tid_is_vp_lag = FALSE;
   1493             tid = BCM_GPORT_TRUNK_GET(flow_port->flow_port_id);
   1494             BCM_IF_ERROR_RETURN(
   1495                 _bcm_esw_trunk_id_is_vp_lag(unit, tid, &tid_is_vp_lag));
   1496             if (tid_is_vp_lag) {
   1497                 BCM_IF_ERROR_RETURN(
   1498                     bcm_td2_vp_lag_get(unit, tid, NULL, 1,
   1499                                        &trunk_member, &port_count));
   1500                 if (BCM_GPORT_IS_NIV_PORT(trunk_member.gport) ||
   1501                     BCM_GPORT_IS_EXTENDER_PORT(trunk_member.gport)) {
   1502                     BCM_IF_ERROR_RETURN(
   1503                         _bcm_esw_trunk_tid_to_vp_lag_vp(unit, tid, &vp));
   1504                     rv = _bcm_td3_flow_access_niv_pe_set(unit, vp, vfi);
   1505                     if (BCM_SUCCESS(rv)) {
   1506                        rv = _bcm_vp_used_set(unit, vp, vp_info);
   1507                     }
   1508                     return rv;
   1509                 }
   1510             }
   1511         }
   1512 
   1513         vp = BCM_GPORT_FLOW_PORT_ID_GET(flow_port->flow_port_id);
   1514         if (vp == -1) {
   1515             return BCM_E_PARAM;
   1516         }
   1517 
   1518         if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeFlow)) {
   1519             return BCM_E_NOT_FOUND;
   1520         }
   1521 
   1522         BCM_IF_ERROR_RETURN(READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp, &svp));
   1523 
   1524         BCM_IF_ERROR_RETURN(READ_SVP_ATTRS_1m(unit, MEM_BLOCK_ANY, vp, &svp1));
   1525 
   1526         BCM_IF_ERROR_RETURN(READ_SOURCE_VP_2m(unit, MEM_BLOCK_ANY, vp, &svp2));
   1527 
   1528         /* Decrement old-port's VP count */
   1529         BCM_IF_ERROR_RETURN(_bcm_td3_flow_port_cnt_update(
   1530                 unit, flow_port->flow_port_id, vp, FALSE));
   1531     } else if (flow_port->flags & BCM_FLOW_PORT_WITH_ID ) {
   1532        if (!BCM_GPORT_IS_FLOW_PORT(flow_port->flow_port_id)) {
   1533             return (BCM_E_BADID);
   1534         }
   1535 
   1536         vp = BCM_GPORT_FLOW_PORT_ID_GET(flow_port->flow_port_id);
   1537         if (vp == -1) {
   1538             return BCM_E_PARAM;
   1539         }
   1540         /* Vp index zero is reserved in function _bcm_virtual_init because of 
   1541          * HW restriction. 
   1542          */
   1543         if (vp >= num_vp || vp < 1) {
   1544             return BCM_E_BADID;
   1545         }
   1546         if (_bcm_vp_used_get(unit, vp, _bcmVpTypeAny)) {
   1547             return BCM_E_EXISTS;
   1548         }
   1549         BCM_IF_ERROR_RETURN(_bcm_vp_used_set(unit, vp, vp_info));
   1550 
   1551         sal_memset(&svp, 0, sizeof(source_vp_entry_t));
   1552 
   1553         sal_memset(svp1, 0, sizeof(uint32) * SOC_MAX_MEM_WORDS);
   1554 
   1555         sal_memset(&svp2, 0, sizeof(source_vp_2_entry_t));
   1556     } else {
   1557         /* allocate a new VP index */
   1558         BCM_IF_ERROR_RETURN(_bcm_vp_alloc
   1559             (unit, 0, (num_vp - 1), 1, SOURCE_VPm, vp_info, &vp));
   1560         BCM_GPORT_FLOW_PORT_ID_SET(flow_port->flow_port_id, vp);
   1561 
   1562         sal_memset(&svp, 0, sizeof(source_vp_entry_t));
   1563 
   1564         sal_memset(svp1, 0, sizeof(uint32) * SOC_MAX_MEM_WORDS);
   1565 
   1566         sal_memset(&svp2, 0, sizeof(source_vp_2_entry_t));
   1567     }
   1568 
   1569     /* ======== Configure Service-Tag Properties =========== */
   1570     if (flow_port->flags & BCM_FLOW_PORT_SERVICE_TAGGED) {
   1571         rv = _bcm_fb2_outer_tpid_lkup(unit,
   1572             flow_port->egress_service_tpid, &tpid_index);
   1573         _BCM_FLOW_CLEANUP(rv)
   1574 
   1575         tpid_enable = (1 << tpid_index);
   1576         soc_SOURCE_VPm_field32_set(unit, &svp, SD_TAG_MODEf, 1);
   1577         soc_SVP_ATTRS_1m_field_set(unit, &svp1, TPID_ENABLEf, &tpid_enable);
   1578     } else {
   1579         soc_SOURCE_VPm_field32_set(unit, &svp, SD_TAG_MODEf, 0);
   1580     }
   1581 
   1582     /* ======== Configure SVP/DVP Properties ========== */
   1583     soc_SOURCE_VPm_field32_set(unit, &svp, CLASS_IDf, flow_port->if_class);
   1584     soc_SOURCE_VPm_field32_set(unit, &svp, ENTRY_TYPEf, _BCM_VXLAN_SOURCE_VP_TYPE_VFI);
   1585 
   1586     /* Default Split Horizon Group Id
   1587      * 0 - For Access Port;1 - For Network Port*/
   1588     network_group = flow_port->network_group_id;
   1589     rv = _bcm_validate_splithorizon_network_group(unit,
   1590             flow_port->flags & BCM_FLOW_PORT_NETWORK, &network_group);
   1591     BCM_IF_ERROR_RETURN(rv);
   1592     if (flow_port->flags & BCM_FLOW_PORT_NETWORK) {
   1593         if (soc_feature(unit, soc_feature_multiple_split_horizon_group)) {  
   1594             soc_SOURCE_VPm_field32_set(unit, &svp, NETWORK_GROUPf,
   1595                         network_group);
   1596         } else {
   1597             soc_SOURCE_VPm_field32_set(unit, &svp, NETWORK_PORTf, 1);
   1598         }
   1599     } else {
   1600            if (soc_feature(unit, soc_feature_multiple_split_horizon_group)) {
   1601             soc_SOURCE_VPm_field32_set(unit, &svp, NETWORK_GROUPf,
   1602                     network_group);
   1603            } else {
   1604                soc_SOURCE_VPm_field32_set(unit, &svp, NETWORK_PORTf, 0);
   1605            }
   1606     }
   1607     soc_SOURCE_VPm_field32_set(unit, &svp, VFIf, vfi);
   1608     /* Keep CML in the replace operation. It may be set by bcm_td2_vxlan_port_learn_set before */
   1609     if (!(flow_port->flags & BCM_FLOW_PORT_REPLACE)) {
   1610         rv = _bcm_vp_default_cml_mode_get (unit, &cml_default_enable,
   1611                                     &cml_default_new, &cml_default_move);
   1612         _BCM_FLOW_CLEANUP(rv)
   1613 
   1614         if (cml_default_enable) {
   1615             /* Set the CML to default values */
   1616             soc_SOURCE_VPm_field32_set(unit, &svp, CML_FLAGS_NEWf, cml_default_new);
   1617             soc_SOURCE_VPm_field32_set(unit, &svp, CML_FLAGS_MOVEf, cml_default_move);
   1618         } else {
   1619             /* Set the CML to PVP_CML_SWITCH by default (hw learn and forward) */
   1620             soc_SOURCE_VPm_field32_set(unit, &svp, CML_FLAGS_NEWf, 0x8);
   1621             soc_SOURCE_VPm_field32_set(unit, &svp, CML_FLAGS_MOVEf, 0x8);
   1622         }
   1623     }
   1624     if (soc_mem_field_valid(unit, SOURCE_VPm, DISABLE_VLAN_CHECKSf)) {
   1625         if (!soc_feature(unit, soc_feature_vlan_vfi_membership)) {
   1626             soc_SOURCE_VPm_field32_set(unit, &svp, DISABLE_VLAN_CHECKSf, 1);
   1627         }
   1628     }
   1629 
   1630     rv = WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, vp, &svp);
   1631 
   1632     _BCM_FLOW_CLEANUP(WRITE_SVP_ATTRS_1m(unit, MEM_BLOCK_ALL, vp, &svp1));
   1633 
   1634     _BCM_FLOW_CLEANUP(WRITE_SOURCE_VP_2m(unit, MEM_BLOCK_ALL, vp, &svp2));
   1635 
   1636     if ((vfi != _BCM_FLOW_VFI_INVALID) &&
   1637         (flow_port->flags & BCM_FLOW_PORT_NETWORK)) {
   1638         if ( BCM_E_NONE != soc_cancun_app_dest_entry_set (unit, SOURCE_VPm,
   1639             vp, ENTRY_TYPEf, CANCUN_APP__SOURCE_VP__No_Control_Word,
   1640             _BCM_VXLAN_SOURCE_VP_TYPE_VFI)) {
   1641             LOG_ERROR(BSL_LS_BCM_FLOW,
   1642                (BSL_META_U(unit,"SOURCE_VP cancun app cfg error\n")));
   1643         }
   1644     }
   1645 
   1646     _BCM_FLOW_CLEANUP(rv)
   1647 
   1648     /* Configure VP match criteria */
   1649     /*rv = _bcm_td2_vxlan_match_add(unit, vxlan_port, vp, vpn);*/      /* for match API */
   1650     _BCM_FLOW_CLEANUP(rv)
   1651 
   1652     /* Increment new-port's VP count */
   1653     rv = _bcm_td3_flow_port_cnt_update(unit, flow_port->flow_port_id, vp, TRUE);
   1654     _BCM_FLOW_CLEANUP(rv)
   1655 
   1656     return BCM_E_NONE;
   1657 
   1658 cleanup:
   1659     if (tpid_enable) {
   1660         (void) _bcm_fb2_outer_tpid_entry_delete(unit, tpid_index);
   1661     }
   1662     if (!(flow_port->flags & BCM_FLOW_PORT_REPLACE)) {
   1663         (void) _bcm_vp_free(unit, _bcmVpTypeFlow, 1, vp);
   1664     }
   1665     return rv;
   1666 }
   1667 
   1668 /*
   1669  * Function:
   1670  *      _bcm_td3_flow_eline_port_delete
   1671  * Purpose:
   1672  *      Delete FLOW ELINE port from a VPN
   1673  * Parameters:
   1674  *      unit       - (IN) Device Number
   1675  *      vpn        - (IN) VPN instance ID
   1676  *      flow_port_id - (IN) flow port information
   1677  * Returns:
   1678  *      BCM_E_XXX
   1679  */
   1680 
   1681 int
   1682 _bcm_td3_flow_eline_port_delete(int unit, bcm_vpn_t vpn, int active_vp)
   1683 {
   1684     source_vp_entry_t svp;
   1685     source_vp_2_entry_t svp_2_entry;
   1686     int network_port_flag=0;
   1687     int vp1=0, vp2=0, vfi_index= -1;
   1688     int rv = BCM_E_UNAVAIL;
   1689     bcm_gport_t  flow_port_id;
   1690     _bcm_vp_info_t vp_info;
   1691 
   1692     if ( vpn != BCM_FLOW_VPN_INVALID) {
   1693          _BCM_FLOW_VPN_GET(vfi_index, _BCM_VXLAN_VPN_TYPE_ELINE,  vpn);
   1694          if (!_bcm_vfi_used_get(unit, vfi_index, _bcmVfiTypeFlow)) {
   1695             return BCM_E_NOT_FOUND;
   1696          }
   1697     } else {
   1698          vfi_index = _BCM_FLOW_VFI_INVALID;
   1699     }
   1700 
   1701     if (!_bcm_vp_used_get(unit, active_vp, _bcmVpTypeFlow)) {
   1702         return BCM_E_NOT_FOUND;
   1703     }
   1704 
   1705     /* Set FLOW port ID */
   1706     BCM_GPORT_FLOW_PORT_ID_SET(flow_port_id, active_vp);
   1707 
   1708     /* ---- Read in current table values for VP1 and VP2 ----- */
   1709     (void) _bcm_td3_flow_eline_vp_map_get (unit, vfi_index,  &vp1,  &vp2);
   1710 
   1711 /*  flow_match API will handle this
   1712     bcm_flow_port_t_init(&flow_port);
   1713     flow_port.flow_port_id = flow_port_id;
   1714     BCM_IF_ERROR_RETURN(bcmi_esw_flow_port_get(unit, vpn, &flow_port));
   1715     rv = _bcm_td2_vxlan_match_delete(unit, active_vp, vxlan_port);
   1716     if ( rv < 0 ) {
   1717         if (rv != BCM_E_NOT_FOUND) {
   1718              return rv;
   1719         } else {
   1720              rv = BCM_E_NONE;
   1721         }
   1722     }
   1723 */
   1724 
   1725     /* If the other port is valid, point it to itself */
   1726     if (active_vp == vp1) {
   1727         rv = _bcm_td3_flow_eline_vp_map_clear (unit, vfi_index, active_vp, 0);
   1728     } else if (active_vp == vp2) {
   1729         rv = _bcm_td3_flow_eline_vp_map_clear (unit, vfi_index, 0, active_vp);
   1730     }
   1731 
   1732     if (rv >= 0) {
   1733 
   1734         /* Check for Network-Port */
   1735         BCM_IF_ERROR_RETURN(_bcm_vp_info_get(unit, active_vp, &vp_info));
   1736         if (vp_info.flags & _BCM_VP_INFO_NETWORK_PORT) {
   1737             network_port_flag = TRUE;
   1738         }
   1739 
   1740         if (!network_port_flag) {
   1741             sal_memset(&svp_2_entry, 0, sizeof(source_vp_2_entry_t));
   1742             BCM_IF_ERROR_RETURN
   1743                 (WRITE_SOURCE_VP_2m(unit, MEM_BLOCK_ALL, active_vp, &svp_2_entry));
   1744         }
   1745 
   1746         /* Invalidate the VP being deleted */
   1747         sal_memset(&svp, 0, sizeof(source_vp_entry_t));
   1748         rv = WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, active_vp, &svp);
   1749     }
   1750 
   1751     if (rv < 0) {
   1752         return rv;
   1753     }
   1754 
   1755     /* Decrement port's VP count */
   1756     rv = _bcm_td3_flow_port_cnt_update(unit, flow_port_id, active_vp, FALSE);
   1757     if (rv < 0) {
   1758         return rv;
   1759     }
   1760 
   1761     /* Free the VP */
   1762     (void) _bcm_vp_free(unit, _bcmVpTypeVxlan, 1, active_vp);
   1763     return rv;
   1764 
   1765 }
   1766 
   1767 /*
   1768  * Function:
   1769  *      _bcm_td3_flow_elan_port_delete
   1770  * Purpose:
   1771  *      Delete FLOW ELAN port from a VPN
   1772  * Parameters:
   1773  *      unit       - (IN) Device Number
   1774  *      vpn        - (IN) VPN instance ID
   1775  *      flow_port_id - (IN) flow port information
   1776  * Returns:
   1777  *      BCM_E_XXX
   1778  */
   1779 
   1780 int
   1781 _bcm_td3_flow_elan_port_delete(int unit, bcm_vpn_t vpn, int vp)
   1782 {
   1783     source_vp_entry_t svp;
   1784     source_vp_2_entry_t svp_2_entry;
   1785     int network_port_flag=0;
   1786     int vfi_index= -1;
   1787     bcm_gport_t flow_port_id;
   1788     bcm_flow_port_t  flow_port;
   1789     _bcm_vp_info_t vp_info;
   1790 
   1791     if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeFlow)) {
   1792         return BCM_E_NOT_FOUND;
   1793     }
   1794 
   1795     /* Check for Network-Port */
   1796     BCM_IF_ERROR_RETURN(_bcm_vp_info_get(unit, vp, &vp_info));
   1797     if (vp_info.flags & _BCM_VP_INFO_NETWORK_PORT) {
   1798         network_port_flag = TRUE;
   1799     }
   1800 
   1801     /* Set FLOW port ID */
   1802     BCM_GPORT_FLOW_PORT_ID_SET(flow_port_id, vp);
   1803     bcm_flow_port_t_init(&flow_port);
   1804     flow_port.flow_port_id = flow_port_id;
   1805     BCM_IF_ERROR_RETURN(bcmi_esw_flow_port_get(unit, vpn, &flow_port));
   1806 
   1807 /*  handled by flow_match API
   1808 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   1809     if ((!network_port_flag) && (vp_info.flags & _BCM_VP_INFO_SHARED_PORT)) {
   1810         if (VXLAN_INFO(unit)->match_key[vp].match_count > 0) {
   1811             BCM_IF_ERROR_RETURN(bcm_td2p_share_vp_delete(unit, vpn, vp));
   1812         }
   1813         if (vpn != BCM_FLOW_VPN_INVALID) {
   1814             return BCM_E_NONE;
   1815         }
   1816     } else
   1817 #endif
   1818     {
   1819         rv = _bcm_td2_vxlan_match_delete(unit, vp, vxlan_port);
   1820         if (rv < 0 && rv != BCM_E_NOT_FOUND) {
   1821             return rv;
   1822         }
   1823     }
   1824     (void)bcm_td2_vxlan_match_clear(unit, vp);
   1825 */
   1826 
   1827     if ( vpn != BCM_FLOW_VPN_INVALID) {
   1828         if (!network_port_flag) { /* Check VPN only for Access VP */
   1829             _BCM_FLOW_VPN_GET(vfi_index, _BCM_FLOW_VPN_TYPE_ELAN,  vpn);
   1830             if (!_bcm_vfi_used_get(unit, vfi_index, _bcmVfiTypeFlow)) {
   1831                 return BCM_E_NOT_FOUND;
   1832             }
   1833             if (_bcm_vp_used_get(unit, vp, _bcmVpTypeNiv) ||
   1834                 _bcm_vp_used_get(unit, vp, _bcmVpTypeExtender)) {
   1835                 (void) _bcm_vp_free(unit, _bcmVpTypeVxlan, 1, vp);
   1836                 return _bcm_td3_flow_access_niv_pe_reset (unit, vp);
   1837             }
   1838         }
   1839     }
   1840 
   1841     /* Decrement port's VP count */
   1842     BCM_IF_ERROR_RETURN(_bcm_td3_flow_port_cnt_update(unit, flow_port_id, vp, FALSE));
   1843 
   1844     /* Clear the SVP table entries */
   1845     sal_memset(&svp, 0, sizeof(source_vp_entry_t));
   1846     BCM_IF_ERROR_RETURN(WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, vp, &svp));
   1847 
   1848     if (!network_port_flag) {
   1849         sal_memset(&svp_2_entry, 0, sizeof(source_vp_2_entry_t));
   1850         BCM_IF_ERROR_RETURN
   1851             (WRITE_SOURCE_VP_2m(unit, MEM_BLOCK_ALL, vp, &svp_2_entry));
   1852     }
   1853 
   1854     /* Free the VP */
   1855     BCM_IF_ERROR_RETURN(_bcm_vp_free(unit, _bcmVpTypeFlow, 1, vp));
   1856 
   1857     return BCM_E_NONE;
   1858 }
   1859 
   1860 /*
   1861  * Function:
   1862  *      bcmi_esw_flow_port_get
   1863  * Purpose:
   1864  *      Get an FLOW port from a VPN
   1865  * Parameters:
   1866  *      unit       - (IN) Device Number
   1867  *      vpn        - (IN) VPN instance ID
   1868  *      flow  - (IN/OUT) FLOW port information
   1869  */
   1870 int
   1871 bcmi_esw_flow_port_get(int unit, bcm_vpn_t vpn, bcm_flow_port_t *flow_port)
   1872 {
   1873     int vp=0;
   1874     int rv = BCM_E_NONE;
   1875     uint32 reg_val = 0;
   1876     int dft_vxlan_vp = -1;
   1877     int dft_l2gre_vp = -1;
   1878     int dft_gpe_vp = -1;
   1879     int dft_geneve_vp = -1;
   1880 
   1881     if (BCM_GPORT_IS_TRUNK(flow_port->flow_port_id)) {
   1882         bcm_trunk_member_t trunk_member;
   1883         int                port_count = 0;
   1884         bcm_trunk_t        tid = 0;
   1885         int                tid_is_vp_lag = FALSE;
   1886         if (vpn != BCM_FLOW_VPN_INVALID) {
   1887             BCM_IF_ERROR_RETURN(bcmi_esw_flow_vpn_is_valid(unit, vpn));
   1888         }
   1889         tid = BCM_GPORT_TRUNK_GET(flow_port->flow_port_id);
   1890         BCM_IF_ERROR_RETURN(
   1891             _bcm_esw_trunk_id_is_vp_lag(unit, tid, &tid_is_vp_lag));
   1892         if (tid_is_vp_lag) {
   1893             BCM_IF_ERROR_RETURN(
   1894                 bcm_td2_vp_lag_get(unit, tid, NULL, 1,
   1895                                    &trunk_member, &port_count));
   1896             if (BCM_GPORT_IS_NIV_PORT(trunk_member.gport) ||
   1897                 BCM_GPORT_IS_EXTENDER_PORT(trunk_member.gport)) {
   1898                 BCM_IF_ERROR_RETURN(
   1899                     _bcm_esw_trunk_tid_to_vp_lag_vp(unit, tid, &vp));
   1900                 if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeFlow)) {
   1901                     return BCM_E_NOT_FOUND;
   1902                 }
   1903                 return BCM_E_NONE;
   1904             }
   1905         }
   1906     }
   1907 
   1908     if (SOC_REG_IS_VALID(unit, VXLAN_DEFAULT_NETWORK_SVPr)) {
   1909         BCM_IF_ERROR_RETURN(READ_VXLAN_DEFAULT_NETWORK_SVPr(unit, &reg_val));
   1910         dft_vxlan_vp = soc_reg_field_get(unit,
   1911                             VXLAN_DEFAULT_NETWORK_SVPr, reg_val, SVPf);
   1912     }
   1913 
   1914     if (SOC_REG_IS_VALID(unit, L2GRE_DEFAULT_NETWORK_SVPr)) {
   1915         BCM_IF_ERROR_RETURN(READ_L2GRE_DEFAULT_NETWORK_SVPr(unit, &reg_val));
   1916         dft_l2gre_vp = soc_reg_field_get(unit,
   1917                             L2GRE_DEFAULT_NETWORK_SVPr, reg_val, SVPf);
   1918     }
   1919 
   1920     if (SOC_REG_IS_VALID(unit, GPE_DEFAULT_NETWORK_SVPr)) {
   1921         BCM_IF_ERROR_RETURN(READ_GPE_DEFAULT_NETWORK_SVPr(unit, &reg_val));
   1922         dft_gpe_vp = soc_reg_field_get(unit,
   1923                             GPE_DEFAULT_NETWORK_SVPr, reg_val, SVPf);
   1924     }
   1925 
   1926     if (SOC_REG_IS_VALID(unit, GENEVE_DEFAULT_NETWORK_SVPr)) {
   1927         BCM_IF_ERROR_RETURN(READ_GENEVE_DEFAULT_NETWORK_SVPr(unit, &reg_val));
   1928         dft_geneve_vp = soc_reg_field_get(unit,
   1929                             GENEVE_DEFAULT_NETWORK_SVPr, reg_val, SVPf);
   1930     }
   1931 
   1932     vp = BCM_GPORT_FLOW_PORT_ID_GET(flow_port->flow_port_id);
   1933     if (vp == -1) {
   1934         return BCM_E_PARAM;
   1935     }
   1936 
   1937     if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeFlow)) {
   1938         return BCM_E_NOT_FOUND;
   1939     }
   1940 
   1941     if (vpn != BCM_FLOW_VPN_INVALID) {
   1942         BCM_IF_ERROR_RETURN(bcmi_esw_flow_vpn_is_valid(unit, vpn));
   1943     }
   1944 
   1945     if (vp == dft_vxlan_vp || vp == dft_l2gre_vp || vp == dft_gpe_vp ||
   1946         vp == dft_geneve_vp) {
   1947         rv = _bcm_td3_flow_default_port_get(unit, vp, flow_port);
   1948         if (vp == dft_vxlan_vp) {
   1949             flow_port->flags |= BCM_FLOW_PORT_DEFAULT;
   1950         }
   1951         if (vp == dft_l2gre_vp) {
   1952             flow_port->flags |= BCM_FLOW_PORT_DEFAULT_L2GRE;
   1953         }
   1954         if (vp == dft_gpe_vp) {
   1955             flow_port->flags |= BCM_FLOW_PORT_DEFAULT_GPE;
   1956         }
   1957         if (vp == dft_geneve_vp) {
   1958             flow_port->flags |= BCM_FLOW_PORT_DEFAULT_GENEVE;
   1959         }
   1960     } else {
   1961         rv = _bcmi_esw_flow_port_get(unit, vpn, vp, flow_port);
   1962     }
   1963 
   1964     return rv;
   1965 }
   1966 
   1967  /*
   1968   * Function:
   1969   *      _bcm_flow_share_vp_get
   1970   * Purpose:
   1971   *      Get shared VPs info per VPN
   1972   * Parameters:
   1973   *      unit       - (IN) Device Number
   1974   *      vpn        - (IN) VPN that shared vp belong to
   1975   *      vp_bitmap  - (OUT) shared vp bitmap
   1976   * Returns:
   1977   *      BCM_E_XXX
   1978   */
   1979 STATIC int
   1980 _bcm_flow_share_vp_get(int unit, bcm_vpn_t vpn, SHR_BITDCL *vp_bitmap)
   1981 {
   1982     vlan_xlate_entry_t *vent;
   1983     soc_mem_t mem;
   1984     int index_min = 0;
   1985     int index_max = 0;
   1986     uint8 *xlate_buf = NULL;
   1987     int buf_size = 0;
   1988     int i = 0;
   1989     int rv = BCM_E_NONE;
   1990     int vfi = -1;
   1991     int vp = -1;
   1992 
   1993     if (vpn != BCM_FLOW_VPN_INVALID) {
   1994          BCM_IF_ERROR_RETURN(bcmi_esw_flow_vpn_is_valid(unit, vpn));
   1995          _BCM_FLOW_VPN_GET(vfi, _BCM_VPN_TYPE_VFI, vpn);
   1996     }
   1997 
   1998     if (SOC_MEM_IS_VALID(unit, VLAN_XLATE_1_DOUBLEm)) {
   1999         mem = VLAN_XLATE_1_DOUBLEm;
   2000     } else {
   2001         mem = VLAN_XLATEm;
   2002     }
   2003     index_min = soc_mem_index_min(unit, mem);
   2004     index_max = soc_mem_index_max(unit, mem);
   2005 
   2006     buf_size = SOC_MEM_TABLE_BYTES(unit, mem);
   2007     xlate_buf = soc_cm_salloc(unit, buf_size, "VLAN_XLATE buffer");
   2008     if (NULL == xlate_buf) {
   2009         return BCM_E_MEMORY;
   2010     }
   2011     rv = soc_mem_read_range(unit, mem, MEM_BLOCK_ANY, index_min, index_max, 
   2012                                 xlate_buf);
   2013     if (rv < 0) {
   2014         soc_cm_sfree(unit, xlate_buf);
   2015         return rv;
   2016     }
   2017 
   2018     for (i = index_min; i <= index_max; i++) {
   2019         vent = soc_mem_table_idx_to_pointer(unit, mem, void *, xlate_buf, i);
   2020         if (SOC_MEM_IS_VALID(unit, VLAN_XLATE_1_DOUBLEm)) {
   2021             if (soc_mem_field32_get(unit, mem, vent, BASE_VALID_0f) != 3) {
   2022                 continue;
   2023             }
   2024             if (soc_mem_field32_get(unit, mem, vent, BASE_VALID_1f) != 7) {
   2025                 continue;
   2026             }
   2027         }
   2028 
   2029         if (soc_mem_field32_get(unit, mem, vent, XLATE__MPLS_ACTIONf) != 0x1) {
   2030             continue;
   2031         }
   2032 
   2033         if (vfi != -1 && soc_mem_field32_get(unit, mem, vent, XLATE__VFIf) != 
   2034                   vfi) {
   2035             continue;
   2036         }
   2037 
   2038         vp = soc_mem_field32_get(unit, mem, vent, XLATE__SOURCE_VPf);
   2039         SHR_BITSET(vp_bitmap, vp);
   2040     }
   2041 
   2042     (void)soc_cm_sfree(unit, xlate_buf);
   2043 
   2044     return BCM_E_NONE;
   2045 }
   2046 
   2047 /*
   2048  * Function:
   2049  *      bcmi_esw_flow_port_get_all
   2050  * Purpose:
   2051  *      Get all FLOW ports from a VPN
   2052  * Parameters:
   2053  *      unit     - (IN) Device Number
   2054  *      vpn      - (IN) VPN instance ID
   2055  *      port_max   - (IN) Maximum number of interfaces in array
   2056  *      port_array - (OUT) Array of FLOW ports
   2057  *      port_count - (OUT) Number of interfaces returned in array
   2058  */
   2059 int
   2060 bcmi_esw_flow_port_get_all(int unit, bcm_vpn_t vpn, int port_max,
   2061                          bcm_flow_port_t *port_array, int *port_count)
   2062 {
   2063     int vp, rv = BCM_E_NONE;
   2064     int vfi_index=-1;
   2065     int vp1 = 0, vp2 = 0;
   2066     uint8 isEline = 0;
   2067     SHR_BITDCL *share_vp_bitmap = NULL;
   2068 
   2069     if (vpn != BCM_FLOW_VPN_INVALID) {
   2070         _BCM_FLOW_VPN_GET(vfi_index, _BCM_VPN_TYPE_VFI, vpn);
   2071         BCM_IF_ERROR_RETURN(bcmi_esw_flow_vpn_is_eline(unit, vpn, &isEline));
   2072     } else {
   2073         vfi_index = _BCM_FLOW_VFI_INVALID;
   2074     }
   2075 
   2076     *port_count = 0;
   2077 
   2078     if (isEline == 0x1 ) {
   2079         /* ---- Read in current table values for VP1 and VP2 ----- */
   2080         (void) _bcm_td3_flow_eline_vp_map_get (unit, vfi_index,  &vp1,  &vp2);
   2081         vp = vp1;
   2082         if (_bcm_vp_used_get(unit, vp, _bcmVpTypeFlow)) {
   2083             if (0 == port_max) {
   2084                 (*port_count)++;
   2085 
   2086             } else if (*port_count < port_max) {
   2087                 rv = _bcmi_esw_flow_port_get(unit, vpn, vp, 
   2088                                            &port_array[*port_count]);
   2089                 if (rv < 0) {
   2090                     return rv;
   2091                 }
   2092                 (*port_count)++;
   2093             }
   2094         }
   2095 
   2096         vp = vp2;
   2097         if (_bcm_vp_used_get(unit, vp, _bcmVpTypeFlow)) {
   2098             if (0 == port_max) {
   2099                 (*port_count)++;
   2100 
   2101             } else if (*port_count < port_max) {
   2102                 rv = _bcmi_esw_flow_port_get(unit, vpn, vp, 
   2103                                            &port_array[*port_count]);
   2104                 if (rv < 0) {
   2105                     return rv;
   2106                 }
   2107                 (*port_count)++;
   2108             }
   2109         }
   2110     } else if (isEline == 0x0 ) {
   2111         uint32 entry_type = 0;
   2112         source_vp_entry_t svp;
   2113         int num_vp = soc_mem_index_count(unit, SOURCE_VPm);
   2114 
   2115         share_vp_bitmap = sal_alloc(SHR_BITALLOCSIZE(num_vp), "sharr_vp_bitmap");
   2116         if (share_vp_bitmap == NULL) {
   2117             return BCM_E_MEMORY;
   2118         }
   2119         sal_memset(share_vp_bitmap, 0, SHR_BITALLOCSIZE(num_vp));
   2120 
   2121         if (soc_feature(unit, soc_feature_vp_sharing)) {
   2122             rv = _bcm_flow_share_vp_get(unit, vpn, share_vp_bitmap);
   2123             _BCM_FLOW_CLEANUP(rv)
   2124         }
   2125 
   2126         SHR_BIT_ITER(VIRTUAL_INFO(unit)->flow_vp_bitmap, num_vp, vp) {
   2127 
   2128             rv = READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp, &svp);
   2129             _BCM_FLOW_CLEANUP(rv)
   2130             entry_type = soc_SOURCE_VPm_field32_get(unit, &svp, ENTRY_TYPEf);
   2131 
   2132             if ((vfi_index == soc_SOURCE_VPm_field32_get(unit, &svp, VFIf) &&
   2133                     entry_type == _BCM_VXLAN_SOURCE_VP_TYPE_VFI) || 
   2134                 SHR_BITGET(share_vp_bitmap, vp)) {
   2135 
   2136                 /* Check if number of ports is requested */
   2137                 if (0 == port_max) {
   2138                     (*port_count)++;
   2139                     continue;
   2140                 } else if (*port_count == port_max) {
   2141                     break;
   2142                 }
   2143 
   2144                rv = _bcmi_esw_flow_port_get(unit,
   2145                         vpn, vp, &port_array[*port_count]);
   2146                _BCM_FLOW_CLEANUP(rv)
   2147 
   2148                (*port_count)++;
   2149             }
   2150         }
   2151         sal_free(share_vp_bitmap);
   2152     }
   2153 
   2154     return BCM_E_NONE;
   2155 cleanup:
   2156     sal_free(share_vp_bitmap);
   2157     return rv;
   2158 }
   2159 
   2160 /*
   2161  * Function:
   2162  *      _bcm_td3_flow_default_port_get
   2163  * Purpose:
   2164  *      Get FLOW Default port information
   2165  * Parameters:
   2166  *      unit       - (IN) Device Number
   2167  *      vp         - (IN) Source Virtual Port
   2168  *      flow_port  - (IN/OUT) flow port information
   2169  * Returns:
   2170  *      BCM_E_XXX
   2171  */
   2172 int
   2173 _bcm_td3_flow_default_port_get(int unit, int vp, bcm_flow_port_t *flow_port)
   2174 {
   2175     int rv = BCM_E_NONE;
   2176     source_vp_entry_t svp;
   2177     _bcm_vp_info_t vp_info;
   2178 
   2179     bcm_flow_port_t_init(flow_port);
   2180     BCM_GPORT_FLOW_PORT_ID_SET(flow_port->flow_port_id, vp);
   2181 
   2182     BCM_IF_ERROR_RETURN(READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp, &svp));
   2183     flow_port->if_class = soc_SOURCE_VPm_field32_get(unit, &svp, CLASS_IDf);
   2184 
   2185     BCM_IF_ERROR_RETURN(_bcm_vp_info_get(unit, vp, &vp_info));
   2186     if (vp_info.flags & _BCM_VP_INFO_NETWORK_PORT) {
   2187         flow_port->flags |= BCM_FLOW_PORT_NETWORK;
   2188     }
   2189 
   2190     return rv;
   2191 }
   2192 
   2193 /*
   2194  * Function:
   2195  *      _bcmi_esw_flow_port_get
   2196  * Purpose:
   2197  *      Get FLOW port information from a VPN
   2198  * Parameters:
   2199  *      unit       - (IN) Device Number
   2200  *      vpn        - (IN) VPN instance ID
   2201  *      flow_port_id - (IN) vxlan port information
   2202  * Returns:
   2203  *      BCM_E_XXX
   2204  */
   2205 
   2206 int
   2207 _bcmi_esw_flow_port_get(int unit, bcm_vpn_t vpn, int vp, bcm_flow_port_t  *flow_port)
   2208 {
   2209     int i, rv = BCM_E_NONE;
   2210     uint32 tpid_enable = 0;
   2211     source_vp_entry_t svp;
   2212     int split_horizon_port_flag=0;
   2213     _bcm_vp_info_t vp_info;
   2214 
   2215     /* Initialize the structure */
   2216     bcm_flow_port_t_init(flow_port);
   2217     BCM_GPORT_FLOW_PORT_ID_SET(flow_port->flow_port_id, vp);
   2218     BCM_IF_ERROR_RETURN (READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp, &svp));
   2219 
   2220     /* Check for Network-Port */
   2221     BCM_IF_ERROR_RETURN(_bcm_vp_info_get(unit, vp, &vp_info));
   2222     if (vp_info.flags & _BCM_VP_INFO_NETWORK_PORT) {
   2223         split_horizon_port_flag = TRUE;
   2224     }
   2225 
   2226     if ( vpn != BCM_FLOW_VPN_INVALID) {
   2227          if (!split_horizon_port_flag) { /* Check VPN only for Access VP */
   2228              if (_bcm_vp_used_get(unit, vp, _bcmVpTypeNiv) ||
   2229                   _bcm_vp_used_get(unit, vp, _bcmVpTypeExtender)) {
   2230                    return BCM_E_NONE;
   2231              }
   2232          }
   2233     }
   2234 
   2235     if (split_horizon_port_flag) {
   2236         flow_port->flags |= BCM_FLOW_PORT_NETWORK;
   2237     }
   2238 
   2239     /* Get the match parameters */
   2240     /* Done by match API
   2241     rv = _bcm_td2_vxlan_match_get(unit, vxlan_port, vp);
   2242     BCM_IF_ERROR_RETURN(rv);
   2243     */ 
   2244 
   2245     /* Get the BCM_VXLAN_PORT_ENABLE_VLAN_CHECKS flag */
   2246     /* Done by match API
   2247     if (!soc_feature(unit, soc_feature_vlan_vfi_membership)) {
   2248         BCM_IF_ERROR_RETURN(
   2249             _bcm_td2_vxlan_port_vlan_get(unit, vp, vxlan_port));
   2250     }
   2251     */ 
   2252 
   2253     /* Get Tunnel index */
   2254 /* to be done by flow encap set API
   2255     rv = _bcm_td2_vxlan_egress_dvp_get(unit, vp, vxlan_port);
   2256     BCM_IF_ERROR_RETURN(rv);
   2257 */
   2258 
   2259     /* Fill in SVP parameters */
   2260     flow_port->if_class = soc_SOURCE_VPm_field32_get(unit, &svp, CLASS_IDf);
   2261     flow_port->network_group_id = soc_SOURCE_VPm_field32_get(unit, &svp, 
   2262                                     NETWORK_GROUPf);
   2263 
   2264     if (soc_SOURCE_VPm_field32_get(unit, &svp, SD_TAG_MODEf)) {
   2265         uint32 svp1[SOC_MAX_MEM_WORDS];
   2266 
   2267         BCM_IF_ERROR_RETURN(READ_SVP_ATTRS_1m(unit, MEM_BLOCK_ANY, vp, svp1));
   2268         soc_SVP_ATTRS_1m_field_get(unit, &svp1, TPID_ENABLEf, &tpid_enable);
   2269 
   2270         if (tpid_enable) {
   2271             flow_port->flags |= BCM_FLOW_PORT_SERVICE_TAGGED;
   2272             for (i = 0; i < 4; i++) {
   2273                 if (tpid_enable & (1 << i)) {
   2274                     _bcm_fb2_outer_tpid_entry_get(unit, &flow_port->egress_service_tpid, i);
   2275                 }
   2276             }
   2277         }
   2278     }
   2279 
   2280     return rv;
   2281 }
   2282 
   2283 /*
   2284  * Function:
   2285  *      bcmi_esw_flow_port_create
   2286  * Purpose:
   2287  *      Create Flex Flow port and add to a default VPN
   2288  * Parameters:
   2289  *      unit    - (IN) Device Number
   2290  *      vpn     - (IN) VPN instance ID
   2291  *      flow_port - (IN/OUT) flow_port information (OUT : flow_port_id)
   2292  * Returns:
   2293  *      BCM_E_XXX
   2294  */
   2295 
   2296 int
   2297 bcmi_esw_flow_port_create(int unit, bcm_vpn_t vpn, bcm_flow_port_t  *flow_port)
   2298 {
   2299     int mode=0, rv = BCM_E_PARAM;
   2300     uint8 isEline = 0;
   2301     int vp = -1;
   2302     int dft_vxlan_port = FALSE;
   2303     int dft_l2gre_port = FALSE;
   2304     int dft_gpe_port   = FALSE;
   2305     int dft_geneve_port = FALSE;
   2306 
   2307     BCM_IF_ERROR_RETURN(bcm_xgs3_l3_egress_mode_get(unit, &mode));
   2308     if (!mode) {
   2309         LOG_INFO(BSL_LS_BCM_L3,
   2310                  (BSL_META_U(unit,
   2311                              "L3 egress mode must be set first\n")));
   2312         return BCM_E_DISABLED;
   2313     }
   2314 
   2315     if (flow_port->if_class > 0xfff) {
   2316         return BCM_E_PARAM;
   2317     }
   2318 
   2319 /*  mtu programmed in EGR_DVP_ATTRIBUTEm, will be done by bcm_flow_port_set
   2320     if (flow_port->mtu > 0x3fff) {
   2321         return BCM_E_PARAM;
   2322     }
   2323 */
   2324 
   2325     if (vpn != BCM_FLOW_VPN_INVALID) {
   2326         BCM_IF_ERROR_RETURN(bcmi_esw_flow_vpn_is_eline(unit, vpn, &isEline));
   2327     }
   2328 
   2329     if (flow_port->flags & PORT_DEFAULT_ALL) {
   2330         rv =  _bcm_td3_flow_default_port_add(unit, flow_port, &vp);
   2331         BCM_IF_ERROR_RETURN(rv);
   2332 
   2333         if (flow_port->flags & BCM_FLOW_PORT_DEFAULT) {
   2334            if (!SOC_REG_IS_VALID(unit, VXLAN_DEFAULT_NETWORK_SVPr)) {
   2335                rv = BCM_E_UNAVAIL;
   2336                goto err_exit;
   2337            }
   2338            dft_vxlan_port = TRUE;
   2339 
   2340            rv = soc_reg_field32_modify(unit, VXLAN_DEFAULT_NETWORK_SVPr, 
   2341                         REG_PORT_ANY, SVPf, vp);
   2342            if (BCM_FAILURE(rv)) {
   2343                goto err_exit;
   2344            }
   2345 
   2346            if (SOC_REG_IS_VALID(unit, DEFAULT_SVP_ENABLEr)) {
   2347                rv = soc_reg_field32_modify
   2348                      (unit, DEFAULT_SVP_ENABLEr, REG_PORT_ANY,
   2349                                VXLAN_DEFAULT_SVP_ENABLEf, 1);
   2350                if (BCM_FAILURE(rv)) {
   2351                    if (rv != BCM_E_NOT_FOUND) {
   2352                        goto err_exit;
   2353                    } else {
   2354                        rv = BCM_E_NONE;
   2355                    } 
   2356                }
   2357            }
   2358        }
   2359        if (flow_port->flags & BCM_FLOW_PORT_DEFAULT_L2GRE) {
   2360            if (!SOC_REG_IS_VALID(unit, L2GRE_DEFAULT_NETWORK_SVPr)) {
   2361                rv = BCM_E_UNAVAIL;
   2362                goto err_exit;
   2363            }
   2364            rv = soc_reg_field32_modify(unit, L2GRE_DEFAULT_NETWORK_SVPr,
   2365                         REG_PORT_ANY, SVPf, vp);
   2366            if (BCM_FAILURE(rv)) {
   2367                goto err_exit;
   2368            }
   2369 
   2370            dft_l2gre_port = TRUE;
   2371            if (SOC_REG_IS_VALID(unit, DEFAULT_SVP_ENABLEr)) {
   2372                rv = soc_reg_field32_modify
   2373                      (unit, DEFAULT_SVP_ENABLEr, REG_PORT_ANY,
   2374                                L2GRE_DEFAULT_SVP_ENABLEf, 1);
   2375                if (BCM_FAILURE(rv)) {
   2376                    if (rv != BCM_E_NOT_FOUND) {
   2377                        goto err_exit;
   2378                    } else {
   2379                        rv = BCM_E_NONE;
   2380                    } 
   2381                }
   2382            }
   2383        }
   2384 
   2385        if (flow_port->flags & BCM_FLOW_PORT_DEFAULT_GPE) {
   2386            if (!SOC_REG_IS_VALID(unit, GPE_DEFAULT_NETWORK_SVPr)) {
   2387                rv = BCM_E_UNAVAIL;
   2388                goto err_exit;
   2389            }
   2390            rv = soc_reg_field32_modify(unit, GPE_DEFAULT_NETWORK_SVPr,
   2391                         REG_PORT_ANY, SVPf, vp);
   2392            if (BCM_FAILURE(rv)) {
   2393                goto err_exit;
   2394            }
   2395            dft_gpe_port = TRUE;
   2396        }
   2397 
   2398        if (flow_port->flags & BCM_FLOW_PORT_DEFAULT_GENEVE) {
   2399            if (!SOC_REG_IS_VALID(unit, GENEVE_DEFAULT_NETWORK_SVPr)) {
   2400                rv = BCM_E_UNAVAIL;
   2401                goto err_exit;
   2402            }
   2403            rv = soc_reg_field32_modify(unit, GENEVE_DEFAULT_NETWORK_SVPr,
   2404                     REG_PORT_ANY, SVPf, vp);
   2405            if (BCM_FAILURE(rv)) {
   2406                goto err_exit;
   2407            }
   2408            dft_geneve_port = TRUE;
   2409        }
   2410        return rv;
   2411     }
   2412 
   2413     if (isEline) {
   2414         rv = _bcm_td3_flow_eline_port_add(unit, vpn, flow_port);
   2415     } else {
   2416         rv = _bcm_td3_flow_elan_port_add(unit, vpn, flow_port);
   2417     }
   2418 
   2419     return rv;
   2420 
   2421 err_exit:
   2422     if (vp >= 0) {
   2423         if (dft_vxlan_port == TRUE) {
   2424            BCM_IF_ERROR_RETURN(soc_reg_field32_modify(unit,
   2425                VXLAN_DEFAULT_NETWORK_SVPr, REG_PORT_ANY, SVPf, 0));
   2426         }
   2427         if (dft_l2gre_port == TRUE) {
   2428            BCM_IF_ERROR_RETURN(soc_reg_field32_modify(unit,
   2429                L2GRE_DEFAULT_NETWORK_SVPr, REG_PORT_ANY, SVPf, 0));
   2430         }
   2431         if (dft_gpe_port == TRUE) {
   2432            BCM_IF_ERROR_RETURN(soc_reg_field32_modify(unit,
   2433                GPE_DEFAULT_NETWORK_SVPr, REG_PORT_ANY, SVPf, 0));
   2434         }
   2435         if (dft_geneve_port == TRUE) {
   2436            BCM_IF_ERROR_RETURN(soc_reg_field32_modify(unit,
   2437                GENEVE_DEFAULT_NETWORK_SVPr, REG_PORT_ANY, SVPf, 0));
   2438         }
   2439         BCM_IF_ERROR_RETURN(_bcm_td3_flow_default_port_delete(unit,
   2440             BCM_FLOW_VPN_INVALID, vp));
   2441     }
   2442     return rv;
   2443 }
   2444 
   2445 /*
   2446  * Function:
   2447  *      bcmi_esw_flow_port_destroy
   2448  * Purpose:
   2449  *      Delete FLOW port from a VPN
   2450  * Parameters:
   2451  *      unit       - (IN) Device Number
   2452  *      vpn        - (IN) VPN instance ID
   2453  *      flow_port_id - (IN) flow port information
   2454  * Returns:
   2455  *      BCM_E_XXX
   2456  */
   2457 
   2458 int
   2459 bcmi_esw_flow_port_destroy(int unit, bcm_vpn_t vpn, bcm_gport_t flow_port_id)
   2460 {
   2461     int vp=0;
   2462     int rv = BCM_E_UNAVAIL;
   2463     uint8 isEline=0;
   2464     uint32 reg_val=0;
   2465     int default_vp_delete = FALSE;
   2466 
   2467     if (BCM_GPORT_IS_TRUNK(flow_port_id)) {
   2468         bcm_trunk_member_t trunk_member;
   2469         int                port_count = 0;
   2470         bcm_trunk_t        tid = 0;
   2471         int                tid_is_vp_lag = FALSE;
   2472         if (vpn != BCM_FLOW_VPN_INVALID) {
   2473             BCM_IF_ERROR_RETURN(bcmi_esw_flow_vpn_is_valid(unit, vpn));
   2474         }
   2475         tid = BCM_GPORT_TRUNK_GET(flow_port_id);
   2476         BCM_IF_ERROR_RETURN(
   2477             _bcm_esw_trunk_id_is_vp_lag(unit, tid, &tid_is_vp_lag));
   2478         if (tid_is_vp_lag) {
   2479             BCM_IF_ERROR_RETURN(
   2480                 bcm_td2_vp_lag_get(unit, tid, NULL, 1,
   2481                                    &trunk_member, &port_count));
   2482             if (BCM_GPORT_IS_NIV_PORT(trunk_member.gport) ||
   2483                 BCM_GPORT_IS_EXTENDER_PORT(trunk_member.gport)) {
   2484                 BCM_IF_ERROR_RETURN(
   2485                     _bcm_esw_trunk_tid_to_vp_lag_vp(unit, tid, &vp));
   2486                 if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeFlow)) {
   2487                     return BCM_E_NOT_FOUND;
   2488                 }
   2489                 BCM_IF_ERROR_RETURN(_bcm_vp_free(unit, _bcmVpTypeFlow, 1, vp));
   2490                 return _bcm_td3_flow_access_niv_pe_reset(unit, vp);
   2491             }
   2492         }
   2493     }
   2494 
   2495     /* Check for Valid Vpn */
   2496     if (vpn != BCM_FLOW_VPN_INVALID) {
   2497         BCM_IF_ERROR_RETURN(bcmi_esw_flow_vpn_is_valid(unit, vpn));
   2498     }
   2499 
   2500     vp = BCM_GPORT_FLOW_PORT_ID_GET(flow_port_id);
   2501     if (vp == -1) {
   2502         return BCM_E_PARAM;
   2503     }
   2504 
   2505     if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeFlow)) {
   2506         return BCM_E_NOT_FOUND;
   2507     }
   2508 
   2509     
   2510 
   2511     /* Check for VXLAN default port */
   2512     if (SOC_REG_IS_VALID(unit, VXLAN_DEFAULT_NETWORK_SVPr)) {
   2513         BCM_IF_ERROR_RETURN(READ_VXLAN_DEFAULT_NETWORK_SVPr(unit, &reg_val));
   2514         if (vp == soc_reg_field_get(unit,
   2515                     VXLAN_DEFAULT_NETWORK_SVPr, reg_val, SVPf)) {
   2516             rv = soc_reg_field32_modify(unit, VXLAN_DEFAULT_NETWORK_SVPr,
   2517                         REG_PORT_ANY, SVPf, 0);
   2518             BCM_IF_ERROR_RETURN(rv);
   2519 
   2520             rv =  _bcm_td3_flow_default_port_delete(unit, vpn, vp);
   2521             BCM_IF_ERROR_RETURN(rv);
   2522             if (SOC_REG_IS_VALID(unit, DEFAULT_SVP_ENABLEr)) {
   2523                 rv = soc_reg_field32_modify
   2524                       (unit, DEFAULT_SVP_ENABLEr, REG_PORT_ANY, VXLAN_DEFAULT_SVP_ENABLEf, 0);
   2525                 if (BCM_FAILURE(rv)) {
   2526                     if (rv != BCM_E_NOT_FOUND) {
   2527                         return rv;
   2528                     } else {
   2529                         rv = BCM_E_NONE;
   2530                     } 
   2531                 }
   2532             }
   2533             default_vp_delete = TRUE;
   2534         }
   2535     }
   2536 
   2537     /* Check for L2GRE default port */
   2538     if (SOC_REG_IS_VALID(unit, L2GRE_DEFAULT_NETWORK_SVPr)) {
   2539         BCM_IF_ERROR_RETURN(READ_L2GRE_DEFAULT_NETWORK_SVPr(unit, &reg_val));
   2540         if (vp == soc_reg_field_get(unit,
   2541                     L2GRE_DEFAULT_NETWORK_SVPr, reg_val, SVPf)) {
   2542             rv = soc_reg_field32_modify(unit, L2GRE_DEFAULT_NETWORK_SVPr,
   2543                         REG_PORT_ANY, SVPf, 0);
   2544             BCM_IF_ERROR_RETURN(rv);
   2545             if (default_vp_delete == FALSE) {
   2546                 rv =  _bcm_td3_flow_default_port_delete(unit, vpn, vp);
   2547                 BCM_IF_ERROR_RETURN(rv);
   2548             }
   2549             if (SOC_REG_IS_VALID(unit, DEFAULT_SVP_ENABLEr)) {
   2550                 rv = soc_reg_field32_modify(unit, DEFAULT_SVP_ENABLEr,
   2551                          REG_PORT_ANY, L2GRE_DEFAULT_SVP_ENABLEf, 0);
   2552                 if (BCM_FAILURE(rv)) {
   2553                     if (rv != BCM_E_NOT_FOUND) {
   2554                         return rv;
   2555                     } else {
   2556                         rv = BCM_E_NONE;
   2557                     }
   2558                 } 
   2559             }
   2560             default_vp_delete = TRUE;
   2561         }
   2562     }
   2563 
   2564     /* Check for GPE default port */
   2565     if (SOC_REG_IS_VALID(unit, GPE_DEFAULT_NETWORK_SVPr)) {
   2566         BCM_IF_ERROR_RETURN(READ_GPE_DEFAULT_NETWORK_SVPr(unit, &reg_val));
   2567         if (vp == soc_reg_field_get(unit,
   2568                     GPE_DEFAULT_NETWORK_SVPr, reg_val, SVPf)) {
   2569             rv = soc_reg_field32_modify(unit, GPE_DEFAULT_NETWORK_SVPr,
   2570                         REG_PORT_ANY, SVPf, 0);
   2571             BCM_IF_ERROR_RETURN(rv);
   2572             if (default_vp_delete == FALSE) {
   2573                 rv =  _bcm_td3_flow_default_port_delete(unit, vpn, vp);
   2574                 BCM_IF_ERROR_RETURN(rv);
   2575             }
   2576             default_vp_delete = TRUE;
   2577         }
   2578     }
   2579 
   2580     /* Check for GENEVE default port */
   2581     if (SOC_REG_IS_VALID(unit, GENEVE_DEFAULT_NETWORK_SVPr)) {
   2582         BCM_IF_ERROR_RETURN(READ_GENEVE_DEFAULT_NETWORK_SVPr(unit, &reg_val));
   2583         if (vp == soc_reg_field_get(unit,
   2584                     GENEVE_DEFAULT_NETWORK_SVPr, reg_val, SVPf)) {
   2585             rv = soc_reg_field32_modify(unit, GENEVE_DEFAULT_NETWORK_SVPr,
   2586                         REG_PORT_ANY, SVPf, 0);
   2587             BCM_IF_ERROR_RETURN(rv);
   2588             if (default_vp_delete == FALSE) {
   2589                 rv =  _bcm_td3_flow_default_port_delete(unit, vpn, vp);
   2590                 BCM_IF_ERROR_RETURN(rv);
   2591             }
   2592             default_vp_delete = TRUE;
   2593         }
   2594     }
   2595 
   2596     if (default_vp_delete == TRUE) {
   2597         return BCM_E_NONE;
   2598     }
   2599 
   2600     BCM_IF_ERROR_RETURN(bcmi_esw_flow_vp_is_eline(unit, vp, &isEline));
   2601 
   2602     if (isEline == 0x1 ) {
   2603        rv = _bcm_td3_flow_eline_port_delete(unit, vpn, vp);
   2604     } else if (isEline == 0x0 ) {
   2605        rv = _bcm_td3_flow_elan_port_delete(unit, vpn, vp);
   2606     }
   2607     return rv;
   2608 }
   2609 
   2610 /*
   2611  * Function:
   2612  *      bcmi_esw_flow_port_delete_all
   2613  * Purpose:
   2614  *      Delete all FLOW ports from a VPN
   2615  * Parameters:
   2616  *      unit       - (IN) Device Number
   2617  *      vpn        - (IN) VPN instance ID
   2618  * Returns:
   2619  *      BCM_E_XXX
   2620  */
   2621 int
   2622 bcmi_esw_flow_port_delete_all(int unit, bcm_vpn_t vpn)
   2623 {
   2624     int rv = BCM_E_NONE;
   2625     int vfi_index=0;
   2626     int vp1 = 0, vp2 = 0;
   2627     uint8 isEline = 0;
   2628     bcm_gport_t flow_port_id;
   2629     uint32 vp=0;
   2630 
   2631     if (vpn != BCM_FLOW_VPN_INVALID) {
   2632         _BCM_FLOW_VPN_GET(vfi_index, _BCM_VPN_TYPE_VFI, vpn);
   2633         BCM_IF_ERROR_RETURN(bcmi_esw_flow_vpn_is_eline(unit, vpn, &isEline));
   2634     } else {
   2635         vfi_index = _BCM_FLOW_VFI_INVALID;
   2636     }
   2637 
   2638     if (isEline == 0x1 ) {
   2639          /* ---- Read in current table values for VP1 and VP2 ----- */
   2640          (void) _bcm_td3_flow_eline_vp_map_get (unit, vfi_index,  &vp1,  &vp2);
   2641          if (vp1 != 0) {
   2642               rv = _bcm_td3_flow_eline_port_delete(unit, vpn, vp1);
   2643               BCM_IF_ERROR_RETURN(rv);
   2644          }
   2645          if (vp2 != 0) {
   2646               rv = _bcm_td3_flow_eline_port_delete(unit, vpn, vp2);
   2647               BCM_IF_ERROR_RETURN(rv);
   2648          }
   2649     } else if (isEline == 0x0 ) {
   2650         uint32 num_vp = 0, entry_type = 0;
   2651         source_vp_entry_t svp;
   2652         uint32 reg_val=0;
   2653 
   2654         if (SOC_REG_IS_VALID(unit, VXLAN_DEFAULT_NETWORK_SVPr)) {
   2655             BCM_IF_ERROR_RETURN(READ_VXLAN_DEFAULT_NETWORK_SVPr(unit, &reg_val));
   2656             vp = soc_reg_field_get(unit, VXLAN_DEFAULT_NETWORK_SVPr, reg_val, SVPf);
   2657             if (_bcm_vp_used_get(unit, vp, _bcmVpTypeVxlan)) {
   2658                 BCM_IF_ERROR_RETURN(_bcm_td3_flow_default_port_delete(unit, vpn, vp));
   2659                 if (SOC_REG_IS_VALID(unit, DEFAULT_SVP_ENABLEr)) {
   2660                     rv = soc_reg_field32_modify
   2661                           (unit, DEFAULT_SVP_ENABLEr, REG_PORT_ANY, VXLAN_DEFAULT_SVP_ENABLEf, 0);
   2662                     if (BCM_FAILURE(rv)) {
   2663                         if (rv != BCM_E_NOT_FOUND) {
   2664                             return rv;
   2665                         } else {
   2666                             rv = BCM_E_NONE;
   2667                         }
   2668                     }
   2669                 }
   2670             }
   2671         }
   2672 
   2673         num_vp = soc_mem_index_count(unit, SOURCE_VPm);
   2674         SHR_BIT_ITER(VIRTUAL_INFO(unit)->flow_vp_bitmap, num_vp, vp) {
   2675 
   2676             BCM_IF_ERROR_RETURN(READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp, &svp));
   2677             entry_type = soc_SOURCE_VPm_field32_get(unit, &svp, ENTRY_TYPEf);
   2678             if ((vfi_index == soc_SOURCE_VPm_field32_get(unit, &svp, VFIf) &&
   2679                     entry_type == _BCM_VXLAN_SOURCE_VP_TYPE_VFI)
   2680 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   2681                     || SHR_BITGET(VIRTUAL_INFO(unit)->vp_shared_vp_bitmap, vp)
   2682 #endif
   2683                     ) {
   2684                 if (_bcm_vp_used_get(unit, vp, _bcmVpTypeVpLag)) {
   2685                     bcm_trunk_t        tid = 0;
   2686                     bcm_trunk_member_t trunk_member;
   2687                     int                port_count = 0;
   2688                     BCM_IF_ERROR_RETURN(
   2689                         _bcm_esw_trunk_vp_lag_vp_to_tid(unit, vp, &tid));
   2690                     BCM_IF_ERROR_RETURN(
   2691                         bcm_td2_vp_lag_get(unit, tid, NULL, 1,
   2692                                            &trunk_member, &port_count));
   2693                     if (BCM_GPORT_IS_NIV_PORT(trunk_member.gport) ||
   2694                         BCM_GPORT_IS_EXTENDER_PORT(trunk_member.gport)) {
   2695                         BCM_IF_ERROR_RETURN(
   2696                             _bcm_vp_free(unit, _bcmVpTypeFlow, 1, vp));
   2697                         BCM_IF_ERROR_RETURN(
   2698                             _bcm_td3_flow_access_niv_pe_reset(unit, vp));
   2699                         continue;
   2700                     }
   2701                 }
   2702                    /* Set FLOW port ID */
   2703                 BCM_GPORT_FLOW_PORT_ID_SET(flow_port_id, vp);
   2704                 BCM_IF_ERROR_RETURN(bcmi_esw_flow_port_destroy(unit, vpn, flow_port_id));
   2705             }
   2706         }
   2707     }
   2708     return rv;
   2709 }
   2710 #endif