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_match.c (123438B)


      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_match.c
      8  * Purpose:     Flex flow match 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/virtual.h> 
     23 #include <bcm_int/esw/trx.h>
     24 #include <bcm_int/esw/port.h>
     25 #include <bcm_int/esw_dispatch.h>
     26 #include <bcm_int/esw/stack.h>
     27 #include <bcm_int/esw/vpn.h>
     28 #include <bcm_int/esw/flow.h>
     29 #include <soc/esw/flow_db.h>
     30 #include <include/soc/tnl_term.h>
     31 #include <bcm_int/esw/trident3.h>
     32 
     33 #define _BCM_FLOW_FFO_ENTRY_MAX  20
     34 #define _BCM_FLOW_TD3_L3_TUNNEL_DOUBLE_WIDE 2
     35 #define _BCM_FLOW_TD3_L3_TUNNEL_QUAD_WIDE   1
     36 #define _QUAD_ENTRY_MAX   (4 * SOC_MAX_MEM_WORDS)
     37 
     38 int _bcm_flow_mem_view_to_flow_info_get(int unit, 
     39                uint32 mem_view_id,
     40                uint32 func_id, 
     41                uint32 *flow_hndl,
     42                uint32 *flow_opt,
     43                int    instance)
     44 {
     45     int i;
     46     soc_flow_db_ffo_t ffo[_BCM_FLOW_FFO_ENTRY_MAX];
     47     uint32 num_ffo;
     48     uint32 match_num = 0;
     49     int rv;
     50 
     51     rv = soc_flow_db_mem_view_to_ffo_get(unit,mem_view_id, 
     52                           _BCM_FLOW_FFO_ENTRY_MAX, ffo, &num_ffo);
     53     SOC_IF_ERROR_RETURN(rv);
     54 
     55     rv = SOC_E_NOT_FOUND;    
     56     for (i = 0; i < num_ffo; i++) {
     57         if (ffo[i].function_id == func_id) {
     58             match_num++;     
     59             if (match_num == instance) {
     60                 *flow_hndl = ffo[i].flow_handle;
     61                 *flow_opt  = ffo[i].option_id;
     62                 rv = SOC_E_NONE;
     63                 break;
     64             }
     65         }
     66     }  
     67     return rv;
     68 }
     69 
     70 STATIC int
     71 _bcm_flow_match_term_entry_to_mem_entry(int unit, soc_mem_t mem,
     72                                soc_tunnel_term_t *tnl_entry,
     73                                uint32 *entry)
     74 {
     75 
     76     int entry_width = sizeof(tunnel_entry_t);
     77     int mode;
     78     int i;
     79 
     80     mode = soc_mem_field32_get(unit, mem,
     81                  (uint32 *)&tnl_entry->entry_arr[0], MODEf);
     82     sal_memcpy((uint8 *)entry, &tnl_entry->entry_arr[0],entry_width);
     83     if (mode == _BCM_FLOW_TD3_L3_TUNNEL_DOUBLE_WIDE) {
     84         sal_memcpy((uint8 *)entry + entry_width,
     85                    &tnl_entry->entry_arr[1],entry_width);
     86 
     87     } else if (mode == _BCM_FLOW_TD3_L3_TUNNEL_QUAD_WIDE) {
     88         for (i = 1; i < 4; i++) {
     89             if (i < COUNTOF(tnl_entry->entry_arr)) {
     90                 sal_memcpy((uint8 *)entry + entry_width * i,
     91                        &tnl_entry->entry_arr[i],entry_width);
     92             }
     93         }
     94     }
     95     return BCM_E_NONE;
     96 }
     97 
     98 STATIC int
     99 _bcm_flow_match_mem_entry_to_term_entry(int unit, soc_mem_t mem,
    100                                soc_tunnel_term_t *tnl_entry,
    101                                uint32 *entry)
    102 {
    103 
    104     int entry_width = sizeof(tunnel_entry_t);
    105     int mode;
    106     int i;
    107 
    108     sal_memcpy(&tnl_entry->entry_arr[0], (uint8 *)entry,entry_width);
    109     mode = soc_mem_field32_get(unit, mem,
    110                  (uint32 *)&tnl_entry->entry_arr[0], MODEf);
    111     if (mode == _BCM_FLOW_TD3_L3_TUNNEL_DOUBLE_WIDE) {
    112         sal_memcpy(&tnl_entry->entry_arr[1],
    113                    (uint8 *)entry + entry_width, entry_width);
    114 
    115     } else if (mode == _BCM_FLOW_TD3_L3_TUNNEL_QUAD_WIDE) {
    116         for (i = 1; i < 4; i++) {
    117             if (i < COUNTOF(tnl_entry->entry_arr)) {
    118                 sal_memcpy(&tnl_entry->entry_arr[i],
    119                        (uint8 *)entry + entry_width * i,entry_width);
    120             }
    121         }
    122     }
    123     return BCM_E_NONE;
    124 }
    125 /*
    126  * Function:
    127  *      _bcm_flow_match_untagged_profile_set
    128  * Purpose:
    129  *      Set  VLan profile per Physical port entry
    130  * Parameters:
    131  *      unit   - (IN) SOC unit #
    132  *      port  - (IN) Physical port
    133  * Returns:
    134  *      BCM_E_XXX
    135  */
    136 
    137 STATIC int
    138 _bcm_flow_match_untagged_profile_set (int unit, bcm_port_t port)
    139 {
    140     int rv=BCM_E_NONE;
    141     bcm_vlan_action_set_t action;
    142     uint32 ing_profile_idx = 0xffffffff;
    143     int old_ing_profile_idx = 0xffffffff;
    144 
    145 #if defined(BCM_TRIDENT3_SUPPORT)
    146     if (soc_feature(unit, soc_feature_vxlan_decoupled_mode)) {
    147         return BCM_E_NONE;
    148     }
    149 #endif
    150 
    151     bcm_vlan_action_set_t_init(&action);
    152     action.ut_outer = 0x0; /* No Op */
    153     action.ut_inner = 0x0; /* No Op */
    154 
    155     rv = _bcm_trx_vlan_action_profile_entry_add(unit, &action, &ing_profile_idx);
    156     if (rv < 0) {
    157         return rv;
    158     }
    159 
    160     SOC_IF_ERROR_RETURN(
    161         _bcm_esw_port_tab_get(unit, port, TAG_ACTION_PROFILE_PTRf,
    162                               &old_ing_profile_idx));
    163 
    164     rv = _bcm_esw_port_tab_set(unit, port, _BCM_CPU_TABS_NONE,
    165                                TAG_ACTION_PROFILE_PTRf, ing_profile_idx);
    166 
    167     if (old_ing_profile_idx != 0x1) {
    168         rv = _bcm_trx_vlan_action_profile_entry_delete(unit,
    169                 old_ing_profile_idx);
    170     }
    171 
    172     return rv;
    173 }
    174 
    175 /*
    176  * Function:
    177  *      _bcm_flow_match_untagged_profile_reset
    178  * Purpose:
    179  *      Reset  VLan profile per Physical port entry
    180  * Parameters:
    181  *      unit   - (IN) SOC unit #
    182  *      port  - (IN) Physical port
    183  * Returns:
    184  *      BCM_E_XXX
    185  */
    186 
    187 STATIC int
    188 _bcm_flow_match_untagged_profile_reset(int unit, bcm_port_t port)
    189 {
    190     int rv = BCM_E_NONE;
    191     int ing_profile_idx = -1;
    192 
    193     SOC_IF_ERROR_RETURN(
    194         _bcm_esw_port_tab_get(unit, port, TAG_ACTION_PROFILE_PTRf,
    195                               &ing_profile_idx));
    196     rv = _bcm_trx_vlan_action_profile_entry_delete(unit, ing_profile_idx);
    197     if (rv < 0) {
    198         return rv;
    199     }
    200 
    201     rv = _bcm_esw_port_tab_set(unit, port, _BCM_CPU_TABS_NONE,
    202                                TAG_ACTION_PROFILE_PTRf, 0x1);
    203 
    204     return rv;
    205 }
    206 
    207 /*
    208  * Function:
    209  *      _bcm_flow_match_trunk_table_set
    210  * Purpose:
    211  *      Configure Flow Trunk port entry
    212  * Parameters:
    213  *      unit    - (IN) Device Number
    214  *      port    - (IN) Trunk member port
    215  *      tgid    - (IN) Trunk group Id
    216  *      info    - (IN) flow_match configuration info 
    217  * Returns:
    218  *      BCM_E_XXX
    219  */
    220 
    221 STATIC int
    222 _bcm_flow_match_trunk_table_set(int unit, bcm_port_t port, bcm_trunk_t tgid, 
    223           bcm_flow_match_config_t *info, int *replaced_vp,int *replaced_iif)
    224 {
    225     source_trunk_map_table_entry_t trunk_map_entry;/*Trunk table entry buffer.*/
    226     bcm_module_t my_modid;
    227     int     src_trk_idx = -1;
    228     int     port_type;
    229     soc_mem_t mem = SOURCE_TRUNK_MAP_TABLEm;
    230     int     rv = BCM_E_NONE;
    231     int old_vp;
    232     int old_iif;
    233 
    234     if (tgid != BCM_TRUNK_INVALID) {
    235         port_type = 1; /* TRUNK_PORT_TYPE */
    236     } else {
    237         LOG_ERROR(BSL_LS_BCM_FLOW,
    238                   (BSL_META_U(unit, "Invalid Trunk ID\n")));
    239         return BCM_E_PARAM;
    240     }
    241 
    242     /* Get module id for unit. */
    243     BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &my_modid));
    244 
    245     /* Get index to source trunk map table */
    246     BCM_IF_ERROR_RETURN(_bcm_esw_src_mod_port_table_index_get(unit, my_modid,
    247                 port, &src_trk_idx));
    248 
    249     soc_mem_lock(unit, mem);
    250 
    251     /* Read source trunk map table. */
    252     rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY,
    253                         src_trk_idx, &trunk_map_entry);
    254 
    255     if (rv == SOC_E_NONE) {
    256 
    257         /* Set trunk group id. */
    258         soc_mem_field32_set(unit, mem, &trunk_map_entry, SRC_TGIDf, tgid);
    259 
    260         /* Set port is part of Trunk group */
    261         soc_mem_field32_set(unit, mem, &trunk_map_entry, PORT_TYPEf, port_type);
    262 
    263         if (info->valid_elements & BCM_FLOW_MATCH_FLOW_PORT_VALID) {
    264             int vp = _SHR_GPORT_FLOW_PORT_ID_GET(info->flow_port);
    265 
    266             if (replaced_vp && (!(*replaced_vp))) {
    267                 old_vp = soc_mem_field32_get(unit, mem, &trunk_map_entry, 
    268                                          SOURCE_VPf);
    269                 if (old_vp && (old_vp != vp)) {
    270                     *replaced_vp = old_vp;
    271                 }
    272             }
    273             /* Set SVP */
    274             soc_mem_field32_set(unit, mem, &trunk_map_entry, SOURCE_VPf, vp);
    275         }
    276 
    277         if (info->valid_elements & BCM_FLOW_MATCH_IIF_VALID) {
    278             if (replaced_iif && (!(*replaced_iif))) {
    279                 old_iif = soc_mem_field32_get(unit, mem, &trunk_map_entry, 
    280                                          L3_IIFf);
    281                 if (old_iif && (old_iif != info->intf_id)) {
    282                     *replaced_iif = old_iif;
    283                 }
    284             }
    285             /* Set IIF */
    286             soc_mem_field32_set(unit, mem, &trunk_map_entry, L3_IIFf,
    287                                     info->intf_id);
    288         }
    289 
    290         /* Write entry to hw. */
    291         rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, src_trk_idx, 
    292                             &trunk_map_entry);
    293     }
    294     soc_mem_unlock(unit, mem);
    295 
    296     return rv;
    297 }
    298 
    299 /*
    300  * Function:
    301  *      _bcm_flow_match_trunk_table_get
    302  * Purpose:
    303  *      Configure flow Trunk port entry
    304  * Parameters:
    305  *      unit    - (IN) Device Number
    306  *      port   - (IN) Trunk member port
    307  *      tgid - (IN) Trunk group Id
    308  *      info - (IN) flow_match configuration info 
    309  * Returns:
    310  *      BCM_E_XXX
    311  */
    312 
    313 STATIC int
    314 _bcm_flow_match_trunk_table_get(int unit, bcm_port_t port, bcm_trunk_t tgid, 
    315           bcm_flow_match_config_t *info)
    316 {
    317     source_trunk_map_table_entry_t trunk_map_entry;/*Trunk table entry buffer.*/
    318     bcm_module_t my_modid;
    319     int     src_trk_idx = -1;
    320     soc_mem_t mem = SOURCE_TRUNK_MAP_TABLEm;
    321     int     rv = BCM_E_NONE;
    322     uint32 vp;
    323 
    324     /* Get module id for unit. */
    325     BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &my_modid));
    326 
    327     /* Get index to source trunk map table */
    328     BCM_IF_ERROR_RETURN(_bcm_esw_src_mod_port_table_index_get(unit, my_modid,
    329                 port, &src_trk_idx));
    330 
    331     /* Read source trunk map table. */
    332     rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY,
    333                         src_trk_idx, &trunk_map_entry);
    334     SOC_IF_ERROR_RETURN(rv);
    335 
    336     /* Get SVP */
    337     vp = soc_mem_field32_get(unit, mem, &trunk_map_entry, SOURCE_VPf);
    338     _SHR_GPORT_FLOW_PORT_ID_SET(info->flow_port,vp);
    339 
    340     /* Get IIF */
    341     info->intf_id = soc_mem_field32_get(unit, mem, &trunk_map_entry, L3_IIFf);
    342 
    343     return rv;
    344 }
    345 
    346 /*
    347  * Function:
    348  *      _bcm_flow_match_trunk_table_reset
    349  * Purpose:
    350  *      Reset flow Trunk port entry
    351  * Parameters:
    352  *      unit    - (IN) Device Number
    353  *      port   - (IN) Trunk member port
    354  * Returns:
    355  *      BCM_E_XXX
    356  */
    357 
    358 STATIC int
    359 _bcm_flow_match_trunk_table_reset(int unit, bcm_port_t port, 
    360                 int *deleted_vp,int *deleted_iif)
    361 {
    362     source_trunk_map_table_entry_t trunk_map_entry;/*Trunk table entry buffer.*/
    363     bcm_module_t my_modid;
    364     int    src_trk_idx = -1;
    365     int rv = BCM_E_NONE;
    366     soc_mem_t mem = SOURCE_TRUNK_MAP_TABLEm;
    367     int vp;
    368     int iif;
    369  
    370     /* Get module id for unit. */
    371     BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &my_modid));
    372 
    373     /* Get index to source trunk map table */
    374     BCM_IF_ERROR_RETURN(_bcm_esw_src_mod_port_table_index_get(unit, my_modid,
    375                         port, &src_trk_idx));
    376 
    377     soc_mem_lock(unit, mem);
    378 
    379     /* Read source trunk map table. */
    380     rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY,
    381                                      src_trk_idx, &trunk_map_entry);
    382     if (rv == SOC_E_NONE) {
    383 
    384         /* Set trunk group id. */
    385         soc_mem_field32_set(unit, mem, &trunk_map_entry, SRC_TGIDf, 0);
    386 
    387         vp = soc_mem_field32_get(unit, mem, &trunk_map_entry, SOURCE_VPf);
    388         if (deleted_vp && (!(*deleted_vp))) {
    389             vp = soc_mem_field32_get(unit, mem, &trunk_map_entry, SOURCE_VPf);
    390             if (vp) {
    391                 *deleted_vp = vp;
    392             }
    393         }
    394 
    395         /* Set SVP */
    396         soc_mem_field32_set(unit, mem, &trunk_map_entry, SOURCE_VPf, 0);
    397 
    398         if (deleted_iif && (!(*deleted_iif))) {
    399             iif = soc_mem_field32_get(unit, mem, &trunk_map_entry, L3_IIFf);
    400             if (iif) {
    401                 *deleted_iif = iif;
    402             }
    403         }
    404         soc_mem_field32_set(unit, mem, &trunk_map_entry, L3_IIFf, 0);
    405 
    406         /* Write entry to hw. */
    407         rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, src_trk_idx, 
    408                            &trunk_map_entry);
    409     }
    410     soc_mem_unlock(unit, mem);
    411 
    412     return rv;
    413 }
    414 
    415 /*
    416  * Function:
    417  *      _bcm_flow_match_trunk_add
    418  * Purpose:
    419  *      Assign SVP of  flow Trunk port
    420  * Parameters:
    421  *      unit - (IN) Device Number
    422  *      tgid - (IN) Trunk group Id
    423  *      info - (IN) flow_match configuration info 
    424  * Returns:
    425  *      BCM_E_XXX
    426  */
    427 
    428 STATIC int
    429  _bcm_flow_match_trunk_add(int unit, 
    430           bcm_trunk_t tgid, 
    431           bcm_flow_match_config_t *info,
    432           int *replaced_vp,
    433           int *replaced_iif)
    434 {
    435     int port_idx=0;
    436     int local_port_out[SOC_MAX_NUM_PORTS];
    437     int local_member_count=0;
    438     int rv = BCM_E_NONE;
    439 
    440     BCM_IF_ERROR_RETURN(_bcm_esw_trunk_local_members_get(unit, tgid,
    441                 SOC_MAX_NUM_PORTS, local_port_out, &local_member_count));
    442     for (port_idx = 0; port_idx < local_member_count; port_idx++) {
    443         rv = _bcm_flow_match_trunk_table_set(unit, 
    444                             local_port_out[port_idx], tgid, info,
    445                             replaced_vp,replaced_iif);
    446         if (BCM_FAILURE(rv)) {
    447             goto trunk_cleanup;
    448         }
    449         rv = _bcm_esw_port_tab_set(
    450                  unit, local_port_out[port_idx],
    451                  _BCM_CPU_TABS_NONE, PORT_OPERATIONf, 1); /* L2_SVP */
    452         if (BCM_FAILURE(rv)) {
    453             goto trunk_cleanup;
    454         }
    455 
    456         rv = _bcm_flow_match_untagged_profile_set(unit, 
    457                                      local_port_out[port_idx]);
    458         if (BCM_FAILURE(rv)) {
    459             goto trunk_cleanup;
    460         }
    461     }
    462 
    463     return BCM_E_NONE;
    464 
    465  trunk_cleanup:
    466     for (; port_idx >= 0; port_idx--) {
    467         (void) _bcm_esw_port_tab_set(unit, local_port_out[port_idx],
    468                                  _BCM_CPU_TABS_NONE, PORT_OPERATIONf, 0);
    469         (void) _bcm_flow_match_trunk_table_reset(unit, 
    470                                local_port_out[port_idx],NULL,NULL);
    471     }
    472     return rv;
    473 }
    474 
    475 /*
    476  * Function:
    477  *      _bcm_flow_match_trunk_delete
    478  * Purpose:
    479  *      Remove SVP of flow Trunk port
    480  * Parameters:
    481  *      unit - (IN) Device Number
    482  *      tgid - (IN) Trunk group Id
    483  *      info - (IN) flow_match configuration info 
    484  * Returns:
    485  *      BCM_E_XXX
    486  */
    487 
    488 STATIC int
    489 _bcm_flow_match_trunk_delete(int unit, 
    490           bcm_trunk_t tgid,
    491           bcm_flow_match_config_t *info,
    492           int *deleted_vp,
    493           int *deleted_iif)
    494 {
    495     int port_idx=0;
    496     int local_port_out[SOC_MAX_NUM_PORTS];
    497     int local_member_count=0;
    498     int rv = BCM_E_NONE;
    499 
    500     BCM_IF_ERROR_RETURN(_bcm_esw_trunk_local_members_get(unit, tgid,
    501                 SOC_MAX_NUM_PORTS, local_port_out, &local_member_count));
    502 
    503     for (port_idx = 0; port_idx < local_member_count; port_idx++) {
    504         rv = _bcm_flow_match_trunk_table_reset(unit, local_port_out[port_idx],
    505                     deleted_vp,deleted_iif);
    506         if (BCM_FAILURE(rv)) {
    507             goto trunk_cleanup;
    508         }
    509         rv = _bcm_esw_port_tab_set(unit, local_port_out[port_idx],
    510                                    _BCM_CPU_TABS_NONE, PORT_OPERATIONf, 0);
    511         if (BCM_FAILURE(rv)) {
    512             goto trunk_cleanup;
    513         }
    514 
    515         rv = _bcm_flow_match_untagged_profile_reset(unit, 
    516                                   local_port_out[port_idx]);
    517         if (BCM_FAILURE(rv)) {
    518             goto trunk_cleanup;
    519         }
    520     }
    521 
    522     return BCM_E_NONE;
    523 
    524  trunk_cleanup:
    525     for (;port_idx >= 0; port_idx--) {
    526         (void)_bcm_esw_port_tab_set(unit, local_port_out[port_idx],
    527                                     _BCM_CPU_TABS_NONE, PORT_OPERATIONf, 0x1);
    528         (void) _bcm_flow_match_trunk_table_set(unit, local_port_out[port_idx], 
    529                             tgid, info,NULL,NULL);
    530     }
    531     return rv;
    532 }
    533 
    534 /*
    535  * Function:
    536  *      _bcm_flow_match_trunk_get
    537  * Purpose:
    538  *      Assign SVP of  flow Trunk port
    539  * Parameters:
    540  *      unit - (IN) Device Number
    541  *      tgid - (IN) Trunk group Id
    542  *      info - (IN) flow_match configuration info 
    543  * Returns:
    544  *      BCM_E_XXX
    545  */
    546 
    547 STATIC int
    548  _bcm_flow_match_trunk_get(int unit, 
    549           bcm_trunk_t tgid, 
    550           bcm_flow_match_config_t *info)
    551 {
    552     int local_port_out[SOC_MAX_NUM_PORTS];
    553     int local_member_count=0;
    554     int rv = BCM_E_NONE;
    555 
    556     BCM_IF_ERROR_RETURN(_bcm_esw_trunk_local_members_get(unit, tgid,
    557                 SOC_MAX_NUM_PORTS, local_port_out, &local_member_count));
    558     
    559     /* get from the first port */
    560     rv = _bcm_flow_match_trunk_table_get(unit, 
    561                             local_port_out[0], tgid, info);
    562     BCM_IF_ERROR_RETURN(rv);
    563     return BCM_E_NONE;
    564 }
    565 
    566 /*
    567  * Function:
    568  *      _bcm_flow_match_fixed_view_entry_init
    569  * Purpose:
    570  *      initialize the fixed view memory entry
    571  * Parameters:
    572  *      unit - (IN) Device Number
    573  *      mem  - (IN) memory id
    574  *      info - (IN) flow_match configuration info 
    575  *      key_type - (IN) the fixed key type
    576  *      entry    - (OUT) point to the entry to be initialized
    577  * Returns:
    578  *      BCM_E_XXX
    579  */
    580 STATIC int
    581 _bcm_flow_match_fixed_view_entry_init(int unit,
    582         soc_mem_t mem,
    583         bcm_flow_match_config_t *info,
    584         uint32 key_type,
    585         uint32 *entry)
    586 {
    587     int rv = BCM_E_NONE;
    588 
    589     soc_mem_field32_set(unit,mem, entry,  KEY_TYPEf,  key_type);
    590     if (key_type == _BCM_FLOW_MATCH_KEY_TYPE_VXLAN_FLEX_VNID) {
    591         soc_mem_field32_set(unit, mem, entry, DATA_TYPEf,
    592             _BCM_FLOW_MATCH_KEY_TYPE_VXLAN_FLEX_SIP_VNID);
    593     } else if (key_type == _BCM_FLOW_MATCH_KEY_TYPE_VXLAN_SIP) {
    594         soc_mem_field32_set(unit, mem, entry, DATA_TYPEf,
    595             _BCM_VXLAN_FLEX_DATA_TYPE_IPV4_SIP);
    596     } else {
    597         soc_mem_field32_set(unit, mem, entry, DATA_TYPEf, key_type);
    598     }
    599 
    600     if (soc_mem_field_valid(unit, mem, BASE_VALIDf)) {
    601         soc_mem_field32_set(unit, mem, entry, BASE_VALIDf, 1);
    602     } else {
    603         soc_mem_field32_set(unit, mem, entry, BASE_VALID_0f, 3);
    604         soc_mem_field32_set(unit, mem, entry, BASE_VALID_1f, 7);
    605     }
    606 
    607     return rv;
    608 }
    609 
    610 STATIC int
    611 _bcm_flow_match_sgpp_ctrl_set(int unit,
    612         bcm_flow_match_config_t *info,
    613         uint32 num_of_fields,
    614         bcm_flow_logical_field_t *field,
    615         int clear_action)
    616 {
    617     soc_mem_t sgpp_view_id;
    618     int rv, i, j;
    619     uint32 entry[SOC_MAX_MEM_WORDS];
    620     bcm_module_t mod_out = -1;
    621     bcm_port_t port_out = -1;
    622     bcm_trunk_t trunk_id = -1;
    623     int    gport_id=-1;
    624     int    src_trk_idx=0;  /*Source Trunk table index.*/
    625     soc_mem_t mem;
    626     int ctrl_profile1 = 0, ctrl_profile0 = 0;
    627     int edit_ctrl_id = 0, vxlt_ctrl_id = 0;
    628     int gbp_sel = 0;
    629     uint32  data_array[_BCM_FLOW_LOGICAL_FIELD_MAX];
    630     uint32  data_count;
    631     uint32 values[4];
    632     soc_field_t fields[4];
    633     int field_cnt = 0;
    634     soc_flow_db_mem_view_info_t vinfo;
    635 
    636     /* currently don't handle trunk port yet */
    637     if (BCM_GPORT_IS_TRUNK(info->port)) {
    638         return BCM_E_UNAVAIL;
    639     }
    640 
    641     sal_memset(entry, 0, sizeof(entry));
    642     rv = soc_flow_db_ffo_to_mem_view_id_get(unit,info->flow_handle, info->flow_option,
    643                  SOC_FLOW_DB_FUNC_SGPP_CONTROL_ID, (uint32 *)&sgpp_view_id);
    644     SOC_IF_ERROR_RETURN(rv);
    645 
    646     soc_flow_db_mem_view_entry_init(unit,sgpp_view_id,entry);
    647     if (SOC_MEM_FIELD_VALID(unit, sgpp_view_id, CTRL_PROFILE_IDX_1f)) {
    648         ctrl_profile1 = soc_mem_field32_get(unit, sgpp_view_id, entry,
    649                                             CTRL_PROFILE_IDX_1f);
    650     }
    651     if (SOC_MEM_FIELD_VALID(unit, sgpp_view_id, CTRL_PROFILE_IDX_0f)) {
    652         ctrl_profile0 = soc_mem_field32_get(unit, sgpp_view_id, entry,
    653                                             CTRL_PROFILE_IDX_0f);
    654     }
    655     if (SOC_MEM_FIELD_VALID(unit, sgpp_view_id, EDIT_CTRL_IDf)) {
    656         edit_ctrl_id = soc_mem_field32_get(unit, sgpp_view_id, entry,
    657                                            EDIT_CTRL_IDf);
    658         if (clear_action) {
    659             edit_ctrl_id = 0;  /* clear to default */
    660         }
    661         fields[field_cnt] = EDIT_CTRL_IDf;
    662         values[field_cnt++] = edit_ctrl_id;
    663 
    664     }
    665     if (SOC_MEM_FIELD_VALID(unit, sgpp_view_id, VXLT_CTRL_IDf)) {
    666         vxlt_ctrl_id = soc_mem_field32_get(unit, sgpp_view_id, entry,
    667                                            VXLT_CTRL_IDf);
    668         if (clear_action) {
    669             vxlt_ctrl_id = 0;  /* clear to default */
    670         }
    671         fields[field_cnt] = VXLT_CTRL_IDf;
    672         values[field_cnt++] = vxlt_ctrl_id;
    673 
    674     }
    675     if (info->valid_elements & BCM_FLOW_MATCH_FLEX_DATA_VALID) {
    676         if (SOC_MEM_FIELD_VALID(unit, sgpp_view_id, IDf)) {
    677             gbp_sel = soc_mem_field32_get(unit, sgpp_view_id, entry,
    678                     IDf);
    679         }
    680     }
    681     BCM_IF_ERROR_RETURN(_bcm_esw_gport_resolve(unit, info->port,
    682                            &mod_out, &port_out, &trunk_id, &gport_id));
    683 
    684     /* Get index to source trunk map table */
    685     BCM_IF_ERROR_RETURN(_bcm_esw_src_mod_port_table_index_get(unit, mod_out,
    686                  port_out, &src_trk_idx));
    687 
    688     rv = soc_flow_db_mem_view_info_get(unit, sgpp_view_id, &vinfo);
    689     BCM_IF_ERROR_RETURN(rv);
    690 
    691     mem = vinfo.mem;
    692     soc_mem_lock(unit,mem);
    693     rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, src_trk_idx, entry);
    694     if (SOC_SUCCESS(rv)) {
    695         if (SOC_MEM_FIELD_VALID(unit, sgpp_view_id, CTRL_PROFILE_IDX_1f)) {
    696             if (clear_action) {
    697                 ctrl_profile1 = 0;  /* clear to default */
    698             }
    699             soc_mem_field32_set(unit, sgpp_view_id, entry, CTRL_PROFILE_IDX_1f,
    700                                 ctrl_profile1);
    701         }
    702         if (SOC_MEM_FIELD_VALID(unit, sgpp_view_id, CTRL_PROFILE_IDX_0f)) {
    703             if (clear_action) {
    704                 ctrl_profile0 = 0;  /* clear to default */
    705             }
    706             soc_mem_field32_set(unit, sgpp_view_id, entry, CTRL_PROFILE_IDX_0f,
    707                                 ctrl_profile0);
    708         }
    709         if (info->valid_elements & BCM_FLOW_MATCH_FLEX_DATA_VALID) {
    710             if (SOC_MEM_FIELD_VALID(unit, sgpp_view_id, IDf)) {
    711                 if (clear_action) {
    712                     gbp_sel = 0;  /* clear to default */
    713                 }
    714                 soc_mem_field32_set(unit, sgpp_view_id, entry, IDf,
    715                                     gbp_sel);
    716             }
    717             /* Get logical PDD field list for this view id. */
    718             rv = soc_flow_db_mem_view_field_list_get(unit, sgpp_view_id,
    719                     SOC_FLOW_DB_FIELD_TYPE_LOGICAL_POLICY_DATA,
    720                     _BCM_FLOW_LOGICAL_FIELD_MAX,
    721                     data_array, &data_count);
    722             BCM_IF_ERROR_RETURN(rv);
    723             for (j = 0; j < num_of_fields; j++) {
    724                 for (i = 0; i < data_count; i++) {
    725                     if (field[j].id == data_array[i]) {
    726                         if (clear_action) {
    727                             field[j].value = 0;  /* clear to default */
    728                         }
    729                         soc_mem_field32_set(unit, sgpp_view_id, entry, field[j].id,
    730                                             field[j].value);
    731                         break;
    732                     }
    733                 }
    734             }
    735         }
    736         rv = soc_mem_write(unit, mem, MEM_BLOCK_ANY, src_trk_idx, entry);
    737     }
    738             
    739     soc_mem_unlock(unit,mem);
    740 
    741     mem = EGR_LPORT_PROFILEm;
    742     soc_mem_lock(unit,mem);
    743     if (soc_feature(unit, soc_feature_egr_lport_tab_profile)) {
    744         rv = bcm_esw_port_egr_lport_fields_set(unit, info->port,
    745                                     mem, field_cnt, fields, values);
    746     }
    747     soc_mem_unlock(unit,mem);
    748     return rv;
    749 }
    750 
    751 STATIC
    752 void _bcm_flow_match_default_option_get(
    753     int unit,
    754     bcm_flow_match_config_t *info,
    755     char **option_str)
    756 {
    757     *option_str = NULL;
    758     
    759     if (info->criteria == BCM_FLOW_MATCH_CRITERIA_SIP) {
    760         if (info->valid_elements & (BCM_FLOW_MATCH_SIP_VALID |
    761                                     BCM_FLOW_MATCH_FLOW_PORT_VALID)) {
    762             *option_str = "LOOKUP_IPV4_SIP_ASSIGN_SVP";
    763         } else if (info->valid_elements & (BCM_FLOW_MATCH_SIP_V6_VALID |
    764                                     BCM_FLOW_MATCH_FLOW_PORT_VALID)) {
    765             *option_str = "LOOKUP_IPV6_SIP_ASSIGN_SVP";
    766         } 
    767     } else if (info->criteria == BCM_FLOW_MATCH_CRITERIA_VN_ID) {
    768         if (info->valid_elements & (BCM_FLOW_MATCH_VNID_VALID |
    769                                     BCM_FLOW_MATCH_VPN_VALID)) {
    770             *option_str = "LOOKUP_VNID_ASSIGN_VFI";
    771         } else if (info->valid_elements & (BCM_FLOW_MATCH_VNID_VALID |
    772                                     BCM_FLOW_MATCH_IIF_VALID)) {
    773             *option_str = "LOOKUP_VNID_ASSIGN_L3_IIF";
    774         } 
    775     } else if (info->criteria == BCM_FLOW_MATCH_CRITERIA_MPLS_LABEL) {
    776         *option_str = "LOOKUP_MPLS_LABEL_ASSIGN_SVP";
    777     }
    778 }
    779 
    780 /*
    781  * Function:
    782  *      _bcm_flow_match_entry_set
    783  * Purpose:
    784  *      Set flow Match Entry
    785  * Parameters:
    786  *      unit - (IN) Device Number
    787  *      info - (IN) flow_match configuration info 
    788  *      field - (IN) array of logical fields 
    789  *      num_of_fields -(IN) the size of the above array 
    790  *      mem  - (IN) memory id
    791  *      entry - (IN) point to the match entry
    792  * Returns:
    793  *      BCM_E_XXX
    794  */
    795 
    796 STATIC int
    797 _bcm_flow_match_entry_set(int unit, 
    798         bcm_flow_match_config_t *info, 
    799         bcm_flow_logical_field_t *field,
    800         int num_of_fields,
    801         soc_flow_db_mem_view_info_t *view_info,
    802         uint32 *entry,
    803         int *replaced_iif,
    804         int *replaced_vp)
    805 {
    806     int rv = BCM_E_NONE;
    807     int i;
    808     int j;
    809     int index = -1;
    810     int action_type;
    811     uint32 return_entry[_QUAD_ENTRY_MAX];
    812     int vp = _SHR_GPORT_FLOW_PORT_ID_GET(info->flow_port);
    813     int new_entry_add = FALSE;
    814     soc_mem_t mem;
    815     soc_tunnel_term_t tnl_entry;
    816     soc_tunnel_term_t tnl_return_entry;
    817     uint32 action_set;
    818 
    819     sal_memset(&tnl_entry, 0, sizeof(soc_tunnel_term_t));
    820     sal_memset(&tnl_return_entry, 0, sizeof(soc_tunnel_term_t));
    821 
    822     mem = _BCM_FLOW_IS_FLEX_VIEW(info)? 
    823              view_info->mem_view_id: view_info->mem;
    824 
    825     if (replaced_iif != NULL) {
    826         *replaced_iif = 0;
    827     } 
    828     if (replaced_vp != NULL) {
    829         *replaced_vp = 0;
    830     } 
    831     if (view_info->mem == L3_TUNNELm) {  /* TCAM */
    832         rv = _bcm_flow_match_mem_entry_to_term_entry(unit, mem,
    833                         &tnl_entry, entry);
    834         BCM_IF_ERROR_RETURN(rv);
    835         rv = soc_tunnel_term_match(unit,&tnl_entry, 
    836                           &tnl_return_entry, &index);
    837     } else { /* hash table */
    838         rv = soc_mem_search(unit, mem, MEM_BLOCK_ANY, &index, entry,
    839                         return_entry, 0);
    840     }
    841     if (BCM_E_NONE == rv) {
    842         /* found memory entry */
    843         if (info->options & BCM_FLOW_MATCH_OPTION_REPLACE) {
    844             if (view_info->mem == L3_TUNNELm) {
    845                 BCM_IF_ERROR_RETURN(
    846                 _bcm_flow_match_term_entry_to_mem_entry(unit, mem,
    847                         &tnl_return_entry, return_entry));
    848             }
    849             sal_memcpy(entry,return_entry,sizeof(return_entry));
    850         } else {
    851             LOG_ERROR(BSL_LS_BCM_FLOW,
    852                   (BSL_META_U(unit, "Entry with same key already exists\n")));
    853             return BCM_E_EXISTS;
    854         }
    855     } else if (BCM_E_NOT_FOUND == rv) {
    856         if (info->options & BCM_FLOW_MATCH_OPTION_REPLACE) {
    857             LOG_ERROR(BSL_LS_BCM_FLOW,
    858                   (BSL_META_U(unit, "Entry doesn't exist\n")));
    859             return BCM_E_NOT_FOUND;
    860         } else {
    861             new_entry_add = TRUE;
    862         }
    863     } else {
    864         return rv;
    865     }
    866 
    867     /* data fields: flex view uses PDD */
    868     action_type = 0;
    869     if (info->valid_elements & BCM_FLOW_MATCH_FLOW_PORT_VALID) {
    870         if (_BCM_FLOW_IS_FLEX_VIEW(info)) {
    871             if (!SOC_MEM_FIELD_VALID(unit, mem, SVP_ACTION_SETf)) {
    872                 return BCM_E_PARAM;
    873             }
    874             if (new_entry_add == FALSE && replaced_vp != NULL) {
    875                 action_set = soc_mem_field32_get(unit, mem, entry,
    876                                  SVP_ACTION_SETf);
    877                 *replaced_vp = soc_format_field32_get(unit, SVP_ACTION_SETfmt, 
    878                                       &action_set, SVPf);
    879             }
    880             action_set = 0;
    881             soc_format_field32_set(unit, SVP_ACTION_SETfmt,
    882                                        &action_set, SVPf, vp);
    883             soc_mem_field32_set(unit, mem, entry, SVP_ACTION_SETf, action_set);
    884         } else {
    885             if (info->flow_handle == SOC_FLOW_DB_FLOW_ID_LEGACY_VXLAN) {
    886                 soc_field_t svp_f = VXLAN_SIP__SVPf;
    887 
    888                 if (soc_feature(unit, soc_feature_vxlan_decoupled_mode)) {
    889                     svp_f = VXLAN_FLEX_IPV4_SIP__SVPf;
    890                 }
    891                 if (!SOC_MEM_FIELD_VALID(unit, mem, svp_f)) {
    892                     return BCM_E_PARAM;
    893                 }
    894                 if (new_entry_add == FALSE && replaced_vp != NULL) {
    895                     *replaced_vp = soc_mem_field32_get(unit, mem, entry,
    896                                            svp_f);
    897                 }
    898                 soc_mem_field32_set(unit, mem, entry, svp_f, vp);
    899             } else if (info->flow_handle == SOC_FLOW_DB_FLOW_ID_LEGACY_L2GRE) {
    900                 if (!SOC_MEM_FIELD_VALID(unit, mem, L2GRE_SIP__SVPf)) {
    901                     return BCM_E_PARAM;
    902                 }
    903                 if (new_entry_add == FALSE && replaced_vp != NULL) {
    904                     *replaced_vp = soc_mem_field32_get(unit, mem, entry, 
    905                                            L2GRE_SIP__SVPf);
    906                 }
    907                 soc_mem_field32_set(unit, mem, entry, L2GRE_SIP__SVPf, vp);
    908             } else {
    909                 if (!SOC_MEM_FIELD_VALID(unit, mem, XLATE__SOURCE_VPf)) {
    910                     return BCM_E_PARAM;
    911                 }
    912                 if (new_entry_add == FALSE && replaced_vp != NULL) {
    913                     *replaced_vp = soc_mem_field32_get(unit, mem, entry, 
    914                                            XLATE__SOURCE_VPf);
    915                 }
    916                 action_type = 1; /*SVP */
    917                 soc_mem_field32_set(unit, mem, entry, XLATE__MPLS_ACTIONf, 
    918                             action_type); 
    919                 soc_mem_field32_set(unit, mem, entry, XLATE__SOURCE_VPf, vp);
    920             }
    921         }
    922     }
    923 
    924     /* get the replaced iif if replace action */
    925     if (info->valid_elements & BCM_FLOW_MATCH_IIF_VALID) {
    926         if (_BCM_FLOW_IS_FLEX_VIEW(info)) {
    927             if (!SOC_MEM_FIELD_VALID(unit, mem, L3_IIF_ACTION_SETf)) {
    928                 return BCM_E_PARAM;
    929             }
    930             if (new_entry_add == FALSE && replaced_iif != NULL) {
    931                 *replaced_iif = soc_mem_field32_get(unit, mem, entry, 
    932                                         L3_IIF_ACTION_SETf);
    933             }
    934             soc_mem_field32_set(unit, mem, entry, L3_IIF_ACTION_SETf, 
    935                    info->intf_id);
    936         } else {
    937             if (!SOC_MEM_FIELD_VALID(unit, mem, XLATE__L3_IIFf)) {
    938                 return BCM_E_PARAM;
    939             }
    940             if (new_entry_add == FALSE && replaced_iif != NULL) {
    941                 *replaced_iif = soc_mem_field32_get(unit, mem, entry, 
    942                                         XLATE__L3_IIFf);
    943             }
    944             action_type |= 0x2; /* IIF */
    945             soc_mem_field32_set(unit, mem, entry, XLATE__MPLS_ACTIONf, 
    946                                 action_type); 
    947             soc_mem_field32_set(unit, mem, entry,XLATE__L3_IIFf, info->intf_id);
    948         }
    949     }
    950  
    951     if (info->valid_elements & BCM_FLOW_MATCH_VPN_VALID) {
    952         int vfi = 0;
    953         BCM_IF_ERROR_RETURN(
    954              (bcmi_esw_flow_vpn_is_valid(unit, info->vpn)));
    955         _BCM_FLOW_VPN_GET(vfi, _BCM_VPN_TYPE_VFI, info->vpn);
    956         if (_BCM_FLOW_IS_FLEX_VIEW(info)) {
    957             if (!SOC_MEM_FIELD_VALID(unit, mem, VFI_ACTION_SETf)) {
    958                 return BCM_E_PARAM;
    959             }
    960             soc_mem_field32_set(unit, mem, entry, VFI_ACTION_SETf, vfi);
    961         } else {
    962             if (info->flow_handle == SOC_FLOW_DB_FLOW_ID_LEGACY_VXLAN) {
    963                 if (soc_feature(unit, soc_feature_vxlan_decoupled_mode)) {
    964                     if (!SOC_MEM_FIELD_VALID(unit, mem, VXLAN_FLEX__VFI_ACTION_SETf)) {
    965                         return BCM_E_PARAM;
    966                     }
    967                     soc_mem_field32_set(unit, mem, entry, VXLAN_FLEX__VFI_ACTION_SETf, vfi);
    968                 } else {
    969                     if (!SOC_MEM_FIELD_VALID(unit, mem, VXLAN_VN_ID__VFIf)) {
    970                         return BCM_E_PARAM;
    971                     }
    972                     soc_mem_field32_set(unit, mem, entry, VXLAN_VN_ID__VFIf, vfi);
    973                 }
    974             } else if (info->flow_handle == SOC_FLOW_DB_FLOW_ID_LEGACY_L2GRE) {
    975                 if (!SOC_MEM_FIELD_VALID(unit, mem, L2GRE_VPNID__VFIf)) {
    976                     return BCM_E_PARAM;
    977                 }
    978                 soc_mem_field32_set(unit, mem, entry, L2GRE_VPNID__VFIf, vfi);
    979             } else {
    980                 if (!SOC_MEM_FIELD_VALID(unit, mem, XLATE__VFIf)) {
    981                     return BCM_E_PARAM;
    982                 }
    983                 soc_mem_field32_set(unit, mem, entry, XLATE__VFIf, vfi);
    984             }
    985         }
    986     }
    987 
    988     if (info->valid_elements & BCM_FLOW_MATCH_VLAN_VALID) {
    989         if (_BCM_FLOW_IS_FLEX_VIEW(info)) {
    990             if (SOC_MEM_FIELD_VALID(unit, mem, TAG_ACTION_SETf)) {
    991                 uint32 profile = 0;
    992 
    993                 action_set = 0;
    994                 action_set = soc_mem_field32_get(unit, mem, entry,
    995                                     TAG_ACTION_SETf);
    996                 profile = soc_format_field32_get(unit, TAG_ACTION_SETfmt,
    997                                   &action_set, ING_TAG_ACTION_PROFILE_IDXf);
    998                 _bcm_td3_def_vlan_profile_get(unit, &profile);
    999                 soc_format_field32_set(unit, TAG_ACTION_SETfmt,
   1000                         &action_set, ING_TAG_ACTION_PROFILE_IDXf, profile);
   1001                 soc_mem_field32_set(unit, mem, entry, TAG_ACTION_SETf,
   1002                         action_set);
   1003 
   1004                 action_set = 0;
   1005                 soc_format_field32_set(unit, OVLAN_ACTION_SETfmt,
   1006                         &action_set, VLAN_IDf, info->vlan);
   1007                 soc_mem_field32_set(unit, mem, entry, OVLAN_ACTION_SETf,
   1008                         action_set);
   1009             }
   1010         } else if (info->flow_handle == SOC_FLOW_DB_FLOW_ID_LEGACY_VXLAN) {
   1011             if (soc_feature(unit, soc_feature_vxlan_decoupled_mode)) {
   1012                 if (soc_mem_field_valid(unit, mem, VXLAN_FLEX__OVIDf)) {
   1013                     uint32 profile = 0;
   1014                     soc_field_t vlan_act_f = VXLAN_FLEX__ING_TAG_ACTION_PROFILE_IDXf;
   1015 
   1016                     if (soc_mem_field_valid(unit, mem, vlan_act_f)) {
   1017                         profile = soc_mem_field32_get(unit, mem, entry, vlan_act_f);
   1018                         _bcm_td3_def_vlan_profile_get(unit, &profile);
   1019                         soc_mem_field32_set(unit, mem, entry, vlan_act_f, profile);
   1020                     }
   1021                     soc_mem_field32_set(unit, mem, entry, VXLAN_FLEX__OVIDf, info->vlan);
   1022                 }
   1023             }
   1024         }
   1025     }
   1026 
   1027     if (info->valid_elements & BCM_FLOW_MATCH_FLEX_DATA_VALID) {
   1028         uint32 data_ids[_BCM_FLOW_LOGICAL_FIELD_MAX]; 
   1029         uint32 cnt;
   1030         rv = soc_flow_db_mem_view_field_list_get(unit,
   1031                       mem,
   1032                       SOC_FLOW_DB_FIELD_TYPE_LOGICAL_POLICY_DATA,
   1033                       _BCM_FLOW_LOGICAL_FIELD_MAX, data_ids, &cnt);
   1034         BCM_IF_ERROR_RETURN(rv);
   1035         for (i = 0; i < num_of_fields; i++) {
   1036             for (j = 0; j < cnt; j++) {
   1037                 if (field[i].id == data_ids[j]) {
   1038                     soc_mem_field32_set(unit, mem, entry,
   1039                          field[i].id, field[i].value);
   1040                     break;
   1041                 }
   1042             }
   1043         }
   1044     }
   1045 
   1046     if (view_info->mem == L3_TUNNELm) {
   1047         rv = _bcm_flow_match_mem_entry_to_term_entry(unit, mem,
   1048                         &tnl_entry, entry);
   1049         if (BCM_SUCCESS(rv)) { 
   1050             rv = soc_tunnel_term_insert(unit, &tnl_entry, (uint32 *)&index);
   1051         }
   1052     } else { /* hash */
   1053         if (new_entry_add) {
   1054             rv = soc_mem_insert(unit, mem, MEM_BLOCK_ALL, entry);
   1055         } else {
   1056             rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, index, entry);
   1057         }
   1058     }
   1059     BCM_IF_ERROR_RETURN(rv);
   1060     return rv;
   1061 }
   1062 
   1063 /*
   1064  * Function:
   1065  *      _bcm_flow_match_entry_get
   1066  * Purpose:
   1067  *      Get the flow Match Entry based on the given key
   1068  * Parameters:
   1069  *      unit - (IN) Device Number
   1070  *      info - (OUT) flow_match configuration info 
   1071  *      field - (OUT) array of logical fields 
   1072  *      num_of_fields -(IN) the size of the above array 
   1073  *      mem  - (IN) memory id
   1074  *      entry - (IN) point to the match entry
   1075  * Returns:
   1076  *      BCM_E_XXX
   1077  */
   1078 
   1079 STATIC int
   1080 _bcm_flow_match_entry_data_get(int unit, 
   1081         bcm_flow_match_config_t *info, 
   1082         bcm_flow_logical_field_t *field,
   1083         int num_of_fields,
   1084         soc_mem_t mem,
   1085         uint32 *entry)
   1086 {
   1087     int rv = BCM_E_NONE;
   1088     int i;
   1089     int j;
   1090     int vp = 0;
   1091     int vfi = 0;
   1092     _bcm_flow_bookkeeping_t *flow_info;
   1093     uint32 action_set;
   1094 
   1095     flow_info = FLOW_INFO(unit);
   1096 
   1097     /* data fields: flex view uses PDD */
   1098     if (_BCM_FLOW_IS_FLEX_VIEW(info)) {
   1099         if (SOC_MEM_FIELD_VALID(unit,mem,SVP_ACTION_SETf)) {
   1100             action_set = soc_mem_field32_get(unit, mem, entry,
   1101                                  SVP_ACTION_SETf);
   1102             vp = soc_format_field32_get(unit, SVP_ACTION_SETfmt,
   1103                                       &action_set, SVPf);
   1104         }
   1105         if (SOC_MEM_FIELD_VALID(unit, mem, OVLAN_ACTION_SETf)) {
   1106             action_set = soc_mem_field32_get(unit, mem, entry,
   1107                                  OVLAN_ACTION_SETf);
   1108             info->vlan = soc_format_field32_get(unit, OVLAN_ACTION_SETfmt,
   1109                                       &action_set, VLAN_IDf);
   1110         }
   1111     } else {
   1112         if (info->flow_handle == SOC_FLOW_DB_FLOW_ID_LEGACY_VXLAN) {
   1113             if (soc_mem_field_valid(unit, mem, VXLAN_SIP__SVPf)) {
   1114                 vp = soc_mem_field32_get(unit, mem, entry, VXLAN_SIP__SVPf);
   1115             }
   1116             if (soc_feature(unit, soc_feature_vxlan_decoupled_mode)) {
   1117                 if (soc_mem_field_valid(unit, mem, VXLAN_FLEX_IPV4_SIP__SVPf)) {
   1118                     vp = soc_mem_field32_get(unit, mem, entry, VXLAN_FLEX_IPV4_SIP__SVPf);
   1119                 }
   1120                 if (soc_mem_field_valid(unit, mem, VXLAN_FLEX__OVIDf)) {
   1121                    info->vlan = soc_mem_field32_get(unit, mem, entry, VXLAN_FLEX__OVIDf);
   1122                 }
   1123             }
   1124         } else if (info->flow_handle == SOC_FLOW_DB_FLOW_ID_LEGACY_L2GRE) {
   1125             vp = soc_mem_field32_get(unit, mem, entry, L2GRE_SIP__SVPf);
   1126         } else {
   1127             if (SOC_MEM_FIELD_VALID(unit,mem,XLATE__SOURCE_VPf)) {
   1128                 vp = soc_mem_field32_get(unit, mem, entry, XLATE__SOURCE_VPf);
   1129             } 
   1130         }
   1131     }
   1132     if (flow_info->vp_ref_cnt[vp]) {
   1133         _SHR_GPORT_FLOW_PORT_ID_SET(info->flow_port,vp);
   1134         info->valid_elements |= BCM_FLOW_MATCH_FLOW_PORT_VALID;
   1135     }
   1136     if (_BCM_FLOW_IS_FLEX_VIEW(info)) {
   1137         if (SOC_MEM_FIELD_VALID(unit,mem,L3_IIF_ACTION_SETf)) {
   1138             info->intf_id = soc_mem_field32_get(unit, mem, entry, 
   1139                                   L3_IIF_ACTION_SETf); 
   1140         }
   1141     } else {
   1142         if (SOC_MEM_FIELD_VALID(unit,mem,XLATE__L3_IIFf)) {
   1143             info->intf_id = soc_mem_field32_get(unit, mem, entry,
   1144                                                 XLATE__L3_IIFf);
   1145         }
   1146     }
   1147     if (flow_info->iif_ref_cnt[info->intf_id]) {
   1148         info->valid_elements |= BCM_FLOW_MATCH_IIF_VALID;
   1149     }
   1150   
   1151     if (_BCM_FLOW_IS_FLEX_VIEW(info)) {
   1152         if (SOC_MEM_FIELD_VALID(unit,mem,VFI_ACTION_SETf)) {
   1153             vfi = soc_mem_field32_get(unit, mem, entry, VFI_ACTION_SETf);
   1154         }
   1155     } else {
   1156         if (info->flow_handle == SOC_FLOW_DB_FLOW_ID_LEGACY_VXLAN) {
   1157             if (soc_feature(unit, soc_feature_vxlan_decoupled_mode)) {
   1158                 if (soc_mem_field_valid(unit, mem, VXLAN_FLEX__VFI_ACTION_SETf)) {
   1159                     vfi = soc_mem_field32_get(unit, mem, entry, VXLAN_FLEX__VFI_ACTION_SETf);
   1160                 }
   1161             }
   1162             if (soc_mem_field_valid(unit, mem, VXLAN_VN_ID__VFIf)) {
   1163                 vfi = soc_mem_field32_get(unit, mem, entry, VXLAN_VN_ID__VFIf);
   1164             }
   1165         } else if (info->flow_handle == SOC_FLOW_DB_FLOW_ID_LEGACY_L2GRE) {
   1166             vfi = soc_mem_field32_get(unit, mem, entry, L2GRE_VPNID__VFIf);
   1167         } else {
   1168             if (SOC_MEM_FIELD_VALID(unit,mem,XLATE__VFIf)) {
   1169                 vfi = soc_mem_field32_get(unit, mem, entry, XLATE__VFIf);
   1170             }
   1171         }
   1172     }
   1173     if (_bcm_vfi_used_get(unit, vfi, _bcmVfiTypeFlow)) { 
   1174         info->valid_elements |= BCM_FLOW_MATCH_VPN_VALID; 
   1175     }
   1176     _BCM_FLOW_VPN_SET(info->vpn,_BCM_VPN_TYPE_VFI,vfi);
   1177 
   1178     if (_BCM_FLOW_IS_FLEX_VIEW(info) && (field != NULL)) {
   1179         uint32 data_ids[_BCM_FLOW_LOGICAL_FIELD_MAX]; 
   1180         uint32 cnt;
   1181         rv = soc_flow_db_mem_view_field_list_get(unit,
   1182                       mem,
   1183                       SOC_FLOW_DB_FIELD_TYPE_LOGICAL_POLICY_DATA,
   1184                       _BCM_FLOW_LOGICAL_FIELD_MAX, data_ids, &cnt);
   1185         BCM_IF_ERROR_RETURN(rv);
   1186         for (i = 0; i < num_of_fields; i++) {
   1187             for (j = 0; j < cnt; j++) {
   1188                 if (field[i].id == data_ids[j]) {
   1189                     field[i].value = soc_mem_field32_get(unit, mem, entry,
   1190                                      field[i].id);
   1191                     break;
   1192                 }
   1193             }
   1194         }
   1195     }
   1196 
   1197     return BCM_E_NONE;
   1198 }
   1199 /*
   1200  * Function:
   1201  *      _bcm_flow_match_entry_get
   1202  * Purpose:
   1203  *      Get the flow Match Entry based on the given key
   1204  * Parameters:
   1205  *      unit - (IN) Device Number
   1206  *      info - (IN/OUT) flow_match configuration info 
   1207  *      field - (IN/OUT) array of logical fields 
   1208  *      num_of_fields -(IN) the size of the above array 
   1209  *      mem  - (IN) memory id
   1210  *      entry - (IN) point to the match entry
   1211  * Returns:
   1212  *      BCM_E_XXX
   1213  * Parameters:
   1214  *  IN :  Unit
   1215  *  IN :  entry
   1216  * Returns:
   1217  *      BCM_E_XXX
   1218  */
   1219 
   1220 STATIC int
   1221 _bcm_flow_match_entry_get(int unit,
   1222         bcm_flow_match_config_t *info,
   1223         bcm_flow_logical_field_t *field,
   1224         int num_of_fields,
   1225         soc_flow_db_mem_view_info_t *view_info,
   1226         uint32 *entry)
   1227 {
   1228     int index = -1;
   1229     uint32 return_entry[_QUAD_ENTRY_MAX];
   1230     int rv = BCM_E_NONE;
   1231     soc_mem_t mem;
   1232     soc_tunnel_term_t tnl_entry;
   1233     soc_tunnel_term_t tnl_return_entry;
   1234 
   1235     if (view_info->mem == L3_TUNNELm) {
   1236         rv = _bcm_flow_match_mem_entry_to_term_entry(unit, view_info->mem,
   1237                         &tnl_entry, entry);
   1238         BCM_IF_ERROR_RETURN(rv);
   1239         rv = soc_tunnel_term_match(unit,&tnl_entry, &tnl_return_entry, &index);
   1240         rv = _bcm_flow_match_term_entry_to_mem_entry(unit, view_info->mem,
   1241                         &tnl_return_entry, return_entry);
   1242         BCM_IF_ERROR_RETURN(rv);
   1243     } else {
   1244         SOC_IF_ERROR_RETURN(soc_mem_search(unit, view_info->mem, 
   1245                       MEM_BLOCK_ANY, &index, entry, return_entry, 0));
   1246     }
   1247     mem = _BCM_FLOW_IS_FLEX_VIEW(info)? view_info->mem_view_id: 
   1248            view_info->mem;
   1249     rv = _bcm_flow_match_entry_data_get(unit,info,field,num_of_fields,
   1250                     mem,return_entry);
   1251     BCM_IF_ERROR_RETURN(rv);
   1252     return rv;
   1253 }
   1254 
   1255 /*
   1256  * Function:
   1257  *      _bcm_flow_match_entry_key_set
   1258  * Purpose:
   1259  *      Set flow Match Entry Key
   1260  * Parameters:
   1261  *      unit - (IN) Device Number
   1262  *      info - (IN) flow_match configuration info 
   1263  *      field - (IN) array of logical fields 
   1264  *      num_of_fields -(IN) the size of the above array 
   1265  *      mem - (IN) memory id
   1266  *      entry - (IN) point to the match entry
   1267  * Returns:
   1268  *      BCM_E_XXX
   1269  */
   1270 
   1271 STATIC 
   1272 int _bcm_flow_match_entry_key_set(int unit,
   1273     bcm_flow_match_config_t *info,
   1274     bcm_flow_logical_field_t *field,
   1275     int num_of_fields,
   1276     soc_mem_t mem_id,
   1277     uint32 *entry)
   1278 {
   1279     int i;
   1280     int j;
   1281     bcm_module_t mod_out = -1;
   1282     bcm_port_t port_out = -1;
   1283     bcm_trunk_t trunk_id = -1;
   1284     bcm_port_t gport_id = -1;
   1285     soc_field_t ovid_f;
   1286     soc_field_t ivid_f;
   1287     soc_field_t sip_f;
   1288     soc_field_t vnid_f;
   1289     soc_field_t t_f;
   1290     soc_field_t tgid_f;
   1291     soc_field_t module_id_f;
   1292     soc_field_t port_num_f;
   1293     soc_field_t lbl_f;
   1294     int rv;
   1295 
   1296     /* validate parameters */
   1297 
   1298     /* XXX check if ELAN/ELINE handle differently */
   1299 
   1300     if (_BCM_FLOW_IS_FLEX_VIEW(info)) {
   1301         t_f         = Tf;
   1302         tgid_f      = TGIDf;
   1303         module_id_f = MODULE_IDf;
   1304         port_num_f  = PORT_NUMf;
   1305         ovid_f      = OVIDf;
   1306         ivid_f      = IVIDf;
   1307     } else {
   1308         t_f         = XLATE__Tf;
   1309         tgid_f      = XLATE__TGIDf;
   1310         module_id_f = XLATE__MODULE_IDf;
   1311         port_num_f  = XLATE__PORT_NUMf;
   1312         ovid_f      = XLATE__OVIDf;
   1313         ivid_f      = XLATE__IVIDf;
   1314     }
   1315     if (info->valid_elements & BCM_FLOW_MATCH_PORT_VALID) {
   1316         rv = _bcm_esw_gport_resolve(unit, info->port, &mod_out,
   1317                         &port_out, &trunk_id, &gport_id);
   1318         BCM_IF_ERROR_RETURN(rv);
   1319     }
   1320     if (info->criteria == BCM_FLOW_MATCH_CRITERIA_PORT_VLAN ||
   1321         info->criteria == BCM_FLOW_MATCH_CRITERIA_PORT_INNER_VLAN ||
   1322         info->criteria == BCM_FLOW_MATCH_CRITERIA_PORT_VLAN_STACKED ||
   1323         info->criteria == BCM_FLOW_MATCH_CRITERIA_VLAN_PRI) {
   1324         if (info->valid_elements & BCM_FLOW_MATCH_PORT_VALID) {
   1325             if (BCM_GPORT_IS_TRUNK(info->port)) {
   1326                 if (!(SOC_MEM_FIELD_VALID(unit, mem_id, t_f) &&
   1327                     SOC_MEM_FIELD_VALID(unit, mem_id, tgid_f))) {
   1328                     return BCM_E_PARAM;
   1329                 }
   1330                 soc_mem_field32_set(unit,mem_id, entry, t_f, 1);
   1331                 soc_mem_field32_set(unit,mem_id, entry, tgid_f, trunk_id);
   1332             } else {
   1333                 if (mod_out != -1) {
   1334                     if (!SOC_MEM_FIELD_VALID(unit, mem_id, module_id_f)) {
   1335                         return BCM_E_PARAM;
   1336                     }
   1337                 
   1338                     soc_mem_field32_set(unit, mem_id, entry, module_id_f, 
   1339                                         mod_out);
   1340                 }
   1341                 if (!SOC_MEM_FIELD_VALID(unit, mem_id, port_num_f)) {
   1342                     return BCM_E_PARAM;
   1343                 }
   1344                 soc_mem_field32_set(unit,mem_id, entry, port_num_f, port_out);
   1345             }
   1346         }
   1347         if (!SOC_MEM_FIELD_VALID(unit,mem_id,SOURCE_TYPEf)) {
   1348             return BCM_E_PARAM;
   1349         }
   1350         soc_mem_field32_set(unit, mem_id, entry, SOURCE_TYPEf, 1);
   1351     }
   1352 
   1353     if (info->criteria == BCM_FLOW_MATCH_CRITERIA_PORT_VLAN ) {
   1354         if (!BCM_VLAN_VALID(info->vlan)) {
   1355             LOG_ERROR(BSL_LS_BCM_FLOW,
   1356                   (BSL_META_U(unit, "Invalid vlan\n")));
   1357              return BCM_E_PARAM;
   1358         }
   1359         if (!SOC_MEM_FIELD_VALID(unit, mem_id, ovid_f)) {
   1360             return BCM_E_PARAM;
   1361         }
   1362         soc_mem_field32_set(unit,mem_id, entry, ovid_f, info->vlan);
   1363 
   1364     } else if (info->criteria == BCM_FLOW_MATCH_CRITERIA_PORT_INNER_VLAN) {
   1365         if (!BCM_VLAN_VALID(info->inner_vlan)) {
   1366             LOG_ERROR(BSL_LS_BCM_FLOW,
   1367                   (BSL_META_U(unit, "Invalid inner vlan\n")));
   1368             return BCM_E_PARAM;
   1369         }
   1370         if (!SOC_MEM_FIELD_VALID(unit, mem_id, ivid_f)) {
   1371             return BCM_E_PARAM;
   1372         }
   1373         soc_mem_field32_set(unit,mem_id, entry, ivid_f, info->inner_vlan);
   1374 
   1375     } else if (info->criteria == BCM_FLOW_MATCH_CRITERIA_PORT_VLAN_STACKED) {
   1376         if (!BCM_VLAN_VALID(info->vlan) ||
   1377                 !BCM_VLAN_VALID(info->inner_vlan)) {
   1378             LOG_ERROR(BSL_LS_BCM_FLOW,
   1379              (BSL_META_U(unit, "Invalid either outer vlan or inner vlan\n")));
   1380             return BCM_E_PARAM;
   1381         }
   1382 
   1383         if (!(SOC_MEM_FIELD_VALID(unit, mem_id, ovid_f) &&
   1384             SOC_MEM_FIELD_VALID(unit, mem_id, ivid_f))) {
   1385             return BCM_E_PARAM;
   1386         }
   1387         soc_mem_field32_set(unit,mem_id, entry, ovid_f, info->vlan);
   1388         soc_mem_field32_set(unit,mem_id, entry, ivid_f, info->inner_vlan);
   1389 
   1390     } else if (info->criteria == BCM_FLOW_MATCH_CRITERIA_VLAN_PRI) {
   1391 
   1392         /* match_vlan : Bits 12-15 contains VLAN_PRI + CFI, vlan=BCM_E_NONE */
   1393         if (!SOC_MEM_FIELD_VALID(unit, mem_id, OTAGf)) {
   1394             return BCM_E_PARAM;
   1395         }
   1396         soc_mem_field32_set(unit,mem_id, entry, OTAGf, info->vlan);
   1397 
   1398     } else if (info->criteria == BCM_FLOW_MATCH_CRITERIA_SIP) {
   1399         if (_BCM_FLOW_IS_FLEX_VIEW(info)) {
   1400             ovid_f = OVIDf;
   1401             if (SOC_MEM_FIELD_VALID(unit,mem_id,IPV4__SIPf)) {
   1402                 sip_f = IPV4__SIPf;
   1403             } else {
   1404                 sip_f = SIPf;
   1405             }
   1406         } else {
   1407             if (info->flow_handle == SOC_FLOW_DB_FLOW_ID_LEGACY_VXLAN) {
   1408                 ovid_f = VXLAN_SIP__OVIDf;
   1409                 sip_f  = VXLAN_SIP__SIPf;
   1410                 if (soc_feature(unit, soc_feature_vxlan_decoupled_mode)) {
   1411                     sip_f = VXLAN_FLEX_IPV4_SIP__SIPf;
   1412                 }
   1413             } else if (info->flow_handle == SOC_FLOW_DB_FLOW_ID_LEGACY_L2GRE) {
   1414                 sip_f  = L2GRE_SIP__SIPf;
   1415             } else {
   1416                 LOG_ERROR(BSL_LS_BCM_FLOW,
   1417                       (BSL_META_U(unit, "Invalid legacy flow handle\n")));
   1418                 return BCM_E_PARAM;
   1419             }
   1420         }
   1421         if (soc_feature(unit, soc_feature_vrf_aware_vxlan_termination) &&
   1422             (info->valid_elements & BCM_FLOW_MATCH_VLAN_VALID)) {
   1423             VLAN_CHK_ID(unit,info->vlan);
   1424             if (!SOC_MEM_FIELD_VALID(unit, mem_id, ovid_f)) {
   1425                 return BCM_E_PARAM;
   1426             }
   1427             soc_mem_field32_set(unit,mem_id, entry, ovid_f, info->vlan);
   1428         }
   1429         if (!SOC_MEM_FIELD_VALID(unit, mem_id, sip_f)) {
   1430             return BCM_E_PARAM;
   1431         }
   1432         soc_mem_field32_set(unit,mem_id, entry, sip_f, info->sip);
   1433 
   1434     }  else if (info->criteria == BCM_FLOW_MATCH_CRITERIA_VN_ID ||
   1435                 info->criteria == BCM_FLOW_MATCH_CRITERIA_SIP_VNID) {
   1436 
   1437         if (_BCM_FLOW_IS_FLEX_VIEW(info)) {
   1438             ovid_f = OVIDf;
   1439             vnid_f = VNIDf; 
   1440             if (SOC_MEM_FIELD_VALID(unit,mem_id,IPV4__SIPf)) {
   1441                 sip_f = IPV4__SIPf;
   1442             } else {
   1443                 sip_f = SIPf;
   1444             }
   1445         } else {
   1446             if (info->flow_handle == SOC_FLOW_DB_FLOW_ID_LEGACY_VXLAN) {
   1447                 if (soc_feature(unit, soc_feature_vxlan_decoupled_mode)) {
   1448                     ovid_f = VXLAN_FLEX__OVIDf;
   1449                     sip_f  = VXLAN_FLEX__SIPf;
   1450                     vnid_f = VXLAN_FLEX__VNIDf;
   1451                 } else {
   1452                     ovid_f = VXLAN_VN_ID__OVIDf;
   1453                     sip_f  = VXLAN_VN_ID__SIPf;
   1454                     vnid_f = VXLAN_VN_ID__VN_IDf;
   1455                 }
   1456             } else if (info->flow_handle == SOC_FLOW_DB_FLOW_ID_LEGACY_L2GRE) {
   1457                 vnid_f = L2GRE_VPNID__VPNIDf;
   1458                 sip_f   = L2GRE_VPNID__SIPf;
   1459             } else {
   1460                 LOG_ERROR(BSL_LS_BCM_FLOW,
   1461                       (BSL_META_U(unit, "Invalid legacy flow handle\n")));
   1462                 return BCM_E_PARAM;
   1463             }
   1464         }
   1465         if (!SOC_MEM_FIELD_VALID(unit, mem_id, vnid_f)) {
   1466             return BCM_E_PARAM;
   1467         }
   1468         soc_mem_field32_set(unit, mem_id, entry, vnid_f, info->vnid);
   1469         if (info->criteria == BCM_FLOW_MATCH_CRITERIA_SIP_VNID) {
   1470             if (!SOC_MEM_FIELD_VALID(unit, mem_id, sip_f)) {
   1471                 return BCM_E_PARAM;
   1472             }
   1473             soc_mem_field32_set(unit,mem_id, entry, sip_f, info->sip);
   1474         }
   1475 
   1476         if (soc_feature(unit,soc_feature_vrf_aware_vxlan_termination) &&
   1477             (info->valid_elements & BCM_FLOW_MATCH_VLAN_VALID)) {
   1478             VLAN_CHK_ID(unit, info->vlan);
   1479             if (!SOC_MEM_FIELD_VALID(unit, mem_id, ovid_f)) {
   1480                 return BCM_E_PARAM;
   1481             }
   1482             soc_mem_field32_set(unit,mem_id, entry, ovid_f, info->vlan);
   1483         }
   1484     } else if (info->criteria == BCM_FLOW_MATCH_CRITERIA_MPLS_LABEL) {
   1485         if (_BCM_FLOW_IS_FLEX_VIEW(info)) {
   1486             if (SOC_MEM_FIELD_VALID(unit, mem_id, MPLS_LABEL_1f)) {
   1487                 lbl_f = MPLS_LABEL_1f;
   1488             } else if (SOC_MEM_FIELD_VALID(unit, mem_id, MPLS_LABEL_2f)) {
   1489                 lbl_f = MPLS_LABEL_2f;
   1490             } else {
   1491                 LOG_ERROR(BSL_LS_BCM_FLOW,
   1492                  (BSL_META_U(unit, "mpls_label field not found\n")));
   1493                 return BCM_E_PARAM;
   1494             }
   1495             soc_mem_field32_set(unit,mem_id, entry, lbl_f, info->mpls_label);
   1496         } else {
   1497             LOG_ERROR(BSL_LS_BCM_FLOW,
   1498              (BSL_META_U(unit, "mpls_label only supported for flex view\n")));
   1499             return BCM_E_PARAM;
   1500         }
   1501     } else if (info->criteria == BCM_FLOW_MATCH_CRITERIA_FLEX) {
   1502         uint32 key_ids[_BCM_FLOW_LOGICAL_FIELD_MAX]; 
   1503         uint32 cnt;
   1504 
   1505         ovid_f = OVIDf;
   1506         vnid_f = VNIDf; 
   1507 
   1508         rv = soc_flow_db_mem_view_field_list_get(unit,
   1509                       mem_id,
   1510                       SOC_FLOW_DB_FIELD_TYPE_LOGICAL_KEY,
   1511                       _BCM_FLOW_LOGICAL_FIELD_MAX, key_ids, &cnt);
   1512         if (rv != SOC_E_NONE && rv != SOC_E_NOT_FOUND) {
   1513             return rv;
   1514         }
   1515         if (rv == SOC_E_NONE) {
   1516             for (i = 0; i < num_of_fields; i++) {
   1517                 for (j = 0; j < cnt; j++) {
   1518                     if (field[i].id == key_ids[j]) {
   1519                         soc_mem_field32_set(unit, mem_id, entry,
   1520                              field[i].id, field[i].value);
   1521                         break;
   1522                     }
   1523                 }
   1524             }
   1525         }
   1526         rv = SOC_E_NONE;
   1527         if (info->valid_elements & BCM_FLOW_MATCH_VNID_VALID) {
   1528             if (!SOC_MEM_FIELD_VALID(unit,mem_id,vnid_f)) {
   1529                 return SOC_E_PARAM;
   1530             }
   1531             soc_mem_field32_set(unit,mem_id, entry, vnid_f, info->vnid);
   1532         }
   1533         if (info->valid_elements & BCM_FLOW_MATCH_VLAN_VALID) {
   1534             if (!SOC_MEM_FIELD_VALID(unit,mem_id,ovid_f)) {
   1535                 return SOC_E_PARAM;
   1536             }
   1537             soc_mem_field32_set(unit,mem_id, entry, ovid_f, info->vlan);
   1538         }
   1539         if (info->valid_elements & BCM_FLOW_MATCH_INNER_VLAN_VALID) {
   1540             if (!SOC_MEM_FIELD_VALID(unit,mem_id,ivid_f)) {
   1541                 return SOC_E_PARAM;
   1542             }
   1543             soc_mem_field32_set(unit,mem_id, entry, ivid_f, info->inner_vlan);
   1544         }
   1545         if (info->valid_elements & BCM_FLOW_MATCH_PORT_VALID) {
   1546             if (BCM_GPORT_IS_TRUNK(info->port)) {
   1547                 if (!(SOC_MEM_FIELD_VALID(unit,mem_id,t_f) &&
   1548                       SOC_MEM_FIELD_VALID(unit,mem_id,tgid_f))) {
   1549                     if (SOC_MEM_FIELD_VALID(unit,mem_id,SGLP_16f &&
   1550                         SOC_MEM_FIELD_VALID(unit,mem_id,SGLP_15_0f))) {
   1551                         t_f = SGLP_16f;
   1552                         tgid_f = SGLP_15_0f;
   1553                     } else {
   1554                         return SOC_E_PARAM;
   1555                     }
   1556                 }
   1557             
   1558                 soc_mem_field32_set(unit,mem_id, entry, t_f, 1);
   1559                 soc_mem_field32_set(unit,mem_id, entry, tgid_f, trunk_id);
   1560             } else {
   1561                 if ((SOC_MEM_FIELD_VALID(unit,mem_id,module_id_f) &&
   1562                      SOC_MEM_FIELD_VALID(unit,mem_id,port_num_f))) {
   1563                     soc_mem_field32_set(unit,mem_id, entry, module_id_f, 
   1564                                          mod_out);
   1565                     soc_mem_field32_set(unit,mem_id, entry, port_num_f, 
   1566                                          port_out);
   1567                 } else if (SOC_MEM_FIELD_VALID(unit,mem_id,SGPPf)) {
   1568                     soc_mem_field32_set(unit,mem_id, entry, SGPPf, 
   1569                                          port_out | (mod_out << 8));
   1570                 } else if (SOC_MEM_FIELD_VALID(unit,mem_id,SGLP_15_0f)) {
   1571                     soc_mem_field32_set(unit,mem_id, entry, SGLP_15_0f,
   1572                                          port_out | (mod_out << 8));
   1573                 } else {
   1574                     return SOC_E_PARAM;
   1575                 }
   1576             }
   1577         }
   1578         if (info->valid_elements & BCM_FLOW_MATCH_SIP_VALID) {
   1579             if (SOC_MEM_FIELD_VALID(unit,mem_id,SIPf)) {
   1580                 sip_f = SIPf;
   1581             } else if (SOC_MEM_FIELD_VALID(unit,mem_id,IPV4__SIPf)) {
   1582                 sip_f = IPV4__SIPf;
   1583             } else {
   1584                 return SOC_E_PARAM;
   1585             }
   1586             soc_mem_field32_set(unit,mem_id, entry, sip_f, info->sip);
   1587         }
   1588         if (info->valid_elements & BCM_FLOW_MATCH_SIP_V6_VALID) {
   1589             if (!SOC_MEM_FIELD_VALID(unit,mem_id,IPV6__SIPf)) {
   1590                 return SOC_E_PARAM;
   1591             }
   1592             soc_mem_ip6_addr_set(unit, mem_id, entry,IPV6__SIPf, 
   1593                                       info->sip6, 0);
   1594         }
   1595         if (info->valid_elements & BCM_FLOW_MATCH_DIP_VALID) {
   1596             if (!SOC_MEM_FIELD_VALID(unit,mem_id,IPV4__DIPf)) {
   1597                 return SOC_E_PARAM;
   1598             }
   1599             soc_mem_field32_set(unit,mem_id, entry, IPV4__DIPf, info->dip);
   1600         }
   1601         if (info->valid_elements & BCM_FLOW_MATCH_DIP_V6_VALID) {
   1602             if (!SOC_MEM_FIELD_VALID(unit,mem_id,IPV6__DIPf)) {
   1603                 return SOC_E_PARAM;
   1604             }
   1605             soc_mem_ip6_addr_set(unit, mem_id, entry,IPV6__DIPf, info->dip6, 0);
   1606         }
   1607         if (info->valid_elements & BCM_FLOW_MATCH_PROTOCOL_VALID) {
   1608             if (!SOC_MEM_FIELD_VALID(unit,mem_id,IPV4__PROTOCOLf)) {
   1609                 return SOC_E_PARAM;
   1610             }
   1611             soc_mem_field32_set(unit,mem_id, entry, IPV4__PROTOCOLf, 
   1612                     info->protocol);
   1613         }
   1614         if (info->valid_elements & BCM_FLOW_MATCH_UDP_SRC_PORT_VALID) {
   1615             if (!SOC_MEM_FIELD_VALID(unit,mem_id,L4_SRC_PORTf)) {
   1616                 return SOC_E_PARAM;
   1617             }
   1618             soc_mem_field32_set(unit,mem_id, entry, L4_SRC_PORTf, 
   1619                     info->udp_src_port);
   1620         }
   1621         if (info->valid_elements & BCM_FLOW_MATCH_UDP_DST_PORT_VALID) {
   1622             if (!SOC_MEM_FIELD_VALID(unit,mem_id,L4_DST_PORTf)) {
   1623                 return SOC_E_PARAM;
   1624             }
   1625             soc_mem_field32_set(unit,mem_id, entry, L4_DST_PORTf, 
   1626                     info->udp_dst_port);
   1627         }
   1628     }
   1629     return BCM_E_NONE;
   1630 }
   1631 
   1632 /*
   1633  * Function:
   1634  *      _bcm_flow_match_port_ctrl
   1635  * Purpose:
   1636  *      Perform SET/GET/DELETE actions for port match criteria 
   1637  * Parameters:
   1638  *      unit - (IN) Device Number
   1639  *      info - (IN) flow_match configuration info 
   1640  *      action - (IN) action id 
   1641  * Returns:
   1642  *      BCM_E_XXX
   1643  */
   1644 
   1645 int _bcm_flow_match_port_ctrl(
   1646     int unit,
   1647     bcm_flow_match_config_t *info,
   1648     int action,
   1649     int *replaced_vp,
   1650     int *replaced_iif)
   1651 {
   1652     bcm_module_t mod_out = -1;
   1653     bcm_port_t port_out = -1;
   1654     bcm_trunk_t trunk_id = -1;
   1655     int    gport_id=-1;
   1656     int    src_trk_idx=0;  /*Source Trunk table index.*/
   1657     int vp = 0;
   1658     int rv = BCM_E_NONE;
   1659     uint32 port_op = 0;
   1660     source_trunk_map_table_entry_t stm_entry;
   1661     soc_mem_t mem;
   1662     int old_vp = 0;
   1663     int old_iif = 0;
   1664 
   1665     if (replaced_vp != NULL) {
   1666         *replaced_vp = 0;
   1667     }
   1668     if (replaced_iif != NULL) {
   1669         *replaced_iif = 0;
   1670     }
   1671    
   1672     if (action == _BCM_FLOW_MATCH_PORT_CTRL_SET) {
   1673         port_op = 1;
   1674         vp = _SHR_GPORT_FLOW_PORT_ID_GET(info->flow_port);
   1675     }
   1676 
   1677     BCM_IF_ERROR_RETURN(_bcm_esw_gport_resolve(unit, info->port,
   1678                            &mod_out, &port_out, &trunk_id, &gport_id));
   1679     if (BCM_GPORT_IS_TRUNK(info->port)) {
   1680         if (action == _BCM_FLOW_MATCH_PORT_CTRL_SET) {
   1681             BCM_IF_ERROR_RETURN(_bcm_flow_match_trunk_add(unit, trunk_id, 
   1682                                      info,replaced_vp,replaced_iif));
   1683         } else if (action == _BCM_FLOW_MATCH_PORT_CTRL_DELETE) {
   1684             BCM_IF_ERROR_RETURN(_bcm_flow_match_trunk_delete(unit, trunk_id, 
   1685                                      info,replaced_vp,replaced_iif));
   1686         } else {
   1687             BCM_IF_ERROR_RETURN(_bcm_flow_match_trunk_get(unit, trunk_id, 
   1688                                      info));
   1689         }
   1690     } else {
   1691         int is_local;
   1692 
   1693         BCM_IF_ERROR_RETURN
   1694             ( _bcm_esw_modid_is_local(unit, mod_out, &is_local));
   1695 
   1696         /* Get index to source trunk map table */
   1697         BCM_IF_ERROR_RETURN(
   1698                _bcm_esw_src_mod_port_table_index_get(unit, mod_out,
   1699                  port_out, &src_trk_idx));
   1700 
   1701         mem = SOURCE_TRUNK_MAP_TABLEm;
   1702         if (action != _BCM_FLOW_MATCH_PORT_CTRL_GET) {
   1703             soc_mem_lock(unit,mem);
   1704         }
   1705         rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, src_trk_idx, &stm_entry);
   1706         old_vp = soc_mem_field32_get(unit, mem, &stm_entry, SOURCE_VPf);
   1707         old_iif = soc_mem_field32_get(unit, mem, &stm_entry, L3_IIFf);
   1708         if (rv == SOC_E_NONE) {
   1709             if (action == _BCM_FLOW_MATCH_PORT_CTRL_SET) {
   1710                 /* Enable SVP Mode */
   1711                 if  (info->valid_elements & BCM_FLOW_MATCH_FLOW_PORT_VALID) { 
   1712                     if (replaced_vp && old_vp && (old_vp != vp)) {
   1713                         /* replace action */
   1714                         *replaced_vp = old_vp;
   1715                     }
   1716                     soc_mem_field32_set(unit, mem, &stm_entry, SOURCE_VPf, 
   1717                                              vp);
   1718                 }
   1719                 if (info->valid_elements & BCM_FLOW_MATCH_IIF_VALID) { 
   1720                     if (replaced_iif && old_iif && (old_iif != info->intf_id)) {
   1721                         /* replace action */
   1722                         *replaced_iif = old_iif;
   1723                     }
   1724                     soc_mem_field32_set(unit, mem, &stm_entry, L3_IIFf, 
   1725                                              info->intf_id);
   1726                 } 
   1727             } else if (action == _BCM_FLOW_MATCH_PORT_CTRL_DELETE) {
   1728                 if (replaced_vp) {
   1729                     *replaced_vp = old_vp;
   1730                 }
   1731                 if (replaced_iif) {
   1732                     *replaced_iif = old_iif;
   1733                 }
   1734                 soc_mem_field32_set(unit, mem, &stm_entry, SOURCE_VPf, 0);
   1735                 soc_mem_field32_set(unit, mem, &stm_entry, L3_IIFf, 0);
   1736             } else { /* _BCM_FLOW_MATCH_PORT_CTRL_GET */
   1737                 _SHR_GPORT_FLOW_PORT_ID_SET(info->flow_port,old_vp);
   1738                 info->intf_id = old_iif;
   1739             }
   1740         }
   1741         if (action != _BCM_FLOW_MATCH_PORT_CTRL_GET) {
   1742             if (rv == SOC_E_NONE) {
   1743                 rv = soc_mem_write(unit, mem, MEM_BLOCK_ANY, src_trk_idx, 
   1744                                &stm_entry);
   1745             }
   1746             soc_mem_unlock(unit,mem);
   1747         }
   1748         BCM_IF_ERROR_RETURN(rv);
   1749 
   1750         if (is_local) {
   1751             if (action != _BCM_FLOW_MATCH_PORT_CTRL_GET) {
   1752                 rv = _bcm_esw_port_tab_set(
   1753                          unit, info->port, _BCM_CPU_TABS_NONE,
   1754                          PORT_OPERATIONf, port_op); /* L2_SVP */
   1755                 BCM_IF_ERROR_RETURN(rv);
   1756             }
   1757 
   1758             if (action == _BCM_FLOW_MATCH_PORT_CTRL_SET) {
   1759                 /* Set TAG_ACTION_PROFILE_PTR */
   1760                 rv = _bcm_flow_match_untagged_profile_set(
   1761                          unit, info->port);
   1762             } else if (action == _BCM_FLOW_MATCH_PORT_CTRL_DELETE) {
   1763                 rv = _bcm_flow_match_untagged_profile_reset(unit,info->port);
   1764             }
   1765             BCM_IF_ERROR_RETURN(rv);
   1766         }
   1767     }
   1768     return rv;
   1769 }
   1770 
   1771 /*
   1772  * Function:
   1773  *      _bcm_flow_match_key_set
   1774  * Purpose:
   1775  *      Set the key for a flow match entry 
   1776  * Parameters:
   1777  *      unit - (IN) Device Number
   1778  *      info - (IN) flow_match configuration info 
   1779  *      field - (IN) array of logical fields 
   1780  *      num_of_fields -(IN) the size of the above array 
   1781  *      entry - (IN) point to the match entry
   1782  *      mem - (IN) memory id
   1783  * Returns:
   1784  *      BCM_E_XXX
   1785  */
   1786 
   1787 STATIC
   1788 int _bcm_flow_match_key_set(
   1789     int unit,
   1790     bcm_flow_match_config_t *info,
   1791     bcm_flow_logical_field_t *field,
   1792     uint32 num_of_fields,
   1793     uint32 *entry,
   1794     soc_flow_db_mem_view_info_t *view_info)
   1795 {
   1796     int rv;
   1797     soc_mem_t mem_view_id;
   1798     uint32 key_type = 0;
   1799     soc_mem_t mem_id = 0;
   1800     soc_flow_db_mem_view_info_t vinfo;
   1801 
   1802     if (view_info == NULL) {
   1803         return BCM_E_INTERNAL;
   1804     }
   1805 
   1806     if (info->criteria <= BCM_FLOW_MATCH_CRITERIA_INVALID ||
   1807             info->criteria >= BCM_FLOW_MATCH_CRITERIA_COUNT) {
   1808         return BCM_E_PARAM;
   1809     }
   1810 
   1811     /* validate parameters */
   1812 
   1813     if (info->criteria == BCM_FLOW_MATCH_CRITERIA_PORT_VLAN) {
   1814         mem_id = VLAN_XLATE_1_DOUBLEm;  /* fixed view */
   1815         key_type = TR_VLXLT_HASH_KEY_TYPE_OVID;
   1816     } else if (info->criteria == BCM_FLOW_MATCH_CRITERIA_PORT_INNER_VLAN) {
   1817         mem_id = VLAN_XLATE_1_DOUBLEm;
   1818         key_type = TR_VLXLT_HASH_KEY_TYPE_IVID;
   1819     } else if (info->criteria == BCM_FLOW_MATCH_CRITERIA_PORT_VLAN_STACKED) {
   1820         mem_id = VLAN_XLATE_1_DOUBLEm;
   1821         key_type = TR_VLXLT_HASH_KEY_TYPE_IVID_OVID;
   1822     } else if (info->criteria == BCM_FLOW_MATCH_CRITERIA_VLAN_PRI) {
   1823         mem_id = VLAN_XLATE_1_DOUBLEm;
   1824         key_type = TR_VLXLT_HASH_KEY_TYPE_PRI_CFI;
   1825     } else if (info->criteria == BCM_FLOW_MATCH_CRITERIA_VN_ID) {
   1826         mem_id = MPLS_ENTRYm;  /* fixed view */
   1827         if (info->flow_handle == SOC_FLOW_DB_FLOW_ID_LEGACY_VXLAN) {
   1828             if (soc_feature(unit, soc_feature_vxlan_decoupled_mode)) {
   1829                 mem_id = VLAN_XLATE_1_DOUBLEm;
   1830                 key_type = _BCM_FLOW_MATCH_KEY_TYPE_VXLAN_FLEX_VNID;
   1831             } else {
   1832                 key_type = _BCM_FLOW_MATCH_KEY_TYPE_VXLAN_VNID;
   1833             }
   1834         } else {
   1835             key_type = _BCM_FLOW_MATCH_KEY_TYPE_L2GRE_VPNID;
   1836         }
   1837     } else if (info->criteria == BCM_FLOW_MATCH_CRITERIA_SIP) {
   1838         mem_id = MPLS_ENTRYm;  /* fixed view */
   1839         if (info->flow_handle == SOC_FLOW_DB_FLOW_ID_LEGACY_VXLAN) {
   1840             if (soc_feature(unit, soc_feature_vxlan_decoupled_mode)) {
   1841                 mem_id = MPLS_ENTRY_SINGLEm;
   1842             }
   1843             key_type = _BCM_FLOW_MATCH_KEY_TYPE_VXLAN_SIP;
   1844         } else {
   1845             key_type = _BCM_FLOW_MATCH_KEY_TYPE_L2GRE_SIP;
   1846         }
   1847     } else if (info->criteria == BCM_FLOW_MATCH_CRITERIA_SIP_VNID) {
   1848         mem_id = MPLS_ENTRYm;  /* fixed view */
   1849         if (info->flow_handle == SOC_FLOW_DB_FLOW_ID_LEGACY_VXLAN) {
   1850             if (soc_feature(unit, soc_feature_vxlan_decoupled_mode)) {
   1851                 mem_id = VLAN_XLATE_1_DOUBLEm;
   1852                 key_type = _BCM_FLOW_MATCH_KEY_TYPE_VXLAN_FLEX_SIP_VNID;
   1853             } else {
   1854                 key_type = _BCM_FLOW_MATCH_KEY_TYPE_VXLAN_SIP_VNID;
   1855             }
   1856         } else {
   1857             key_type = _BCM_FLOW_MATCH_KEY_TYPE_L2GRE_SIP_VPNID;
   1858         }
   1859     }
   1860 
   1861     view_info->mem = mem_id;
   1862     view_info->type = 0;
   1863     view_info->mem_view_id = 0;
   1864 
   1865     /* get the physical memory view */
   1866     if (!_BCM_FLOW_IS_FLEX_VIEW(info)) {
   1867         rv = _bcm_flow_match_fixed_view_entry_init(unit, mem_id,
   1868                        info, key_type, entry);
   1869         BCM_IF_ERROR_RETURN(rv);      
   1870     } else {
   1871         char *option_str;
   1872         uint32 dft_option_id;
   1873         uint32 option_id;
   1874 
   1875         option_id = info->flow_option;
   1876         if (!option_id) {
   1877             _bcm_flow_match_default_option_get(unit,info, &option_str);
   1878             if (option_str != NULL) {
   1879                 rv = soc_flow_db_flow_option_id_get(unit, info->flow_handle,
   1880                                     option_str, &dft_option_id);
   1881                 if (rv == SOC_E_NONE) {
   1882                     option_id = dft_option_id;
   1883                 } 
   1884             }
   1885         }
   1886         rv = soc_flow_db_ffo_to_mem_view_id_get(unit,info->flow_handle,
   1887              option_id,
   1888              SOC_FLOW_DB_FUNC_MATCH_ID, (uint32 *)&mem_view_id);
   1889         BCM_IF_ERROR_RETURN(rv);      
   1890         rv = soc_flow_db_mem_view_info_get(unit, mem_view_id, &vinfo);
   1891         BCM_IF_ERROR_RETURN(rv); 
   1892         view_info->type        = vinfo.type;
   1893         view_info->mem_view_id = mem_view_id;
   1894         view_info->mem         = vinfo.mem;
   1895      
   1896         /* flex view, initialize all control fields such as data_type */ 
   1897         soc_flow_db_mem_view_entry_init(unit,mem_view_id,entry);
   1898         if (vinfo.mem == L3_TUNNELm) { 
   1899             /* only available for flex */
   1900             if ((info->criteria != BCM_FLOW_MATCH_CRITERIA_FLEX) ||
   1901                 (!_BCM_FLOW_IS_FLEX_VIEW(info))) {
   1902                 return BCM_E_PARAM;
   1903             }
   1904         } 
   1905         mem_id = mem_view_id; 
   1906     }
   1907 
   1908     rv = _bcm_flow_match_entry_key_set(unit,info,field,num_of_fields,
   1909                         mem_id, entry); 
   1910     
   1911     /* BCM_FLOW_MATCH_CRITERIA_FLEX
   1912      * flex key -- flex view
   1913      * key comprises of logical fields and fixed fields selected
   1914      * by valid_elements
   1915      *
   1916      * BCM_FLOW_MATCH_CRITERIA_XXX other than FLEX
   1917      * fixed key -- fixed view or flex view. 
   1918      * key comprises of fixed fields in the parameter structure. Should be 
   1919      * determined by MATCH_CRITERIA. valid_elements can be used as parameter
   1920      * checking in this case.
   1921      *
   1922      * The objects or attributes selected for the match should be determined by
   1923      * the valid_elements
   1924      */
   1925 
   1926     return rv;
   1927     
   1928 }
   1929 
   1930 /*
   1931  * Function:
   1932  *      _bcm_flow_match_info_save
   1933  * Purpose:
   1934  *      Save flow Match info
   1935  * Parameters:
   1936  *      unit - (IN) Device Number
   1937  *      vp   - (IN) flow port
   1938  *      info - (IN) flow_match configuration info
   1939  * Returns:
   1940  *      BCM_E_XXX
   1941  */
   1942 
   1943 STATIC void
   1944 _bcm_flow_match_info_save(int unit,
   1945         int vp,
   1946         bcm_flow_match_config_t *info)
   1947 {
   1948     _bcm_flow_bookkeeping_t *flow_info;
   1949     bcm_flow_match_vp_t* match_key;
   1950 
   1951     flow_info = FLOW_INFO(unit);
   1952     match_key = &flow_info->match_key[vp];
   1953     match_key->vlan        = info->vlan;
   1954     match_key->inner_vlan  = info->inner_vlan;
   1955     match_key->port        = info->port;
   1956     match_key->sip         = info->sip;
   1957     sal_memcpy(match_key->sip6, info->sip6,
   1958                    BCM_IP6_ADDRLEN);
   1959     match_key->criteria    = info->criteria;
   1960     match_key->flow_handle = info->flow_handle;
   1961     match_key->flow_option = info->flow_option;
   1962 
   1963     match_key->mpls_label  = info->mpls_label;
   1964     match_key->vnid        = info->vnid;
   1965 }
   1966 
   1967 /*
   1968  * Function:
   1969  *      _bcm_flow_match_info_clear
   1970  * Purpose:
   1971  *      Clear flow Match Entry
   1972  * Parameters:
   1973  *      unit - (IN) Device Number
   1974  *      VP - (IN) flow VP
   1975  * Returns:
   1976  *      BCM_E_XXX
   1977  */
   1978 
   1979 STATIC void
   1980 _bcm_flow_match_info_clear(int unit,
   1981         int vp)
   1982 {
   1983     _bcm_flow_bookkeeping_t *flow_info;
   1984     bcm_flow_match_vp_t* match_key;
   1985 
   1986     flow_info = FLOW_INFO(unit);
   1987     match_key = &flow_info->match_key[vp];
   1988 
   1989     if (match_key != NULL) {
   1990         sal_memset(match_key, 0, sizeof(*match_key));
   1991     }
   1992 }
   1993 
   1994 /*
   1995  * Function:
   1996  *      bcmi_esw_flow_match_add
   1997  * Purpose:
   1998  *      Add a flow match entry
   1999  * Parameters:
   2000  *      unit    - (IN) Device Number
   2001  *      info    - (IN) Flow match config descriptor
   2002  *      num_of_fields - (IN) number of logical fields 
   2003  *      field         - (IN) logical field array 
   2004  * Returns:
   2005  *      BCM_E_XXX
   2006  */
   2007 
   2008 int bcmi_esw_flow_match_add(
   2009     int unit,
   2010     bcm_flow_match_config_t *info,
   2011     uint32 num_of_fields,
   2012     bcm_flow_logical_field_t *field)
   2013 {
   2014     /* L3_TUNNELm could support 4 entry wide view definition */
   2015     uint32 entry[_QUAD_ENTRY_MAX];  
   2016     int rv;
   2017     _bcm_flow_bookkeeping_t *flow_info;
   2018     int replaced_iif;
   2019     int replaced_vp;
   2020     int vp;
   2021     soc_flow_db_mem_view_info_t view_info;
   2022 
   2023     if (info == NULL) {
   2024         return BCM_E_PARAM;
   2025     }
   2026 
   2027     flow_info = FLOW_INFO(unit);
   2028 
   2029     /* validate the vp */
   2030     if (info->valid_elements & BCM_FLOW_MATCH_FLOW_PORT_VALID) {
   2031         vp = _SHR_GPORT_FLOW_PORT_ID_GET(info->flow_port);
   2032         if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeFlow)) {
   2033             LOG_ERROR(BSL_LS_BCM_FLOW,
   2034                   (BSL_META_U(unit, "flow port ID is not valid\n")));
   2035 
   2036             return BCM_E_PORT;
   2037         }
   2038     }
   2039         
   2040     /* port match doesn't use hash table */
   2041     if (info->criteria == BCM_FLOW_MATCH_CRITERIA_PORT) {
   2042         /* check if this match set flow specific controls on the given port*/
   2043         if (_BCM_FLOW_IS_FLEX_VIEW(info) &&
   2044             info->valid_elements & BCM_FLOW_MATCH_PORT_VALID) {
   2045             rv = _bcm_flow_match_sgpp_ctrl_set(unit,info,num_of_fields,field,FALSE);
   2046             BCM_IF_ERROR_RETURN(rv);
   2047         }
   2048 
   2049         BCM_IF_ERROR_RETURN(_bcm_flow_match_port_ctrl(unit,info,
   2050                  _BCM_FLOW_MATCH_PORT_CTRL_SET,&replaced_vp,&replaced_iif));
   2051 
   2052         bcmi_esw_flow_lock(unit);
   2053         /* update the iif reference counter */
   2054         if (info->valid_elements & BCM_FLOW_MATCH_IIF_VALID) {
   2055             if (info->intf_id) {
   2056                 flow_info->iif_ref_cnt[info->intf_id]++;
   2057             }
   2058             if (replaced_iif) {
   2059                 if (flow_info->iif_ref_cnt[replaced_iif]) {
   2060                     flow_info->iif_ref_cnt[replaced_iif]--;
   2061                 }
   2062             }
   2063         }
   2064         if (info->valid_elements & BCM_FLOW_MATCH_FLOW_PORT_VALID) {
   2065             vp = _SHR_GPORT_FLOW_PORT_ID_GET(info->flow_port);
   2066             if (vp) {
   2067                 flow_info->vp_ref_cnt[vp]++;
   2068             }
   2069             _bcm_flow_match_info_save(unit, vp, info);
   2070             if (replaced_vp) {
   2071                 if (flow_info->vp_ref_cnt[replaced_vp]) {
   2072                     flow_info->vp_ref_cnt[replaced_vp]--;
   2073                 }
   2074             }
   2075         }
   2076         bcmi_esw_flow_unlock(unit);
   2077         return BCM_E_NONE;
   2078     }
   2079 
   2080     sal_memset(entry, 0, sizeof(entry));
   2081     BCM_IF_ERROR_RETURN(_bcm_flow_match_key_set(unit,info,field,
   2082                         num_of_fields,entry,&view_info));
   2083 
   2084     soc_mem_lock(unit,view_info.mem);
   2085     /* set the match object and attributes and write to memory */ 
   2086     rv = _bcm_flow_match_entry_set(unit,info,field,
   2087               num_of_fields,
   2088               &view_info,
   2089                entry,&replaced_iif,&replaced_vp); 
   2090     soc_mem_unlock(unit,view_info.mem);
   2091 
   2092     bcmi_esw_flow_lock(unit);
   2093     /* update the iif reference counter */
   2094     if (BCM_SUCCESS(rv)) { 
   2095         if (info->valid_elements & BCM_FLOW_MATCH_IIF_VALID) {
   2096             flow_info->iif_ref_cnt[info->intf_id]++;
   2097             if (info->options & BCM_FLOW_MATCH_OPTION_REPLACE) {
   2098                 if (flow_info->iif_ref_cnt[replaced_iif]) {
   2099                     flow_info->iif_ref_cnt[replaced_iif]--;
   2100                 }
   2101             }
   2102         }
   2103         if (info->valid_elements & BCM_FLOW_MATCH_FLOW_PORT_VALID) {
   2104             vp = _SHR_GPORT_FLOW_PORT_ID_GET(info->flow_port);
   2105             flow_info->vp_ref_cnt[vp]++;
   2106              _bcm_flow_match_info_save(unit, vp, info);
   2107             if (info->options & BCM_FLOW_MATCH_OPTION_REPLACE) {
   2108                 if (flow_info->vp_ref_cnt[replaced_vp]) {
   2109                     flow_info->vp_ref_cnt[replaced_vp]--;
   2110                 }
   2111             }
   2112         }
   2113     }
   2114     if (!(info->options & BCM_FLOW_MATCH_OPTION_REPLACE)) {
   2115         if (view_info.mem == VLAN_XLATE_1_DOUBLEm) {
   2116             flow_info->mem_use_cnt[_BCM_FLOW_VXLT1_INX]++;
   2117         } else if (view_info.mem == VLAN_XLATE_2_DOUBLEm) {
   2118             flow_info->mem_use_cnt[_BCM_FLOW_VXLT2_INX]++;
   2119         } else if ((view_info.mem == MPLS_ENTRYm) || (view_info.mem == MPLS_ENTRY_SINGLEm)) {
   2120             flow_info->mem_use_cnt[_BCM_FLOW_MPLS_INX]++;
   2121         } else if (view_info.mem == L3_TUNNELm) {
   2122             flow_info->mem_use_cnt[_BCM_FLOW_TNL_INX]++;
   2123         }
   2124     }
   2125     bcmi_esw_flow_unlock(unit);
   2126     return rv;
   2127 }
   2128 
   2129 /*
   2130  * Function:
   2131  *      _bcm_flow_match_profile_delete
   2132  * Purpose:
   2133  *      Delete a profile in flow match entry based on the given info
   2134  * Parameters:
   2135  *      unit     - (IN) Device Number
   2136  *      mem      - (IN) mempru ID
   2137  *      mem_view - (IN) memory view ID
   2138  *      key_data - (IN) entry key
   2139  * Returns:
   2140  *      BCM_E_XXX
   2141  */
   2142 STATIC int
   2143 _bcm_flow_match_profile_delete(
   2144         int unit,
   2145         soc_mem_t mem,
   2146         soc_mem_t mem_view,
   2147         void *key_data)
   2148 {
   2149     soc_format_t tag_profile_fmt = TAG_ACTION_SETfmt;
   2150     soc_field_t tag_profile_fmt_f = TAG_ACTION_SETf;
   2151     soc_field_t tag_act_f = ING_TAG_ACTION_PROFILE_IDXf;
   2152     uint32 tag_profile_set = 0;
   2153     uint32 profile_index = 0;
   2154     uint32 return_entry[SOC_MAX_MEM_WORDS];
   2155     int index = 0;
   2156     int rv = BCM_E_NONE;
   2157 
   2158     BCM_IF_ERROR_RETURN(soc_mem_search(unit, mem, MEM_BLOCK_ANY, &index,
   2159         key_data, return_entry, 0));
   2160     if (soc_flow_db_mem_view_is_valid(unit, mem_view) &&
   2161         soc_mem_field_valid(unit, mem_view, tag_profile_fmt_f)) {
   2162         tag_profile_set = soc_mem_field32_get(unit, mem_view, return_entry,
   2163                             tag_profile_fmt_f);
   2164         profile_index = soc_format_field32_get(unit, tag_profile_fmt,
   2165                             &tag_profile_set, tag_act_f);
   2166     } else if (soc_mem_field_valid(unit, mem, tag_act_f)) {
   2167         tag_profile_set = soc_mem_field32_get(unit, mem, return_entry,
   2168                             tag_act_f);
   2169     }
   2170 
   2171     if ((profile_index != 0) && (profile_index != 1)) {
   2172         rv = _bcm_trx_vlan_action_profile_entry_delete(unit,
   2173                     profile_index);
   2174     }
   2175     return rv;
   2176 }
   2177 
   2178 
   2179 /*
   2180  * Function:
   2181  *      bcmi_esw_flow_match_delete
   2182  * Purpose:
   2183  *      Delete a flow match entry based on the given key
   2184  * Parameters:
   2185  *      unit    - (IN) Device Number
   2186  *      info    - (IN) Flow match config descriptor
   2187  *      num_of_fields - (IN) number of logical fields
   2188  *      field         - (IN) logical field array
   2189  * Returns:
   2190  *      BCM_E_XXX
   2191  */
   2192 
   2193 int bcmi_esw_flow_match_delete(
   2194     int unit,
   2195     bcm_flow_match_config_t *info,
   2196     uint32 num_of_fields,
   2197     bcm_flow_logical_field_t *field)
   2198 {
   2199     uint32 entry[_QUAD_ENTRY_MAX];
   2200     _bcm_flow_bookkeeping_t *flow_info;
   2201     int vp;
   2202     int deleted_vp;
   2203     int deleted_iif;
   2204     soc_flow_db_mem_view_info_t view_info;
   2205     soc_tunnel_term_t key;
   2206     int rv;
   2207 
   2208     if (info == NULL) {
   2209         return BCM_E_PARAM;
   2210     }
   2211     flow_info = FLOW_INFO(unit);
   2212 
   2213     /* port match doesn't use hash table */
   2214     if (info->criteria == BCM_FLOW_MATCH_CRITERIA_PORT) {
   2215         /* Check if delete the flow specfic sgpp control on a specfic port */
   2216         if (_BCM_FLOW_IS_FLEX_VIEW(info) &&
   2217             info->valid_elements & BCM_FLOW_MATCH_PORT_VALID) {
   2218             rv = _bcm_flow_match_sgpp_ctrl_set(unit,info,num_of_fields,field,TRUE);
   2219             BCM_IF_ERROR_RETURN(rv);
   2220         }
   2221         /* perform delete action */
   2222         BCM_IF_ERROR_RETURN(_bcm_flow_match_port_ctrl(unit,info,
   2223                       _BCM_FLOW_MATCH_PORT_CTRL_DELETE,&deleted_vp,
   2224                        &deleted_iif));
   2225         bcmi_esw_flow_lock(unit);
   2226         if (info->intf_id) {
   2227             if (flow_info->iif_ref_cnt[info->intf_id]) {
   2228                 flow_info->iif_ref_cnt[info->intf_id]--; 
   2229             }
   2230         }
   2231         vp = _SHR_GPORT_FLOW_PORT_ID_GET(info->flow_port);
   2232         if (vp) {
   2233             if (flow_info->vp_ref_cnt[vp]) {
   2234                 flow_info->vp_ref_cnt[vp]--; 
   2235             }
   2236         }
   2237         bcmi_esw_flow_unlock(unit);
   2238         if (deleted_vp) {
   2239             _bcm_flow_match_info_clear(unit, deleted_vp);
   2240         }
   2241         return BCM_E_NONE;
   2242     }
   2243 
   2244     sal_memset(entry, 0, sizeof(entry));
   2245     BCM_IF_ERROR_RETURN(_bcm_flow_match_key_set(unit,info,field,
   2246                         num_of_fields,entry,&view_info));
   2247     if (view_info.mem == L3_TUNNELm) {
   2248         rv = _bcm_flow_match_mem_entry_to_term_entry(unit, view_info.mem,
   2249                     &key, entry);
   2250         BCM_IF_ERROR_RETURN(rv);
   2251     }
   2252     BCM_IF_ERROR_RETURN(_bcm_flow_match_entry_get(unit,info,field,
   2253               num_of_fields,
   2254               &view_info,
   2255               entry));
   2256 
   2257     if (view_info.mem == L3_TUNNELm) {
   2258         BCM_IF_ERROR_RETURN(soc_tunnel_term_delete(unit, &key)); 
   2259     } else {
   2260         BCM_IF_ERROR_RETURN(_bcm_flow_match_profile_delete(unit, view_info.mem,
   2261                     view_info.mem_view_id, entry));
   2262         BCM_IF_ERROR_RETURN(soc_mem_delete(unit, view_info.mem, 
   2263                         MEM_BLOCK_ANY, entry));
   2264     }
   2265 
   2266     bcmi_esw_flow_lock(unit);
   2267     if (info->intf_id) {
   2268         if (flow_info->iif_ref_cnt[info->intf_id]) {
   2269             flow_info->iif_ref_cnt[info->intf_id]--; 
   2270         }
   2271     }
   2272     vp = _SHR_GPORT_FLOW_PORT_ID_GET(info->flow_port);
   2273     if (vp) {
   2274         if (flow_info->vp_ref_cnt[vp]) {
   2275             flow_info->vp_ref_cnt[vp]--; 
   2276         }
   2277     }
   2278     if (view_info.mem == VLAN_XLATE_1_DOUBLEm) {
   2279         if (flow_info->mem_use_cnt[_BCM_FLOW_VXLT1_INX]) {
   2280             flow_info->mem_use_cnt[_BCM_FLOW_VXLT1_INX]--;
   2281         }
   2282     } else if (view_info.mem == VLAN_XLATE_2_DOUBLEm) {
   2283         if (flow_info->mem_use_cnt[_BCM_FLOW_VXLT2_INX]) {
   2284             flow_info->mem_use_cnt[_BCM_FLOW_VXLT2_INX]--;
   2285         }
   2286     } else if ((view_info.mem == MPLS_ENTRYm) || (view_info.mem == MPLS_ENTRY_SINGLEm)) {
   2287         if (flow_info->mem_use_cnt[_BCM_FLOW_MPLS_INX]) {
   2288             flow_info->mem_use_cnt[_BCM_FLOW_MPLS_INX]--;
   2289         }
   2290     } else if (view_info.mem == L3_TUNNELm) {
   2291         if (flow_info->mem_use_cnt[_BCM_FLOW_TNL_INX]) {
   2292             flow_info->mem_use_cnt[_BCM_FLOW_TNL_INX]--;
   2293         }
   2294     }
   2295     bcmi_esw_flow_unlock(unit);
   2296     if (vp) {
   2297         _bcm_flow_match_info_clear(unit, vp);
   2298     }
   2299     return BCM_E_NONE;
   2300 }
   2301 
   2302 /*
   2303  * Function:
   2304  *      bcmi_esw_flow_match_get
   2305  * Purpose:
   2306  *      Delete a flow match entry based on the given key
   2307  * Parameters:
   2308  *      unit    - (IN) Device Number
   2309  *      info    - (IN) Flow match config descriptor
   2310  *      num_of_fields - (IN) number of logical fields
   2311  *      field         - (IN) logical field array
   2312  * Returns:
   2313  *      BCM_E_XXX
   2314  */
   2315 
   2316 int bcmi_esw_flow_match_get(
   2317     int unit,
   2318     bcm_flow_match_config_t *info,
   2319     uint32 num_of_fields,
   2320     bcm_flow_logical_field_t *field)
   2321 {
   2322     uint32 entry[_QUAD_ENTRY_MAX];
   2323     soc_flow_db_mem_view_info_t view_info;
   2324 
   2325     if (info == NULL) {
   2326         return BCM_E_PARAM;
   2327     }
   2328     /* port match doesn't use hash table */
   2329     if (info->criteria == BCM_FLOW_MATCH_CRITERIA_PORT) {
   2330         /* perform delete action */
   2331         BCM_IF_ERROR_RETURN(_bcm_flow_match_port_ctrl(unit,info,
   2332                             _BCM_FLOW_MATCH_PORT_CTRL_GET,NULL,NULL));
   2333         return BCM_E_NONE;
   2334     }
   2335 
   2336     sal_memset(entry, 0, sizeof(entry));
   2337     BCM_IF_ERROR_RETURN(_bcm_flow_match_key_set(unit,info,field,
   2338                         num_of_fields,entry,&view_info));
   2339 
   2340     BCM_IF_ERROR_RETURN(_bcm_flow_match_entry_get(unit,info,field,
   2341               num_of_fields,
   2342               &view_info,
   2343               entry)); 
   2344     return BCM_E_NONE;
   2345 }
   2346 
   2347 STATIC int
   2348 _bcm_flow_match_entry_valid(int unit, soc_mem_t mem, uint32 *entry, int *valid)
   2349 {
   2350     if (INVALIDm == mem) {
   2351         return BCM_E_MEMORY;
   2352     }
   2353 
   2354     if ((NULL == entry) || (NULL == valid)) {
   2355         return BCM_E_PARAM;
   2356     }
   2357     *valid = TRUE;
   2358     if (SOC_MEM_FIELD_VALID(unit,mem,BASE_VALID_0f)) {
   2359         if (!soc_mem_field32_get(unit, mem, entry, BASE_VALID_0f)) {
   2360             *valid = FALSE;
   2361         }
   2362     }
   2363     if (SOC_MEM_FIELD_VALID(unit,mem,BASE_VALID_1f)) {
   2364         if (!soc_mem_field32_get(unit, mem, entry, BASE_VALID_1f)) {
   2365             *valid = FALSE;
   2366         }
   2367     }
   2368     if (SOC_MEM_FIELD_VALID(unit,mem,VALIDf)) {
   2369         if (!soc_mem_field32_get(unit, mem, entry, VALIDf)) {
   2370             *valid = FALSE;
   2371         }
   2372     }
   2373     return BCM_E_NONE;
   2374 }
   2375 
   2376 /*
   2377  * Function   :
   2378  *      _bcm_flow_match_entry_parse
   2379  * Description   :
   2380  *      Convert the memory entry field data to the flow match configuration
   2381  *      parameters.
   2382  * Parameters   :
   2383  *      unit    - (IN) Device Number
   2384  *      mem     - (IN)  memory id.
   2385  *      entry   - (IN) HW entry.
   2386  *      info    - (OUT) Flow match config descriptor
   2387  *      num_of_fields - (OUT) number of logical fields
   2388  *      field         - (OUT) logical field array
   2389  */
   2390 int
   2391 _bcm_flow_match_entry_parse(int unit, soc_mem_t mem, uint32 *entry,
   2392                              bcm_flow_match_config_t *info,
   2393                              uint32 *num_of_fields,
   2394                              bcm_flow_logical_field_t *field)
   2395 {
   2396     int data_type;  
   2397     int key_type;
   2398     bcm_module_t mod_out = -1;
   2399     bcm_port_t port_out = -1;
   2400     bcm_trunk_t trunk_id = -1;
   2401     uint32 trunk_bit = 0;
   2402     soc_field_t ovid_f;
   2403     soc_field_t otag_f;
   2404     soc_field_t ivid_f;
   2405     soc_field_t sip_f;
   2406     soc_field_t dip_f;
   2407     soc_field_t vnid_f;
   2408     soc_field_t t_f;
   2409     soc_field_t tgid_f;
   2410     soc_field_t module_id_f;
   2411     soc_field_t port_num_f;
   2412     uint32 field_id[_BCM_FLOW_LOGICAL_FIELD_MAX];
   2413     uint32 cnt;
   2414     uint32 data_cnt;
   2415     int i;
   2416     int rv;
   2417     soc_mem_t mem_view_id;
   2418     int is_flex_view;
   2419 
   2420     key_type  = 0;
   2421     data_type = 0; 
   2422     vnid_f = VXLAN_VN_ID__VN_IDf; 
   2423     sip_f  = SIPf;
   2424     is_flex_view = FALSE;
   2425 
   2426     if (SOC_MEM_FIELD_VALID(unit,mem,KEY_TYPEf)) { 
   2427         key_type = soc_mem_field32_get(unit, mem, entry, KEY_TYPEf);
   2428     }
   2429     if (SOC_MEM_FIELD_VALID(unit,mem,DATA_TYPEf)) { 
   2430         data_type = soc_mem_field32_get(unit, mem, entry, DATA_TYPEf);
   2431     }  
   2432 
   2433     /* find the memory view based on the memory and key type */
   2434     rv = soc_flow_db_mem_to_view_id_get (unit, mem, key_type, data_type, 
   2435                     0, NULL, (uint32 *)&mem_view_id);
   2436 
   2437     if (rv != SOC_E_NONE && rv != SOC_E_NOT_FOUND) {
   2438         return rv;
   2439     }
   2440     if (rv == SOC_E_NOT_FOUND) {  /* fixed view */ 
   2441         /* match action in L3_TUNNELm only available for flex view */
   2442         if (mem == L3_TUNNELm) {
   2443             return SOC_E_NOT_FOUND;
   2444         }
   2445         rv = SOC_E_NONE;
   2446         if (mem == VLAN_XLATE_1_DOUBLEm || mem == VLAN_XLATE_2_DOUBLEm) {
   2447             switch (key_type) {
   2448                 case TR_VLXLT_HASH_KEY_TYPE_OVID:
   2449                     info->criteria = BCM_FLOW_MATCH_CRITERIA_PORT_VLAN;
   2450                     info->valid_elements |= BCM_FLOW_MATCH_PORT_VALID |
   2451                                             BCM_FLOW_MATCH_VLAN_VALID;
   2452                     break;
   2453 
   2454                 case TR_VLXLT_HASH_KEY_TYPE_IVID:
   2455                     info->criteria = BCM_FLOW_MATCH_CRITERIA_PORT_INNER_VLAN;
   2456                     info->valid_elements |= BCM_FLOW_MATCH_PORT_VALID |
   2457                                             BCM_FLOW_MATCH_INNER_VLAN_VALID;
   2458                     break;
   2459 
   2460                 case TR_VLXLT_HASH_KEY_TYPE_IVID_OVID:
   2461                     info->criteria = BCM_FLOW_MATCH_CRITERIA_PORT_VLAN_STACKED;
   2462                     info->valid_elements |= BCM_FLOW_MATCH_PORT_VALID |
   2463                                             BCM_FLOW_MATCH_VLAN_VALID |
   2464                                             BCM_FLOW_MATCH_INNER_VLAN_VALID;
   2465                     break;
   2466 
   2467                 case TR_VLXLT_HASH_KEY_TYPE_PRI_CFI:
   2468                     info->criteria = BCM_FLOW_MATCH_CRITERIA_VLAN_PRI;
   2469                     info->valid_elements |= BCM_FLOW_MATCH_PORT_VALID |
   2470                                             BCM_FLOW_MATCH_VLAN_VALID;
   2471                     break;
   2472                 case _BCM_FLOW_MATCH_KEY_TYPE_VXLAN_FLEX_VNID:
   2473                     info->criteria = BCM_FLOW_MATCH_CRITERIA_VN_ID;
   2474                     info->flow_handle = SOC_FLOW_DB_FLOW_ID_LEGACY_VXLAN;
   2475                     info->valid_elements |= BCM_FLOW_MATCH_VNID_VALID;
   2476                     break;
   2477                 case _BCM_FLOW_MATCH_KEY_TYPE_VXLAN_FLEX_SIP_VNID:
   2478                     info->criteria = BCM_FLOW_MATCH_CRITERIA_SIP_VNID;
   2479                     info->flow_handle = SOC_FLOW_DB_FLOW_ID_LEGACY_VXLAN;
   2480                     info->valid_elements |= BCM_FLOW_MATCH_SIP_VALID |
   2481                                             BCM_FLOW_MATCH_VNID_VALID;
   2482                     break;
   2483                 default:
   2484                     /* not used by the flow_match functions */
   2485                     return BCM_E_NOT_FOUND;
   2486                     break;
   2487              }
   2488         } else if (mem == MPLS_ENTRYm) {
   2489             switch (key_type) {
   2490                 case _BCM_FLOW_MATCH_KEY_TYPE_VXLAN_VNID:
   2491                     info->criteria = BCM_FLOW_MATCH_CRITERIA_VN_ID;
   2492                     info->flow_handle = SOC_FLOW_DB_FLOW_ID_LEGACY_VXLAN;
   2493                     info->valid_elements |= BCM_FLOW_MATCH_VNID_VALID;
   2494                     break;
   2495                 case _BCM_FLOW_MATCH_KEY_TYPE_L2GRE_VPNID:
   2496                     info->criteria = BCM_FLOW_MATCH_CRITERIA_VN_ID;
   2497                     info->flow_handle = SOC_FLOW_DB_FLOW_ID_LEGACY_L2GRE;
   2498                     info->valid_elements |= BCM_FLOW_MATCH_VNID_VALID;
   2499                     break;
   2500                 case _BCM_FLOW_MATCH_KEY_TYPE_VXLAN_SIP:
   2501                     info->criteria = BCM_FLOW_MATCH_CRITERIA_SIP;
   2502                     info->flow_handle = SOC_FLOW_DB_FLOW_ID_LEGACY_VXLAN;
   2503                     info->valid_elements |= BCM_FLOW_MATCH_SIP_VALID;
   2504                     info->vlan = soc_mem_field32_get(unit, mem,
   2505                            entry, VXLAN_SIP__OVIDf);
   2506                     break;
   2507                 case _BCM_FLOW_MATCH_KEY_TYPE_L2GRE_SIP:
   2508                     info->criteria = BCM_FLOW_MATCH_CRITERIA_SIP;
   2509                     info->flow_handle = SOC_FLOW_DB_FLOW_ID_LEGACY_L2GRE;
   2510                     info->valid_elements |= BCM_FLOW_MATCH_SIP_VALID;
   2511                     break;
   2512                 case _BCM_FLOW_MATCH_KEY_TYPE_VXLAN_SIP_VNID:
   2513                     info->criteria = BCM_FLOW_MATCH_CRITERIA_SIP_VNID;
   2514                     info->flow_handle = SOC_FLOW_DB_FLOW_ID_LEGACY_VXLAN;
   2515                     info->valid_elements |= BCM_FLOW_MATCH_SIP_VALID |
   2516                                             BCM_FLOW_MATCH_VNID_VALID;
   2517                     break;
   2518                 case _BCM_FLOW_MATCH_KEY_TYPE_L2GRE_SIP_VPNID:
   2519                     info->criteria = BCM_FLOW_MATCH_CRITERIA_SIP_VNID;
   2520                     info->flow_handle = SOC_FLOW_DB_FLOW_ID_LEGACY_L2GRE;
   2521                     info->valid_elements |= BCM_FLOW_MATCH_SIP_VALID |
   2522                                             BCM_FLOW_MATCH_VNID_VALID;
   2523                     break;
   2524 
   2525                 default:
   2526                     /* not used by the flow_match functions */
   2527                     return BCM_E_NOT_FOUND;
   2528                     break;
   2529              }
   2530         } else if (mem == MPLS_ENTRY_SINGLEm) {
   2531             switch (key_type) {
   2532                 case _BCM_FLOW_MATCH_KEY_TYPE_VXLAN_SIP:
   2533                     info->criteria = BCM_FLOW_MATCH_CRITERIA_SIP;
   2534                     info->flow_handle = SOC_FLOW_DB_FLOW_ID_LEGACY_VXLAN;
   2535                     info->valid_elements |= BCM_FLOW_MATCH_SIP_VALID;
   2536                     break;
   2537                 default:
   2538                     /* not used by the flow_match functions */
   2539                     return BCM_E_NOT_FOUND;
   2540                     break;
   2541             }
   2542         }
   2543     } else {  /* flex view found */      
   2544         uint32 port_ovid_ids[3];
   2545         uint32 port_ivid_ids[3];
   2546         uint32 port_dtag_ids[4];
   2547         uint32 otag_id[1];
   2548         uint32 sip_id[1];
   2549         uint32 vnid_id[1];
   2550         uint32 vnid_sip_ids[2];
   2551 
   2552         is_flex_view = TRUE;
   2553         port_ovid_ids[0] = MODULE_IDf;
   2554         port_ovid_ids[1] = PORT_NUMf;
   2555         port_ovid_ids[2] = OVIDf;
   2556 
   2557         port_ivid_ids[0] = MODULE_IDf;
   2558         port_ivid_ids[1] = PORT_NUMf;
   2559         port_ivid_ids[2] = IVIDf;
   2560 
   2561         port_dtag_ids[0] = MODULE_IDf;
   2562         port_dtag_ids[1] = PORT_NUMf;
   2563         port_dtag_ids[2] = OVIDf;
   2564         port_dtag_ids[3] = IVIDf;
   2565 
   2566         otag_id[0] = OTAGf;
   2567         vnid_id[0] = VNIDf;
   2568         vnid_sip_ids[1] = VNIDf;
   2569         if (SOC_MEM_FIELD_VALID(unit,mem_view_id,IPV4__SIPf)) {
   2570             sip_id[0]  = IPV4__SIPf;
   2571             vnid_sip_ids[0] = IPV4__SIPf;
   2572         } else {
   2573             sip_id[0]  = SIPf;
   2574             vnid_sip_ids[0] = SIPf;
   2575         }
   2576         rv = _bcm_flow_mem_view_to_flow_info_get(unit, mem_view_id, 
   2577                SOC_FLOW_DB_FUNC_MATCH_ID, 
   2578                &info->flow_handle, &info->flow_option, 1);
   2579         SOC_IF_ERROR_RETURN(rv);
   2580 
   2581         mem = mem_view_id;
   2582         if (_bcm_flow_key_is_valid(unit, mem, port_ovid_ids, 3)) {
   2583             info->criteria = BCM_FLOW_MATCH_CRITERIA_PORT_VLAN;
   2584             info->valid_elements |= BCM_FLOW_MATCH_PORT_VALID |
   2585                                     BCM_FLOW_MATCH_VLAN_VALID;
   2586         } else if (_bcm_flow_key_is_valid(unit, mem, port_ivid_ids,3)) {
   2587             info->criteria = BCM_FLOW_MATCH_CRITERIA_PORT_INNER_VLAN;
   2588             info->valid_elements |= BCM_FLOW_MATCH_PORT_VALID |
   2589                                     BCM_FLOW_MATCH_INNER_VLAN_VALID;
   2590         } else if (_bcm_flow_key_is_valid(unit, mem, port_dtag_ids,4)) {
   2591             info->criteria = BCM_FLOW_MATCH_CRITERIA_PORT_VLAN_STACKED;
   2592             info->valid_elements |= BCM_FLOW_MATCH_PORT_VALID |
   2593                                     BCM_FLOW_MATCH_VLAN_VALID |
   2594                                     BCM_FLOW_MATCH_INNER_VLAN_VALID;
   2595         } else if (_bcm_flow_key_is_valid(unit, mem, otag_id, 1)) {
   2596             info->criteria = BCM_FLOW_MATCH_CRITERIA_VLAN_PRI;
   2597             info->valid_elements |= BCM_FLOW_MATCH_PORT_VALID |
   2598                                     BCM_FLOW_MATCH_VLAN_VALID;
   2599         } else if (_bcm_flow_key_is_valid(unit, mem, vnid_id, 1)) {
   2600             info->criteria = BCM_FLOW_MATCH_CRITERIA_VN_ID;
   2601             info->valid_elements |= BCM_FLOW_MATCH_VNID_VALID;
   2602         } else if (_bcm_flow_key_is_valid(unit, mem, sip_id, 1)) {
   2603             info->criteria = BCM_FLOW_MATCH_CRITERIA_SIP;
   2604             info->valid_elements |= BCM_FLOW_MATCH_SIP_VALID;
   2605         } else if (_bcm_flow_key_is_valid(unit, mem, vnid_sip_ids, 1)) {
   2606             info->criteria = BCM_FLOW_MATCH_CRITERIA_SIP_VNID;
   2607             info->valid_elements |= BCM_FLOW_MATCH_SIP_VALID |
   2608                                     BCM_FLOW_MATCH_VNID_VALID;
   2609         } else {
   2610             info->criteria = BCM_FLOW_MATCH_CRITERIA_FLEX;
   2611             info->valid_elements |= BCM_FLOW_MATCH_FLEX_KEY_VALID;
   2612         }
   2613     }
   2614 
   2615     /* retrieve the key fields */
   2616     if (is_flex_view) { /* flex view */
   2617         t_f         = Tf;
   2618         tgid_f      = TGIDf;
   2619         module_id_f = MODULE_IDf;
   2620         port_num_f  = PORT_NUMf;
   2621         ovid_f      = OVIDf;
   2622         ivid_f      = IVIDf;
   2623         otag_f      = OTAGf;
   2624     } else {  /* fix key type */
   2625         t_f         = XLATE__Tf;
   2626         tgid_f      = XLATE__TGIDf;
   2627         module_id_f = XLATE__MODULE_IDf;
   2628         port_num_f  = XLATE__PORT_NUMf;
   2629         ovid_f      = XLATE__OVIDf;
   2630         ivid_f      = XLATE__IVIDf;
   2631         otag_f      = XLATE__OTAGf;
   2632     }
   2633     if (info->criteria == BCM_FLOW_MATCH_CRITERIA_VLAN_PRI) {
   2634         if (SOC_MEM_FIELD_VALID(unit,mem,otag_f)) { 
   2635             info->vlan = soc_mem_field32_get(unit, mem, entry, otag_f);
   2636         }
   2637     } else {
   2638         if (SOC_MEM_FIELD_VALID(unit,mem,ovid_f)) { 
   2639             info->vlan = soc_mem_field32_get(unit, mem, entry, ovid_f);
   2640         }
   2641     }
   2642     if (SOC_MEM_FIELD_VALID(unit,mem,ivid_f)) { 
   2643         info->inner_vlan = soc_mem_field32_get(unit, mem, entry, ivid_f);
   2644     }
   2645     if (SOC_MEM_FIELD_VALID(unit,mem,t_f)) { 
   2646         trunk_bit = soc_mem_field32_get(unit,mem, entry, t_f);
   2647     }
   2648     if (trunk_bit) {
   2649         if (SOC_MEM_FIELD_VALID(unit,mem,tgid_f)) { 
   2650             trunk_id = soc_mem_field32_get(unit,mem, entry, tgid_f);
   2651             BCM_GPORT_TRUNK_SET(info->port,trunk_id);
   2652             info->valid_elements |= BCM_FLOW_MATCH_PORT_VALID;
   2653         }
   2654     } else {
   2655         if (SOC_MEM_FIELD_VALID(unit,mem,module_id_f)) { 
   2656             mod_out = soc_mem_field32_get(unit,mem, entry, module_id_f);
   2657             if (SOC_MEM_FIELD_VALID(unit,mem,port_num_f)) { 
   2658                 port_out= soc_mem_field32_get(unit,mem, entry, port_num_f);
   2659             }
   2660             if (mod_out != -1 && port_out != 1) { 
   2661                 BCM_GPORT_MODPORT_SET(info->port,mod_out,port_out);
   2662                 info->valid_elements |= BCM_FLOW_MATCH_PORT_VALID;
   2663             }
   2664         }
   2665     }
   2666     if (SOC_MEM_FIELD_VALID(unit,mem,SGPPf)) {
   2667         uint32 sgpp;
   2668 
   2669         sgpp = soc_mem_field32_get(unit,mem, entry, SGPPf); 
   2670         port_out = sgpp & 0xff;
   2671         mod_out  = (sgpp >> 8) & 0xff;
   2672         BCM_GPORT_MODPORT_SET(info->port,mod_out,port_out);
   2673         info->valid_elements |= BCM_FLOW_MATCH_PORT_VALID;
   2674     }
   2675 
   2676     if (info->criteria == BCM_FLOW_MATCH_CRITERIA_SIP) {
   2677         if (is_flex_view) {
   2678             ovid_f = OVIDf;
   2679             vnid_f = VNIDf; 
   2680             if (SOC_MEM_FIELD_VALID(unit,mem,IPV4__SIPf)) {
   2681                 sip_f  = IPV4__SIPf;
   2682             } else {
   2683                 sip_f  = SIPf;
   2684             }
   2685         } else {
   2686             if (info->flow_handle == SOC_FLOW_DB_FLOW_ID_LEGACY_VXLAN) {
   2687                 if (soc_feature(unit, soc_feature_vxlan_decoupled_mode)) {
   2688                     sip_f  = VXLAN_FLEX_IPV4_SIP__SIPf;
   2689                 } else {
   2690                     ovid_f = VXLAN_SIP__OVIDf;
   2691                     sip_f  = VXLAN_SIP__SIPf;
   2692                 }
   2693             } else if (info->flow_handle == SOC_FLOW_DB_FLOW_ID_LEGACY_L2GRE) {
   2694                 sip_f  = L2GRE_SIP__SIPf;
   2695             } else {
   2696                 LOG_ERROR(BSL_LS_BCM_FLOW,
   2697                       (BSL_META_U(unit, "Invalid legacy flow handle\n")));
   2698                 return BCM_E_PARAM;
   2699             }
   2700         }
   2701         if (soc_feature(unit, soc_feature_vrf_aware_vxlan_termination)) { 
   2702             if (SOC_MEM_FIELD_VALID(unit,mem,ovid_f)) {
   2703                 info->vlan = soc_mem_field32_get(unit,mem, entry, ovid_f);
   2704                 info->valid_elements |= BCM_FLOW_MATCH_VLAN_VALID;
   2705             }
   2706         }
   2707         info->sip = soc_mem_field32_get(unit,mem, entry, sip_f);
   2708         info->valid_elements |= BCM_FLOW_MATCH_SIP_VALID;
   2709     } else if (info->criteria == BCM_FLOW_MATCH_CRITERIA_VN_ID ||
   2710             info->criteria == BCM_FLOW_MATCH_CRITERIA_SIP_VNID) {
   2711         if (is_flex_view) {
   2712             ovid_f = OVIDf;
   2713             vnid_f = VNIDf; 
   2714             if (SOC_MEM_FIELD_VALID(unit,mem,IPV4__SIPf)) {
   2715                 sip_f  = IPV4__SIPf;
   2716             } else {
   2717                 sip_f  = SIPf;
   2718             }
   2719         } else {
   2720             if (info->flow_handle == SOC_FLOW_DB_FLOW_ID_LEGACY_VXLAN) {
   2721                 if (soc_feature(unit, soc_feature_vxlan_decoupled_mode)) {
   2722                     ovid_f = VXLAN_FLEX__OVIDf;
   2723                     sip_f  = VXLAN_FLEX__SIPf;
   2724                     vnid_f = VXLAN_FLEX__VNIDf;
   2725                 } else {
   2726                     ovid_f = VXLAN_VN_ID__OVIDf;
   2727                     sip_f  = VXLAN_VN_ID__SIPf;
   2728                     vnid_f = VXLAN_VN_ID__VN_IDf;
   2729                 }
   2730             } else if (info->flow_handle == SOC_FLOW_DB_FLOW_ID_LEGACY_L2GRE) {
   2731                 vnid_f = L2GRE_VPNID__VPNIDf;
   2732                 sip_f   = L2GRE_VPNID__SIPf;
   2733             } else {
   2734                 LOG_ERROR(BSL_LS_BCM_FLOW,
   2735                       (BSL_META_U(unit, "Invalid legacy flow handle\n")));
   2736                 return BCM_E_PARAM;
   2737             }
   2738         }
   2739         info->vnid = soc_mem_field32_get(unit, mem, entry, vnid_f);
   2740         info->valid_elements |= BCM_FLOW_MATCH_VNID_VALID;
   2741         if (info->criteria == BCM_FLOW_MATCH_CRITERIA_SIP_VNID) {
   2742             info->sip = soc_mem_field32_get(unit,mem, entry, sip_f);
   2743             info->valid_elements |= BCM_FLOW_MATCH_SIP_VALID;
   2744         }
   2745         if (SOC_MEM_FIELD_VALID(unit,mem,ovid_f)) {
   2746             info->vlan = soc_mem_field32_get(unit,mem, entry, ovid_f);
   2747             info->valid_elements |= BCM_FLOW_MATCH_VLAN_VALID;
   2748         } else if (SOC_MEM_FIELD_VALID(unit, mem, OVLAN_ACTION_SETf)) {
   2749                 uint32 action_set = soc_mem_field32_get(unit, mem, entry, OVLAN_ACTION_SETf);
   2750                 info->vlan = soc_format_field32_get(unit, OVLAN_ACTION_SETfmt, &action_set, VLAN_IDf);
   2751                 info->valid_elements |= BCM_FLOW_MATCH_VLAN_VALID;
   2752             }
   2753 
   2754     } else if (info->criteria == BCM_FLOW_MATCH_CRITERIA_FLEX) {
   2755         rv = soc_flow_db_mem_view_field_list_get(unit,
   2756                          mem,
   2757                          SOC_FLOW_DB_FIELD_TYPE_LOGICAL_KEY,
   2758                          _BCM_FLOW_LOGICAL_FIELD_MAX, field_id, &cnt);
   2759         SOC_IF_ERROR_RETURN(rv);
   2760         if (cnt >= _BCM_FLOW_LOGICAL_FIELD_MAX) {
   2761                 LOG_ERROR(BSL_LS_BCM_FLOW,
   2762                       (BSL_META_U(unit, 
   2763                        "Exceed max logical array size: %d\n"),cnt));
   2764             return BCM_E_PARAM;
   2765         }
   2766         for (i = 0; i < cnt; i++) {
   2767             field[i].id = field_id[i]; 
   2768             field[i].value = soc_mem_field32_get(unit,mem, entry,
   2769                      field[i].id);
   2770         }
   2771            
   2772         if (SOC_MEM_FIELD_VALID(unit,mem,vnid_f)) { 
   2773             info->vnid = soc_mem_field32_get(unit,mem, entry, vnid_f);
   2774             info->valid_elements |= BCM_FLOW_MATCH_VNID_VALID;
   2775         }
   2776         if (SOC_MEM_FIELD_VALID(unit,mem,ovid_f)) { 
   2777             info->vlan = soc_mem_field32_get(unit,mem, entry, ovid_f);
   2778             info->valid_elements |= BCM_FLOW_MATCH_VLAN_VALID;
   2779         }
   2780         if (SOC_MEM_FIELD_VALID(unit,mem,ivid_f)) { 
   2781             info->inner_vlan = soc_mem_field32_get(unit,mem, entry, ivid_f);
   2782             info->valid_elements |= BCM_FLOW_MATCH_INNER_VLAN_VALID;
   2783         }
   2784         if (SOC_MEM_FIELD_VALID(unit,mem,IPV4__SIPf)) {
   2785             sip_f  = IPV4__SIPf;
   2786         } else {
   2787             sip_f  = SIPf;
   2788         }
   2789         if (SOC_MEM_FIELD_VALID(unit,mem,sip_f)) { 
   2790             info->sip = soc_mem_field32_get(unit,mem, entry, sip_f);
   2791             info->valid_elements |= BCM_FLOW_MATCH_SIP_VALID;
   2792         }
   2793         if (SOC_MEM_FIELD_VALID(unit,mem,IPV6__SIPf)) { 
   2794             soc_mem_ip6_addr_get(unit, mem, entry,IPV6__SIPf, info->sip6, 0);
   2795             info->valid_elements |= BCM_FLOW_MATCH_SIP_V6_VALID;
   2796         }
   2797 
   2798         if (SOC_MEM_FIELD_VALID(unit,mem,IPV4__DIPf)) {
   2799             dip_f  = IPV4__DIPf;
   2800         } else {
   2801             dip_f  = DIPf;
   2802         }
   2803         if (SOC_MEM_FIELD_VALID(unit,mem,dip_f)) { 
   2804             info->dip = soc_mem_field32_get(unit,mem, entry, dip_f);
   2805             info->valid_elements |= BCM_FLOW_MATCH_DIP_VALID;
   2806         }
   2807         if (SOC_MEM_FIELD_VALID(unit,mem,IPV6__DIPf)) { 
   2808             soc_mem_ip6_addr_get(unit, mem, entry,IPV6__DIPf, info->dip6, 0);
   2809             info->valid_elements |= BCM_FLOW_MATCH_DIP_V6_VALID;
   2810         }
   2811         if (SOC_MEM_FIELD_VALID(unit,mem,IPV4__PROTOCOLf)) {
   2812             info->protocol = soc_mem_field32_get(unit,mem, entry, 
   2813                                    IPV4__PROTOCOLf);
   2814             info->valid_elements |= BCM_FLOW_MATCH_PROTOCOL_VALID;
   2815         }
   2816         if (SOC_MEM_FIELD_VALID(unit,mem,L4_SRC_PORTf)) {
   2817             info->udp_src_port = soc_mem_field32_get(unit,mem, entry, 
   2818                         L4_SRC_PORTf);
   2819             info->valid_elements |= BCM_FLOW_MATCH_UDP_SRC_PORT_VALID;
   2820         }
   2821         if (SOC_MEM_FIELD_VALID(unit,mem,L4_DST_PORTf)) {
   2822             info->udp_dst_port = soc_mem_field32_get(unit,mem, entry, 
   2823                                    L4_DST_PORTf);
   2824             info->valid_elements |= BCM_FLOW_MATCH_UDP_DST_PORT_VALID;
   2825         }
   2826     }     
   2827 
   2828     if (info->criteria != BCM_FLOW_MATCH_CRITERIA_FLEX) {
   2829         cnt = 0;
   2830     }
   2831 
   2832     data_cnt = 0;
   2833     if (is_flex_view) { /* flex view */
   2834         /* retrieve the data fields, cnt: number of key fields */
   2835         rv = soc_flow_db_mem_view_field_list_get(unit,
   2836                    mem,
   2837                    SOC_FLOW_DB_FIELD_TYPE_LOGICAL_POLICY_DATA,
   2838                    _BCM_FLOW_LOGICAL_FIELD_MAX - cnt, field_id, &data_cnt);
   2839         if (rv != SOC_E_NONE && rv != SOC_E_NOT_FOUND) {
   2840             return rv;
   2841         }
   2842     
   2843         if (data_cnt >= _BCM_FLOW_LOGICAL_FIELD_MAX - cnt) {
   2844             LOG_ERROR(BSL_LS_BCM_FLOW,
   2845                 (BSL_META_U(unit, 
   2846                 "Exceed default logical array size: %d\n"),cnt + data_cnt));
   2847             return BCM_E_PARAM;
   2848         }
   2849         for (i = 0; i < data_cnt; i++) {
   2850             field[i+cnt].id = field_id[i];
   2851         }
   2852         if (!_BCM_FLOW_IS_FLEX_VIEW(info)) {
   2853             /* flow_handle is not properly set, use default flex handle*/
   2854             info->flow_handle = SOC_FLOW_DB_FLOW_ID_START;
   2855         }
   2856     }
   2857     rv = _bcm_flow_match_entry_data_get(unit, info, field+cnt, 
   2858                     data_cnt, mem, entry);
   2859     BCM_IF_ERROR_RETURN(rv);
   2860     *num_of_fields = cnt + data_cnt;
   2861     if (data_cnt) {
   2862         info->valid_elements |= BCM_FLOW_MATCH_FLEX_DATA_VALID;
   2863     }
   2864 
   2865     /* non-flow match APIs could also use the same key type to add the entries
   2866      * to this table. Make sure the right entries are traversed by validating
   2867      * the objects.
   2868      */
   2869     if (!(info->valid_elements & (BCM_FLOW_MATCH_FLOW_PORT_VALID |
   2870                                 BCM_FLOW_MATCH_IIF_VALID |
   2871                                 BCM_FLOW_MATCH_VPN_VALID |
   2872                                 BCM_FLOW_MATCH_FLEX_DATA_VALID))) {
   2873         return BCM_E_NOT_FOUND;
   2874     } 
   2875     return BCM_E_NONE;
   2876 }
   2877 
   2878 /*
   2879  * Function:
   2880  *      _bcm_flow_match_trunk_mem_traverse
   2881  * Purpose:
   2882  *      Read the source trunk memory table and call the user callback function 
   2883  *      on each entry.
   2884  * Parameters:
   2885  *      unit    - (IN) Device Number
   2886  *      cb      - (IN) user callback function
   2887  *      user_data     - (IN) user context data
   2888  * Returns:
   2889  *      BCM_E_XXX
   2890  */
   2891 
   2892 STATIC int
   2893 _bcm_flow_match_trunk_mem_traverse(int unit, 
   2894                              bcm_flow_match_traverse_cb cb,
   2895                              void *user_data)
   2896 {
   2897     /* Indexes to iterate over memories, chunks and entries */
   2898     int             ent_idx;
   2899     int             buf_size, cfg_buf_size;
   2900     uint32          *trunk_map_tbl;
   2901     source_trunk_map_table_entry_t *entry;
   2902     bcm_module_t local_modid;
   2903     int mod_base;
   2904     bcm_flow_match_config_t *info;
   2905     uint32 port_type;
   2906     uint32 tgid;
   2907     uint32 svp;
   2908     int i,j,cnt;
   2909     int tid_found;
   2910     int rv = BCM_E_NONE;
   2911     soc_mem_t mem = SOURCE_TRUNK_MAP_TABLEm;
   2912     uint32 iif;
   2913     _bcm_flow_bookkeeping_t *flow_info;
   2914 
   2915     flow_info = FLOW_INFO(unit);
   2916 
   2917     if (!soc_mem_index_count(unit, mem)) {
   2918         return BCM_E_NONE;
   2919     }
   2920 
   2921     /* Get local module id. */
   2922     rv = bcm_esw_stk_my_modid_get(unit, &local_modid);
   2923     BCM_IF_ERROR_RETURN(rv);
   2924     rv = _bcm_esw_src_modid_base_index_get(unit,local_modid,TRUE,&mod_base);
   2925     BCM_IF_ERROR_RETURN(rv);
   2926 
   2927     /* validate the port index range */
   2928     if ((mod_base + SOC_MODPORT_MAX(unit)) > 
   2929                (soc_mem_index_max(unit, mem) + 1)) {
   2930         return BCM_E_PARAM;
   2931     }
   2932     buf_size = sizeof(source_trunk_map_table_entry_t) * SOC_MODPORT_MAX(unit);
   2933     trunk_map_tbl = soc_cm_salloc(unit, buf_size, 
   2934                                   "flow match trunk map traverse");
   2935     if (NULL == trunk_map_tbl) {
   2936         return BCM_E_MEMORY;
   2937     }
   2938 
   2939     /* allocate match config buffer */
   2940     cfg_buf_size  = sizeof(bcm_flow_match_config_t) * SOC_MODPORT_MAX(unit);
   2941     info = sal_alloc(cfg_buf_size, 
   2942                                   "flow match trunk map traverse config");
   2943     if (NULL == info) {
   2944         soc_cm_sfree(unit, trunk_map_tbl);
   2945         return BCM_E_MEMORY;
   2946     }
   2947 
   2948     sal_memset((void *)trunk_map_tbl, 0, buf_size);
   2949     sal_memset((void *)info, 0, cfg_buf_size);
   2950 
   2951     rv = soc_mem_read_range(unit, mem, MEM_BLOCK_ANY, mod_base, 
   2952                      mod_base + SOC_MODPORT_MAX(unit) - 1, trunk_map_tbl);
   2953     if (SOC_FAILURE(rv)) {
   2954         soc_cm_sfree(unit, trunk_map_tbl);
   2955         sal_free(info);
   2956         return BCM_E_MEMORY;
   2957     }
   2958     cnt = 0;
   2959     for (ent_idx = 0; ent_idx < SOC_MODPORT_MAX(unit); ent_idx ++) {
   2960         entry = soc_mem_table_idx_to_pointer(unit, mem, 
   2961                       source_trunk_map_table_entry_t *,
   2962                        trunk_map_tbl, ent_idx);
   2963         port_type = soc_mem_field32_get(unit, mem, entry, PORT_TYPEf);
   2964         tgid      = soc_mem_field32_get(unit, mem, entry, SRC_TGIDf);
   2965         svp       = soc_mem_field32_get(unit, mem, entry, SOURCE_VPf);
   2966         iif       = soc_mem_field32_get(unit, mem, entry, L3_IIFf);
   2967 
   2968         /* skip the entries not added by flow api */
   2969         if (flow_info->iif_ref_cnt[iif] || flow_info->vp_ref_cnt[svp]) {
   2970             if (port_type == 1) { /* trunk port type */
   2971                 BCM_GPORT_TRUNK_SET((info + cnt)->port,tgid);
   2972             } else {
   2973                 BCM_GPORT_MODPORT_SET((info + cnt)->port,local_modid,ent_idx);
   2974             }
   2975             _SHR_GPORT_FLOW_PORT_ID_SET((info + cnt)->flow_port,svp);
   2976             (info + cnt)->criteria = BCM_FLOW_MATCH_CRITERIA_PORT;
   2977             cnt++;
   2978         }
   2979     }
   2980 
   2981     /* invoke the callback functions on each entry */
   2982     for (i = 0; i < cnt; i++) {
   2983         /* skip the same trunk id */
   2984         tid_found = FALSE;
   2985         for (j = 0; j < i; j++) {
   2986             if (info[j].port == info[i].port) {
   2987                 tid_found = TRUE;
   2988                 break;
   2989             }
   2990         }
   2991         if (tid_found) {
   2992             continue;
   2993         }
   2994         rv = cb(unit,info + i,0,NULL,user_data);
   2995         if (BCM_FAILURE(rv)) {
   2996             soc_cm_sfree(unit, trunk_map_tbl);
   2997             sal_free(info);
   2998             return rv;
   2999         }
   3000     }       
   3001     
   3002     soc_cm_sfree(unit, trunk_map_tbl);
   3003     sal_free(info);
   3004     return rv;
   3005 }
   3006 
   3007 /*
   3008  * Function:
   3009  *      _bcm_flow_match_traverse_mem
   3010  * Purpose:
   3011  *      Read the given memory table and call the user callback function on 
   3012  *      each entry. 
   3013  * Parameters:
   3014  *      unit    - (IN) Device Number
   3015  *      mem     - (IN) the memory id
   3016  *      cb      - (IN) user callback function
   3017  *      user_data     - (IN) user context data
   3018  * Returns:
   3019  *      BCM_E_XXX
   3020  */
   3021 
   3022 STATIC int
   3023 _bcm_flow_match_traverse_mem(int unit, soc_mem_t mem,
   3024                              bcm_flow_match_traverse_cb cb,
   3025                              void *user_data)
   3026 {
   3027     /* Indexes to iterate over memories, chunks and entries */
   3028     int             chnk_idx, ent_idx, chnk_idx_max, mem_idx_max;
   3029     int             buf_size, chunksize, chnk_end;
   3030     /* Buffer to store chunk of table we currently work on */
   3031     uint32          *vt_tbl_chnk;
   3032     uint32          *entry;
   3033     int             valid, rv = BCM_E_NONE;
   3034     bcm_flow_match_config_t info;
   3035     uint32 num_of_fields = _BCM_FLOW_LOGICAL_FIELD_MAX;
   3036     bcm_flow_logical_field_t field[_BCM_FLOW_LOGICAL_FIELD_MAX];
   3037 
   3038     if (INVALIDm == mem) {
   3039         return BCM_E_MEMORY;
   3040     }
   3041     if (!soc_mem_index_count(unit, mem)) {
   3042         return BCM_E_NONE;
   3043     }
   3044 
   3045     chunksize = soc_property_get(unit, spn_VLANDELETE_CHUNKS,
   3046                                  VLAN_MEM_CHUNKS_DEFAULT);
   3047 
   3048     buf_size = 4 * SOC_MAX_MEM_FIELD_WORDS * chunksize;
   3049     vt_tbl_chnk = soc_cm_salloc(unit, buf_size, "flow match traverse");
   3050     if (NULL == vt_tbl_chnk) {
   3051         return BCM_E_MEMORY;
   3052     }
   3053 
   3054     mem_idx_max = soc_mem_index_max(unit, mem);
   3055     for (chnk_idx = soc_mem_index_min(unit, mem);
   3056          chnk_idx <= mem_idx_max;
   3057          chnk_idx += chunksize) {
   3058         sal_memset((void *)vt_tbl_chnk, 0, buf_size);
   3059 
   3060         chnk_idx_max =
   3061             ((chnk_idx + chunksize) <= mem_idx_max) ?
   3062             chnk_idx + chunksize - 1: mem_idx_max;
   3063 
   3064         rv = soc_mem_read_range(unit, mem, MEM_BLOCK_ANY,
   3065                                 chnk_idx, chnk_idx_max, vt_tbl_chnk);
   3066         if (SOC_FAILURE(rv)) {
   3067             break;
   3068         }
   3069         chnk_end = (chnk_idx_max - chnk_idx);
   3070         for (ent_idx = 0 ; ent_idx <= chnk_end; ent_idx ++) {
   3071             entry =
   3072                 soc_mem_table_idx_to_pointer(unit, mem, uint32 *,
   3073                                              vt_tbl_chnk, ent_idx);
   3074             rv = _bcm_flow_match_entry_valid(unit, mem, entry, &valid);
   3075             if (BCM_FAILURE(rv)) {
   3076                 break;
   3077             }
   3078             if (!valid) {
   3079                 continue;
   3080             }
   3081             bcm_flow_match_config_t_init(&info);
   3082             rv = _bcm_flow_match_entry_parse(unit, mem, entry, &info,
   3083                     &num_of_fields,field);
   3084             if (rv == BCM_E_NOT_FOUND) { /* for entries not exposed to user */
   3085                 continue;
   3086             } else if (BCM_FAILURE(rv)) {
   3087                 break;
   3088             }
   3089             rv = cb(unit, &info, num_of_fields,field,user_data);
   3090             if (BCM_FAILURE(rv)) {
   3091                 break;
   3092             }
   3093         }
   3094     }
   3095     soc_cm_sfree(unit, vt_tbl_chnk);
   3096     return rv;
   3097 }
   3098 
   3099 /*
   3100  * Function:
   3101  *      _bcm_flow_match_traverse_tcam
   3102  * Purpose:
   3103  *      Read the given memory table and call the user callback function on
   3104  *      each entry.
   3105  * Parameters:
   3106  *      unit    - (IN) Device Number
   3107  *      mem     - (IN) the memory id
   3108  *      cb      - (IN) user callback function
   3109  *      user_data     - (IN) user context data
   3110  * Returns:
   3111  *      BCM_E_XXX
   3112  */
   3113 
   3114 STATIC int
   3115 _bcm_flow_match_traverse_tcam(int unit, soc_mem_t mem,
   3116                              bcm_flow_match_traverse_cb cb,
   3117                              void *user_data)
   3118 {
   3119     /* Indexes to iterate over memories, chunks and entries */
   3120     int             idx,mem_idx_max;
   3121     int i;
   3122     uint32          entry[_QUAD_ENTRY_MAX];
   3123     int             valid, rv = BCM_E_NONE;
   3124     bcm_flow_match_config_t info;
   3125     uint32 num_of_fields = _BCM_FLOW_LOGICAL_FIELD_MAX;
   3126     bcm_flow_logical_field_t field[_BCM_FLOW_LOGICAL_FIELD_MAX];
   3127     soc_tunnel_term_t tnl_entry;
   3128     int entry_width = sizeof(tunnel_entry_t);
   3129     int mode;
   3130 
   3131     if (INVALIDm == mem) {
   3132         return BCM_E_MEMORY;
   3133     }
   3134 
   3135     idx = soc_mem_index_min(unit, mem);
   3136     mem_idx_max = soc_mem_index_max(unit, mem);
   3137     if ((idx < 0) || (mem_idx_max < 0)) {
   3138         return BCM_E_MEMORY;
   3139     }
   3140     while (idx <= mem_idx_max) {
   3141         rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, idx,
   3142                             (uint32 *)&tnl_entry.entry_arr[0]);
   3143         SOC_IF_ERROR_RETURN(rv);
   3144 
   3145         rv = _bcm_flow_match_entry_valid(unit, mem, 
   3146                     (uint32 *)&tnl_entry.entry_arr[0], &valid);
   3147         if (BCM_FAILURE(rv)) {
   3148             break;
   3149         }
   3150         if (!valid) {
   3151             idx++;
   3152             continue;
   3153         }
   3154         /* copy to the memory view format */
   3155         sal_memcpy(entry,&tnl_entry.entry_arr[0],entry_width);
   3156 
   3157         /* mode:
   3158          * 0 -- single wide
   3159          * 2 -- double wide
   3160          * 1 -- quad wide
   3161          */
   3162         mode = soc_mem_field32_get(unit, mem,
   3163                      (uint32 *)&tnl_entry.entry_arr[0], MODEf);
   3164 
   3165         if (mode == _BCM_FLOW_TD3_L3_TUNNEL_DOUBLE_WIDE) {
   3166             idx++;
   3167             rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, idx,
   3168                             (uint32 *)&tnl_entry.entry_arr[1]);
   3169             SOC_IF_ERROR_RETURN(rv);
   3170             sal_memcpy((uint8 *)entry + entry_width,
   3171                        &tnl_entry.entry_arr[1],entry_width);
   3172 
   3173         } else if (mode == _BCM_FLOW_TD3_L3_TUNNEL_QUAD_WIDE) {
   3174             for (i = 1; (i < COUNTOF(tnl_entry.entry_arr)) && 
   3175                         (i < SOC_TNL_TERM_ENTRY_WIDTH_QUAD); i++) {
   3176                 idx++;
   3177                 rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, idx,
   3178                             (uint32 *)&tnl_entry.entry_arr[i]);
   3179                 SOC_IF_ERROR_RETURN(rv);
   3180                 sal_memcpy((uint8 *)entry + entry_width * i,
   3181                        &tnl_entry.entry_arr[i],entry_width);
   3182             }
   3183         }
   3184         idx++;
   3185 
   3186         bcm_flow_match_config_t_init(&info);
   3187         rv = _bcm_flow_match_entry_parse(unit, mem, entry, &info,
   3188                     &num_of_fields,field);
   3189         if (rv == BCM_E_NOT_FOUND) { /* for entries not exposed to user */
   3190             continue;
   3191         } else if (BCM_FAILURE(rv)) {
   3192             break;
   3193         }
   3194         rv = cb(unit, &info, num_of_fields,field,user_data);
   3195         if (BCM_FAILURE(rv)) {
   3196             break;
   3197         }
   3198     }
   3199     return rv;
   3200 }
   3201 
   3202 /*
   3203  * Function:
   3204  *      bcmi_esw_flow_match_traverse
   3205  * Purpose:
   3206  *      Traverse flow match entries and call the user callback function on 
   3207  *      each entry. 
   3208  * Parameters:
   3209  *      unit    - (IN) Device Number
   3210  *      info    - (IN) Flow match config descriptor
   3211  *      num_of_fields - (IN) number of logical fields
   3212  *      field         - (IN) logical field array
   3213  *      cb            - (IN) user callback function
   3214  *      user_data     - (IN) user context data
   3215  * Returns:
   3216  *      BCM_E_XXX
   3217  */
   3218 
   3219 int bcmi_esw_flow_match_traverse(
   3220     int unit,
   3221     bcm_flow_match_traverse_cb cb,
   3222     void *user_data)
   3223 {
   3224     /* XXX remove info, num_of_fields, field parameters. Add option field
   3225      * to select traverse the port table or hash table: vxlate/mpls
   3226      */
   3227     soc_mem_t mem;
   3228     int rv;
   3229     _bcm_flow_bookkeeping_t *flow_info;
   3230 
   3231     if (cb == NULL) {
   3232         return BCM_E_PARAM;
   3233     }
   3234     flow_info = FLOW_INFO(unit);
   3235 
   3236     /* traverse the port table */
   3237     rv = _bcm_flow_match_trunk_mem_traverse(unit, cb, user_data);
   3238     BCM_IF_ERROR_RETURN(rv);
   3239    
   3240     /* traverse the vlan_xlate_1 first */
   3241     if (flow_info->mem_use_cnt[_BCM_FLOW_VXLT1_INX]) {
   3242         mem = VLAN_XLATE_1_DOUBLEm;
   3243         rv = _bcm_flow_match_traverse_mem(unit, mem, cb, user_data);
   3244         BCM_IF_ERROR_RETURN(rv);
   3245     }
   3246 
   3247     /* traverse the vlan_xlate_2 */
   3248     if (flow_info->mem_use_cnt[_BCM_FLOW_VXLT2_INX]) {
   3249         mem = VLAN_XLATE_2_DOUBLEm;
   3250         rv = _bcm_flow_match_traverse_mem(unit, mem, cb, user_data);
   3251         BCM_IF_ERROR_RETURN(rv);
   3252     }
   3253 
   3254     /* traverse the mpls_entry next */
   3255     if (flow_info->mem_use_cnt[_BCM_FLOW_MPLS_INX]) {
   3256         mem = MPLS_ENTRYm;
   3257         rv = _bcm_flow_match_traverse_mem(unit, mem, cb, user_data);
   3258         BCM_IF_ERROR_RETURN(rv);
   3259 
   3260         mem = MPLS_ENTRY_SINGLEm;
   3261         rv = _bcm_flow_match_traverse_mem(unit, mem, cb, user_data);
   3262         BCM_IF_ERROR_RETURN(rv);
   3263     }
   3264     
   3265     /* traverse the l3_tunnel  */
   3266     if (flow_info->mem_use_cnt[_BCM_FLOW_TNL_INX]) {
   3267         mem = L3_TUNNELm;
   3268         rv = _bcm_flow_match_traverse_tcam(unit, mem, cb, user_data);
   3269         BCM_IF_ERROR_RETURN(rv);
   3270     }
   3271     
   3272     return rv;
   3273 }
   3274 
   3275 /*
   3276  * Function:
   3277  *      bcmi_esw_flow_match_svp_replace
   3278  * Purpose:
   3279  *      replace SVP in a flow match
   3280  * Parameters:
   3281  *      unit    - (IN) Device Number
   3282  *      gport    - (IN) Flow gport
   3283  *      new_vp - (IN) new VP used to repalce
   3284  * Returns:
   3285  *      BCM_E_XXX
   3286  */
   3287 int bcmi_esw_flow_match_svp_replace(
   3288     int unit,
   3289     int gport,
   3290     int new_vp)
   3291 {
   3292     /* L3_TUNNELm could support 4 entry wide view definition */
   3293     uint32 entry[_QUAD_ENTRY_MAX];
   3294     int rv;
   3295     _bcm_flow_bookkeeping_t *flow_info;
   3296     int replaced_vp;
   3297     int vp;
   3298     soc_flow_db_mem_view_info_t view_info;
   3299     bcm_flow_match_vp_t* match_key;
   3300     bcm_flow_match_config_t *info;
   3301 
   3302     flow_info = FLOW_INFO(unit);
   3303 
   3304     /* validate the vp */
   3305     vp = _SHR_GPORT_FLOW_PORT_ID_GET(gport);
   3306     if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeFlow)) {
   3307         LOG_ERROR(BSL_LS_BCM_FLOW,
   3308               (BSL_META_U(unit, "flow port ID is not valid\n")));
   3309 
   3310         return BCM_E_PORT;
   3311     }
   3312 
   3313     match_key = &flow_info->match_key[vp];
   3314     info = sal_alloc(sizeof(*info),
   3315                             "flow match svp replace");
   3316     if (NULL == info) {
   3317         return BCM_E_MEMORY;
   3318     }
   3319     sal_memset(info, 0, sizeof(*info));
   3320     if (match_key->vlan) {
   3321         info->valid_elements |= BCM_FLOW_MATCH_VLAN_VALID;
   3322         info->vlan = match_key->vlan;
   3323     }
   3324     if (match_key->inner_vlan) {
   3325         info->valid_elements |= BCM_FLOW_MATCH_INNER_VLAN_VALID;
   3326         info->inner_vlan= match_key->inner_vlan;
   3327     }
   3328     if (match_key->port) {
   3329         info->valid_elements |= BCM_FLOW_MATCH_PORT_VALID;
   3330         info->port = match_key->port;
   3331     }
   3332     if (match_key->sip) {
   3333         info->valid_elements |= BCM_FLOW_MATCH_SIP_VALID;
   3334         info->sip = match_key->sip;
   3335     }
   3336     if (bcmi_flow_ip6_addr_is_valid(match_key->sip6)) {
   3337         info->valid_elements |= BCM_FLOW_MATCH_SIP_V6_VALID;
   3338         sal_memcpy(info->sip6, match_key->sip6, BCM_IP6_ADDRLEN);
   3339     }
   3340     info->criteria = match_key->criteria;
   3341     info->flow_handle = match_key->flow_handle;
   3342     info->flow_option = match_key->flow_option;
   3343 
   3344     _SHR_GPORT_FLOW_PORT_ID_SET(info->flow_port,new_vp);
   3345     info->valid_elements |= BCM_FLOW_MATCH_FLOW_PORT_VALID;
   3346     info->options = BCM_FLOW_MATCH_OPTION_REPLACE;
   3347 
   3348     /* port match doesn't use hash table */
   3349     if (info->criteria == BCM_FLOW_MATCH_CRITERIA_PORT) {
   3350         rv = _bcm_flow_match_port_ctrl(unit,info,
   3351                  _BCM_FLOW_MATCH_PORT_CTRL_SET,&replaced_vp,NULL);
   3352         if (SOC_FAILURE(rv)) {
   3353             sal_free(info);
   3354             return rv;
   3355         }
   3356         bcmi_esw_flow_lock(unit);
   3357         if (info->valid_elements & BCM_FLOW_MATCH_FLOW_PORT_VALID) {
   3358             vp = _SHR_GPORT_FLOW_PORT_ID_GET(info->flow_port);
   3359             if (vp) {
   3360                 flow_info->vp_ref_cnt[vp]++;
   3361             }
   3362             if (replaced_vp) {
   3363                 if (flow_info->vp_ref_cnt[replaced_vp]) {
   3364                     flow_info->vp_ref_cnt[replaced_vp]--;
   3365                 }
   3366             }
   3367         }
   3368         bcmi_esw_flow_unlock(unit);
   3369         sal_free(info);
   3370         return BCM_E_NONE;
   3371     }
   3372 
   3373     sal_memset(entry, 0, sizeof(entry));
   3374     rv = _bcm_flow_match_key_set(unit,info,NULL,
   3375                         0,entry,&view_info);
   3376     if (SOC_FAILURE(rv)) {
   3377         sal_free(info);
   3378         return rv;
   3379     }
   3380 
   3381     soc_mem_lock(unit,view_info.mem);
   3382     /* set the match object and attributes and write to memory */
   3383     rv = _bcm_flow_match_entry_set(unit,info,NULL,
   3384               0,
   3385               &view_info,
   3386                entry, NULL ,&replaced_vp);
   3387     soc_mem_unlock(unit,view_info.mem);
   3388 
   3389     bcmi_esw_flow_lock(unit);
   3390     if (BCM_SUCCESS(rv)) {
   3391         if (info->valid_elements & BCM_FLOW_MATCH_FLOW_PORT_VALID) {
   3392             vp = _SHR_GPORT_FLOW_PORT_ID_GET(info->flow_port);
   3393             flow_info->vp_ref_cnt[vp]++;
   3394             if (info->options & BCM_FLOW_MATCH_OPTION_REPLACE) {
   3395                 if (flow_info->vp_ref_cnt[replaced_vp]) {
   3396                     flow_info->vp_ref_cnt[replaced_vp]--;
   3397                 }
   3398             }
   3399         }
   3400     }
   3401     bcmi_esw_flow_unlock(unit);
   3402     sal_free(info);
   3403     return rv;
   3404 }
   3405 
   3406 /*
   3407  * Function:
   3408  *      bcmi_esw_flow_match_get
   3409  * Purpose:
   3410  *      get VP_LAG SVP from a flow match entry
   3411  * Parameters:
   3412  *      unit    - (IN) Device Number
   3413  *      gport    - (IN) Flow gport
   3414  *      vp_lag_vp - (IN) ptr of vp lag VP
   3415  * Returns:
   3416  *      BCM_E_XXX
   3417  */
   3418 
   3419 int bcmi_esw_flow_match_svp_get(
   3420     int unit,
   3421     bcm_gport_t gport,
   3422     int* vp_lag_vp)
   3423 {
   3424     _bcm_flow_bookkeeping_t *flow_info;
   3425     bcm_flow_match_vp_t* match_key;
   3426     bcm_flow_match_config_t *info;
   3427     int vp;
   3428     int rv;
   3429 
   3430     flow_info = FLOW_INFO(unit);
   3431 
   3432     /* validate the vp */
   3433     vp = _SHR_GPORT_FLOW_PORT_ID_GET(gport);
   3434     if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeFlow)) {
   3435         LOG_ERROR(BSL_LS_BCM_FLOW,
   3436               (BSL_META_U(unit, "flow port ID is not valid\n")));
   3437         return BCM_E_PORT;
   3438     }
   3439 
   3440     match_key = &flow_info->match_key[vp];
   3441     info = sal_alloc(sizeof(*info),
   3442                             "flow match svp get");
   3443     if (NULL == info) {
   3444         return BCM_E_MEMORY;
   3445     }
   3446     sal_memset(info, 0, sizeof(*info));
   3447     if (match_key->vlan) {
   3448         info->valid_elements |= BCM_FLOW_MATCH_VLAN_VALID;
   3449         info->vlan = match_key->vlan;
   3450     }
   3451     if (match_key->inner_vlan) {
   3452         info->valid_elements |= BCM_FLOW_MATCH_INNER_VLAN_VALID;
   3453         info->inner_vlan= match_key->inner_vlan;
   3454     }
   3455     if (match_key->port) {
   3456         info->valid_elements |= BCM_FLOW_MATCH_PORT_VALID;
   3457         info->port = match_key->port;
   3458     }
   3459     if (match_key->sip) {
   3460         info->valid_elements |= BCM_FLOW_MATCH_SIP_VALID;
   3461         info->sip = match_key->sip;
   3462     }
   3463     if (bcmi_flow_ip6_addr_is_valid(match_key->sip6)) {
   3464         info->valid_elements |= BCM_FLOW_MATCH_SIP_V6_VALID;
   3465         sal_memcpy(info->sip6, match_key->sip6, BCM_IP6_ADDRLEN);
   3466     }
   3467     info->criteria = match_key->criteria;
   3468     info->flow_handle = match_key->flow_handle;
   3469     info->flow_option = match_key->flow_option;
   3470 
   3471     rv = bcmi_esw_flow_match_get(unit, info, 0, NULL);
   3472     if (SOC_FAILURE(rv)) {
   3473         sal_free(info);
   3474         return rv;
   3475     }
   3476 
   3477     if (info->valid_elements & BCM_FLOW_MATCH_FLOW_PORT_VALID) {
   3478         *vp_lag_vp = _SHR_GPORT_FLOW_PORT_ID_GET(info->flow_port);
   3479     } else {
   3480         sal_free(info);
   3481         return BCM_E_NOT_FOUND;
   3482     }
   3483 
   3484     sal_free(info);
   3485     return BCM_E_NONE;
   3486 }
   3487 
   3488 
   3489 #endif  /* INCLUDE_L3 */
   3490