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_encap.c (185045B)


      1 /*
      2  * 
      3  * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file.
      4  * 
      5  * Copyright 2007-2019 Broadcom Inc. All rights reserved.
      6  *
      7  * File:        flexflow_encap.c
      8  * Purpose:     Flex flow Encap APIs.
      9  */
     10 
     11 #include <shared/bsl.h>
     12 #include <soc/defs.h>
     13 
     14 #ifdef INCLUDE_L3
     15 
     16 #include <assert.h>
     17 #include <bcm/error.h>
     18 #include <soc/error.h>
     19 #include <bcm/types.h>
     20 #include <soc/drv.h>
     21 #include <soc/format.h>
     22 #include <bcm_int/esw/trident2plus.h>
     23 #include <bcm_int/esw/trident3.h>
     24 #include <bcm_int/esw/virtual.h>
     25 #include <bcm_int/esw/trx.h>
     26 #include <bcm_int/esw/vlan.h>
     27 #include <bcm_int/esw/port.h>
     28 #include <bcm_int/esw_dispatch.h>
     29 #include <bcm_int/esw/stack.h>
     30 #include <bcm_int/esw/vpn.h>
     31 #include <bcm_int/esw/flow.h>
     32 #include <soc/esw/flow_db.h>
     33 
     34 /* encap criteria specifies the key field composition excluding key type. A
     35  * same criteria can associate with both fixed key type and flex key type.
     36  * encap criteria along with flow_handle and flow_option 
     37  * determines the key type. In a get/delete operation, user is required to 
     38  * specify all these parameters.  
     39  *
     40  * for network-facing side:
     41  *   L3_INTF  -- no fixed key type
     42  *   VFI      -- L2GRE_VFI, VXLAN_VFI and flex key types
     43  *   VFI_DVP  -- L2GRE_VFI_DVP,VXLAN_VFI_DVP and flex key types
     44  *   VFI_DVP_GROUP -- VFI_DVP_GROUP and flex key types
     45  *   VRF_MAPPING   -- VRF_MAPPING and flex key types
     46  *
     47  * for access-facing side:
     48  *   L3_INTF  -- no fixed key type
     49  *   VFI_DVP  -- VLAN_XLATE_VFI and flex key types
     50  *   VFI_DVP_GROUP -- VFI_DVP_GROUP and flex key types
     51  */
     52 
     53 #define _BCM_FLOW_DATA_TYPE_COMMON      0
     54 #define _BCM_FLOW_PDD_FIELD_MAX         50
     55 #define _BCM_FLOW_MODID_SHIFTER        8
     56 #define _BCM_FLOW_PORT_MASK            8
     57 
     58 STATIC int _bcm_flow_nexthop_entry_set(int unit, int nh_index, int drop,
     59               bcm_flow_port_encap_t *pe_info, int is_network_port);
     60 STATIC int _bcm_flow_sd_tag_set(int unit, bcm_flow_encap_config_t *info,
     61                          uint32 *sd_tag, int *tpid_index);
     62 STATIC int _bcm_flow_sd_tag_get(int unit, bcm_flow_encap_config_t *info,
     63                           uint32 sd_tag, int  *tpid_idx);
     64 STATIC int _bcm_flow_port_encap_info_convert(bcm_flow_port_encap_t *pe_info,
     65         bcm_flow_encap_config_t *info, int port_encap2config);
     66 STATIC void _bcm_flow_egr_nh_sd_tag_get(int unit, soc_mem_t hw_mem, 
     67                   uint32 *entry, uint32 *sd_tag);
     68 STATIC int _bcm_flow_linked_tbl_sd_tag_get(int unit, soc_mem_t view_id, 
     69               uint32 *egr_nh, uint32 *sd_tag);
     70 STATIC int _bcm_flow_sd_tag_set_to_entry(int unit,
     71             bcm_flow_encap_config_t *info, soc_mem_t mem, uint32 *entry,
     72             int *tpid_index);
     73 STATIC int _bcm_flow_sd_tag_get_from_entry(int unit,
     74             bcm_flow_encap_config_t *info, soc_mem_t mem, uint32 *entry,
     75             int  *tpid_idx);
     76 STATIC int _bcm_flow_sd_tag_set_to_format(int unit,
     77             bcm_flow_encap_config_t *info, soc_mem_t mem, uint32 *entry,
     78             int *tpid_index);
     79 STATIC int _bcm_flow_sd_tag_get_from_format(int unit,
     80             bcm_flow_encap_config_t *info, soc_mem_t mem, uint32 *entry,
     81             int  *tpid_idx);
     82 
     83 
     84 /*
     85  * Function:
     86  *      bcmi_esw_flow_dvp_vlan_xlate_key_set
     87  * Description:
     88  *   Set egress vlan translation key per flow gport. call from  
     89  *   bcm_vlan_control_port_set with control type bcmVlanPortTranslateEgressKey
     90  *
     91  * Parameters:
     92  *      unit             - (IN) unit number
     93  *      port_id         - (IN) vxlan gport
     94  *      key_type      - (IN) Hardware egress vlan translation key type.
     95  *
     96  * Return Value:
     97  *      BCM_E_XXX
     98  */
     99 int
    100 bcmi_esw_flow_dvp_vlan_xlate_key_set(int unit, bcm_gport_t port_id, 
    101                                      int key_type)
    102 {
    103     int vp, egr_key_type_value = 0, rv = BCM_E_UNAVAIL;
    104     soc_mem_t mem = EGR_DVP_ATTRIBUTEm;
    105     int network_port = 0;
    106     egr_dvp_attribute_entry_t egr_dvp_attribute;
    107     _bcm_vp_info_t vp_info;
    108     soc_field_t evxlt_field_id = 0;
    109     int key_type_value;
    110     uint32 data_type;
    111 
    112     vp = BCM_GPORT_FLOW_PORT_ID_GET(port_id);
    113     if (vp < 0) {
    114         return BCM_E_NOT_FOUND;
    115     }
    116     if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeFlow)) {
    117         return BCM_E_NOT_FOUND;
    118     }
    119 
    120     /* make sure the dvp is initialized */
    121     if (!_BCM_FLOW_EGR_DVP_USED_GET(unit,vp)) {
    122         LOG_ERROR(BSL_LS_BCM_FLOW, (BSL_META_U(unit,
    123           "DVP %d not initialized, call bcm_flow_port_encap_set first\n"), vp));
    124         return BCM_E_NOT_FOUND;
    125     }
    126     BCM_IF_ERROR_RETURN(_bcm_esw_dvp_vtkey_type_value_get(unit, key_type,
    127                                                            &key_type_value));
    128  
    129     /* Check for Network-Port */
    130     BCM_IF_ERROR_RETURN(_bcm_vp_info_get(unit, vp, &vp_info));
    131     if (vp_info.flags & _BCM_VP_INFO_NETWORK_PORT) {
    132         network_port = TRUE;
    133     } else {
    134         network_port = FALSE;
    135     }
    136 
    137     /* bcmVlanTranslateEgressKeyVpn only for network port*/
    138     if ((!network_port) && (key_type == bcmVlanTranslateEgressKeyVpn)) {
    139         return BCM_E_UNAVAIL;
    140     }
    141 
    142     sal_memset(&egr_dvp_attribute, 0,
    143                sizeof(egr_dvp_attribute_entry_t));
    144 
    145     soc_mem_lock(unit,mem);
    146     rv = soc_mem_read(unit, mem, MEM_BLOCK_ALL, vp, &egr_dvp_attribute);
    147     if (BCM_FAILURE(rv)) {
    148         soc_mem_unlock(unit,mem);
    149         return rv;
    150     }
    151 
    152     data_type = soc_mem_field32_get(unit, mem, &egr_dvp_attribute,
    153                                         DATA_TYPEf);
    154     if (data_type == _BCM_FLOW_VXLAN_EGRESS_DEST_VP_TYPE) {  
    155         evxlt_field_id = VXLAN__EVXLT_KEY_SELf;
    156     } else if (data_type == _BCM_FLOW_L2GRE_EGRESS_DEST_VP_TYPE) { 
    157         evxlt_field_id = L2GRE__EVXLT_KEY_SELf;
    158     } else if (data_type > _BCM_FLOW_L2GRE_EGRESS_DEST_VP_TYPE) { 
    159        /* flex type */
    160         /* use vxlt_control_id */
    161         LOG_ERROR(BSL_LS_BCM_FLOW, (BSL_META_U(unit,
    162           "DVP %d is for flex flow, TBD\n"), vp));
    163     } else if (data_type == _BCM_FLOW_DATA_TYPE_COMMON) { 
    164         evxlt_field_id = COMMON__EVXLT_KEY_SELf;
    165     }
    166     if (evxlt_field_id != 0) {
    167         egr_key_type_value = soc_mem_field32_get(unit, mem, &egr_dvp_attribute,
    168                                         evxlt_field_id);
    169        
    170         if (key_type_value != egr_key_type_value) {
    171             soc_mem_field32_set(unit, mem, &egr_dvp_attribute,
    172                             evxlt_field_id, key_type);
    173             rv = soc_mem_write(unit, mem, MEM_BLOCK_ANY,
    174                                vp, &egr_dvp_attribute);
    175         } else {
    176             /* already exist, same key */
    177             rv = BCM_E_NONE;
    178         }
    179     }
    180     soc_mem_unlock(unit,mem);
    181     return rv;
    182 }
    183 
    184 /*
    185  * Function:
    186  *      bcmi_esw_flow_dvp_vlan_xlate_key_get
    187  * Description:
    188  *   Get egress vlan translation key per flow gport. call from  
    189  *   bcm_vlan_control_port_get with control type bcmVlanPortTranslateEgressKey
    190  *
    191  * Parameters:
    192  *      unit             - (IN) unit number
    193  *      port_id         - (IN) vxlan gport
    194  *      key_type      - (OUT) logical egress vlan translation key type.
    195  *
    196  * Return Value:
    197  *      BCM_E_XXX
    198  */
    199 int
    200 bcmi_esw_flow_dvp_vlan_xlate_key_get(int unit, bcm_gport_t port_id, 
    201                                      int *key_type)
    202 {
    203     int vp, egr_key_type_value = 0, rv = BCM_E_UNAVAIL;
    204     soc_mem_t mem = EGR_DVP_ATTRIBUTEm;
    205     int network_port = 0;
    206     egr_dvp_attribute_entry_t egr_dvp_attribute;
    207     _bcm_vp_info_t vp_info;
    208     soc_field_t evxlt_field_id = 0;
    209     uint32 data_type;
    210 
    211     vp = BCM_GPORT_FLOW_PORT_ID_GET(port_id);
    212     if (vp < 0) {
    213         return BCM_E_NOT_FOUND;
    214     }
    215     if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeFlow)) {
    216         return BCM_E_NOT_FOUND;
    217     }
    218 
    219     /* make sure the dvp is initialized */
    220     if (!_BCM_FLOW_EGR_DVP_USED_GET(unit,vp)) {
    221         LOG_ERROR(BSL_LS_BCM_FLOW, (BSL_META_U(unit,
    222           "DVP %d not initialized, call bcm_flow_port_encap_set first\n"), vp));
    223         return BCM_E_NOT_FOUND;
    224     }
    225  
    226     /* Check for Network-Port */
    227     BCM_IF_ERROR_RETURN(_bcm_vp_info_get(unit, vp, &vp_info));
    228     if (vp_info.flags & _BCM_VP_INFO_NETWORK_PORT) {
    229         network_port = TRUE;
    230     } else {
    231         network_port = FALSE;
    232     }
    233 
    234     sal_memset(&egr_dvp_attribute, 0,
    235                sizeof(egr_dvp_attribute_entry_t));
    236 
    237     rv = soc_mem_read(unit, mem, MEM_BLOCK_ALL, vp, &egr_dvp_attribute);
    238     if (BCM_FAILURE(rv)) {
    239         return rv;
    240     }
    241 
    242     data_type = soc_mem_field32_get(unit, mem, &egr_dvp_attribute,
    243                                         DATA_TYPEf);
    244     if (data_type == _BCM_FLOW_VXLAN_EGRESS_DEST_VP_TYPE) {  
    245         evxlt_field_id = VXLAN__EVXLT_KEY_SELf;
    246     } else if (data_type == _BCM_FLOW_L2GRE_EGRESS_DEST_VP_TYPE) { 
    247         evxlt_field_id = L2GRE__EVXLT_KEY_SELf;
    248     } else if (data_type > _BCM_FLOW_L2GRE_EGRESS_DEST_VP_TYPE) { 
    249        /* flex type */
    250         /* use vxlt_control_id */
    251         LOG_ERROR(BSL_LS_BCM_FLOW, (BSL_META_U(unit,
    252           "DVP %d is for flex flow, TBD\n"), vp));
    253     } else if (data_type == _BCM_FLOW_DATA_TYPE_COMMON) { 
    254         evxlt_field_id = COMMON__EVXLT_KEY_SELf;
    255     }
    256     if (evxlt_field_id != 0) {
    257         egr_key_type_value = soc_mem_field32_get(unit, mem, &egr_dvp_attribute,
    258                                         evxlt_field_id);
    259         rv = _bcm_esw_dvp_vtkey_type_get(unit, 
    260                                  egr_key_type_value, key_type);
    261 
    262         /* bcmVlanTranslateEgressKeyVpn only for network port*/
    263         if ((!network_port) && (*key_type == bcmVlanTranslateEgressKeyVpn)) {
    264             return BCM_E_UNAVAIL;
    265         }
    266     }
    267     return rv;
    268 }
    269 
    270 STATIC int
    271 _bcm_flow_egress_network_dvp_set(int unit,
    272                        bcm_flow_port_encap_t *info,
    273                        bcm_flow_logical_field_t *field,
    274                        int num_of_fields)
    275 {
    276 
    277     int rv=BCM_E_UNAVAIL;
    278     int local_drop = 0;
    279     int network_group=0;
    280     soc_mem_t mem_view_id;
    281     soc_mem_t mem_id = 0;
    282     int dvp;
    283     uint32 entry[SOC_MAX_MEM_WORDS];
    284     uint32 dvp_ctrl;
    285     soc_field_t dvp_grp_f;
    286     soc_field_t network_grp_f;
    287     soc_field_t dvp_port_f;
    288     soc_field_t dis_vp_p_f;
    289     soc_field_t del_vntag_f;
    290     soc_field_t class_id_f;
    291     soc_field_t mtu_val_f;
    292     soc_field_t mtu_en_f;
    293     soc_field_t uuc_drop_f;
    294     soc_field_t umc_drop_f;
    295     soc_field_t bc_drop_f;
    296     uint32 data_ids[_BCM_FLOW_LOGICAL_FIELD_MAX];
    297     uint32 cnt;
    298     int i;
    299     int j;
    300 
    301     dvp = _SHR_GPORT_FLOW_PORT_ID_GET(info->flow_port);
    302     mem_id = EGR_DVP_ATTRIBUTEm;
    303 
    304     /* get the physical memory view */
    305     if (_BCM_FLOW_IS_FLEX_VIEW(info)) {
    306         rv = soc_flow_db_ffo_to_mem_view_id_get(unit,info->flow_handle,
    307                    info->flow_option, SOC_FLOW_DB_FUNC_ENCAP_SET_ID,
    308                    (uint32 *)&mem_view_id);
    309         BCM_IF_ERROR_RETURN(rv);
    310         LOG_VERBOSE(BSL_LS_BCM_FLOW, (BSL_META_U(unit,
    311              "dvp: %d mem_view_id: 0x%x\n"), dvp, mem_view_id));
    312 
    313         mem_id = mem_view_id;
    314     }
    315 
    316     if (info->options & BCM_FLOW_PORT_ENCAP_OPTION_REPLACE) {
    317         if (!_BCM_FLOW_EGR_DVP_USED_GET(unit,dvp)) {
    318             return BCM_E_NOT_FOUND;
    319         }
    320         BCM_IF_ERROR_RETURN(soc_mem_read(unit,mem_id, MEM_BLOCK_ANY, dvp, 
    321                                          entry));
    322     } else {
    323         sal_memset(entry, 0, sizeof(entry));
    324         if (_BCM_FLOW_IS_FLEX_VIEW(info)) {
    325             /* flex view, initialize all control fields such as data_type */
    326             soc_flow_db_mem_view_entry_init(unit,mem_view_id,entry);
    327         }
    328     }
    329 
    330     local_drop = (info->flags & BCM_FLOW_PORT_ENCAP_FLAG_DROP) ? 1 : 0;
    331 
    332     if (info->valid_elements & BCM_FLOW_PORT_ENCAP_NETWORK_GROUP_VALID) {
    333         if (soc_feature(unit, soc_feature_multiple_split_horizon_group)){
    334             network_group = info->network_group; 
    335             rv = _bcm_validate_splithorizon_network_group(unit,
    336                    TRUE, &network_group);
    337             BCM_IF_ERROR_RETURN(rv);
    338         }
    339     }
    340 
    341     if (!_BCM_FLOW_IS_FLEX_VIEW(info)) {
    342         soc_mem_field32_set(unit, mem_id, entry, DATA_TYPEf, 
    343                            info->flow_handle == SOC_FLOW_DB_FLOW_ID_LEGACY_VXLAN?
    344                                    _BCM_FLOW_VXLAN_EGRESS_DEST_VP_TYPE:
    345                                    _BCM_FLOW_L2GRE_EGRESS_DEST_VP_TYPE);
    346 
    347         if (info->flow_handle == SOC_FLOW_DB_FLOW_ID_LEGACY_VXLAN) {
    348             dvp_grp_f    = VXLAN__VT_DVP_GROUP_IDf;
    349             network_grp_f = VXLAN__DVP_NETWORK_GROUPf;
    350             dvp_port_f   = VXLAN__DVP_IS_NETWORK_PORTf;
    351             dis_vp_p_f   = VXLAN__DISABLE_VP_PRUNINGf;
    352             del_vntag_f  = VXLAN__DELETE_VNTAGf;
    353             class_id_f   = VXLAN__CLASS_IDf;
    354             mtu_val_f    = VXLAN__MTU_VALUEf;
    355             mtu_en_f     = VXLAN__MTU_ENABLEf;
    356             uuc_drop_f   = VXLAN__UUC_DROPf;
    357             umc_drop_f   = VXLAN__UMC_DROPf;
    358             bc_drop_f    = VXLAN__BC_DROPf;
    359         } else if (info->flow_handle == SOC_FLOW_DB_FLOW_ID_LEGACY_L2GRE) {
    360             dvp_grp_f    = L2GRE__VT_DVP_GROUP_IDf;
    361             network_grp_f = L2GRE__DVP_NETWORK_GROUPf;
    362             dvp_port_f   = L2GRE__DVP_IS_NETWORK_PORTf;
    363             dis_vp_p_f   = L2GRE__DISABLE_VP_PRUNINGf;
    364             del_vntag_f  = L2GRE__DELETE_VNTAGf;
    365             class_id_f   = L2GRE__CLASS_IDf;
    366             mtu_val_f    = L2GRE__MTU_VALUEf;
    367             mtu_en_f     = L2GRE__MTU_ENABLEf;
    368             uuc_drop_f   = L2GRE__UUC_DROPf;
    369             umc_drop_f   = L2GRE__UMC_DROPf;
    370             bc_drop_f    = L2GRE__BC_DROPf;
    371         } else {
    372             LOG_ERROR(BSL_LS_BCM_FLOW, (BSL_META_U(unit,
    373                  "flow handle: %d unsupported\n"), info->flow_handle));
    374             return BCM_E_PARAM;
    375         }
    376 
    377         if (info->valid_elements & BCM_FLOW_PORT_ENCAP_NETWORK_GROUP_VALID) {
    378             if (soc_feature(unit, soc_feature_multiple_split_horizon_group)){
    379                 soc_mem_field32_set(unit, mem_id, entry, network_grp_f, 
    380                                     network_group);
    381             } else {
    382                 soc_mem_field32_set(unit, mem_id, entry, dvp_port_f, 1);
    383             }
    384         }
    385         soc_mem_field32_set(unit, mem_id, entry, dis_vp_p_f, 0);
    386         soc_mem_field32_set(unit, mem_id, entry, del_vntag_f, 1);
    387         if (info->valid_elements & BCM_FLOW_PORT_ENCAP_CLASS_ID_VALID) {
    388             soc_mem_field32_set(unit, mem_id, entry, class_id_f,info->class_id);
    389         }
    390         if (info->valid_elements & BCM_FLOW_PORT_ENCAP_MTU_VALID) {
    391             soc_mem_field32_set(unit, mem_id, entry, mtu_val_f, info->mtu);
    392             soc_mem_field32_set(unit, mem_id, entry, mtu_en_f, info->mtu? 1: 0);
    393         }
    394         if (info->valid_elements & BCM_FLOW_PORT_ENCAP_DVP_GROUP_VALID) {
    395             soc_mem_field32_set(unit, mem_id, entry, dvp_grp_f,info->dvp_group);
    396         }
    397         soc_mem_field32_set(unit, mem_id, entry, uuc_drop_f, local_drop);
    398         soc_mem_field32_set(unit, mem_id, entry, umc_drop_f, local_drop);
    399         soc_mem_field32_set(unit, mem_id, entry, bc_drop_f,  local_drop);
    400 
    401     } else {
    402 
    403         if (info->valid_elements & BCM_FLOW_PORT_ENCAP_NETWORK_GROUP_VALID) {
    404             if (SOC_MEM_FIELD_VALID(unit,mem_id,SWITCHING_CTRLS_ACTION_SETf)) {
    405                 dvp_ctrl = 0;
    406                 if (soc_feature(unit, soc_feature_multiple_split_horizon_group)){
    407                     soc_format_field32_set(unit, DVP_SWITCHING_CTRLS_ACTION_SETfmt,
    408                                        &dvp_ctrl, DVP_NETWORK_GROUPf,network_group);
    409                 } 
    410                 soc_format_field32_set(unit, DVP_SWITCHING_CTRLS_ACTION_SETfmt,
    411                                  &dvp_ctrl, DISABLE_VP_PRUNINGf,0);
    412 
    413                 soc_format_field32_set(unit, DVP_SWITCHING_CTRLS_ACTION_SETfmt,
    414                                  &dvp_ctrl, UUC_DROPf,local_drop);
    415                 soc_format_field32_set(unit, DVP_SWITCHING_CTRLS_ACTION_SETfmt,
    416                                  &dvp_ctrl, UMC_DROPf,local_drop);
    417                 soc_format_field32_set(unit, DVP_SWITCHING_CTRLS_ACTION_SETfmt,
    418                                  &dvp_ctrl, BC_DROPf,local_drop);
    419                 soc_mem_field32_set(unit, mem_id, entry,
    420                                      SWITCHING_CTRLS_ACTION_SETf, dvp_ctrl);
    421             } else {
    422                 LOG_ERROR(BSL_LS_BCM_FLOW, (BSL_META_U(unit,
    423                      "SWITCHING_CTRLS_ACTION_SETf not defined in memory view\n")));
    424                 return BCM_E_PARAM;
    425             }
    426         }
    427         if (info->valid_elements & BCM_FLOW_PORT_ENCAP_CLASS_ID_VALID) {
    428             if (SOC_MEM_FIELD_VALID(unit,mem_id,CLASS_ID_ACTION_SETf)) {
    429                 soc_mem_field32_set(unit, mem_id, entry, CLASS_ID_ACTION_SETf,
    430                                     info->class_id);
    431             } else {
    432                 LOG_ERROR(BSL_LS_BCM_FLOW, (BSL_META_U(unit,
    433                      "CLASS_ID_ACTION_SETf not defined in memory view\n")));
    434                 return BCM_E_INTERNAL;
    435             }
    436         }
    437         if (info->valid_elements & BCM_FLOW_PORT_ENCAP_MTU_VALID) {
    438             if (SOC_MEM_FIELD_VALID(unit,mem_id,MTU_CONTROLS_ACTION_SETf)) {
    439                 uint32 mtu = 0;
    440 
    441                 soc_format_field32_set(unit, MTU_CONTROLS_ACTION_SETfmt,
    442                                        &mtu, MTU_VALUEf,info->mtu);
    443                 soc_format_field32_set(unit, MTU_CONTROLS_ACTION_SETfmt,
    444                                        &mtu, MTU_ENABLEf,info->mtu? 1 : 0);
    445                 soc_mem_field32_set(unit, mem_id, entry, 
    446                                     MTU_CONTROLS_ACTION_SETf, mtu);
    447             } else {
    448                 LOG_ERROR(BSL_LS_BCM_FLOW, (BSL_META_U(unit,
    449                      "MTU_CONTROLS_ACTION_SETf not defined in memory view\n")));
    450                 return BCM_E_PARAM;
    451             }
    452         }
    453         if (info->valid_elements & BCM_FLOW_PORT_ENCAP_DVP_GROUP_VALID) {
    454             if (SOC_MEM_FIELD_VALID(unit,mem_id,VXLT_CLASS_IDf)) {
    455                 soc_mem_field32_set(unit, mem_id, entry, VXLT_CLASS_IDf,
    456                                     info->dvp_group);
    457             } else {
    458                 LOG_ERROR(BSL_LS_BCM_FLOW, (BSL_META_U(unit,
    459                      "VXLT_CLASS_IDf not defined in memory view\n")));
    460                 return BCM_E_PARAM;
    461             }
    462         }
    463 
    464         if (info->valid_elements & BCM_FLOW_PORT_ENCAP_FLEX_DATA_VALID) {
    465             rv = soc_flow_db_mem_view_field_list_get(unit,
    466                       mem_id,
    467                       SOC_FLOW_DB_FIELD_TYPE_LOGICAL_POLICY_DATA,
    468                       _BCM_FLOW_LOGICAL_FIELD_MAX, data_ids, &cnt);
    469             BCM_IF_ERROR_RETURN(rv);
    470             for (i = 0; i < num_of_fields; i++) {
    471                 for (j = 0; j < cnt; j++) {
    472                     if (field[i].id == data_ids[j]) {
    473                         soc_mem_field32_set(unit,mem_id, entry,
    474                               field[i].id, field[i].value);
    475                         break;
    476                     }
    477                 }
    478             }
    479         }
    480     }
    481     rv = soc_mem_write(unit, mem_id, MEM_BLOCK_ALL, dvp, entry);
    482     BCM_IF_ERROR_RETURN(rv);
    483     return rv;
    484 }
    485 
    486 STATIC int
    487 _bcm_flow_egress_dvp_get(int unit,
    488                        bcm_flow_port_encap_t *info,
    489                        bcm_flow_logical_field_t *field,
    490                        int num_of_fields)
    491 {
    492 
    493     int rv;
    494     int local_drop = 0;
    495     soc_mem_t mem_id = 0;
    496     int dvp;
    497     uint32 entry[SOC_MAX_MEM_WORDS];
    498     uint32 dvp_ctrl;
    499     soc_field_t dvp_grp_f;
    500     soc_field_t netowk_grp_f;
    501     soc_field_t class_id_f;
    502     soc_field_t mtu_val_f;
    503     soc_field_t uuc_drop_f;
    504     uint32 data_type;
    505     uint32 data_ids[_BCM_FLOW_LOGICAL_FIELD_MAX];
    506     uint32 cnt;
    507     int i;
    508     int j;
    509     soc_mem_t mem_view_id;
    510 
    511     dvp = _SHR_GPORT_FLOW_PORT_ID_GET(info->flow_port);
    512     mem_id = EGR_DVP_ATTRIBUTEm;
    513 
    514     BCM_IF_ERROR_RETURN(soc_mem_read(unit,mem_id, MEM_BLOCK_ANY, dvp, 
    515                                          entry));
    516     data_type = soc_mem_field32_get(unit, mem_id, entry, DATA_TYPEf);
    517     
    518     if (data_type == _BCM_FLOW_DATA_TYPE_COMMON) {
    519         info->flow_handle = 0;
    520         info->mtu = soc_mem_field32_get(unit, mem_id, entry,
    521                                 COMMON__MTU_VALUEf);
    522         info->network_group = soc_mem_field32_get(unit, mem_id, entry,
    523                                 COMMON__DVP_NETWORK_GROUPf);
    524         return BCM_E_NONE;
    525     } else if (data_type == _BCM_FLOW_VXLAN_EGRESS_DEST_VP_TYPE) {
    526         info->flow_handle = SOC_FLOW_DB_FLOW_ID_LEGACY_VXLAN;
    527     } else if (data_type == _BCM_FLOW_L2GRE_EGRESS_DEST_VP_TYPE) {
    528         info->flow_handle = SOC_FLOW_DB_FLOW_ID_LEGACY_L2GRE;
    529     } else { /* flex */
    530         /* find the memory view based on the memory and key type */
    531         rv = soc_flow_db_mem_to_view_id_get (unit, mem_id, 
    532                     SOC_FLOW_DB_KEY_TYPE_INVALID, data_type,
    533                     0, NULL, (uint32 *)&mem_view_id);
    534         SOC_IF_ERROR_RETURN(rv);
    535         mem_id = mem_view_id;
    536     }
    537 
    538     if (data_type <= _BCM_FLOW_L2GRE_EGRESS_DEST_VP_TYPE) {  /* fixed view */
    539         if (info->flow_handle == SOC_FLOW_DB_FLOW_ID_LEGACY_VXLAN) {
    540             netowk_grp_f = VXLAN__DVP_NETWORK_GROUPf;
    541             dvp_grp_f    = VXLAN__VT_DVP_GROUP_IDf;
    542             class_id_f   = VXLAN__CLASS_IDf;
    543             mtu_val_f    = VXLAN__MTU_VALUEf;
    544             uuc_drop_f   = VXLAN__UUC_DROPf;
    545         } else {
    546             netowk_grp_f = L2GRE__DVP_NETWORK_GROUPf;
    547             dvp_grp_f    = L2GRE__VT_DVP_GROUP_IDf;
    548             class_id_f   = L2GRE__CLASS_IDf;
    549             mtu_val_f    = L2GRE__MTU_VALUEf;
    550             uuc_drop_f   = L2GRE__UUC_DROPf;
    551         }
    552         info->network_group = soc_mem_field32_get(unit, mem_id, entry, 
    553                                     netowk_grp_f);
    554         info->dvp_group = soc_mem_field32_get(unit, mem_id, entry, 
    555                                     dvp_grp_f);
    556         
    557         info->class_id = soc_mem_field32_get(unit, mem_id, entry, class_id_f);
    558         info->mtu = soc_mem_field32_get(unit, mem_id, entry, mtu_val_f);
    559         local_drop = soc_mem_field32_get(unit, mem_id, entry, uuc_drop_f);
    560         if (local_drop) {
    561             info->flags |= BCM_FLOW_PORT_ENCAP_FLAG_DROP;
    562         }
    563 
    564     } else {  /* flex view */
    565         if (SOC_MEM_FIELD_VALID(unit,mem_id,SWITCHING_CTRLS_ACTION_SETf)) {
    566             dvp_ctrl = soc_mem_field32_get(unit, mem_id, entry,
    567                                      SWITCHING_CTRLS_ACTION_SETf);
    568             info->network_group = soc_format_field32_get(unit, 
    569                                    DVP_SWITCHING_CTRLS_ACTION_SETfmt,
    570                                    &dvp_ctrl, DVP_NETWORK_GROUPf);
    571             local_drop = soc_format_field32_get(unit, 
    572                                DVP_SWITCHING_CTRLS_ACTION_SETfmt,
    573                                &dvp_ctrl, UUC_DROPf);
    574         }
    575         if (SOC_MEM_FIELD_VALID(unit,mem_id,CLASS_ID_ACTION_SETf)) {
    576             info->class_id = soc_mem_field32_get(unit, mem_id, entry, 
    577                                 CLASS_ID_ACTION_SETf);
    578         }
    579         if (SOC_MEM_FIELD_VALID(unit,mem_id,MTU_CONTROLS_ACTION_SETf)) {
    580             uint32 mtu = 0;
    581 
    582             mtu = soc_mem_field32_get(unit, mem_id, entry,
    583                                     MTU_CONTROLS_ACTION_SETf);
    584             info->mtu = soc_format_field32_get(unit, MTU_CONTROLS_ACTION_SETfmt,
    585                                    &mtu, MTU_VALUEf);
    586         }
    587         if (SOC_MEM_FIELD_VALID(unit,mem_id,VXLT_CLASS_IDf)) {
    588             info->dvp_group  = soc_mem_field32_get(unit, mem_id, entry, 
    589                                         VXLT_CLASS_IDf);
    590         }
    591 
    592         if (field != NULL && num_of_fields) {
    593             rv = soc_flow_db_mem_view_field_list_get(unit,
    594                           mem_id,
    595                           SOC_FLOW_DB_FIELD_TYPE_LOGICAL_POLICY_DATA,
    596                           _BCM_FLOW_LOGICAL_FIELD_MAX, data_ids, &cnt);
    597             BCM_IF_ERROR_RETURN(rv);
    598             for (i = 0; i < num_of_fields; i++) {
    599                 for (j = 0; j < cnt; j++) {
    600                     if (field[i].id == data_ids[j]) {
    601                         field[i].value = soc_mem_field32_get(unit,mem_id, entry,
    602                               field[i].id);
    603                         break;
    604                     }
    605                 }
    606             }
    607         }
    608     }
    609     return BCM_E_NONE;
    610 }
    611 
    612 STATIC int
    613 _bcm_flow_egress_access_dvp_set(int unit,
    614                        bcm_flow_port_encap_t *info,
    615                        bcm_flow_logical_field_t *field,
    616                        int num_of_fields)
    617 {
    618     int rv = BCM_E_UNAVAIL;
    619     soc_mem_t mem = EGR_DVP_ATTRIBUTEm;
    620     uint32 entry[SOC_MAX_MEM_WORDS];
    621     int dvp;
    622     soc_mem_t mem_view_id;
    623     uint32 data_ids[_BCM_FLOW_LOGICAL_FIELD_MAX];
    624     uint32 cnt;
    625     int i;
    626     int j;
    627     int network_group = 0;
    628 
    629     dvp = _SHR_GPORT_FLOW_PORT_ID_GET(info->flow_port);
    630 
    631     /* get the physical memory view */
    632     if (_BCM_FLOW_IS_FLEX_VIEW(info)) {
    633         rv = soc_flow_db_ffo_to_mem_view_id_get(unit,info->flow_handle,
    634                    info->flow_option, SOC_FLOW_DB_FUNC_ENCAP_SET_ID,
    635                    (uint32 *)&mem_view_id);
    636         BCM_IF_ERROR_RETURN(rv);
    637         mem = mem_view_id;
    638     }
    639 
    640     if (info->options & BCM_FLOW_PORT_ENCAP_OPTION_REPLACE) {
    641         if (!_BCM_FLOW_EGR_DVP_USED_GET(unit,dvp)) {
    642             return BCM_E_NOT_FOUND;
    643         }
    644         BCM_IF_ERROR_RETURN(soc_mem_read(unit,mem, MEM_BLOCK_ANY, dvp,
    645                                          entry));
    646     } else {
    647         sal_memset(entry, 0, sizeof(entry));
    648         if (_BCM_FLOW_IS_FLEX_VIEW(info)) {
    649             /* flex view, initialize all control fields such as data_type */
    650             soc_flow_db_mem_view_entry_init(unit,mem_view_id,entry);
    651         }
    652     }
    653 
    654     if (info->valid_elements & BCM_FLOW_PORT_ENCAP_NETWORK_GROUP_VALID) {
    655         if (soc_feature(unit, soc_feature_multiple_split_horizon_group)){
    656             network_group = info->network_group;
    657             rv = _bcm_validate_splithorizon_network_group(unit,
    658                    TRUE, &network_group);
    659             BCM_IF_ERROR_RETURN(rv);
    660         }
    661     }
    662 
    663     if (!_BCM_FLOW_IS_FLEX_VIEW(info)) {
    664         if (info->valid_elements & BCM_FLOW_PORT_ENCAP_MTU_VALID) {
    665             /* L2 MTU - This is different from L3 MTU */
    666             if (info->mtu > 0) {
    667                 soc_mem_field32_set(unit, mem, entry, COMMON__MTU_VALUEf,
    668                                     info->mtu);
    669                 soc_mem_field32_set(unit, mem, entry, COMMON__MTU_ENABLEf, 0x1);
    670             } else {
    671                 /* Disable mtu checking if mtu = 0 */
    672                 soc_mem_field32_set(unit, mem, entry, COMMON__MTU_ENABLEf, 0x0);
    673             }
    674         }
    675 
    676         if (info->valid_elements & BCM_FLOW_PORT_ENCAP_NETWORK_GROUP_VALID) {
    677             if (soc_feature(unit, soc_feature_multiple_split_horizon_group)){
    678                 soc_mem_field32_set(unit, mem, entry, COMMON__DVP_NETWORK_GROUPf,
    679                                     network_group);
    680             }
    681         }
    682     } else {
    683         if (info->valid_elements & BCM_FLOW_PORT_ENCAP_MTU_VALID) {
    684             if (SOC_MEM_FIELD_VALID(unit,mem,MTU_CONTROLS_ACTION_SETf)) {
    685                 uint32 mtu = 0;
    686 
    687                 soc_format_field32_set(unit, MTU_CONTROLS_ACTION_SETfmt,
    688                                        &mtu, MTU_VALUEf,info->mtu);
    689                 soc_format_field32_set(unit, MTU_CONTROLS_ACTION_SETfmt,
    690                                        &mtu, MTU_ENABLEf,info->mtu? 1 : 0);
    691                 soc_mem_field32_set(unit, mem, entry,
    692                                     MTU_CONTROLS_ACTION_SETf, mtu);
    693             }
    694         }
    695 
    696         if (info->valid_elements & BCM_FLOW_PORT_ENCAP_FLEX_DATA_VALID) {
    697             rv = soc_flow_db_mem_view_field_list_get(unit,
    698                       mem,
    699                       SOC_FLOW_DB_FIELD_TYPE_LOGICAL_POLICY_DATA,
    700                       _BCM_FLOW_LOGICAL_FIELD_MAX, data_ids, &cnt);
    701             BCM_IF_ERROR_RETURN(rv);
    702             for (i = 0; i < num_of_fields; i++) {
    703                 for (j = 0; j < cnt; j++) {
    704                     if (field[i].id == data_ids[j]) {
    705                         soc_mem_field32_set(unit,mem, entry,
    706                               field[i].id, field[i].value);
    707                         break;
    708                     }
    709                 }
    710             }
    711         }
    712     }
    713     rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, dvp, entry);
    714     BCM_IF_ERROR_RETURN(rv);
    715 
    716     return rv;
    717 }
    718 
    719 /*
    720  * Function:
    721  *      _bcm_flow_nh_cnt_dec
    722  * Purpose:
    723  *      Decrease vxlan port's nexthop count.
    724  * Parameters:
    725  *      unit  - (IN) SOC unit number.
    726  *      vp    - (IN) Virtual port number.
    727  * Returns:
    728  *      BCM_E_XXX
    729  */
    730 
    731 STATIC int
    732 _bcm_flow_nh_cnt_dec(int unit, int vp)
    733 {
    734     int nh_ecmp_index = -1;
    735     ing_dvp_table_entry_t dvp;
    736     uint32  flags = 0;
    737     int  ref_count = 0;
    738     int ecmp = 0;
    739 
    740     BCM_IF_ERROR_RETURN(
    741         READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp, &dvp));
    742 
    743     ecmp = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, ECMPf);
    744     if (ecmp) {
    745         nh_ecmp_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, ECMP_PTRf);
    746         flags = BCM_L3_MULTIPATH;
    747         /* Decrement reference count */
    748         BCM_IF_ERROR_RETURN(
    749              bcm_xgs3_get_ref_count_from_nhi(unit, flags, &ref_count, nh_ecmp_index));
    750     } else {
    751         nh_ecmp_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp,
    752                                               NEXT_HOP_INDEXf);
    753         if(nh_ecmp_index != 0) {
    754              /* Decrement reference count */
    755              BCM_IF_ERROR_RETURN(
    756                   bcm_xgs3_get_ref_count_from_nhi(unit, flags, &ref_count, nh_ecmp_index));
    757         }
    758     }
    759 
    760     return BCM_E_NONE;
    761 }
    762 
    763 /*
    764  * Function:
    765  *      _bcm_flow_ecmp_member_egress_get_first
    766  * Purpose:
    767  *      Modify flow ecmp member object's Egress next hop entry
    768  * Parameters:
    769  *      unit - Device Number
    770  *      ecmp_index - ECMP index
    771  *      index - poiter to first next hop index
    772  * Returns:
    773  *      BCM_E_XXX
    774  */
    775 
    776 STATIC int
    777 _bcm_flow_ecmp_member_egress_get_first(int unit, int ecmp_index, int* index)
    778 {
    779     int i = 0, ecmp_member_count = 0;
    780     int alloc_size;
    781     bcm_if_t *ecmp_member_array = NULL;
    782     int rv = BCM_E_NONE;
    783 
    784     if (!BCM_XGS3_L3_MPATH_EGRESS_IDX_VALID(unit, ecmp_index)) {
    785         return BCM_E_PARAM;
    786     }
    787     alloc_size = sizeof(bcm_if_t)*BCM_XGS3_L3_ECMP_MAX(unit);
    788     ecmp_member_array = sal_alloc(alloc_size, "ecmp member array");
    789     if (NULL == ecmp_member_array) {
    790         return BCM_E_MEMORY;
    791     }
    792     sal_memset(ecmp_member_array, 0, alloc_size);
    793 
    794     rv = bcm_xgs3_l3_egress_multipath_get(unit, ecmp_index, BCM_XGS3_L3_ECMP_MAX(unit),
    795                                   ecmp_member_array, &ecmp_member_count);
    796     if (BCM_FAILURE(rv)) {
    797         goto clean_up;
    798     }
    799 
    800     if (BCM_XGS3_L3_EGRESS_IDX_VALID(unit,
    801                 ecmp_member_array[i])) {
    802         *index = (ecmp_member_array[i] - BCM_XGS3_EGRESS_IDX_MIN(unit));
    803     } else {
    804         rv = BCM_E_PARAM;
    805         goto clean_up;
    806     }
    807 clean_up:
    808     if (ecmp_member_array) {
    809         sal_free(ecmp_member_array);
    810         ecmp_member_array = NULL;
    811     }
    812 
    813     return rv;
    814 }
    815 
    816 
    817 /*
    818  * Function:
    819  *      _bcm_flow_port_egr_nh_get
    820  * Purpose:
    821  *      Get FLOW Next Hop entry
    822  * Parameters:
    823  * Returns:
    824  *      BCM_E_XXX
    825  */
    826 
    827 STATIC int
    828 _bcm_flow_port_egr_nh_get(int unit, bcm_flow_port_encap_t *info)
    829 {
    830     egr_l3_next_hop_entry_t egr_nh;
    831     ing_dvp_table_entry_t dvp;
    832     bcm_flow_encap_config_t einfo;
    833     int nh_ecmp_index=0;
    834     uint32 ecmp=0;
    835     int vp_type;
    836     int rv = BCM_E_NONE;
    837     uint32 action_set = 0;
    838     uint8 process_sd_tag = 0;
    839     uint8 process_higig_controls = 0;
    840     uint8 process_switching_controls = 0;
    841     int i;
    842     int vp;
    843     int data_type;
    844     uint32 view_id = 0;
    845     uint32 flex_data_array[_BCM_FLOW_PDD_FIELD_MAX];
    846     uint32 flex_data_count;
    847     int old_tpid_idx;
    848     soc_mem_t mem;
    849     int num_vp;
    850     uint32 sd_tag;
    851  
    852     vp = _SHR_GPORT_FLOW_PORT_ID_GET(info->flow_port);
    853     num_vp = soc_mem_index_count(unit, SOURCE_VPm);
    854     if ((vp <= 0) || (vp >= num_vp)) {
    855         return BCM_E_PARAM;
    856     } 
    857     mem = EGR_L3_NEXT_HOPm;
    858 
    859     /* Read the HW entries */
    860     BCM_IF_ERROR_RETURN (READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp, &dvp));
    861     vp_type = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, VP_TYPEf); 
    862     if (vp_type == _BCM_FLOW_VXLAN_INGRESS_DEST_VP_TYPE ||
    863         vp_type == _BCM_FLOW_L2GRE_INGRESS_DEST_VP_TYPE) {
    864         ecmp = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, ECMPf);
    865         if (ecmp) {
    866             nh_ecmp_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, 
    867                                       ECMP_PTRf);
    868             info->egress_if = nh_ecmp_index + 
    869                                         BCM_XGS3_MPATH_EGRESS_IDX_MIN(unit);
    870             /*get ecmp's first member nexthop index*/
    871             BCM_IF_ERROR_RETURN(_bcm_flow_ecmp_member_egress_get_first(unit,
    872                       info->egress_if, &nh_ecmp_index));
    873         } else {
    874             nh_ecmp_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, 
    875                                        NEXT_HOP_INDEXf);
    876             /* Extract next hop index from unipath egress object. */
    877             info->egress_if  =  nh_ecmp_index + BCM_XGS3_EGRESS_IDX_MIN(unit);
    878         }
    879 
    880     } else if (soc_ING_DVP_TABLEm_field32_get(unit, &dvp,
    881                           VP_TYPEf) == _BCM_FLOW_DEST_VP_TYPE_ACCESS) {
    882         /* Egress into Access-side, find the tunnel_if */
    883         BCM_IF_ERROR_RETURN(
    884             READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp, &dvp));
    885         nh_ecmp_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, 
    886                                    NEXT_HOP_INDEXf);
    887         /* Extract next hop index from unipath egress object. */
    888         info->egress_if  =  nh_ecmp_index + BCM_XGS3_EGRESS_IDX_MIN(unit);
    889     } else {
    890         return BCM_E_NOT_FOUND;
    891     }
    892 
    893     BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL,
    894                       nh_ecmp_index, &egr_nh));
    895 
    896     data_type = soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, DATA_TYPEf);
    897 
    898     if (BCMI_L3_NH_FLEX_VIEW(data_type)) {
    899         /* Get view id corresponding to the data type. */
    900         rv = soc_flow_db_mem_to_view_id_get(unit,
    901                                  mem,
    902                                  SOC_FLOW_DB_KEY_TYPE_INVALID,
    903                                  data_type,
    904                                  0,
    905                                  NULL,
    906                                  &view_id);
    907         BCM_IF_ERROR_RETURN(rv);
    908 
    909         /* Get PDD field list corresponding to the view id. */
    910         rv = soc_flow_db_mem_view_field_list_get(unit,
    911                             view_id,
    912                             SOC_FLOW_DB_FIELD_TYPE_POLICY_DATA,
    913                             _BCM_FLOW_PDD_FIELD_MAX,
    914                             flex_data_array,
    915                             &flex_data_count);
    916 
    917         BCM_IF_ERROR_RETURN(rv);
    918 
    919         for (i=0; i<flex_data_count; i++) {
    920             switch (flex_data_array[i]) {
    921                 case SD_TAG_ACTION_SETf:
    922                     process_sd_tag = 1;
    923                     break;
    924                 case HIGIG_CONTROLS_ACTION_SETf:
    925                     process_higig_controls = 1;
    926                     break;
    927                 case SWITCHING_CTRLS_ACTION_SETf:
    928                     process_switching_controls = 1;
    929                     break;
    930                 default:
    931                     break;
    932             }
    933         }
    934     } 
    935 
    936     if (BCMI_L3_NH_FLEX_VIEW(data_type) || 
    937         (data_type == _BCM_VXLAN_EGR_NEXT_HOP_SDTAG_VIEW) ||
    938         (data_type == _BCM_VXLAN_EGR_NEXT_HOP_L2OTAG_VIEW)) {
    939 
    940         bcm_flow_encap_config_t_init(&einfo);
    941         /* just to give a flex handle to indicate the flex view */
    942         if (BCMI_L3_NH_FLEX_VIEW(data_type)) {
    943             einfo.flow_handle = SOC_FLOW_DB_FLOW_ID_START + 1;
    944             if (process_sd_tag) {
    945                 sd_tag = soc_mem_field32_get(unit, view_id, &egr_nh,
    946                               SD_TAG_ACTION_SETf);
    947             } else {
    948                 /* check other linked tables */
    949                 (void)_bcm_flow_linked_tbl_sd_tag_get(unit, view_id, 
    950                          (uint32 *)&egr_nh, &sd_tag);
    951             }
    952         } else {
    953             if (data_type != _BCM_VXLAN_EGR_NEXT_HOP_L2OTAG_VIEW) {
    954                 _bcm_flow_egr_nh_sd_tag_get(unit, mem, (uint32 *)&egr_nh, &sd_tag);
    955             }
    956         }
    957 
    958         if (data_type == _BCM_VXLAN_EGR_NEXT_HOP_L2OTAG_VIEW) {
    959             rv = _bcm_flow_sd_tag_get_from_entry(unit, &einfo, mem,
    960                     (uint32 *)&egr_nh, &old_tpid_idx);
    961         } else {
    962             rv = _bcm_flow_sd_tag_get(unit, &einfo, sd_tag, &old_tpid_idx);
    963         }
    964         BCM_IF_ERROR_RETURN(rv);
    965         rv = _bcm_flow_port_encap_info_convert(info, &einfo, FALSE);
    966         BCM_IF_ERROR_RETURN(rv);
    967     }
    968 
    969     if (BCMI_L3_NH_FLEX_VIEW(data_type)) {
    970         if (process_switching_controls) {
    971             int drop;
    972             action_set = 0;
    973 
    974             action_set = soc_mem_field32_get(unit, view_id, &egr_nh,
    975                               SWITCHING_CTRLS_ACTION_SETf);
    976             drop = soc_format_field32_get(unit, SWITCHING_CTRLS_ACTION_SETfmt,
    977                                &action_set, L2_DROPf);
    978             if (drop) {
    979                 info->flags |= BCM_FLOW_PORT_ENCAP_FLAG_DROP;
    980             }
    981             if (process_higig_controls) {
    982                 action_set = soc_mem_field32_get(unit, view_id, &egr_nh,
    983                                   HIGIG_CONTROLS_ACTION_SETf);
    984                 if (soc_format_field32_get(unit, HIGIG_CONTROLS_ACTION_SETfmt,
    985                                        &action_set, HG_HDR_SELf)) {
    986                     info->flags |= BCM_FLOW_PORT_ENCAP_FLAG_LOCAL;
    987                 }
    988             }
    989         }
    990     } else {
    991        if (data_type == _BCM_VXLAN_EGR_NEXT_HOP_SDTAG_VIEW) {
    992            if (soc_mem_field32_get(unit, mem, &egr_nh, SD_TAG__BC_DROPf)
    993               || soc_mem_field32_get(unit, mem, &egr_nh, SD_TAG__UUC_DROPf)
    994               || soc_mem_field32_get(unit, mem, &egr_nh, SD_TAG__UMC_DROPf)) {
    995             info->flags |= BCM_FLOW_PORT_ENCAP_FLAG_DROP;
    996            }
    997        } else if (data_type == _BCM_VXLAN_EGR_NEXT_HOP_L3_VIEW) {
    998            if (!soc_mem_field32_get(unit, mem, &egr_nh, L3__HG_HDR_SELf)) {
    999                info->flags |= BCM_FLOW_PORT_ENCAP_FLAG_LOCAL;
   1000            }
   1001        } else if (data_type == _BCM_VXLAN_EGR_NEXT_HOP_L2OTAG_VIEW) {
   1002            if (soc_mem_field32_get(unit, mem, &egr_nh, L2_OTAG__BC_DROPf)
   1003               || soc_mem_field32_get(unit, mem, &egr_nh, L2_OTAG__UUC_DROPf)
   1004               || soc_mem_field32_get(unit, mem, &egr_nh, L2_OTAG__UMC_DROPf)) {
   1005             info->flags |= BCM_FLOW_PORT_ENCAP_FLAG_DROP;
   1006            }
   1007        }
   1008     }
   1009     return rv;
   1010 }
   1011 
   1012 /*
   1013  * Function:
   1014  *     _bcm_flow_ingress_dvp_2_set
   1015  * Purpose:
   1016  *     Set Ingress DVP tables
   1017  * Parameters:
   1018  *   IN :  Unit
   1019  *   IN :  vp
   1020  *   IN :  flow_port
   1021  * Returns:
   1022  *   BCM_E_XXX
   1023  */
   1024 
   1025 STATIC int
   1026 _bcm_flow_ingress_dvp_2_set(int unit, int vp, uint32 mpath_flag,
   1027                    int vp_nh_ecmp_index, bcm_flow_port_encap_t *info,
   1028                    int is_network_port)
   1029 {
   1030     ing_dvp_2_table_entry_t dvp;
   1031     int rv = BCM_E_NONE;
   1032     int network_group=0;
   1033 
   1034     if (info->options & BCM_FLOW_PORT_ENCAP_OPTION_REPLACE) {
   1035         BCM_IF_ERROR_RETURN(
   1036             READ_ING_DVP_2_TABLEm(unit, MEM_BLOCK_ANY, vp, &dvp));
   1037     } else {
   1038         sal_memset(&dvp, 0, sizeof(ing_dvp_2_table_entry_t));
   1039     }
   1040 
   1041     if (info->valid_elements & BCM_FLOW_PORT_ENCAP_EGRESS_IF_VALID) {
   1042         if (mpath_flag) {
   1043             soc_ING_DVP_2_TABLEm_field32_set(unit, &dvp,
   1044                                   NEXT_HOP_INDEXf, 0x0);
   1045             soc_ING_DVP_2_TABLEm_field32_set(unit, &dvp,
   1046                                  ECMPf, 0x1);
   1047             soc_ING_DVP_2_TABLEm_field32_set(unit, &dvp,
   1048                                  ECMP_PTRf, vp_nh_ecmp_index);
   1049         } else {
   1050             soc_ING_DVP_2_TABLEm_field32_set(unit, &dvp,
   1051                                  ECMPf, 0x0);
   1052             soc_ING_DVP_2_TABLEm_field32_set(unit, &dvp,
   1053                                  ECMP_PTRf, 0);
   1054             soc_ING_DVP_2_TABLEm_field32_set(unit, &dvp,
   1055                                  NEXT_HOP_INDEXf, vp_nh_ecmp_index);
   1056         }
   1057    } 
   1058 
   1059    network_group = info->network_group;
   1060    rv = _bcm_validate_splithorizon_network_group(unit, is_network_port, 
   1061                       &network_group);
   1062    BCM_IF_ERROR_RETURN(rv);
   1063 
   1064    /* Enable DVP as Network_port */
   1065    if (is_network_port) {
   1066        /* Not setting dvp as network port for RIOT as all
   1067           routed packet gets dropped if overlay SVP and DVP
   1068           both are network ports.
   1069           SVP and DVP as network ports is a valid used case
   1070           but reg file says that this field
   1071           is set when DVP is a TRILL port */
   1072 #ifdef BCM_RIOT_SUPPORT
   1073        if ((BCMI_RIOT_IS_ENABLED(unit))) {
   1074            if (soc_feature(unit,
   1075                soc_feature_multiple_split_horizon_group)) {
   1076                soc_ING_DVP_2_TABLEm_field32_set(unit, &dvp,
   1077                        NETWORK_GROUPf, 0x0);
   1078            } else {
   1079                soc_ING_DVP_2_TABLEm_field32_set(unit, &dvp,
   1080                        NETWORK_PORTf, 0x0);
   1081            }
   1082        } else
   1083 #endif
   1084        {
   1085            if (soc_feature(unit, soc_feature_multiple_split_horizon_group)) {
   1086                soc_ING_DVP_2_TABLEm_field32_set(unit, &dvp, NETWORK_GROUPf,
   1087                                  network_group);
   1088            } else {
   1089                soc_ING_DVP_2_TABLEm_field32_set(unit, &dvp,
   1090                              NETWORK_PORTf, 0x1);
   1091            }
   1092        }
   1093        if (info->flow_handle == SOC_FLOW_DB_FLOW_ID_LEGACY_L2GRE) {
   1094            soc_ING_DVP_2_TABLEm_field32_set(unit, &dvp,
   1095                       VP_TYPEf, _BCM_FLOW_L2GRE_INGRESS_DEST_VP_TYPE);
   1096        } else {
   1097            soc_ING_DVP_2_TABLEm_field32_set(unit, &dvp,
   1098                       VP_TYPEf, _BCM_FLOW_VXLAN_INGRESS_DEST_VP_TYPE);
   1099        }
   1100     } else {
   1101         if (soc_feature(unit, soc_feature_multiple_split_horizon_group)) {
   1102             soc_ING_DVP_2_TABLEm_field32_set(unit, &dvp, NETWORK_GROUPf,
   1103                             network_group);
   1104         } else {
   1105             soc_ING_DVP_2_TABLEm_field32_set(unit, &dvp, NETWORK_PORTf, 0x0);
   1106         }
   1107         soc_ING_DVP_2_TABLEm_field32_set(unit, &dvp,
   1108                            VP_TYPEf, _BCM_FLOW_DEST_VP_TYPE_ACCESS);
   1109     }
   1110 
   1111     rv =  WRITE_ING_DVP_2_TABLEm(unit, MEM_BLOCK_ALL, vp, &dvp);
   1112     return rv;
   1113 }
   1114 
   1115 /*
   1116  * Function:
   1117  *     _bcm_flow_ingress_dvp_set
   1118  * Purpose:
   1119  *     Set Ingress DVP tables
   1120  * Parameters:
   1121  *   IN :  Unit
   1122  *   IN :  vp
   1123  *   IN :  flow_port
   1124  * Returns:
   1125  *   BCM_E_XXX
   1126  */
   1127 
   1128 STATIC int
   1129 _bcm_flow_ingress_dvp_set(int unit, int vp, uint32 mpath_flag,
   1130                 int vp_nh_ecmp_index, bcm_flow_port_encap_t *info, 
   1131                 int is_network_port)
   1132 {
   1133     ing_dvp_table_entry_t dvp;
   1134     int rv = BCM_E_NONE;
   1135 
   1136     if (info->options & BCM_FLOW_PORT_ENCAP_OPTION_REPLACE) {
   1137         BCM_IF_ERROR_RETURN(
   1138             READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp, &dvp));
   1139     } else {
   1140         sal_memset(&dvp, 0, sizeof(ing_dvp_table_entry_t));
   1141     }
   1142 
   1143     if (info->valid_elements & BCM_FLOW_PORT_ENCAP_EGRESS_IF_VALID) {
   1144         if (mpath_flag) {
   1145             soc_ING_DVP_TABLEm_field32_set(unit, &dvp,
   1146                                       NEXT_HOP_INDEXf, 0x0);
   1147             soc_ING_DVP_TABLEm_field32_set(unit, &dvp,
   1148                                       ECMPf, 0x1);
   1149             soc_ING_DVP_TABLEm_field32_set(unit, &dvp,
   1150                                       ECMP_PTRf, vp_nh_ecmp_index);
   1151         } else {
   1152             soc_ING_DVP_TABLEm_field32_set(unit, &dvp,
   1153                                       ECMPf, 0x0);
   1154             soc_ING_DVP_TABLEm_field32_set(unit, &dvp,
   1155                                       ECMP_PTRf, 0);
   1156             soc_ING_DVP_TABLEm_field32_set(unit, &dvp,
   1157                                  NEXT_HOP_INDEXf, vp_nh_ecmp_index);
   1158         }
   1159     }
   1160 
   1161    if (is_network_port) {
   1162        if (info->flow_handle == SOC_FLOW_DB_FLOW_ID_LEGACY_VXLAN) {
   1163            soc_ING_DVP_TABLEm_field32_set(unit, &dvp,
   1164                       VP_TYPEf, _BCM_FLOW_VXLAN_INGRESS_DEST_VP_TYPE);
   1165        } else if (info->flow_handle == SOC_FLOW_DB_FLOW_ID_LEGACY_L2GRE) {
   1166            soc_ING_DVP_TABLEm_field32_set(unit, &dvp,
   1167                       VP_TYPEf, _BCM_FLOW_L2GRE_INGRESS_DEST_VP_TYPE);
   1168        } else {
   1169            soc_ING_DVP_TABLEm_field32_set(unit, &dvp,
   1170                       VP_TYPEf, _BCM_FLOW_VXLAN_INGRESS_DEST_VP_TYPE);
   1171       }
   1172    } else {
   1173        soc_ING_DVP_TABLEm_field32_set(unit, &dvp,
   1174                       VP_TYPEf, _BCM_FLOW_DEST_VP_TYPE_ACCESS);
   1175    }
   1176 
   1177    rv =  WRITE_ING_DVP_TABLEm(unit, MEM_BLOCK_ALL, vp, &dvp);
   1178    return rv;
   1179 }
   1180 
   1181 STATIC int
   1182 _bcm_flow_port_encap_info_convert( 
   1183         bcm_flow_port_encap_t *pe_info,
   1184         bcm_flow_encap_config_t *info,
   1185         int port_encap2config)
   1186 {
   1187     uint32 pe_vl[] = {BCM_FLOW_PORT_ENCAP_VLAN_VALID,
   1188                       BCM_FLOW_PORT_ENCAP_PKT_PRI_VALID,
   1189                       BCM_FLOW_PORT_ENCAP_PKT_CFI_VALID,
   1190                       0};
   1191     uint32 pe_flg[] = {BCM_FLOW_PORT_ENCAP_FLAG_SERVICE_VLAN_ADD,
   1192                      BCM_FLOW_PORT_ENCAP_FLAG_SERVICE_VLAN_TPID_REPLACE,
   1193                      BCM_FLOW_PORT_ENCAP_FLAG_VLAN_REPLACE,
   1194                      BCM_FLOW_PORT_ENCAP_FLAG_VLAN_DELETE,
   1195                      BCM_FLOW_PORT_ENCAP_FLAG_VLAN_PRI_TPID_REPLACE,
   1196                      BCM_FLOW_PORT_ENCAP_FLAG_VLAN_PRI_REPLACE, 
   1197                      BCM_FLOW_PORT_ENCAP_FLAG_PRI_REPLACE,
   1198                      BCM_FLOW_PORT_ENCAP_FLAG_TPID_REPLACE,
   1199                      0};
   1200     uint32 e_vl[] = {BCM_FLOW_ENCAP_VLAN_VALID,
   1201                       BCM_FLOW_ENCAP_PKT_PRI_VALID,
   1202                       BCM_FLOW_ENCAP_PKT_CFI_VALID,
   1203                       0};
   1204     uint32 e_flg[] = {BCM_FLOW_ENCAP_FLAG_SERVICE_VLAN_ADD,
   1205                     BCM_FLOW_ENCAP_FLAG_SERVICE_VLAN_TPID_REPLACE,
   1206                     BCM_FLOW_ENCAP_FLAG_VLAN_REPLACE,
   1207                     BCM_FLOW_ENCAP_FLAG_VLAN_DELETE,
   1208                     BCM_FLOW_ENCAP_FLAG_VLAN_PRI_TPID_REPLACE,
   1209                     BCM_FLOW_ENCAP_FLAG_VLAN_PRI_REPLACE,
   1210                     BCM_FLOW_ENCAP_FLAG_PRI_REPLACE,
   1211                     BCM_FLOW_ENCAP_FLAG_TPID_REPLACE,
   1212                     0};
   1213     int i;
   1214 
   1215     if (port_encap2config) {
   1216         i = 0;
   1217         while (pe_vl[i]) {
   1218             if (pe_info->valid_elements & pe_vl[i]) {
   1219                 info->valid_elements |= e_vl[i];
   1220             }
   1221             i++;
   1222         }
   1223         i = 0;
   1224         while (pe_flg[i]) {
   1225             if (pe_info->flags & pe_flg[i]) {
   1226                 info->flags |= e_flg[i];
   1227             }
   1228             i++;
   1229         }
   1230         info->vlan = pe_info->vlan;
   1231         info->pri = pe_info->pri;
   1232         info->cfi = pe_info->cfi;
   1233         info->tpid = pe_info->tpid;
   1234     } else {   /* reverse */
   1235         i = 0;
   1236         while (e_vl[i]) {
   1237             if (info->valid_elements & e_vl[i]) {
   1238                 pe_info->valid_elements |= pe_vl[i];
   1239             }
   1240             i++;
   1241         }
   1242         i = 0;
   1243         while (e_flg[i]) {
   1244             if (info->flags & e_flg[i]) {
   1245                 pe_info->flags |= pe_flg[i];
   1246             }
   1247             i++;
   1248         }
   1249         pe_info->vlan = info->vlan;
   1250         pe_info->pri = info->pri;
   1251         pe_info->cfi = info->cfi;
   1252         pe_info->tpid = info->tpid;
   1253     }
   1254     return BCM_E_NONE;
   1255 }
   1256 
   1257 /*
   1258  * Function:
   1259  *      _bcm_td2_vxlan_ecmp_higig_ppd_select
   1260  * Purpose:
   1261  *      Modify vxlan ecmp member object's higig ppd select
   1262  * Parameters:
   1263  *      unit - Device Number
   1264  *      ecmp_index - ECMP index
   1265  *      flags - vxlan vp flags
   1266  * Returns:
   1267  *      BCM_E_XXX
   1268  */
   1269 
   1270 STATIC int
   1271 _bcm_flow_ecmp_nexthop_entry_set(int unit, int ecmp_index, 
   1272               bcm_flow_port_encap_t *pe_info, int is_network_port)
   1273 {
   1274     int i = 0, ecmp_member_count = 0;
   1275     int alloc_size, index;
   1276     bcm_if_t *ecmp_member_array = NULL;
   1277     int rv = BCM_E_NONE;
   1278 
   1279     if (!BCM_XGS3_L3_MPATH_EGRESS_IDX_VALID(unit, ecmp_index)) {
   1280         return BCM_E_PARAM;
   1281     }
   1282 
   1283     alloc_size = sizeof(bcm_if_t) * BCM_XGS3_L3_ECMP_MAX(unit);
   1284     ecmp_member_array = sal_alloc(alloc_size, "ecmp member array");
   1285     if (NULL == ecmp_member_array) {
   1286         return BCM_E_MEMORY;
   1287     }
   1288     sal_memset(ecmp_member_array, 0, alloc_size);
   1289 
   1290     rv = bcm_xgs3_l3_egress_multipath_get(unit, ecmp_index, 
   1291                                BCM_XGS3_L3_ECMP_MAX(unit),
   1292                               ecmp_member_array, &ecmp_member_count);
   1293     if (BCM_FAILURE(rv)) {
   1294         goto clean_up;
   1295     }
   1296 
   1297     while(i < ecmp_member_count) {
   1298         if (BCM_XGS3_L3_EGRESS_IDX_VALID(unit,
   1299                     ecmp_member_array[i])) {
   1300             index = (ecmp_member_array[i] - BCM_XGS3_EGRESS_IDX_MIN(unit));
   1301 
   1302         } else {
   1303             rv = BCM_E_PARAM;
   1304             goto clean_up;
   1305         }
   1306         rv = _bcm_flow_nexthop_entry_set(unit, index, 0,
   1307               pe_info, is_network_port);
   1308 
   1309         if (BCM_FAILURE(rv)) {
   1310             goto clean_up;
   1311         }
   1312 
   1313         i++;
   1314     }
   1315 
   1316 clean_up:
   1317     if (ecmp_member_array) {
   1318         sal_free(ecmp_member_array);
   1319         ecmp_member_array = NULL;
   1320     }
   1321 
   1322     return rv;
   1323 }
   1324 
   1325 STATIC void
   1326 _bcm_flow_egr_nh_sd_tag_set(int unit, soc_mem_t hw_mem, uint32 *entry,
   1327                             uint32 sd_tag)
   1328 {
   1329     int tag_format;
   1330     uint32 value;
   1331 
   1332     tag_format = SD_TAG_DATA_FORMAT_DOUBLEfmt;
   1333 
   1334     value = soc_format_field32_get(unit,tag_format,&sd_tag, SD_TAG_VIDf);
   1335     soc_mem_field32_set(unit, hw_mem, entry, SD_TAG__SD_TAG_VIDf, value);
   1336 
   1337     value = soc_format_field32_get(unit,tag_format,&sd_tag, SD_TAG_NEW_PRIf);
   1338     soc_mem_field32_set(unit, hw_mem, entry, SD_TAG__NEW_PRIf, value);
   1339     
   1340     value = soc_format_field32_get(unit,tag_format,&sd_tag, SD_TAG_NEW_CFIf);
   1341     soc_mem_field32_set(unit, hw_mem, entry, SD_TAG__NEW_CFIf, value);
   1342     
   1343     value = soc_format_field32_get(unit,tag_format,&sd_tag, SD_TAG_REMARK_CFIf);
   1344     soc_mem_field32_set(unit, hw_mem, entry, SD_TAG__SD_TAG_REMARK_CFIf, value);
   1345     
   1346     value = soc_format_field32_get(unit,tag_format,&sd_tag, 
   1347                                         SD_TAG_ACTION_IF_NOT_PRESENTf);
   1348     soc_mem_field32_set(unit, hw_mem, entry, 
   1349                              SD_TAG__SD_TAG_ACTION_IF_NOT_PRESENTf, value);
   1350     
   1351     value = soc_format_field32_get(unit,tag_format,&sd_tag, 
   1352                                         SD_TAG_ACTION_IF_PRESENTf);
   1353     soc_mem_field32_set(unit, hw_mem, entry, 
   1354                              SD_TAG__SD_TAG_ACTION_IF_PRESENTf, value);
   1355 
   1356     value = soc_format_field32_get(unit,tag_format,&sd_tag, SD_TAG_TPID_INDEXf);
   1357     soc_mem_field32_set(unit, hw_mem, entry, SD_TAG__SD_TAG_TPID_INDEXf, value);
   1358 }
   1359 
   1360 STATIC void
   1361 _bcm_flow_egr_nh_sd_tag_get(int unit, soc_mem_t hw_mem, uint32 *entry,
   1362                             uint32 *sd_tag)
   1363 {
   1364     int tag_format;
   1365     uint32 value;
   1366 
   1367     tag_format = SD_TAG_DATA_FORMAT_DOUBLEfmt;
   1368 
   1369     *sd_tag = 0;
   1370     value = soc_mem_field32_get(unit, hw_mem, entry, SD_TAG__SD_TAG_VIDf);
   1371     soc_format_field32_set(unit,tag_format,sd_tag, SD_TAG_VIDf, value);
   1372 
   1373     value = soc_mem_field32_get(unit, hw_mem, entry, SD_TAG__NEW_PRIf);
   1374     soc_format_field32_set(unit,tag_format,sd_tag, SD_TAG_NEW_PRIf, value);
   1375 
   1376     value = soc_mem_field32_get(unit, hw_mem, entry, SD_TAG__NEW_CFIf);
   1377     soc_format_field32_set(unit,tag_format,sd_tag, SD_TAG_NEW_CFIf, value);
   1378 
   1379     value = soc_mem_field32_get(unit, hw_mem, entry,SD_TAG__SD_TAG_REMARK_CFIf);
   1380     soc_format_field32_set(unit,tag_format,sd_tag, SD_TAG_REMARK_CFIf, value);
   1381 
   1382     value = soc_mem_field32_get(unit, hw_mem, entry,
   1383                                 SD_TAG__SD_TAG_ACTION_IF_NOT_PRESENTf);
   1384     soc_format_field32_set(unit,tag_format,sd_tag, 
   1385                                 SD_TAG_ACTION_IF_NOT_PRESENTf, value);
   1386 
   1387     value = soc_mem_field32_get(unit, hw_mem, entry,
   1388                                 SD_TAG__SD_TAG_ACTION_IF_PRESENTf);
   1389     soc_format_field32_set(unit,tag_format,sd_tag, 
   1390                                 SD_TAG_ACTION_IF_PRESENTf, value);
   1391 
   1392     value = soc_mem_field32_get(unit, hw_mem, entry,SD_TAG__SD_TAG_TPID_INDEXf);
   1393     soc_format_field32_set(unit,tag_format,sd_tag, SD_TAG_TPID_INDEXf, value);
   1394 }
   1395 
   1396 STATIC int
   1397 _bcm_flow_linked_tbl_sd_tag_set(int unit, soc_mem_t view_id, 
   1398               uint32 *egr_nh, uint32 sd_tag)
   1399 {
   1400     uint32 nptr_entry[SOC_MAX_MEM_WORDS];
   1401     uint32 action_set;
   1402     int next_ptr_type;
   1403     int next_ptr;
   1404     int data_type;
   1405     uint32 nptr_view_id;
   1406     soc_mem_t mem;
   1407     int rv = SOC_E_NOT_FOUND;
   1408 
   1409     if (!SOC_MEM_FIELD_VALID(unit,view_id,NEXT_PTR_ACTION_SETf)) {
   1410         return SOC_E_NOT_FOUND; 
   1411     }
   1412     action_set = soc_mem_field32_get(unit, view_id, egr_nh, 
   1413                                            NEXT_PTR_ACTION_SETf);
   1414     next_ptr_type = soc_format_field32_get(unit, NEXT_PTR_ACTION_SETfmt,
   1415                                       &action_set, NEXT_PTR_TYPEf);
   1416     next_ptr = soc_format_field32_get(unit, NEXT_PTR_ACTION_SETfmt,
   1417                                       &action_set, NEXT_PTRf);
   1418 
   1419     /* for now only handle VC_AND_SWAP table */
   1420     if (next_ptr_type == 3) { /* VC_AND_SWAP */
   1421         mem = EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm;
   1422     } else {
   1423         mem = 0;
   1424     }
   1425    
   1426     if (mem) {
   1427         soc_mem_lock(unit,mem);
   1428         rv =  soc_mem_read(unit, mem, MEM_BLOCK_ANY,
   1429                                       next_ptr, nptr_entry);
   1430         if (SOC_FAILURE(rv)) {
   1431             soc_mem_unlock(unit,mem);
   1432             return rv;
   1433         }
   1434         data_type = soc_mem_field32_get(unit, mem, nptr_entry, DATA_TYPEf);
   1435 
   1436         rv = soc_flow_db_mem_to_view_id_get(unit,
   1437                          mem,
   1438                          SOC_FLOW_DB_KEY_TYPE_INVALID,
   1439                          data_type,
   1440                          0,
   1441                          NULL,
   1442                          &nptr_view_id);
   1443         if (SOC_FAILURE(rv)) {
   1444             soc_mem_unlock(unit,mem);
   1445             return rv;
   1446         }
   1447         if (SOC_MEM_FIELD_VALID(unit,nptr_view_id, SD_TAG_ACTION_SETf)) {
   1448             soc_mem_field32_set(unit, nptr_view_id, nptr_entry, 
   1449                                 SD_TAG_ACTION_SETf, sd_tag);
   1450             rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, next_ptr, nptr_entry);
   1451 
   1452         }
   1453         soc_mem_unlock(unit,mem);
   1454     }
   1455     return rv; 
   1456 }
   1457 STATIC int
   1458 _bcm_flow_linked_tbl_sd_tag_get(int unit, soc_mem_t view_id, 
   1459               uint32 *egr_nh, uint32 *sd_tag)
   1460 {
   1461     uint32 nptr_entry[SOC_MAX_MEM_WORDS];
   1462     uint32 action_set;
   1463     int next_ptr_type;
   1464     int next_ptr;
   1465     int data_type;
   1466     uint32 nptr_view_id;
   1467     soc_mem_t mem;
   1468 
   1469     *sd_tag = 0;
   1470     if (!SOC_MEM_FIELD_VALID(unit,view_id,NEXT_PTR_ACTION_SETf)) {
   1471         return SOC_E_NOT_FOUND; 
   1472     }
   1473     action_set = soc_mem_field32_get(unit, view_id, egr_nh, 
   1474                                            NEXT_PTR_ACTION_SETf);
   1475     next_ptr_type = soc_format_field32_get(unit, NEXT_PTR_ACTION_SETfmt,
   1476                                       &action_set, NEXT_PTR_TYPEf);
   1477     next_ptr = soc_format_field32_get(unit, NEXT_PTR_ACTION_SETfmt,
   1478                                       &action_set, NEXT_PTRf);
   1479 
   1480     /* for now only handle VC_AND_SWAP table */
   1481     if (next_ptr_type == 3) { /* VC_AND_SWAP */
   1482         mem = EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm;
   1483     } else {
   1484         mem = 0;
   1485     }
   1486    
   1487     if (mem) {
   1488         SOC_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ANY,
   1489                                       next_ptr, nptr_entry));
   1490         data_type = soc_mem_field32_get(unit, mem, nptr_entry, DATA_TYPEf);
   1491 
   1492         SOC_IF_ERROR_RETURN(soc_flow_db_mem_to_view_id_get(unit,
   1493                          mem,
   1494                          SOC_FLOW_DB_KEY_TYPE_INVALID,
   1495                          data_type,
   1496                          0,
   1497                          NULL,
   1498                          &nptr_view_id));
   1499         if (SOC_MEM_FIELD_VALID(unit,nptr_view_id, SD_TAG_ACTION_SETf)) {
   1500             *sd_tag = soc_mem_field32_get(unit, nptr_view_id, nptr_entry, 
   1501                                 SD_TAG_ACTION_SETf);
   1502         }
   1503     }
   1504     return SOC_E_NONE; 
   1505 }
   1506    
   1507 
   1508              
   1509 /*
   1510  * Function:
   1511  *      _bcm_flow_nexthop_entry_set
   1512  * Purpose:
   1513  *      Modify Egress entry - flex views only
   1514  * Parameters:
   1515  *      unit - Device Number
   1516  *      nh_index - Next Hop Index
   1517  *      new_entry_type - New Entry type
   1518  * Returns:
   1519  *      BCM_E_XXX
   1520  */
   1521 
   1522 STATIC int
   1523 _bcm_flow_nexthop_entry_set(int unit, int nh_index, int drop,
   1524               bcm_flow_port_encap_t *pe_info, int is_network_port)
   1525 {
   1526     uint32 egr_nh[SOC_MAX_MEM_WORDS];
   1527     bcm_flow_encap_config_t einfo;
   1528     uint32 sd_tag;
   1529     int tpid_index = -1;
   1530     int vp;
   1531     source_vp_entry_t svp;
   1532     int data_type;
   1533 
   1534     int rv = BCM_E_NONE;
   1535 
   1536     int i;
   1537     uint32 action_set = 0;
   1538     uint8 process_sd_tag = 0;
   1539     uint8 process_higig_controls = 0;
   1540     uint8 process_switching_controls = 0;
   1541     uint8 process_next_ptr = 0;
   1542     uint8 is_eline;
   1543 
   1544     uint32  view_id=0;
   1545     uint32 flex_data_array[_BCM_FLOW_PDD_FIELD_MAX];
   1546     uint32 flex_data_count;
   1547 
   1548     vp = _SHR_GPORT_FLOW_PORT_ID_GET(pe_info->flow_port);
   1549     rv = READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp, &svp);
   1550     BCM_IF_ERROR_RETURN(rv);
   1551 
   1552     soc_mem_lock(unit,EGR_L3_NEXT_HOPm); 
   1553     rv = soc_mem_read(unit, EGR_L3_NEXT_HOPm, MEM_BLOCK_ALL,
   1554                       nh_index, egr_nh);
   1555     if (SOC_FAILURE(rv)) {
   1556         goto cleanup;
   1557     }
   1558 
   1559     data_type = soc_EGR_L3_NEXT_HOPm_field32_get(unit, egr_nh, DATA_TYPEf);
   1560 
   1561     if (BCMI_L3_NH_FLEX_VIEW(data_type)) {
   1562         /* Get view id corresponding to the data type. */
   1563         rv = soc_flow_db_mem_to_view_id_get(unit,
   1564                                  EGR_L3_NEXT_HOPm,
   1565                                  SOC_FLOW_DB_KEY_TYPE_INVALID,
   1566                                  data_type,
   1567                                  0,
   1568                                  NULL,
   1569                                  &view_id);
   1570         if (SOC_FAILURE(rv)) {
   1571             goto cleanup;
   1572         }
   1573 
   1574         /* Get PDD field list corresponding to the view id. */
   1575         rv = soc_flow_db_mem_view_field_list_get(unit,
   1576                             view_id,
   1577                             SOC_FLOW_DB_FIELD_TYPE_POLICY_DATA,
   1578                             _BCM_FLOW_PDD_FIELD_MAX,
   1579                             flex_data_array,
   1580                             &flex_data_count);
   1581 
   1582         if (SOC_FAILURE(rv)) {
   1583             goto cleanup;
   1584         }
   1585 
   1586         for (i=0; i<flex_data_count; i++) {
   1587             switch (flex_data_array[i]) {
   1588                 case SD_TAG_ACTION_SETf:
   1589                     process_sd_tag = 1;
   1590                     break;
   1591                 case HIGIG_CONTROLS_ACTION_SETf:
   1592                     process_higig_controls = 1;
   1593                     break;
   1594                 case SWITCHING_CTRLS_ACTION_SETf:
   1595                     process_switching_controls = 1;
   1596                     break;
   1597                 case NEXT_PTR_ACTION_SETf:
   1598                     process_next_ptr = 1;
   1599                     break;
   1600                 default:
   1601                     break;
   1602             }
   1603         }
   1604     } 
   1605 
   1606     if (!is_network_port) {  /* access port side */
   1607 
   1608         if (BCMI_L3_NH_FLEX_VIEW(data_type)) {
   1609             if (process_next_ptr) {
   1610                 action_set = 0;
   1611                 soc_format_field32_set(unit, NEXT_PTR_ACTION_SETfmt,
   1612                                &action_set, NEXT_PTR_TYPEf,
   1613                                BCMI_L3_NH_EGR_NEXT_PTR_TYPE_DVP);
   1614 
   1615                 soc_format_field32_set(unit, NEXT_PTR_ACTION_SETfmt,
   1616                                &action_set, NEXT_PTRf,
   1617                                vp);
   1618 
   1619                 soc_mem_field32_set(unit, view_id, egr_nh,
   1620                               NEXT_PTR_ACTION_SETf, action_set);
   1621             }
   1622         } else {
   1623             if (soc_feature(unit, soc_feature_vxlan_decoupled_mode)) {
   1624                 /* should always be L2TAG view */
   1625                 if (data_type != _BCM_VXLAN_EGR_NEXT_HOP_L2OTAG_VIEW) {
   1626                     /* first time setup */
   1627                     sal_memset(egr_nh, 0, sizeof(egr_nh));
   1628                     soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, egr_nh,
   1629                                 DATA_TYPEf, _BCM_VXLAN_EGR_NEXT_HOP_L2OTAG_VIEW);
   1630 
   1631                     soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, egr_nh,
   1632                                 L2_OTAG__FLOW_SELECT_CTRL_IDf, 0x8);
   1633                     soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, egr_nh,
   1634                                 L2_OTAG__NEXT_PTR_TYPEf, 0x1);
   1635                     data_type = _BCM_VXLAN_EGR_NEXT_HOP_L2OTAG_VIEW;
   1636                 }
   1637                 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, egr_nh,
   1638                                 L2_OTAG__DVPf, vp);
   1639                 if (pe_info->valid_elements & BCM_FLOW_PORT_ENCAP_CLASS_ID_VALID) {
   1640                     soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, egr_nh,
   1641                             L2_OTAG__CLASS_IDf, pe_info->class_id);
   1642                 }
   1643             } else {
   1644                 /* should always be SDTAG view */
   1645                 if (data_type != _BCM_VXLAN_EGR_NEXT_HOP_SDTAG_VIEW) {
   1646                     /* first time setup */
   1647                     sal_memset(egr_nh, 0, sizeof(egr_nh));
   1648                     soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, egr_nh,
   1649                                 DATA_TYPEf, _BCM_VXLAN_EGR_NEXT_HOP_SDTAG_VIEW);
   1650                 }
   1651                 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, egr_nh,
   1652                                 SD_TAG__DVPf, vp);
   1653             }
   1654         } 
   1655 
   1656         if (pe_info->valid_elements & BCM_FLOW_PORT_ENCAP_FLAGS_VALID) {
   1657             rv = bcmi_esw_flow_vp_is_eline(unit,vp, &is_eline);
   1658             if (SOC_FAILURE(rv)) {
   1659                 goto cleanup;
   1660             }
   1661          
   1662             if (!BCMI_L3_NH_FLEX_VIEW(data_type) ) {
   1663                 if (soc_feature(unit, soc_feature_vxlan_decoupled_mode)) {
   1664                     soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, egr_nh,
   1665                             L2_OTAG__BC_DROPf, drop ? 1 : 0);
   1666                     soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, egr_nh,
   1667                             L2_OTAG__UUC_DROPf, drop ? 1 : 0);
   1668                     soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, egr_nh,
   1669                             L2_OTAG__UMC_DROPf, drop ? 1 : 0);
   1670                     soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, egr_nh,
   1671                             L2_OTAG__HG_LEARN_OVERRIDEf, is_eline ? 1 : 0);
   1672                     soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, egr_nh,
   1673                                 L2_OTAG__HG_MODIFY_ENABLEf, 0x0);
   1674                     soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, egr_nh,
   1675                                 L2_OTAG__HG_HDR_SELf,
   1676                             pe_info->flags & BCM_FLOW_PORT_ENCAP_FLAG_LOCAL? 0: 1);
   1677                 } else {
   1678                     soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, egr_nh,
   1679                             SD_TAG__BC_DROPf, drop ? 1 : 0);
   1680                     soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, egr_nh,
   1681                             SD_TAG__UUC_DROPf, drop ? 1 : 0);
   1682                     soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, egr_nh,
   1683                             SD_TAG__UMC_DROPf, drop ? 1 : 0);
   1684                     soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, egr_nh,
   1685                             SD_TAG__HG_LEARN_OVERRIDEf, is_eline ? 1 : 0);
   1686                     /* HG_MODIFY_ENABLE must be 0x0 for Ingress and Egress Chip */
   1687                     soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, egr_nh,
   1688                                 SD_TAG__HG_MODIFY_ENABLEf, 0x0);
   1689                     soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, egr_nh,
   1690                                 SD_TAG__HG_HDR_SELf,
   1691                             pe_info->flags & BCM_FLOW_PORT_ENCAP_FLAG_LOCAL? 0: 1);
   1692                 }
   1693             } else {
   1694                 if (process_switching_controls) {
   1695                     action_set = 0;
   1696 
   1697                     action_set = soc_mem_field32_get(unit, view_id, egr_nh,
   1698                                   SWITCHING_CTRLS_ACTION_SETf);
   1699                     soc_format_field32_set(unit, SWITCHING_CTRLS_ACTION_SETfmt,
   1700                                    &action_set, L2_DROPf,
   1701                                    drop ? 1: 0 );
   1702                     soc_mem_field32_set(unit, view_id, egr_nh,
   1703                                   SWITCHING_CTRLS_ACTION_SETf, action_set);
   1704                 }
   1705 
   1706                 if (process_higig_controls) {
   1707                     action_set = 0;
   1708                     action_set = soc_mem_field32_get(unit, view_id, egr_nh,
   1709                                   HIGIG_CONTROLS_ACTION_SETf);
   1710                     soc_format_field32_set(unit, HIGIG_CONTROLS_ACTION_SETfmt,
   1711                                            &action_set, HG_LEARN_OVERRIDEf,
   1712                                        is_eline ? 1 : 0);
   1713                     soc_mem_field32_set(unit, view_id, egr_nh, 
   1714                                  HIGIG_CONTROLS_ACTION_SETf, action_set);
   1715                 }
   1716             }
   1717         }
   1718     } else {   /* network port side. Should only have L3 view  */
   1719         if (!BCMI_L3_NH_FLEX_VIEW(data_type)) {
   1720             if (data_type == _BCM_VXLAN_EGR_NEXT_HOP_L3_VIEW) {
   1721                 if (soc_feature(unit, soc_feature_egr_modport_to_nhi)) {
   1722                     if (pe_info->flags & BCM_FLOW_PORT_ENCAP_FLAG_LOCAL) {
   1723                         soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, egr_nh,
   1724                                         L3__HG_L2_TUNNEL_ENCAP_ENABLEf, 1);
   1725                         soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, egr_nh,
   1726                                         L3__HG_HDR_SELf, 0);
   1727                     } else {
   1728                         soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, egr_nh,
   1729                                         L3__HG_L2_TUNNEL_ENCAP_ENABLEf, 0);
   1730                         soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, egr_nh,
   1731                                         L3__HG_HDR_SELf, 1);
   1732                     }
   1733                 } else {
   1734                     soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, egr_nh,
   1735                                     L3__HG_HDR_SELf, 1);
   1736                 }
   1737             }
   1738         } else {  /* flex view */
   1739             if (process_higig_controls) {
   1740                 action_set = 0;
   1741                 action_set = soc_mem_field32_get(unit, view_id, egr_nh,
   1742                                   HIGIG_CONTROLS_ACTION_SETf);
   1743                 soc_format_field32_set(unit, HIGIG_CONTROLS_ACTION_SETfmt,
   1744                      &action_set, HG_HDR_SELf,
   1745                      (pe_info->flags & BCM_FLOW_PORT_ENCAP_FLAG_LOCAL)? 0 : 1);
   1746                 soc_mem_field32_set(unit, view_id, egr_nh,
   1747                              HIGIG_CONTROLS_ACTION_SETf, action_set);
   1748             }
   1749         }
   1750     }
   1751 
   1752     if (pe_info->valid_elements & BCM_FLOW_PORT_ENCAP_FLAGS_VALID) {
   1753         /* SD_TAG handling */
   1754         bcm_flow_encap_config_t_init(&einfo);
   1755 
   1756         if (pe_info->flags & BCM_FLOW_PORT_ENCAP_FLAG_SERVICE_TAGGED) {
   1757             rv = _bcm_flow_port_encap_info_convert(pe_info, &einfo, TRUE);
   1758             if (SOC_FAILURE(rv)) {
   1759                 goto cleanup;
   1760             }
   1761             if (BCMI_L3_NH_FLEX_VIEW(data_type)) {
   1762                 /* just to indicate the flex flow */
   1763                 einfo.flow_handle = SOC_FLOW_DB_FLOW_ID_START + 1;
   1764             }
   1765             if (data_type == _BCM_VXLAN_EGR_NEXT_HOP_L2OTAG_VIEW) {
   1766                 rv = _bcm_flow_sd_tag_set_to_entry(unit, &einfo,
   1767                             EGR_L3_NEXT_HOPm, egr_nh, &tpid_index);
   1768             } else {
   1769                 rv = _bcm_flow_sd_tag_set(unit, &einfo, &sd_tag, &tpid_index);
   1770             }
   1771             if (SOC_FAILURE(rv)) {
   1772                 goto cleanup;
   1773             }
   1774             if (BCMI_L3_NH_FLEX_VIEW(data_type)) {
   1775                 if (process_sd_tag) {
   1776                     soc_mem_field32_set(unit, view_id, egr_nh,
   1777                               SD_TAG_ACTION_SETf, sd_tag);
   1778                 } else {
   1779                 /* check sd-tag should be set in a different table */
   1780                     rv = _bcm_flow_linked_tbl_sd_tag_set(unit, view_id,
   1781                             egr_nh, sd_tag);
   1782                     if (rv != SOC_E_NONE && rv != SOC_E_NOT_FOUND) {
   1783                         if (SOC_FAILURE(rv)) {
   1784                             goto cleanup;
   1785                         }
   1786                     }
   1787                 }
   1788             } else {
   1789                 if (!is_network_port) {  /* access port side */
   1790                     if (data_type != _BCM_VXLAN_EGR_NEXT_HOP_L2OTAG_VIEW) {
   1791                         _bcm_flow_egr_nh_sd_tag_set(unit, EGR_L3_NEXT_HOPm, egr_nh,
   1792                                             sd_tag);
   1793                     }
   1794                 }
   1795             }
   1796         }
   1797     }
   1798     rv = soc_mem_write(unit, EGR_L3_NEXT_HOPm,
   1799                        MEM_BLOCK_ALL, nh_index, egr_nh);
   1800     soc_mem_unlock(unit,EGR_L3_NEXT_HOPm); 
   1801     return rv;
   1802 
   1803 cleanup:
   1804     soc_mem_unlock(unit,EGR_L3_NEXT_HOPm); 
   1805     if (tpid_index != -1) {
   1806         (void) _bcm_fb2_outer_tpid_entry_delete(unit, tpid_index);
   1807     }
   1808     return rv;    
   1809 }
   1810 
   1811 /*
   1812  * Function:
   1813  *      _bcm_flow_port_egr_nh_add
   1814  * Purpose:
   1815  *      Add FLOW Next Hop entry
   1816  * Parameters:
   1817  * Returns:
   1818  *      BCM_E_XXX
   1819  */
   1820 
   1821 STATIC int
   1822 _bcm_flow_port_egr_nh_add(int unit, bcm_flow_port_encap_t *info, 
   1823                           int is_network_port, int *nh_idx, uint32 *mflag)    
   1824 {
   1825     egr_l3_next_hop_entry_t egr_nh;
   1826     int rv=BCM_E_NONE;
   1827     uint32 mpath_flag=0;
   1828     int vp_nh_ecmp_index=-1;
   1829     int ref_count = 0;
   1830     int vp;
   1831     int drop;
   1832     int nh_ecmp_index = -1;
   1833     ing_dvp_table_entry_t dvp;
   1834 
   1835     vp = _SHR_GPORT_FLOW_PORT_ID_GET(info->flow_port);
   1836     drop = (info->flags & BCM_FLOW_PORT_ENCAP_FLAG_DROP) ? 1 : 0;
   1837     *nh_idx = 0;
   1838     *mflag  = 0;
   1839 
   1840     if (info->options & BCM_FLOW_PORT_ENCAP_OPTION_REPLACE) {
   1841         SOC_IF_ERROR_RETURN(
   1842             READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp, &dvp));
   1843 
   1844         nh_ecmp_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp,
   1845                                                   NEXT_HOP_INDEXf);
   1846         if (nh_ecmp_index) {
   1847             BCM_IF_ERROR_RETURN(_bcm_flow_nh_cnt_dec(unit, vp));
   1848         }
   1849     }
   1850 
   1851     /*
   1852      * Get egress next-hop index from egress object and
   1853      * increment egress object reference count. multicast will be entirely
   1854      * handled in bcm_l3_egress_create API context.
   1855      */
   1856     rv = bcm_xgs3_get_nh_from_egress_object(unit, info->egress_if,
   1857                                      &mpath_flag, 1, &vp_nh_ecmp_index);
   1858     BCM_IF_ERROR_RETURN(rv);
   1859 
   1860     /* Read the existing egress next_hop entry */
   1861     if (mpath_flag == 0) {
   1862         if (is_network_port) {
   1863             int l3_flag = BCM_XGS3_L3_ENT_FLAG(
   1864                BCM_XGS3_L3_TBL_PTR(unit, next_hop), vp_nh_ecmp_index);
   1865             if (l3_flag != _BCM_L3_FLOW_ONLY) {
   1866                 rv = BCM_E_CONFIG;
   1867                 _BCM_FLOW_CLEANUP(rv)
   1868             }
   1869         }
   1870         rv = soc_mem_read(unit, EGR_L3_NEXT_HOPm, MEM_BLOCK_ANY,
   1871                           vp_nh_ecmp_index, &egr_nh);
   1872         _BCM_FLOW_CLEANUP(rv)
   1873     }
   1874 #if defined(BCM_RIOT_SUPPORT) || defined(BCM_MULTI_LEVEL_ECMP_SUPPORT)
   1875     else {
   1876         /*
   1877          * When Multi-level ECMP is enabled, ECMP group pointed
   1878          * to by DVP must be an underlay group.
   1879          */
   1880         if (BCMI_L3_ECMP_IS_MULTI_LEVEL(unit)) {
   1881             if (vp_nh_ecmp_index < BCMI_L3_ECMP_OVERLAY_ENTRIES(unit)) {
   1882                 return BCM_E_PARAM;
   1883             }
   1884         }
   1885     }
   1886 #endif
   1887 
   1888     *nh_idx = vp_nh_ecmp_index;
   1889     *mflag  = mpath_flag;
   1890     if (is_network_port) {
   1891         if (mpath_flag == 0) {
   1892             rv = _bcm_flow_nexthop_entry_set(unit, vp_nh_ecmp_index, drop,
   1893               info, is_network_port);
   1894             _BCM_FLOW_CLEANUP(rv)
   1895         } else {
   1896             rv = _bcm_flow_ecmp_nexthop_entry_set(unit, info->egress_if, 
   1897                                  info, is_network_port);
   1898             _BCM_FLOW_CLEANUP(rv)
   1899         }
   1900     } else {    /* Egress into Access - Non Tunnel */
   1901         rv = _bcm_flow_nexthop_entry_set(unit, vp_nh_ecmp_index, drop,
   1902               info, is_network_port);
   1903         _BCM_FLOW_CLEANUP(rv)
   1904     }
   1905 
   1906 #ifdef BCM_RIOT_SUPPORT
   1907     if (info->options & BCM_FLOW_PORT_ENCAP_OPTION_REPLACE) {
   1908         rv = bcmi_l3_nh_assoc_ol_ul_link_replace(unit, nh_ecmp_index,
   1909             vp_nh_ecmp_index);
   1910     }
   1911 #endif /* BCM_RIOT_SUPPORT */
   1912     return rv;
   1913 
   1914 cleanup:
   1915     if (vp_nh_ecmp_index != -1) {
   1916         /* Decrement reference count */
   1917         (void) bcm_xgs3_get_ref_count_from_nhi(
   1918             unit, mpath_flag, &ref_count, vp_nh_ecmp_index);
   1919     }
   1920     return rv;
   1921 }
   1922 
   1923 /*
   1924  * Function:
   1925  *           _bcm_flow_port_egr_nh_reset
   1926  * Purpose:
   1927  *           Reset VXLAN Egress NextHop
   1928  * Parameters:
   1929  *           IN :  Unit
   1930  *           IN :  nh_index
   1931  * Returns:
   1932  *           BCM_E_XXX
   1933  */
   1934 
   1935 STATIC int
   1936 _bcm_flow_port_egr_nh_reset(int unit, int nh_index, int vp_type)
   1937 {
   1938     egr_l3_next_hop_entry_t egr_nh;
   1939     int rv=BCM_E_NONE;
   1940     int action_present=0, action_not_present=0, old_tpid_idx = -1;
   1941     uint32 view_id;
   1942     uint32 action_set;
   1943     uint32 entry_type;
   1944 
   1945     BCM_IF_ERROR_RETURN(soc_mem_read(unit, EGR_L3_NEXT_HOPm,
   1946                                  MEM_BLOCK_ANY, nh_index, &egr_nh));
   1947     entry_type = soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, DATA_TYPEf);
   1948 
   1949     if (BCMI_L3_NH_FLEX_VIEW(entry_type)) {
   1950         /* Get view id corresponding to the entry type. */
   1951         rv = soc_flow_db_mem_to_view_id_get(unit,
   1952                                  EGR_L3_NEXT_HOPm,
   1953                                  SOC_FLOW_DB_KEY_TYPE_INVALID,
   1954                                  entry_type,
   1955                                  0,
   1956                                  NULL,
   1957                                  &view_id);
   1958 
   1959         if (!SOC_MEM_FIELD_VALID(unit, view_id, SD_TAG_ACTION_SETf)) {
   1960             return rv;
   1961         }
   1962 
   1963         action_set =  soc_mem_field32_get(unit, view_id, &egr_nh,
   1964                               SD_TAG_ACTION_SETf);
   1965 
   1966         if (vp_type == _BCM_FLOW_DEST_VP_TYPE_ACCESS) {
   1967             action_present =
   1968                 soc_format_field32_get(unit, SD_TAG_ACTION_SETfmt,
   1969                            &action_set, SD_TAG_ACTION_IF_PRESENTf);
   1970             action_not_present =
   1971                 soc_format_field32_get(unit, SD_TAG_ACTION_SETfmt,
   1972                            &action_set, SD_TAG_ACTION_IF_NOT_PRESENTf);
   1973             if ((action_not_present == 0x1) || (action_present == 0x1) ||
   1974                 (action_present == 0x4) || (action_present == 0x7)) {
   1975                 old_tpid_idx =
   1976                      soc_format_field32_get(unit, SD_TAG_ACTION_SETfmt,
   1977                            &action_set, SD_TAG_TPID_INDEXf);
   1978                 BCM_IF_ERROR_RETURN(
   1979                     _bcm_fb2_outer_tpid_entry_delete(unit, old_tpid_idx));
   1980             }
   1981             soc_mem_field32_set(unit, view_id, &egr_nh, SD_TAG_ACTION_SETf,0);
   1982         } else {  /* XXXX reset HG_HDR */
   1983         }
   1984     } else {  /* fixed view */
   1985         if (entry_type == _BCM_VXLAN_EGR_NEXT_HOP_SDTAG_VIEW) {
   1986             action_present =
   1987                 soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh,
   1988                     SD_TAG__SD_TAG_ACTION_IF_PRESENTf);
   1989             action_not_present =
   1990                 soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh,
   1991                     SD_TAG__SD_TAG_ACTION_IF_NOT_PRESENTf);
   1992             if ((action_not_present == 0x1) || (action_present == 0x1) ||
   1993                 (action_present == 0x4) || (action_present == 0x7)) {
   1994                 old_tpid_idx = soc_EGR_L3_NEXT_HOPm_field32_get(unit,
   1995                     &egr_nh, SD_TAG__SD_TAG_TPID_INDEXf);
   1996                 BCM_IF_ERROR_RETURN(
   1997                     _bcm_fb2_outer_tpid_entry_delete(unit, old_tpid_idx));
   1998             }
   1999             /* Normalize Next-hop Entry to L3 View */
   2000             soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, DATA_TYPEf, 0);
   2001         } else if (entry_type == _BCM_VXLAN_EGR_NEXT_HOP_L2OTAG_VIEW) {
   2002             uint32 profile_index;
   2003 
   2004             profile_index = soc_EGR_L3_NEXT_HOPm_field32_get(unit,
   2005                     &egr_nh, L2_OTAG__TAG_ACTION_PROFILE_PTRf);
   2006             BCM_IF_ERROR_RETURN(_bcm_td3_sd_tag_action_get(unit, profile_index,
   2007                     &action_present, &action_not_present));
   2008             if (profile_index != 0) {
   2009                 BCM_IF_ERROR_RETURN(
   2010                     _bcm_trx_egr_vlan_action_profile_entry_delete(unit,
   2011                         profile_index));
   2012             }
   2013             if ((action_not_present == 0x1) || (action_present == 0x1) ||
   2014                 (action_present == 0x4) || (action_present == 0x7)) {
   2015                 old_tpid_idx = soc_EGR_L3_NEXT_HOPm_field32_get(unit,
   2016                     &egr_nh, L2_OTAG__TPID_INDEXf);
   2017                 BCM_IF_ERROR_RETURN(
   2018                     _bcm_fb2_outer_tpid_entry_delete(unit, old_tpid_idx));
   2019             }
   2020             soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, DATA_TYPEf, 0);
   2021             soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   2022                         L2_OTAG__FLOW_SELECT_CTRL_IDf, 0x0);
   2023             soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   2024                         L2_OTAG__NEXT_PTR_TYPEf, 0x0);
   2025         } else { /* L3 view */
   2026         }
   2027     }
   2028 
   2029     BCM_IF_ERROR_RETURN(soc_mem_write(unit, EGR_L3_NEXT_HOPm,
   2030                                  MEM_BLOCK_ANY, nh_index, &egr_nh));
   2031 
   2032     return rv;
   2033 }
   2034 
   2035 /*
   2036  * Function:
   2037  *      _bcm_flow_port_egr_nh_delete
   2038  * Purpose:
   2039  *      Delete FLOW Next Hop entry
   2040  * Parameters:
   2041  * Returns:
   2042  *      BCM_E_XXX
   2043  */
   2044 
   2045 STATIC int
   2046 _bcm_flow_port_egr_nh_delete(int unit, int vp)
   2047 {
   2048     int rv=BCM_E_NONE;
   2049     int nh_ecmp_index=-1;
   2050     ing_dvp_table_entry_t dvp;
   2051     uint32  vp_type=0;
   2052     uint32  flags=0;
   2053     int  ref_count=0;
   2054     int ecmp =-1;
   2055 
   2056     BCM_IF_ERROR_RETURN(READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp, &dvp));
   2057 
   2058     vp_type = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, VP_TYPEf);
   2059     ecmp = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, ECMPf);
   2060     if (ecmp) {
   2061         nh_ecmp_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, ECMP_PTRf);
   2062         flags = BCM_L3_MULTIPATH;
   2063         /* Decrement reference count */
   2064         BCM_IF_ERROR_RETURN(bcm_xgs3_get_ref_count_from_nhi(unit, flags, 
   2065                                  &ref_count, nh_ecmp_index));
   2066         if (ref_count == 1) {
   2067             if (nh_ecmp_index &&
   2068                 ((vp_type == _BCM_FLOW_VXLAN_INGRESS_DEST_VP_TYPE) ||
   2069                  (vp_type == _BCM_FLOW_L2GRE_INGRESS_DEST_VP_TYPE))) {
   2070                 /* support ecmp on network port only 
   2071                  * only deal with the field in L3_VIEW changed by this API
   2072                  * That is the HG_HDR XXXX
   2073                  */
   2074             }
   2075         }
   2076     } else {
   2077         nh_ecmp_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp,
   2078                                               NEXT_HOP_INDEXf);
   2079         if(nh_ecmp_index != 0) {
   2080              /* Decrement reference count */
   2081              BCM_IF_ERROR_RETURN(bcm_xgs3_get_ref_count_from_nhi(unit, flags, 
   2082                                   &ref_count, nh_ecmp_index));
   2083         }
   2084         if (ref_count == 1) {
   2085             if (nh_ecmp_index) {
   2086                 BCM_IF_ERROR_RETURN(_bcm_flow_port_egr_nh_reset(
   2087                                   unit, nh_ecmp_index, vp_type));
   2088             }
   2089         }
   2090     }
   2091     return rv;
   2092 }
   2093 
   2094 /*
   2095  * Function:
   2096  *     _bcm_flow_ingress_dvp_reset
   2097  * Purpose:
   2098  *     Reset Ingress DVP tables
   2099  * Parameters:
   2100  *   IN :  Unit
   2101  *   IN :  vp
   2102  * Returns:
   2103  *   BCM_E_XXX
   2104  */
   2105 
   2106 STATIC int
   2107 _bcm_flow_ingress_dvp_reset(int unit, int vp)
   2108 {
   2109     int rv=BCM_E_UNAVAIL;
   2110     ing_dvp_table_entry_t dvp;
   2111     ing_dvp_2_table_entry_t dvp_2;
   2112 
   2113 
   2114     sal_memset(&dvp, 0, sizeof(ing_dvp_table_entry_t));
   2115     rv =  WRITE_ING_DVP_TABLEm(unit, MEM_BLOCK_ALL, vp, &dvp);
   2116     BCM_IF_ERROR_RETURN(rv);
   2117     sal_memset(&dvp_2, 0, sizeof(ing_dvp_2_table_entry_t));
   2118     rv =  WRITE_ING_DVP_2_TABLEm(unit, MEM_BLOCK_ALL, vp, &dvp_2);
   2119 
   2120     return rv;
   2121 }
   2122 
   2123 /*
   2124  * Function:
   2125  *      _bcm_flow_egress_dvp_reset
   2126  * Purpose:
   2127  *      Reet Egress DVP tables
   2128  * Parameters:
   2129  *      IN :  Unit
   2130  *           IN :  vp
   2131  * Returns:
   2132  *      BCM_E_XXX
   2133  */
   2134 
   2135 STATIC int
   2136 _bcm_flow_egress_dvp_reset(int unit, int vp)
   2137 {
   2138     uint32 dvp[SOC_MAX_MEM_WORDS];
   2139 
   2140     sal_memset(dvp, 0, sizeof(uint32) * SOC_MAX_MEM_WORDS);
   2141     BCM_IF_ERROR_RETURN(soc_mem_write(unit,
   2142             EGR_DVP_ATTRIBUTEm, MEM_BLOCK_ALL, vp, dvp));
   2143 
   2144     return BCM_E_NONE;
   2145 }
   2146 
   2147 /*
   2148  * Function:
   2149  *      bcmi_esw_flow_port_encap_set
   2150  * Purpose:
   2151  *      bind the tunnel object and egress object to the given dvp and cofigure
   2152  * the dvp's tunnel attributes if it is L2 tunnel. For L3 tunnel, bind the
   2153  * egress object with the given tunnel.
   2154  * 
   2155  * Parameters:
   2156  *      unit    - (IN) Device Number
   2157  *      info    - (IN) Flow egress encap descriptor
   2158  *      num_of_fields - (IN) number of logical fields
   2159  *      field         - (IN) logical field array
   2160  * Returns:
   2161  *      BCM_E_XXX
   2162  */
   2163 
   2164 int bcmi_esw_flow_port_encap_set(
   2165     int unit,
   2166     bcm_flow_port_encap_t *info,
   2167     uint32 num_of_fields,
   2168     bcm_flow_logical_field_t *field)
   2169 {
   2170     int dvp;
   2171     int rv;
   2172     int network_port = 0;
   2173     _bcm_vp_info_t vp_info;
   2174     int nh_idx = 0;
   2175     uint32 mpath_flag = 0;
   2176     int num_vp;
   2177 
   2178     if (info == NULL) {
   2179         return BCM_E_PARAM;
   2180     }
   2181 
   2182     dvp = _SHR_GPORT_FLOW_PORT_ID_GET(info->flow_port);
   2183     num_vp = soc_mem_index_count(unit, SOURCE_VPm);
   2184     if ((dvp <= 0) || (dvp >= num_vp)) {
   2185         return BCM_E_PARAM;
   2186     } 
   2187     bcmi_esw_flow_lock(unit);
   2188     if (info->options & BCM_FLOW_PORT_ENCAP_OPTION_CLEAR) {
   2189         if (_BCM_FLOW_EGR_DVP_USED_GET(unit,dvp)) {
   2190             _BCM_FLOW_EGR_DVP_USED_CLR(unit,dvp);
   2191             rv = _bcm_flow_port_egr_nh_delete(unit,dvp);
   2192             if (BCM_SUCCESS(rv)) {
   2193                 rv = _bcm_flow_egress_dvp_reset(unit, dvp);
   2194                 if (BCM_SUCCESS(rv)) {
   2195                     rv = _bcm_flow_ingress_dvp_reset(unit, dvp);
   2196                 }
   2197             }
   2198         } else {
   2199             rv = BCM_E_NOT_FOUND;
   2200         }
   2201         bcmi_esw_flow_unlock(unit);
   2202         SOC_IF_ERROR_RETURN(rv);
   2203         return rv;
   2204     }
   2205  
   2206     if (!_bcm_vp_used_get(unit, dvp, _bcmVpTypeFlow)) {
   2207         LOG_ERROR(BSL_LS_BCM_FLOW, (BSL_META_U(unit,
   2208           "DVP %d is not flow port, create flow port first\n"), dvp));
   2209         bcmi_esw_flow_unlock(unit);
   2210         return BCM_E_NOT_FOUND;
   2211     }
   2212 
   2213     /* Check for Network-Port */
   2214     rv = _bcm_vp_info_get(unit, dvp, &vp_info);
   2215     _BCM_FLOW_CLEANUP(rv);
   2216     if (vp_info.flags & _BCM_VP_INFO_NETWORK_PORT) {
   2217         network_port = TRUE;
   2218     } else {
   2219         network_port = FALSE;
   2220     }
   2221 
   2222     if (info->valid_elements & BCM_FLOW_PORT_ENCAP_EGRESS_IF_VALID) {
   2223         rv = _bcm_flow_port_egr_nh_add(unit, info, network_port, &nh_idx, 
   2224                                    &mpath_flag);
   2225         _BCM_FLOW_CLEANUP(rv);
   2226     }
   2227     if (network_port) {
   2228         rv = _bcm_flow_egress_network_dvp_set(unit, info, field, 
   2229                     num_of_fields);
   2230         _BCM_FLOW_CLEANUP(rv);
   2231 
   2232         /* Program DVP entry  - Ingress  */
   2233         rv = _bcm_flow_ingress_dvp_set(unit, dvp, mpath_flag,
   2234                      nh_idx, info, network_port);
   2235         _BCM_FLOW_CLEANUP(rv);
   2236 
   2237         rv = _bcm_flow_ingress_dvp_2_set(unit, dvp, mpath_flag,
   2238                     nh_idx, info, network_port);
   2239         _BCM_FLOW_CLEANUP(rv);
   2240 
   2241     } else {
   2242         rv = _bcm_flow_egress_access_dvp_set(unit, info, field, num_of_fields);
   2243         _BCM_FLOW_CLEANUP(rv);
   2244 
   2245         /* Program DVP entry  with ECMP / Next Hop Index */
   2246         rv = _bcm_flow_ingress_dvp_set(unit, dvp, mpath_flag,
   2247                        nh_idx, info, network_port);
   2248         _BCM_FLOW_CLEANUP(rv);
   2249 
   2250         rv = _bcm_flow_ingress_dvp_2_set(unit, dvp, mpath_flag,
   2251                                nh_idx, info, network_port);
   2252         _BCM_FLOW_CLEANUP(rv);
   2253     }
   2254 
   2255     if (BCM_SUCCESS(rv)) {
   2256         /* indicates the dvp is set up */
   2257         _BCM_FLOW_EGR_DVP_USED_SET(unit,dvp);
   2258     }
   2259 
   2260 cleanup:
   2261     bcmi_esw_flow_unlock(unit);
   2262     return rv;
   2263 }
   2264 
   2265 /*
   2266  * Function:
   2267  *      bcmi_esw_flow_port_encap_get
   2268  * Purpose:
   2269  *      Get the user configuration parameters from the given object. For L2
   2270    tunnel, it is dvp. For L3 tunnel, it is egress object id. 
   2271  *
   2272  * Parameters:
   2273  *      unit    - (IN) Device Number
   2274  *      info    - (IN/OUT) Flow egress encap descriptor
   2275  *      num_of_fields - (IN) number of logical fields
   2276  *      field         - (IN/OUT) logical field array
   2277  * Returns:
   2278  *      BCM_E_XXX
   2279  */
   2280 
   2281 
   2282 int bcmi_esw_flow_port_encap_get(
   2283     int unit,
   2284     bcm_flow_port_encap_t *info,
   2285     uint32 num_of_fields,
   2286     bcm_flow_logical_field_t *field)
   2287 {
   2288     int dvp;
   2289     int num_vp;
   2290 
   2291     if (info == NULL) {
   2292         return BCM_E_PARAM;
   2293     }
   2294 
   2295     dvp = _SHR_GPORT_FLOW_PORT_ID_GET(info->flow_port);
   2296     num_vp = soc_mem_index_count(unit, SOURCE_VPm);
   2297     if ((dvp <= 0) || (dvp >= num_vp)) {
   2298         return BCM_E_PARAM;
   2299     } 
   2300     if (!_bcm_vp_used_get(unit, dvp, _bcmVpTypeFlow)) {
   2301         LOG_ERROR(BSL_LS_BCM_FLOW, (BSL_META_U(unit,
   2302           "DVP %d is not flow port, create flow port first\n"), dvp));
   2303         return BCM_E_NOT_FOUND;
   2304     }
   2305 
   2306     BCM_IF_ERROR_RETURN(_bcm_flow_port_egr_nh_get(unit, info));
   2307     BCM_IF_ERROR_RETURN(_bcm_flow_egress_dvp_get(unit,
   2308                        info, field, num_of_fields));
   2309     return BCM_E_NONE;
   2310 }
   2311 
   2312 /*
   2313  * Function:
   2314  *      _bcm_flow_encap_fixed_view_entry_init
   2315  * Purpose:
   2316  *      initialize the fixed view memory entry
   2317  * Parameters:
   2318  *      unit - (IN) Device Number
   2319  *      mem  - (IN) memory id
   2320  *      info - (IN) flow encap configuration info
   2321  *      key_type - (IN) the fixed key type
   2322  *      entry    - (OUT) point to the entry to be initialized
   2323  * Returns:
   2324  *      BCM_E_XXX
   2325  */
   2326 STATIC int
   2327 _bcm_flow_encap_fixed_view_entry_init(int unit,
   2328         soc_mem_t mem,
   2329         uint32 key_type,
   2330         uint32 *entry)
   2331 {
   2332     int rv = BCM_E_NONE;
   2333 
   2334     soc_mem_field32_set(unit,mem, entry,  KEY_TYPEf,  key_type);
   2335     if (soc_feature(unit, soc_feature_vxlan_decoupled_mode)) {
   2336         if ((key_type == _BCM_FLOW_ENCAP_VXLAN_KEY_TYPE_VFI) ||
   2337             (key_type == _BCM_FLOW_ENCAP_VXLAN_KEY_TYPE_VFI_DVP)) {
   2338                 soc_mem_field32_set(unit, mem, entry, DATA_TYPEf, 23);
   2339         } else if (key_type == _BCM_FLOW_ENCAP_KEY_TYPE_VFI_DVP_GROUP) {
   2340             soc_mem_field32_set(unit, mem, entry, DATA_TYPEf, 21);
   2341         } else {
   2342             soc_mem_field32_set(unit, mem, entry, DATA_TYPEf, key_type);
   2343         }
   2344     } else {
   2345         soc_mem_field32_set(unit, mem, entry, DATA_TYPEf, key_type);
   2346     }
   2347     if (soc_mem_field_valid(unit, mem, BASE_VALIDf)) {
   2348         soc_mem_field32_set(unit, mem, entry, BASE_VALIDf, 1);
   2349     } else {
   2350         soc_mem_field32_set(unit, mem, entry, BASE_VALID_0f, 3);
   2351         soc_mem_field32_set(unit, mem, entry, BASE_VALID_1f, 7);
   2352     }
   2353     return rv;
   2354 }
   2355 
   2356 /*
   2357  * Function:
   2358  *      _bcm_flow_encap_entry_key_set
   2359  * Purpose:
   2360  *      Set flow encap Entry Key
   2361  * Parameters:
   2362  *      unit - (IN) Device Number
   2363  *      info - (IN) flow_match configuration info
   2364  *      field - (IN) array of logical fields
   2365  *      num_of_fields -(IN) the size of the above array
   2366  *      mem - (IN) memory id
   2367  *      entry - (IN) point to the match entry
   2368  * Returns:
   2369  *      BCM_E_XXX
   2370  */
   2371 
   2372 STATIC
   2373 int _bcm_flow_encap_entry_key_set(int unit,
   2374     bcm_flow_encap_config_t *info,
   2375     bcm_flow_logical_field_t *field,
   2376     int num_of_fields,
   2377     soc_mem_t mem_id,
   2378     uint32 *entry,
   2379     int network_port)
   2380 {
   2381     int i;
   2382     int j;
   2383     soc_field_t vfi_f = 0;
   2384     soc_field_t vrf_f = 0;
   2385     soc_field_t dvp_f = 0;
   2386     soc_field_t dvp_grp_f = 0;
   2387     soc_field_t oif_grp_f = 0;
   2388     int rv;
   2389     uint32 dvp = 0;
   2390     uint32 vfi = 0;
   2391     uint32 vrf = 0;
   2392 
   2393     /*
   2394      * BCM_FLOW_ENCAP_CRITERIA_VFI_DVP_GROUP
   2395      *   if network_port 
   2396      *      VFI_DVP_GROUP__DATA_TYPE = 0 tunnel data
   2397      *   else access DVP
   2398      *      VFI_DVP_GROUP__DATA_TYPE = 1 vlan_xlate
   2399      *
   2400      * BCM_FLOW_ENCAP_CRITERIA_VFI_DVP
   2401      *   if network_port 
   2402      *     regular match
   2403      *   else access DVP
   2404      *     VLAN_XLATE_VFI  key_type = 12
   2405      */
   2406 
   2407     /* validate parameters */
   2408 
   2409     if (info->valid_elements & BCM_FLOW_ENCAP_FLOW_PORT_VALID) {
   2410         if (!BCM_GPORT_IS_MODPORT(info->flow_port)) {
   2411             dvp = _SHR_GPORT_FLOW_PORT_ID_GET(info->flow_port);
   2412         }
   2413     }
   2414     if (info->valid_elements & BCM_FLOW_ENCAP_VPN_VALID) {
   2415        BCM_IF_ERROR_RETURN(
   2416              (bcmi_esw_flow_vpn_is_valid(unit, info->vpn)));
   2417         _BCM_FLOW_VPN_GET(vfi, _BCM_VPN_TYPE_VFI, info->vpn);
   2418     }
   2419 
   2420     if (info->criteria == BCM_FLOW_ENCAP_CRITERIA_DVP) {
   2421         if (!dvp) {
   2422              return BCM_E_PARAM;
   2423         }
   2424         /* only apply to flex view */
   2425         if (!_BCM_FLOW_IS_FLEX_VIEW(info)) {
   2426             return BCM_E_PARAM;
   2427         }
   2428         if (SOC_MEM_FIELD_VALID(unit,mem_id,DVPf)) {
   2429             soc_mem_field32_set(unit,mem_id, entry, DVPf, dvp);
   2430         } else {
   2431             LOG_VERBOSE(BSL_LS_BCM_FLOW, (BSL_META_U(unit,
   2432              "DVPf not in memory view definition\n")));
   2433             return BCM_E_PARAM;
   2434         }
   2435 
   2436     } else if (info->criteria == BCM_FLOW_ENCAP_CRITERIA_L3_INTF) {
   2437         
   2438         if (info->valid_elements & BCM_FLOW_ENCAP_INTF_VALID) {
   2439         
   2440             /* only apply to flex view */
   2441             if (!_BCM_FLOW_IS_FLEX_VIEW(info)) {
   2442                 return BCM_E_PARAM;
   2443             }
   2444             if (SOC_MEM_FIELD_VALID(unit,mem_id,L3_OIFf)) {
   2445                 soc_mem_field32_set(unit,mem_id, entry, L3_OIFf, info->intf_id);
   2446             } else {
   2447                 LOG_VERBOSE(BSL_LS_BCM_FLOW, (BSL_META_U(unit,
   2448                  "L3_OIFf not in memory view definition\n")));
   2449                 return BCM_E_PARAM;
   2450             }
   2451         }
   2452     } else if (info->criteria == BCM_FLOW_ENCAP_CRITERIA_VRF_MAPPING) {
   2453         /* KEY : VRF,VT_DVP_GROUP_ID,VT_L3_OIF_GROUP_ID
   2454          * VT_DVP_GROUP_ID    : from EGR_DVP_ATTRIBUTEm
   2455          * VT_L3_OIF_GROUP_ID : from EGR_L3_INTFm
   2456          */
   2457         _BCM_FLOW_VPN_GET(vrf, _BCM_VPN_TYPE_L3, info->vpn);
   2458         if (_BCM_FLOW_IS_FLEX_VIEW(info)) {
   2459             vrf_f = VRFf;
   2460             dvp_grp_f = VT_DVP_GROUP_IDf;
   2461             oif_grp_f = VT_L3OIF_GROUP_IDf;
   2462         } else {
   2463             vrf_f = VRF_MAPPING__VRFf;
   2464             dvp_grp_f = VRF_MAPPING__VT_DVP_GROUP_IDf;
   2465             oif_grp_f = VRF_MAPPING__VT_L3OIF_GROUP_IDf;
   2466         }
   2467         if (info->valid_elements & BCM_FLOW_ENCAP_VPN_VALID) {
   2468             if (!SOC_MEM_FIELD_VALID(unit, mem_id, vrf_f) ||
   2469                     (vrf > SOC_VRF_MAX(unit))) {
   2470                 return BCM_E_PARAM;
   2471             }
   2472             soc_mem_field32_set(unit,mem_id, entry, vrf_f, vrf);
   2473         }
   2474         if (info->valid_elements & BCM_FLOW_ENCAP_DVP_GROUP_VALID) {
   2475             if (!SOC_MEM_FIELD_VALID(unit, mem_id, dvp_grp_f)) {
   2476                 return BCM_E_PARAM;
   2477             }
   2478             soc_mem_field32_set(unit,mem_id, entry, dvp_grp_f, info->dvp_group);
   2479         }
   2480         if (info->valid_elements & BCM_FLOW_ENCAP_OIF_GROUP_VALID) {
   2481             if (!SOC_MEM_FIELD_VALID(unit, mem_id, oif_grp_f)) {
   2482                 return BCM_E_PARAM;
   2483             }
   2484             soc_mem_field32_set(unit,mem_id, entry, oif_grp_f, info->oif_group);
   2485         }
   2486     } else if (info->criteria == BCM_FLOW_ENCAP_CRITERIA_VFI_DVP_GROUP) {
   2487         if (_BCM_FLOW_IS_FLEX_VIEW(info)) {
   2488             vfi_f = VFIf;
   2489             dvp_grp_f = VT_DVP_GROUP_IDf;
   2490         } else {
   2491             vfi_f = VFI_DVP_GROUP__VFIf;
   2492             dvp_grp_f = VFI_DVP_GROUP__VT_DVP_GROUP_IDf;
   2493         }
   2494         if (info->valid_elements & BCM_FLOW_ENCAP_VPN_VALID) {
   2495             if (!SOC_MEM_FIELD_VALID(unit, mem_id, vfi_f)) {
   2496                 return BCM_E_PARAM;
   2497             }
   2498             soc_mem_field32_set(unit,mem_id, entry, vfi_f, vfi);
   2499         }
   2500         if (info->valid_elements & BCM_FLOW_ENCAP_DVP_GROUP_VALID) {
   2501             if (!SOC_MEM_FIELD_VALID(unit, mem_id, dvp_grp_f)) {
   2502                 return BCM_E_PARAM;
   2503             }
   2504             soc_mem_field32_set(unit,mem_id, entry, dvp_grp_f, info->dvp_group);
   2505         }
   2506         if (!_BCM_FLOW_IS_FLEX_VIEW(info)) {
   2507             if (!SOC_MEM_FIELD_VALID(unit, mem_id, 
   2508                                  VFI_DVP_GROUP__DATA_OVERLAY_TYPEf)) {
   2509                 return BCM_E_PARAM;
   2510             }
   2511             if (network_port) {
   2512                 soc_mem_field32_set(unit,mem_id, entry, 
   2513                                  VFI_DVP_GROUP__DATA_OVERLAY_TYPEf, 0);
   2514             } else { /* access DVP */                
   2515                 soc_mem_field32_set(unit,mem_id, entry, 
   2516                                  VFI_DVP_GROUP__DATA_OVERLAY_TYPEf, 1);
   2517             }
   2518         }    
   2519     } else if (info->criteria == BCM_FLOW_ENCAP_CRITERIA_VFI) {
   2520         if (_BCM_FLOW_IS_FLEX_VIEW(info)) {
   2521             vfi_f = VFIf;
   2522         } else {
   2523             if (info->flow_handle == SOC_FLOW_DB_FLOW_ID_LEGACY_VXLAN) {
   2524                 if (soc_feature(unit, soc_feature_vxlan_decoupled_mode)) {
   2525                     vfi_f = VXLAN_VFI_FLEX__VFIf;
   2526                 } else {
   2527                     vfi_f = VXLAN_VFI__VFIf;
   2528                 }
   2529             } else if (info->flow_handle == SOC_FLOW_DB_FLOW_ID_LEGACY_L2GRE) {
   2530                 vfi_f  = L2GRE_VFI__VFIf;
   2531             } else {
   2532                 return BCM_E_PARAM;
   2533             }
   2534         }
   2535         if (info->valid_elements & BCM_FLOW_ENCAP_VPN_VALID) {
   2536             if (!SOC_MEM_FIELD_VALID(unit, mem_id, vfi_f)) {
   2537                 return BCM_E_PARAM;
   2538             }
   2539             soc_mem_field32_set(unit,mem_id, entry, vfi_f, vfi);
   2540         }
   2541     }  else if (info->criteria == BCM_FLOW_ENCAP_CRITERIA_VFI_DVP) {
   2542 
   2543         if (_BCM_FLOW_IS_FLEX_VIEW(info)) {
   2544             vfi_f = VFIf;
   2545             dvp_f = DVPf;
   2546         } else {
   2547             if (info->flow_handle == SOC_FLOW_DB_FLOW_ID_LEGACY_VXLAN) {
   2548                 if (soc_feature(unit, soc_feature_vxlan_decoupled_mode)) {
   2549                     vfi_f = VXLAN_VFI_FLEX__VFIf;
   2550                     dvp_f = VXLAN_VFI_FLEX__DVPf;
   2551                 } else {
   2552                     vfi_f = VXLAN_VFI__VFIf;
   2553                     dvp_f = VXLAN_VFI__DVPf;
   2554                 }
   2555             } else if (info->flow_handle == SOC_FLOW_DB_FLOW_ID_LEGACY_L2GRE) {
   2556                 vfi_f = L2GRE_VFI__VFIf;
   2557                 dvp_f = L2GRE_VFI__DVPf;
   2558             } else {
   2559                 vfi_f = VLAN_XLATE_VFI__VFIf;
   2560                 dvp_f = VLAN_XLATE_VFI__DVPf;
   2561             }
   2562         }
   2563         if (info->valid_elements & BCM_FLOW_ENCAP_VPN_VALID) {
   2564             if (!SOC_MEM_FIELD_VALID(unit,mem_id,vfi_f)) {
   2565                 return BCM_E_PARAM;
   2566             }
   2567             soc_mem_field32_set(unit, mem_id, entry, vfi_f, vfi);
   2568         }
   2569         if (info->valid_elements & BCM_FLOW_ENCAP_FLOW_PORT_VALID) {
   2570             if (!dvp) {
   2571                 return BCM_E_PARAM;
   2572             }
   2573             if (!SOC_MEM_FIELD_VALID(unit,mem_id,dvp_f)) {
   2574                 return BCM_E_PARAM;
   2575             }
   2576             soc_mem_field32_set(unit, mem_id, entry, dvp_f, dvp);
   2577         }
   2578     } else if (info->criteria == BCM_FLOW_ENCAP_CRITERIA_FLEX) {
   2579         uint32 key_ids[_BCM_FLOW_LOGICAL_FIELD_MAX];
   2580         uint32 cnt;
   2581 
   2582         rv = soc_flow_db_mem_view_field_list_get(unit,
   2583                       mem_id,
   2584                       SOC_FLOW_DB_FIELD_TYPE_LOGICAL_KEY,
   2585                       _BCM_FLOW_LOGICAL_FIELD_MAX, key_ids, &cnt);
   2586         BCM_IF_ERROR_RETURN(rv);
   2587         for (i = 0; i < num_of_fields; i++) {
   2588             for (j = 0; j < cnt; j++) {
   2589                 if (field[i].id == key_ids[j]) {
   2590                     soc_mem_field32_set(unit,mem_id, entry,
   2591                           field[i].id, field[i].value);
   2592                     break;
   2593                 }
   2594             }
   2595         }
   2596         if (info->valid_elements & BCM_FLOW_ENCAP_FLOW_PORT_VALID) {
   2597             if (BCM_GPORT_IS_MODPORT(info->flow_port)) {
   2598                 if (!SOC_MEM_FIELD_VALID(unit, mem_id, DGPPf)) {
   2599                     return BCM_E_PARAM;
   2600                 }
   2601                 soc_mem_field32_set(unit,mem_id, entry, DGPPf, 
   2602                   (_SHR_GPORT_MODPORT_MODID_GET(info->flow_port) << 
   2603                    _BCM_FLOW_MODID_SHIFTER) |
   2604                   _SHR_GPORT_MODPORT_PORT_GET(info->flow_port));
   2605             } else { 
   2606                 if (!dvp) {
   2607                     return BCM_E_PARAM;
   2608                 }
   2609                 if (!SOC_MEM_FIELD_VALID(unit, mem_id, DVPf)) {
   2610                     return BCM_E_PARAM;
   2611                 }
   2612                 soc_mem_field32_set(unit,mem_id, entry, DVPf, dvp);
   2613             }
   2614         }
   2615         if (info->valid_elements & BCM_FLOW_ENCAP_VPN_VALID) {
   2616             if (!SOC_MEM_FIELD_VALID(unit, mem_id, VFIf)) {
   2617                 return BCM_E_PARAM;
   2618             }
   2619             soc_mem_field32_set(unit,mem_id, entry, VFIf, vfi);
   2620         }
   2621         if (info->valid_elements & BCM_FLOW_ENCAP_INTF_VALID) {
   2622             if (!SOC_MEM_FIELD_VALID(unit, mem_id, L3_OIFf)) {
   2623                 return BCM_E_PARAM;
   2624             }
   2625             soc_mem_field32_set(unit,mem_id, entry, L3_OIFf, info->intf_id);
   2626         }
   2627         if (info->valid_elements & BCM_FLOW_ENCAP_DVP_GROUP_VALID) {
   2628             if (!SOC_MEM_FIELD_VALID(unit, mem_id, VT_DVP_GROUP_IDf)) {
   2629                 return BCM_E_PARAM;
   2630             }
   2631             soc_mem_field32_set(unit,mem_id, entry, VT_DVP_GROUP_IDf, 
   2632                     info->dvp_group);
   2633         }
   2634         if (info->valid_elements & BCM_FLOW_ENCAP_OIF_GROUP_VALID) {
   2635             if (!SOC_MEM_FIELD_VALID(unit, mem_id, VT_L3OIF_GROUP_IDf)) {
   2636                 return BCM_E_PARAM;
   2637             }
   2638             soc_mem_field32_set(unit,mem_id, entry, VT_L3OIF_GROUP_IDf, 
   2639                     info->oif_group);
   2640         }
   2641         if (info->valid_elements & BCM_FLOW_ENCAP_SRC_FLOW_PORT_VALID) {
   2642             uint32 svp = 0;
   2643             if (BCM_GPORT_IS_FLOW_PORT(info->src_flow_port)) {
   2644                 svp = _SHR_GPORT_FLOW_PORT_ID_GET(info->src_flow_port);
   2645             } else {
   2646                 return BCM_E_PARAM;
   2647             }
   2648             if (!SOC_MEM_FIELD_VALID(unit, mem_id, SVPf)) {
   2649                 return BCM_E_PARAM;
   2650             }
   2651             soc_mem_field32_set(unit,mem_id, entry, SVPf, svp);
   2652         }
   2653         if (info->valid_elements & BCM_FLOW_ENCAP_CLASS_ID_VALID) {
   2654             if (SOC_MEM_FIELD_VALID(unit, mem_id, CLASS_IDf)) {
   2655                 soc_mem_field32_set(unit, mem_id, entry, CLASS_IDf, info->class_id);
   2656             } else if (SOC_MEM_FIELD_VALID(unit, mem_id, CLASS_ID_ACTION_SETf)) {
   2657                 soc_mem_field32_set(unit, mem_id, entry, CLASS_ID_ACTION_SETf, info->class_id);
   2658             } else {
   2659                 return BCM_E_PARAM;
   2660             }
   2661         }
   2662     } else if (info->criteria == BCM_FLOW_ENCAP_CRITERIA_SVP_DVP) {
   2663         if (soc_feature(unit, soc_feature_vxlan_evpn)) {
   2664             if (!dvp) {
   2665                 return BCM_E_PARAM;
   2666             }
   2667             if (!SOC_MEM_FIELD_VALID(unit, mem_id, DVPf)) {
   2668                 return BCM_E_PARAM;
   2669             }
   2670             soc_mem_field32_set(unit,mem_id, entry, DVPf, dvp);
   2671 
   2672             if (info->valid_elements & BCM_FLOW_ENCAP_SRC_FLOW_PORT_VALID) {
   2673                 uint32 svp = 0;
   2674 
   2675                 if (BCM_GPORT_IS_FLOW_PORT(info->src_flow_port)) {
   2676                     svp = _SHR_GPORT_FLOW_PORT_ID_GET(info->src_flow_port);
   2677                 } else {
   2678                     return BCM_E_PARAM;
   2679                 }
   2680 
   2681                 if (!SOC_MEM_FIELD_VALID(unit, mem_id, SVPf)) {
   2682                     return BCM_E_PARAM;
   2683                 }
   2684                 soc_mem_field32_set(unit,mem_id, entry, SVPf, svp);
   2685             }
   2686         } else {
   2687             return BCM_E_UNAVAIL;
   2688         }
   2689     }
   2690     return BCM_E_NONE;
   2691 }
   2692 
   2693 
   2694 /*
   2695  * Function:
   2696  *      _bcm_flow_encap_key_set
   2697  * Purpose:
   2698  *      Set the key for a flow encap entry
   2699  * Parameters:
   2700  *      unit - (IN) Device Number
   2701  *      info - (IN) flow_match configuration info
   2702  *      field - (IN) array of logical fields
   2703  *      num_of_fields -(IN) the size of the above array
   2704  *      entry - (IN) point to the match entry
   2705  *      mem - (OUT) memory id
   2706  *      mem_view - (OUT) memory view id
   2707  * Returns:
   2708  *      BCM_E_XXX
   2709  */
   2710 
   2711 STATIC
   2712 int _bcm_flow_encap_key_set(
   2713     int unit,
   2714     bcm_flow_encap_config_t *info,
   2715     bcm_flow_logical_field_t *field,
   2716     uint32 num_of_fields,
   2717     uint32 *entry,
   2718     soc_mem_t *mem,
   2719     soc_mem_t *mem_view,
   2720     int *network_port)
   2721 {
   2722     int rv;
   2723     soc_mem_t mem_view_id = 0;
   2724     uint32 key_type = 0;
   2725     soc_mem_t mem_id = 0;
   2726     soc_flow_db_mem_view_info_t vinfo;
   2727 
   2728     *network_port = FALSE;
   2729     /* validate parameters */
   2730 
   2731     /* flow port based encap */
   2732     if (info->criteria == BCM_FLOW_ENCAP_CRITERIA_DVP ||
   2733         info->criteria == BCM_FLOW_ENCAP_CRITERIA_L3_INTF) {
   2734         /* no fixed view supported */
   2735         if (!_BCM_FLOW_IS_FLEX_VIEW(info)) {
   2736             LOG_ERROR(BSL_LS_BCM_FLOW, (BSL_META_U(unit, 
   2737                   "encap criteria not supported in legacy flow\n")));
   2738             return BCM_E_PARAM;
   2739         }
   2740     } else if (info->criteria == BCM_FLOW_ENCAP_CRITERIA_VRF_MAPPING) {
   2741         mem_id = EGR_VLAN_XLATE_1_DOUBLEm;
   2742         key_type = _BCM_FLOW_ENCAP_KEY_TYPE_VRF_MAPPING;
   2743         *network_port = TRUE;
   2744     } else if (info->criteria == BCM_FLOW_ENCAP_CRITERIA_VFI) {
   2745         mem_id = EGR_VLAN_XLATE_1_DOUBLEm;  /* fixed view */
   2746         if (info->flow_handle == SOC_FLOW_DB_FLOW_ID_LEGACY_VXLAN) {
   2747             if (soc_feature(unit, soc_feature_vxlan_decoupled_mode)) {
   2748                 mem_id = EGR_VLAN_XLATE_1_SINGLEm;
   2749             }
   2750             key_type = _BCM_FLOW_ENCAP_VXLAN_KEY_TYPE_VFI;
   2751             *network_port = TRUE;
   2752         } else if (info->flow_handle == SOC_FLOW_DB_FLOW_ID_LEGACY_L2GRE) {
   2753             key_type = _BCM_FLOW_ENCAP_L2GRE_KEY_TYPE_VFI;
   2754             *network_port = TRUE;
   2755         }
   2756     } else if (info->criteria == BCM_FLOW_ENCAP_CRITERIA_VFI_DVP) {
   2757         mem_id = EGR_VLAN_XLATE_1_DOUBLEm;  /* fixed view */
   2758         if (info->flow_handle == SOC_FLOW_DB_FLOW_ID_LEGACY_VXLAN) {
   2759             key_type = _BCM_FLOW_ENCAP_VXLAN_KEY_TYPE_VFI_DVP;
   2760             *network_port = TRUE;
   2761             if (soc_feature(unit, soc_feature_vxlan_decoupled_mode)) {
   2762                 mem_id = EGR_VLAN_XLATE_1_SINGLEm;
   2763             }
   2764         } else if (info->flow_handle == SOC_FLOW_DB_FLOW_ID_LEGACY_L2GRE) {
   2765             key_type = _BCM_FLOW_ENCAP_L2GRE_KEY_TYPE_VFI_DVP;
   2766             *network_port = TRUE;
   2767         } else if (!(info->flow_handle)) {  /* access DVP */
   2768             key_type = _BCM_FLOW_ENCAP_KEY_TYPE_VLAN_XLATE_VFI;
   2769         }
   2770     } else if (info->criteria == BCM_FLOW_ENCAP_CRITERIA_VFI_DVP_GROUP) {
   2771         key_type = _BCM_FLOW_ENCAP_KEY_TYPE_VFI_DVP_GROUP;
   2772         if (info->flow_handle == SOC_FLOW_DB_FLOW_ID_LEGACY_VXLAN || 
   2773             info->flow_handle == SOC_FLOW_DB_FLOW_ID_LEGACY_L2GRE) {
   2774             *network_port = TRUE;
   2775         } else if (!(info->flow_handle)) {  /* access DVP */
   2776             key_type = _BCM_FLOW_ENCAP_KEY_TYPE_VLAN_XLATE_VFI;
   2777         }
   2778 
   2779         mem_id = EGR_VLAN_XLATE_1_DOUBLEm;  /* fixed view */
   2780     } 
   2781     *mem = mem_id;
   2782 
   2783     if (!_BCM_FLOW_IS_FLEX_VIEW(info)) {
   2784         if (!(*mem)) {
   2785             return BCM_E_PARAM;
   2786         }
   2787         rv = _bcm_flow_encap_fixed_view_entry_init(unit, mem_id,
   2788                         key_type, entry);
   2789         BCM_IF_ERROR_RETURN(rv);
   2790     } else {
   2791         /* get the physical memory view */
   2792         rv = soc_flow_db_ffo_to_mem_view_id_get(unit,info->flow_handle,
   2793              info->flow_option,
   2794              SOC_FLOW_DB_FUNC_ENCAP_ID, (uint32 *)&mem_view_id);
   2795         BCM_IF_ERROR_RETURN(rv);
   2796         rv = soc_flow_db_mem_view_info_get(unit, mem_view_id, &vinfo);
   2797         BCM_IF_ERROR_RETURN(rv);
   2798         if (mem_view != NULL) {
   2799             *mem_view = mem_view_id;
   2800         }
   2801         *mem = vinfo.mem;
   2802 
   2803         /* flex view, initialize all control fields such as data_type */
   2804         soc_flow_db_mem_view_entry_init(unit,mem_view_id,entry);
   2805         mem_id = mem_view_id;
   2806         *network_port = TRUE;
   2807     }
   2808 
   2809     rv = _bcm_flow_encap_entry_key_set(unit,info,field,num_of_fields,
   2810                         mem_id, entry,*network_port);
   2811     return rv;
   2812 }
   2813 
   2814 STATIC int
   2815 _bcm_flow_encap_vlan_set(int unit, bcm_flow_encap_config_t *info,
   2816                          soc_mem_t mem,
   2817                          uint32 *entry,
   2818                          uint32 *otag,
   2819                          uint32 *xlate_data)
   2820 {
   2821     int xlate_format;
   2822     bcm_vlan_action_set_t action;
   2823     uint32 profile_idx;
   2824     xlate_format = EGR_VLAN_XLATE_XLATE_DATA_DOUBLEfmt;
   2825 
   2826     /* access facing port. Derive vlan tag from VFI/DVP. If VFI is valid
   2827      * in EGR_L3_INTF, then the packet is treated as un-tagged
   2828      */ 
   2829     if (info->criteria == BCM_FLOW_ENCAP_CRITERIA_VFI_DVP_GROUP ||
   2830         info->criteria == BCM_FLOW_ENCAP_CRITERIA_VFI_DVP) {
   2831         if (info->valid_elements & BCM_FLOW_ENCAP_VLAN_VALID) {
   2832             if (_BCM_FLOW_IS_FLEX_VIEW(info)) {
   2833                 soc_format_field32_set(unit,OTAG_ACTION_SETfmt,&otag,
   2834                                 VIDf,info->vlan);
   2835             } else {
   2836                 if (soc_mem_field_valid(unit, mem, VXLAN_VFI_FLEX__OVIDf)) {
   2837                     soc_mem_field32_set(unit, mem, entry, VXLAN_VFI_FLEX__OVIDf, info->vlan);
   2838                 } else {
   2839                     soc_format_field32_set(unit,xlate_format,
   2840                             xlate_data, NEW_OVIDf,info->vlan);
   2841                 }
   2842             }
   2843         }
   2844         if (info->valid_elements & BCM_FLOW_ENCAP_PKT_PRI_VALID) {
   2845             if (_BCM_FLOW_IS_FLEX_VIEW(info)) {
   2846                 soc_format_field32_set(unit,OTAG_ACTION_SETfmt,&otag,
   2847                                 PCPf,info->pri);
   2848             } else {
   2849                 if (soc_mem_field_valid(unit, mem, VXLAN_VFI_FLEX__OPRIf)) {
   2850                     soc_mem_field32_set(unit, mem, entry, VXLAN_VFI_FLEX__OPRIf, info->pri);
   2851                 } else {
   2852                     soc_format_field32_set(unit,xlate_format,
   2853                         xlate_data, NEW_OPRIf,info->pri);
   2854                 }
   2855             }
   2856         }
   2857         if (info->valid_elements & BCM_FLOW_ENCAP_PKT_CFI_VALID) {
   2858             if (_BCM_FLOW_IS_FLEX_VIEW(info)) {
   2859                 soc_format_field32_set(unit,OTAG_ACTION_SETfmt,&otag,
   2860                                 DEf,info->cfi);
   2861             } else {
   2862                 if (soc_mem_field_valid(unit, mem, VXLAN_VFI_FLEX__OCFIf)) {
   2863                     soc_mem_field32_set(unit, mem, entry, VXLAN_VFI_FLEX__OCFIf,info->cfi);
   2864                 } else {
   2865                 soc_format_field32_set(unit,xlate_format,
   2866                         xlate_data, NEW_OCFIf,info->cfi);
   2867                 }
   2868             }
   2869         }
   2870         if (info->valid_elements & (BCM_FLOW_ENCAP_VLAN_VALID |
   2871                                     BCM_FLOW_ENCAP_PKT_PRI_VALID |
   2872                                     BCM_FLOW_ENCAP_PKT_CFI_VALID) ) {
   2873 
   2874             /* action profile */
   2875             bcm_vlan_action_set_t_init(&action);
   2876             action.ut_outer          = bcmVlanActionAdd;
   2877             action.ut_outer_pkt_prio = bcmVlanActionAdd;
   2878             action.ut_outer_cfi      = bcmVlanActionAdd;
   2879             
   2880             BCM_IF_ERROR_RETURN(_bcm_trx_egr_vlan_action_profile_entry_add(
   2881                      unit, &action, &profile_idx));
   2882             if (_BCM_FLOW_IS_FLEX_VIEW(info)) {
   2883                 soc_mem_field32_set(unit,mem, entry,
   2884                             TAG_ACTION_PROFILE_ACTION_SETf,profile_idx);
   2885             } else {
   2886                 if (soc_mem_field_valid(unit, mem, VXLAN_VFI_FLEX__TAG_ACTION_PROFILE_PTRf)) {
   2887                     soc_mem_field32_set(unit, mem, entry,
   2888                         VXLAN_VFI_FLEX__TAG_ACTION_PROFILE_PTRf, profile_idx);
   2889                 } else {
   2890                     soc_format_field32_set(unit,xlate_format,
   2891                             xlate_data, TAG_ACTION_PROFILE_PTRf,profile_idx);
   2892                 }
   2893             }
   2894         }
   2895     }
   2896     return BCM_E_NONE;
   2897 }
   2898 
   2899 STATIC int
   2900 _bcm_flow_encap_vlan_get(int unit, bcm_flow_encap_config_t *info,
   2901                          soc_mem_t hw_mem,
   2902                          uint32 *entry,
   2903                          uint32 *otag,
   2904                          uint32 *xlate_data)
   2905 {
   2906     int xlate_format;
   2907     xlate_format = EGR_VLAN_XLATE_XLATE_DATA_DOUBLEfmt;
   2908 
   2909     /* access facing port. Derive vlan tag from VFI/DVP. If VFI is valid
   2910      * in EGR_L3_INTF, then the packet is treated as un-tagged
   2911      */ 
   2912     if (info->criteria == BCM_FLOW_ENCAP_CRITERIA_VFI_DVP_GROUP ||
   2913         info->criteria == BCM_FLOW_ENCAP_CRITERIA_VFI_DVP) {
   2914         if (_BCM_FLOW_IS_FLEX_VIEW(info)) {
   2915             info->vlan = soc_format_field32_get(unit,OTAG_ACTION_SETfmt,&otag,
   2916                                                 VIDf);
   2917             info->pri = soc_format_field32_get(unit,OTAG_ACTION_SETfmt,&otag,
   2918                                                PCPf);
   2919             info->cfi = soc_format_field32_get(unit,OTAG_ACTION_SETfmt,&otag,
   2920                                                DEf);
   2921         } else {
   2922             if (soc_mem_field_valid(unit, hw_mem, OVIDf)) {
   2923                 info->vlan = soc_mem_field32_get(unit,hw_mem, entry, OVIDf);
   2924             } else {
   2925                 info->vlan = soc_format_field32_get(unit,xlate_format,
   2926                                          xlate_data, NEW_OVIDf);
   2927             }
   2928             if (soc_mem_field_valid(unit, hw_mem, OPRIf)) {
   2929                 info->pri = soc_mem_field32_get(unit,hw_mem, entry, OPRIf);
   2930             } else {
   2931                 info->pri = soc_format_field32_get(unit,xlate_format,
   2932                                          xlate_data, NEW_OPRIf);
   2933             }
   2934             if (soc_mem_field_valid(unit, hw_mem, OCFIf)) {
   2935                 info->cfi = soc_mem_field32_get(unit,hw_mem, entry, OCFIf);
   2936             } else {
   2937                 info->cfi = soc_format_field32_get(unit,xlate_format,
   2938                                          xlate_data, NEW_OCFIf);
   2939             }
   2940         }
   2941     }
   2942     return BCM_E_NONE;
   2943 }
   2944 
   2945 STATIC int
   2946 _bcm_flow_sd_tag_set(int unit, bcm_flow_encap_config_t *info,
   2947                          uint32 *sd_tag,
   2948                          int *tpid_index)
   2949 {
   2950     int action_present;
   2951     int action_not_present;
   2952     int sd_tag_remark_cfi_set = 0;
   2953     int tag_format;
   2954     int old_tpid_inx;
   2955 
   2956     if (_BCM_FLOW_IS_FLEX_VIEW(info) ||
   2957         (info->criteria == BCM_FLOW_ENCAP_CRITERIA_VFI_DVP_GROUP)) {
   2958         tag_format = SD_TAG_ACTION_SETfmt;
   2959     } else {
   2960         tag_format = SD_TAG_DATA_FORMAT_DOUBLEfmt;
   2961     }
   2962 
   2963     action_present = 0;
   2964     action_not_present = 0;
   2965 
   2966     /* only these two fixed views use specific field names
   2967      * Others use sd_tag format 
   2968      */
   2969     if (info->valid_elements & BCM_FLOW_ENCAP_VLAN_VALID) {
   2970         if (info->vlan >= BCM_VLAN_INVALID) {
   2971             return  BCM_E_PARAM;
   2972         }
   2973         soc_format_field32_set(unit,tag_format,sd_tag,
   2974                             SD_TAG_VIDf,info->vlan);
   2975     }
   2976     if (info->valid_elements & BCM_FLOW_ENCAP_PKT_PRI_VALID) {
   2977         if (info->pri > BCM_PRIO_MAX) {
   2978             return  BCM_E_PARAM;
   2979         }
   2980         soc_format_field32_set(unit,tag_format,sd_tag,
   2981                             SD_TAG_NEW_PRIf,info->pri);
   2982     }
   2983     if (info->valid_elements & BCM_FLOW_ENCAP_PKT_CFI_VALID) {
   2984         if (info->cfi > 1) {
   2985            return  BCM_E_PARAM;
   2986         }
   2987         soc_format_field32_set(unit,tag_format,sd_tag,
   2988                             SD_TAG_NEW_CFIf,info->cfi);
   2989     }
   2990 
   2991     if (info->flags & BCM_FLOW_ENCAP_FLAG_SERVICE_VLAN_ADD) {
   2992         sd_tag_remark_cfi_set = TRUE;
   2993         action_not_present = 0x1;  /* ADD */ 
   2994     }
   2995 
   2996     if (info->flags & BCM_FLOW_ENCAP_FLAG_SERVICE_VLAN_TPID_REPLACE) {
   2997         action_present = 0x1; /* REPLACE_VID_TPID */
   2998 
   2999     } else if (info->flags & BCM_FLOW_ENCAP_FLAG_VLAN_REPLACE) {
   3000         action_present = 0x2;  /* REPLACE_VID_ONLY */ 
   3001 
   3002     } else if (info->flags & BCM_FLOW_ENCAP_FLAG_VLAN_DELETE) {
   3003         action_present = 0x3;  /* DELETE */ 
   3004 
   3005     } else if (info->flags & BCM_FLOW_ENCAP_FLAG_VLAN_PRI_TPID_REPLACE) {
   3006         sd_tag_remark_cfi_set = TRUE;
   3007         action_present = 0x4;  /* REPLACE_VID_PRI_TPID */ 
   3008 
   3009     } else if (info->flags & BCM_FLOW_ENCAP_FLAG_VLAN_PRI_REPLACE){
   3010         sd_tag_remark_cfi_set = TRUE;
   3011         action_present = 0x5;  /* REPLACE_VID_PRI */ 
   3012 
   3013     } else if (info->flags & BCM_FLOW_ENCAP_FLAG_PRI_REPLACE ) {
   3014         sd_tag_remark_cfi_set = TRUE;
   3015         action_present = 0x6;  /*  REPLACE_PRI_ONLY */ 
   3016 
   3017     } else if (info->flags & BCM_FLOW_ENCAP_FLAG_TPID_REPLACE) {
   3018         action_present = 0x7;  /* REPLACE_TPID_ONLY */ 
   3019     }
   3020     if (sd_tag_remark_cfi_set) {
   3021         soc_format_field32_set(unit,tag_format,sd_tag,
   3022                             SD_TAG_REMARK_CFIf,info->cfi);
   3023     }
   3024     if (action_not_present) {
   3025         soc_format_field32_set(unit,tag_format,sd_tag,
   3026                             SD_TAG_ACTION_IF_NOT_PRESENTf,action_not_present);
   3027     }
   3028     if (action_present) {
   3029         soc_format_field32_set(unit,tag_format,sd_tag,
   3030                             SD_TAG_ACTION_IF_PRESENTf,action_present);
   3031     }
   3032 
   3033     if ((info->flags & BCM_FLOW_ENCAP_FLAG_SERVICE_VLAN_ADD) ||
   3034         (info->flags & BCM_FLOW_ENCAP_FLAG_SERVICE_VLAN_TPID_REPLACE) ||
   3035         (info->flags & BCM_FLOW_ENCAP_FLAG_TPID_REPLACE) ||
   3036         (info->flags & BCM_FLOW_ENCAP_FLAG_VLAN_PRI_TPID_REPLACE)) {
   3037         if (info->options & BCM_FLOW_ENCAP_OPTION_REPLACE) {
   3038             old_tpid_inx = soc_format_field32_get(unit,tag_format,sd_tag,
   3039                                 SD_TAG_TPID_INDEXf);
   3040             BCM_IF_ERROR_RETURN(_bcm_fb2_outer_tpid_entry_delete(unit, 
   3041                                 old_tpid_inx));
   3042         }
   3043     
   3044         /* TPID value is used */
   3045         BCM_IF_ERROR_RETURN(_bcm_fb2_outer_tpid_entry_add(unit, info->tpid, 
   3046                              tpid_index));
   3047         soc_format_field32_set(unit,tag_format,sd_tag,
   3048                             SD_TAG_TPID_INDEXf,*tpid_index);
   3049     }
   3050     return  BCM_E_NONE;
   3051 }
   3052 
   3053 STATIC int
   3054 _bcm_flow_sd_tag_get(int unit, bcm_flow_encap_config_t *info, uint32 sd_tag,
   3055                      int  *tpid_idx)
   3056 {
   3057     int action_present;
   3058     int action_not_present;
   3059     int tag_format;
   3060     int tpid_index;
   3061     int rv;
   3062  
   3063     if (_BCM_FLOW_IS_FLEX_VIEW(info) ||
   3064         (info->criteria == BCM_FLOW_ENCAP_CRITERIA_VFI_DVP_GROUP)) {
   3065         tag_format = SD_TAG_ACTION_SETfmt;
   3066     } else {
   3067         tag_format = SD_TAG_DATA_FORMAT_DOUBLEfmt;
   3068     }
   3069     action_present = 0;
   3070     action_not_present = 0;
   3071 
   3072     info->vlan = soc_format_field32_get(unit,tag_format,&sd_tag,
   3073                             SD_TAG_VIDf);
   3074 
   3075     info->pri = soc_format_field32_get(unit,tag_format,&sd_tag,
   3076                             SD_TAG_NEW_PRIf);
   3077     info->cfi = soc_format_field32_get(unit,tag_format,&sd_tag,
   3078                             SD_TAG_NEW_CFIf);
   3079     action_not_present = soc_format_field32_get(unit,tag_format,&sd_tag,
   3080                                    SD_TAG_ACTION_IF_NOT_PRESENTf);
   3081     action_present = soc_format_field32_get(unit,tag_format,&sd_tag,
   3082                                    SD_TAG_ACTION_IF_PRESENTf);
   3083     
   3084     if (action_not_present || action_present) {
   3085         info->flags |= BCM_FLOW_ENCAP_FLAG_SERVICE_TAGGED;
   3086     }
   3087     if (action_not_present) {
   3088         info->flags |= BCM_FLOW_ENCAP_FLAG_SERVICE_VLAN_ADD;
   3089     }
   3090 
   3091     if (action_present == 0x1) {  
   3092         info->flags |= BCM_FLOW_ENCAP_FLAG_SERVICE_VLAN_TPID_REPLACE;
   3093 
   3094     } else if (action_present == 0x2) {
   3095         info->flags  |= BCM_FLOW_ENCAP_FLAG_VLAN_REPLACE;
   3096 
   3097     } else if (action_present == 0x3) {
   3098         info->flags |= BCM_FLOW_ENCAP_FLAG_VLAN_DELETE;
   3099 
   3100     } else if (action_present == 4) {
   3101         info->flags |= BCM_FLOW_ENCAP_FLAG_VLAN_PRI_TPID_REPLACE;
   3102 
   3103     } else if (action_present == 0x5) {
   3104         info->flags |= BCM_FLOW_ENCAP_FLAG_VLAN_PRI_REPLACE;
   3105 
   3106     } else if (action_present == 0x6) {
   3107         info->flags |= BCM_FLOW_ENCAP_FLAG_PRI_REPLACE;
   3108 
   3109     } else if (action_present == 0x7) {
   3110         info->flags |= BCM_FLOW_ENCAP_FLAG_TPID_REPLACE;
   3111     }
   3112 
   3113     if ((info->flags & BCM_FLOW_ENCAP_FLAG_SERVICE_VLAN_ADD) ||
   3114         (info->flags & BCM_FLOW_ENCAP_FLAG_SERVICE_VLAN_TPID_REPLACE) ||
   3115         (info->flags & BCM_FLOW_ENCAP_FLAG_TPID_REPLACE) ||
   3116         (info->flags & BCM_FLOW_ENCAP_FLAG_VLAN_PRI_TPID_REPLACE)) {
   3117 
   3118         tpid_index = soc_format_field32_get(unit,tag_format,&sd_tag,
   3119                             SD_TAG_TPID_INDEXf);
   3120         rv = _bcm_fb2_outer_tpid_entry_get(unit,&info->tpid,tpid_index);
   3121         if (BCM_FAILURE(rv)) {
   3122             info->flags |= _BCM_FLOW_ENCAP_FLAG_TPID_INDEX;
   3123             info->tpid = tpid_index;
   3124         }
   3125         if (tpid_idx != NULL) {
   3126             *tpid_idx = tpid_index;
   3127         }
   3128     }
   3129     return  BCM_E_NONE;
   3130 }
   3131 
   3132 STATIC int
   3133 _bcm_flow_sd_tag_set_to_entry(
   3134         int unit,
   3135         bcm_flow_encap_config_t *info,
   3136         soc_mem_t mem,
   3137         uint32 *entry,
   3138         int *tpid_index)
   3139 {
   3140     int action_present = 0;
   3141     int action_not_present = 0;
   3142     int sd_tag_remark_cfi_set = 0;
   3143     int old_tpid_inx = 0;
   3144     uint32 profile_index = 0;
   3145     soc_field_t vlan_f = INVALIDf;
   3146     soc_field_t pri_f = INVALIDf;
   3147     soc_field_t cfi_f = INVALIDf;
   3148     soc_field_t pri_cfi_sel_f = INVALIDf;
   3149     soc_field_t tag_act_f = INVALIDf;
   3150     soc_field_t tpid_f = INVALIDf;
   3151 
   3152     if (_BCM_FLOW_IS_FLEX_VIEW(info)) {
   3153         LOG_ERROR(BSL_LS_BCM_FLOW, (BSL_META_U(unit,
   3154            "Fixed view only\n")));
   3155         return BCM_E_PARAM;
   3156     }
   3157 
   3158     if (mem == EGR_VLAN_XLATE_1_SINGLEm) {
   3159         /* View VXLAN_VFI_FLEX */
   3160         vlan_f = VXLAN_VFI_FLEX__OVIDf;
   3161         pri_f = VXLAN_VFI_FLEX__OPRIf;
   3162         cfi_f = VXLAN_VFI_FLEX__OCFIf;
   3163         pri_cfi_sel_f = VXLAN_VFI_FLEX__OPRI_OCFI_SELf;
   3164         tag_act_f = VXLAN_VFI_FLEX__TAG_ACTION_PROFILE_PTRf;
   3165         tpid_f = VXLAN_VFI_FLEX__OUTER_TPID_INDEXf;
   3166     } else if (mem == EGR_L3_NEXT_HOPm) {
   3167         /* View L2_OTAG */
   3168         vlan_f = L2_OTAG__VIDf;
   3169         pri_f = L2_OTAG__PCPf;
   3170         cfi_f = L2_OTAG__DEf;
   3171         pri_cfi_sel_f = L2_OTAG__PCP_DE_SELf;
   3172         tag_act_f = L2_OTAG__TAG_ACTION_PROFILE_PTRf;
   3173         tpid_f = L2_OTAG__TPID_INDEXf;
   3174     } else {
   3175         LOG_ERROR(BSL_LS_BCM_FLOW, (BSL_META_U(unit,
   3176            "Unsupported mem or view: %s\n"), SOC_MEM_UFNAME(unit, mem)));
   3177         return BCM_E_PARAM;
   3178     }
   3179 
   3180     if (info->valid_elements & BCM_FLOW_ENCAP_VLAN_VALID) {
   3181         if (info->vlan >= BCM_VLAN_INVALID) {
   3182             return  BCM_E_PARAM;
   3183         }
   3184         soc_mem_field32_set(unit, mem, entry, vlan_f, info->vlan);
   3185     }
   3186     if (info->valid_elements & BCM_FLOW_ENCAP_PKT_PRI_VALID) {
   3187         if (info->pri > BCM_PRIO_MAX) {
   3188             return  BCM_E_PARAM;
   3189         }
   3190         soc_mem_field32_set(unit, mem, entry, pri_f, info->pri);
   3191     }
   3192     if (info->valid_elements & BCM_FLOW_ENCAP_PKT_CFI_VALID) {
   3193         if (info->cfi > 1) {
   3194            return  BCM_E_PARAM;
   3195         }
   3196         soc_mem_field32_set(unit, mem, entry, cfi_f, info->cfi);
   3197     }
   3198 
   3199     if (info->flags & BCM_FLOW_ENCAP_FLAG_SERVICE_VLAN_ADD) {
   3200         sd_tag_remark_cfi_set = TRUE;
   3201         action_not_present = 0x1;  /* ADD */
   3202     }
   3203 
   3204     if (info->flags & BCM_FLOW_ENCAP_FLAG_SERVICE_VLAN_TPID_REPLACE) {
   3205         action_present = 0x1; /* REPLACE_VID_TPID */
   3206 
   3207     } else if (info->flags & BCM_FLOW_ENCAP_FLAG_VLAN_REPLACE) {
   3208         action_present = 0x2;  /* REPLACE_VID_ONLY */
   3209 
   3210     } else if (info->flags & BCM_FLOW_ENCAP_FLAG_VLAN_DELETE) {
   3211         action_present = 0x3;  /* DELETE */
   3212 
   3213     } else if (info->flags & BCM_FLOW_ENCAP_FLAG_VLAN_PRI_TPID_REPLACE) {
   3214         sd_tag_remark_cfi_set = TRUE;
   3215         action_present = 0x4;  /* REPLACE_VID_PRI_TPID */
   3216 
   3217     } else if (info->flags & BCM_FLOW_ENCAP_FLAG_VLAN_PRI_REPLACE){
   3218         sd_tag_remark_cfi_set = TRUE;
   3219         action_present = 0x5;  /* REPLACE_VID_PRI */
   3220 
   3221     } else if (info->flags & BCM_FLOW_ENCAP_FLAG_PRI_REPLACE ) {
   3222         sd_tag_remark_cfi_set = TRUE;
   3223         action_present = 0x6;  /*  REPLACE_PRI_ONLY */
   3224 
   3225     } else if (info->flags & BCM_FLOW_ENCAP_FLAG_TPID_REPLACE) {
   3226         action_present = 0x7;  /* REPLACE_TPID_ONLY */
   3227     }
   3228 
   3229     soc_mem_field32_set(unit, mem, entry, pri_cfi_sel_f, sd_tag_remark_cfi_set);
   3230     profile_index = soc_mem_field32_get(unit, mem, entry, tag_act_f);
   3231     _bcm_td3_sd_tag_action_profile_get(unit, action_present,
   3232             action_not_present, &profile_index);
   3233     soc_mem_field32_set(unit, mem, entry, tag_act_f, profile_index);
   3234 
   3235     if ((info->flags & BCM_FLOW_ENCAP_FLAG_SERVICE_VLAN_ADD) ||
   3236         (info->flags & BCM_FLOW_ENCAP_FLAG_SERVICE_VLAN_TPID_REPLACE) ||
   3237         (info->flags & BCM_FLOW_ENCAP_FLAG_TPID_REPLACE) ||
   3238         (info->flags & BCM_FLOW_ENCAP_FLAG_VLAN_PRI_TPID_REPLACE)) {
   3239         if (info->options & BCM_FLOW_ENCAP_OPTION_REPLACE) {
   3240             old_tpid_inx = soc_mem_field32_get(unit, mem, entry, tpid_f);
   3241             BCM_IF_ERROR_RETURN(_bcm_fb2_outer_tpid_entry_delete(unit,
   3242                                 old_tpid_inx));
   3243         }
   3244 
   3245         /* TPID value is used */
   3246         BCM_IF_ERROR_RETURN(_bcm_fb2_outer_tpid_entry_add(unit, info->tpid,
   3247                              tpid_index));
   3248         soc_mem_field32_set(unit, mem, entry, tpid_f, *tpid_index);
   3249     }
   3250     return  BCM_E_NONE;
   3251 }
   3252 
   3253 
   3254 STATIC int
   3255 _bcm_flow_sd_tag_get_from_entry(
   3256         int unit,
   3257         bcm_flow_encap_config_t *info,
   3258         soc_mem_t mem,
   3259         uint32 *entry,
   3260         int  *tpid_idx)
   3261 {
   3262     int action_present = 0;
   3263     int action_not_present = 0;
   3264     int tpid_index = 0;
   3265     uint32 profile_index = 0;
   3266     int rv = BCM_E_NONE;
   3267     soc_field_t vlan_f = INVALIDf;
   3268     soc_field_t pri_f = INVALIDf;
   3269     soc_field_t cfi_f = INVALIDf;
   3270     soc_field_t tag_act_f = INVALIDf;
   3271     soc_field_t tpid_f = INVALIDf;
   3272 
   3273     if (_BCM_FLOW_IS_FLEX_VIEW(info)) {
   3274         LOG_ERROR(BSL_LS_BCM_FLOW, (BSL_META_U(unit,
   3275            "Fixed view only\n")));
   3276         return BCM_E_PARAM;
   3277     }
   3278 
   3279     if (mem == EGR_VLAN_XLATE_1_SINGLEm) {
   3280         /* View VXLAN_VFI_FLEX */
   3281         vlan_f = VXLAN_VFI_FLEX__OVIDf;
   3282         pri_f = VXLAN_VFI_FLEX__OPRIf;
   3283         cfi_f = VXLAN_VFI_FLEX__OCFIf;
   3284         tag_act_f = VXLAN_VFI_FLEX__TAG_ACTION_PROFILE_PTRf;
   3285         tpid_f = VXLAN_VFI_FLEX__OUTER_TPID_INDEXf;
   3286     } else if (mem == EGR_L3_NEXT_HOPm) {
   3287         /* View L2_OTAG */
   3288         vlan_f = L2_OTAG__VIDf;
   3289         pri_f = L2_OTAG__PCPf;
   3290         cfi_f = L2_OTAG__DEf;
   3291         tag_act_f = L2_OTAG__TAG_ACTION_PROFILE_PTRf;
   3292         tpid_f = L2_OTAG__TPID_INDEXf;
   3293     } else {
   3294         LOG_ERROR(BSL_LS_BCM_FLOW, (BSL_META_U(unit,
   3295            "Unsupported mem or view: %s\n"), SOC_MEM_UFNAME(unit, mem)));
   3296         return BCM_E_PARAM;
   3297     }
   3298 
   3299     info->vlan = soc_mem_field32_get(unit, mem, entry, vlan_f);
   3300     info->pri = soc_mem_field32_get(unit, mem, entry, pri_f);
   3301     info->cfi = soc_mem_field32_get(unit, mem, entry, cfi_f);
   3302 
   3303     profile_index = soc_mem_field32_get(unit, mem, entry, tag_act_f);
   3304     (void)_bcm_td3_sd_tag_action_get(unit, profile_index, &action_present,
   3305                     &action_not_present);
   3306 
   3307     if (action_not_present || action_present) {
   3308         info->flags |= BCM_FLOW_ENCAP_FLAG_SERVICE_TAGGED;
   3309     }
   3310     if (action_not_present) {
   3311         info->flags |= BCM_FLOW_ENCAP_FLAG_SERVICE_VLAN_ADD;
   3312     }
   3313 
   3314     if (action_present == 0x1) {
   3315         info->flags |= BCM_FLOW_ENCAP_FLAG_SERVICE_VLAN_TPID_REPLACE;
   3316 
   3317     } else if (action_present == 0x2) {
   3318         info->flags  |= BCM_FLOW_ENCAP_FLAG_VLAN_REPLACE;
   3319 
   3320     } else if (action_present == 0x3) {
   3321         info->flags |= BCM_FLOW_ENCAP_FLAG_VLAN_DELETE;
   3322 
   3323     } else if (action_present == 4) {
   3324         info->flags |= BCM_FLOW_ENCAP_FLAG_VLAN_PRI_TPID_REPLACE;
   3325 
   3326     } else if (action_present == 0x5) {
   3327         info->flags |= BCM_FLOW_ENCAP_FLAG_VLAN_PRI_REPLACE;
   3328 
   3329     } else if (action_present == 0x6) {
   3330         info->flags |= BCM_FLOW_ENCAP_FLAG_PRI_REPLACE;
   3331 
   3332     } else if (action_present == 0x7) {
   3333         info->flags |= BCM_FLOW_ENCAP_FLAG_TPID_REPLACE;
   3334     }
   3335 
   3336     if ((info->flags & BCM_FLOW_ENCAP_FLAG_SERVICE_VLAN_ADD) ||
   3337         (info->flags & BCM_FLOW_ENCAP_FLAG_SERVICE_VLAN_TPID_REPLACE) ||
   3338         (info->flags & BCM_FLOW_ENCAP_FLAG_TPID_REPLACE) ||
   3339         (info->flags & BCM_FLOW_ENCAP_FLAG_VLAN_PRI_TPID_REPLACE)) {
   3340         tpid_index = soc_mem_field32_get(unit, mem, entry, tpid_f);
   3341 
   3342         rv = _bcm_fb2_outer_tpid_entry_get(unit, &info->tpid, tpid_index);
   3343         if (BCM_FAILURE(rv)) {
   3344             info->flags |= _BCM_FLOW_ENCAP_FLAG_TPID_INDEX;
   3345             info->tpid = tpid_index;
   3346         }
   3347         if (tpid_idx != NULL) {
   3348             *tpid_idx = tpid_index;
   3349         }
   3350     }
   3351     return  BCM_E_NONE;
   3352 }
   3353 
   3354 STATIC int
   3355 _bcm_flow_sd_tag_set_to_format(
   3356         int unit,
   3357         bcm_flow_encap_config_t *info,
   3358         soc_mem_t mem,
   3359         uint32 *entry,
   3360         int *tpid_index)
   3361 {
   3362     int action_present = 0;
   3363     int action_not_present = 0;
   3364     int sd_tag_remark_cfi_set = 0;
   3365     int old_tpid_inx = 0;
   3366     uint32 profile_index = 0;
   3367     soc_format_t tag_profile_fmt = TAG_ACTION_PROFILE_ACTION_SETfmt;
   3368     soc_format_t tag_act_fmt = OTAG_ACTION_SETfmt;
   3369     soc_field_t tag_profile_fmt_f = TAG_ACTION_PROFILE_ACTION_SETf;
   3370     soc_field_t tag_act_fmt_f = OTAG_ACTION_SETf;
   3371     uint32 tag_profile_set = 0;
   3372     uint32 tag_act_set = 0;
   3373     soc_field_t vlan_f = VIDf;
   3374     soc_field_t pri_f = PCPf;
   3375     soc_field_t cfi_f = DEf;
   3376     soc_field_t pri_cfi_sel_f = PCP_DE_SELf;
   3377     soc_field_t tag_act_f = TAG_ACTION_PROFILE_PTRf;
   3378     soc_field_t tpid_f = TPID_INDEXf;
   3379 
   3380     if (!_BCM_FLOW_IS_FLEX_VIEW(info)) {
   3381         LOG_ERROR(BSL_LS_BCM_FLOW, (BSL_META_U(unit,
   3382            "Flex view only\n")));
   3383         return BCM_E_PARAM;
   3384     }
   3385 
   3386     if (info->valid_elements & BCM_FLOW_ENCAP_VLAN_VALID) {
   3387         if (info->vlan >= BCM_VLAN_INVALID) {
   3388             return  BCM_E_PARAM;
   3389         }
   3390         soc_format_field32_set(unit, tag_act_fmt, &tag_act_set, vlan_f, info->vlan);
   3391     }
   3392     if (info->valid_elements & BCM_FLOW_ENCAP_PKT_PRI_VALID) {
   3393         if (info->pri > BCM_PRIO_MAX) {
   3394             return  BCM_E_PARAM;
   3395         }
   3396         soc_format_field32_set(unit, tag_act_fmt, &tag_act_set, pri_f, info->pri);
   3397     }
   3398     if (info->valid_elements & BCM_FLOW_ENCAP_PKT_CFI_VALID) {
   3399         if (info->cfi > 1) {
   3400            return  BCM_E_PARAM;
   3401         }
   3402         soc_format_field32_set(unit, tag_act_fmt, &tag_act_set, cfi_f, info->cfi);
   3403     }
   3404 
   3405     if (info->flags & BCM_FLOW_ENCAP_FLAG_SERVICE_VLAN_ADD) {
   3406         sd_tag_remark_cfi_set = TRUE;
   3407         action_not_present = 0x1;  /* ADD */
   3408     }
   3409 
   3410     if (info->flags & BCM_FLOW_ENCAP_FLAG_SERVICE_VLAN_TPID_REPLACE) {
   3411         action_present = 0x1; /* REPLACE_VID_TPID */
   3412 
   3413     } else if (info->flags & BCM_FLOW_ENCAP_FLAG_VLAN_REPLACE) {
   3414         action_present = 0x2;  /* REPLACE_VID_ONLY */
   3415 
   3416     } else if (info->flags & BCM_FLOW_ENCAP_FLAG_VLAN_DELETE) {
   3417         action_present = 0x3;  /* DELETE */
   3418 
   3419     } else if (info->flags & BCM_FLOW_ENCAP_FLAG_VLAN_PRI_TPID_REPLACE) {
   3420         sd_tag_remark_cfi_set = TRUE;
   3421         action_present = 0x4;  /* REPLACE_VID_PRI_TPID */
   3422 
   3423     } else if (info->flags & BCM_FLOW_ENCAP_FLAG_VLAN_PRI_REPLACE){
   3424         sd_tag_remark_cfi_set = TRUE;
   3425         action_present = 0x5;  /* REPLACE_VID_PRI */
   3426 
   3427     } else if (info->flags & BCM_FLOW_ENCAP_FLAG_PRI_REPLACE ) {
   3428         sd_tag_remark_cfi_set = TRUE;
   3429         action_present = 0x6;  /*  REPLACE_PRI_ONLY */
   3430 
   3431     } else if (info->flags & BCM_FLOW_ENCAP_FLAG_TPID_REPLACE) {
   3432         action_present = 0x7;  /* REPLACE_TPID_ONLY */
   3433     }
   3434 
   3435     soc_format_field32_set(unit, tag_act_fmt, &tag_act_set, pri_cfi_sel_f, sd_tag_remark_cfi_set);
   3436     soc_mem_field32_set(unit, mem, entry, tag_act_fmt_f, tag_act_set);
   3437 
   3438     tag_profile_set = soc_mem_field32_get(unit, mem, entry, tag_profile_fmt_f);
   3439 
   3440     profile_index = soc_format_field32_get(unit, tag_profile_fmt, &tag_profile_set, tag_act_f);
   3441     _bcm_td3_sd_tag_action_profile_get(unit, action_present,
   3442             action_not_present, &profile_index);
   3443     soc_format_field32_set(unit, tag_profile_fmt, &tag_profile_set, tag_act_f, profile_index);
   3444     soc_mem_field32_set(unit, mem, entry, tag_profile_fmt_f, tag_profile_set);
   3445 
   3446     if ((info->flags & BCM_FLOW_ENCAP_FLAG_SERVICE_VLAN_ADD) ||
   3447         (info->flags & BCM_FLOW_ENCAP_FLAG_SERVICE_VLAN_TPID_REPLACE) ||
   3448         (info->flags & BCM_FLOW_ENCAP_FLAG_TPID_REPLACE) ||
   3449         (info->flags & BCM_FLOW_ENCAP_FLAG_VLAN_PRI_TPID_REPLACE)) {
   3450         if (info->options & BCM_FLOW_ENCAP_OPTION_REPLACE) {
   3451             tag_act_set = soc_mem_field32_get(unit, mem, entry, tag_act_fmt_f);
   3452             old_tpid_inx = soc_format_field32_get(unit, tag_act_fmt, &tag_act_set, tpid_f);
   3453             BCM_IF_ERROR_RETURN(_bcm_fb2_outer_tpid_entry_delete(unit,
   3454                                 old_tpid_inx));
   3455         }
   3456 
   3457         /* TPID value is used */
   3458         BCM_IF_ERROR_RETURN(_bcm_fb2_outer_tpid_entry_add(unit, info->tpid,
   3459                              tpid_index));
   3460 
   3461         soc_format_field32_set(unit, tag_act_fmt, &tag_act_set, tpid_f, *tpid_index);
   3462         soc_mem_field32_set(unit, mem, entry, tag_act_fmt_f, tag_act_set);
   3463     }
   3464     return  BCM_E_NONE;
   3465 }
   3466 
   3467 
   3468 STATIC int
   3469 _bcm_flow_sd_tag_get_from_format(
   3470         int unit,
   3471         bcm_flow_encap_config_t *info,
   3472         soc_mem_t mem,
   3473         uint32 *entry,
   3474         int  *tpid_idx)
   3475 {
   3476     int action_present = 0;
   3477     int action_not_present = 0;
   3478     int tpid_index = 0;
   3479     uint32 profile_index = 0;
   3480     int rv = BCM_E_NONE;
   3481     soc_format_t tag_profile_fmt = TAG_ACTION_PROFILE_ACTION_SETfmt;
   3482     soc_format_t tag_act_fmt = OTAG_ACTION_SETfmt;
   3483     soc_field_t tag_profile_fmt_f = TAG_ACTION_PROFILE_ACTION_SETf;
   3484     soc_field_t tag_act_fmt_f = OTAG_ACTION_SETf;
   3485     uint32 tag_profile_set = 0;
   3486     uint32 tag_act_set = 0;
   3487     soc_field_t vlan_f = VIDf;
   3488     soc_field_t pri_f = PCPf;
   3489     soc_field_t cfi_f = DEf;
   3490     soc_field_t tag_act_f = TAG_ACTION_PROFILE_PTRf;
   3491     soc_field_t tpid_f = TPID_INDEXf;
   3492 
   3493 
   3494     if (!_BCM_FLOW_IS_FLEX_VIEW(info)) {
   3495         LOG_ERROR(BSL_LS_BCM_FLOW, (BSL_META_U(unit,
   3496            "Flex view only\n")));
   3497         return BCM_E_PARAM;
   3498     }
   3499 
   3500     tag_act_set = soc_mem_field32_get(unit, mem, entry, tag_act_fmt_f);
   3501 
   3502     info->vlan = soc_format_field32_get(unit, tag_act_fmt, &tag_act_set, vlan_f);
   3503     info->pri = soc_format_field32_get(unit, tag_act_fmt, &tag_act_set, pri_f);
   3504     info->cfi = soc_format_field32_get(unit, tag_act_fmt, &tag_act_set, cfi_f);
   3505 
   3506     tag_profile_set = soc_mem_field32_get(unit, mem, entry, tag_profile_fmt_f);
   3507 
   3508     profile_index = soc_format_field32_get(unit, tag_profile_fmt, &tag_profile_set, tag_act_f);
   3509     (void)_bcm_td3_sd_tag_action_get(unit, profile_index, &action_present,
   3510                     &action_not_present);
   3511 
   3512     if (action_not_present || action_present) {
   3513         info->flags |= BCM_FLOW_ENCAP_FLAG_SERVICE_TAGGED;
   3514     }
   3515     if (action_not_present) {
   3516         info->flags |= BCM_FLOW_ENCAP_FLAG_SERVICE_VLAN_ADD;
   3517     }
   3518 
   3519     if (action_present == 0x1) {
   3520         info->flags |= BCM_FLOW_ENCAP_FLAG_SERVICE_VLAN_TPID_REPLACE;
   3521 
   3522     } else if (action_present == 0x2) {
   3523         info->flags  |= BCM_FLOW_ENCAP_FLAG_VLAN_REPLACE;
   3524 
   3525     } else if (action_present == 0x3) {
   3526         info->flags |= BCM_FLOW_ENCAP_FLAG_VLAN_DELETE;
   3527 
   3528     } else if (action_present == 4) {
   3529         info->flags |= BCM_FLOW_ENCAP_FLAG_VLAN_PRI_TPID_REPLACE;
   3530 
   3531     } else if (action_present == 0x5) {
   3532         info->flags |= BCM_FLOW_ENCAP_FLAG_VLAN_PRI_REPLACE;
   3533 
   3534     } else if (action_present == 0x6) {
   3535         info->flags |= BCM_FLOW_ENCAP_FLAG_PRI_REPLACE;
   3536 
   3537     } else if (action_present == 0x7) {
   3538         info->flags |= BCM_FLOW_ENCAP_FLAG_TPID_REPLACE;
   3539     }
   3540 
   3541     if ((info->flags & BCM_FLOW_ENCAP_FLAG_SERVICE_VLAN_ADD) ||
   3542         (info->flags & BCM_FLOW_ENCAP_FLAG_SERVICE_VLAN_TPID_REPLACE) ||
   3543         (info->flags & BCM_FLOW_ENCAP_FLAG_TPID_REPLACE) ||
   3544         (info->flags & BCM_FLOW_ENCAP_FLAG_VLAN_PRI_TPID_REPLACE)) {
   3545         tpid_index = soc_format_field32_get(unit, tag_act_fmt, &tag_act_set, tpid_f);
   3546 
   3547         rv = _bcm_fb2_outer_tpid_entry_get(unit, &info->tpid, tpid_index);
   3548         if (BCM_FAILURE(rv)) {
   3549             info->flags |= _BCM_FLOW_ENCAP_FLAG_TPID_INDEX;
   3550             info->tpid = tpid_index;
   3551         }
   3552         if (tpid_idx != NULL) {
   3553             *tpid_idx = tpid_index;
   3554         }
   3555     }
   3556     return  BCM_E_NONE;
   3557 }
   3558 
   3559 /*
   3560  * Function:
   3561  *      _bcm_flow_encap_profile_delete
   3562  * Purpose:
   3563  *      Delete a profile in flow encap entry based on the given info
   3564  * Parameters:
   3565  *      unit     - (IN) Device Number
   3566  *      info    - (IN) Flow encap config descriptor
   3567  *      mem      - (IN) mempru ID
   3568  *      mem_view - (IN) memory view ID
   3569  *      key_data - (IN) entry key
   3570  * Returns:
   3571  *      BCM_E_XXX
   3572  */
   3573 
   3574 STATIC int
   3575 _bcm_flow_encap_profile_delete(
   3576         int unit,
   3577         bcm_flow_encap_config_t *info,
   3578         soc_mem_t mem,
   3579         soc_mem_t mem_view,
   3580         void *key_data)
   3581 {
   3582     soc_format_t tag_profile_fmt = TAG_ACTION_PROFILE_ACTION_SETfmt;
   3583     soc_field_t tag_profile_fmt_f = TAG_ACTION_PROFILE_ACTION_SETf;
   3584     soc_field_t tag_act_f = TAG_ACTION_PROFILE_PTRf;
   3585     uint32 tag_profile_set = 0;
   3586     uint32 profile_index = 0;
   3587     uint32 return_entry[SOC_MAX_MEM_WORDS];
   3588     int index = 0;
   3589     int rv = BCM_E_NONE;
   3590 
   3591     rv = soc_mem_search(unit, mem, MEM_BLOCK_ANY, &index,
   3592              key_data, return_entry, 0);
   3593     if (rv != BCM_E_NONE) {
   3594         return BCM_E_NONE;
   3595     }
   3596     if (soc_flow_db_mem_view_is_valid(unit, mem_view)){
   3597         if (soc_mem_field_valid(unit, mem_view, tag_profile_fmt_f)){
   3598             tag_profile_set = soc_mem_field32_get(unit, mem_view, return_entry,
   3599                             tag_profile_fmt_f);
   3600             profile_index = soc_format_field32_get(unit, tag_profile_fmt,
   3601                             &tag_profile_set, tag_act_f);
   3602         }
   3603     } else if ((info->flow_handle == SOC_FLOW_DB_FLOW_ID_LEGACY_VXLAN) &&
   3604     (soc_mem_field_valid(unit, mem, tag_act_f))) {
   3605         profile_index = soc_mem_field32_get(unit, mem, return_entry,
   3606                             tag_act_f);
   3607     }
   3608 
   3609     if (profile_index != 0) {
   3610         rv = _bcm_trx_egr_vlan_action_profile_entry_delete(unit,
   3611                     profile_index);
   3612     }
   3613     return rv;
   3614 }
   3615 
   3616 
   3617 /*
   3618  * Function:
   3619  *      _bcm_flow_encap_entry_set
   3620  * Purpose:
   3621  *      Set flow Match Entry
   3622  * Parameters:
   3623  *      unit - (IN) Device Number
   3624  *      info - (IN) flow_match configuration info
   3625  *      field - (IN) array of logical fields
   3626  *      num_of_fields -(IN) the size of the above array
   3627  *      mem  - (IN) memory id
   3628  *      entry - (IN) point to the match entry
   3629  * Returns:
   3630  *      BCM_E_XXX
   3631  */
   3632 
   3633 STATIC int
   3634 _bcm_flow_encap_entry_set(int unit,
   3635         bcm_flow_encap_config_t *info,
   3636         bcm_flow_logical_field_t *field,
   3637         int num_of_fields,
   3638         soc_mem_t mem,
   3639         uint32 *entry,
   3640         int network_port)
   3641 {
   3642     int rv = BCM_E_NONE;
   3643     int index = -1;
   3644     uint32 return_entry[SOC_MAX_MEM_WORDS];
   3645     int i;
   3646     int j;
   3647     soc_field_t vnid_f;
   3648     uint32 sd_tag;
   3649     int tpid_index;
   3650     uint32 tunnel_data[3];
   3651     uint32 otag;
   3652     uint32 xlate_data[3];
   3653     int tunnel_format;
   3654     int type = 0;
   3655     int new_entry_add = FALSE;
   3656     tunnel_format = EGR_VLAN_XLATE_TUNNEL_DATA_DOUBLEfmt;
   3657 
   3658     /* data fields: flex view uses PDD */
   3659     sal_memset(tunnel_data, 0, sizeof(tunnel_data));
   3660 
   3661     rv = soc_mem_search(unit, mem, MEM_BLOCK_ANY, &index, entry,
   3662                         return_entry, 0);
   3663     if (BCM_E_NONE == rv) {
   3664         /* found memory entry */
   3665         if (info->options & BCM_FLOW_ENCAP_OPTION_REPLACE) {
   3666             sal_memcpy(entry,return_entry,SOC_MAX_MEM_WORDS * 4);
   3667         } else {
   3668             return BCM_E_EXISTS;
   3669         }
   3670     } else if (BCM_E_NOT_FOUND == rv) {
   3671         if (info->options & BCM_FLOW_ENCAP_OPTION_REPLACE) {
   3672             return BCM_E_NOT_FOUND;
   3673         } else {
   3674             new_entry_add = TRUE;
   3675         }
   3676     } else {
   3677         return rv;
   3678     }
   3679 
   3680     if (network_port) {
   3681         sd_tag = 0;
   3682         if (info->options & BCM_FLOW_ENCAP_OPTION_REPLACE) {
   3683             if (_BCM_FLOW_SD_TAG_FORMAT(info)) {
   3684                 if (!_BCM_FLOW_IS_FLEX_VIEW(info)) {
   3685                     if (info->criteria == BCM_FLOW_ENCAP_CRITERIA_VRF_MAPPING) {
   3686                         soc_mem_field_get(unit, mem, entry,
   3687                              VRF_MAPPING__TUNNEL_DATAf, tunnel_data);
   3688                         sd_tag = soc_format_field32_get(unit,tunnel_format,
   3689                                        tunnel_data, SD_TAG_DATAf);
   3690                     } else {
   3691                         if (soc_mem_field_valid(unit, mem, VFI_DVP_GROUP__TUNNEL_DATAf)) {
   3692                             soc_mem_field_get(unit, mem, entry,
   3693                                  VFI_DVP_GROUP__TUNNEL_DATAf, tunnel_data);
   3694                             sd_tag = soc_format_field32_get(unit,tunnel_format,
   3695                                            tunnel_data, SD_TAG_DATAf);
   3696                         }
   3697                     }
   3698                 } else {
   3699                     if (SOC_MEM_FIELD_VALID(unit,mem,SD_TAG_ACTION_SETf)) {
   3700                         sd_tag = soc_mem_field32_get(unit, mem, entry,
   3701                                           SD_TAG_ACTION_SETf);
   3702                     }
   3703                 }
   3704             } else {
   3705                 if (info->criteria == BCM_FLOW_ENCAP_CRITERIA_VFI) {
   3706                     if (info->flow_handle == SOC_FLOW_DB_FLOW_ID_LEGACY_VXLAN) {
   3707                         if (soc_mem_field_valid(unit, mem, VXLAN_VFI__SD_TAG_DATAf)) {
   3708                             sd_tag = soc_mem_field32_get(unit, mem, entry,
   3709                                               VXLAN_VFI__SD_TAG_DATAf);
   3710                         }
   3711                     } else if (info->flow_handle == 
   3712                                          SOC_FLOW_DB_FLOW_ID_LEGACY_L2GRE) {
   3713                         sd_tag = soc_mem_field32_get(unit, mem, entry,
   3714                                           L2GRE_VFI__SD_TAG_DATAf);
   3715                     }
   3716                 }
   3717             }
   3718         }
   3719         if ((info->valid_elements & BCM_FLOW_ENCAP_FLAGS_VALID) &&
   3720             (info->flags & BCM_FLOW_ENCAP_FLAG_SERVICE_TAGGED)) {
   3721             if ((info->flow_handle == SOC_FLOW_DB_FLOW_ID_LEGACY_VXLAN) &&
   3722                 soc_feature(unit, soc_feature_vxlan_decoupled_mode)) {
   3723                 rv = _bcm_flow_sd_tag_set_to_entry(unit, info, mem, entry,
   3724                                       &tpid_index);
   3725             } else if (soc_mem_field_valid(unit, mem, OTAG_ACTION_SETf) &&
   3726                 soc_mem_field_valid(unit, mem, TAG_ACTION_PROFILE_ACTION_SETf)) {
   3727                 rv = _bcm_flow_sd_tag_set_to_format(unit, info, mem, entry,
   3728                                       &tpid_index);
   3729             } else {
   3730                 rv = _bcm_flow_sd_tag_set(unit, info, &sd_tag,
   3731                                       &tpid_index);
   3732             }
   3733             BCM_IF_ERROR_RETURN(rv);
   3734         }
   3735 
   3736         if (info->criteria == BCM_FLOW_ENCAP_CRITERIA_VFI_DVP_GROUP &&
   3737             (!(_BCM_FLOW_IS_FLEX_VIEW(info)))) {
   3738             soc_mem_field32_set(unit, mem, entry, 
   3739                  VFI_DVP_GROUP__DATA_OVERLAY_TYPEf, 0);  /* tunnel data */
   3740         }
   3741         if (info->valid_elements & BCM_FLOW_ENCAP_VNID_VALID) {
   3742             if (_BCM_FLOW_IS_FLEX_VIEW(info)) {
   3743                 vnid_f = DIRECT_ASSIGNMENT_22_ACTION_SETf; /* VNID */
   3744             } else {
   3745                 if (info->flow_handle == SOC_FLOW_DB_FLOW_ID_LEGACY_VXLAN) {
   3746                     if (soc_feature(unit, soc_feature_vxlan_decoupled_mode)) {
   3747                         vnid_f = VXLAN_VFI_FLEX__VNIDf;
   3748                     } else {
   3749                         vnid_f = VXLAN_VFI__VN_IDf;
   3750                     }
   3751                     type = 2;
   3752                     } else if (info->flow_handle == SOC_FLOW_DB_FLOW_ID_LEGACY_L2GRE) {
   3753                     vnid_f = L2GRE_VFI__VPNIDf;
   3754                     type = 1;
   3755                 } else {
   3756                     return BCM_E_PARAM;
   3757                 }
   3758             }
   3759             if (_BCM_FLOW_TUNNEL_DATA_FORMAT(info) && 
   3760                 (!_BCM_FLOW_IS_FLEX_VIEW(info))) {
   3761                 soc_format_field32_set(unit,tunnel_format,tunnel_data,
   3762                                 TUNNEL_HEADER_DATA_TYPEf,type);
   3763                 if (type == 1) {
   3764                     soc_format_field32_set(unit,tunnel_format,tunnel_data,
   3765                                 VPNIDf,info->vnid);
   3766                 } else if (type == 2) {
   3767                     if ((info->flow_handle == SOC_FLOW_DB_FLOW_ID_LEGACY_VXLAN)
   3768                         && soc_feature(unit, soc_feature_vxlan_decoupled_mode)) {
   3769                         if (soc_mem_field_valid(unit, mem, vnid_f)) {
   3770                             soc_mem_field32_set(unit, mem, entry, vnid_f, info->vnid);
   3771                         }
   3772                     } else {
   3773                         soc_format_field32_set(unit,tunnel_format,tunnel_data,
   3774                                     VN_IDf,info->vnid);
   3775                     }
   3776                 }
   3777                 soc_mem_field_set(unit, mem, entry,
   3778                              VFI_DVP_GROUP__TUNNEL_DATAf, tunnel_data);
   3779             } else {
   3780                 if (!SOC_MEM_FIELD_VALID(unit, mem, vnid_f)) {
   3781                     return BCM_E_PARAM;
   3782                 }
   3783                 soc_mem_field32_set(unit, mem, entry, vnid_f, info->vnid);
   3784             }
   3785         }
   3786         if ((info->valid_elements & BCM_FLOW_ENCAP_FLAGS_VALID) &&
   3787             (info->flags & BCM_FLOW_ENCAP_FLAG_SERVICE_TAGGED)) {
   3788             if (_BCM_FLOW_SD_TAG_FORMAT(info)) {
   3789                 if (!_BCM_FLOW_IS_FLEX_VIEW(info)) {
   3790                     soc_format_field32_set(unit,tunnel_format,tunnel_data,
   3791                                 SD_TAG_DATAf,sd_tag);
   3792                     if (info->criteria == BCM_FLOW_ENCAP_CRITERIA_VRF_MAPPING) {
   3793                         soc_mem_field_set(unit, mem, entry, 
   3794                              VRF_MAPPING__TUNNEL_DATAf, tunnel_data);
   3795                     } else {
   3796                         if (soc_mem_field_valid(unit, mem, VFI_DVP_GROUP__TUNNEL_DATAf)) {
   3797                             soc_mem_field_set(unit, mem, entry,
   3798                                  VFI_DVP_GROUP__TUNNEL_DATAf, tunnel_data);
   3799                         }
   3800                     }
   3801                 } else {
   3802                     if (!(soc_mem_field_valid(unit, mem, OTAG_ACTION_SETf) &&
   3803                         soc_mem_field_valid(unit, mem, TAG_ACTION_PROFILE_ACTION_SETf))) {
   3804                         if (!SOC_MEM_FIELD_VALID(unit, mem, SD_TAG_ACTION_SETf)) {
   3805                             return BCM_E_PARAM;
   3806                         }
   3807                         soc_mem_field32_set(unit, mem, entry,
   3808                                                   SD_TAG_ACTION_SETf, sd_tag);
   3809                     }
   3810                 }
   3811             } else {
   3812                 if (info->criteria == BCM_FLOW_ENCAP_CRITERIA_VFI) {
   3813                     if (info->flow_handle == SOC_FLOW_DB_FLOW_ID_LEGACY_VXLAN) {
   3814                         /* VXLAN_VFI__SD_TAG_DATAf defined in regsfile */
   3815                     } else if (info->flow_handle == 
   3816                                             SOC_FLOW_DB_FLOW_ID_LEGACY_L2GRE) {
   3817                         soc_mem_field32_set(unit, mem, entry,
   3818                                           L2GRE_VFI__SD_TAG_DATAf,sd_tag);
   3819                     }
   3820                 }
   3821             }
   3822         }
   3823     } else {  /* if (network_port)  */
   3824         if (info->criteria == BCM_FLOW_ENCAP_CRITERIA_VFI_DVP_GROUP ||
   3825             info->criteria == BCM_FLOW_ENCAP_CRITERIA_VFI_DVP) {
   3826 
   3827             sal_memset(xlate_data, 0, sizeof(xlate_data));
   3828             rv = _bcm_flow_encap_vlan_set(unit, info, mem, entry,
   3829                            &otag,xlate_data);
   3830             BCM_IF_ERROR_RETURN(rv);
   3831             if (info->criteria == BCM_FLOW_ENCAP_CRITERIA_VFI_DVP_GROUP &&
   3832                 (!(_BCM_FLOW_IS_FLEX_VIEW(info)))) {
   3833                 if (soc_mem_field_valid(unit, mem, VFI_DVP_GROUP__DATA_OVERLAY_TYPEf)) {
   3834                     soc_mem_field32_set(unit, mem, entry,
   3835                          VFI_DVP_GROUP__DATA_OVERLAY_TYPEf, 1);  /* vlan xlate data */
   3836                 }
   3837             }
   3838             if (!_BCM_FLOW_IS_FLEX_VIEW(info)) {
   3839                 if (info->criteria == BCM_FLOW_ENCAP_CRITERIA_VFI_DVP_GROUP) {
   3840                     if (soc_mem_field_valid(unit, mem, VFI_DVP_GROUP__XLATE_DATAf)) {
   3841                         soc_mem_field_set(unit, mem, entry,
   3842                              VFI_DVP_GROUP__XLATE_DATAf, xlate_data);
   3843                     }
   3844                 } else { /* VLAN_XLATE_VFI */
   3845                     soc_mem_field_set(unit, mem, entry,
   3846                          VLAN_XLATE_VFI__XLATE_DATAf, xlate_data);
   3847                 }
   3848             } else {
   3849                 if (!SOC_MEM_FIELD_VALID(unit, mem, OTAG_ACTION_SETf)) {
   3850                     return BCM_E_PARAM;
   3851                 }
   3852                 soc_mem_field32_set(unit, mem, entry, OTAG_ACTION_SETf, otag);
   3853             }
   3854         }
   3855     }
   3856 
   3857     if (info->criteria == BCM_FLOW_ENCAP_CRITERIA_SVP_DVP) {
   3858         if (soc_feature(unit, soc_feature_vxlan_evpn)) {
   3859             if (info->valid_elements & BCM_FLOW_ENCAP_CLASS_ID_VALID) {
   3860                 if (!SOC_MEM_FIELD_VALID(unit, mem, CLASS_ID_ACTION_SETf)) {
   3861                     return BCM_E_PARAM;
   3862                 }
   3863                 soc_mem_field32_set(unit,mem, entry, CLASS_ID_ACTION_SETf, info->class_id);
   3864             }
   3865         }
   3866     }
   3867     
   3868     if (info->valid_elements & BCM_FLOW_ENCAP_FLEX_DATA_VALID) {
   3869         uint32 data_ids[_BCM_FLOW_LOGICAL_FIELD_MAX];
   3870         uint32 cnt;
   3871         rv = soc_flow_db_mem_view_field_list_get(unit,
   3872                       mem,
   3873                       SOC_FLOW_DB_FIELD_TYPE_LOGICAL_POLICY_DATA,
   3874                       _BCM_FLOW_LOGICAL_FIELD_MAX, data_ids, &cnt);
   3875         BCM_IF_ERROR_RETURN(rv);
   3876         for (i = 0; i < num_of_fields; i++) {
   3877             for (j = 0; j < cnt; j++) {
   3878                 if (field[i].id == data_ids[j]) {
   3879                     soc_mem_field32_set(unit,mem, entry,
   3880                           field[i].id, field[i].value);
   3881                     break;
   3882                 }
   3883             }
   3884         }
   3885     }
   3886 
   3887     if (new_entry_add) {
   3888         rv = soc_mem_insert(unit, mem, MEM_BLOCK_ALL, entry);
   3889     } else { /* replace action */
   3890         rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, index, entry);
   3891     }
   3892 
   3893     BCM_IF_ERROR_RETURN(rv);
   3894     return rv;
   3895 }
   3896 
   3897 /*
   3898  * Function:
   3899  *      _bcm_flow_encap_entry_data_get
   3900  * Purpose:
   3901  *      Convert the hardware entry data to the flow encap user data 
   3902  * Parameters:
   3903  *      unit - (IN) Device Number
   3904  *      info - (IN) flow_encap configuration info
   3905  *      field - (IN) array of logical fields
   3906  *      num_of_fields -(IN) the size of the above array
   3907  *      mem  - (IN) memory id
   3908  *      entry - (IN) point to the encap entry
   3909  * Returns:
   3910  *      BCM_E_XXX
   3911  */
   3912 
   3913 STATIC int
   3914 _bcm_flow_encap_entry_data_get(int unit,
   3915         bcm_flow_encap_config_t *info,
   3916         bcm_flow_logical_field_t *field,
   3917         int num_of_fields,
   3918         soc_mem_t mem,
   3919         uint32 *entry,
   3920         int network_port)
   3921 {
   3922     int rv = BCM_E_NONE;
   3923     int i;
   3924     int j;
   3925     soc_field_t vnid_f;
   3926     uint32 tunnel_data[3];
   3927     uint32 otag;
   3928     uint32 xlate_data[3];
   3929     int tunnel_format;
   3930     int type;
   3931     uint32 sd_tag = 0;
   3932     
   3933     tunnel_format = EGR_VLAN_XLATE_TUNNEL_DATA_DOUBLEfmt;
   3934 
   3935     /* data fields: flex view uses PDD */
   3936     sal_memset(tunnel_data, 0, sizeof(tunnel_data));
   3937 
   3938     if (network_port) {
   3939         if (_BCM_FLOW_SD_TAG_FORMAT(info)) {
   3940             if (!_BCM_FLOW_IS_FLEX_VIEW(info)) {
   3941                 if (info->criteria == BCM_FLOW_ENCAP_CRITERIA_VRF_MAPPING) {
   3942                     soc_mem_field_get(unit, mem, entry,
   3943                                 VRF_MAPPING__TUNNEL_DATAf, tunnel_data);
   3944                 } else {
   3945                     soc_mem_field_get(unit, mem, entry,
   3946                                 VFI_DVP_GROUP__TUNNEL_DATAf, tunnel_data);
   3947                 }
   3948                 sd_tag = soc_format_field32_get(unit,tunnel_format,
   3949                                    tunnel_data, SD_TAG_DATAf);
   3950             } else {
   3951                 if (SOC_MEM_FIELD_VALID(unit,mem,SD_TAG_ACTION_SETf)) {
   3952                     sd_tag = soc_mem_field32_get(unit, mem, entry,
   3953                                           SD_TAG_ACTION_SETf);
   3954                 }
   3955             }
   3956         } else {
   3957             if (info->criteria == BCM_FLOW_ENCAP_CRITERIA_VFI) {
   3958                 if (info->flow_handle == SOC_FLOW_DB_FLOW_ID_LEGACY_VXLAN) {
   3959                     if (!soc_feature(unit, soc_feature_vxlan_decoupled_mode)) {
   3960                         sd_tag = soc_mem_field32_get(unit, mem, entry,
   3961                                           VXLAN_VFI__SD_TAG_DATAf);
   3962                     }
   3963                 } else if (info->flow_handle == 
   3964                                      SOC_FLOW_DB_FLOW_ID_LEGACY_L2GRE) {
   3965                     sd_tag = soc_mem_field32_get(unit, mem, entry,
   3966                                       L2GRE_VFI__SD_TAG_DATAf);
   3967                 }
   3968             }
   3969         }
   3970         if (soc_feature(unit, soc_feature_vxlan_decoupled_mode) &&
   3971             (info->flow_handle == SOC_FLOW_DB_FLOW_ID_LEGACY_VXLAN) &&
   3972             (mem == EGR_VLAN_XLATE_1_SINGLEm)) {
   3973             rv = _bcm_flow_sd_tag_get_from_entry(unit, info, mem, entry, NULL);
   3974         } else if (soc_mem_field_valid(unit, mem, OTAG_ACTION_SETf) &&
   3975             soc_mem_field_valid(unit, mem, TAG_ACTION_PROFILE_ACTION_SETf)) {
   3976             rv = _bcm_flow_sd_tag_get_from_format(unit, info, mem, entry, NULL);
   3977         } else {
   3978             rv = _bcm_flow_sd_tag_get(unit, info, sd_tag, NULL);
   3979         }
   3980         BCM_IF_ERROR_RETURN(rv);
   3981         
   3982         if (_BCM_FLOW_IS_FLEX_VIEW(info)) {
   3983             vnid_f = DIRECT_ASSIGNMENT_22_ACTION_SETf; /* VNID */
   3984         } else {
   3985             if (info->flow_handle == SOC_FLOW_DB_FLOW_ID_LEGACY_VXLAN) {
   3986                 if (soc_feature(unit, soc_feature_vxlan_decoupled_mode)) {
   3987                     vnid_f = VXLAN_VFI_FLEX__VNIDf;
   3988                 } else {
   3989                     vnid_f = VXLAN_VFI__VN_IDf;
   3990                 }
   3991             } else if (info->flow_handle == SOC_FLOW_DB_FLOW_ID_LEGACY_L2GRE) {
   3992                 vnid_f = L2GRE_VFI__VPNIDf;
   3993             } else {
   3994                 return BCM_E_PARAM;
   3995             }
   3996         }
   3997         if (_BCM_FLOW_TUNNEL_DATA_FORMAT(info) && 
   3998             (!_BCM_FLOW_IS_FLEX_VIEW(info))) {
   3999             type = soc_format_field32_get(unit,tunnel_format,tunnel_data,
   4000                                 TUNNEL_HEADER_DATA_TYPEf);
   4001             if (type == 1) {
   4002                 info->vnid = soc_format_field32_get(unit,tunnel_format,
   4003                                     tunnel_data, VPNIDf);
   4004             } else if (type == 2) {
   4005                 info->vnid = soc_format_field32_get(unit,tunnel_format,
   4006                                    tunnel_data, VN_IDf);
   4007             }
   4008  
   4009         } else {
   4010             if (SOC_MEM_FIELD_VALID(unit,mem,vnid_f)) {
   4011                 info->vnid = soc_mem_field32_get(unit, mem, entry, vnid_f);
   4012             }
   4013         }
   4014         
   4015     } else {  /* if (network_port) */
   4016         if (info->criteria == BCM_FLOW_ENCAP_CRITERIA_VFI_DVP_GROUP ||
   4017             info->criteria == BCM_FLOW_ENCAP_CRITERIA_VFI_DVP) {
   4018             
   4019             if (!_BCM_FLOW_IS_FLEX_VIEW(info)) {
   4020                 if (info->criteria == BCM_FLOW_ENCAP_CRITERIA_VFI_DVP_GROUP) {
   4021                     if (soc_mem_field_valid(unit, mem, VFI_DVP_GROUP__XLATE_DATAf)) {
   4022                         soc_mem_field_get(unit, mem, entry,
   4023                              VFI_DVP_GROUP__XLATE_DATAf, xlate_data);
   4024                     }
   4025                 } else { /* VLAN_XLATE_VFI */
   4026                     soc_mem_field_get(unit, mem, entry,
   4027                          VLAN_XLATE_VFI__XLATE_DATAf, xlate_data);
   4028                 }
   4029             } else {
   4030                 otag = soc_mem_field32_get(unit, mem, entry, OTAG_ACTION_SETf);
   4031             }
   4032             rv = _bcm_flow_encap_vlan_get(unit, info, mem, entry, 
   4033                            &otag,xlate_data);
   4034             BCM_IF_ERROR_RETURN(rv);
   4035         }
   4036     }
   4037 
   4038     if (info->criteria == BCM_FLOW_ENCAP_CRITERIA_SVP_DVP) {
   4039         if (soc_feature(unit, soc_feature_vxlan_evpn)) {
   4040             if (info->valid_elements & BCM_FLOW_ENCAP_SRC_FLOW_PORT_VALID) {
   4041                 if (!SOC_MEM_FIELD_VALID(unit, mem, CLASS_ID_ACTION_SETf)) {
   4042                     return BCM_E_PARAM;
   4043                 }
   4044                 info->class_id = soc_mem_field32_get(unit,mem, entry, CLASS_ID_ACTION_SETf);
   4045             }
   4046         }
   4047     }
   4048 
   4049     if (_BCM_FLOW_IS_FLEX_VIEW(info) && (field != NULL)) {
   4050         uint32 data_ids[_BCM_FLOW_LOGICAL_FIELD_MAX];
   4051         uint32 cnt;
   4052         rv = soc_flow_db_mem_view_field_list_get(unit,
   4053                       mem,
   4054                       SOC_FLOW_DB_FIELD_TYPE_LOGICAL_POLICY_DATA,
   4055                       _BCM_FLOW_LOGICAL_FIELD_MAX, data_ids, &cnt);
   4056         BCM_IF_ERROR_RETURN(rv);
   4057         for (i = 0; i < num_of_fields; i++) {
   4058             for (j = 0; j < cnt; j++) {
   4059                 if (field[i].id == data_ids[j]) {
   4060                     field[i].value = soc_mem_field32_get(unit,mem, entry,
   4061                           field[i].id);
   4062                     break;
   4063                 }
   4064             }
   4065         }
   4066     }
   4067 
   4068     return rv;
   4069 }
   4070 
   4071 /*
   4072  * Function:
   4073  *      bcmi_esw_flow_encap_add
   4074  * Purpose:
   4075  *      Add a flow encap entry
   4076  * Parameters:
   4077  *      unit    - (IN) Device Number
   4078  *      info    - (IN) Flow encap config descriptor
   4079  *      num_of_fields - (IN) number of logical fields
   4080  *      field         - (IN) logical field array
   4081  * Returns:
   4082  *      BCM_E_XXX
   4083  */
   4084 
   4085 int bcmi_esw_flow_encap_add(
   4086     int unit,
   4087     bcm_flow_encap_config_t *info,
   4088     uint32 num_of_fields,
   4089     bcm_flow_logical_field_t *field)
   4090 {
   4091     soc_mem_t mem;
   4092     soc_mem_t mem_view;
   4093     uint32 entry[SOC_MAX_MEM_WORDS];
   4094     int rv;
   4095     int network_port;
   4096     _bcm_vp_info_t vp_info;
   4097     int dvp;
   4098     _bcm_flow_bookkeeping_t *flow_info;
   4099 
   4100     if (info == NULL) {
   4101         return BCM_E_PARAM;
   4102     }
   4103 
   4104     if (info->valid_elements & BCM_FLOW_ENCAP_CLASS_ID_VALID) {
   4105         if ((info->class_id == 0) || (info->class_id > 0xfff)) {
   4106             return BCM_E_PARAM;
   4107         }
   4108     }
   4109 
   4110     flow_info = FLOW_INFO(unit);
   4111 
   4112     sal_memset(entry, 0, sizeof(entry));
   4113     BCM_IF_ERROR_RETURN(_bcm_flow_encap_key_set(unit,info,field,
   4114                         num_of_fields,entry,&mem,&mem_view,&network_port));
   4115 
   4116     /* validate the dvp */
   4117     if ((info->valid_elements & BCM_FLOW_ENCAP_FLOW_PORT_VALID) &&
   4118         (!BCM_GPORT_IS_MODPORT(info->flow_port))) {
   4119         dvp = _SHR_GPORT_FLOW_PORT_ID_GET(info->flow_port);
   4120         if (!_bcm_vp_used_get(unit, dvp, _bcmVpTypeFlow)) {
   4121             LOG_ERROR(BSL_LS_BCM_FLOW, (BSL_META_U(unit,
   4122                "DVP %d is not the flow port\n"), dvp));
   4123             return BCM_E_NOT_FOUND;
   4124         }
   4125         BCM_IF_ERROR_RETURN(_bcm_vp_info_get(unit, dvp, &vp_info));
   4126         if (vp_info.flags & _BCM_VP_INFO_NETWORK_PORT) {
   4127             if (!network_port) {
   4128                 LOG_ERROR(BSL_LS_BCM_FLOW, (BSL_META_U(unit,
   4129                    "DVP %d is a network port, incorrect encap criteria\n"), 
   4130                     dvp));
   4131                 return BCM_E_PARAM;
   4132             }
   4133         }
   4134     }
   4135 
   4136     soc_mem_lock(unit,mem);
   4137     /* set the match object and attributes and write to memory */
   4138     rv = _bcm_flow_encap_entry_set(unit,info,field,
   4139               num_of_fields,
   4140               _BCM_FLOW_IS_FLEX_VIEW(info)? mem_view: mem,
   4141               entry,network_port);
   4142     soc_mem_unlock(unit,mem);
   4143 
   4144     if (BCM_SUCCESS(rv)) {
   4145         if (!(info->options & BCM_FLOW_ENCAP_OPTION_REPLACE)) {
   4146             bcmi_esw_flow_lock(unit);            
   4147             if ((mem == EGR_VLAN_XLATE_1_DOUBLEm) || (mem == EGR_VLAN_XLATE_1_SINGLEm)) {
   4148                 flow_info->mem_use_cnt[_BCM_FLOW_EVXLT1_INX]++;
   4149             } else if ((mem == EGR_VLAN_XLATE_2_DOUBLEm) || (mem == EGR_VLAN_XLATE_2_SINGLEm)) {
   4150                 flow_info->mem_use_cnt[_BCM_FLOW_EVXLT2_INX]++;
   4151             }
   4152             bcmi_esw_flow_unlock(unit);
   4153         }
   4154     }
   4155 
   4156     return rv;
   4157 }
   4158 
   4159 /*
   4160  * Function:
   4161  *      _bcm_flow_encap_entry_get
   4162  * Purpose:
   4163  *      Get the flow Encap Entry based on the given key
   4164  * Parameters:
   4165  *      unit - (IN) Device Number
   4166  *      info - (IN/OUT) flow_encap configuration info
   4167  *      field - (IN/OUT) array of logical fields
   4168  *      num_of_fields -(IN) the size of the above array
   4169  *      mem  - (IN) memory id
   4170  *      entry - (IN) point to the encap entry
   4171  * Returns:
   4172  *      BCM_E_XXX
   4173  */
   4174 
   4175 STATIC int
   4176 _bcm_flow_encap_entry_get(int unit,
   4177         bcm_flow_encap_config_t *info,
   4178         bcm_flow_logical_field_t *field,
   4179         int num_of_fields,
   4180         soc_mem_t mem,
   4181         uint32 *entry,
   4182         int network_port)
   4183 {
   4184     int index = -1;
   4185     uint32 return_entry[SOC_MAX_MEM_WORDS];
   4186     int rv = BCM_E_NONE;
   4187 
   4188     SOC_IF_ERROR_RETURN(soc_mem_search(unit, mem, MEM_BLOCK_ANY, &index,
   4189               entry, return_entry, 0));
   4190     rv = _bcm_flow_encap_entry_data_get(unit,info,field,num_of_fields,
   4191                     mem,return_entry,network_port);
   4192     BCM_IF_ERROR_RETURN(rv);
   4193     return rv;
   4194 }
   4195 
   4196 STATIC int
   4197 _bcm_flow_encap_entry_valid(int unit, soc_mem_t mem, uint32 *entry, int *valid)
   4198 {
   4199     uint32 base_valid_0 = 0;
   4200     uint32 base_valid_1 = 0;
   4201     uint32 base_valid = 0;
   4202 
   4203     if (INVALIDm == mem) {
   4204         return BCM_E_MEMORY;
   4205     }
   4206 
   4207     if ((NULL == entry) || (NULL == valid)) {
   4208         return BCM_E_PARAM;
   4209     }
   4210     if (soc_mem_field_valid(unit, mem, BASE_VALID_0f)) {
   4211         base_valid_0 = soc_mem_field32_get(unit, mem, entry, BASE_VALID_0f);
   4212     }
   4213     if (soc_mem_field_valid(unit, mem, BASE_VALID_1f)) {
   4214         base_valid_1 = soc_mem_field32_get(unit, mem, entry, BASE_VALID_1f);
   4215     }
   4216     if (soc_mem_field_valid(unit, mem, BASE_VALIDf)) {
   4217         base_valid = soc_mem_field32_get(unit, mem, entry, BASE_VALIDf);
   4218     }
   4219 
   4220     if ((base_valid != 0x1) && ((base_valid_0 == 0) || (base_valid_1 == 0)) ) {
   4221         *valid = FALSE;
   4222     } else {
   4223         *valid = TRUE;
   4224     }
   4225     return BCM_E_NONE;
   4226 }
   4227 
   4228 int
   4229 _bcm_flow_key_is_valid(int unit, soc_mem_t mem_view_id, 
   4230                        uint32 *key, int num_keys) 
   4231 {
   4232     int rv;
   4233     uint32 key_ids[_BCM_FLOW_LOGICAL_FIELD_MAX];
   4234     uint32 cnt = 0;
   4235     int i,j;
   4236     int key_match;
   4237     int num_key_fields;
   4238 
   4239     rv = soc_flow_db_mem_view_field_list_get(unit,
   4240                       mem_view_id,
   4241                       SOC_FLOW_DB_FIELD_TYPE_KEY,
   4242                       _BCM_FLOW_LOGICAL_FIELD_MAX, key_ids, &cnt);
   4243     if (BCM_FAILURE(rv)) {
   4244         return FALSE;
   4245     }
   4246 
   4247     /* don't count the overlapped hash key fields */
   4248     num_key_fields = cnt;
   4249     for (i = 0; i < cnt; i++) {
   4250         if ((key_ids[i] == KEY_0f) || (key_ids[i] == KEY_1f)) {
   4251             num_key_fields--;
   4252         }
   4253     }
   4254 
   4255     if (num_keys != num_key_fields) {
   4256         return FALSE;
   4257     }
   4258 
   4259     key_match = 0;
   4260     for (i = 0; i < num_keys; i++) {
   4261         for (j = 0; j < cnt; j++) {
   4262             if (key[i] == key_ids[j]) {
   4263                 key_match++;
   4264                 break;
   4265             }
   4266         }
   4267     }
   4268     if (key_match != num_key_fields) {
   4269         return FALSE;
   4270     }
   4271     return TRUE;
   4272 }
   4273 
   4274 /*
   4275  * Function   :
   4276  *      _bcm_flow_encap_entry_parse
   4277  * Description   :
   4278  *      Convert the memory entry field data to the flow match configuration
   4279  *      parameters.
   4280  * Parameters   :
   4281  *      unit    - (IN) Device Number
   4282  *      mem     - (IN)  memory id.
   4283  *      entry   - (IN) HW entry.
   4284  *      info    - (OUT) Flow match config descriptor
   4285  *      num_of_fields - (OUT) number of logical fields
   4286  *      field         - (OUT) logical field array
   4287  */
   4288 int
   4289 _bcm_flow_encap_entry_parse(int unit, soc_mem_t mem, uint32 *entry,
   4290                              bcm_flow_encap_config_t *info,
   4291                              uint32 *num_of_fields,
   4292                              bcm_flow_logical_field_t *field)
   4293 {
   4294     int data_type;  
   4295     int key_type;
   4296     soc_field_t vfi_f = 0;
   4297     soc_field_t vrf_f = 0;
   4298     soc_field_t dvp_f = 0;
   4299     soc_field_t dvp_grp_f = 0;
   4300     soc_field_t oif_grp_f = 0;
   4301     uint32 dgpp;
   4302 
   4303     uint32 field_id[_BCM_FLOW_LOGICAL_FIELD_MAX];
   4304     uint32 cnt;
   4305     uint32 data_cnt;
   4306     int i;
   4307     int rv;
   4308     soc_mem_t mem_view_id;
   4309     uint32 tunnel_data[3];
   4310     int tunnel_format;
   4311     int type;
   4312     uint32 dvp = 0;
   4313     uint32 vfi = 0;
   4314     uint32 vrf = 0;
   4315     int network_port;
   4316     uint32 svp = 0;
   4317     
   4318     tunnel_format = EGR_VLAN_XLATE_TUNNEL_DATA_DOUBLEfmt;
   4319     key_type  = 0;
   4320     data_type = 0; 
   4321     network_port = FALSE;
   4322    
   4323     if (SOC_MEM_FIELD_VALID(unit,mem,KEY_TYPEf)) {
   4324         key_type = soc_mem_field32_get(unit, mem, entry, KEY_TYPEf);
   4325     }
   4326     if (SOC_MEM_FIELD_VALID(unit,mem,DATA_TYPEf)) {
   4327         data_type = soc_mem_field32_get(unit, mem, entry, DATA_TYPEf);
   4328     }  
   4329 
   4330     /* find the memory view based on the memory and key type */
   4331     rv = soc_flow_db_mem_to_view_id_get (unit, mem, key_type, data_type,
   4332                     0, NULL, (uint32 *)&mem_view_id);
   4333 
   4334     if (rv != SOC_E_NONE && rv != SOC_E_NOT_FOUND) {
   4335         return rv;
   4336     }
   4337 
   4338     if (rv == SOC_E_NOT_FOUND) {  /* fixed view */
   4339         rv = SOC_E_NONE;
   4340         switch (key_type) {
   4341             case _BCM_FLOW_ENCAP_L2GRE_KEY_TYPE_VFI:
   4342                 info->criteria = BCM_FLOW_ENCAP_CRITERIA_VFI;
   4343                 info->valid_elements |= BCM_FLOW_ENCAP_VPN_VALID;
   4344                 info->flow_handle = SOC_FLOW_DB_FLOW_ID_LEGACY_L2GRE;
   4345                 network_port = TRUE;
   4346                 break;
   4347 
   4348             case _BCM_FLOW_ENCAP_L2GRE_KEY_TYPE_VFI_DVP:
   4349                 info->criteria = BCM_FLOW_ENCAP_CRITERIA_VFI_DVP;
   4350                 info->valid_elements |= BCM_FLOW_ENCAP_VPN_VALID |
   4351                                         BCM_FLOW_ENCAP_FLOW_PORT_VALID;
   4352                 info->flow_handle = SOC_FLOW_DB_FLOW_ID_LEGACY_L2GRE;
   4353                 network_port = TRUE;
   4354                 break;
   4355 
   4356             case _BCM_FLOW_ENCAP_VXLAN_KEY_TYPE_VFI:
   4357                 info->criteria = BCM_FLOW_ENCAP_CRITERIA_VFI;
   4358                 info->valid_elements |= BCM_FLOW_ENCAP_VPN_VALID;
   4359                 info->flow_handle = SOC_FLOW_DB_FLOW_ID_LEGACY_VXLAN;
   4360                 network_port = TRUE;
   4361                 break;
   4362 
   4363             case _BCM_FLOW_ENCAP_VXLAN_KEY_TYPE_VFI_DVP:
   4364                 info->criteria = BCM_FLOW_ENCAP_CRITERIA_VFI_DVP;
   4365                 info->valid_elements |= BCM_FLOW_ENCAP_VPN_VALID |
   4366                                         BCM_FLOW_ENCAP_FLOW_PORT_VALID;
   4367                 info->flow_handle = SOC_FLOW_DB_FLOW_ID_LEGACY_VXLAN;
   4368                 network_port = TRUE;
   4369                 break;
   4370             case _BCM_FLOW_ENCAP_KEY_TYPE_VFI_DVP_GROUP:
   4371                 info->criteria = BCM_FLOW_ENCAP_CRITERIA_VFI_DVP_GROUP;
   4372                 info->valid_elements |= BCM_FLOW_ENCAP_VPN_VALID |
   4373                                         BCM_FLOW_ENCAP_DVP_GROUP_VALID;
   4374                 if (soc_mem_field32_get(unit, mem, entry, 
   4375                                          VFI_DVP_GROUP__DATA_OVERLAY_TYPEf)) {
   4376                     /* xlate data */
   4377                     
   4378                 } else {  /* tunnal data */
   4379                     soc_mem_field_get(unit, mem, entry,  
   4380                               VFI_DVP_GROUP__TUNNEL_DATAf, tunnel_data);
   4381                     type = soc_format_field32_get(unit,tunnel_format,
   4382                                     tunnel_data, TUNNEL_HEADER_DATA_TYPEf);
   4383                     if (type == 1) {
   4384                         info->flow_handle = SOC_FLOW_DB_FLOW_ID_LEGACY_L2GRE;
   4385                         network_port = TRUE;
   4386                         info->vnid = soc_format_field32_get(unit,tunnel_format,
   4387                                         tunnel_data, VPNIDf);
   4388                     } else if (type == 2) {
   4389                         info->flow_handle = SOC_FLOW_DB_FLOW_ID_LEGACY_VXLAN;
   4390                         network_port = TRUE;
   4391                         info->vnid = soc_format_field32_get(unit,tunnel_format,
   4392                                    tunnel_data, VN_IDf);
   4393                     }
   4394                 }
   4395                 break;
   4396 
   4397             case _BCM_FLOW_ENCAP_KEY_TYPE_VRF_MAPPING:
   4398                 info->criteria = BCM_FLOW_ENCAP_CRITERIA_VRF_MAPPING;
   4399                 info->valid_elements |= BCM_FLOW_ENCAP_VPN_VALID;
   4400                 network_port = TRUE;
   4401                 soc_mem_field_get(unit, mem, entry, 
   4402                             VRF_MAPPING__TUNNEL_DATAf, tunnel_data);
   4403                 type = soc_format_field32_get(unit,tunnel_format,tunnel_data,
   4404                                 TUNNEL_HEADER_DATA_TYPEf);
   4405                 if (type == 1) {
   4406                     info->flow_handle = SOC_FLOW_DB_FLOW_ID_LEGACY_L2GRE;
   4407                     info->vnid = soc_format_field32_get(unit,tunnel_format,
   4408                                     tunnel_data, VPNIDf);
   4409                 } else if (type == 2) {
   4410                     info->flow_handle = SOC_FLOW_DB_FLOW_ID_LEGACY_VXLAN;
   4411                     info->vnid = soc_format_field32_get(unit,tunnel_format,
   4412                                    tunnel_data, VN_IDf);
   4413                 }
   4414                 break;
   4415 
   4416             case _BCM_FLOW_ENCAP_KEY_TYPE_VLAN_XLATE_VFI:
   4417                 info->criteria = BCM_FLOW_ENCAP_CRITERIA_VFI_DVP;
   4418                 info->valid_elements |= BCM_FLOW_ENCAP_VPN_VALID |
   4419                                         BCM_FLOW_ENCAP_FLOW_PORT_VALID;
   4420                 break;
   4421 
   4422             default:
   4423                 /* not used by the flow_match functions */
   4424                 return BCM_E_NOT_FOUND;
   4425                 break;
   4426          }
   4427     } else {  /* flex view found */
   4428         soc_flow_db_mem_view_info_t vinfo;
   4429         uint32 vfi_dvp_ids[2];
   4430         uint32 vfi_grp_ids[2];
   4431         uint32 vfi_id[1]; 
   4432         uint32 dvp_id[1]; 
   4433         uint32 oif_id[1]; 
   4434         uint32 vrf_id[1];
   4435         uint32 svp_dvp_ids[2];
   4436 
   4437         /* find the memory view info */
   4438         rv = soc_flow_db_mem_view_info_get(unit, mem_view_id, &vinfo);
   4439         SOC_IF_ERROR_RETURN(rv);
   4440 
   4441         mem = mem_view_id;
   4442         vfi_dvp_ids[0] = VFIf;
   4443         vfi_dvp_ids[1] = DVPf;
   4444 
   4445         vfi_grp_ids[0] = VFIf;
   4446         vfi_grp_ids[1] = VT_DVP_GROUP_IDf;
   4447 
   4448         svp_dvp_ids[0] = SVPf;
   4449         svp_dvp_ids[1] = DVPf;
   4450 
   4451         vfi_id[0] = VFIf; 
   4452         dvp_id[0] = DVPf; 
   4453         oif_id[0] = L3_OIFf; 
   4454         vrf_id[0] = VRFf; 
   4455         if (_bcm_flow_key_is_valid(unit, mem_view_id, vfi_dvp_ids, 2)) { 
   4456             info->criteria = BCM_FLOW_ENCAP_CRITERIA_VFI_DVP;
   4457             info->valid_elements |= BCM_FLOW_ENCAP_VPN_VALID |
   4458                                     BCM_FLOW_ENCAP_FLOW_PORT_VALID;
   4459         } else if (_bcm_flow_key_is_valid(unit, mem_view_id, vfi_grp_ids, 2)) { 
   4460              info->criteria = BCM_FLOW_ENCAP_CRITERIA_VFI_DVP_GROUP;
   4461             info->valid_elements |= BCM_FLOW_ENCAP_VPN_VALID |
   4462                                     BCM_FLOW_ENCAP_DVP_GROUP_VALID;
   4463         } else if (_bcm_flow_key_is_valid(unit, mem_view_id, vfi_id, 1)) { 
   4464             info->criteria = BCM_FLOW_ENCAP_CRITERIA_VFI;
   4465             info->valid_elements |= BCM_FLOW_ENCAP_VPN_VALID;
   4466         } else if (_bcm_flow_key_is_valid(unit, mem_view_id, dvp_id, 1)) { 
   4467             info->criteria = BCM_FLOW_ENCAP_CRITERIA_DVP;
   4468             info->valid_elements |= BCM_FLOW_ENCAP_FLOW_PORT_VALID;
   4469         } else if (_bcm_flow_key_is_valid(unit, mem_view_id, oif_id, 1)) { 
   4470             info->criteria = BCM_FLOW_ENCAP_CRITERIA_L3_INTF;
   4471             info->valid_elements |= BCM_FLOW_ENCAP_INTF_VALID;
   4472         } else if (_bcm_flow_key_is_valid(unit, mem_view_id, vrf_id, 1)) { 
   4473             info->criteria = BCM_FLOW_ENCAP_CRITERIA_VRF_MAPPING;
   4474             info->valid_elements |= BCM_FLOW_ENCAP_VPN_VALID;
   4475         } else if (_bcm_flow_key_is_valid(unit, mem_view_id, svp_dvp_ids, 2)) { 
   4476             info->criteria = BCM_FLOW_ENCAP_CRITERIA_SVP_DVP;
   4477             info->valid_elements |= BCM_FLOW_ENCAP_FLOW_PORT_VALID |
   4478                                     BCM_FLOW_ENCAP_SRC_FLOW_PORT_VALID;
   4479         } else {
   4480             info->criteria = BCM_FLOW_ENCAP_CRITERIA_FLEX;
   4481             info->valid_elements |= BCM_FLOW_ENCAP_FLEX_KEY_VALID;
   4482         }
   4483         rv = _bcm_flow_mem_view_to_flow_info_get(unit, mem_view_id,
   4484                SOC_FLOW_DB_FUNC_ENCAP_ID,
   4485                &info->flow_handle, &info->flow_option, 1);
   4486         SOC_IF_ERROR_RETURN(rv);
   4487 
   4488         network_port = TRUE;
   4489     }
   4490 
   4491     if (_BCM_FLOW_IS_FLEX_VIEW(info)) {
   4492         vfi_f     = VFIf;
   4493         dvp_f     = DVPf;
   4494         dvp_grp_f = VT_DVP_GROUP_IDf;
   4495         vrf_f     = VRFf;
   4496         oif_grp_f = VT_L3OIF_GROUP_IDf;
   4497     } else {
   4498         dvp_grp_f = VFI_DVP_GROUP__VT_DVP_GROUP_IDf;
   4499         oif_grp_f = VRF_MAPPING__VT_L3OIF_GROUP_IDf;
   4500         if (info->flow_handle == SOC_FLOW_DB_FLOW_ID_LEGACY_VXLAN) {
   4501             if (soc_feature(unit, soc_feature_vxlan_decoupled_mode) &&
   4502                 (mem == EGR_VLAN_XLATE_1_SINGLEm)) {
   4503                 vfi_f = VXLAN_VFI_FLEX__VFIf;
   4504                 dvp_f = VXLAN_VFI_FLEX__DVPf;
   4505             } else {
   4506                 vfi_f = VXLAN_VFI__VFIf;
   4507                 dvp_f = VXLAN_VFI__DVPf;
   4508             }
   4509         } else if (info->flow_handle == SOC_FLOW_DB_FLOW_ID_LEGACY_L2GRE) {
   4510             vfi_f = L2GRE_VFI__VFIf;
   4511             dvp_f = L2GRE_VFI__DVPf;
   4512         } else {
   4513             /* access side: VLAN_XLATE_VFI */
   4514             vfi_f = VLAN_XLATE_VFI__VFIf;
   4515             dvp_f = VLAN_XLATE_VFI__DVPf;
   4516         }
   4517     }
   4518 
   4519     /* retrieve the key fields */
   4520     if (info->criteria == BCM_FLOW_ENCAP_CRITERIA_VFI) {
   4521         vfi = soc_mem_field32_get(unit,mem, entry, vfi_f);
   4522         _BCM_FLOW_VPN_SET(info->vpn,_BCM_VPN_TYPE_VFI,vfi);
   4523 
   4524     }  else if (info->criteria == BCM_FLOW_ENCAP_CRITERIA_VFI_DVP) {
   4525         vfi = soc_mem_field32_get(unit, mem, entry, vfi_f);
   4526         _BCM_FLOW_VPN_SET(info->vpn,_BCM_VPN_TYPE_VFI,vfi);
   4527         dvp = soc_mem_field32_get(unit, mem, entry, dvp_f);
   4528         _SHR_GPORT_FLOW_PORT_ID_SET(info->flow_port,dvp);
   4529 
   4530     } else if (info->criteria == BCM_FLOW_ENCAP_CRITERIA_VFI_DVP_GROUP) {
   4531         if (!_BCM_FLOW_IS_FLEX_VIEW(info)) {
   4532             vfi_f = VFI_DVP_GROUP__VFIf;
   4533         }
   4534         vfi = soc_mem_field32_get(unit,mem, entry, vfi_f);
   4535         _BCM_FLOW_VPN_SET(info->vpn,_BCM_VPN_TYPE_VFI,vfi);
   4536         info->dvp_group = soc_mem_field32_get(unit,mem, entry, 
   4537                                                  dvp_grp_f);
   4538     } else if (info->criteria == BCM_FLOW_ENCAP_CRITERIA_VRF_MAPPING) {
   4539         /* KEY : VRF,VT_DVP_GROUP_ID,VT_L3_OIF_GROUP_ID
   4540          * VT_DVP_GROUP_ID    : from EGR_DVP_ATTRIBUTEm
   4541          * VT_L3_OIF_GROUP_ID : from EGR_L3_INTFm
   4542          */
   4543         if (!_BCM_FLOW_IS_FLEX_VIEW(info)) {
   4544             vrf_f = VRF_MAPPING__VRFf;
   4545             dvp_grp_f = VRF_MAPPING__VT_DVP_GROUP_IDf;
   4546             oif_grp_f = VRF_MAPPING__VT_L3OIF_GROUP_IDf;
   4547         }
   4548         vrf = soc_mem_field32_get(unit,mem, entry, vrf_f);
   4549         _BCM_FLOW_VPN_SET(info->vpn,_BCM_VPN_TYPE_L3,vrf);
   4550         info->dvp_group = soc_mem_field32_get(unit,mem, entry,dvp_grp_f);
   4551         info->oif_group = soc_mem_field32_get(unit,mem, entry,oif_grp_f);
   4552     } else if (info->criteria == BCM_FLOW_ENCAP_CRITERIA_L3_INTF) {
   4553         /* only apply to flex view */
   4554         if (!_BCM_FLOW_IS_FLEX_VIEW(info)) {
   4555             return BCM_E_PARAM;
   4556         }
   4557         info->intf_id = soc_mem_field32_get(unit,mem, entry, L3_OIFf);
   4558 
   4559     } else if (info->criteria == BCM_FLOW_ENCAP_CRITERIA_DVP) {
   4560         /* only apply to flex view */
   4561         if (!_BCM_FLOW_IS_FLEX_VIEW(info)) {
   4562             return BCM_E_PARAM;
   4563         }
   4564         dvp = soc_mem_field32_get(unit,mem, entry, dvp_f);
   4565         _SHR_GPORT_FLOW_PORT_ID_SET(info->flow_port,dvp);
   4566 
   4567     } else if (info->criteria == BCM_FLOW_ENCAP_CRITERIA_SVP_DVP) {
   4568         /* only apply to flex view */
   4569         if (!_BCM_FLOW_IS_FLEX_VIEW(info)) {
   4570             return BCM_E_PARAM;
   4571         }
   4572         dvp = soc_mem_field32_get(unit,mem, entry, dvp_f);
   4573         _SHR_GPORT_FLOW_PORT_ID_SET(info->flow_port, dvp);
   4574         svp = soc_mem_field32_get(unit,mem, entry, SVPf);
   4575         _SHR_GPORT_FLOW_PORT_ID_SET(info->src_flow_port, svp);
   4576 
   4577     } else if (info->criteria == BCM_FLOW_ENCAP_CRITERIA_FLEX) {
   4578         rv = soc_flow_db_mem_view_field_list_get(unit,
   4579                              mem,
   4580                              SOC_FLOW_DB_FIELD_TYPE_LOGICAL_KEY,
   4581                              _BCM_FLOW_LOGICAL_FIELD_MAX, field_id, &cnt);
   4582         SOC_IF_ERROR_RETURN(rv);
   4583         if (cnt >= _BCM_FLOW_LOGICAL_FIELD_MAX) {
   4584             return BCM_E_PARAM;
   4585         }
   4586         for (i = 0; i < cnt; i++) {
   4587             field[i].id = field_id[i];
   4588             field[i].value = soc_mem_field32_get(unit,mem, entry,
   4589                      field[i].id);
   4590         }
   4591         if (SOC_MEM_FIELD_VALID(unit,mem,vfi_f)) {
   4592             vfi = soc_mem_field32_get(unit,mem, entry, vfi_f);
   4593             _BCM_FLOW_VPN_SET(info->vpn,_BCM_VPN_TYPE_VFI,vfi);
   4594         }
   4595         if (SOC_MEM_FIELD_VALID(unit,mem,dvp_f)) {
   4596             dvp = soc_mem_field32_get(unit,mem, entry, dvp_f);
   4597             _SHR_GPORT_FLOW_PORT_ID_SET(info->flow_port,dvp);
   4598         } else {
   4599             if (SOC_MEM_FIELD_VALID(unit,mem,DGPPf)) {
   4600                 dgpp = soc_mem_field32_get(unit,mem, entry, DGPPf);
   4601                 _SHR_GPORT_MODPORT_SET(info->flow_port,
   4602                       dgpp >> _BCM_FLOW_MODID_SHIFTER, 
   4603                       dgpp & _BCM_FLOW_PORT_MASK);
   4604             }
   4605         }
   4606         if (SOC_MEM_FIELD_VALID(unit,mem,dvp_grp_f)) {
   4607             info->dvp_group = soc_mem_field32_get(unit,mem, entry, 
   4608                                                      dvp_grp_f);
   4609         }
   4610         if (SOC_MEM_FIELD_VALID(unit,mem,oif_grp_f)) {
   4611             info->oif_group = soc_mem_field32_get(unit,mem, entry, 
   4612                                                      oif_grp_f);
   4613         }
   4614         if (SOC_MEM_FIELD_VALID(unit,mem,vrf_f)) {
   4615             vrf = soc_mem_field32_get(unit,mem, entry, vrf_f);
   4616             _BCM_FLOW_VPN_SET(info->vpn,_BCM_VPN_TYPE_L3,vrf);
   4617         }
   4618         if (SOC_MEM_FIELD_VALID(unit,mem,L3_OIFf)) {
   4619             info->intf_id = soc_mem_field32_get(unit,mem, entry, L3_OIFf);
   4620         }
   4621         if (SOC_MEM_FIELD_VALID(unit, mem, CLASS_IDf)) {
   4622             info->class_id = soc_mem_field32_get(unit, mem, entry, CLASS_IDf);
   4623         }
   4624         if (SOC_MEM_FIELD_VALID(unit, mem, SVPf)) {
   4625             svp = soc_mem_field32_get(unit, mem, entry, SVPf);
   4626             _SHR_GPORT_FLOW_PORT_ID_SET(info->src_flow_port, svp);
   4627         }
   4628     }
   4629 
   4630     if (info->criteria != BCM_FLOW_ENCAP_CRITERIA_FLEX) {
   4631         cnt = 0;
   4632     }
   4633 
   4634     data_cnt = 0;
   4635     if (_BCM_FLOW_IS_FLEX_VIEW(info)) {
   4636         /* retrieve the data fields, cnt: number of key fields */
   4637         rv = soc_flow_db_mem_view_field_list_get(unit,
   4638                    mem,
   4639                    SOC_FLOW_DB_FIELD_TYPE_LOGICAL_POLICY_DATA,
   4640                    _BCM_FLOW_LOGICAL_FIELD_MAX - cnt, field_id, &data_cnt);
   4641         BCM_IF_ERROR_RETURN(rv);
   4642         if (data_cnt >= _BCM_FLOW_LOGICAL_FIELD_MAX - cnt) {
   4643             return BCM_E_PARAM;
   4644         }
   4645         for (i = 0; i < data_cnt; i++) {
   4646             field[i+cnt].id = field_id[i];
   4647         }
   4648     }
   4649     rv = _bcm_flow_encap_entry_data_get(unit, info, field+cnt,
   4650                     data_cnt, mem, entry,network_port);
   4651     BCM_IF_ERROR_RETURN(rv);
   4652     *num_of_fields = cnt + data_cnt;
   4653     if (data_cnt) {
   4654         info->valid_elements |= BCM_FLOW_ENCAP_FLEX_DATA_VALID;
   4655     }
   4656     return BCM_E_NONE;
   4657 }
   4658 
   4659 /*
   4660  * Function:
   4661  *      _bcm_flow_match_traverse_mem
   4662  * Purpose:
   4663  *      Read the given memory table and call the user callback function on
   4664  *      each entry.
   4665  * Parameters:
   4666  *      unit    - (IN) Device Number
   4667  *      mem     - (IN) the memory id
   4668  *      cb      - (IN) user callback function
   4669  *      user_data     - (IN) user context data
   4670  * Returns:
   4671  *      BCM_E_XXX
   4672  */
   4673 
   4674 STATIC int
   4675 _bcm_flow_encap_traverse_mem(int unit, soc_mem_t mem,
   4676                              bcm_flow_encap_traverse_cb cb,
   4677                              void *user_data)
   4678 {
   4679     /* Indexes to iterate over memories, chunks and entries */
   4680     int             chnk_idx, ent_idx, chnk_idx_max, mem_idx_max;
   4681     int             buf_size, chunksize, chnk_end;
   4682     /* Buffer to store chunk of table we currently work on */
   4683     uint32          *vt_tbl_chnk;
   4684     uint32          *entry;
   4685     int             valid, rv = BCM_E_NONE;
   4686     bcm_flow_encap_config_t info;
   4687     uint32 num_of_fields = _BCM_FLOW_LOGICAL_FIELD_MAX;
   4688     bcm_flow_logical_field_t field[_BCM_FLOW_LOGICAL_FIELD_MAX];
   4689 
   4690     if (INVALIDm == mem) {
   4691         return BCM_E_MEMORY;
   4692     }
   4693     if (!soc_mem_index_count(unit, mem)) {
   4694         return BCM_E_NONE;
   4695     }
   4696 
   4697     chunksize = soc_property_get(unit, spn_VLANDELETE_CHUNKS,
   4698                                  VLAN_MEM_CHUNKS_DEFAULT);
   4699 
   4700     buf_size = 4 * SOC_MAX_MEM_FIELD_WORDS * chunksize;
   4701     vt_tbl_chnk = soc_cm_salloc(unit, buf_size, "flow encap traverse");
   4702     if (NULL == vt_tbl_chnk) {
   4703         return BCM_E_MEMORY;
   4704     }
   4705 
   4706     mem_idx_max = soc_mem_index_max(unit, mem);
   4707     for (chnk_idx = soc_mem_index_min(unit, mem);
   4708          chnk_idx <= mem_idx_max;
   4709          chnk_idx += chunksize) {
   4710         sal_memset((void *)vt_tbl_chnk, 0, buf_size);
   4711 
   4712         chnk_idx_max =
   4713             ((chnk_idx + chunksize) <= mem_idx_max) ?
   4714             chnk_idx + chunksize - 1: mem_idx_max;
   4715 
   4716         rv = soc_mem_read_range(unit, mem, MEM_BLOCK_ANY,
   4717                                 chnk_idx, chnk_idx_max, vt_tbl_chnk);
   4718         if (SOC_FAILURE(rv)) {
   4719             break;
   4720         }
   4721         chnk_end = (chnk_idx_max - chnk_idx);
   4722         for (ent_idx = 0 ; ent_idx <= chnk_end; ent_idx ++) {
   4723             entry =
   4724                 soc_mem_table_idx_to_pointer(unit, mem, uint32 *,
   4725                                              vt_tbl_chnk, ent_idx);
   4726             rv = _bcm_flow_encap_entry_valid(unit, mem, entry, &valid);
   4727             if (BCM_FAILURE(rv)) {
   4728                 break;
   4729             }
   4730             if (!valid) {
   4731                 continue;
   4732             }
   4733             bcm_flow_encap_config_t_init(&info);
   4734             rv = _bcm_flow_encap_entry_parse(unit, mem, entry, &info,
   4735                     &num_of_fields,field);
   4736             if (rv == BCM_E_NOT_FOUND) { /* for entries not exposed to user */
   4737                 continue;
   4738             } else if (BCM_FAILURE(rv)) {
   4739                 break;
   4740             }
   4741             rv = cb(unit, &info, num_of_fields,field,user_data);
   4742             if (BCM_FAILURE(rv)) {
   4743                 break;
   4744             }
   4745         }
   4746     }
   4747     soc_cm_sfree(unit, vt_tbl_chnk);
   4748     return rv;
   4749 }
   4750 
   4751 /*
   4752  * Function:
   4753  *      bcmi_esw_flow_encap_delete
   4754  * Purpose:
   4755  *      Delete a flow encap entry based on the given key
   4756  * Parameters:
   4757  *      unit    - (IN) Device Number
   4758  *      info    - (IN) Flow encap config descriptor
   4759  *      num_of_fields - (IN) number of logical fields
   4760  *      field         - (IN) logical field array
   4761  * Returns:
   4762  *      BCM_E_XXX
   4763  */
   4764 
   4765 int bcmi_esw_flow_encap_delete(
   4766     int unit,
   4767     bcm_flow_encap_config_t *info,
   4768     uint32 num_of_fields,
   4769     bcm_flow_logical_field_t *field)
   4770 {
   4771     soc_mem_t mem;
   4772     uint32 entry[SOC_MAX_MEM_WORDS];
   4773     int network_port;
   4774     _bcm_flow_bookkeeping_t *flow_info;
   4775     soc_mem_t mem_view;
   4776 
   4777     if (info == NULL) {
   4778         return BCM_E_PARAM;
   4779     }
   4780 
   4781     flow_info = FLOW_INFO(unit);
   4782 
   4783     sal_memset(entry, 0, sizeof(entry));
   4784     BCM_IF_ERROR_RETURN(_bcm_flow_encap_key_set(unit,info,field,
   4785                         num_of_fields,entry,&mem, &mem_view, &network_port));
   4786     BCM_IF_ERROR_RETURN(_bcm_flow_encap_profile_delete(unit, info, mem, mem_view, entry));
   4787     BCM_IF_ERROR_RETURN(soc_mem_delete(unit, mem, MEM_BLOCK_ANY, entry));
   4788 
   4789     bcmi_esw_flow_lock(unit);
   4790     if ((mem == EGR_VLAN_XLATE_1_DOUBLEm) || (mem == EGR_VLAN_XLATE_1_SINGLEm)) {
   4791         if (flow_info->mem_use_cnt[_BCM_FLOW_EVXLT1_INX]) {
   4792             flow_info->mem_use_cnt[_BCM_FLOW_EVXLT1_INX]--;
   4793         }
   4794     } else if ((mem == EGR_VLAN_XLATE_2_DOUBLEm)  || (mem == EGR_VLAN_XLATE_2_SINGLEm)) {
   4795         if (flow_info->mem_use_cnt[_BCM_FLOW_EVXLT2_INX]) {
   4796             flow_info->mem_use_cnt[_BCM_FLOW_EVXLT2_INX]--;
   4797         }
   4798     }
   4799     bcmi_esw_flow_unlock(unit);
   4800 
   4801     return BCM_E_NONE;
   4802 }
   4803 
   4804 /*
   4805  * Function:
   4806  *      bcmi_esw_flow_encap_get
   4807  * Purpose:
   4808  *      Delete a flow encap entry based on the given key
   4809  * Parameters:
   4810  *      unit    - (IN) Device Number
   4811  *      info    - (IN) Flow encap config descriptor
   4812  *      num_of_fields - (IN) number of logical fields
   4813  *      field         - (IN) logical field array
   4814  * Returns:
   4815  *      BCM_E_XXX
   4816  */
   4817 
   4818 int bcmi_esw_flow_encap_get(
   4819     int unit,
   4820     bcm_flow_encap_config_t *info,
   4821     uint32 num_of_fields,
   4822     bcm_flow_logical_field_t *field)
   4823 {
   4824     soc_mem_t mem;
   4825     soc_mem_t mem_view;
   4826     uint32 entry[SOC_MAX_MEM_WORDS];
   4827     int network_port;
   4828 
   4829     if (info == NULL) {
   4830         return BCM_E_PARAM;
   4831     }
   4832 
   4833     sal_memset(entry, 0, sizeof(entry));
   4834     BCM_IF_ERROR_RETURN(_bcm_flow_encap_key_set(unit,info,field,
   4835                         num_of_fields,entry,&mem,&mem_view,&network_port));
   4836 
   4837     BCM_IF_ERROR_RETURN(_bcm_flow_encap_entry_get(unit,info,field,
   4838               num_of_fields,
   4839               _BCM_FLOW_IS_FLEX_VIEW(info)? mem_view: mem,
   4840               entry,network_port));
   4841     return BCM_E_NONE;
   4842 }
   4843 
   4844 /*
   4845  * Function:
   4846  *      bcmi_esw_flow_encap_traverse
   4847  * Purpose:
   4848  *      Traverse flow encap entries. Call the user callback function on each 
   4849  *      entry. 
   4850  * Parameters:
   4851  *      unit    - (IN) Device Number
   4852  *      info    - (IN) Flow encap config descriptor
   4853  *      num_of_fields - (IN) number of logical fields
   4854  *      field         - (IN) logical field array
   4855  *      cb            - (IN) user callback function
   4856  *      user_data     - (IN) user context data
   4857  * Returns:
   4858  *      BCM_E_XXX
   4859  */
   4860 
   4861 int bcmi_esw_flow_encap_traverse(
   4862     int unit,
   4863     bcm_flow_encap_traverse_cb cb,   
   4864     void *user_data)
   4865 {
   4866     soc_mem_t mem;
   4867     int rv;
   4868     _bcm_flow_bookkeeping_t *flow_info;
   4869 
   4870     if (cb == NULL) {
   4871         return BCM_E_PARAM;
   4872     }
   4873 
   4874     flow_info = FLOW_INFO(unit);
   4875 
   4876     /* traverse the first vlan_xlate */
   4877     if (flow_info->mem_use_cnt[_BCM_FLOW_EVXLT1_INX]) {
   4878         mem = EGR_VLAN_XLATE_1_DOUBLEm;
   4879         rv = _bcm_flow_encap_traverse_mem(unit, mem, cb, user_data);
   4880         BCM_IF_ERROR_RETURN(rv);
   4881     }
   4882 
   4883     if (flow_info->mem_use_cnt[_BCM_FLOW_EVXLT1_INX]) {
   4884         if (soc_feature(unit, soc_feature_vxlan_decoupled_mode)) {
   4885             mem = EGR_VLAN_XLATE_1_SINGLEm;
   4886             rv = _bcm_flow_encap_traverse_mem(unit, mem, cb, user_data);
   4887             BCM_IF_ERROR_RETURN(rv);
   4888         }
   4889     }
   4890 
   4891     /* traverse the second vlan_xlate */
   4892     if (flow_info->mem_use_cnt[_BCM_FLOW_EVXLT2_INX]) {
   4893         mem = EGR_VLAN_XLATE_2_DOUBLEm;
   4894         rv = _bcm_flow_encap_traverse_mem(unit, mem, cb, user_data);
   4895         BCM_IF_ERROR_RETURN(rv);
   4896     }
   4897     return BCM_E_NONE;
   4898 }
   4899 
   4900 /*
   4901  * Function:
   4902  *    bcmi_esw_flow_mshg_prune_egress_set
   4903  * Parameters:
   4904  *    unit          (IN)device number
   4905  *    src_group_id  (IN) source split horizon group ID
   4906  *    dst_group_id  (IN) destination split horizon group ID
   4907  *    prune_enable  (IN) enable or disable pruning
   4908  * Purpose
   4909  *    This API is used to enable/disable egress pruning for Ipv6 VxLAN flow
   4910  * Returns:
   4911  *    BCM_E_XXX
   4912  */
   4913 int
   4914 bcmi_esw_flow_mshg_prune_egress_set(
   4915         int unit,
   4916         bcm_switch_network_group_t src_group_id,
   4917         bcm_switch_network_group_t dst_group_id,
   4918         int prune_enable)
   4919 {
   4920     bcm_flow_handle_t flow_handle = 0;
   4921     bcm_flow_option_id_t flow_option = 0;
   4922     soc_mem_t mem_view_id = 0;
   4923     soc_mem_t mem_id = 0;
   4924     int index = 0;
   4925     uint32 entry[SOC_MAX_MEM_WORDS];
   4926     uint32 return_entry[SOC_MAX_MEM_WORDS];
   4927     soc_flow_db_mem_view_info_t mem_view_info;
   4928     uint32 src_group_id_f = 0;
   4929     uint32 dst_group_id_f = 0;
   4930     int entry_exist = 0;
   4931     int rv = BCM_E_NONE;
   4932 
   4933     BCM_IF_ERROR_RETURN(soc_flow_db_flow_handle_get(unit ,"VXLAN", &flow_handle));
   4934     BCM_IF_ERROR_RETURN(soc_flow_db_flow_option_id_get(unit, flow_handle,
   4935         "LOOKUP_SPLIT_HORIZON_GROUPS_ASSIGN_PASS_ACTION", &flow_option));
   4936     BCM_IF_ERROR_RETURN(soc_flow_db_ffo_to_mem_view_id_get(unit, flow_handle,
   4937              flow_option,
   4938              SOC_FLOW_DB_FUNC_ENCAP_ID, (uint32 *)&mem_view_id));
   4939     BCM_IF_ERROR_RETURN(soc_flow_db_mem_view_logical_field_id_get(unit,
   4940             flow_handle, "SVP_NETWORK_GROUP", &src_group_id_f));
   4941     BCM_IF_ERROR_RETURN(soc_flow_db_mem_view_logical_field_id_get(unit,
   4942             flow_handle, "DVP_NETWORK_GROUP", &dst_group_id_f));
   4943 
   4944     sal_memset(entry, 0, sizeof(entry));
   4945     soc_flow_db_mem_view_entry_init(unit, mem_view_id, entry);
   4946     soc_mem_field32_set(unit, mem_view_id, entry, src_group_id_f, src_group_id);
   4947     soc_mem_field32_set(unit, mem_view_id, entry, dst_group_id_f, dst_group_id);
   4948     sal_memset(&mem_view_info, 0, sizeof(mem_view_info));
   4949     BCM_IF_ERROR_RETURN(soc_flow_db_mem_view_info_get(unit, mem_view_id,
   4950                             &mem_view_info));
   4951     mem_id = mem_view_info.mem;
   4952     rv = soc_mem_search(unit, mem_id, MEM_BLOCK_ANY, &index, entry,
   4953                             return_entry, 0);
   4954     if (BCM_E_NONE == rv) {
   4955         entry_exist = 1;
   4956     } else if (BCM_E_NOT_FOUND == rv) {
   4957         entry_exist = 0;
   4958     } else {
   4959         return rv;
   4960     }
   4961 
   4962     if (prune_enable) {
   4963         sal_memset(entry, 0, sizeof(entry));
   4964     }
   4965     if (entry_exist) {
   4966         rv = soc_mem_write(unit, mem_id, MEM_BLOCK_ALL, index, entry);
   4967     } else {
   4968         rv = soc_mem_insert(unit, mem_id, MEM_BLOCK_ALL, entry);
   4969     }
   4970 
   4971     return rv;
   4972 }
   4973 
   4974 /*
   4975  * Function:
   4976  *    bcmi_esw_flow_mshg_prune_egress_init
   4977  * Parameters:
   4978  *    unit          (IN)device number
   4979  * Purpose
   4980  *    Egress pruning for Ipv6 VxLAN flow initialization.
   4981  * Returns:
   4982  *    BCM_E_XXX
   4983  */
   4984 int
   4985 bcmi_esw_flow_mshg_prune_egress_init(int unit)
   4986 {
   4987     bcm_switch_network_group_t src_group_id;
   4988     bcm_switch_network_group_t dst_group_id;
   4989     int rv = BCM_E_NONE;
   4990 
   4991     if (soc_reg_field_valid(unit, VXLAN_IPV6_CONTROLr, MSHG_ENABLEf)) {
   4992         soc_reg_field32_modify(unit, VXLAN_IPV6_CONTROLr, 0, MSHG_ENABLEf, 0x1);
   4993     }
   4994 
   4995     for (dst_group_id = 0; dst_group_id < 8; dst_group_id++) {
   4996         for (src_group_id = 0; src_group_id < 8; src_group_id++) {
   4997             if ((dst_group_id != src_group_id) ||
   4998                 ((src_group_id == 0) && (dst_group_id == 0))) {
   4999                 rv = bcmi_esw_flow_mshg_prune_egress_set(unit, src_group_id,
   5000                         dst_group_id, 0x0);
   5001                 if (rv != BCM_E_NONE) {
   5002                     LOG_ERROR(BSL_LS_BCM_FLOW, (BSL_META_U(unit,
   5003                             "Ipv6 VxLAN flow: %s\n"), bcm_errmsg(rv)));
   5004                     return rv;
   5005                 }
   5006             }
   5007         }
   5008     }
   5009 
   5010     return rv;
   5011 }
   5012 
   5013 
   5014 #endif  /* INCLUDE_L3 */
   5015