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_tunnel.c (145788B)


      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_tunnel.c
      8  * Purpose:     Flex flow Tunnel 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/firebolt.h>
     23 #include <bcm_int/esw/trx.h>
     24 #include <bcm_int/esw/triumph2.h>
     25 #include <bcm_int/esw/virtual.h>
     26 #include <bcm_int/esw/port.h>
     27 #include <bcm_int/esw_dispatch.h>
     28 #include <bcm_int/esw/stack.h>
     29 #include <bcm_int/esw/vpn.h>
     30 #include <bcm_int/esw/flow.h>
     31 #include <soc/esw/flow_db.h>
     32 #include <bcm/flow.h>
     33 #include <bcm_int/esw/vxlan.h>
     34 #include <bcm_int/esw/l2gre.h>
     35 
     36 /* XXXX move to common header file */
     37 #define _BCM_FLOW_TUNNEL_TYPE_L2(_type) \
     38 	(((_type) == bcmTunnelTypeVxlan) || \
     39          ((_type) == bcmTunnelTypeL2Gre) || \
     40          ((_type) == bcmTunnelTypeL2Flex))
     41 
     42 #define _BCM_FLOW_TUNNEL_TYPE_L3(_type) \
     43         (((_type) == bcmTunnelTypeL3Flex) || \
     44          ((_type) == bcmTunnelTypeIp4In4) || \
     45          ((_type) == bcmTunnelTypeIp6In4) || \
     46          ((_type) == bcmTunnelTypeIpAnyIn4) || \
     47          ((_type) == bcmTunnelTypeIp4In6) || \
     48          ((_type) == bcmTunnelTypeIp6In6) || \
     49          ((_type) == bcmTunnelTypeIpAnyIn6) || \
     50          ((_type) == bcmTunnelTypeGre4In4) || \
     51          ((_type) == bcmTunnelTypeGre6In4) || \
     52          ((_type) == bcmTunnelTypeGreAnyIn4) || \
     53          ((_type) == bcmTunnelTypeGre4In6) || \
     54          ((_type) == bcmTunnelTypeGre6In6) || \
     55          ((_type) == bcmTunnelTypeGreAnyIn6))
     56 
     57 #define _BCM_FLOW_TUNNEL_IP_TUNNEL_MAX(unit) \
     58 	 (soc_mem_index_count(unit, EGR_IP_TUNNELm))
     59 
     60 #define _BCM_FLOW_TUNNEL_L2_MAX(unit) \
     61 	 (soc_mem_index_count(unit, EGR_DVP_ATTRIBUTEm))
     62 #define _BCM_FLOW_TUNNEL_L3_MAX(unit) \
     63 	 (soc_mem_index_count(unit, EGR_L3_INTFm))
     64 #define _BCM_FLOW_TUNNEL_TBL_MAX(unit) (_BCM_FLOW_TUNNEL_L2_MAX(unit) + \
     65 			_BCM_FLOW_TUNNEL_L3_MAX(unit)) 
     66 
     67 #define _BCM_FLOW_TUNNEL_ENTRY_DOUBLE_WIDE(_type) ((_type) & 0x8000)
     68 #define _BCM_FLOW_TUNNEL_DATA_TYPE_IPV4     0x1
     69 #define _BCM_FLOW_TUNNEL_DATA_TYPE_IPV6     0xa
     70 #define _BCM_FLOW_IP_TUNNEL_SINGLE_WIDE_WIDTH 310
     71 #define _BCM_FLOW_VXLAN_TUNNEL_TYPE      0x0B
     72 #define _BCM_FLOW_L2GRE_TUNNEL_TYPE      0x7
     73 #define _QUAD_ENTRY_MAX   (4 * SOC_MAX_MEM_WORDS)
     74 #define _BCM_FLOW_DSCP_SEL_ASSIGN_FROM_TABLE     1
     75 #define _BCM_FLOW_DSCP_SEL_COPY_FROM_ZONE        3
     76 #define _BCM_FLOW_DSCP_SEL_MAP_FROM_PHB          2
     77 
     78 #define _BCM_FLOW_TD3_L3_TUNNEL_SINGLE_ENTRY_SIZE \
     79                   sizeof(tunnel_entry_t)
     80 
     81 #define _BCM_FLOW_TUNNEL_ID_IF_INVALID_RETURN(_unit, _id) \
     82     do {                                                 \
     83         if (((_id) < 0) || ((_id) >= _BCM_FLOW_TUNNEL_TBL_MAX(_unit))) { \
     84             return (BCM_E_BADID);                        \
     85         }                                                \
     86     } while(0)
     87 
     88 typedef struct _bcm_flow_tunnel_record_s {
     89     bcm_flow_tunnel_initiator_t *info;
     90     bcm_flow_logical_field_t *field;
     91     int num_of_fields;
     92     soc_mem_t mem_view;
     93 } _bcm_flow_tunnel_record_t;
     94 
     95 STATIC int
     96 _bcm_flow_hw_tunnel_entry_get(int unit, int idx, 
     97             bcm_flow_tunnel_initiator_t *info,
     98             bcm_flow_logical_field_t *field,
     99             uint32 num_of_fields,
    100             uint32 *field_cnt);
    101 
    102  /*
    103   * Function:
    104   *      _bcm_flow_bud_loopback_termination_set
    105   * Purpose:
    106   *      Enable/Disable termination control for loopback port 
    107   *      for classic flow VXLAN/L2GRE BUD node multicast
    108   * Parameters:
    109   *   IN : unit
    110   *   IN : flow_handle
    111   *   IN : enable
    112   * Returns:
    113   *      BCM_E_XXX
    114   */
    115 
    116 STATIC int
    117 _bcm_flow_bud_loopback_termination_set(int unit, uint32 flow_handle, int enable)
    118 {
    119     int i;
    120     int field_num = 1;
    121 
    122     soc_field_t lport_fields[] = {
    123         VXLAN_TERMINATION_ALLOWEDf,
    124     };
    125     uint32 lport_values[] = {
    126         0x1,  /* VXLAN_TERMINATION_ALLOWEDf */
    127     };
    128 
    129     if (flow_handle == SOC_FLOW_DB_FLOW_ID_LEGACY_VXLAN) {
    130         lport_fields[0] = VXLAN_TERMINATION_ALLOWEDf;
    131     } else if (flow_handle == SOC_FLOW_DB_FLOW_ID_LEGACY_L2GRE) {
    132         lport_fields[0] = L2GRE_TERMINATION_ALLOWEDf;
    133     } else {
    134         /* flex vxlan */
    135         lport_fields[0] = VXLAN_TERMINATION_ALLOWEDf;
    136     }
    137 
    138     lport_values[0] = enable ? 1: 0;
    139 
    140     /* update the default profile 0 referenced by STM table. 
    141      * Packet from loopback port will use pp port number as index to STM 
    142      */
    143     for (i = 0; i < field_num; i++) {
    144         SOC_IF_ERROR_RETURN(soc_mem_field32_modify(unit, LPORT_TABm, 0,
    145                                 lport_fields[i], lport_values[i]));
    146     }
    147     return BCM_E_NONE;
    148 }
    149 
    150 int
    151 bcmi_flow_ip6_addr_is_valid(bcm_ip6_t addr)
    152 {
    153     uint32 idx = 0;
    154     for (idx = 0; idx < 16; idx++) {
    155         if (addr[idx]) {
    156            return TRUE;
    157         }
    158     }
    159     return FALSE;
    160 }
    161 
    162 STATIC int
    163 _bcm_flow_tunnel_idx_from_oif_get(int unit, int oif_idx, int *tnl_idx)
    164 {
    165     uint32 oif_entry[SOC_MAX_MEM_WORDS];
    166     soc_mem_t oif_mem_view;
    167     soc_mem_t oif_mem;
    168     int data_type;
    169     int rv;
    170     uint32 action_set;
    171 
    172     oif_mem = EGR_L3_INTFm;
    173     rv = soc_mem_read(unit, oif_mem, MEM_BLOCK_ANY,
    174                                   oif_idx,oif_entry);
    175     if (SOC_FAILURE(rv)) {
    176         return rv;
    177     }
    178     data_type = soc_mem_field32_get(unit, oif_mem,
    179                                oif_entry, DATA_TYPEf);
    180 
    181     /* find the memory view based on the memory and key type */
    182     rv = soc_flow_db_mem_to_view_id_get (unit, oif_mem,
    183                     SOC_FLOW_DB_KEY_TYPE_INVALID, data_type,
    184                     0, NULL, (uint32 *)&oif_mem_view);
    185     if (SOC_FAILURE(rv)) {
    186         return rv;
    187     }
    188     if (SOC_MEM_FIELD_VALID(unit,oif_mem_view,
    189                                  TUNNEL_PTR_ACTION_SETf)) {
    190         action_set = 0;
    191         action_set = soc_mem_field32_get(unit, oif_mem_view, oif_entry,
    192                                       TUNNEL_PTR_ACTION_SETf);
    193         *tnl_idx = soc_format_field32_get(unit,TUNNEL_PTR_ACTION_SETfmt,
    194                                        &action_set,TUNNEL_INDEXf);
    195     }
    196     return SOC_E_NONE;
    197 }
    198 
    199 /*
    200  * Function:
    201  *      _bcm_flow_tunnel_dip_idx_set
    202  * Purpose:
    203  *      set L2 tunnel DIP address.
    204  * Parameters:
    205  *      unit - (IN) SOC unit number.
    206  * Returns:
    207  *      BCM_X_XXX
    208  * NOTE:
    209  */
    210 
    211 STATIC int
    212 _bcm_flow_tunnel_dip_idx_set(int unit,
    213       bcm_flow_tunnel_initiator_t *info,
    214       int tnl_idx,
    215       int *tnl_in_oif)
    216 {
    217     int rv = BCM_E_NONE;
    218     int data_type;
    219     soc_mem_t dvp_mem;
    220     uint32 dvp_attr[SOC_MAX_MEM_WORDS];
    221     soc_mem_t dvp_mem_view;
    222     int fixed_view = TRUE;
    223     uint32 dip6[4];
    224     int dvp;
    225     uint32 tnl_index;
    226     int l2tnl2oif = FALSE;
    227     int l2_tunnel = FALSE;
    228 
    229     if (tnl_in_oif != NULL) {
    230         *tnl_in_oif = FALSE;
    231     }
    232     if (info->flags & BCM_TUNNEL_REPLACE) {
    233         if (BCM_GPORT_TUNNEL_ID_GET(info->tunnel_id) < 
    234                         _BCM_FLOW_TUNNEL_L2_MAX(unit)) {
    235             l2_tunnel = TRUE;
    236         }
    237     } else {
    238         if (_BCM_FLOW_TUNNEL_TYPE_L2(info->type)) {
    239             l2_tunnel = TRUE;
    240         }
    241     }
    242 
    243     if (l2_tunnel) {
    244         dvp_mem = EGR_DVP_ATTRIBUTEm;
    245         dvp = _SHR_GPORT_FLOW_PORT_ID_GET(info->flow_port);
    246         soc_mem_lock(unit,dvp_mem);
    247         rv = soc_mem_read(unit, dvp_mem, MEM_BLOCK_ANY, dvp, dvp_attr);
    248         data_type = soc_mem_field32_get(unit, dvp_mem, dvp_attr, DATA_TYPEf);
    249     
    250         /* find the memory view based on the memory and key type */
    251         rv = soc_flow_db_mem_to_view_id_get (unit, dvp_mem, 
    252                      SOC_FLOW_DB_KEY_TYPE_INVALID, data_type,
    253                     0, NULL, (uint32 *)&dvp_mem_view);
    254         LOG_VERBOSE(BSL_LS_BCM_FLOW, (BSL_META_U(unit,
    255            "dvp(%d) mem_view_id: 0x%x\n"), dvp, dvp_mem_view));
    256         if (SOC_FAILURE(rv) && (rv != SOC_E_NOT_FOUND)) {
    257             soc_mem_unlock(unit,dvp_mem);
    258             return rv;
    259         } else if (rv == SOC_E_NOT_FOUND) {
    260             /* not found, fixed view */
    261         } else {
    262             /* found, flex view */
    263             fixed_view = FALSE;
    264         }
    265     
    266         if (fixed_view == FALSE) {
    267             if (info->valid_elements & BCM_FLOW_TUNNEL_INIT_DIP_VALID) {
    268                 if (SOC_MEM_FIELD_VALID(unit,dvp_mem_view,
    269                              DIRECT_ASSIGNMENT_10_ACTION_SETf)) {
    270                     soc_mem_field32_set(unit, dvp_mem_view, dvp_attr,
    271                         DIRECT_ASSIGNMENT_10_ACTION_SETf, info->dip);
    272                 }
    273             }
    274             if (info->valid_elements & BCM_FLOW_TUNNEL_INIT_DIP6_VALID) {
    275     
    276                 /* dip in dvp_attribute table */
    277                 SAL_IP6_ADDR_TO_UINT32(info->dip6,dip6);
    278     
    279                 /* OUTER_IPV6_DIP_0_31 */
    280                 if (SOC_MEM_FIELD_VALID(unit,dvp_mem_view,
    281                                  DIRECT_ASSIGNMENT_10_ACTION_SETf)) {
    282                     soc_mem_field32_set(unit, dvp_mem_view, dvp_attr,
    283                             DIRECT_ASSIGNMENT_10_ACTION_SETf, dip6[0]);
    284                 }
    285     
    286                 /* OUTER_IPV6_DIP_32_63 */
    287                 if (SOC_MEM_FIELD_VALID(unit,dvp_mem_view,
    288                                  DIRECT_ASSIGNMENT_12_ACTION_SETf)) {
    289                     soc_mem_field32_set(unit, dvp_mem_view, dvp_attr,
    290                             DIRECT_ASSIGNMENT_12_ACTION_SETf, dip6[1]);
    291                 }
    292     
    293                 /* OUTER_IPV6_DIP_64_95 */
    294                 if (SOC_MEM_FIELD_VALID(unit,dvp_mem_view,
    295                                  DIRECT_ASSIGNMENT_14_ACTION_SETf)) {
    296                     soc_mem_field32_set(unit, dvp_mem_view, dvp_attr,
    297                             DIRECT_ASSIGNMENT_14_ACTION_SETf, dip6[2]);
    298                 }
    299     
    300                 /* OUTER_IPV6_DIP_96_127 */
    301                 if (SOC_MEM_FIELD_VALID(unit,dvp_mem_view,
    302                                  DIRECT_ASSIGNMENT_16_ACTION_SETf)) {
    303                     soc_mem_field32_set(unit, dvp_mem_view, dvp_attr,
    304                             DIRECT_ASSIGNMENT_16_ACTION_SETf, dip6[3]);
    305                 }
    306             }
    307             if (SOC_MEM_FIELD_VALID(unit,dvp_mem_view,
    308                                  TUNNEL_PTR_ACTION_SETf)) {
    309                 tnl_index = 0;
    310                 soc_format_field32_set(unit,TUNNEL_PTR_ACTION_SETfmt,
    311                                        &tnl_index,TUNNEL_INDEXf, tnl_idx);
    312                 soc_mem_field32_set(unit, dvp_mem_view, dvp_attr,
    313                             TUNNEL_PTR_ACTION_SETf, tnl_index);
    314     
    315             } else if (info->l3_intf_id) {
    316                 if (info->l3_intf_id < _BCM_FLOW_TUNNEL_L3_MAX(unit)) {
    317                     /* set to EGR_L3_INTF */
    318                     l2tnl2oif = TRUE;
    319                 }
    320             }
    321         } else {   /* fixed view */
    322             /* L2GRE and VXLAN: DIP is in dvp_attr */
    323     
    324             if (data_type == _BCM_FLOW_VXLAN_EGRESS_DEST_VP_TYPE) {
    325                 if (info->valid_elements & BCM_FLOW_TUNNEL_INIT_DIP_VALID) {
    326                     soc_mem_field32_set(unit, dvp_mem, dvp_attr,
    327                                VXLAN__DIPf, info->dip);
    328                 }
    329                 soc_mem_field32_set(unit, dvp_mem, dvp_attr,
    330                                VXLAN__TUNNEL_INDEXf, tnl_idx);
    331     
    332             } else if (data_type == _BCM_FLOW_L2GRE_EGRESS_DEST_VP_TYPE) {
    333                 if (info->valid_elements & BCM_FLOW_TUNNEL_INIT_DIP_VALID) {
    334                     soc_mem_field32_set(unit, dvp_mem, dvp_attr,
    335                                L2GRE__DIPf, info->dip);
    336                 }
    337                 soc_mem_field32_set(unit, dvp_mem, dvp_attr,
    338                                L2GRE__TUNNEL_INDEXf, tnl_idx);
    339             }
    340         }
    341         rv = soc_mem_write(unit, dvp_mem, MEM_BLOCK_ALL, dvp, dvp_attr);
    342         soc_mem_unlock(unit,dvp_mem);
    343     }
    344 
    345     /* If l3 tunnel or certain l2 tunnel cases, set tunnel idx to oif table */
    346     if ((!_BCM_FLOW_TUNNEL_TYPE_L2(info->type)) || l2tnl2oif) {
    347         uint32 oif_entry[SOC_MAX_MEM_WORDS];
    348         soc_mem_t oif_mem_view;
    349         soc_mem_t oif_mem;
    350 
    351         oif_mem = EGR_L3_INTFm;
    352         soc_mem_lock(unit, oif_mem);
    353         rv = soc_mem_read(unit, oif_mem, MEM_BLOCK_ANY,
    354                                   info->l3_intf_id,oif_entry);
    355         if (SOC_FAILURE(rv)) {
    356             soc_mem_unlock(unit,oif_mem);
    357             return rv;
    358         }
    359         data_type = soc_mem_field32_get(unit, oif_mem,
    360                                oif_entry, DATA_TYPEf);
    361         fixed_view = TRUE;
    362         /* find the memory view based on the memory and key type */
    363         rv = soc_flow_db_mem_to_view_id_get (unit, oif_mem, 
    364                     SOC_FLOW_DB_KEY_TYPE_INVALID, data_type,
    365                     0, NULL, (uint32 *)&oif_mem_view);
    366         if (SOC_FAILURE(rv) && (rv != SOC_E_NOT_FOUND)) {
    367             return rv;
    368         } else if (rv == SOC_E_NOT_FOUND) {
    369             /* not found, fixed view */
    370         } else {
    371             /* found, flex view */
    372             fixed_view = FALSE;
    373         }
    374 
    375         if (fixed_view == TRUE) {
    376             if (!_BCM_FLOW_TUNNEL_TYPE_L2(info->type)) {
    377                 soc_mem_field32_set(unit, oif_mem, oif_entry,
    378                             TUNNEL_INDEXf, tnl_idx);
    379             }
    380         } else {
    381             if (SOC_MEM_FIELD_VALID(unit,oif_mem_view,
    382                                  TUNNEL_PTR_ACTION_SETf)) {
    383                 tnl_index = 0;
    384                 soc_format_field32_set(unit,TUNNEL_PTR_ACTION_SETfmt,
    385                                        &tnl_index,TUNNEL_INDEXf, tnl_idx);
    386                 soc_mem_field32_set(unit, oif_mem_view, oif_entry,
    387                                       TUNNEL_PTR_ACTION_SETf, tnl_index);
    388             } else {
    389                 soc_mem_unlock(unit, oif_mem);
    390                 LOG_ERROR(BSL_LS_BCM_FLOW, (BSL_META_U(unit,
    391                    "TUNNEL_PTR_ACTION_SETf not in either dvp or oif")));
    392                 return BCM_E_NOT_FOUND;
    393             }
    394         } 
    395         if (tnl_in_oif != NULL) {
    396             *tnl_in_oif = TRUE;
    397         }
    398         rv = soc_mem_write(unit, oif_mem, MEM_BLOCK_ALL, info->l3_intf_id, 
    399                            oif_entry);
    400         soc_mem_unlock(unit, oif_mem);
    401     }
    402     SOC_IF_ERROR_RETURN(rv);
    403     return rv;
    404 }
    405 
    406 /*
    407  * Function:
    408  *      _bcm_flow_tunnel_initiator_hash_calc
    409  * Purpose:
    410  *      Calculate tunnel initiator entry hash(signature).
    411  * Parameters:
    412  *      unit - (IN) SOC unit number.
    413  *      buf  - (IN) Tunnel initiator entry information.
    414  *      hash - (OUT)Hash(signature) calculated value.
    415  * Returns:
    416  *      BCM_X_XXX
    417  * NOTE:
    418  * duplication of _bcm_td2_vxlan_tunnel_initiator_hash_calc for
    419  * not including legacy vxlan code in the future.
    420  *
    421  * plugged in _bcm_xgs3_tnl_init_hash_calc
    422  */
    423 
    424 int
    425 _bcm_flow_tunnel_initiator_hash_calc(int unit, void *buf, uint16 *hash)
    426 {
    427     _bcm_flow_tunnel_record_t *tnl_rec;
    428     bcm_flow_tunnel_initiator_t tnl_entry;
    429     bcm_flow_tunnel_initiator_t *info;
    430    
    431     if ((NULL == buf) || (NULL == hash)) {
    432         return (BCM_E_PARAM);
    433     }
    434 
    435     tnl_rec = (_bcm_flow_tunnel_record_t *)buf;
    436     info = tnl_rec->info;
    437 
    438     bcm_flow_tunnel_initiator_t_init(&tnl_entry);
    439     tnl_entry.type = info->type;
    440   
    441     if (_BCM_FLOW_TUNNEL_TYPE_L2(tnl_entry.type)) {
    442         /* Set source ip */
    443         if (info->valid_elements & BCM_FLOW_TUNNEL_INIT_SIP6_VALID) {
    444             sal_memcpy(tnl_entry.sip6, info->sip6, sizeof(bcm_ip6_t));
    445         }
    446     
    447         if (info->valid_elements & BCM_FLOW_TUNNEL_INIT_SIP_VALID) {
    448             tnl_entry.sip = info->sip;
    449         }
    450      
    451         tnl_entry.udp_dst_port = info->udp_dst_port;
    452         tnl_entry.udp_src_port = info->udp_src_port;
    453 
    454      } else {  /* L3 tunnel */
    455          /* include all fields, copy buffer to structure. */
    456          sal_memcpy(&tnl_entry, (void *)info, 
    457                            sizeof(bcm_flow_tunnel_initiator_t));
    458 
    459          /* Ignore flow label for not V6 tunnels. */
    460          if (_BCM_TUNNEL_OUTER_HEADER_IPV6(tnl_entry.type))  {
    461              tnl_entry.flow_label = 0;
    462          }
    463 
    464          /* Mask fields we don't want to include in hash. */
    465          tnl_entry.flags = 0;
    466          tnl_entry.flow_handle = 0;
    467          tnl_entry.flow_option = 0;
    468          tnl_entry.flow_port = 0;
    469          tnl_entry.valid_elements = 0;
    470          tnl_entry.tunnel_id = 0;
    471          tnl_entry.l3_intf_id = 0;
    472 
    473          switch (tnl_entry.type) {
    474              case bcmTunnelTypeIp4In4:
    475              case bcmTunnelTypeIp6In4:
    476                  tnl_entry.type = bcmTunnelTypeIpAnyIn4;
    477                  break;
    478              case bcmTunnelTypeIp4In6:
    479              case bcmTunnelTypeIp6In6:
    480                  tnl_entry.type = bcmTunnelTypeIpAnyIn6;
    481                  break;
    482              case bcmTunnelTypeGre4In4:
    483              case bcmTunnelTypeGre6In4:
    484                  tnl_entry.type = bcmTunnelTypeGreAnyIn4;
    485                  break;
    486              case bcmTunnelTypeGre4In6:
    487              case bcmTunnelTypeGre6In6:
    488                  tnl_entry.type = bcmTunnelTypeGreAnyIn6;
    489                  break;
    490              default:
    491                  break;
    492          }
    493      }
    494 
    495      /* Calculate hash */
    496     *hash = _shr_crc16(0, (uint8 *)&tnl_entry,
    497         sizeof(bcm_flow_tunnel_initiator_t));
    498     
    499     return BCM_E_NONE;
    500 }
    501 
    502 
    503 /*
    504  * Function:
    505  *      _bcm_flow_tunnel_initiator_cmp
    506  * Purpose:
    507  *      Routine compares vxlan tunnel initiator entry with entry in the chip
    508  *      with specified index.
    509  * Parameters:
    510  *      unit       - (IN) SOC unit number.
    511  *      buf        - (IN) Tunnel initiator entry to compare.
    512  *      index      - (IN) Entry index in the chip to compare.
    513  *      cmp_result - (OUT)Compare result.
    514  * Returns:
    515  *      BCM_E_XXX
    516  *
    517  * NOTE:
    518  * duplication of _bcm_td2_vxlan_tunnel_initiator_cmp for
    519  * not including legacy vxlan code in the future.
    520  *
    521  * plugged in _bcm_xgs3_tnl_init_cmp
    522  */
    523 
    524 int
    525 _bcm_flow_tunnel_initiator_cmp(int unit, void *buf,
    526                                           int index, int *cmp_result)
    527 {
    528     bcm_flow_tunnel_initiator_t hw_entry;   /* Entry read from hw */
    529     bcm_flow_tunnel_initiator_t *tnl_entry; /* Api passed buffer */
    530     _bcm_flow_tunnel_record_t *tnl_rec;
    531     int rv = BCM_E_NONE;
    532     bcm_flow_logical_field_t field[_BCM_FLOW_LOGICAL_FIELD_MAX];
    533     uint32 data_ids[_BCM_FLOW_LOGICAL_FIELD_MAX];
    534     uint32 mem_entry[SOC_MAX_MEM_WORDS];
    535     int i;
    536     uint32 cnt = 0;
    537     int data_type;
    538     int flow_ctrl_id;
    539     int hw_data_type;
    540     int hw_flow_ctrl_id;
    541     int flex_type_match = FALSE;
    542     soc_mem_t mem;
    543 
    544     if ((NULL == buf) || (NULL == cmp_result)) {
    545         return BCM_E_PARAM;
    546     }
    547     tnl_rec = (_bcm_flow_tunnel_record_t *)buf;
    548 
    549     *cmp_result = BCM_L3_CMP_NOT_EQUAL;
    550     mem = EGR_IP_TUNNELm;
    551 
    552     /* point to the input entry */
    553     tnl_entry = tnl_rec->info;
    554 
    555     /* Initialize entry to get from hw */
    556     bcm_flow_tunnel_initiator_t_init(&hw_entry);
    557 
    558     if (_BCM_FLOW_IS_FLEX_VIEW(tnl_entry)) {
    559         rv = soc_flow_db_mem_view_field_list_get(unit,
    560                       tnl_rec->mem_view,
    561                       SOC_FLOW_DB_FIELD_TYPE_LOGICAL_POLICY_DATA,
    562                       _BCM_FLOW_LOGICAL_FIELD_MAX, data_ids, &cnt);
    563         SOC_IF_ERROR_RETURN(rv);
    564         for (i = 0; i < cnt; i++) {
    565             field[i].id = data_ids[i];
    566         }
    567         rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, index, mem_entry);
    568         SOC_IF_ERROR_RETURN(rv);
    569         hw_data_type = soc_mem_field32_get(unit, mem, mem_entry, DATA_TYPEf);
    570         hw_flow_ctrl_id = soc_mem_field32_get(unit, mem, mem_entry, 
    571                                          FLEX_FLOW_SELECT_CTRL_IDf);
    572         soc_flow_db_mem_view_entry_init(unit,tnl_rec->mem_view, mem_entry);
    573         data_type = soc_mem_field32_get(unit, tnl_rec->mem_view, 
    574                                         mem_entry, DATA_TYPEf);
    575         flow_ctrl_id = soc_mem_field32_get(unit, tnl_rec->mem_view, mem_entry, 
    576                                          FLEX_FLOW_SELECT_CTRL_IDf);
    577         if (hw_data_type == data_type && hw_flow_ctrl_id == flow_ctrl_id) {
    578             flex_type_match = TRUE;
    579         } else {
    580             return (BCM_E_NONE);
    581         }
    582     } 
    583 
    584     /* Get tunnel initiator entry from hw */
    585     BCM_XGS3_L3_MODULE_LOCK(unit);
    586     rv = _bcm_flow_hw_tunnel_entry_get(unit, index, &hw_entry,field,
    587                                        cnt,NULL);
    588     BCM_XGS3_L3_MODULE_UNLOCK(unit);
    589     BCM_IF_ERROR_RETURN(rv);
    590 
    591     /* compare the type first */
    592     if ((tnl_entry->type != hw_entry.type) && (flex_type_match == FALSE)) {
    593         switch (tnl_entry->type) {
    594           case bcmTunnelTypeIp4In4:
    595           case bcmTunnelTypeIp6In4:
    596               if (bcmTunnelTypeIpAnyIn4 != hw_entry.type) {
    597                   return (BCM_E_NONE);
    598               }
    599               break;
    600           case bcmTunnelTypeIp4In6:
    601           case bcmTunnelTypeIp6In6:
    602               if (bcmTunnelTypeIpAnyIn6 != hw_entry.type) {
    603                   return (BCM_E_NONE);
    604               }
    605               break;
    606           case  bcmTunnelTypeGre4In4:
    607           case  bcmTunnelTypeGre6In4:
    608               if (bcmTunnelTypeGreAnyIn4 != hw_entry.type) {
    609                   return (BCM_E_NONE);
    610               }
    611               break;
    612           case    bcmTunnelTypeGre4In6:
    613           case    bcmTunnelTypeGre6In6:
    614               if (bcmTunnelTypeGreAnyIn6 != hw_entry.type) {
    615                   return (BCM_E_NONE);
    616               }
    617               break;
    618           default:
    619               return (BCM_E_NONE);
    620         }
    621     }
    622     
    623     /* Compare source ip */
    624     if (tnl_entry->valid_elements & BCM_FLOW_TUNNEL_INIT_SIP_VALID) {
    625         if (tnl_entry->sip != hw_entry.sip) {
    626             return BCM_E_NONE;
    627         }
    628     }
    629     if (tnl_entry->valid_elements & BCM_FLOW_TUNNEL_INIT_SIP6_VALID) {
    630         if (sal_memcmp(tnl_entry->sip6, hw_entry.sip6, sizeof(bcm_ip6_t))) {
    631             return BCM_E_NONE;
    632         }
    633     }
    634 
    635     if (!_BCM_FLOW_TUNNEL_TYPE_L2(tnl_entry->type)) {
    636         if (tnl_entry->valid_elements & BCM_FLOW_TUNNEL_INIT_DIP_VALID) {
    637             if (tnl_entry->dip != hw_entry.dip) {
    638                 return BCM_E_NONE;
    639             }
    640         }
    641         if (tnl_entry->valid_elements & BCM_FLOW_TUNNEL_INIT_DIP6_VALID) {
    642             if (sal_memcmp(tnl_entry->dip6, hw_entry.dip6, sizeof(bcm_ip6_t))) {
    643                 return BCM_E_NONE;
    644             }
    645         }
    646     }
    647 
    648     /* Compare udp dst port */
    649     if ((tnl_entry->udp_dst_port != hw_entry.udp_dst_port) ||
    650         (tnl_entry->udp_src_port != hw_entry.udp_src_port)) {
    651         return BCM_E_NONE;
    652     }
    653 
    654     /* Compare hw entry with passed one. */
    655     if ((tnl_entry->dscp_sel != hw_entry.dscp_sel) ||
    656         (tnl_entry->dscp != hw_entry.dscp)) {
    657         return (BCM_E_NONE);
    658     }
    659 
    660     if (tnl_entry->ttl != hw_entry.ttl) {
    661         return (BCM_E_NONE);
    662     }
    663     /* Compare destination mac. */
    664     if (sal_memcmp(tnl_entry->dmac, hw_entry.dmac, sizeof(bcm_mac_t))) {
    665         return (BCM_E_NONE);
    666     }
    667 
    668     /* compare the logical fields if it is flex view */
    669     if (_BCM_FLOW_IS_FLEX_VIEW(tnl_entry)) {
    670         for (i = 0; i < cnt && i < tnl_rec->num_of_fields; i++) {
    671             if (field[i].id == tnl_rec->field[i].id) {
    672                 if (field[i].value != tnl_rec->field[i].value) {
    673                     return (BCM_E_NONE);
    674                 }
    675             }                    
    676         }
    677     }
    678     *cmp_result = BCM_L3_CMP_EQUAL;
    679     return BCM_E_NONE;
    680 }
    681 
    682 /*
    683  * Function:
    684  *      _bcm_flow_tnl_init_add
    685  * Purpose:
    686  *       Allocate tunnel initiator table index & Write tunnel initiator entry.
    687  *       Routine trying to match new entry to an existing one,
    688  *       if match found reference cound is incremented, otherwise
    689  *       new index allocated & entry added to hw.
    690  * Parameters:
    691  *      unit       - (IN)StrataSwitch unit number.
    692  *      flags      - (IN)Table shared flags.
    693  *      tnl_entry  - (IN)Tunnel initiator entry.
    694  *      index      - (OUT)next hop index.
    695  * Returns:
    696  *    BCM_E_XXX
    697  */
    698 int
    699 _bcm_flow_tnl_init_add(int unit, uint32 flags, 
    700                       bcm_flow_tunnel_initiator_t *tnl_entry,
    701                       bcm_flow_logical_field_t *field,
    702                       uint32 num_of_fields,
    703                       int *index)
    704 {
    705     _bcm_l3_tbl_op_t data;        /* Operation data.               */
    706     soc_flow_db_mem_view_info_t vinfo;
    707     int rv = BCM_E_NONE;
    708     soc_mem_t mem_view_id;
    709     int double_wide;
    710     _bcm_flow_tunnel_record_t tnl_rec;
    711 
    712     if (!(flags & _BCM_L3_SHR_WRITE_DISABLE)) {
    713         /* Make sure hw call is defined. */
    714         if (!BCM_XGS3_L3_HWCALL_CHECK(unit, tnl_init_add)) {
    715             return (BCM_E_UNAVAIL);
    716         }
    717     }
    718 
    719     tnl_rec.info = tnl_entry;
    720     tnl_rec.field = field;
    721     tnl_rec.num_of_fields = num_of_fields;
    722 
    723     /* get the physical memory view */
    724     if (_BCM_FLOW_IS_FLEX_VIEW(tnl_entry)) {
    725         rv = soc_flow_db_ffo_to_mem_view_id_get(unit,tnl_entry->flow_handle,
    726                    tnl_entry->flow_option,
    727                    SOC_FLOW_DB_FUNC_TUNNEL_INITIATOR_ID,
    728                     (uint32 *)&mem_view_id);
    729         BCM_IF_ERROR_RETURN(rv);
    730         rv = soc_flow_db_mem_view_info_get(unit,mem_view_id,&vinfo);
    731         BCM_IF_ERROR_RETURN(rv);
    732         double_wide = vinfo.width > _BCM_FLOW_IP_TUNNEL_SINGLE_WIDE_WIDTH? 
    733                       TRUE: FALSE;
    734         tnl_rec.mem_view = mem_view_id;
    735     } else {
    736         double_wide = _BCM_EGR_IP_TUNNEL_DOUBLE_WIDE_ENTRY(unit, 
    737                         tnl_entry->type) ? TRUE: FALSE;
    738     }
    739 
    740     /* this flag must be set, so tnl_init_add never called */
    741     flags |= _BCM_L3_SHR_WRITE_DISABLE;
    742 
    743     /* Initialization */
    744     sal_memset(&data, 0, sizeof(_bcm_l3_tbl_op_t));
    745     data.tbl_ptr =  BCM_XGS3_L3_TBL_PTR(unit, tnl_init);
    746     data.width = double_wide? _BCM_DOUBLE_WIDE: _BCM_SINGLE_WIDE;
    747     data.oper_flags = flags;
    748     data.entry_buffer = (void *)&tnl_rec;
    749     data.hash_func = _bcm_flow_tunnel_initiator_hash_calc;
    750     data.cmp_func  = _bcm_flow_tunnel_initiator_cmp;
    751  
    752     /* init add_func to pass the error check */
    753     data.add_func  = BCM_XGS3_L3_HWCALL(unit, tnl_init_add);
    754     if (flags & _BCM_L3_SHR_WITH_ID) {
    755         data.entry_index = *index;
    756     }
    757 
    758     /* Add tunnel initiator entry. */
    759     BCM_IF_ERROR_RETURN (_bcm_xgs3_tbl_add(unit, &data));
    760     *index = data.entry_index;
    761 
    762     return (BCM_E_NONE);
    763 }
    764 
    765 /*
    766  * Function:
    767  *      _bcm_flow_tunnel_init_delete
    768  * Purpose:
    769  *      Clear the tunnel initiator hardware entry.
    770  * Parameters:
    771  *      unit     - (IN)SOC unit number.
    772  *      idx      - (IN)Index to tunnel initiator hardware entry table.
    773  * Returns:
    774  *      BCM_E_XXX
    775  */
    776 STATIC int
    777 _bcm_flow_tunnel_init_delete(int unit, int idx, int width)
    778 {
    779     uint32 tnl_entry[SOC_MAX_MEM_FIELD_WORDS]; /* Buffer to write hw entry */
    780     soc_mem_t mem;                        /* Tunnel initiator table memory */
    781 
    782     /* Get table memory. */
    783     mem = BCM_XGS3_L3_MEM(unit, tnl_init_v4);
    784     if (width == _BCM_DOUBLE_WIDE) {
    785         mem = BCM_XGS3_L3_MEM(unit, tnl_init_v6);
    786         idx >>= 1;    /* Each record takes two slots. */
    787     }
    788     /* Zero write buffer. */
    789     sal_memset(&tnl_entry, 0, SOC_MAX_MEM_FIELD_WORDS * sizeof(uint32));
    790 
    791     /* Write buffer to hw. */
    792     return BCM_XGS3_MEM_WRITE(unit, mem, idx, &tnl_entry);
    793 }
    794 
    795 /*
    796  * Function:
    797  *      _bcm_flow_tunnel_init_get
    798  * Purpose:
    799  *      Add tunnel initiator entry to hw.
    800  * Parameters:
    801  *      unit     - (IN)SOC unit number.
    802  *      idx      - (IN)Index to insert tunnel initiator.
    803  *      info     - (IN)Tunnel initiator entry info.
    804  * Returns:
    805  *      BCM_E_XXX
    806  */
    807 STATIC int
    808 _bcm_flow_tunnel_init_get(int unit, 
    809             int soft_tnl_idx, 
    810             bcm_flow_tunnel_initiator_t *info,
    811             bcm_flow_logical_field_t *field,
    812             uint32 num_of_fields,
    813             uint32 *field_cnt)
    814 {
    815     uint32 dvp_attr[SOC_MAX_MEM_WORDS];
    816     soc_mem_t dvp_mem;
    817     soc_mem_t dvp_mem_view;
    818     int rv = BCM_E_NONE;                  /* Return value                  */
    819     uint32 dip6[4];
    820     uint32 dvp_data_type;
    821     _bcm_flow_bookkeeping_t *flow_info;
    822     int oif_idx;
    823     int tnl_idx;
    824 
    825     flow_info = FLOW_INFO(unit);
    826 
    827     dvp_mem = EGR_DVP_ATTRIBUTEm;    
    828 
    829     tnl_idx = flow_info->init_tunnel[soft_tnl_idx].idx; 
    830     if (soft_tnl_idx < _BCM_FLOW_TUNNEL_L2_MAX(unit)) {
    831         /* L2 tunnel */
    832         rv = soc_mem_read(unit, dvp_mem, MEM_BLOCK_ANY, soft_tnl_idx,dvp_attr);
    833         dvp_data_type = soc_mem_field32_get(unit, dvp_mem, dvp_attr, 
    834                                             DATA_TYPEf); 
    835 
    836         /* find the memory view based on the memory and key type */
    837         rv = soc_flow_db_mem_to_view_id_get (unit, dvp_mem, 
    838                     SOC_FLOW_DB_KEY_TYPE_INVALID, dvp_data_type,
    839                     0, NULL, (uint32 *)&dvp_mem_view);
    840         if (SOC_FAILURE(rv) && (rv != SOC_E_NOT_FOUND)) {
    841             return rv;
    842         } else if (rv == SOC_E_NOT_FOUND) {
    843             /* not found, fixed view */
    844         } else {
    845             /* found, flex view */
    846             info->type = bcmTunnelTypeL2Flex;
    847             dvp_mem = dvp_mem_view;
    848         } 
    849 
    850         if (info->type == bcmTunnelTypeL2Flex) {
    851             /* dip in dvp_attribute table */ 
    852 
    853             dip6[0] = 0;
    854             dip6[1] = 0;
    855             dip6[2] = 0;
    856             dip6[3] = 0;
    857             SAL_IP6_ADDR_FROM_UINT32(info->dip6,dip6);
    858             info->dip = 0;
    859 
    860             /* OUTER_IPV6_DIP_0_31 */
    861             if (SOC_MEM_FIELD_VALID(unit,dvp_mem,
    862                          DIRECT_ASSIGNMENT_10_ACTION_SETf)) {
    863                 dip6[0] = soc_mem_field32_get(unit, dvp_mem, dvp_attr,
    864                                 DIRECT_ASSIGNMENT_10_ACTION_SETf);
    865             }
    866 
    867             /* OUTER_IPV6_DIP_32_63 */
    868             if (SOC_MEM_FIELD_VALID(unit,dvp_mem,
    869                          DIRECT_ASSIGNMENT_12_ACTION_SETf)) {
    870                 dip6[1] = soc_mem_field32_get(unit, dvp_mem, dvp_attr,
    871                                 DIRECT_ASSIGNMENT_12_ACTION_SETf);
    872             }
    873 
    874             /* OUTER_IPV6_DIP_64_95 */
    875             if (SOC_MEM_FIELD_VALID(unit,dvp_mem,
    876                          DIRECT_ASSIGNMENT_14_ACTION_SETf)) {
    877                 dip6[2] = soc_mem_field32_get(unit, dvp_mem, dvp_attr,
    878                                        DIRECT_ASSIGNMENT_14_ACTION_SETf);
    879             }
    880 
    881             /* OUTER_IPV6_DIP_96_127 */
    882             if (SOC_MEM_FIELD_VALID(unit,dvp_mem,
    883                                  DIRECT_ASSIGNMENT_16_ACTION_SETf)) {
    884                 dip6[3] = soc_mem_field32_get(unit, dvp_mem, dvp_attr,
    885                                 DIRECT_ASSIGNMENT_16_ACTION_SETf);
    886             }
    887             if ((dip6[1] == 0) && (dip6[2] == 0) && (dip6[3] == 0)) {
    888                 info->dip = dip6[0];
    889             } else {
    890                 SAL_IP6_ADDR_FROM_UINT32(info->dip6,dip6);
    891             }
    892         } else {   /* fixed view */
    893 
    894             /* L2GRE and VXLAN: DIP is in dvp_attr */
    895  
    896             if (dvp_data_type == _BCM_FLOW_VXLAN_EGRESS_DEST_VP_TYPE) {
    897                 info->type = bcmTunnelTypeVxlan;
    898                 info->flow_handle = SOC_FLOW_DB_FLOW_ID_LEGACY_VXLAN;
    899                 info->dip = soc_mem_field32_get(unit, dvp_mem, dvp_attr, 
    900                                                    VXLAN__DIPf);
    901             } else if (dvp_data_type == _BCM_FLOW_L2GRE_EGRESS_DEST_VP_TYPE) {
    902                 info->type = bcmTunnelTypeL2Gre;
    903                 info->flow_handle = SOC_FLOW_DB_FLOW_ID_LEGACY_L2GRE;
    904                 info->dip = soc_mem_field32_get(unit, dvp_mem, dvp_attr, 
    905                                                  L2GRE__DIPf);
    906             } else {
    907                 return BCM_E_INTERNAL;
    908             }
    909         }
    910         if (tnl_idx >= _BCM_FLOW_TUNNEL_IP_TUNNEL_MAX(unit)) {
    911             /* l3_oif index */
    912             oif_idx = tnl_idx - _BCM_FLOW_TUNNEL_IP_TUNNEL_MAX(unit);
    913             info->l3_intf_id = oif_idx;
    914             BCM_IF_ERROR_RETURN(_bcm_flow_tunnel_idx_from_oif_get(unit,
    915                                  oif_idx, &tnl_idx));
    916         }
    917     }
    918 
    919     rv = _bcm_flow_hw_tunnel_entry_get(unit, tnl_idx, info, field, 
    920                            num_of_fields,field_cnt);
    921     BCM_IF_ERROR_RETURN(rv);
    922     return rv;
    923 }
    924 
    925 /*
    926  * Function:
    927  *     _bcm_flow_hw_tunnel_entry_get 
    928  * Purpose:
    929  *      Get a IP_TUNNEL entry and convert to bcm_flow_tunnel_initiator_t info.
    930  * Parameters:
    931  *      unit     - (IN)SOC unit number.
    932  *      idx      - (IN)Index to IP_TUNNEL hw table.
    933  *      info     - (IN)Tunnel initiator entry info.
    934  * Returns:
    935  *      BCM_E_XXX
    936  */
    937 STATIC int
    938 _bcm_flow_hw_tunnel_entry_get(int unit,
    939             int idx,
    940             bcm_flow_tunnel_initiator_t *info,
    941             bcm_flow_logical_field_t *field,
    942             uint32 num_of_fields,
    943             uint32 *field_cnt)
    944 {
    945     uint32 tnl_entry[SOC_MAX_MEM_FIELD_WORDS]; /* Buffer to write hw entry */
    946     soc_mem_t mem;                        /* Tunnel initiator table memory */
    947     soc_mem_t mem_view_id;
    948     int rv;                               /* Return value                  */
    949     int df_val=0;                           /* Don't fragment encoding       */
    950     uint32 sip6[4];
    951     uint32 dip6[4];
    952     uint32 tnl_data_type;
    953     int tnl_type = 0;
    954     uint32 data_ids[_BCM_FLOW_LOGICAL_FIELD_MAX];
    955     uint32 cnt;
    956     int i;
    957     int j;
    958     uint32 ttl;
    959     int fixed_view = TRUE;
    960     soc_field_t qos_f;
    961     egr_sequence_number_table_entry_t entry;
    962     _bcm_flow_bookkeeping_t *flow_info;
    963     int dscp_sel;
    964 
    965     flow_info = FLOW_INFO(unit);
    966 
    967     mem = EGR_IP_TUNNELm;
    968     rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, idx, tnl_entry);
    969     SOC_IF_ERROR_RETURN(rv);
    970     tnl_data_type = soc_mem_field32_get(unit, mem, tnl_entry, DATA_TYPEf);
    971     if (tnl_data_type == _BCM_FLOW_TUNNEL_DATA_TYPE_IPV6) {
    972         mem = BCM_XGS3_L3_MEM(unit, tnl_init_v6);
    973         idx >>= 1;    /* Each record takes two slots. */
    974 
    975         rv = BCM_XGS3_MEM_READ(unit, mem, idx, tnl_entry);
    976         BCM_IF_ERROR_RETURN(rv);
    977     }
    978     
    979     /* find the memory view based on the memory and key type */
    980     rv = soc_flow_db_mem_to_view_id_get (unit, mem, 
    981                 SOC_FLOW_DB_KEY_TYPE_INVALID, tnl_data_type,
    982                 0, NULL, (uint32 *)&mem_view_id);
    983     if (SOC_FAILURE(rv) && (rv != SOC_E_NOT_FOUND)) {
    984         return rv;
    985     } else if (rv == SOC_E_NOT_FOUND) {
    986         /* not found, fixed view */
    987         fixed_view = TRUE;
    988     } else {
    989         /* found, flex view */
    990         if (info->type != bcmTunnelTypeL2Flex) {
    991             info->type = bcmTunnelTypeL3Flex; /* set as default */
    992         }
    993         fixed_view = FALSE;
    994     }
    995 
    996     if (fixed_view == TRUE) {  /* fixed view */
    997         tnl_type = soc_mem_field32_get(unit, mem, tnl_entry, TUNNEL_TYPEf);
    998         if (tnl_data_type == _BCM_FLOW_TUNNEL_DATA_TYPE_IPV4) {
    999             if ((tnl_type != _BCM_FLOW_VXLAN_TUNNEL_TYPE) &&
   1000                 (tnl_type != _BCM_FLOW_L2GRE_TUNNEL_TYPE)) {
   1001                 info->dip = soc_mem_field32_get(unit, mem, tnl_entry, DIPf);
   1002             }
   1003             info->sip = soc_mem_field32_get(unit, mem, tnl_entry, SIPf);
   1004         } else if (tnl_data_type == _BCM_FLOW_TUNNEL_DATA_TYPE_IPV6) {
   1005 
   1006             /* Get destination ip. */
   1007             soc_mem_ip6_addr_get(unit, mem, tnl_entry, DIPf, info->dip6,
   1008                                  SOC_MEM_IP6_FULL_ADDR);
   1009 
   1010             /* Get source ip. */
   1011             soc_mem_ip6_addr_get(unit, mem, tnl_entry, SIPf, info->sip6,
   1012                                  SOC_MEM_IP6_FULL_ADDR);
   1013         }
   1014 
   1015         /* Tunnel header DSCP select. */
   1016         info->dscp_sel = soc_mem_field32_get(unit, mem, tnl_entry, DSCP_SELf);
   1017 
   1018         if (info->dscp_sel == bcmTunnelDscpMap) {
   1019             /* Set DSCP_MAP value. */
   1020             int hw_map_idx = 0;
   1021             hw_map_idx = soc_mem_field32_get(unit, mem, tnl_entry,
   1022                             DSCP_MAPPING_PTRf);
   1023             BCM_IF_ERROR_RETURN(
   1024                 _bcm_tr2_qos_idx2id(unit, hw_map_idx,
   1025                       _BCM_QOS_MAP_TYPE_EGR_DSCP_TABLE, &info->dscp_map));
   1026         } else {
   1027             /* Set DSCP value. */
   1028             info->dscp = soc_mem_field32_get(unit, mem, tnl_entry, DSCPf);
   1029         }
   1030         /* Set TTL. */
   1031         info->ttl = soc_mem_field32_get(unit, mem, tnl_entry, TTLf);
   1032 
   1033         /* Set UDP Dest Port */
   1034         info->udp_dst_port = soc_mem_field32_get(unit, mem, tnl_entry, 
   1035                                         L4_DEST_PORTf);
   1036 
   1037         /* Set UDP Src Port */
   1038         info->udp_src_port = soc_mem_field32_get(unit, mem, tnl_entry, 
   1039                                     L4_SRC_PORTf);
   1040 
   1041         if (SOC_MEM_FIELD_VALID(unit, mem, IPV4_DF_SELf)) {
   1042             /* IP tunnel hdr DF bit for IPv4 */
   1043             df_val = soc_mem_field32_get(unit, mem, tnl_entry, IPV4_DF_SELf);
   1044             if (0x2 <= df_val) {
   1045                 info->flags |= BCM_TUNNEL_INIT_USE_INNER_DF;
   1046             } else if (0x1 == df_val) {
   1047                 info->flags |= BCM_TUNNEL_INIT_IPV4_SET_DF;
   1048             }
   1049         }
   1050 
   1051         if (SOC_MEM_FIELD_VALID(unit, mem, IPV6_DF_SELf)) {
   1052             /* IP tunnel hdr DF bit for IPv6 */
   1053             if (soc_mem_field32_get(unit, mem, tnl_entry, IPV6_DF_SELf)) {
   1054                 info->flags |= BCM_TUNNEL_INIT_IPV6_SET_DF;
   1055             }
   1056         }
   1057 
   1058         /* FRAGMENT ID */
   1059         SOC_IF_ERROR_RETURN(soc_mem_read(unit, EGR_SEQUENCE_NUMBER_TABLEm,
   1060             MEM_BLOCK_ANY, idx + flow_info->frag_base_inx, &entry));
   1061         info->ip4_id = soc_mem_field32_get(unit, EGR_SEQUENCE_NUMBER_TABLEm,
   1062                         &entry, SEQUENCE_NUMBERf);
   1063 
   1064     } else {  /* flex view */
   1065         uint32 qos = 0;
   1066         if (info->type == bcmTunnelTypeL3Flex) {
   1067             dip6[0] = 0;
   1068             dip6[1] = 0;
   1069             dip6[2] = 0;
   1070             dip6[3] = 0;
   1071             info->dip = 0;
   1072             SAL_IP6_ADDR_FROM_UINT32(info->dip6,dip6);
   1073 
   1074             /* OUTER_IPV6_DIP_0_31 */
   1075             if (SOC_MEM_FIELD_VALID(unit,mem_view_id,
   1076                          DIRECT_ASSIGNMENT_10_ACTION_SETf)) {
   1077                 dip6[0] = soc_mem_field32_get(unit, mem_view_id, tnl_entry,
   1078                                         DIRECT_ASSIGNMENT_10_ACTION_SETf);
   1079             }
   1080 
   1081             /* OUTER_IPV6_DIP_32_63 */
   1082             if (SOC_MEM_FIELD_VALID(unit,mem_view_id,
   1083                          DIRECT_ASSIGNMENT_12_ACTION_SETf)) {
   1084                 dip6[1] = soc_mem_field32_get(unit, mem_view_id, tnl_entry,
   1085                                         DIRECT_ASSIGNMENT_12_ACTION_SETf);
   1086             }
   1087 
   1088             /* OUTER_IPV6_DIP_64_95 */
   1089             if (SOC_MEM_FIELD_VALID(unit,mem_view_id,
   1090                              DIRECT_ASSIGNMENT_14_ACTION_SETf)) {
   1091                 dip6[2] = soc_mem_field32_get(unit, mem_view_id, tnl_entry,
   1092                         DIRECT_ASSIGNMENT_14_ACTION_SETf);
   1093             }
   1094 
   1095             /* OUTER_IPV6_DIP_96_127 */
   1096             if (SOC_MEM_FIELD_VALID(unit,mem_view_id,
   1097                              DIRECT_ASSIGNMENT_16_ACTION_SETf)) {
   1098                 dip6[3] = soc_mem_field32_get(unit, mem_view_id, tnl_entry,
   1099                         DIRECT_ASSIGNMENT_16_ACTION_SETf);
   1100             }
   1101             if ((dip6[1] == 0) && (dip6[2] == 0) && (dip6[3] == 0)) {
   1102                 info->dip = dip6[0];
   1103             } else {
   1104                 SAL_IP6_ADDR_FROM_UINT32(info->dip6,dip6);
   1105             }
   1106         }
   1107                  
   1108         sip6[0] = 0;
   1109         sip6[1] = 0;
   1110         sip6[2] = 0;
   1111         sip6[3] = 0;
   1112         info->sip = 0;
   1113         SAL_IP6_ADDR_FROM_UINT32(info->sip6,sip6);
   1114 
   1115         if (SOC_MEM_FIELD_VALID(unit,mem_view_id,
   1116                          DIRECT_ASSIGNMENT_11_ACTION_SETf)) {
   1117             sip6[0] = soc_mem_field32_get(unit, mem_view_id, tnl_entry,
   1118                             DIRECT_ASSIGNMENT_11_ACTION_SETf);
   1119         }
   1120         if (SOC_MEM_FIELD_VALID(unit,mem_view_id,
   1121                          DIRECT_ASSIGNMENT_13_ACTION_SETf)) {
   1122             sip6[1] = soc_mem_field32_get(unit, mem_view_id, tnl_entry,
   1123                             DIRECT_ASSIGNMENT_13_ACTION_SETf);
   1124         }
   1125         if (SOC_MEM_FIELD_VALID(unit,mem_view_id,
   1126                          DIRECT_ASSIGNMENT_15_ACTION_SETf)) {
   1127             sip6[2] = soc_mem_field32_get(unit, mem_view_id, tnl_entry,
   1128                                 DIRECT_ASSIGNMENT_15_ACTION_SETf);
   1129         }
   1130         if (SOC_MEM_FIELD_VALID(unit,mem_view_id,
   1131                          DIRECT_ASSIGNMENT_17_ACTION_SETf)) {
   1132             sip6[3] = soc_mem_field32_get(unit, mem_view_id, tnl_entry,
   1133                                 DIRECT_ASSIGNMENT_17_ACTION_SETf);
   1134         }
   1135         if ((sip6[1] == 0) && (sip6[2] == 0) && (sip6[3] == 0)) {
   1136             info->sip = sip6[0];
   1137         } else {
   1138             SAL_IP6_ADDR_FROM_UINT32(info->sip6,sip6);
   1139         }
   1140 
   1141         if (SOC_MEM_FIELD_VALID(unit,mem_view_id,
   1142                          QOS_A_ACTION_SETf)) {
   1143             qos_f = QOS_A_ACTION_SETf;
   1144         } else if (SOC_MEM_FIELD_VALID(unit,mem_view_id,
   1145                          QOS_B_ACTION_SETf)) {
   1146             qos_f = QOS_B_ACTION_SETf;
   1147         } else {
   1148             qos_f = 0;
   1149         }
   1150         if (qos_f) {    
   1151             qos = soc_mem_field32_get(unit, mem_view_id, tnl_entry, qos_f);
   1152             dscp_sel = soc_format_field32_get(unit,QOS_A_ACTION_SETfmt,
   1153                                &qos,QOS_ACTION_SELf);
   1154             if (dscp_sel == _BCM_FLOW_DSCP_SEL_ASSIGN_FROM_TABLE) {
   1155                 info->dscp_sel = bcmTunnelDscpAssign;
   1156             } else if (dscp_sel == _BCM_FLOW_DSCP_SEL_COPY_FROM_ZONE) {
   1157                 info->dscp_sel = bcmTunnelDscpPacket;
   1158             } else if (dscp_sel == _BCM_FLOW_DSCP_SEL_MAP_FROM_PHB) {
   1159                 info->dscp_sel = bcmTunnelDscpMap;
   1160             } else {
   1161                 info->dscp_sel = bcmTunnelDscpCount;
   1162             }
   1163                
   1164             if (info->dscp_sel == bcmTunnelDscpMap) {
   1165                 /* Set DSCP_MAP value. */
   1166                 int hw_map_idx = 0;
   1167                 hw_map_idx = soc_format_field32_get(unit,QOS_A_ACTION_SETfmt,
   1168                                &qos,QOS_MAPPING_PTRf);
   1169                 BCM_IF_ERROR_RETURN(
   1170                     _bcm_tr2_qos_idx2id(unit, hw_map_idx,
   1171                         _BCM_QOS_MAP_TYPE_EGR_DSCP_TABLE,&info->dscp_map));
   1172             } else {
   1173                 /* Set DSCP value. */
   1174                 info->dscp = soc_format_field32_get(unit,QOS_A_ACTION_SETfmt,
   1175                                    &qos,QOS_VALUEf);
   1176             }
   1177         }
   1178         if (SOC_MEM_FIELD_VALID(unit,mem_view_id, TTL_B_ACTION_SETf)) {
   1179             ttl = soc_mem_field32_get(unit, mem_view_id, tnl_entry, 
   1180                           TTL_B_ACTION_SETf);
   1181             info->ttl = soc_format_field32_get(unit,TTL_B_ACTION_SETfmt,
   1182                                &ttl,TTL_VALUEf);
   1183         }
   1184 
   1185         /* Set UDP Dest Port */
   1186         if (SOC_MEM_FIELD_VALID(unit,mem_view_id, 
   1187                              DIRECT_ASSIGNMENT_18_ACTION_SETf)) {
   1188             info->udp_dst_port = soc_mem_field32_get(unit, mem_view_id, 
   1189                           tnl_entry, DIRECT_ASSIGNMENT_18_ACTION_SETf);
   1190         }
   1191 
   1192         /* Set UDP Src Port */
   1193         if (SOC_MEM_FIELD_VALID(unit,mem_view_id, 
   1194                              DIRECT_ASSIGNMENT_19_ACTION_SETf)) {
   1195             info->udp_src_port = soc_mem_field32_get(unit, mem_view_id, 
   1196                          tnl_entry, DIRECT_ASSIGNMENT_19_ACTION_SETf);
   1197         }
   1198 
   1199         /* FRAGMENT ID */
   1200         if (SOC_MEM_FIELD_VALID(unit,mem_view_id,
   1201                          SEQUENCE_NUMBER_ACTION_SETf)) {
   1202             uint32 seq_num;
   1203             uint32 inx;
   1204  
   1205             seq_num = soc_mem_field32_get(unit, mem_view_id, tnl_entry, 
   1206                             SEQUENCE_NUMBER_ACTION_SETf);
   1207             inx = soc_format_field32_get(unit,SEQUENCE_NUMBER_ACTION_SETfmt,
   1208                                   &seq_num, SEQ_NUM_COUNTER_INDEXf);
   1209             SOC_IF_ERROR_RETURN(soc_mem_read(unit, EGR_SEQUENCE_NUMBER_TABLEm,
   1210                                MEM_BLOCK_ANY, inx, &entry));
   1211             info->ip4_id = soc_mem_field32_get(unit, EGR_SEQUENCE_NUMBER_TABLEm,
   1212                                      &entry, SEQUENCE_NUMBERf);
   1213         }
   1214 
   1215     }
   1216 
   1217     if ((fixed_view == FALSE) && (field != NULL) && (num_of_fields)) {
   1218         rv = soc_flow_db_mem_view_field_list_get(unit,
   1219                       mem_view_id,
   1220                       SOC_FLOW_DB_FIELD_TYPE_LOGICAL_POLICY_DATA,
   1221                       _BCM_FLOW_LOGICAL_FIELD_MAX, data_ids, &cnt);
   1222         SOC_IF_ERROR_RETURN(rv);
   1223 
   1224         if (field_cnt == NULL) { 
   1225             for (i = 0; i < num_of_fields; i++) {
   1226                 for (j = 0; j < cnt; j++) {
   1227                     if (field[i].id == data_ids[j]) {
   1228                         field[i].value = soc_mem_field32_get(unit,mem_view_id,
   1229                                              tnl_entry, field[i].id);
   1230                         break;
   1231                     }
   1232                 }
   1233             }
   1234         } else {
   1235             *field_cnt = cnt < num_of_fields? cnt: num_of_fields;
   1236             if (cnt > num_of_fields) {
   1237                 cnt = num_of_fields;
   1238             }
   1239             for (i = 0; i < cnt; i++) {
   1240                 field[i].id = data_ids[i];
   1241                 field[i].value = soc_mem_field32_get(unit,mem_view_id, tnl_entry,
   1242                          field[i].id);
   1243             }
   1244         }
   1245     }
   1246     return BCM_E_NONE;
   1247 }
   1248 
   1249 /*
   1250  * Function:
   1251  *      _bcm_flow_tunnel_init_set
   1252  * Purpose:
   1253  *      Add tunnel initiator entry to hw.
   1254  * Parameters:
   1255  *      unit     - (IN)SOC unit number.
   1256  *      idx      - (IN)Index to insert tunnel initiator.
   1257  *      info     - (IN)Tunnel initiator entry info.
   1258  * Returns:
   1259  *      BCM_E_XXX
   1260  */
   1261 STATIC int
   1262 _bcm_flow_tunnel_init_set(int unit, 
   1263     int idx, 
   1264     bcm_flow_tunnel_initiator_t *info,
   1265     bcm_flow_logical_field_t *field,
   1266     int num_of_fields,
   1267     int *tnl_in_oif)
   1268 {
   1269     uint32 tnl_entry[SOC_MAX_MEM_FIELD_WORDS]; /* Buffer to write hw entry */
   1270     soc_mem_t mem;                        /* Tunnel initiator table memory */
   1271     soc_mem_t mem_view;
   1272     int rv = BCM_E_NONE;                  /* Return value                  */
   1273     int df_val=0;                           /* Don't fragment encoding       */
   1274     uint32 sip6[4];
   1275     uint32 dip6[4];
   1276     uint32 data_ids[_BCM_FLOW_LOGICAL_FIELD_MAX];
   1277     uint32 cnt;
   1278     int i;
   1279     int j;
   1280     int ipv6;
   1281     int entry_type = BCM_XGS3_TUNNEL_INIT_V4;
   1282     uint16 random;
   1283     egr_sequence_number_table_entry_t entry;
   1284     _bcm_flow_bookkeeping_t *flow_info;
   1285 
   1286     flow_info = FLOW_INFO(unit);
   1287 
   1288     ipv6 = _BCM_TUNNEL_OUTER_HEADER_IPV6(info->type);
   1289     if (_BCM_FLOW_TUNNEL_ENTRY_DOUBLE_WIDE(info->type)) {
   1290         idx >>= 1;
   1291         mem = BCM_XGS3_L3_MEM(unit, tnl_init_v6);
   1292     } else {
   1293         mem =  BCM_XGS3_L3_MEM(unit, tnl_init_v4);
   1294     }
   1295     if (!SOC_MEM_IS_VALID(unit, mem)) {
   1296         return (BCM_E_UNAVAIL);
   1297     }
   1298 
   1299     rv = _bcm_flow_tunnel_dip_idx_set(unit, info, idx, tnl_in_oif);
   1300     BCM_IF_ERROR_RETURN(rv);
   1301 
   1302     /* get the physical memory view */
   1303     if (_BCM_FLOW_IS_FLEX_VIEW(info)) {
   1304         rv = soc_flow_db_ffo_to_mem_view_id_get(unit,info->flow_handle,
   1305                    info->flow_option, 
   1306                    SOC_FLOW_DB_FUNC_TUNNEL_INITIATOR_ID,
   1307                     (uint32 *)&mem_view);
   1308         BCM_IF_ERROR_RETURN(rv);
   1309     }
   1310 
   1311     soc_mem_lock(unit,mem);
   1312     if (info->flags & BCM_TUNNEL_REPLACE) {
   1313         rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, idx, tnl_entry);
   1314         if (SOC_FAILURE(rv)) {
   1315             soc_mem_unlock(unit,mem);
   1316             return rv;
   1317         }
   1318     } else {
   1319         /* Zero write buffer. */
   1320         sal_memset(tnl_entry, 0, sizeof(tnl_entry));
   1321         if (_BCM_FLOW_IS_FLEX_VIEW(info)) {
   1322             soc_flow_db_mem_view_entry_init(unit,mem_view,tnl_entry);
   1323         }
   1324     }
   1325 
   1326     /* flex view doesn't seem to have these functions */
   1327     if (!_BCM_FLOW_IS_FLEX_VIEW(info)) {
   1328 
   1329        if ((!ipv6) && SOC_MEM_FIELD_VALID(unit, mem, IPV4_DF_SELf)) {
   1330            /* Outer IPv4 tunnel hdr DF bit for Inner IPv4 hdr. */
   1331            df_val = 0;
   1332            if (info->flags & BCM_TUNNEL_INIT_USE_INNER_DF) {
   1333                df_val |= 0x2;
   1334            } else if (info->flags & BCM_TUNNEL_INIT_IPV4_SET_DF) {
   1335                df_val |= 0x1;
   1336            }
   1337            soc_mem_field32_set(unit, mem, tnl_entry, IPV4_DF_SELf, df_val);
   1338         }
   1339 
   1340         if ((!ipv6) && SOC_MEM_FIELD_VALID(unit, mem, IPV6_DF_SELf)) {
   1341             /* Outer IPv4 tunnel hdr DF bit for Inner IPv6 hdr. */
   1342             df_val = (info->flags & BCM_TUNNEL_INIT_IPV6_SET_DF) ? 0x1 : 0;
   1343             soc_mem_field32_set(unit, mem, tnl_entry, IPV6_DF_SELf, df_val);
   1344         }
   1345 
   1346     }
   1347 
   1348     if (!_BCM_FLOW_IS_FLEX_VIEW(info)) {
   1349 
   1350         if (ipv6) {
   1351             if (info->valid_elements & BCM_FLOW_TUNNEL_INIT_DIP6_VALID) {
   1352                 /* Set destination ipv6 address. */
   1353                 soc_mem_ip6_addr_set(unit, mem, tnl_entry, DIPf, info->dip6,
   1354                                      SOC_MEM_IP6_FULL_ADDR);
   1355             }
   1356 
   1357             if (info->valid_elements & BCM_FLOW_TUNNEL_INIT_SIP6_VALID) {
   1358                 /* Set source ipv6 address. */
   1359                 soc_mem_ip6_addr_set(unit, mem, tnl_entry, SIPf, info->sip6,
   1360                                  SOC_MEM_IP6_FULL_ADDR);
   1361             }
   1362         } else {
   1363             if (info->valid_elements & BCM_FLOW_TUNNEL_INIT_DIP_VALID) {
   1364                 /* Set destination address. */
   1365                 soc_mem_field_set(unit, mem, tnl_entry, DIPf, 
   1366                                                (uint32 *)&info->dip);
   1367             }
   1368 
   1369             if (info->valid_elements & BCM_FLOW_TUNNEL_INIT_SIP_VALID) {
   1370                 /* Set source address. */
   1371                 soc_mem_field_set(unit, mem, tnl_entry, SIPf, 
   1372                                                (uint32 *)&info->sip);
   1373             }
   1374         }
   1375 
   1376         if (info->valid_elements & BCM_FLOW_TUNNEL_INIT_DSCP_VALID) {
   1377             /* Tunnel header DSCP select. */
   1378             soc_mem_field32_set(unit, mem, tnl_entry, DSCP_SELf,info->dscp_sel);
   1379 
   1380             if (info->dscp_sel == bcmTunnelDscpMap) {
   1381                 /* Set DSCP_MAP value. */
   1382                 int hw_map_idx = 0;
   1383                 rv = _bcm_tr2_qos_id2idx(unit, info->dscp_map, &hw_map_idx);
   1384                 if (SOC_FAILURE(rv)) {
   1385                     soc_mem_unlock(unit,mem);
   1386                     return rv;
   1387                 }
   1388             
   1389                 soc_mem_field32_set(unit, mem, tnl_entry,
   1390                             DSCP_MAPPING_PTRf, hw_map_idx);
   1391             } else {
   1392                 /* Set DSCP value. */
   1393                 soc_mem_field32_set(unit, mem, tnl_entry, DSCPf, info->dscp);
   1394             }
   1395         }
   1396 
   1397         /* Set TTL. */
   1398         if (info->valid_elements & BCM_FLOW_TUNNEL_INIT_TTL_VALID) {
   1399             soc_mem_field32_set(unit, mem, tnl_entry, TTLf, info->ttl);
   1400         }
   1401 
   1402         /* Set UDP Dest Port */
   1403         if (info->valid_elements & BCM_FLOW_TUNNEL_INIT_UDP_DPORT_VALID) {
   1404             soc_mem_field32_set(unit, mem, tnl_entry, L4_DEST_PORTf, 
   1405                             info->udp_dst_port);
   1406         }
   1407 
   1408         /* Set UDP Src Port */
   1409         if (info->valid_elements & BCM_FLOW_TUNNEL_INIT_UDP_SPORT_VALID) {
   1410             soc_mem_field32_set(unit, mem, tnl_entry, L4_SRC_PORTf, 
   1411                                 info->udp_src_port);
   1412         }
   1413 
   1414         /* Set destination mac address. */
   1415         if (info->valid_elements & BCM_FLOW_TUNNEL_INIT_DMAC_VALID) {
   1416             if (SOC_MEM_FIELD_VALID(unit, mem, DEST_ADDRf)) {
   1417                 soc_mem_mac_addr_set(unit, mem, &tnl_entry, DEST_ADDRf, 
   1418                                      info->dmac);
   1419             }
   1420         }
   1421 
   1422         /* IPv4 Fragment ID  */
   1423         if (info->valid_elements & BCM_FLOW_TUNNEL_INIT_IP4_ID_VALID) {
   1424             sal_memset(&entry,0,sizeof(egr_sequence_number_table_entry_t));
   1425             if (info->flags & BCM_TUNNEL_INIT_IP4_ID_SET_FIXED) {
   1426                 soc_EGR_SEQUENCE_NUMBER_TABLEm_field32_set(unit, &entry,
   1427                                     SEQUENCE_NUMBERf, info->ip4_id);
   1428             } else if (info->flags & BCM_TUNNEL_INIT_IP4_ID_SET_RANDOM) {
   1429                 random = (uint16) (sal_time_usecs() & 0xFFFF);
   1430                 soc_EGR_SEQUENCE_NUMBER_TABLEm_field32_set(unit, &entry,
   1431                                                SEQUENCE_NUMBERf, random);
   1432             }
   1433             rv = soc_mem_write(unit, EGR_SEQUENCE_NUMBER_TABLEm, 
   1434                     MEM_BLOCK_ANY, idx + flow_info->frag_base_inx, &entry);
   1435             if (SOC_FAILURE(rv)) {
   1436                 soc_mem_unlock(unit,mem);
   1437                 return rv;
   1438             }
   1439         }
   1440  
   1441         if (info->type == bcmTunnelTypeVxlan) {
   1442             /* Set Tunnel type = VXLAN */
   1443             soc_mem_field32_set(unit, mem, tnl_entry, TUNNEL_TYPEf, 
   1444                                   _BCM_FLOW_VXLAN_TUNNEL_TYPE);
   1445         } else if (info->type == bcmTunnelTypeL2Gre) {
   1446             /* Set Tunnel type = L2GRE */
   1447             soc_mem_field32_set(unit, mem, tnl_entry, TUNNEL_TYPEf, 
   1448                                   _BCM_FLOW_L2GRE_TUNNEL_TYPE);
   1449         } else {
   1450             int hw_code;
   1451 
   1452             rv = _bcm_trx_tnl_type_to_hw_code(unit, info->type,
   1453                                  &hw_code, &entry_type);
   1454             if (SOC_FAILURE(rv)) {
   1455                 soc_mem_unlock(unit,mem);
   1456                 return rv;
   1457             }
   1458             soc_mem_field32_set(unit, mem, tnl_entry, TUNNEL_TYPEf, 
   1459                                   hw_code);
   1460 
   1461         }
   1462 
   1463         /* Set entry type = IPv4 */
   1464         if (entry_type == BCM_XGS3_TUNNEL_INIT_V6) {
   1465             soc_mem_field32_set(unit, mem, tnl_entry, DATA_TYPEf, 
   1466                         _BCM_FLOW_TUNNEL_DATA_TYPE_IPV6);
   1467         } else {   /* ipv4 */
   1468             soc_mem_field32_set(unit, mem, tnl_entry, DATA_TYPEf, 
   1469                          _BCM_FLOW_TUNNEL_DATA_TYPE_IPV4);
   1470         }
   1471        
   1472     } else {  /* flex view */
   1473         uint32 qos = 0;
   1474         uint32 ttl = 0;
   1475 
   1476         if (info->type == bcmTunnelTypeL3Flex) {
   1477             if (info->valid_elements & BCM_FLOW_TUNNEL_INIT_DIP_VALID) {
   1478                 if (SOC_MEM_FIELD_VALID(unit,mem_view,
   1479                              DIRECT_ASSIGNMENT_10_ACTION_SETf)) {
   1480                     soc_mem_field32_set(unit, mem_view, tnl_entry,
   1481                                 DIRECT_ASSIGNMENT_10_ACTION_SETf, info->dip);
   1482                 }
   1483             }  
   1484             if (info->valid_elements & BCM_FLOW_TUNNEL_INIT_DIP6_VALID) {
   1485      
   1486                 SAL_IP6_ADDR_TO_UINT32(info->dip6,dip6);
   1487 
   1488                 /* OUTER_IPV6_DIP_0_31 */
   1489                 if (SOC_MEM_FIELD_VALID(unit,mem_view,
   1490                              DIRECT_ASSIGNMENT_10_ACTION_SETf)) {
   1491                     soc_mem_field32_set(unit, mem_view, tnl_entry,
   1492                         DIRECT_ASSIGNMENT_10_ACTION_SETf, dip6[0]);
   1493                 }
   1494 
   1495                 /* OUTER_IPV6_DIP_32_63 */
   1496                 if (SOC_MEM_FIELD_VALID(unit,mem_view,
   1497                              DIRECT_ASSIGNMENT_12_ACTION_SETf)) {
   1498                     soc_mem_field32_set(unit, mem_view, tnl_entry,
   1499                         DIRECT_ASSIGNMENT_12_ACTION_SETf, dip6[1]);
   1500                 }
   1501 
   1502                 /* OUTER_IPV6_DIP_64_95 */
   1503                 if (SOC_MEM_FIELD_VALID(unit,mem_view,
   1504                              DIRECT_ASSIGNMENT_14_ACTION_SETf)) {
   1505                     soc_mem_field32_set(unit, mem_view, tnl_entry,
   1506                         DIRECT_ASSIGNMENT_14_ACTION_SETf, dip6[2]);
   1507                 }
   1508 
   1509                 /* OUTER_IPV6_DIP_96_127 */
   1510                 if (SOC_MEM_FIELD_VALID(unit,mem_view,
   1511                              DIRECT_ASSIGNMENT_16_ACTION_SETf)) {
   1512                     soc_mem_field32_set(unit, mem_view, tnl_entry,
   1513                         DIRECT_ASSIGNMENT_16_ACTION_SETf, dip6[3]);
   1514                 }
   1515             }
   1516         }
   1517         if (info->valid_elements & BCM_FLOW_TUNNEL_INIT_SIP_VALID) {
   1518             soc_mem_field32_set(unit, mem_view, tnl_entry,
   1519                 DIRECT_ASSIGNMENT_11_ACTION_SETf, info->sip);
   1520         }
   1521         if (info->valid_elements & BCM_FLOW_TUNNEL_INIT_SIP6_VALID) {
   1522             SAL_IP6_ADDR_TO_UINT32(info->sip6,sip6);
   1523             soc_mem_field32_set(unit, mem_view, tnl_entry,
   1524                 DIRECT_ASSIGNMENT_11_ACTION_SETf, sip6[0]);
   1525             soc_mem_field32_set(unit, mem_view, tnl_entry,
   1526                 DIRECT_ASSIGNMENT_13_ACTION_SETf, sip6[1]);
   1527             soc_mem_field32_set(unit, mem_view, tnl_entry,
   1528                 DIRECT_ASSIGNMENT_15_ACTION_SETf, sip6[2]);
   1529             soc_mem_field32_set(unit, mem_view, tnl_entry,
   1530                 DIRECT_ASSIGNMENT_17_ACTION_SETf, sip6[3]);
   1531         } 
   1532 
   1533         if (info->valid_elements & BCM_FLOW_TUNNEL_INIT_DSCP_VALID) {
   1534             int sel_value;
   1535 
   1536             if (info->dscp_sel == bcmTunnelDscpAssign) {
   1537                 sel_value = _BCM_FLOW_DSCP_SEL_ASSIGN_FROM_TABLE; 
   1538             } else if (info->dscp_sel == bcmTunnelDscpPacket) {
   1539                 sel_value = _BCM_FLOW_DSCP_SEL_COPY_FROM_ZONE; 
   1540             } else if (info->dscp_sel == bcmTunnelDscpMap) {
   1541                 sel_value = _BCM_FLOW_DSCP_SEL_MAP_FROM_PHB; 
   1542             } else {
   1543                 sel_value = 0; /* do not modify */
   1544             }
   1545             soc_format_field32_set(unit,QOS_A_ACTION_SETfmt,
   1546                                &qos,QOS_ACTION_SELf, sel_value);
   1547             if (info->dscp_sel == bcmTunnelDscpMap) {
   1548                 /* Set DSCP_MAP value. */
   1549                 int hw_map_idx = 0;
   1550                 rv = _bcm_tr2_qos_id2idx(unit, info->dscp_map, &hw_map_idx);
   1551                 if (SOC_FAILURE(rv)) {
   1552                     soc_mem_unlock(unit,mem);
   1553                     return rv;
   1554                 }
   1555                 soc_format_field32_set(unit,QOS_A_ACTION_SETfmt,
   1556                                &qos,QOS_MAPPING_PTRf, hw_map_idx);
   1557             } else {
   1558                 /* Set DSCP value. */
   1559                 soc_format_field32_set(unit,QOS_A_ACTION_SETfmt,
   1560                                    &qos,QOS_VALUEf, info->dscp);
   1561             }
   1562             soc_mem_field32_set(unit, mem_view, tnl_entry, QOS_A_ACTION_SETf, qos);
   1563         }
   1564 
   1565         /* Set TTL. */
   1566         soc_format_field32_set(unit,TTL_B_ACTION_SETfmt,
   1567                            &ttl,TTL_ACTION_TYPEf, 1);
   1568         if (info->valid_elements & BCM_FLOW_TUNNEL_INIT_TTL_VALID) {
   1569             soc_format_field32_set(unit,TTL_B_ACTION_SETfmt,
   1570                                &ttl,TTL_VALUEf, info->ttl);
   1571         } else {
   1572             soc_format_field32_set(unit,TTL_B_ACTION_SETfmt,
   1573                                &ttl,TTL_VALUEf, 0xff);
   1574         }
   1575         soc_mem_field32_set(unit, mem_view, tnl_entry, TTL_B_ACTION_SETf, ttl);
   1576 
   1577         /* Set UDP Dest Port */
   1578         if (info->valid_elements & BCM_FLOW_TUNNEL_INIT_UDP_DPORT_VALID) {
   1579             soc_mem_field32_set(unit, mem_view, tnl_entry, 
   1580                          DIRECT_ASSIGNMENT_18_ACTION_SETf, info->udp_dst_port);
   1581         }
   1582 
   1583         /* Set UDP Src Port */
   1584         if (info->valid_elements & BCM_FLOW_TUNNEL_INIT_UDP_SPORT_VALID) {
   1585             soc_mem_field32_set(unit, mem_view, tnl_entry, 
   1586                          DIRECT_ASSIGNMENT_19_ACTION_SETf, info->udp_src_port);
   1587         }
   1588 
   1589         if (SOC_MEM_FIELD_VALID(unit,mem_view, ECN_ACTION_SETf)) {
   1590             uint32 ecn = 0;
   1591             soc_format_field32_set(unit,ECN_ACTION_SETfmt,&ecn, ECN_VALUEf, 0);
   1592             soc_format_field32_set(unit,ECN_ACTION_SETfmt,&ecn, CHANGE_ECNf, 1);
   1593             soc_mem_field32_set(unit, mem_view, tnl_entry, ECN_ACTION_SETf, ecn);
   1594         }
   1595 
   1596         if (info->valid_elements & BCM_FLOW_TUNNEL_INIT_IP4_ID_VALID) {
   1597             uint32 seq_num = 0;
   1598 
   1599             /* Use the same tunnel base as for the fixed view */
   1600             soc_format_field32_set(unit,SEQUENCE_NUMBER_ACTION_SETfmt,
   1601                               &seq_num, SEQ_NUM_PROFILE_INDEXf, 1);
   1602             soc_format_field32_set(unit,SEQUENCE_NUMBER_ACTION_SETfmt,
   1603                                   &seq_num, SEQ_NUM_COUNTER_INDEXf, 
   1604                                   idx + flow_info->frag_base_inx);
   1605             soc_mem_field32_set(unit, mem_view, tnl_entry, 
   1606                          SEQUENCE_NUMBER_ACTION_SETf, seq_num);
   1607             sal_memset(&entry,0,sizeof(egr_sequence_number_table_entry_t));
   1608             if (info->flags & BCM_TUNNEL_INIT_IP4_ID_SET_FIXED) {
   1609                 soc_EGR_SEQUENCE_NUMBER_TABLEm_field32_set(unit, &entry,
   1610                                    SEQUENCE_NUMBERf, info->ip4_id);
   1611             } else if (info->flags & BCM_TUNNEL_INIT_IP4_ID_SET_RANDOM) {
   1612                 random = (uint16) (sal_time_usecs() & 0xFFFF);
   1613                 soc_EGR_SEQUENCE_NUMBER_TABLEm_field32_set(unit, &entry,
   1614                                    SEQUENCE_NUMBERf, random);
   1615             }
   1616             rv = soc_mem_write(unit, EGR_SEQUENCE_NUMBER_TABLEm,
   1617                     MEM_BLOCK_ANY, idx + flow_info->frag_base_inx, &entry);
   1618             if (SOC_FAILURE(rv)) {
   1619                 soc_mem_unlock(unit,mem);
   1620                 return rv;
   1621             }
   1622         }
   1623  
   1624         if (info->valid_elements & BCM_FLOW_TUNNEL_INIT_FLEX_VALID) {
   1625             rv = soc_flow_db_mem_view_field_list_get(unit,
   1626                       mem_view,
   1627                       SOC_FLOW_DB_FIELD_TYPE_LOGICAL_POLICY_DATA,
   1628                       _BCM_FLOW_LOGICAL_FIELD_MAX, data_ids, &cnt);
   1629             if (SOC_FAILURE(rv)) {
   1630                 soc_mem_unlock(unit,mem);
   1631                 return rv;
   1632             }
   1633             for (i = 0; i < num_of_fields; i++) {
   1634                 for (j = 0; j < cnt; j++) {
   1635                     if (field[i].id == data_ids[j]) {
   1636                         soc_mem_field32_set(unit,mem_view, tnl_entry,
   1637                               field[i].id, field[i].value);
   1638                         break;
   1639                     }
   1640                 }
   1641             }
   1642         }
   1643     }
   1644 
   1645     /* Write buffer to hw. */
   1646     rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, idx, tnl_entry);
   1647     soc_mem_unlock(unit,mem);
   1648     return rv;
   1649 }
   1650 
   1651 /*
   1652  * Function:
   1653  *      _bcm_flow_tunnel_initiator_entry_add
   1654  * Purpose:
   1655  *      Configure VXLAN Tunnel initiator hardware Entry
   1656  * Returns:
   1657  *      BCM_E_XXX
   1658  */
   1659 STATIC int
   1660 _bcm_flow_tunnel_initiator_entry_add(int unit, 
   1661      uint32 flags, 
   1662      bcm_flow_tunnel_initiator_t *info, 
   1663     bcm_flow_logical_field_t *field,
   1664     uint32 num_of_fields)
   1665 {
   1666     int tnl_idx;
   1667     int rv = BCM_E_NONE;
   1668     _bcm_flow_bookkeeping_t *flow_info;
   1669     int dvp;
   1670     int soft_tnl_idx = 0;
   1671     int tnl_in_oif;
   1672     int oif_idx;
   1673 
   1674     flow_info = FLOW_INFO(unit);
   1675 
   1676     if (info->flags & BCM_TUNNEL_REPLACE) {
   1677         soft_tnl_idx = BCM_GPORT_TUNNEL_ID_GET(info->tunnel_id);
   1678         tnl_idx = flow_info->init_tunnel[soft_tnl_idx].idx;
   1679         if (tnl_idx >= _BCM_FLOW_TUNNEL_IP_TUNNEL_MAX(unit)) {
   1680             /* l3_oif index */
   1681             oif_idx = tnl_idx - _BCM_FLOW_TUNNEL_IP_TUNNEL_MAX(unit);
   1682             BCM_IF_ERROR_RETURN(_bcm_flow_tunnel_idx_from_oif_get(unit,
   1683                                      oif_idx, &tnl_idx));
   1684             info->l3_intf_id = oif_idx;
   1685         }
   1686 
   1687         /* cannot modify if this tunnel is used more than once */
   1688         if (BCM_XGS3_L3_ENT_REF_CNT(BCM_XGS3_L3_TBL_PTR(unit, tnl_init),tnl_idx)
   1689              > 1) {
   1690             return BCM_E_PARAM;
   1691         }
   1692     }
   1693 
   1694     rv = _bcm_flow_tnl_init_add(unit, flags, info, field,
   1695                                 num_of_fields,&tnl_idx);
   1696     if (BCM_FAILURE(rv)) {
   1697           return rv;
   1698     }
   1699     /* Write the entry to HW */
   1700     rv = _bcm_flow_tunnel_init_set(unit, tnl_idx, info,field,num_of_fields,
   1701                       &tnl_in_oif);
   1702     if (BCM_FAILURE(rv)) {
   1703         flags = _BCM_L3_SHR_WRITE_DISABLE;
   1704         (void) bcm_xgs3_tnl_init_del(unit, flags, tnl_idx);
   1705         BCM_IF_ERROR_RETURN(rv);
   1706     }
   1707     if (_BCM_FLOW_TUNNEL_TYPE_L2(info->type)) {
   1708         if (!(info->flags & BCM_TUNNEL_REPLACE)) {
   1709             dvp = _SHR_GPORT_FLOW_PORT_ID_GET(info->flow_port);
   1710             soft_tnl_idx = dvp;
   1711         }
   1712         if (tnl_in_oif == TRUE) { 
   1713             /* tunnel index in oif, save oif instead */
   1714             flow_info->init_tunnel[soft_tnl_idx].idx = 
   1715                 _BCM_FLOW_TUNNEL_IP_TUNNEL_MAX(unit) + info->l3_intf_id;
   1716         } else {    
   1717             flow_info->init_tunnel[soft_tnl_idx].idx = tnl_idx;  
   1718         }
   1719     } else { /* L3 tunnel */
   1720         if (!(info->flags & BCM_TUNNEL_REPLACE)) {
   1721             soft_tnl_idx = _BCM_FLOW_TUNNEL_L2_MAX(unit) + info->l3_intf_id;
   1722         }
   1723         flow_info->init_tunnel[soft_tnl_idx].idx = tnl_idx;  
   1724     }
   1725     BCM_GPORT_TUNNEL_ID_SET(info->tunnel_id,soft_tnl_idx);
   1726     return rv;
   1727 }
   1728 
   1729 /*
   1730  * Function:
   1731  *      _bcm_esw_flow_tnl_initiator_validate
   1732  * Purpose:
   1733  *      Validate  the tunnel initiator attributes
   1734  *
   1735  * Parameters:
   1736  *      unit          - (IN) Device Number
   1737  *      info          - (IN) Flow tunnel initiator descriptor
   1738  * Returns:
   1739  *      TRUE/FALSE
   1740  */
   1741 STATIC
   1742 int _bcm_esw_flow_tnl_initiator_validate(
   1743     int unit,
   1744     bcm_flow_tunnel_initiator_t *info)
   1745 {
   1746     if (NULL == info) {
   1747         return (BCM_E_PARAM);
   1748     }
   1749     if ((!_BCM_FLOW_TUNNEL_TYPE_L2(info->type)) &&
   1750         (!_BCM_FLOW_TUNNEL_TYPE_L3(info->type))) {
   1751         LOG_ERROR(BSL_LS_BCM_FLOW, (BSL_META_U(unit,
   1752          "Flow Tunnel Initiation: Invalid tunnel type.\n")));
   1753         return BCM_E_PARAM;
   1754     }
   1755 
   1756     if (((info->flow_handle == SOC_FLOW_DB_FLOW_ID_LEGACY_VXLAN) &&
   1757         (info->type != bcmTunnelTypeVxlan)) ||
   1758         ((info->flow_handle == SOC_FLOW_DB_FLOW_ID_LEGACY_L2GRE) &&
   1759         (info->type != bcmTunnelTypeL2Gre)) ||
   1760         ((info->flow_handle >= SOC_FLOW_DB_FLOW_ID_START) &&
   1761         ((info->type == bcmTunnelTypeL2Gre) ||
   1762         (info->type == bcmTunnelTypeVxlan)))) {
   1763         LOG_ERROR(BSL_LS_BCM_FLOW, (BSL_META_U(unit,
   1764         "Flow Tunnel Initiation: tunnel type and flow handle mismatch.\n")));
   1765         return BCM_E_PARAM;
   1766     }
   1767 
   1768     return BCM_E_NONE;
   1769 }
   1770 
   1771 /*
   1772  * Function:
   1773  *      bcmi_esw_flow_tunnel_initiator_create
   1774  * Purpose:
   1775  *      Create a flow tunnel initiator object on the given flow port for L2
   1776  * tunnel or on the given L3 interface for L3 tunnel.
   1777  *
   1778  * Parameters:
   1779  *      unit    - (IN) Device Number
   1780  *      info    - (IN/OUT) Flow tunnel initiator descriptor
   1781  *      num_of_fields - (IN) number of logical fields
   1782  *      field         - (IN) logical field array
   1783  * Returns:
   1784  *      BCM_E_XXX
   1785  */
   1786 int bcmi_esw_flow_tunnel_initiator_create(
   1787     int unit,
   1788     bcm_flow_tunnel_initiator_t *info,
   1789     uint32 num_of_fields,
   1790     bcm_flow_logical_field_t *field)
   1791 {
   1792     int rv = BCM_E_NONE;
   1793     uint32 flags=0;
   1794     int soft_tnl_idx;
   1795     _bcm_flow_bookkeeping_t *flow_info;
   1796     int dvp;
   1797     int l2_tunnel;
   1798 
   1799     flow_info = FLOW_INFO(unit);
   1800 
   1801     BCM_IF_ERROR_RETURN(_bcm_esw_flow_tnl_initiator_validate(unit, info));
   1802 
   1803     l2_tunnel = FALSE;
   1804 
   1805     if (info->flags & BCM_TUNNEL_REPLACE) {
   1806 
   1807         /* validate the tunnel index */
   1808         soft_tnl_idx = BCM_GPORT_TUNNEL_ID_GET(info->tunnel_id);
   1809         _BCM_FLOW_TUNNEL_ID_IF_INVALID_RETURN(unit, soft_tnl_idx);
   1810 
   1811         /* check if tunnel exist */
   1812         if (!flow_info->init_tunnel[soft_tnl_idx].idx) {
   1813             LOG_ERROR(BSL_LS_BCM_FLOW, (BSL_META_U(unit, 
   1814                "Invalid replace action, tunnel not created\n")));
   1815             return BCM_E_PARAM;
   1816         }
   1817         if (soft_tnl_idx < _BCM_FLOW_TUNNEL_L2_MAX(unit)) {
   1818             l2_tunnel = TRUE;
   1819         }
   1820         
   1821         if (l2_tunnel) {    
   1822             /* flow_port and l3_intf_id cannot be replaced */
   1823             _SHR_GPORT_FLOW_PORT_ID_SET(info->flow_port,soft_tnl_idx);
   1824         } else {
   1825             /* L3 tunnel */
   1826             info->l3_intf_id = soft_tnl_idx - _BCM_FLOW_TUNNEL_L2_MAX(unit);
   1827         }          
   1828     } else {
   1829         if (_BCM_FLOW_TUNNEL_TYPE_L2(info->type)) {
   1830             l2_tunnel = TRUE;
   1831         }
   1832     } 
   1833 
   1834     /* Input parameters check. */
   1835     if (l2_tunnel) {
   1836 
   1837        /* check the dvp is in range and already created and dvp_encap is set
   1838         * The dvp entry should be already initialized. flow_port_encap_set 
   1839         * should be called first
   1840         */
   1841         dvp = _SHR_GPORT_FLOW_PORT_ID_GET(info->flow_port);
   1842         _BCM_FLOW_TUNNEL_ID_IF_INVALID_RETURN(unit, dvp);
   1843 
   1844         if (!_BCM_FLOW_EGR_DVP_USED_GET(unit,dvp)) {
   1845             LOG_ERROR(BSL_LS_BCM_FLOW, (BSL_META_U(unit,
   1846                "dvp(%d) type not set, call bcm_flow_port_encap_set first\n"), 
   1847                  dvp));
   1848             return BCM_E_PARAM;
   1849         }
   1850 
   1851         if (!(info->flags & BCM_TUNNEL_REPLACE)) {
   1852             soft_tnl_idx = dvp;
   1853             if (flow_info->init_tunnel[soft_tnl_idx].idx) {
   1854                 LOG_ERROR(BSL_LS_BCM_FLOW, (BSL_META_U(unit, 
   1855                    "tunnel already created, use replace action to change\n")));
   1856                 return BCM_E_PARAM;
   1857             }
   1858         }
   1859     } else {   /* l3 tunnel */
   1860         /* make sure intf_id is valid */
   1861         if (info->l3_intf_id >= _BCM_FLOW_TUNNEL_L3_MAX(unit)) {
   1862             LOG_ERROR(BSL_LS_BCM_FLOW, (BSL_META_U(unit, 
   1863                "Invalid l3 interface ID\n")));
   1864             return BCM_E_PARAM;
   1865         }
   1866         if (!(info->flags & BCM_TUNNEL_REPLACE)) {
   1867             soft_tnl_idx = _BCM_FLOW_TUNNEL_L2_MAX(unit) + info->l3_intf_id;
   1868             /* tunnel already exists */
   1869             if (flow_info->init_tunnel[soft_tnl_idx].idx) {
   1870                 LOG_ERROR(BSL_LS_BCM_FLOW, (BSL_META_U(unit, 
   1871                    "L3 tunnel exists, use replace action to change\n")));
   1872                 return BCM_E_PARAM;
   1873             }
   1874         }
   1875     }
   1876     if (info->valid_elements & BCM_FLOW_TUNNEL_INIT_TTL_VALID) { 
   1877         if (!BCM_TTL_VALID(info->ttl)) {
   1878             return BCM_E_PARAM;
   1879         }
   1880     }
   1881     if (info->valid_elements & BCM_FLOW_TUNNEL_INIT_DSCP_VALID) {
   1882         if (info->dscp_sel > 2 || info->dscp_sel < 0) {
   1883             return BCM_E_PARAM;
   1884         }
   1885         
   1886         if (info->dscp > 63 || info->dscp < 0) {
   1887             return BCM_E_PARAM;
   1888         }
   1889     }
   1890     if (info->valid_elements & BCM_FLOW_TUNNEL_INIT_FLEX_VALID) {
   1891         if ((field == NULL) || (!num_of_fields)) {
   1892             return BCM_E_PARAM;
   1893         }
   1894     }
   1895     flags =  _BCM_L3_SHR_WRITE_DISABLE | _BCM_L3_SHR_SKIP_INDEX_ZERO;
   1896 
   1897     /* XXXX use this flag _BCM_L3_SHR_MATCH_DISABLE? */
   1898     /* flags |= _BCM_L3_SHR_MATCH_DISABLE; */
   1899  
   1900     if (info->flags & BCM_TUNNEL_REPLACE) {
   1901         flags |= _BCM_L3_SHR_UPDATE | _BCM_L3_SHR_WITH_ID;
   1902     }  
   1903     
   1904     /* Allocate either existing or new tunnel initiator entry */
   1905     BCM_XGS3_L3_MODULE_LOCK(unit);
   1906     rv = _bcm_flow_tunnel_initiator_entry_add(unit, flags, info,
   1907                                 field,num_of_fields);
   1908     BCM_XGS3_L3_MODULE_UNLOCK(unit);
   1909     return rv;
   1910 }
   1911 
   1912 /*
   1913  * Function:
   1914  *      bcmi_esw_flow_tunnel_initiator_destroy
   1915  * Purpose:
   1916  *      Delete the flow tunnel initiator object
   1917  *
   1918  * Parameters:
   1919  *      unit    - (IN) Device Number
   1920  *      flow_tunnel_id - (IN/OUT) Flow tunnel initiator object ID
   1921  * Returns:
   1922  *      BCM_E_XXX
   1923  */
   1924 int bcmi_esw_flow_tunnel_initiator_destroy(
   1925     int unit,
   1926     bcm_gport_t flow_tunnel_id)
   1927 {
   1928     int soft_tnl_idx;
   1929     _bcm_flow_bookkeeping_t *flow_info;
   1930     bcm_flow_tunnel_initiator_t info;
   1931     uint32 flags = 0;
   1932     int idx;
   1933     int rv;
   1934     int oif_idx;
   1935     _bcm_l3_tbl_op_t data;               /* Delete operation info. */
   1936     uint32 tnl_entry[SOC_MAX_MEM_FIELD_WORDS]; /* Buffer to write hw entry */
   1937     soc_mem_t mem;
   1938     int data_type;
   1939 
   1940     mem = BCM_XGS3_L3_MEM(unit, tnl_init_v4);
   1941     bcm_flow_tunnel_initiator_t_init(&info);
   1942     soft_tnl_idx = BCM_GPORT_TUNNEL_ID_GET(flow_tunnel_id);
   1943     flow_info = FLOW_INFO(unit);
   1944 
   1945     if (soft_tnl_idx < _BCM_FLOW_TUNNEL_L2_MAX(unit)) {
   1946         /* L2 tunnel */
   1947         _SHR_GPORT_FLOW_PORT_ID_SET(info.flow_port,soft_tnl_idx);
   1948         info.valid_elements = BCM_FLOW_TUNNEL_INIT_DIP_VALID |
   1949                               BCM_FLOW_TUNNEL_INIT_DIP6_VALID;
   1950         info.type = bcmTunnelTypeL2Flex;
   1951 
   1952     } else if (soft_tnl_idx < _BCM_FLOW_TUNNEL_TBL_MAX(unit)) {
   1953         /* L3 tunnel */
   1954         info.l3_intf_id = soft_tnl_idx - _BCM_FLOW_TUNNEL_L2_MAX(unit);
   1955     } else {
   1956         return BCM_E_NOT_FOUND;
   1957     }
   1958     idx = flow_info->init_tunnel[soft_tnl_idx].idx;
   1959 
   1960     if (idx >= _BCM_FLOW_TUNNEL_IP_TUNNEL_MAX(unit)) {
   1961         /* l3_oif index */
   1962         oif_idx = idx - _BCM_FLOW_TUNNEL_IP_TUNNEL_MAX(unit);
   1963         info.l3_intf_id = oif_idx;
   1964         BCM_IF_ERROR_RETURN(_bcm_flow_tunnel_idx_from_oif_get(unit,
   1965                                  oif_idx, &idx));
   1966     }
   1967 
   1968     if (!idx) {
   1969         return BCM_E_NOT_FOUND;
   1970     } 
   1971 
   1972     BCM_XGS3_L3_MODULE_LOCK(unit);
   1973     rv = _bcm_flow_tunnel_dip_idx_set(unit, &info, 0, NULL);
   1974     if (BCM_SUCCESS(rv)) {
   1975         flags = _BCM_L3_SHR_WRITE_DISABLE;
   1976 
   1977         /* Initialization */
   1978         sal_memset(&data, 0, sizeof(_bcm_l3_tbl_op_t));
   1979 
   1980         rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, idx,tnl_entry);
   1981         if (SOC_FAILURE(rv)) {
   1982             BCM_XGS3_L3_MODULE_UNLOCK(unit);
   1983             return rv;
   1984         }
   1985         data_type = soc_mem_field32_get(unit, mem, tnl_entry, DATA_TYPEf);
   1986 
   1987         if (_BCM_FLOW_TUNNEL_ENTRY_DOUBLE_WIDE(data_type)) {
   1988             data.width = _BCM_DOUBLE_WIDE;
   1989         } else {
   1990             /* Default is single table entry operation.*/
   1991             data.width = _BCM_SINGLE_WIDE;
   1992         }
   1993 
   1994         data.tbl_ptr =  BCM_XGS3_L3_TBL_PTR(unit, tnl_init);
   1995         data.entry_index = idx;
   1996         data.oper_flags = flags;
   1997         data.delete_func = BCM_XGS3_L3_HWCALL(unit, tnl_init_del);
   1998 
   1999         /* Delete tunnel initiator table entry. */
   2000         rv = _bcm_xgs3_tbl_del(unit, &data);
   2001         if (SOC_FAILURE(rv)) {
   2002             BCM_XGS3_L3_MODULE_UNLOCK(unit);
   2003             return rv;
   2004         }
   2005         /* don't clear if the entry is still been referenced by other objs */ 
   2006         if (!BCM_XGS3_L3_ENT_REF_CNT(data.tbl_ptr, idx)) {
   2007             (void) _bcm_flow_tunnel_init_delete(unit, idx, data.width);
   2008         }
   2009         flow_info->init_tunnel[soft_tnl_idx].idx = 0;
   2010     }
   2011     BCM_XGS3_L3_MODULE_UNLOCK(unit);
   2012 
   2013     return rv;
   2014 }
   2015 
   2016 /*
   2017  * Function:
   2018  *      bcmi_esw_flow_tunnel_initiator_destroy_all
   2019  * Purpose:
   2020  *      Delete all flow tunnel initiator object
   2021  *
   2022  * Parameters:
   2023  *      unit    - (IN) Device Number
   2024  * Returns:
   2025  *      BCM_E_XXX
   2026  */
   2027 int bcmi_esw_flow_tunnel_initiator_destroy_all(
   2028     int unit)
   2029 {
   2030     int soft_tnl_idx;
   2031     _bcm_flow_bookkeeping_t *flow_info;
   2032     int num_tnl = 0;
   2033     bcm_gport_t flow_tunnel_id;
   2034     int rv = 0;
   2035 
   2036     num_tnl = soc_mem_index_count(unit, EGR_DVP_ATTRIBUTEm) +
   2037                     soc_mem_index_count(unit, EGR_L3_INTFm);
   2038 
   2039     flow_info = FLOW_INFO(unit);
   2040     for (soft_tnl_idx = 0; soft_tnl_idx < num_tnl; soft_tnl_idx++) {
   2041         if (flow_info->init_tunnel[soft_tnl_idx].idx) {
   2042             BCM_GPORT_TUNNEL_ID_SET(flow_tunnel_id, soft_tnl_idx);
   2043             rv = bcmi_esw_flow_tunnel_initiator_destroy(unit, flow_tunnel_id);
   2044             if ((rv != BCM_E_NONE) && (rv != BCM_E_NOT_FOUND)) {
   2045               return rv;
   2046             }
   2047         }
   2048     }
   2049 
   2050     return BCM_E_NONE;
   2051 }
   2052 
   2053 /*
   2054  * Function:
   2055  *      bcmi_esw_flow_tunnel_initiator_get
   2056  * Purpose:
   2057  *      Retrieve the flow tunnel initiator object on the given flow port for L2
   2058  * tunnel or on the given L3 interface for L3 tunnel.
   2059  *
   2060  * Parameters:
   2061  *      unit    - (IN) Device Number
   2062  *      info    - (IN/OUT) Flow tunnel initiator descriptor
   2063  *      num_of_fields - (IN) number of logical fields
   2064  *      field         - (IN) logical field array
   2065  * Returns:
   2066  *      BCM_E_XXX
   2067  */
   2068 int bcmi_esw_flow_tunnel_initiator_get(
   2069     int unit,
   2070     bcm_flow_tunnel_initiator_t *info,
   2071     uint32 num_of_fields,
   2072     bcm_flow_logical_field_t *field)
   2073 {
   2074     uint32 soft_tnl_idx;
   2075     _bcm_flow_bookkeeping_t *flow_info;
   2076     int dvp;
   2077     int rv = BCM_E_NONE;
   2078 
   2079     flow_info = FLOW_INFO(unit);
   2080 
   2081     if (NULL == info) {
   2082         return (BCM_E_PARAM);
   2083     }
   2084 
   2085     /* Input parameters check. */
   2086     soft_tnl_idx = BCM_GPORT_TUNNEL_ID_GET(info->tunnel_id);
   2087     if (soft_tnl_idx >= (_BCM_FLOW_TUNNEL_L2_MAX(unit) +
   2088                          _BCM_FLOW_TUNNEL_L3_MAX(unit))) {
   2089         return (BCM_E_PARAM);
   2090     }
   2091 
   2092     if (!flow_info->init_tunnel[soft_tnl_idx].idx) {
   2093         return (BCM_E_PARAM);
   2094     }
   2095 
   2096     if (soft_tnl_idx < _BCM_FLOW_TUNNEL_L2_MAX(unit)) {
   2097         /* L2 tunnel */
   2098         dvp = _SHR_GPORT_FLOW_PORT_ID_GET(info->flow_port);
   2099         if (!dvp) {
   2100             _SHR_GPORT_FLOW_PORT_ID_SET(info->flow_port, soft_tnl_idx); 
   2101         } else if (dvp != soft_tnl_idx) {
   2102             return BCM_E_PARAM;
   2103         }
   2104     } else if (soft_tnl_idx < _BCM_FLOW_TUNNEL_TBL_MAX(unit)) {
   2105         /* L3 tunnel */
   2106         if (!info->l3_intf_id) {
   2107             info->l3_intf_id = soft_tnl_idx - _BCM_FLOW_TUNNEL_L2_MAX(unit);
   2108         } else if (info->l3_intf_id !=
   2109                  (soft_tnl_idx - _BCM_FLOW_TUNNEL_L2_MAX(unit))) {
   2110             return BCM_E_PARAM;
   2111         }
   2112     } else {
   2113         return BCM_E_NOT_FOUND;
   2114     }
   2115 
   2116     rv = _bcm_flow_tunnel_init_get(unit, soft_tnl_idx, info,field,
   2117                                    num_of_fields,NULL);
   2118     return rv;
   2119 }
   2120 
   2121 /*
   2122  * Function:
   2123  *      bcmi_esw_flow_tunnel_initiator_traverse
   2124  * Purpose:
   2125  *      Traverse all flow tunnel initiator objects and call the user specified
   2126  * callback function on each object.
   2127  *
   2128  * Parameters:
   2129  *      unit      - (IN) Device Number
   2130  *      bcm_flow_tunnel_initiator_traverse_cb - (IN) user callback function 
   2131  *      user_data - (IN) user context data for the callback 
   2132  * Returns:
   2133  *      BCM_E_XXX
   2134  */
   2135 int bcmi_esw_flow_tunnel_initiator_traverse(
   2136     int unit,
   2137     bcm_flow_tunnel_initiator_traverse_cb cb,
   2138     void *user_data)
   2139 {
   2140     bcm_flow_tunnel_initiator_t info;
   2141     uint32 num_of_fields = _BCM_FLOW_LOGICAL_FIELD_MAX;
   2142     bcm_flow_logical_field_t field[_BCM_FLOW_LOGICAL_FIELD_MAX];
   2143     int rv = BCM_E_NONE;
   2144     uint32 soft_tnl_idx;
   2145     _bcm_flow_bookkeeping_t *flow_info;
   2146     uint32 cnt = 0;
   2147 
   2148     if (NULL == cb) {
   2149         return (BCM_E_PARAM);
   2150     } 
   2151     flow_info = FLOW_INFO(unit);
   2152 
   2153     for (soft_tnl_idx = 0; soft_tnl_idx < _BCM_FLOW_TUNNEL_TBL_MAX(unit); 
   2154                            soft_tnl_idx++) {
   2155         if (!flow_info->init_tunnel[soft_tnl_idx].idx) {
   2156             continue;
   2157         } 
   2158         bcm_flow_tunnel_initiator_t_init(&info);
   2159         BCM_GPORT_TUNNEL_ID_SET(info.tunnel_id,soft_tnl_idx);
   2160         rv = _bcm_flow_tunnel_init_get(unit, soft_tnl_idx, &info, field, 
   2161                   num_of_fields,&cnt);
   2162         if (rv == BCM_E_NOT_FOUND) { /* for entries not exposed to user */
   2163             continue;
   2164         } else if (BCM_FAILURE(rv)) {
   2165             break;
   2166         }
   2167         if (soft_tnl_idx < _BCM_FLOW_TUNNEL_L2_MAX(unit)) {
   2168             /* L2 tunnel */
   2169             _SHR_GPORT_FLOW_PORT_ID_SET(info.flow_port, soft_tnl_idx);
   2170 
   2171         } else {
   2172             /* L3 tunnel */
   2173             info.l3_intf_id = soft_tnl_idx - _BCM_FLOW_TUNNEL_L2_MAX(unit);
   2174         }
   2175 
   2176         rv = cb(unit,&info,cnt,field,user_data);
   2177         if (BCM_FAILURE(rv)) {
   2178             break;
   2179         }
   2180     }
   2181     return rv;
   2182 }
   2183 
   2184 STATIC 
   2185 int _bcm_esw_flow_tnl_term_num_hw_entries_get(int unit, 
   2186                                               soc_mem_t mem, 
   2187                                               uint32 *entry,
   2188                                               uint32 *num_hw_entries)
   2189 {
   2190     int mode;
   2191 
   2192     if ((entry == NULL) ||
   2193         (num_hw_entries == NULL)) {
   2194         return BCM_E_PARAM;
   2195     }
   2196     *num_hw_entries = 0;
   2197     if (mem == L3_TUNNELm) {
   2198         mode =  soc_mem_field32_get(unit, mem, entry, MODEf);
   2199         if (mode == _BCM_FLOW_TD3_L3_TUNNEL_QUAD_WIDE) {
   2200             *num_hw_entries = _BCM_FLOW_TD3_L3_TUNNEL_QUAD;
   2201         } else if (mode == _BCM_FLOW_TD3_L3_TUNNEL_DOUBLE_WIDE) {
   2202             *num_hw_entries = _BCM_FLOW_TD3_L3_TUNNEL_DOUBLE;
   2203         } else {
   2204             *num_hw_entries = _BCM_FLOW_TD3_L3_TUNNEL_WIDTH_SINGLE;
   2205         }
   2206         return BCM_E_NONE;
   2207     }
   2208     return BCM_E_PARAM;
   2209 }
   2210                                       
   2211 int bcmi_esw_flow_entry_to_tnl_term(int unit,
   2212                                     uint32 *entry, 
   2213                                     soc_tunnel_term_t *tnl_term) 
   2214 {
   2215    uint32 num_hw_entries = 0;
   2216    uint32 i = 0;
   2217    uint32 entry_width = _BCM_FLOW_TD3_L3_TUNNEL_SINGLE_ENTRY_SIZE;
   2218 
   2219    BCM_IF_ERROR_RETURN(
   2220         _bcm_esw_flow_tnl_term_num_hw_entries_get(unit, L3_TUNNELm,
   2221                              entry, &num_hw_entries));
   2222    for (i = 0; i < num_hw_entries; i++) {
   2223        sal_memcpy((uint8 *) &tnl_term->entry_arr[i], 
   2224                   entry + entry_width * i, entry_width);
   2225    }
   2226    return BCM_E_NONE;
   2227 }
   2228 
   2229 int bcmi_esw_flow_tnl_term_to_entry(int unit,
   2230                                     soc_tunnel_term_t *tnl_term,
   2231                                     uint32 *entry)
   2232 {
   2233    uint32 num_hw_entries = 0;
   2234    uint32 i = 0;
   2235    uint32 entry_width = _BCM_FLOW_TD3_L3_TUNNEL_SINGLE_ENTRY_SIZE;
   2236 
   2237    BCM_IF_ERROR_RETURN(
   2238         _bcm_esw_flow_tnl_term_num_hw_entries_get(unit, L3_TUNNELm,
   2239                              entry, &num_hw_entries));
   2240    for (i = 0; i < num_hw_entries; i++) {
   2241        sal_memcpy(entry + (entry_width * i),
   2242                  (uint8 *) &tnl_term->entry_arr[i],
   2243                   entry_width);
   2244    }
   2245    return BCM_E_NONE;
   2246 }
   2247 
   2248 /*
   2249  * Function:
   2250  *      _bcm_esw_flow_tnl_term_validate
   2251  * Purpose:
   2252  *      Validate  the tunnel terrmination attributes
   2253  *
   2254  * Parameters:
   2255  *      unit          - (IN) Device Number
   2256  *      info          - (IN) Flow tunnel terminator descriptor
   2257  * Returns:
   2258  *      TRUE/FALSE
   2259  */
   2260 STATIC 
   2261 int _bcm_esw_flow_tnl_term_validate(
   2262     int unit,
   2263     bcm_flow_tunnel_terminator_t *info)
   2264 {
   2265 
   2266     if (info->valid_elements & BCM_FLOW_TUNNEL_TERM_DIP_VALID) {
   2267         if (0 == info->dip) {
   2268             LOG_ERROR(BSL_LS_BCM_FLOW, (BSL_META_U(unit,
   2269             "Flow Tunnel Termination : \
   2270              mismatch valid_elements flag and dip field\n"))); 
   2271             return FALSE;
   2272         }
   2273     }
   2274     if (info->valid_elements & BCM_FLOW_TUNNEL_TERM_SIP_VALID) {
   2275         if (0 == info->sip) {
   2276             LOG_ERROR(BSL_LS_BCM_FLOW, (BSL_META_U(unit,
   2277             "Flow Tunnel Termination : \
   2278              mismatch valid_elements flag and sip field\n")));
   2279             return FALSE;
   2280         }
   2281     }
   2282     
   2283     if (info->valid_elements & BCM_FLOW_TUNNEL_TERM_SIP_MASK_VALID) {
   2284         if (0 == info->sip_mask) {
   2285             LOG_ERROR(BSL_LS_BCM_FLOW, (BSL_META_U(unit,
   2286             "Flow Tunnel Termination : \
   2287              mismatch valid_elements flag and sip_mask field\n")));
   2288             return FALSE;
   2289         }
   2290     }
   2291     if (info->valid_elements & BCM_FLOW_TUNNEL_TERM_DIP_MASK_VALID) {
   2292         if (0 == info->dip_mask) {
   2293             LOG_ERROR(BSL_LS_BCM_FLOW, (BSL_META_U(unit,
   2294             "Flow Tunnel Termination : \
   2295              mismatch valid_elements flag and dip_mask field\n")));
   2296             return FALSE;
   2297         }
   2298     }
   2299     if (info->valid_elements & BCM_FLOW_TUNNEL_TERM_DIP6_VALID) {
   2300         if (!bcmi_flow_ip6_addr_is_valid(info->dip6)) {
   2301             LOG_ERROR(BSL_LS_BCM_FLOW, (BSL_META_U(unit,
   2302             "Flow Tunnel Termination : \
   2303              mismatch valid_elements flag and dip6 field\n")));
   2304             return FALSE;
   2305         }
   2306     }
   2307     if (info->valid_elements & BCM_FLOW_TUNNEL_TERM_SIP6_VALID) {
   2308         if (!bcmi_flow_ip6_addr_is_valid(info->sip6)) {
   2309             LOG_ERROR(BSL_LS_BCM_FLOW, (BSL_META_U(unit,
   2310             "Flow Tunnel Termination : \
   2311              mismatch valid_elements flag and sip6 field\n")));
   2312             return FALSE;
   2313         }
   2314     }
   2315 
   2316     if (info->valid_elements & BCM_FLOW_TUNNEL_TERM_SIP6_MASK_VALID) {
   2317         if (!bcmi_flow_ip6_addr_is_valid(info->sip6_mask)) {
   2318             LOG_ERROR(BSL_LS_BCM_FLOW, (BSL_META_U(unit,
   2319             "Flow Tunnel Termination : \
   2320              mismatch valid_elements flag and sip6_mask field\n")));
   2321             return FALSE;
   2322         }
   2323     }
   2324     if (info->valid_elements & BCM_FLOW_TUNNEL_TERM_DIP6_MASK_VALID) {
   2325         if (!bcmi_flow_ip6_addr_is_valid(info->dip6_mask)) {
   2326             LOG_ERROR(BSL_LS_BCM_FLOW, (BSL_META_U(unit,
   2327             "Flow Tunnel Termination : \
   2328              mismatch valid_elements flag and dip6_mask field\n")));
   2329             return FALSE;
   2330         }
   2331     }
   2332     if (info->valid_elements & BCM_FLOW_TUNNEL_TERM_UDP_SRC_PORT_VALID) {
   2333         if (0 == info->udp_src_port) {
   2334             LOG_ERROR(BSL_LS_BCM_FLOW, (BSL_META_U(unit,
   2335             "Flow Tunnel Termination : \
   2336              mismatch valid_elements flag and udp_src_port field\n")));
   2337             return FALSE;
   2338         }
   2339     }
   2340     if (info->valid_elements & BCM_FLOW_TUNNEL_TERM_UDP_DST_PORT_VALID) {
   2341         if (0 == info->udp_dst_port) {
   2342             LOG_ERROR(BSL_LS_BCM_FLOW, (BSL_META_U(unit,
   2343             "Flow Tunnel Termination : \
   2344              mismatch valid_elements flag and udp_dst_port field\n")));
   2345             return FALSE;
   2346         }
   2347     }
   2348     if (info->valid_elements & BCM_FLOW_TUNNEL_TERM_PROTOCOL_VALID) {
   2349         if (0 == info->protocol) {
   2350             LOG_ERROR(BSL_LS_BCM_FLOW, (BSL_META_U(unit,
   2351             "Flow Tunnel Termination : \
   2352              mismatch valid_elements flag and protocol field\n")));
   2353             return FALSE;
   2354         }
   2355     }
   2356     if (info->valid_elements & BCM_FLOW_TUNNEL_TERM_VLAN_VALID) {
   2357         VLAN_CHK_ID(unit, info->vlan);
   2358     }
   2359     return TRUE;
   2360 }
   2361 
   2362 /*
   2363  * Function:
   2364  *     _bcm_flow_tnl_term_entry_data_set
   2365  * Purpose:
   2366  *      Set the data information for flow tunnel terminator entry.
   2367  * Parameters:
   2368  *      unit          - (IN)     Device Number.
   2369  *      info          - (IN)     Flow tunnel terminator descriptor.
   2370  *      field         - (IN)     logical field array.      
   2371  *      num_of_fields - (IN)     number of logical fields.
   2372  *      entry         - (IN)     memory entry.
   2373  *      vinfo         - (IN)     view information.
   2374  * Returns:
   2375  *      BCM_E_XXX
   2376  */
   2377 STATIC int
   2378 _bcm_flow_tnl_term_entry_data_set(int unit,
   2379     bcm_flow_tunnel_terminator_t *info,
   2380     bcm_flow_logical_field_t *field,
   2381     uint32 num_of_fields, 
   2382     uint32 *entry,
   2383     soc_flow_db_mem_view_info_t vinfo)
   2384 {
   2385     int rv = BCM_E_NONE;
   2386     int i;
   2387     int j;
   2388     int index = -1;
   2389     uint32 return_entry[SOC_MAX_MEM_WORDS];
   2390     int new_entry_add = FALSE;
   2391     uint32 field_list[SOC_FLOW_DB_MAX_VIEW_FIELDS];
   2392     uint32 field_count = 0;
   2393     soc_mem_t mem;
   2394     uint32 mem_view_id;
   2395     soc_tunnel_term_t tnl_term;
   2396     soc_tunnel_term_t ret_tnl_term;
   2397     uint32 vxlan_handle;
   2398 
   2399     mem = _BCM_FLOW_IS_FLEX_VIEW(info)?
   2400              vinfo.mem_view_id: vinfo.mem;
   2401     mem_view_id = vinfo.mem_view_id;
   2402 
   2403     if (vinfo.mem == L3_TUNNELm) {
   2404         BCM_IF_ERROR_RETURN(
   2405         bcmi_esw_flow_entry_to_tnl_term(unit, entry, &tnl_term));
   2406         rv = soc_tunnel_term_match(unit, &tnl_term,
   2407                               &ret_tnl_term, &index); 
   2408     } else { 
   2409         rv = soc_mem_search(unit, mem, MEM_BLOCK_ANY, &index, entry,
   2410                         return_entry, 0);
   2411     }
   2412 
   2413     if (BCM_E_NONE == rv) {
   2414         /* found memory entry */
   2415         if (!(info->flags & BCM_TUNNEL_REPLACE)) {
   2416             LOG_ERROR(BSL_LS_BCM_FLOW,
   2417                 (BSL_META_U(unit,
   2418                  "Flow Tunnel Termination: \
   2419                  Entry with same key already exists\n")));
   2420             return BCM_E_EXISTS;
   2421         }
   2422     } else if (BCM_E_NOT_FOUND == rv) {
   2423         new_entry_add = TRUE;
   2424     } else {
   2425         return rv;
   2426     }
   2427 
   2428     if (_BCM_FLOW_IS_FLEX_VIEW(info)) {
   2429         /* Policy data fields*/
   2430         if (soc_flow_db_mem_view_field_is_valid
   2431                        (unit, mem_view_id, TERM_TUNNELf)) {
   2432             soc_mem_field32_set(unit, mem, entry,
   2433                                    TERM_TUNNELf, 1);
   2434             soc_mem_field32_set(unit, mem, entry, 
   2435                                    IGNORE_UDP_CHECKSUMf,
   2436                (info->flags & BCM_TUNNEL_TERM_UDP_CHECKSUM_ENABLE) ? 0x0 : 0x1);
   2437             if (info->flags & BCM_TUNNEL_TERM_USE_OUTER_DSCP) {
   2438                 soc_mem_field32_set(unit, mem, entry, 
   2439                                         USE_OUTER_HEADER_PHBf, 0x1);
   2440             } else if (info->flags & BCM_TUNNEL_TERM_USE_OUTER_PCP) {
   2441                 soc_mem_field32_set(unit, mem, entry,
   2442                                        USE_OUTER_HEADER_PHBf, 0x2);
   2443             } 
   2444             if (info->flags & BCM_TUNNEL_TERM_USE_OUTER_TTL) {
   2445                 soc_mem_field32_set(unit, mem, entry, 
   2446                     USE_OUTER_HDR_TTLf, 1);
   2447             } 
   2448             if (info->flags & BCM_TUNNEL_TERM_KEEP_INNER_DSCP) {
   2449                 soc_mem_field32_set(unit, mem, entry, 
   2450                     DONOT_CHANGE_INNER_HDR_DSCPf, 1);
   2451             }
   2452             SOC_IF_ERROR_RETURN(soc_flow_db_flow_handle_get(unit, "VXLAN", 
   2453                                  &vxlan_handle));
   2454 
   2455             if (info->multicast_flag == BCM_FLOW_MULTICAST_TUNNEL_STATE_BUD_ENABLE) {
   2456                 soc_mem_field32_set(unit, mem, entry, 
   2457                                      NETWORK_RECEIVERS_PRESENTf, 0x01);
   2458                 if (info->flow_handle == vxlan_handle) {
   2459                     BCM_IF_ERROR_RETURN(_bcm_flow_bud_loopback_termination_set(
   2460                             unit, info->flow_handle,TRUE));
   2461                 }
   2462             } else if (info->multicast_flag == BCM_FLOW_MULTICAST_TUNNEL_STATE_BUD_DISABLE) {
   2463                 soc_mem_field32_set(unit, mem, entry, NETWORK_RECEIVERS_PRESENTf, 0x00);
   2464                 if (info->flow_handle == vxlan_handle) {
   2465                     BCM_IF_ERROR_RETURN(_bcm_flow_bud_loopback_termination_set(
   2466                             unit, info->flow_handle,FALSE));
   2467                 }
   2468             }
   2469         }
   2470         if (SOC_MEM_FIELD_VALID(unit, mem, TUNNEL_TERM_SUBLAYER_ACTION_SETf)) {
   2471             soc_mem_field32_set(unit, mem, entry, 
   2472                              TUNNEL_TERM_SUBLAYER_ACTION_SETf, 1);
   2473         } 
   2474 
   2475         /* Logical policy data fields */
   2476         if (info->valid_elements == BCM_FLOW_MATCH_FLEX_DATA_VALID) {
   2477             BCM_IF_ERROR_RETURN(
   2478                       soc_flow_db_mem_view_field_list_get(unit,
   2479                       mem_view_id,
   2480                       SOC_FLOW_DB_FIELD_TYPE_LOGICAL_POLICY_DATA,
   2481                       SOC_FLOW_DB_MAX_VIEW_FIELDS, field_list, &field_count));
   2482             for (i = 0; (i < num_of_fields); i++) {
   2483                 for (j = 0; j < field_count; j++) {
   2484                     if (field[i].id == field_list[j]) {
   2485                         soc_mem_field32_set(unit,mem, entry,
   2486                              field[i].id, field[i].value);
   2487                     }
   2488                 }
   2489             }
   2490       
   2491         }
   2492 
   2493     } else {
   2494         /* fixed views */
   2495         if ((info->flow_handle == SOC_FLOW_DB_FLOW_ID_LEGACY_VXLAN) &&
   2496             (info->type == bcmTunnelTypeVxlan)) {
   2497             if (soc_feature(unit, soc_feature_vxlan_decoupled_mode)) {
   2498                 if (info->multicast_flag == BCM_FLOW_MULTICAST_TUNNEL_STATE_BUD_ENABLE) {
   2499                     soc_mem_field32_set(unit, mem, entry,
   2500                     VXLAN_FLEX_IPV4_DIP__NETWORK_RECEIVERS_PRESENTf, 0x01);
   2501                     BCM_IF_ERROR_RETURN(_bcm_flow_bud_loopback_termination_set(unit,
   2502                                         info->flow_handle,TRUE));
   2503                 } else if (info->multicast_flag == BCM_FLOW_MULTICAST_TUNNEL_STATE_BUD_DISABLE) {
   2504                     soc_mem_field32_set(unit, mem, entry,
   2505                     VXLAN_FLEX_IPV4_DIP__NETWORK_RECEIVERS_PRESENTf, 0x00);
   2506                     BCM_IF_ERROR_RETURN(_bcm_flow_bud_loopback_termination_set(unit,
   2507                                         info->flow_handle,FALSE));
   2508                 }
   2509             } else {
   2510                 if (info->multicast_flag == BCM_FLOW_MULTICAST_TUNNEL_STATE_BUD_ENABLE) {
   2511                     soc_mem_field32_set(unit, mem, entry,
   2512                     VXLAN_DIP__NETWORK_RECEIVERS_PRESENTf, 0x01);
   2513                     BCM_IF_ERROR_RETURN(_bcm_flow_bud_loopback_termination_set(unit,
   2514                                         info->flow_handle,TRUE));
   2515                 } else if (info->multicast_flag == BCM_FLOW_MULTICAST_TUNNEL_STATE_BUD_DISABLE) {
   2516                     soc_mem_field32_set(unit, mem, entry,
   2517                     VXLAN_DIP__NETWORK_RECEIVERS_PRESENTf, 0x00);
   2518                     BCM_IF_ERROR_RETURN(_bcm_flow_bud_loopback_termination_set(unit,
   2519                                         info->flow_handle,FALSE));
   2520                 }
   2521             }
   2522         } else if ((info->flow_handle == SOC_FLOW_DB_FLOW_ID_LEGACY_L2GRE) &&
   2523             (info->type == bcmTunnelTypeL2Gre)) {
   2524             if (info->multicast_flag == BCM_FLOW_MULTICAST_TUNNEL_STATE_BUD_ENABLE) {
   2525                 soc_mem_field32_set(unit, mem, entry,
   2526                 L2GRE_DIP__NETWORK_RECEIVERS_PRESENTf, 0x01);
   2527                 BCM_IF_ERROR_RETURN(_bcm_flow_bud_loopback_termination_set(unit,
   2528                                     info->flow_handle,TRUE));
   2529             } else if (info->multicast_flag == 
   2530                        BCM_FLOW_MULTICAST_TUNNEL_STATE_BUD_DISABLE) {
   2531                 soc_mem_field32_set(unit, mem, entry,
   2532                 L2GRE_DIP__NETWORK_RECEIVERS_PRESENTf, 0x00);
   2533                 BCM_IF_ERROR_RETURN(_bcm_flow_bud_loopback_termination_set(unit,
   2534                                     info->flow_handle,FALSE));
   2535             }
   2536             
   2537         }
   2538     } 
   2539 
   2540 
   2541     if (vinfo.mem == L3_TUNNELm) {
   2542         BCM_IF_ERROR_RETURN(
   2543         bcmi_esw_flow_entry_to_tnl_term(unit, entry, &tnl_term));
   2544         rv = soc_tunnel_term_insert(unit, &tnl_term, (uint32 *) &index);
   2545     } else {
   2546         if (new_entry_add) {
   2547             rv = soc_mem_insert(unit, mem,
   2548                               MEM_BLOCK_ALL, entry);
   2549         } else {
   2550             rv = soc_mem_write(unit, mem,
   2551                           MEM_BLOCK_ALL, index, entry);
   2552         }
   2553     }
   2554     return rv;
   2555 }
   2556 
   2557 /*
   2558  * Function:
   2559  *     _bcm_flow_tnl_term_entry_data_get
   2560  * Purpose:
   2561  *      Get the data information from flow tunnel terminator entry.
   2562  * Parameters:
   2563  *      unit          - (IN)     Device Number.
   2564  *      info          - (IN)     Flow tunnel terminator descriptor.
   2565  *      field         - (IN)     logical field array.
   2566  *      num_of_fields - (IN)     number of logical fields.
   2567  *      entry         - (IN)     memory entry.
   2568  *      vinfo         - (IN)     view information.
   2569  * Returns:
   2570  *      BCM_E_XXX
   2571  */
   2572 
   2573 STATIC int
   2574 _bcm_flow_tnl_term_entry_data_get(int unit,
   2575     bcm_flow_tunnel_terminator_t *info,
   2576     bcm_flow_logical_field_t *field,
   2577     uint32 num_of_fields, 
   2578     uint32 *entry,
   2579     soc_flow_db_mem_view_info_t vinfo) 
   2580 {
   2581     int i;
   2582     int j;
   2583     int index = -1;
   2584     uint32 rentry[SOC_MAX_MEM_WORDS];
   2585     uint32 field_list[SOC_FLOW_DB_MAX_VIEW_FIELDS];
   2586     uint32 field_count = 0;
   2587     soc_tunnel_term_t tnl_entry;
   2588     soc_tunnel_term_t ret_tnl_entry;
   2589     soc_mem_t mem;
   2590     uint32 mem_view_id;
   2591   
   2592     mem = _BCM_FLOW_IS_FLEX_VIEW(info)?
   2593              vinfo.mem_view_id: vinfo.mem;
   2594     mem_view_id = vinfo.mem_view_id; 
   2595     
   2596     if (vinfo.mem == L3_TUNNELm) {
   2597         BCM_IF_ERROR_RETURN(
   2598         bcmi_esw_flow_entry_to_tnl_term(unit, entry, &tnl_entry));
   2599         BCM_IF_ERROR_RETURN(
   2600            soc_tunnel_term_match(unit, &tnl_entry,
   2601                               &ret_tnl_entry, &index));
   2602        bcmi_esw_flow_tnl_term_to_entry(unit, &ret_tnl_entry, rentry);
   2603     } else {
   2604         BCM_IF_ERROR_RETURN(
   2605               soc_mem_search(unit, mem, MEM_BLOCK_ANY, &index, entry,
   2606                         rentry, 0));
   2607     }
   2608     if (_BCM_FLOW_IS_FLEX_VIEW(info)) {
   2609         if (soc_flow_db_mem_view_field_is_valid
   2610                        (unit, mem_view_id, TERM_TUNNELf)) { 
   2611         /* Policy data fields*/
   2612             if (soc_mem_field32_get(unit, mem, rentry, 
   2613                                    IGNORE_UDP_CHECKSUMf) == 0x0) 
   2614             {
   2615                 info->flags |= BCM_TUNNEL_TERM_UDP_CHECKSUM_ENABLE; 
   2616             } 
   2617             if (soc_mem_field32_get(unit, mem, rentry, 
   2618                              USE_OUTER_HEADER_PHBf) ==  0x1) {
   2619                 info->flags |= BCM_TUNNEL_TERM_USE_OUTER_DSCP;
   2620             } else if (soc_mem_field32_get(unit, mem, rentry,
   2621                                        USE_OUTER_HEADER_PHBf) ==  0x2) {
   2622                 info->flags |= BCM_TUNNEL_TERM_USE_OUTER_PCP;
   2623             }
   2624             if (soc_mem_field32_get(unit, mem, rentry, 
   2625                     USE_OUTER_HDR_TTLf) ==  1) {
   2626                  info->flags |=  BCM_TUNNEL_TERM_USE_OUTER_TTL;
   2627             }
   2628             if (soc_mem_field32_get(unit, mem, rentry, 
   2629                     DONOT_CHANGE_INNER_HDR_DSCPf) ==  1) {
   2630                 info->flags |= BCM_TUNNEL_TERM_KEEP_INNER_DSCP;
   2631             }           
   2632             if(soc_mem_field32_get(unit, mem, rentry, 
   2633                     NETWORK_RECEIVERS_PRESENTf) == 0x01) {
   2634                info->multicast_flag |= BCM_FLOW_MULTICAST_TUNNEL_STATE_BUD_ENABLE;
   2635             } else if (soc_mem_field32_get(unit, mem, rentry, 
   2636                     NETWORK_RECEIVERS_PRESENTf) == 0x00) {
   2637                info->multicast_flag |= BCM_FLOW_MULTICAST_TUNNEL_STATE_BUD_DISABLE;
   2638             }
   2639         }
   2640         /* Logical policy data fields */
   2641         if (_BCM_FLOW_IS_FLEX_VIEW(info) && (field != NULL)) {
   2642             BCM_IF_ERROR_RETURN(
   2643                       soc_flow_db_mem_view_field_list_get(unit,
   2644                       mem_view_id,
   2645                       SOC_FLOW_DB_FIELD_TYPE_LOGICAL_POLICY_DATA,
   2646                       SOC_FLOW_DB_MAX_VIEW_FIELDS, field_list, &field_count));
   2647             for (i = 0; (i < num_of_fields); i++) {
   2648                 for (j = 0; j < field_count; j++) {
   2649                     if (field[i].id == field_list[j]) {
   2650                        field[i].value = 
   2651                            soc_mem_field32_get(unit, mem, rentry, field[i].id);;
   2652                     }
   2653                 }
   2654             }
   2655       
   2656         }
   2657 
   2658     } else {
   2659         /* fixed views */
   2660         if ((info->flow_handle == SOC_FLOW_DB_FLOW_ID_LEGACY_VXLAN) &&
   2661             (info->type == bcmTunnelTypeVxlan)) {
   2662             if (soc_mem_field32_get(unit, mem, rentry,
   2663                                     VXLAN_DIP__IGNORE_UDP_CHECKSUMf) == 0x0)
   2664             {
   2665                 info->flags |= BCM_TUNNEL_TERM_UDP_CHECKSUM_ENABLE;
   2666             }
   2667             if (soc_mem_field32_get(unit, mem, rentry,
   2668                             VXLAN_DIP__USE_OUTER_HEADER_PHBf) ==  0x1) {
   2669                 info->flags |= BCM_TUNNEL_TERM_USE_OUTER_DSCP;
   2670             } else if (soc_mem_field32_get(unit, mem, rentry,
   2671                                      VXLAN_DIP__USE_OUTER_HEADER_PHBf) ==  0x2) {
   2672                 info->flags |= BCM_TUNNEL_TERM_USE_OUTER_PCP;
   2673             }
   2674             /*Multicast flag information */
   2675             if(soc_mem_field32_get(unit, mem, rentry,
   2676                     VXLAN_DIP__NETWORK_RECEIVERS_PRESENTf) == 0x01) {
   2677                info->multicast_flag |= BCM_FLOW_MULTICAST_TUNNEL_STATE_BUD_ENABLE;
   2678             } else if (soc_mem_field32_get(unit, mem, rentry,
   2679                     VXLAN_DIP__NETWORK_RECEIVERS_PRESENTf) == 0x00) {
   2680                info->multicast_flag |= BCM_FLOW_MULTICAST_TUNNEL_STATE_BUD_DISABLE;
   2681             }
   2682 
   2683         } else if ((info->flow_handle == SOC_FLOW_DB_FLOW_ID_LEGACY_L2GRE) &&
   2684                   (info->type == bcmTunnelTypeL2Gre)) {
   2685             /*Multicast flag information */
   2686             if(soc_mem_field32_get(unit, mem, rentry,
   2687                     L2GRE_DIP__NETWORK_RECEIVERS_PRESENTf) == 0x01) {
   2688                info->multicast_flag |= BCM_FLOW_MULTICAST_TUNNEL_STATE_BUD_ENABLE;
   2689             } else if (soc_mem_field32_get(unit, mem, rentry,
   2690                     L2GRE_DIP__NETWORK_RECEIVERS_PRESENTf) == 0x00) {
   2691                info->multicast_flag |= BCM_FLOW_MULTICAST_TUNNEL_STATE_BUD_DISABLE;
   2692             }
   2693 
   2694         }       
   2695         
   2696     } 
   2697     return BCM_E_NONE;
   2698 }
   2699 
   2700 /*
   2701  * Function:
   2702  *      _bcm_flow_tnl_term_entry_key_set
   2703  * Purpose:
   2704  *      Set the key information for flow tunnel terminator object.
   2705  * Parameters:
   2706  *      unit          - (IN)     Device Number.
   2707  *      info          - (IN/OUT) Flow tunnel terminator descriptor.
   2708  *      field         - (IN)     logical field array.      
   2709  *      num_of_fields - (IN)     number of logical fields.
   2710  *      entry         - (IN)     memory entry.
   2711  *      vinfo         - (IN)     view information.
   2712  * Returns:
   2713  *      BCM_E_XXX
   2714  */
   2715 STATIC int
   2716 _bcm_flow_tnl_term_entry_key_set(int unit,
   2717     bcm_flow_tunnel_terminator_t *info,
   2718     bcm_flow_logical_field_t *field,
   2719     uint32 num_of_fields, 
   2720     uint32 *entry,
   2721     soc_flow_db_mem_view_info_t *vinfo)
   2722 {
   2723     int rv = BCM_E_NONE;
   2724     uint32  key_list[SOC_FLOW_DB_MAX_VIEW_FIELDS];
   2725     uint32  key_count = 0;
   2726     uint32  mem_view_id = 0;
   2727     soc_mem_t   mem = 0;
   2728     int i = 0;
   2729     int j = 0;
   2730 
   2731     /* Get the view info */
   2732     if (_BCM_FLOW_IS_FLEX_VIEW(info)) {
   2733         mem_view_id = vinfo->mem_view_id;
   2734         mem = vinfo->mem_view_id;
   2735         
   2736         /* intitalize the entry with 
   2737          * key_type , data_type , control fields
   2738          */       
   2739         soc_flow_db_mem_view_entry_init(unit, mem_view_id, entry);
   2740         /* set the key fields */
   2741         /* get the list of key fields
   2742          * based VALID FIELDS , set the matching fields.  
   2743          */  
   2744         BCM_IF_ERROR_RETURN(
   2745             soc_flow_db_mem_view_field_list_get(unit, 
   2746                         mem_view_id, 
   2747                         SOC_FLOW_DB_FIELD_TYPE_KEY,      
   2748                         SOC_FLOW_DB_MAX_VIEW_FIELDS,
   2749                         key_list,
   2750                         &key_count));
   2751         for (i = 0; i < key_count; i++) {
   2752             if (key_list[i] == IPV4__DIPf) {
   2753                 if (info->valid_elements & BCM_FLOW_TUNNEL_TERM_DIP_VALID) {
   2754                     rv = (info->dip) ? BCM_E_NONE :  BCM_E_PARAM;
   2755                     BCM_IF_ERROR_RETURN(rv);
   2756                     soc_mem_field32_set(unit, mem, entry, 
   2757                                      IPV4__DIPf, info->dip);
   2758                 } 
   2759             } else if (key_list[i] == IPV4__SIPf) { 
   2760                 if (info->valid_elements & BCM_FLOW_TUNNEL_TERM_SIP_VALID) {
   2761                     rv = (info->sip) ? BCM_E_NONE :  BCM_E_PARAM;
   2762                     BCM_IF_ERROR_RETURN(rv);
   2763                     soc_mem_field32_set(unit, mem, entry, 
   2764                                      IPV4__SIPf, info->sip);
   2765                 }
   2766            } else if (key_list[i] == IPV4__DIP_MASKf) {
   2767                 if (info->valid_elements & BCM_FLOW_TUNNEL_TERM_DIP_MASK_VALID) {
   2768                     rv = (info->dip_mask) ? BCM_E_NONE :  BCM_E_PARAM;
   2769                     BCM_IF_ERROR_RETURN(rv);
   2770                     soc_mem_field32_set(unit, mem, entry, 
   2771                                      IPV4__DIP_MASKf, info->dip);
   2772                 }
   2773             } else if (key_list[i] == IPV4__SIP_MASKf) {
   2774                 if (info->valid_elements & BCM_FLOW_TUNNEL_TERM_SIP_MASK_VALID) {
   2775                     rv = (info->sip_mask) ? BCM_E_NONE :  BCM_E_PARAM;
   2776                     BCM_IF_ERROR_RETURN(rv);
   2777                     soc_mem_field32_set(unit, mem, entry, 
   2778                                      IPV4__SIP_MASKf, info->sip_mask);
   2779                 }
   2780             } else if (key_list[i] == L4_DEST_PORTf) {
   2781                 if(info->valid_elements & BCM_FLOW_TUNNEL_TERM_UDP_DST_PORT_VALID) {
   2782                     rv = (info->udp_dst_port) ? BCM_E_NONE :  BCM_E_PARAM;
   2783                     BCM_IF_ERROR_RETURN(rv);
   2784                     soc_mem_field32_set(unit, mem, entry, 
   2785                                      L4_DEST_PORTf, info->udp_dst_port);
   2786                 }
   2787             } else if (key_list[i] == L4_SRC_PORTf) {
   2788                 if(info->valid_elements & BCM_FLOW_TUNNEL_TERM_UDP_SRC_PORT_VALID) {
   2789                     rv = (info->udp_src_port) ? BCM_E_NONE :  BCM_E_PARAM;
   2790                     BCM_IF_ERROR_RETURN(rv);
   2791                     soc_mem_field32_set(unit, mem, entry, 
   2792                            L4_SRC_PORTf, info->udp_src_port);
   2793                 }
   2794             } else if (key_list[i] == PROTOCOLf) {
   2795                 if(info->valid_elements & BCM_FLOW_TUNNEL_TERM_PROTOCOL_VALID) {
   2796                     rv = (info->protocol) ? BCM_E_NONE :  BCM_E_PARAM;
   2797                     BCM_IF_ERROR_RETURN(rv);
   2798                     soc_mem_field32_set(unit, mem, entry,
   2799                           PROTOCOLf, info->protocol);
   2800                 }
   2801             } else if (key_list[i] == IPV6__SIPf) {
   2802                 if (info->valid_elements & BCM_FLOW_TUNNEL_TERM_SIP6_VALID) {
   2803                     rv = (bcmi_flow_ip6_addr_is_valid(info->sip6)) ?
   2804                           BCM_E_NONE :  BCM_E_PARAM;
   2805                     BCM_IF_ERROR_RETURN(rv);
   2806                     soc_mem_ip6_addr_set(unit, mem, entry, 
   2807                                IPV6__SIPf, info->sip6, 0);
   2808                 }
   2809             } else if (key_list[i] == IPV6__DIPf) {
   2810                 if (info->valid_elements & BCM_FLOW_TUNNEL_TERM_DIP6_VALID) {
   2811                     rv = (bcmi_flow_ip6_addr_is_valid(info->dip6)) ?
   2812                           BCM_E_NONE :  BCM_E_PARAM;
   2813                     BCM_IF_ERROR_RETURN(rv);
   2814                     soc_mem_ip6_addr_set(unit, mem, entry, 
   2815                              IPV6__DIPf, info->dip6, 0);
   2816                 }
   2817              } else if (key_list[i] == IPV6__SIP_MASKf) {
   2818                 if (info->valid_elements & BCM_FLOW_TUNNEL_TERM_SIP6_MASK_VALID) {
   2819                     rv = (bcmi_flow_ip6_addr_is_valid(info->sip6_mask)) ?
   2820                           BCM_E_NONE :  BCM_E_PARAM;
   2821                     BCM_IF_ERROR_RETURN(rv);
   2822                     soc_mem_ip6_addr_set(unit, mem, entry,
   2823                              IPV6__SIP_MASKf, info->sip6_mask, 0);
   2824                 }
   2825             } else if (key_list[i] == IPV6__DIP_MASKf) {
   2826                 if (info->valid_elements & BCM_FLOW_TUNNEL_TERM_DIP6_MASK_VALID) {
   2827                     rv = (bcmi_flow_ip6_addr_is_valid(info->dip6_mask)) ?
   2828                           BCM_E_NONE :  BCM_E_PARAM;
   2829                     BCM_IF_ERROR_RETURN(rv);
   2830                     soc_mem_ip6_addr_set(unit, mem, entry,
   2831                              IPV6__DIP_MASKf, info->dip6_mask, 0);
   2832                 }
   2833             } 
   2834         }
   2835 
   2836         if (info->valid_elements & BCM_FLOW_TUNNEL_TERM_FLEX_KEY_VALID) {
   2837             /* Logical key fields */
   2838             BCM_IF_ERROR_RETURN(
   2839                 soc_flow_db_mem_view_field_list_get(unit, 
   2840                             mem_view_id, 
   2841                             SOC_FLOW_DB_FIELD_TYPE_LOGICAL_KEY,      
   2842                             SOC_FLOW_DB_MAX_VIEW_FIELDS,
   2843                             key_list,
   2844                             &key_count));
   2845 
   2846             for (i = 0;(i < num_of_fields); i++) {
   2847                 for (j = 0; j < key_count; j++) {
   2848                     if (field[i].id == key_list[j]) {
   2849                         soc_mem_field32_set(unit, mem, entry,
   2850                              field[i].id, field[i].value);
   2851                     }
   2852                 }
   2853             }
   2854         }
   2855    
   2856     } else {
   2857         /* legacy VXLAN and L2GRE */
   2858         if ((info->flow_handle == SOC_FLOW_DB_FLOW_ID_LEGACY_VXLAN) &&
   2859             (info->type == bcmTunnelTypeVxlan)) {
   2860             /* initialize the view info*/
   2861             if (soc_feature(unit, soc_feature_vxlan_decoupled_mode)) {
   2862                 mem = vinfo->mem = MPLS_ENTRY_SINGLEm;
   2863 
   2864                 soc_mem_field32_set(unit, mem, entry, BASE_VALIDf, 1);
   2865                 soc_mem_field32_set(unit, mem, entry, DATA_TYPEf,
   2866                                     _BCM_VXLAN_FLEX_KEY_TYPE_LOOKUP_DIP);
   2867                 soc_mem_field32_set(unit, mem, entry, KEY_TYPEf, _BCM_VXLAN_FLEX_KEY_TYPE_LOOKUP_DIP);
   2868                 soc_mem_field32_set(unit, mem, entry, VXLAN_FLEX_IPV4_DIP__DIPf, info->dip);
   2869                 soc_mem_field32_set(unit, mem, entry, VXLAN_FLEX_IPV4_DIP__TERM_TUNNELf, 0x1);
   2870                 soc_mem_field32_set(unit, mem, entry,
   2871                                  VXLAN_FLEX_IPV4_DIP__IGNORE_UDP_CHECKSUMf,
   2872                 (info->flags & BCM_TUNNEL_TERM_UDP_CHECKSUM_ENABLE) ? 0x0 : 0x1);
   2873 
   2874                 if (info->flags & BCM_TUNNEL_TERM_USE_OUTER_DSCP) {
   2875                     soc_mem_field32_set(unit, mem, entry,
   2876                      VXLAN_FLEX_IPV4_DIP__USE_OUTER_HEADER_PHBf, 0x1);
   2877                 } else if (info->flags & BCM_TUNNEL_TERM_USE_OUTER_PCP) {
   2878                     soc_mem_field32_set(unit, mem, entry,
   2879                      VXLAN_FLEX_IPV4_DIP__USE_OUTER_HEADER_PHBf, 0x2);
   2880                 }
   2881             } else {
   2882                 mem = vinfo->mem = VLAN_XLATE_1_DOUBLEm;
   2883 
   2884                 soc_mem_field32_set(unit, mem, entry, BASE_VALID_0f, 3);
   2885                 soc_mem_field32_set(unit, mem, entry, BASE_VALID_1f, 7);
   2886                 soc_mem_field32_set(unit, mem, entry, DATA_TYPEf,
   2887                                     _BCM_VXLAN_KEY_TYPE_LOOKUP_DIP);
   2888                 soc_mem_field32_set(unit, mem, entry, KEY_TYPEf, _BCM_VXLAN_KEY_TYPE_LOOKUP_DIP);
   2889                 soc_mem_field32_set(unit, mem, entry, VXLAN_DIP__DIPf, info->dip);
   2890                 if (soc_feature(unit, soc_feature_vrf_aware_vxlan_termination)) {
   2891                     soc_mem_field32_set(unit, mem, entry,
   2892                                     VXLAN_DIP__OVIDf, info->vlan);
   2893                 }
   2894                 soc_mem_field32_set(unit, mem, entry, 
   2895                                  VXLAN_DIP__IGNORE_UDP_CHECKSUMf,
   2896                 (info->flags & BCM_TUNNEL_TERM_UDP_CHECKSUM_ENABLE) ? 0x0 : 0x1);
   2897 
   2898                 if (info->flags & BCM_TUNNEL_TERM_USE_OUTER_DSCP) {
   2899                     soc_mem_field32_set(unit, mem, entry,
   2900                      VXLAN_DIP__USE_OUTER_HEADER_PHBf, 0x1);
   2901                 } else if (info->flags & BCM_TUNNEL_TERM_USE_OUTER_PCP) {
   2902                     soc_mem_field32_set(unit, mem, entry,
   2903                      VXLAN_DIP__USE_OUTER_HEADER_PHBf, 0x2);
   2904                 }
   2905             }
   2906         } else if ((info->flow_handle == SOC_FLOW_DB_FLOW_ID_LEGACY_L2GRE) &&
   2907                    (info->type == bcmTunnelTypeL2Gre)) {
   2908             mem = vinfo->mem = VLAN_XLATE_1_DOUBLEm;
   2909 
   2910             soc_mem_field32_set(unit, mem, entry, BASE_VALID_0f, 3);
   2911             soc_mem_field32_set(unit, mem, entry, BASE_VALID_1f, 7);
   2912             soc_mem_field32_set(unit, mem, entry, KEY_TYPEf,
   2913                                      _BCM_TD2_L2GRE_KEY_TYPE_LOOKUP_DIP);
   2914             soc_mem_field32_set(unit, mem, entry, DATA_TYPEf,
   2915                                     _BCM_TD2_L2GRE_KEY_TYPE_LOOKUP_DIP);
   2916             soc_mem_field32_set(unit, mem, entry, 
   2917                                 L2GRE_DIP__DIPf, info->dip);
   2918         } else {
   2919             LOG_ERROR(BSL_LS_BCM_FLOW, (BSL_META_U(unit,
   2920                      "Invalid Legacy flow handle or flow type\n")));
   2921             return BCM_E_PARAM;
   2922         }
   2923     }
   2924      
   2925     return rv;
   2926 }
   2927 
   2928 /*
   2929  * Function:
   2930  *      bcmi_esw_flow_tunnel_terminator_create
   2931  * Purpose:
   2932  *      Create a flow tunnel terminator  object.
   2933  *
   2934  * Parameters:
   2935  *      unit          - (IN)     Device Number
   2936  *      info          - (IN/OUT) Flow tunnel terminator descriptor
   2937  *      num_of_fields - (IN)     number of logical fields
   2938  *      field         - (IN)     logical field array
   2939  * Returns:
   2940  *      BCM_E_XXX
   2941  */
   2942 int bcmi_esw_flow_tunnel_terminator_create(
   2943     int unit,
   2944     bcm_flow_tunnel_terminator_t *info,
   2945     uint32 num_of_fields,
   2946     bcm_flow_logical_field_t *field)
   2947 {
   2948     int rv = BCM_E_NONE;
   2949     _bcm_flow_bookkeeping_t *flow_info;
   2950     soc_mem_t mem_view_id;
   2951     uint32 entry[SOC_MAX_MEM_WORDS];
   2952     soc_flow_db_mem_view_info_t vinfo;
   2953 
   2954     flow_info = FLOW_INFO(unit);
   2955 
   2956     if (NULL == info) {
   2957         return (BCM_E_PARAM);
   2958     }
   2959 
   2960     if (flow_info == NULL) {
   2961         return (BCM_E_INTERNAL);
   2962     }
   2963 
   2964     if ((!_BCM_FLOW_TUNNEL_TYPE_L2(info->type)) && 
   2965         (!_BCM_FLOW_TUNNEL_TYPE_L3(info->type))) {
   2966         LOG_ERROR(BSL_LS_BCM_FLOW, (BSL_META_U(unit,
   2967          "Flow Tunnel Termination: Invalid tunnel type.\n")));
   2968         return BCM_E_PARAM;
   2969     }
   2970    
   2971     BCM_IF_ERROR_RETURN(_bcm_esw_flow_tnl_term_validate(unit, info));
   2972 
   2973     /* Zero write buffer. */
   2974     sal_memset(entry, 0, sizeof(entry));
   2975 
   2976     if (_BCM_FLOW_IS_FLEX_VIEW(info)) {
   2977         BCM_IF_ERROR_RETURN(
   2978            soc_flow_db_ffo_to_mem_view_id_get(
   2979                    unit,
   2980                    info->flow_handle,
   2981                    info->flow_option,
   2982                    SOC_FLOW_DB_FUNC_TUNNEL_TERMINATOR_ID,
   2983                    (uint32 *)&mem_view_id));
   2984         BCM_IF_ERROR_RETURN(
   2985             soc_flow_db_mem_view_info_get(unit, mem_view_id, &vinfo));
   2986     }
   2987 
   2988 
   2989     BCM_IF_ERROR_RETURN(_bcm_flow_tnl_term_entry_key_set(unit, info,
   2990                                     field, num_of_fields,
   2991                                     entry, &vinfo));
   2992     /* Allocate tunnel terminator  entry */
   2993     bcmi_esw_flow_lock(unit);
   2994     rv = _bcm_flow_tnl_term_entry_data_set(unit, info,
   2995                                     field, num_of_fields,
   2996                                     entry, vinfo);
   2997     bcmi_esw_flow_unlock(unit);
   2998     return rv;
   2999 }
   3000 
   3001 /*
   3002  * Function:
   3003  *      bcmi_esw_flow_tunnel_terminator_destroy
   3004  * Purpose:
   3005  *      Destroy a flow tunnel terminator entry
   3006  *
   3007  * Parameters:
   3008  *      unit          - (IN)     Device Number
   3009  *      info          - (IN/OUT) Flow tunnel terminator descriptor
   3010  *      num_of_fields - (IN)     number of logical fields
   3011  *      field         - (IN)     logical field array
   3012  * Returns:
   3013  *      BCM_E_XXX
   3014  */
   3015 int bcmi_esw_flow_tunnel_terminator_destroy(
   3016     int unit,
   3017     bcm_flow_tunnel_terminator_t *info,
   3018     uint32 num_of_fields,
   3019     bcm_flow_logical_field_t *field) 
   3020 {
   3021     int rv = BCM_E_NONE;
   3022     _bcm_flow_bookkeeping_t *flow_info;
   3023     soc_mem_t mem_view_id;
   3024     soc_tunnel_term_t tnl_entry;
   3025     soc_tunnel_term_t ret_tnl_entry;
   3026     uint32 entry[SOC_MAX_MEM_WORDS];
   3027     uint32 ret_entry[SOC_MAX_MEM_WORDS];
   3028     int index = 0;
   3029     soc_flow_db_mem_view_info_t vinfo;
   3030 
   3031     flow_info = FLOW_INFO(unit);
   3032 
   3033     if (NULL == info) {
   3034         return (BCM_E_PARAM);
   3035     }
   3036 
   3037     if (flow_info == NULL) {
   3038         return (BCM_E_INTERNAL);
   3039     }
   3040 
   3041     if ((!_BCM_FLOW_TUNNEL_TYPE_L2(info->type)) &&
   3042         (!_BCM_FLOW_TUNNEL_TYPE_L3(info->type))) {
   3043         LOG_ERROR(BSL_LS_BCM_FLOW, (BSL_META_U(unit,
   3044          "Flow Tunnel Termination : Update fail,\
   3045           Invalid tunnel type for flow tunnels\n")));
   3046         return BCM_E_PARAM;
   3047     }
   3048 
   3049     BCM_IF_ERROR_RETURN(_bcm_esw_flow_tnl_term_validate(unit, info));
   3050     /* Zero write buffer. */
   3051     sal_memset(entry, 0, sizeof(entry));
   3052 
   3053     if (_BCM_FLOW_IS_FLEX_VIEW(info)) {
   3054         BCM_IF_ERROR_RETURN(
   3055            soc_flow_db_ffo_to_mem_view_id_get(unit,
   3056                    info->flow_handle,
   3057                    info->flow_option,
   3058                    SOC_FLOW_DB_FUNC_TUNNEL_TERMINATOR_ID,
   3059                    (uint32 *)&mem_view_id));
   3060         BCM_IF_ERROR_RETURN(
   3061             soc_flow_db_mem_view_info_get(unit, mem_view_id, &vinfo));
   3062     }
   3063 
   3064     BCM_IF_ERROR_RETURN(_bcm_flow_tnl_term_entry_key_set(unit, info,
   3065                                     field, num_of_fields,
   3066                                     entry, &vinfo));
   3067     if (vinfo.mem == L3_TUNNELm) {
   3068         BCM_IF_ERROR_RETURN(
   3069         bcmi_esw_flow_entry_to_tnl_term(unit, entry, &tnl_entry));
   3070         rv = soc_tunnel_term_match(unit, &tnl_entry, &ret_tnl_entry, &index);
   3071         if (rv == BCM_E_NONE) {
   3072             BCM_IF_ERROR_RETURN(
   3073                 soc_tunnel_term_delete(unit, &ret_tnl_entry));
   3074         } else if (rv != BCM_E_NOT_FOUND) {
   3075             return rv;
   3076         }
   3077 
   3078     } else {
   3079         rv = soc_mem_search(unit, vinfo.mem, MEM_BLOCK_ANY, &index,
   3080                                      entry, ret_entry, 0);
   3081         if (rv == BCM_E_NONE) {
   3082             rv = soc_mem_delete(unit, vinfo.mem, MEM_BLOCK_ALL, &ret_entry);
   3083             if (BCM_FAILURE(rv)) {
   3084                  return rv;
   3085             }
   3086         } else if (rv != BCM_E_NOT_FOUND) {
   3087             return rv;
   3088         }
   3089     }
   3090     return BCM_E_NONE;
   3091 }
   3092 
   3093 /*
   3094  * Function:
   3095  *      bcmi_esw_flow_tunnel_terminator_get
   3096  * Purpose:
   3097  *      Get a flow tunnel terminator entry
   3098  *
   3099  * Parameters:
   3100  *      unit          - (IN)     Device Number
   3101  *      info          - (IN/OUT) Flow tunnel terminator descriptor
   3102  *      num_of_fields - (IN)     number of logical fields
   3103  *      field         - (IN)     logical field array
   3104  * Returns:
   3105  *      BCM_E_XXX
   3106  */
   3107 int bcmi_esw_flow_tunnel_terminator_get(
   3108     int unit,
   3109     bcm_flow_tunnel_terminator_t *info,
   3110     uint32 num_of_fields,
   3111     bcm_flow_logical_field_t *field) 
   3112 {
   3113     _bcm_flow_bookkeeping_t *flow_info;
   3114     soc_mem_t mem_view_id;
   3115     uint32 entry[SOC_MAX_MEM_WORDS];
   3116     soc_flow_db_mem_view_info_t vinfo;
   3117       
   3118     flow_info = FLOW_INFO(unit);
   3119 
   3120     if (NULL == info) {
   3121         return (BCM_E_PARAM);
   3122     }
   3123 
   3124     if (flow_info == NULL) {
   3125         return (BCM_E_INTERNAL);
   3126     }
   3127 
   3128     if ((!_BCM_FLOW_TUNNEL_TYPE_L2(info->type)) &&
   3129         (!_BCM_FLOW_TUNNEL_TYPE_L3(info->type))) {
   3130         LOG_ERROR(BSL_LS_BCM_FLOW, (BSL_META_U(unit,
   3131          "Flow Tunnel Termination : Update fail,\
   3132           Invalid tunnel type for flow tunnels\n")));
   3133         return BCM_E_PARAM;
   3134     }
   3135 
   3136     BCM_IF_ERROR_RETURN(_bcm_esw_flow_tnl_term_validate(unit, info));
   3137     /* Zero write buffer. */
   3138     sal_memset(entry, 0, sizeof(entry));
   3139 
   3140     if (_BCM_FLOW_IS_FLEX_VIEW(info)) {
   3141         BCM_IF_ERROR_RETURN(
   3142            soc_flow_db_ffo_to_mem_view_id_get(unit,
   3143                    info->flow_handle,
   3144                    info->flow_option,
   3145                    SOC_FLOW_DB_FUNC_TUNNEL_TERMINATOR_ID,
   3146                    (uint32 *)&mem_view_id));
   3147         BCM_IF_ERROR_RETURN(
   3148             soc_flow_db_mem_view_info_get(unit, mem_view_id, &vinfo));
   3149     }
   3150 
   3151     BCM_IF_ERROR_RETURN(
   3152            _bcm_flow_tnl_term_entry_key_set(unit, info,
   3153                      field, num_of_fields, entry, &vinfo));
   3154     BCM_IF_ERROR_RETURN(
   3155            _bcm_flow_tnl_term_entry_data_get(unit, info,
   3156                                   field, num_of_fields,
   3157                                   entry, vinfo));
   3158     return BCM_E_NONE;
   3159 }
   3160 
   3161 STATIC int
   3162 _bcm_flow_tunnel_terminator_entry_valid(int unit,
   3163                                        soc_mem_t mem,
   3164                                        uint32 *entry,
   3165                                        int *valid)
   3166 {
   3167     if (INVALIDm == mem) {
   3168         return BCM_E_MEMORY;
   3169     }
   3170 
   3171     if ((NULL == entry) || (NULL == valid)) {
   3172         return BCM_E_PARAM;
   3173     }
   3174 
   3175     *valid = TRUE;
   3176     if (SOC_MEM_FIELD_VALID(unit,mem,BASE_VALID_0f)) {
   3177         if (!soc_mem_field32_get(unit, mem, entry, BASE_VALID_0f)) {
   3178             *valid = FALSE;
   3179         }
   3180     }
   3181     if (SOC_MEM_FIELD_VALID(unit,mem,BASE_VALID_1f)) {
   3182         if (!soc_mem_field32_get(unit, mem, entry, BASE_VALID_1f)) {
   3183             *valid = FALSE;
   3184         }
   3185     }
   3186     if (SOC_MEM_FIELD_VALID(unit, mem, VALIDf)) {
   3187         if (!soc_mem_field32_get(unit, mem, entry, VALIDf)) {
   3188             *valid = FALSE;
   3189         }
   3190     }
   3191     /* validation for single view like MPLS_ENTRY_SINGLE */
   3192     if (SOC_MEM_FIELD_VALID(unit, mem, BASE_VALIDf)) {
   3193         if (0x1 != soc_mem_field32_get(unit, mem, entry, BASE_VALIDf)) {
   3194             *valid = FALSE;
   3195         }
   3196     }
   3197 
   3198     return BCM_E_NONE;
   3199 
   3200 }
   3201 
   3202 /*
   3203  * Function   :
   3204  *      _bcm_flow_tunnel_terminator_entry_parse
   3205  * Description   :
   3206  *      Convert the memory entry field data to the tunnel terminator
   3207  *      parameters.
   3208  * Parameters   :
   3209  *      unit             - (IN) Device Number
   3210  *      mem              - (IN)  memory id.
   3211  *      mem_view_id      - (IN)  memory view id.
   3212  *      entry            - (IN) HW entry.
   3213  *      info             - (OUT) Flow tunnel termination descriptor
   3214  *      num_of_fields    - (OUT) number of logical fields
   3215  *      field            - (OUT) logical field array
   3216  */
   3217 STATIC int
   3218 _bcm_flow_tunnel_terminator_entry_parse(int unit, 
   3219                              soc_mem_t mem, 
   3220                              uint32 *entry,
   3221                              bcm_flow_tunnel_terminator_t *info,
   3222                              uint32 *num_of_fields,
   3223                              bcm_flow_logical_field_t *field)
   3224 {
   3225     int key_type = SOC_FLOW_DB_KEY_TYPE_INVALID;
   3226     int data_type = SOC_FLOW_DB_KEY_TYPE_INVALID;
   3227     uint32 data_count;
   3228     int i;
   3229     soc_flow_db_mem_view_info_t vinfo;
   3230     uint32 key_list[SOC_FLOW_DB_MAX_VIEW_FIELDS];
   3231     uint32 key_count = 0;
   3232     uint32 field_list[SOC_FLOW_DB_MAX_VIEW_FIELDS];
   3233     uint32 cnt = 0;
   3234     soc_flow_db_ffo_t ffo[SOC_FLOW_DB_MAX_VIEW_FFO_TPL];
   3235     uint32 num_ffo = 0;
   3236     uint32 key_typef[] = {KEY_TYPEf,
   3237                          KEY_TYPE0f,
   3238                          KEY_TYPE1f};
   3239     uint32 data_typef[] = {DATA_TYPEf,
   3240                           DATA_TYPE0f,
   3241                           DATA_TYPE1f};
   3242     int rv = BCM_E_NONE;
   3243     uint32 mem_view_id = 0;
   3244 
   3245     for (i = 0; i < SOC_FLOW_DB_MAX_KEY_TYPE; i++) {
   3246         if (SOC_MEM_FIELD_VALID(unit,mem,key_typef[i])) {
   3247             key_type = soc_mem_field32_get(unit, mem, entry, key_typef[i]);
   3248             break;
   3249         }
   3250     }
   3251     for (i = 0; i < SOC_FLOW_DB_MAX_DATA_TYPE; i++) {
   3252         if (SOC_MEM_FIELD_VALID(unit,mem,data_typef[i])) {
   3253             data_type = soc_mem_field32_get(unit, mem, entry, data_typef[i]);
   3254         }
   3255     }
   3256 
   3257     /* find the memory view based on the memory and key type */
   3258     rv = soc_flow_db_mem_to_view_id_get (unit, mem, key_type, data_type,
   3259                     0, NULL, (uint32 *) &mem_view_id);
   3260 
   3261     if (rv != BCM_E_NONE && rv != BCM_E_NOT_FOUND) {
   3262         return rv;
   3263     }
   3264 
   3265     if (rv == BCM_E_NOT_FOUND) {
   3266         /* Fixed view */
   3267         switch (key_type) {
   3268             case _BCM_VXLAN_KEY_TYPE_LOOKUP_DIP:
   3269             case _BCM_VXLAN_FLEX_KEY_TYPE_LOOKUP_DIP:
   3270                 info->flow_handle = SOC_FLOW_DB_FLOW_ID_LEGACY_VXLAN;
   3271                 info->type = bcmTunnelTypeVxlan;
   3272                 break;
   3273             case _BCM_TD2_L2GRE_KEY_TYPE_LOOKUP_DIP:
   3274                 info->flow_handle = SOC_FLOW_DB_FLOW_ID_LEGACY_L2GRE;
   3275                 info->type = bcmTunnelTypeL2Gre;
   3276                 break;
   3277             default: 
   3278                 return BCM_E_NONE;
   3279         }
   3280 
   3281         if (info->flow_handle == SOC_FLOW_DB_FLOW_ID_LEGACY_VXLAN) {
   3282             if (soc_feature(unit, soc_feature_vxlan_decoupled_mode)) {
   3283                 info->dip = soc_mem_field32_get(unit, mem, entry, VXLAN_FLEX_IPV4_DIP__DIPf);
   3284                 info->valid_elements |= BCM_FLOW_TUNNEL_TERM_DIP_VALID;
   3285                 if (soc_mem_field32_get(unit, mem, entry,
   3286                                     VXLAN_FLEX_IPV4_DIP__IGNORE_UDP_CHECKSUMf) == 0x0) {
   3287                     info->flags |= BCM_TUNNEL_TERM_UDP_CHECKSUM_ENABLE;
   3288                 }
   3289 
   3290                 if (soc_mem_field32_get(unit, mem, entry,
   3291                                     VXLAN_FLEX_IPV4_DIP__USE_OUTER_HEADER_PHBf) == 0x01) {
   3292                     info->flags |= BCM_TUNNEL_TERM_USE_OUTER_DSCP;
   3293                 }
   3294                 if (soc_mem_field32_get(unit, mem, entry,
   3295                         VXLAN_FLEX_IPV4_DIP__USE_OUTER_HEADER_PHBf) == 0x02) {
   3296                     info->flags |= BCM_TUNNEL_TERM_USE_OUTER_PCP;
   3297                 }
   3298                 /* Multicast Flags */
   3299                 if(soc_mem_field32_get(unit, mem, entry,
   3300                         VXLAN_FLEX_IPV4_DIP__NETWORK_RECEIVERS_PRESENTf) == 0x01) {
   3301                    info->multicast_flag |= BCM_FLOW_MULTICAST_TUNNEL_STATE_BUD_ENABLE;
   3302                 } else if (soc_mem_field32_get(unit, mem, entry,
   3303                         VXLAN_FLEX_IPV4_DIP__NETWORK_RECEIVERS_PRESENTf) == 0x00) {
   3304                    info->multicast_flag |= BCM_FLOW_MULTICAST_TUNNEL_STATE_BUD_DISABLE;
   3305                 }
   3306             } else {
   3307                 info->dip = soc_mem_field32_get(unit, mem,
   3308                                                       entry, VXLAN_DIP__DIPf);
   3309                 info->valid_elements |= BCM_FLOW_TUNNEL_TERM_DIP_VALID;
   3310 
   3311                 if (soc_feature(unit, soc_feature_vrf_aware_vxlan_termination)) {
   3312                     info->vlan = soc_mem_field32_get(unit, mem, entry,
   3313                                         VXLAN_DIP__OVIDf);
   3314                 }
   3315 
   3316                 if (soc_mem_field32_get(unit, mem, entry,
   3317                                     VXLAN_DIP__IGNORE_UDP_CHECKSUMf) == 0x0) {
   3318                     info->flags |= BCM_TUNNEL_TERM_UDP_CHECKSUM_ENABLE;
   3319                 }
   3320 
   3321                 if (soc_mem_field32_get(unit, mem, entry,
   3322                                     VXLAN_DIP__USE_OUTER_HEADER_PHBf) == 0x01) {
   3323                     info->flags |= BCM_TUNNEL_TERM_USE_OUTER_DSCP;
   3324                 }
   3325                 if (soc_mem_field32_get(unit, mem, entry,
   3326                         VXLAN_DIP__USE_OUTER_HEADER_PHBf) == 0x02) {
   3327                     info->flags |= BCM_TUNNEL_TERM_USE_OUTER_PCP;
   3328                 }
   3329                 /* Multicast Flags */
   3330                 if(soc_mem_field32_get(unit, mem, entry,
   3331                         VXLAN_DIP__NETWORK_RECEIVERS_PRESENTf) == 0x01) {
   3332                    info->multicast_flag |= BCM_FLOW_MULTICAST_TUNNEL_STATE_BUD_ENABLE;
   3333                 } else if (soc_mem_field32_get(unit, mem, entry,
   3334                         VXLAN_DIP__NETWORK_RECEIVERS_PRESENTf) == 0x00) {
   3335                    info->multicast_flag |= BCM_FLOW_MULTICAST_TUNNEL_STATE_BUD_DISABLE;
   3336                 }
   3337             }
   3338         } else if (info->flow_handle == SOC_FLOW_DB_FLOW_ID_LEGACY_L2GRE) {
   3339             info->dip = soc_mem_field32_get(unit, mem,
   3340                                                   entry, L2GRE_DIP__DIPf);
   3341             info->flags |= BCM_FLOW_TUNNEL_TERM_DIP_VALID;
   3342             /* Multicast flags */
   3343             if(soc_mem_field32_get(unit, mem, entry,
   3344                     L2GRE_DIP__NETWORK_RECEIVERS_PRESENTf) == 0x01) {
   3345                info->multicast_flag |= BCM_FLOW_MULTICAST_TUNNEL_STATE_BUD_ENABLE;
   3346             } else if (soc_mem_field32_get(unit, mem, entry,
   3347                     L2GRE_DIP__NETWORK_RECEIVERS_PRESENTf) == 0x00) {
   3348                info->multicast_flag |= BCM_FLOW_MULTICAST_TUNNEL_STATE_BUD_DISABLE;
   3349             }
   3350 
   3351         } 
   3352         
   3353     } else {
   3354         /* Flex view */
   3355         /* find the memory view info */
   3356         BCM_IF_ERROR_RETURN(
   3357                soc_flow_db_mem_view_info_get(unit, mem_view_id, &vinfo));
   3358       
   3359         /* get the flow handle, function id, option id */
   3360         BCM_IF_ERROR_RETURN(
   3361               soc_flow_db_mem_view_to_ffo_get(unit,
   3362                                          mem_view_id,
   3363                                          SOC_FLOW_DB_MAX_VIEW_FFO_TPL,
   3364                                          ffo,
   3365                                          &num_ffo));
   3366        info->flow_handle = ffo[0].flow_handle;
   3367        info->flow_option = ffo[0].option_id;
   3368        info->type = bcmTunnelTypeL2Flex;
   3369           
   3370         /* key - Flex view */ 
   3371         BCM_IF_ERROR_RETURN(
   3372                 soc_flow_db_mem_view_field_list_get(unit,
   3373                 mem_view_id,
   3374                 SOC_FLOW_DB_FIELD_TYPE_KEY,
   3375                 SOC_FLOW_DB_MAX_VIEW_FIELDS,
   3376                 key_list,
   3377                 &key_count));
   3378 
   3379         for (i = 0; i < key_count; i++) {
   3380             if (key_list[i] == IPV4__DIPf) {
   3381                 info->dip = soc_mem_field32_get(unit, mem_view_id,
   3382                                               entry, IPV4__DIPf);
   3383                 info->valid_elements |= BCM_FLOW_TUNNEL_TERM_DIP_VALID;
   3384             } else if (key_list[i] == IPV4__SIPf) {
   3385                 info->sip = soc_mem_field32_get(unit, mem_view_id, 
   3386                                        entry, IPV4__SIPf);
   3387                 info->valid_elements |= BCM_FLOW_TUNNEL_TERM_SIP_VALID;
   3388             }  else if (key_list[i] == IPV4__DIP_MASKf) {
   3389                 info->dip_mask = soc_mem_field32_get(unit, mem_view_id,
   3390                                          entry, IPV4__DIP_MASKf);
   3391                 info->valid_elements |= BCM_FLOW_TUNNEL_TERM_DIP_MASK_VALID; 
   3392             } else if (key_list[i] == IPV4__SIP_MASKf) {
   3393                 info->sip_mask = soc_mem_field32_get(unit, mem_view_id,
   3394                                          entry, IPV4__SIP_MASKf);
   3395                 info->valid_elements |= BCM_FLOW_TUNNEL_TERM_SIP_MASK_VALID;
   3396             } else if (key_list[i] == IPV6__SIPf) {
   3397                 soc_mem_ip6_addr_get(unit, mem_view_id,
   3398                         entry, IPV6__SIPf, info->sip6, 0);
   3399                 info->valid_elements |= BCM_FLOW_TUNNEL_TERM_SIP6_VALID;
   3400             } else if (key_list[i] == IPV6__DIPf) {
   3401                 soc_mem_ip6_addr_get(unit, mem_view_id, 
   3402                         entry, IPV6__DIPf, info->dip6, 0);
   3403                 info->valid_elements |= BCM_FLOW_TUNNEL_TERM_DIP6_VALID;
   3404             } else if (key_list[i] == IPV6__SIP_MASKf) {
   3405                 soc_mem_ip6_addr_get(unit, mem_view_id,
   3406                         entry, IPV6__SIP_MASKf, info->sip6_mask, 0);
   3407                 info->valid_elements |= BCM_FLOW_TUNNEL_TERM_SIP6_MASK_VALID;
   3408             } else if (key_list[i] == IPV6__DIP_MASKf) {
   3409                 soc_mem_ip6_addr_get(unit, mem_view_id,
   3410                         entry, IPV6__DIP_MASKf, info->dip6_mask, 0);
   3411                 info->valid_elements |= BCM_FLOW_TUNNEL_TERM_DIP6_MASK_VALID;
   3412             } else if (key_list[i] == L4_DEST_PORTf) {
   3413                 info->udp_dst_port = soc_mem_field32_get(unit, mem_view_id,
   3414                                          entry, L4_DEST_PORTf);
   3415                 info->valid_elements |= BCM_FLOW_TUNNEL_TERM_UDP_DST_PORT_VALID;
   3416             } else if (key_list[i] ==  L4_SRC_PORTf) {
   3417                 info->udp_src_port = soc_mem_field32_get(unit, mem_view_id,
   3418                                          entry, L4_SRC_PORTf);
   3419                 info->valid_elements |= BCM_FLOW_TUNNEL_TERM_UDP_SRC_PORT_VALID;
   3420             } else if (key_list[i] ==  PROTOCOLf) {
   3421                 info->protocol  = soc_mem_field32_get(unit, mem_view_id,
   3422                                          entry, PROTOCOLf);
   3423                 info->valid_elements |= BCM_FLOW_TUNNEL_TERM_PROTOCOL_VALID;
   3424             }
   3425         }
   3426 
   3427         BCM_IF_ERROR_RETURN(soc_flow_db_mem_view_field_list_get(unit,
   3428                              mem_view_id,
   3429                              SOC_FLOW_DB_FIELD_TYPE_LOGICAL_KEY,
   3430                              SOC_FLOW_DB_MAX_VIEW_FIELDS, key_list, &key_count));
   3431         
   3432         if(key_count) {
   3433             info->valid_elements |= BCM_FLOW_TUNNEL_TERM_FLEX_KEY_VALID;
   3434         }
   3435         for (i = 0; i < key_count; i++) {
   3436             field[cnt].id = key_list[i];
   3437                 field[cnt++].value = soc_mem_field32_get(unit,mem_view_id, entry,
   3438                      key_list[i]);
   3439         }
   3440     
   3441         /* DATA - Flex VIew */    
   3442         if (soc_flow_db_mem_view_field_is_valid
   3443                        (unit, mem_view_id, TERM_TUNNELf)) {
   3444     
   3445             if (soc_mem_field32_get(unit, mem_view_id, entry,
   3446                                    IGNORE_UDP_CHECKSUMf) == 0x0)
   3447             {
   3448                 info->flags |= BCM_TUNNEL_TERM_UDP_CHECKSUM_ENABLE;
   3449             }
   3450             if (soc_mem_field32_get(unit, mem_view_id, entry,
   3451                              USE_OUTER_HEADER_PHBf) ==  0x1) {
   3452                 info->flags |= BCM_TUNNEL_TERM_USE_OUTER_DSCP;
   3453             }
   3454             if (soc_mem_field32_get(unit, mem_view_id, entry,
   3455                                        USE_OUTER_HEADER_PHBf) ==  0x2) {
   3456                 info->flags |= BCM_TUNNEL_TERM_USE_OUTER_PCP;
   3457             }
   3458             if (soc_mem_field32_get(unit, mem_view_id, entry, 
   3459                     USE_OUTER_HDR_TTLf) ==  1) {
   3460                  info->flags |=  BCM_TUNNEL_TERM_USE_OUTER_TTL;
   3461             }
   3462             if (soc_mem_field32_get(unit, mem_view_id, entry, 
   3463                     DONOT_CHANGE_INNER_HDR_DSCPf) ==  1) {
   3464                 info->flags |= BCM_TUNNEL_TERM_KEEP_INNER_DSCP;
   3465             }
   3466             if(soc_mem_field32_get(unit, mem_view_id, entry, 
   3467                     NETWORK_RECEIVERS_PRESENTf) == 0x01) {
   3468                info->multicast_flag |= BCM_FLOW_MULTICAST_TUNNEL_STATE_BUD_ENABLE;
   3469             } else if (soc_mem_field32_get(unit, mem_view_id, entry, 
   3470                     NETWORK_RECEIVERS_PRESENTf) == 0x00) {
   3471                info->multicast_flag |= BCM_FLOW_MULTICAST_TUNNEL_STATE_BUD_DISABLE;
   3472             }
   3473         }
   3474         BCM_IF_ERROR_RETURN(
   3475                     soc_flow_db_mem_view_field_list_get(unit,
   3476                         mem_view_id,
   3477                         SOC_FLOW_DB_FIELD_TYPE_LOGICAL_POLICY_DATA,
   3478                         SOC_FLOW_DB_MAX_VIEW_FIELDS, field_list, &data_count));
   3479        
   3480         if (data_count) {
   3481             info->valid_elements |= BCM_FLOW_TUNNEL_TERM_FLEX_DATA_VALID;
   3482         } 
   3483         for (i = 0; i < data_count; i++) {
   3484             field[cnt].id = field_list[i]; 
   3485             field[cnt++].value =
   3486                 soc_mem_field32_get(unit, mem_view_id, entry, field_list[i]);
   3487         }
   3488         *num_of_fields = cnt;
   3489                  
   3490     }
   3491     
   3492     return BCM_E_NONE; 
   3493 
   3494 }
   3495 
   3496 /*
   3497  * Function:
   3498  *      _bcm_flow_tunnel_terminator_traverse_mem
   3499  * Purpose:
   3500  *      Read the given memory table and call the user callback function on
   3501  *      each entry.
   3502  * Parameters:
   3503  *      unit          - (IN) Device Number
   3504  *      mem           - (IN) the memory id
   3505  *      cb            - (IN) user callback function
   3506  *      user_data     - (IN) user context data
   3507  * Returns:
   3508  *      BCM_E_XXX
   3509  */
   3510 
   3511 STATIC int
   3512 _bcm_flow_tunnel_terminator_mem_traverse(int unit, soc_mem_t mem,
   3513                              bcm_flow_tunnel_terminator_traverse_cb cb,
   3514                              void *user_data)
   3515 {
   3516 
   3517 
   3518     bcm_flow_tunnel_terminator_t info;
   3519     uint32 num_of_fields = _BCM_FLOW_LOGICAL_FIELD_MAX;
   3520     bcm_flow_logical_field_t field[_BCM_FLOW_LOGICAL_FIELD_MAX];
   3521     int             chnk_idx, ent_idx, chnk_idx_max, mem_idx_max;
   3522     int             buf_size, chunksize, chnk_end;
   3523     /* Buffer to store chunk of table we currently work on */
   3524     uint32          *vt_tbl_chnk;
   3525     uint32          *entry;
   3526     uint32          trav_entry[_QUAD_ENTRY_MAX];
   3527     int             valid = FALSE;
   3528     int             rv = BCM_E_NONE;
   3529     uint32 entry_width = _BCM_FLOW_TD3_L3_TUNNEL_SINGLE_ENTRY_SIZE;
   3530     uint32 num_hw_entries = 0;
   3531     int i = 0;
   3532 
   3533     if (INVALIDm == mem) {
   3534         return BCM_E_MEMORY;
   3535     }
   3536 
   3537     if (!soc_mem_index_count(unit, mem)) {
   3538         return BCM_E_NONE;
   3539     }
   3540 
   3541     chunksize = soc_property_get(unit, spn_VLANDELETE_CHUNKS,
   3542                                  VLAN_MEM_CHUNKS_DEFAULT);
   3543   
   3544     buf_size = 4 * SOC_MAX_MEM_FIELD_WORDS * chunksize;
   3545     vt_tbl_chnk = soc_cm_salloc(unit, buf_size, "flow tunnel terminator traverse");
   3546     if (NULL == vt_tbl_chnk) {
   3547         return BCM_E_MEMORY;
   3548     }
   3549     
   3550     mem_idx_max = soc_mem_index_max(unit, mem);
   3551     for (chnk_idx = soc_mem_index_min(unit, mem);
   3552          chnk_idx <= mem_idx_max;
   3553          chnk_idx += chunksize) {
   3554         sal_memset((void *)vt_tbl_chnk, 0, buf_size);
   3555 
   3556         chnk_idx_max =
   3557             ((chnk_idx + chunksize) <= mem_idx_max) ?
   3558             chnk_idx + chunksize - 1: mem_idx_max;
   3559 
   3560         rv = soc_mem_read_range(unit, mem, MEM_BLOCK_ANY,
   3561                                 chnk_idx, chnk_idx_max, vt_tbl_chnk);
   3562         if (SOC_FAILURE(rv)) {
   3563             break;
   3564         }
   3565         chnk_end = (chnk_idx_max - chnk_idx);
   3566         for (ent_idx = 0 ; ent_idx <= chnk_end; ) {
   3567             entry =
   3568                 soc_mem_table_idx_to_pointer(unit, mem, uint32 *,
   3569                                              vt_tbl_chnk, ent_idx);            
   3570             rv = _bcm_flow_tunnel_terminator_entry_valid(unit, 
   3571                               mem, entry, &valid);
   3572             if (BCM_FAILURE(rv)) {
   3573                 break;
   3574             }
   3575             if (!valid) {
   3576                 ent_idx++;
   3577                 continue;
   3578             }
   3579             if (mem == L3_TUNNELm) {
   3580                 rv = _bcm_esw_flow_tnl_term_num_hw_entries_get(unit, mem, 
   3581                              entry, &num_hw_entries); 
   3582                 if (BCM_FAILURE(rv)) {
   3583                     break;
   3584                 }
   3585                 for (i= 0; i < num_hw_entries; i++) {                    
   3586                     sal_memcpy((uint8 *)trav_entry + entry_width * i,
   3587                                 entry, entry_width);
   3588                     ent_idx++;
   3589                     entry = soc_mem_table_idx_to_pointer(unit, mem, uint32 *,
   3590                                              vt_tbl_chnk, ent_idx);
   3591                 }
   3592             } else {
   3593                 sal_memcpy(trav_entry, entry,
   3594                       WORDS2BYTES(soc_mem_entry_words(unit, mem)));
   3595                 ent_idx++;
   3596             }   
   3597             bcm_flow_tunnel_terminator_t_init(&info);
   3598              
   3599             rv = _bcm_flow_tunnel_terminator_entry_parse(unit, mem, trav_entry, &info,
   3600                     &num_of_fields,field);
   3601             if (rv == BCM_E_NOT_FOUND) { /* for entries not exposed to user */
   3602                 continue;
   3603             } else if (BCM_FAILURE(rv)) {
   3604                 break;
   3605             }
   3606             rv = cb(unit, &info, num_of_fields,field,user_data);
   3607             if (BCM_FAILURE(rv)) {
   3608                 break;
   3609             }
   3610         }
   3611     }
   3612     soc_cm_sfree(unit, vt_tbl_chnk);
   3613     return rv;
   3614 }
   3615 
   3616 /*
   3617  * Function:
   3618  *      bcmi_esw_flow_tunnel_terminator_traverse
   3619  * Purpose:
   3620  *      Traverse all flow tunnel initiator objects and call the user specified
   3621  * callback function on each object.
   3622  *
   3623  * Parameters:
   3624  *      unit      - (IN) Device Number
   3625  *      bcm_flow_tunnel_initiator_traverse_cb - (IN) user callback function 
   3626  *      user_data - (IN) user context data for the callback 
   3627  * Returns:
   3628  *      BCM_E_XXX
   3629  */
   3630 int bcmi_esw_flow_tunnel_terminator_traverse(
   3631     int unit,
   3632     bcm_flow_tunnel_terminator_traverse_cb cb,
   3633     void *user_data)
   3634 {
   3635     soc_mem_t mem; 
   3636  
   3637     if (NULL == cb) {
   3638         return (BCM_E_PARAM);
   3639     } 
   3640     mem = VLAN_XLATE_1_DOUBLEm; 
   3641     BCM_IF_ERROR_RETURN(
   3642           _bcm_flow_tunnel_terminator_mem_traverse(unit, mem, cb, user_data));
   3643     
   3644     mem = MPLS_ENTRYm; /* MPLS_ENTRY_DOUBLE */
   3645     BCM_IF_ERROR_RETURN(
   3646            _bcm_flow_tunnel_terminator_mem_traverse(unit, mem, cb, user_data));
   3647     
   3648     mem = L3_TUNNELm;
   3649     BCM_IF_ERROR_RETURN(
   3650            _bcm_flow_tunnel_terminator_mem_traverse(unit, mem, cb, user_data));
   3651     
   3652     mem = MPLS_ENTRY_SINGLEm;
   3653     BCM_IF_ERROR_RETURN(
   3654            _bcm_flow_tunnel_terminator_mem_traverse(unit, mem, cb, user_data));
   3655     return BCM_E_NONE;
   3656 }
   3657 
   3658 /*
   3659  * Function   :
   3660  *      _bcm_flow_tunnel_terminator_entry_term
   3661  * Description   :
   3662  *      Determine whether this is a tunnel terminator entry.
   3663  * Parameters   :
   3664  *      unit             - (IN) Device Number
   3665  *      mem              - (IN)  memory id.
   3666  *      entry            - (IN) HW entry.
   3667  *      term            - (OUT) Tunnel terminator entry.
   3668  */
   3669 STATIC int
   3670 _bcm_flow_tunnel_terminator_entry_term(int unit,
   3671                              soc_mem_t mem,
   3672                              uint32 *entry,
   3673                              int *term)
   3674 {
   3675     int key_type = SOC_FLOW_DB_KEY_TYPE_INVALID;
   3676     int data_type = SOC_FLOW_DB_KEY_TYPE_INVALID;
   3677     int i;
   3678     soc_flow_db_mem_view_info_t vinfo;
   3679     soc_flow_db_ffo_t ffo[SOC_FLOW_DB_MAX_VIEW_FFO_TPL];
   3680     uint32 num_ffo = 0;
   3681     uint32 key_typef[] = {KEY_TYPEf, KEY_TYPE0f, KEY_TYPE1f};
   3682     uint32 data_typef[] = {DATA_TYPEf, DATA_TYPE0f, DATA_TYPE1f};
   3683 
   3684     uint32 mem_view_id = 0;
   3685     int rv = BCM_E_NONE;
   3686 
   3687     for (i = 0; i < SOC_FLOW_DB_MAX_KEY_TYPE; i++) {
   3688         if (SOC_MEM_FIELD_VALID(unit,mem,key_typef[i])) {
   3689             key_type = soc_mem_field32_get(unit, mem, entry, key_typef[i]);
   3690             break;
   3691         }
   3692     }
   3693     for (i = 0; i < SOC_FLOW_DB_MAX_DATA_TYPE; i++) {
   3694         if (SOC_MEM_FIELD_VALID(unit,mem,data_typef[i])) {
   3695             data_type = soc_mem_field32_get(unit, mem, entry, data_typef[i]);
   3696         }
   3697     }
   3698 
   3699     /* find the memory view based on the memory and key type */
   3700     rv = soc_flow_db_mem_to_view_id_get (unit, mem, key_type, data_type,
   3701         0, NULL, (uint32 *) &mem_view_id);
   3702 
   3703     if (rv != BCM_E_NONE && rv != BCM_E_NOT_FOUND) {
   3704         return rv;
   3705     }
   3706 
   3707     *term = 0;
   3708     if (rv == BCM_E_NOT_FOUND) {
   3709         /* Fixed view */
   3710         if ((key_type == _BCM_VXLAN_KEY_TYPE_LOOKUP_DIP) ||
   3711             (key_type == _BCM_TD2_L2GRE_KEY_TYPE_LOOKUP_DIP)) {
   3712             *term = 1;
   3713         } else {
   3714             *term = 0;
   3715         }
   3716     } else {
   3717         /* Flex view */
   3718         /* find the memory view info */
   3719         BCM_IF_ERROR_RETURN(
   3720             soc_flow_db_mem_view_info_get(unit, mem_view_id, &vinfo));
   3721 
   3722         /* get the flow handle, function id, option id */
   3723         BCM_IF_ERROR_RETURN(
   3724             soc_flow_db_mem_view_to_ffo_get(unit,
   3725                 mem_view_id,
   3726                 SOC_FLOW_DB_MAX_VIEW_FFO_TPL,
   3727                 ffo,
   3728                 &num_ffo));
   3729 
   3730 
   3731         if(ffo[0].function_id == SOC_FLOW_DB_FUNC_TUNNEL_TERMINATOR_ID) {
   3732             *term = 1;
   3733         } else {
   3734             *term = 0;
   3735         }
   3736     }
   3737 
   3738     return BCM_E_NONE;
   3739 }
   3740 
   3741 /*
   3742  * Function:
   3743  *      bcmi_esw_flow_tunnel_terminator_destroy_all
   3744  * Purpose:
   3745  *      Destroy all flow tunnel terminator entry
   3746  *
   3747  * Parameters:
   3748  *      unit          - (IN)     Device Number
   3749  * Returns:
   3750  *      BCM_E_XXX
   3751  */
   3752 int bcmi_esw_flow_tunnel_terminator_destroy_all(
   3753     int unit)
   3754 {
   3755     soc_mem_t tunnel_mems[4] = {VLAN_XLATE_1_DOUBLEm, MPLS_ENTRYm,
   3756                                     L3_TUNNELm, INVALIDm};
   3757     int mem_index = 0;
   3758     soc_tunnel_term_t tnl_entry;
   3759     soc_tunnel_term_t ret_tnl_entry;
   3760     uint32 ret_entry[SOC_MAX_MEM_WORDS];
   3761     int index = 0;
   3762     int chnk_idx, ent_idx, chnk_idx_max, mem_idx_max;
   3763     int buf_size, chunksize, chnk_end;
   3764     uint32 *tbl_chnk;
   3765     uint32 *entry;
   3766     int valid = FALSE;
   3767     uint32 num_hw_entries = 0;
   3768     int i = 0;
   3769     soc_mem_t mem;
   3770     int term = 0;
   3771     int rv = BCM_E_NONE;
   3772 
   3773     if ((SOC_HW_RESET(unit) ||
   3774         (SOC_SWITCH_BYPASS_MODE(unit) != SOC_SWITCH_BYPASS_MODE_NONE))) {
   3775         return BCM_E_NONE;
   3776     }
   3777 
   3778     while (INVALIDm != tunnel_mems[mem_index]){
   3779         mem = tunnel_mems[mem_index++];
   3780         if (!soc_mem_index_count(unit, mem)) {
   3781             continue;
   3782         }
   3783 
   3784         chunksize = 1024;
   3785         buf_size = soc_mem_entry_words(unit, mem) * sizeof(uint32) * chunksize;
   3786         tbl_chnk = soc_cm_salloc(unit, buf_size, "flow tunnel term destroy");
   3787         if (NULL == tbl_chnk) {
   3788             return BCM_E_MEMORY;
   3789         }
   3790 
   3791         mem_idx_max = soc_mem_index_max(unit, mem);
   3792 
   3793         for (chnk_idx = soc_mem_index_min(unit, mem);
   3794                 chnk_idx <= mem_idx_max;
   3795                 chnk_idx += chunksize) {
   3796             sal_memset((void *)tbl_chnk, 0, buf_size);
   3797 
   3798             chnk_idx_max =
   3799                 ((chnk_idx + chunksize) <= mem_idx_max) ?
   3800                 chnk_idx + chunksize - 1: mem_idx_max;
   3801 
   3802             rv = soc_mem_read_range(unit, mem, MEM_BLOCK_ANY,
   3803                 chnk_idx, chnk_idx_max, tbl_chnk);
   3804             if (SOC_FAILURE(rv)) {
   3805                 break;
   3806             }
   3807 
   3808             chnk_end = (chnk_idx_max - chnk_idx);
   3809             for (ent_idx = 0 ; ent_idx <= chnk_end; ) {
   3810                 entry =
   3811                     soc_mem_table_idx_to_pointer(unit, mem, uint32 *,
   3812                         tbl_chnk, ent_idx);
   3813                 rv = _bcm_flow_tunnel_terminator_entry_valid(unit,
   3814                         mem, entry, &valid);
   3815                 if (BCM_FAILURE(rv)) {
   3816                     break;
   3817                 }
   3818                 if (!valid) {
   3819                     ent_idx++;
   3820                     continue;
   3821                 }
   3822                 if (mem == L3_TUNNELm) {
   3823                     rv = _bcm_esw_flow_tnl_term_num_hw_entries_get(unit, mem,
   3824                             entry, &num_hw_entries);
   3825                     if (BCM_FAILURE(rv)) {
   3826                         break;
   3827                     }
   3828                     for (i= 0; i < num_hw_entries; i++) {
   3829                         ent_idx++;
   3830                         entry = soc_mem_table_idx_to_pointer(unit, mem,
   3831                             uint32 *,tbl_chnk, ent_idx);
   3832                     }
   3833                 } else {
   3834                     ent_idx++;
   3835                 }
   3836 
   3837                 term = 0;
   3838                 rv = _bcm_flow_tunnel_terminator_entry_term(unit, mem,
   3839                         entry, &term);
   3840                 if (BCM_FAILURE(rv)) {
   3841                     break;
   3842                 } else if (term){
   3843                     if (mem == L3_TUNNELm) {
   3844                         rv = bcmi_esw_flow_entry_to_tnl_term(unit, entry,
   3845                                 &tnl_entry);
   3846                         if (rv == BCM_E_NONE) {
   3847                             rv = soc_tunnel_term_match(unit, &tnl_entry,
   3848                                 &ret_tnl_entry, &index);
   3849                         }
   3850                         if (rv == BCM_E_NONE) {
   3851                             rv = soc_tunnel_term_delete(unit, &ret_tnl_entry);
   3852                         }
   3853                     } else {
   3854                         rv = soc_mem_search(unit, mem, MEM_BLOCK_ANY, &index,
   3855                             entry, ret_entry, 0);
   3856                         if (rv == BCM_E_NONE) {
   3857                             rv = soc_mem_delete(unit, mem, MEM_BLOCK_ALL,
   3858                                 &ret_entry);
   3859                         }
   3860                     }
   3861 
   3862                     if ((rv != BCM_E_NOT_FOUND) && (rv != BCM_E_NONE)) {
   3863                         break;
   3864                     }
   3865                 } else {
   3866                     continue;
   3867                 }
   3868             }
   3869             /* error detect, ignore this table */
   3870             if (ent_idx <= chnk_end ) {
   3871                 break;
   3872             }
   3873         }
   3874         soc_cm_sfree(unit, tbl_chnk);
   3875     }
   3876 
   3877     return BCM_E_NONE;
   3878 }
   3879 
   3880 #ifdef BCM_WARM_BOOT_SUPPORT
   3881 
   3882 /*
   3883  * Function:
   3884  *      _bcm_flow_tunnel_initiator_reinit
   3885  * Purpose:
   3886  *      Tunnel initiator hash and ref-count recovery.
   3887  * Parameters:
   3888  *      unit          - (IN) BCM device number.
   3889  * Returns:
   3890  *      BCM_E_XXX
   3891  */
   3892 int
   3893 _bcm_flow_tunnel_initiator_reinit(int unit)
   3894 {
   3895     bcm_flow_tunnel_initiator_t tnl_init_info;
   3896     int rv = BCM_E_NONE;
   3897     int i = 0;
   3898     int idx_min = 0;
   3899     int idx_max = 0;
   3900     bcm_flow_logical_field_t field[_BCM_FLOW_LOGICAL_FIELD_MAX];
   3901     uint32 cnt;
   3902     soc_mem_t mem;
   3903     _bcm_flow_tunnel_record_t tnl_rec;
   3904 
   3905     mem = EGR_IP_TUNNELm;
   3906     idx_min = soc_mem_index_min(unit, mem);
   3907     idx_max = soc_mem_index_max(unit, mem);
   3908 
   3909     for (i = idx_min; i <= idx_max; i++) {
   3910 
   3911         bcm_flow_tunnel_initiator_t_init(&tnl_init_info);
   3912         rv = _bcm_flow_hw_tunnel_entry_get(unit, i, &tnl_init_info,field,
   3913                          _BCM_FLOW_LOGICAL_FIELD_MAX,&cnt);
   3914         BCM_IF_ERROR_RETURN(rv);
   3915 
   3916         tnl_rec.info = &tnl_init_info;
   3917         tnl_rec.field = field;
   3918         tnl_rec.num_of_fields = cnt;
   3919 
   3920         rv = _bcm_flow_tunnel_initiator_hash_calc(unit, &tnl_rec,
   3921                     &BCM_XGS3_L3_ENT_HASH(BCM_XGS3_L3_TBL_PTR(
   3922                         unit, tnl_init), i));
   3923         BCM_IF_ERROR_RETURN(rv);
   3924             BCM_XGS3_L3_ENT_REF_CNT_INC
   3925                 (BCM_XGS3_L3_TBL_PTR(unit, tnl_init), i,
   3926                     ((_BCM_TUNNEL_OUTER_HEADER_IPV6(tnl_init_info.type)) ?
   3927                         _BCM_DOUBLE_WIDE : _BCM_SINGLE_WIDE));
   3928     }
   3929     return rv;
   3930 }
   3931 #endif
   3932 
   3933 #endif  /* INCLUDE_L3 */
   3934