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_init.c (28665B)


      1 /*
      2  * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file.
      3  * 
      4  * Copyright 2007-2019 Broadcom Inc. All rights reserved.
      5  */
      6 
      7 
      8 #include <sal/core/libc.h>
      9 #if defined(INCLUDE_L3)
     10 
     11 #include <soc/drv.h>
     12 #include <soc/scache.h>
     13 #include <bcm/error.h>
     14 #include <bcm/module.h>
     15 #include <bcm_int/esw/trx.h>
     16 #include <bcm_int/esw/xgs5.h>
     17 #include <bcm_int/esw/flow.h>
     18 #include <bcm_int/esw/switch.h>
     19 #include <soc/esw/flow_db_core.h>
     20 #include <bcm_int/esw/virtual.h>
     21 
     22 _bcm_flow_bookkeeping_t   *_bcm_flow_bk_info[BCM_MAX_NUM_UNITS] = { 0 };
     23 
     24 #define VIRTUAL_INFO(_unit_)    (&_bcm_virtual_bk_info[_unit_])
     25 #define L3_INFO(_unit_)         (&_bcm_l3_bk_info[_unit_])
     26 
     27 /*
     28  * Function:
     29  *      _bcm_td3_flow_free_resource
     30  * Purpose:
     31  *      Free all allocated software resources 
     32  * Parameters:
     33  *      unit - SOC unit number
     34  * Returns:
     35  *      Nothing
     36  */
     37 
     38 STATIC void
     39 _bcm_td3_flow_free_resource(int unit)
     40 {
     41     _bcm_flow_bookkeeping_t *flow_info = FLOW_INFO(unit);
     42 
     43     /* If software tables were not allocated we are done. */ 
     44     if (NULL == FLOW_INFO(unit)) {
     45         return;
     46     }
     47 
     48     /* Destroy EGR_DVP_ATTRIBUTE usage bitmap  */
     49     if (flow_info->dvp_attr_bitmap) {
     50         sal_free(flow_info->dvp_attr_bitmap);
     51         flow_info->dvp_attr_bitmap = NULL;
     52     }
     53 
     54     /* Destroy soft init tunnel table   */
     55     if (flow_info->init_tunnel) {
     56         sal_free(flow_info->init_tunnel);
     57         flow_info->init_tunnel = NULL;
     58     }
     59 
     60     /* Destroy iif_ref_cnt table   */
     61     if (flow_info->iif_ref_cnt) {
     62         sal_free(flow_info->iif_ref_cnt);
     63         flow_info->iif_ref_cnt = NULL;
     64     }
     65 
     66     /* Destroy vp_ref_cnt table   */
     67     if (flow_info->vp_ref_cnt) {
     68         sal_free(flow_info->vp_ref_cnt);
     69         flow_info->vp_ref_cnt = NULL;
     70     }
     71 
     72 /*
     73     if (flow_info->flow_tunnel_term) {
     74         sal_free(flow_info->flow_tunnel_term);
     75         flow_info->flow_tunnel_term = NULL;
     76     }
     77 */
     78 
     79     if (flow_info->flow_vpn_vlan) {
     80         sal_free(flow_info->flow_vpn_vlan);
     81         flow_info->flow_vpn_vlan = NULL;
     82     }
     83 
     84     if (flow_info->match_key) {
     85         sal_free(flow_info->match_key);
     86         flow_info->match_key = NULL;
     87     }
     88 
     89     /* Free module data. */
     90     sal_free(FLOW_INFO(unit));
     91     FLOW_INFO(unit) = NULL;
     92 }
     93 /*
     94  * Function:
     95  *      bcm_td3_flow_allocate_bk
     96  * Purpose:
     97  *      Initialize FLOW software book-kepping
     98  * Parameters:
     99  *      unit     - Device Number
    100  * Returns:
    101  *      BCM_E_XXX
    102  */
    103 
    104 STATIC int
    105 bcm_td3_flow_allocate_bk(int unit)
    106 {
    107     /* Allocate/Init unit software tables. */
    108     if (NULL == FLOW_INFO(unit)) {
    109         BCM_TD3_FLOW_ALLOC(FLOW_INFO(unit), sizeof(_bcm_flow_bookkeeping_t),
    110                           "flow_bk_module_data");
    111         if (NULL == FLOW_INFO(unit)) {
    112             return (BCM_E_MEMORY);
    113         } else {
    114             FLOW_INFO(unit)->initialized = FALSE;
    115         }
    116     }
    117     return BCM_E_NONE;
    118 }
    119 
    120 /*
    121  * Function:
    122  *      _bcm_td3_flow_hw_clear
    123  * Purpose:
    124  *      Free all allocated hardware resources
    125  * Parameters:
    126  *      unit - SOC unit number
    127  * Returns:
    128  *      BCM_E_XXX
    129  */
    130 
    131 STATIC int
    132 _bcm_td3_flow_hw_clear(int unit)
    133 {
    134     int rv = BCM_E_NONE, rv1 = BCM_E_NONE;
    135 
    136     rv = bcmi_esw_flow_tunnel_terminator_destroy_all(unit);
    137     if (BCM_FAILURE(rv)) {
    138         rv1 = rv;
    139     }
    140 
    141     rv = bcmi_esw_flow_tunnel_initiator_destroy_all(unit);
    142     if (BCM_FAILURE(rv) && (BCM_E_NONE == rv1)) {
    143         rv1 = rv;
    144     }
    145 
    146     rv = bcmi_esw_flow_vpn_destroy_all(unit);
    147     if (BCM_FAILURE(rv) && (BCM_E_NONE == rv1)) {
    148         rv1 = rv;
    149     }
    150 
    151 
    152     return rv1;
    153 }
    154 
    155 #ifdef BCM_WARM_BOOT_SUPPORT
    156 
    157 #define BCM_WB_VERSION_1_0                SOC_SCACHE_VERSION(1, 0)
    158 #define BCM_WB_VERSION_2_0                SOC_SCACHE_VERSION(2, 0)
    159 #define BCM_WB_DEFAULT_VERSION            BCM_WB_VERSION_2_0
    160 
    161 STATIC int _bcm_flow_wb_alloc(int unit);
    162 
    163 /*
    164  * Function:
    165  *      _bcm_flow_wb_recover
    166  *
    167  * Purpose:
    168  *      Recover VXLAN module info for Level 2 Warm Boot from persisitent memory
    169  *
    170  * Warm Boot Version Map:
    171  *      see _bcm_esw_flow_sync definition
    172  *
    173  * Parameters:
    174  *      unit - (IN) Device Unit Number.
    175  *
    176  * Returns:
    177  *      BCM_E_XXX
    178  */
    179 STATIC int
    180 _bcm_flow_wb_recover(int unit)
    181 {
    182     int sz = 0, rv = BCM_E_NONE;
    183     int num_dvp = 0;
    184     int num_iif;
    185     int num_vp;
    186     int stable_size;
    187     uint16 recovered_ver = 0;
    188     uint8 *flow_scache_ptr = NULL;
    189     soc_scache_handle_t scache_handle;
    190     _bcm_flow_bookkeeping_t *flow_info;
    191     int num_soft_tnl = 0;
    192     int i;
    193     int additional_scache_size = 0;
    194 
    195     flow_info = FLOW_INFO(unit);
    196 
    197     SOC_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size));
    198 
    199     /* Requires extended scache support level-2 warmboot */
    200     if ((stable_size == 0) || (SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit))) {
    201         return BCM_E_NONE;
    202     }
    203     SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_FLOW, 0);
    204     rv = _bcm_esw_scache_ptr_get(unit, scache_handle, FALSE,
    205                                  0, &flow_scache_ptr,
    206                                  BCM_WB_DEFAULT_VERSION, &recovered_ver);
    207     if (BCM_FAILURE(rv) && (rv != BCM_E_NOT_FOUND)) {
    208         return rv;
    209     } else if (rv == BCM_E_NOT_FOUND) {
    210         return _bcm_flow_wb_alloc(unit);
    211     }
    212 
    213     if (flow_scache_ptr != NULL) {
    214         num_dvp = soc_mem_index_count(unit, EGR_DVP_ATTRIBUTEm);
    215         num_soft_tnl = num_dvp + soc_mem_index_count(unit, EGR_L3_INTFm);
    216         sz = sizeof(uint16);  /* idx of _bcm_flow_init_tunnel_entry_t */
    217 
    218         /* recover init_tunnel state */
    219         for (i = 0; i < num_soft_tnl; i++) {
    220             sal_memcpy(&flow_info->init_tunnel[i].idx, flow_scache_ptr, sz);
    221             flow_scache_ptr += sz;
    222         }
    223 
    224         /* recover the dvp_attr_bitmap */
    225         sz = SHR_BITALLOCSIZE(num_dvp);
    226         sal_memcpy(flow_info->dvp_attr_bitmap,flow_scache_ptr,sz);
    227         flow_scache_ptr += sz;
    228 
    229         num_iif = soc_mem_index_count(unit, L3_IIFm);
    230         sz =  sizeof(uint16);  /* iif_ref_cnt */
    231         for (i = 0; i < num_iif; i++) {
    232             sal_memcpy(&flow_info->iif_ref_cnt[i], flow_scache_ptr, sz);
    233             flow_scache_ptr += sz;
    234         }
    235 
    236         num_vp = soc_mem_index_count(unit, SOURCE_VPm);
    237         sz =  sizeof(uint16);  /* vp_ref_cnt */
    238         for (i = 0; i < num_vp; i++) {
    239             sal_memcpy(&flow_info->vp_ref_cnt[i], flow_scache_ptr, sz);
    240             flow_scache_ptr += sz;
    241         }
    242 
    243         /* recover the memory usage reference count table */
    244         sz = sizeof(uint32);                  
    245         for (i = 0; i < _BM_FLOW_MEM_USE_MAX; i++) {
    246             sal_memcpy(&flow_info->mem_use_cnt[i], flow_scache_ptr, sz);
    247             flow_scache_ptr += sz;
    248         }
    249 
    250         sz = sizeof(bcm_flow_match_vp_t);
    251         if (recovered_ver >= BCM_WB_VERSION_2_0) {
    252              for (i = 0; i < num_vp; i++) {
    253                 sal_memcpy(&flow_info->match_key[i], flow_scache_ptr, sz);
    254                 flow_scache_ptr += sz;
    255             }
    256         } else {
    257             additional_scache_size += num_vp * sz;
    258         }
    259 
    260         /* Reallocate additional scache size if current scache requirement
    261          * is more than the one recovered.
    262          */ 
    263         if (additional_scache_size > 0) {
    264             rv = soc_scache_realloc(unit,scache_handle,additional_scache_size);
    265             if(BCM_FAILURE(rv)) {
    266                return rv;
    267             }
    268         }
    269     }
    270     return BCM_E_NONE;
    271 }
    272 
    273 /*
    274  * Function:
    275  *      _bcm_flow_wb_alloc
    276  *
    277  * Purpose:
    278  *      Alloc persisitent memory for Level 2 Warm Boot scache.
    279  *
    280  * Parameters:
    281  *      unit - (IN) Device Unit Number.
    282  *
    283  * Returns:
    284  *      BCM_E_XXX
    285  */
    286 
    287 STATIC int
    288 _bcm_flow_wb_alloc(int unit)
    289 {
    290     int alloc_sz = 0, rv = BCM_E_NONE;
    291     soc_scache_handle_t scache_handle;
    292     int num_soft_tnl = 0, num_dvp = 0;
    293     uint8 *flow_scache_ptr = NULL;
    294     int stable_size;
    295     int num_iif;
    296     int num_vp;
    297 
    298     SOC_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size));
    299 
    300     if ((stable_size == 0) || (SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit))) {
    301         return BCM_E_NONE;
    302     }
    303 
    304     /* init tunnel entry table size */
    305     num_dvp = soc_mem_index_count(unit, EGR_DVP_ATTRIBUTEm);
    306     num_soft_tnl = num_dvp + soc_mem_index_count(unit, EGR_L3_INTFm);
    307     /* num_soft_tnl * idx of _bcm_flow_init_tunnel_entry_t */
    308     alloc_sz = num_soft_tnl * sizeof(uint16); 
    309 
    310     /* dvp_attr_bitmap size */
    311     alloc_sz += SHR_BITALLOCSIZE(num_dvp);
    312 
    313     /* iif_ref_cnt table size */
    314     num_iif = soc_mem_index_count(unit, L3_IIFm);
    315     /* num_iif * iif_ref_cnt */
    316     alloc_sz += num_iif * sizeof(uint16);
    317 
    318     /* vp_ref_cnt table size */
    319     num_vp = soc_mem_index_count(unit, SOURCE_VPm);
    320     /* num_vp * vp_ref_cnt */
    321     alloc_sz += num_vp * sizeof(uint16);
    322 
    323     /* mem_use_cnt table size */
    324     alloc_sz += _BM_FLOW_MEM_USE_MAX * sizeof(uint32);
    325 
    326     /*match_key array size from BCM_WB_VERSION_2_0*/
    327      alloc_sz += num_vp * sizeof(bcm_flow_match_vp_t);
    328 
    329     SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_FLOW, 0);
    330     rv = _bcm_esw_scache_ptr_get(unit, scache_handle, TRUE,
    331                                  alloc_sz, (uint8**)&flow_scache_ptr,
    332                                  BCM_WB_DEFAULT_VERSION, NULL);
    333     if (BCM_FAILURE(rv) && (rv != BCM_E_NOT_FOUND)) {
    334         return rv;
    335     }
    336 
    337     return BCM_E_NONE;
    338 }
    339 
    340 /*
    341  * Function:
    342  *      _bcm_flow_next_hop_refcnt_restore
    343  * Purpose:
    344  *      Recover the next hop egress object reference count increased by 
    345  * bcm_flow_port_encap_set when attaching the object to the flow port.
    346  * This routine is only used in warmboot.
    347  * 
    348  * Parameters:
    349  *      unit     - Device Number
    350  * Returns:
    351  *      BCM_E_XXX
    352  */
    353 STATIC int
    354 _bcm_flow_next_hop_refcnt_restore(int unit)
    355 {
    356     int num_vp;
    357     ing_dvp_table_entry_t dvp;
    358     int vp;
    359     int nh_index;
    360     int ecmp;
    361     int ecmp_index;
    362     int width;
    363 
    364     /* restore nextHop reference count set by flow_port_encap_set */
    365     num_vp = soc_mem_index_count(unit, EGR_DVP_ATTRIBUTEm);
    366     for (vp = 1; vp < num_vp; vp++) {
    367         if (_BCM_FLOW_EGR_DVP_USED_GET(unit,vp)) {
    368             SOC_IF_ERROR_RETURN(READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY,
    369                                 vp, &dvp));
    370             nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp,
    371                                                   NEXT_HOP_INDEXf);
    372             ecmp = soc_ING_DVP_TABLEm_field32_get(unit, &dvp,
    373                                                   ECMPf);
    374             ecmp_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, ECMP_PTRf);
    375             if (ecmp) {
    376                 width = BCM_XGS3_L3_MAX_ECMP_MODE(unit) ?
    377                       _BCM_SINGLE_WIDE : _BCM_DOUBLE_WIDE;
    378 
    379                 /* increment ecmp group reference count. */
    380                 BCM_XGS3_L3_ENT_REF_CNT_INC
    381                     (BCM_XGS3_L3_TBL_PTR(unit, ecmp_grp), ecmp_index, width);
    382 
    383             } else if (nh_index) {
    384                 BCM_XGS3_L3_ENT_REF_CNT_INC(BCM_XGS3_L3_TBL_PTR(unit, next_hop),
    385                       nh_index, _BCM_SINGLE_WIDE);
    386 
    387             }
    388         }
    389     }
    390     return BCM_E_NONE;
    391 }
    392 
    393 STATIC int
    394 _bcm_flow_encap_traverse_cb_tpid_refcnt(int unit,
    395         bcm_flow_encap_config_t *info, uint32 num_of_fields,
    396         bcm_flow_logical_field_t *field,
    397         void *user_data)
    398 {
    399     int rv;
    400     int tpid_inx;
    401 
    402     if (info->flags & (BCM_FLOW_ENCAP_FLAG_SERVICE_VLAN_TPID_REPLACE |
    403                        BCM_FLOW_ENCAP_FLAG_VLAN_PRI_TPID_REPLACE |
    404                        BCM_FLOW_ENCAP_FLAG_TPID_REPLACE |
    405                        BCM_FLOW_ENCAP_FLAG_SERVICE_VLAN_ADD) ) {
    406         /* tpid reference count */
    407         if (info->flags & _BCM_FLOW_ENCAP_FLAG_TPID_INDEX) {
    408             tpid_inx = info->tpid;
    409             (void)_bcm_fb2_outer_tpid_tab_ref_count_add(unit,tpid_inx,1);
    410         } else if (info->tpid) {
    411             rv = _bcm_fb2_outer_tpid_lkup(unit,info->tpid, &tpid_inx);
    412             if (BCM_SUCCESS(rv)) {
    413                (void)_bcm_fb2_outer_tpid_tab_ref_count_add(unit,tpid_inx,1);
    414             }
    415         }
    416     }
    417     return BCM_E_NONE;
    418 }
    419 /*
    420  * Function:
    421  *    _bcm_flow_egr_mac_da_restore
    422  * Purpose:
    423  *    WB recovery for egr mac da profile ref count
    424  * Parameters:
    425  *    unit           - (IN) Device Number
    426  *    ecmp_nh_index - (IN) ecmp group number
    427  * Returns:
    428  *    BCM_E_XXX
    429  */
    430 STATIC int
    431 _bcm_flow_egr_mac_da_restore(int unit)
    432 {
    433     int min, max, i;
    434     soc_mem_t mem;
    435     uint32 view_id;
    436     uint32 data_type = 0;
    437     soc_flow_db_ctrl_field_t field_list;
    438     uint32 l3_if_entry[SOC_MAX_MEM_WORDS];
    439     int num_fields = 0;
    440     int rv = BCM_E_NONE;
    441 
    442     sal_memset(&l3_if_entry, 0, sizeof(l3_if_entry));
    443 
    444     mem = BCM_XGS3_L3_MEM(unit, intf);
    445     min = soc_mem_index_min(unit, mem);
    446     max = soc_mem_index_max(unit, mem);
    447 
    448     for (i = min; i < max; i++) {
    449          BCM_IF_ERROR_RETURN
    450              (BCM_XGS3_MEM_READ(unit, mem, i, &l3_if_entry));
    451 
    452          if (SOC_MEM_FIELD_VALID(unit, mem, DATA_TYPEf)) {
    453              data_type = soc_mem_field32_get(unit, mem, &l3_if_entry, DATA_TYPEf);
    454          }
    455 
    456          if (data_type == 0) {
    457             continue;
    458          }
    459 
    460          if(soc_mem_field_valid(unit, mem, FLOW_SELECT_CTRL_IDf)) {
    461              field_list.field_id = FLOW_SELECT_CTRL_IDf;
    462              field_list.value = soc_mem_field32_get(unit, mem,
    463                  &l3_if_entry, FLOW_SELECT_CTRL_IDf);
    464              num_fields = 1;
    465          }
    466          /* coverity[callee_ptr_arith : FALSE] */
    467          rv = soc_flow_db_mem_to_view_id_get(unit,
    468                  mem,
    469                  SOC_FLOW_DB_KEY_TYPE_INVALID,
    470                  data_type,
    471                  num_fields,
    472                  &field_list,
    473                  &view_id);
    474 
    475         /* Recover MAC_DA profile count */
    476         if ((rv == BCM_E_NONE) && soc_mem_field_valid(unit, view_id,
    477              PROFILED_ASSIGNMENT_SRC_MAC_ADDRESS_ACTION_SETf)) {
    478 
    479             uint32 macda_idx;
    480 
    481             macda_idx = soc_mem_field32_get(unit, view_id, &l3_if_entry,
    482                 PROFILED_ASSIGNMENT_SRC_MAC_ADDRESS_ACTION_SETf);
    483 
    484             _bcm_common_profile_mem_ref_cnt_update(
    485                     unit, EGR_MAC_DA_PROFILEm, macda_idx, 1);
    486         }
    487     }
    488 
    489     return rv;
    490 }
    491 /*
    492  * Function:
    493  *      _bcm_flow_reinit
    494  * Purpose:
    495  *      Warm boot recovery for the VXLAN software module
    496  * Parameters:
    497  *      unit     - Device Number
    498  * Returns:
    499  *      BCM_E_XXX
    500  */
    501 STATIC int
    502 _bcm_flow_reinit(int unit)
    503 {
    504     int rv = BCM_E_NONE;
    505 
    506     /* Tunnel initiator hash and ref-count recovery */
    507     rv = _bcm_flow_tunnel_initiator_reinit(unit);
    508     if (BCM_FAILURE(rv)) {
    509         return rv;
    510     }
    511 
    512     /* Recover L2 scache */
    513     rv = _bcm_flow_wb_recover(unit);
    514     BCM_IF_ERROR_RETURN(rv);
    515 
    516     /* increase the used next hop object reference count */
    517     rv = _bcm_flow_next_hop_refcnt_restore(unit);
    518     BCM_IF_ERROR_RETURN(rv);
    519 
    520     /* increase the used egr mac da reference count */
    521     rv = _bcm_flow_egr_mac_da_restore(unit);
    522     BCM_IF_ERROR_RETURN(rv);
    523 
    524     /* traverse egress adaptation tables to recover the tpid reference count */
    525     rv = bcmi_esw_flow_encap_traverse(0,
    526                     _bcm_flow_encap_traverse_cb_tpid_refcnt,NULL);
    527     BCM_IF_ERROR_RETURN(rv);
    528 
    529     return rv;
    530 }
    531 
    532 /*
    533  * Function:
    534  *      _bcm_esw_flow_sync
    535  *
    536  * Purpose:
    537  *      Record flow module persistent info for Level 2 Warm Boot
    538  *
    539  * Warm Boot Version Map:
    540  *  WB_VERSION_1_0
    541 * Parameters:
    542  *      unit - (IN) Device Unit Number.
    543  *
    544  * Returns:
    545  *      BCM_E_XXX
    546  */
    547 
    548 int
    549 _bcm_esw_flow_sync(int unit)
    550 {
    551     int sz = 0, rv = BCM_E_NONE;
    552     int num_soft_tnl = 0, num_dvp = 0;
    553     int stable_size;
    554     uint8 *flow_scache_ptr = NULL;
    555     soc_scache_handle_t scache_handle;
    556     _bcm_flow_bookkeeping_t *flow_info;
    557     int num_iif;
    558     int num_vp;
    559     int i;
    560 
    561     if (!soc_feature(unit, soc_feature_flex_flow)) {
    562         return BCM_E_UNAVAIL;
    563     }
    564 
    565     /* Parameter validation checks */
    566     if (!SOC_UNIT_VALID(unit)) {
    567         return BCM_E_UNIT;
    568     }
    569     BCM_IF_ERROR_RETURN(bcmi_esw_flow_check_init(unit));
    570 
    571     flow_info = FLOW_INFO(unit);
    572 
    573     SOC_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size));
    574 
    575     /* Requires extended scache support level-2 warmboot */
    576     if ((stable_size == 0) || (SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit))) {
    577         return BCM_E_NONE;
    578     }
    579 
    580     SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_FLOW, 0);
    581     rv = _bcm_esw_scache_ptr_get(unit, scache_handle, FALSE,
    582                                  0, &flow_scache_ptr,
    583                                  BCM_WB_DEFAULT_VERSION, NULL);
    584     if (BCM_FAILURE(rv) && (rv != BCM_E_INTERNAL)) {
    585         return rv;
    586     }
    587 
    588     num_dvp = soc_mem_index_count(unit, EGR_DVP_ATTRIBUTEm);
    589     num_soft_tnl = num_dvp + soc_mem_index_count(unit, EGR_L3_INTFm);
    590 
    591     /* save init_tunnel entry table */
    592     sz = sizeof(uint16); /* idx of _bcm_flow_init_tunnel_entry_t */
    593     for (i = 0; i < num_soft_tnl; i++) {
    594         sal_memcpy(flow_scache_ptr,&flow_info->init_tunnel[i].idx, sz);
    595         flow_scache_ptr += sz;
    596     }
    597 
    598     /* save the dvp_attr_bitmap */
    599     sz = SHR_BITALLOCSIZE(num_dvp);
    600     sal_memcpy(flow_scache_ptr, flow_info->dvp_attr_bitmap, sz);
    601     flow_scache_ptr += sz;
    602 
    603     /* save iif_ref_cnt table */
    604     num_iif = soc_mem_index_count(unit, L3_IIFm);
    605     sz = sizeof(uint16); /* iif_ref_cnt */ 
    606     for (i = 0; i < num_iif; i++) {
    607         sal_memcpy(flow_scache_ptr,&flow_info->iif_ref_cnt[i], sz);
    608         flow_scache_ptr += sz;
    609     }
    610 
    611     /* save vp_ref_cnt table */
    612     num_vp = soc_mem_index_count(unit, SOURCE_VPm);
    613     sz = sizeof(uint16); /* vp_ref_cnt */ 
    614     for (i = 0; i < num_vp; i++) {
    615         sal_memcpy(flow_scache_ptr,&flow_info->vp_ref_cnt[i], sz);
    616         flow_scache_ptr += sz;
    617     }
    618 
    619     /* save the memory usage reference count table */
    620     sz = sizeof(uint32);  
    621     for (i = 0; i < _BM_FLOW_MEM_USE_MAX; i++) {
    622         sal_memcpy(flow_scache_ptr,&flow_info->mem_use_cnt[i], sz);
    623         flow_scache_ptr += sz;
    624     }
    625 
    626     /* save match_key array */
    627     sz = sizeof(bcm_flow_match_vp_t);
    628     for (i = 0; i < num_vp; i++) {
    629         sal_memcpy(flow_scache_ptr,&flow_info->match_key[i], sz);
    630         flow_scache_ptr += sz;
    631     }
    632  
    633     return rv;
    634 }
    635 
    636 #endif /* BCM_WARM_BOOT_SUPPORT */
    637 
    638 /*
    639  * Function:
    640  *      bcmi_esw_flow_init
    641  * Purpose:
    642  *      Initialize the FLOW software module
    643  * Parameters:
    644  *      unit     - Device Number
    645  * Returns:
    646  *      BCM_E_XXX
    647  */
    648 int
    649 bcmi_esw_flow_init(int unit)
    650 {
    651     _bcm_flow_bookkeeping_t *flow_info;
    652     int num_dvp; 
    653     int rv = BCM_E_NONE;
    654     int num_vfi = 0;
    655     int num_tnl;
    656     int num_iif;
    657     int num_vp;
    658     uint64 rval;
    659 
    660     if (!L3_INFO(unit)->l3_initialized) {
    661         LOG_ERROR(BSL_LS_BCM_FLOW,
    662                   (BSL_META_U(unit,
    663                               "L3 module must be initialized prior to FLOW Init\n")));
    664         return BCM_E_CONFIG;
    665     }
    666 
    667     if (BCM_FAILURE(soc_flow_db_status_get(unit))) {
    668         return BCM_E_INIT;
    669     }
    670     /* Allocate BK Info */
    671     BCM_IF_ERROR_RETURN(bcm_td3_flow_allocate_bk(unit));
    672     flow_info = FLOW_INFO(unit);
    673 
    674     /*
    675      * allocate resources
    676      */
    677     if (flow_info->initialized) {
    678          BCM_IF_ERROR_RETURN(bcmi_esw_flow_cleanup(unit));
    679          BCM_IF_ERROR_RETURN(bcm_td3_flow_allocate_bk(unit));
    680          flow_info = FLOW_INFO(unit);
    681     }
    682 
    683     /* Create EGR_DVP_ATTRIBUTEm usage bitmap */
    684     num_dvp = soc_mem_index_count(unit, EGR_DVP_ATTRIBUTEm);
    685 
    686     flow_info->dvp_attr_bitmap =
    687         sal_alloc(SHR_BITALLOCSIZE(num_dvp), "dvp_attr_bitmap");
    688     if (flow_info->dvp_attr_bitmap == NULL) {
    689         _bcm_td3_flow_free_resource(unit);
    690         return BCM_E_MEMORY;
    691     }
    692     sal_memset(flow_info->dvp_attr_bitmap, 0, SHR_BITALLOCSIZE(num_dvp));
    693 
    694     /* Create soft tunnel index table  */
    695     /* L2 tunnel associated with dvp, dvp represents the soft tunnnel index */
    696     num_tnl = soc_mem_index_count(unit, EGR_DVP_ATTRIBUTEm);
    697 
    698     /* L3 tunnel associated with egr_intf, soft tunnel index: 
    699      * max l2 tunnel + EGR_L3_INTFm index. 
    700      */
    701     num_tnl += soc_mem_index_count(unit, EGR_L3_INTFm);
    702     flow_info->init_tunnel =
    703         sal_alloc(sizeof(_bcm_flow_init_tunnel_entry_t) * num_tnl, 
    704                   "flow_init_tunnel");
    705     if (flow_info->init_tunnel == NULL) {
    706         _bcm_td3_flow_free_resource(unit);
    707         return BCM_E_MEMORY;
    708     }
    709     sal_memset(flow_info->init_tunnel, 0, 
    710                sizeof(_bcm_flow_init_tunnel_entry_t) * num_tnl);
    711 
    712     /* Create iif_ref_cnt table */
    713     num_iif = soc_mem_index_count(unit, L3_IIFm);
    714     flow_info->iif_ref_cnt =
    715         sal_alloc(sizeof(uint16) * num_iif,
    716                   "flow_match iif_ref_cnt");
    717     if (flow_info->iif_ref_cnt == NULL) {
    718         _bcm_td3_flow_free_resource(unit);
    719         return BCM_E_MEMORY;
    720     }
    721     sal_memset(flow_info->iif_ref_cnt, 0,
    722                sizeof(uint16) * num_iif);
    723 
    724     /* Create vp_ref_cnt table */
    725     num_vp = soc_mem_index_count(unit, SOURCE_VPm);
    726     flow_info->vp_ref_cnt =
    727         sal_alloc(sizeof(uint16) * num_vp,
    728                   "flow_match vp_ref_cnt");
    729     if (flow_info->vp_ref_cnt == NULL) {
    730         _bcm_td3_flow_free_resource(unit);
    731         return BCM_E_MEMORY;
    732     }
    733     sal_memset(flow_info->vp_ref_cnt, 0,
    734                sizeof(uint16) * num_vp);
    735 
    736     flow_info->match_key =
    737         sal_alloc(sizeof(bcm_flow_match_vp_t) * num_vp,
    738                   "flow_match match_key");
    739     if (flow_info->match_key == NULL) {
    740         _bcm_td3_flow_free_resource(unit);
    741         return BCM_E_MEMORY;
    742     }
    743     sal_memset(flow_info->match_key, 0,
    744                sizeof(bcm_flow_match_vp_t) * num_vp);
    745 
    746     rv = READ_EGR_SEQUENCE_NUMBER_CTRLr(unit, &rval);
    747     if (SOC_FAILURE(rv)) {
    748          _bcm_td3_flow_free_resource(unit);
    749          return rv;
    750     }
    751     flow_info->frag_base_inx = soc_reg64_field32_get(unit, 
    752              EGR_SEQUENCE_NUMBER_CTRLr, rval, EGR_IP_TUNNEL_OFFSET_BASEf);
    753 
    754     /* Create FLOW protection mutex. */
    755     flow_info->flow_mutex = sal_mutex_create("flow_mutex");
    756     if (!flow_info->flow_mutex) {
    757          _bcm_td3_flow_free_resource(unit);
    758          return BCM_E_MEMORY;
    759     }
    760 
    761 #if 0
    762     if (NULL == flow_info->flow_tunnel_term) {
    763         flow_info->flow_tunnel_term =
    764             sal_alloc(sizeof(_bcm_vxlan_tunnel_endpoint_t) * num_vp, "flow tunnel term store");
    765         if (flow_info->flow_tunnel_term == NULL) {
    766             _bcm_td3_flow_free_resource(unit);
    767             return BCM_E_MEMORY;
    768         }
    769         sal_memset(flow_info->flow_tunnel_term, 0, 
    770                 sizeof(_bcm_vxlan_tunnel_endpoint_t) * num_vp);
    771     }
    772 
    773 #endif
    774 
    775     num_vfi = soc_mem_index_count(unit, VFIm);
    776     if (NULL == flow_info->flow_vpn_vlan) {
    777         flow_info->flow_vpn_vlan =
    778             sal_alloc(sizeof(bcm_vlan_t) * num_vfi, "flow vpn vlan store");
    779         if (flow_info->flow_vpn_vlan == NULL) {
    780             _bcm_td3_flow_free_resource(unit);
    781             return BCM_E_MEMORY;
    782         }
    783         sal_memset(flow_info->flow_vpn_vlan, 0, sizeof(bcm_vlan_t) * num_vfi);
    784     }
    785 
    786 #ifdef BCM_WARM_BOOT_SUPPORT
    787     if (SOC_WARM_BOOT(unit)) {
    788         rv = _bcm_flow_reinit(unit);
    789         if (BCM_FAILURE(rv)) {
    790             _bcm_td3_flow_free_resource(unit);
    791         }
    792     } else {
    793         rv = _bcm_flow_wb_alloc(unit);
    794 
    795         if (BCM_SUCCESS(rv) &&
    796             soc_property_get(unit, spn_IP6_VXLAN_MSHG_ENABLE, 0)) {
    797             bcmi_esw_flow_mshg_prune_egress_init(unit);
    798         }
    799     }
    800 #endif /* BCM_WARM_BOOT_SUPPORT */
    801 
    802     /* Mark the state as initialized */
    803     flow_info->initialized = TRUE;
    804 
    805     return rv;
    806 }
    807 
    808 /*
    809  * Function:
    810  *      bcmi_esw_flow_check_init
    811  * Purpose:
    812  *      Check if FLOW is initialized
    813  * Parameters:
    814  *      unit     - Device Number
    815  * Returns:
    816  *      BCM_E_XXX
    817  */
    818 
    819 int
    820 bcmi_esw_flow_check_init(int unit)
    821 {
    822     _bcm_flow_bookkeeping_t *flow_info;
    823 
    824     if ((unit < 0) || (unit >= BCM_MAX_NUM_UNITS)) {
    825          return BCM_E_UNIT;
    826     }
    827 
    828     flow_info = FLOW_INFO(unit);
    829 
    830     if ((flow_info == NULL) || (flow_info->initialized == FALSE)) {
    831          return BCM_E_INIT;
    832     } else {
    833          return BCM_E_NONE;
    834     }
    835 }
    836 
    837 /*
    838  * Function:
    839  *      bcmi_esw_flow_cleanup
    840  * Purpose:
    841  *      DeInit  FLOW software module
    842  * Parameters:
    843  *      unit     - Device Number
    844  * Returns:
    845  *      BCM_E_XXX
    846  */
    847 
    848 int
    849 bcmi_esw_flow_cleanup(int unit)
    850 {
    851     _bcm_flow_bookkeeping_t *flow_info;
    852     int rv = BCM_E_UNAVAIL;
    853 
    854     if ((unit < 0) || (unit >= BCM_MAX_NUM_UNITS)) {
    855          return BCM_E_UNIT;
    856     }
    857 
    858     flow_info = FLOW_INFO(unit);
    859 
    860     if (FALSE == flow_info->initialized) {
    861         return (BCM_E_NONE);
    862     } 
    863 
    864     rv = bcmi_esw_flow_lock (unit);
    865     if (BCM_FAILURE(rv)) {
    866         return rv;
    867     }
    868 
    869     if (0 == SOC_HW_ACCESS_DISABLE(unit)) { 
    870         rv = _bcm_td3_flow_hw_clear(unit);
    871     }
    872 
    873     /* Mark the state as uninitialized */
    874     flow_info->initialized = FALSE;
    875 
    876     sal_mutex_give(flow_info->flow_mutex);
    877 
    878     /* Destroy protection mutex. */
    879     sal_mutex_destroy(flow_info->flow_mutex );
    880 
    881     /* Free software resources */
    882     (void) _bcm_td3_flow_free_resource(unit);
    883 
    884     return rv;
    885 }
    886 
    887 /*
    888  * Function:
    889  *      bcmi_esw_flow_lock
    890  * Purpose:
    891  *      Take FLOW Lock Sempahore
    892  * Parameters:
    893  *      unit     - Device Number
    894  * Returns:
    895  *      BCM_E_XXX
    896  */
    897 
    898  int 
    899  bcmi_esw_flow_lock(int unit)
    900 {
    901    int rv=BCM_E_NONE;
    902 
    903    rv = bcmi_esw_flow_check_init(unit);
    904    
    905    if ( rv == BCM_E_NONE ) {
    906            sal_mutex_take(FLOW_INFO((unit))->flow_mutex, sal_mutex_FOREVER);
    907    }
    908    return rv; 
    909 }
    910 
    911 /*
    912  * Function:
    913  *      bcmi_esw_flow_unlock
    914  * Purpose:
    915  *      Release  FLOW Lock Semaphore
    916  * Parameters:
    917  *      unit     - Device Number
    918  * Returns:
    919  *      BCM_E_XXX
    920  */
    921 
    922 
    923 void
    924 bcmi_esw_flow_unlock(int unit)
    925 {
    926    int rv=BCM_E_NONE;
    927 
    928    rv = bcmi_esw_flow_check_init(unit);
    929     if ( rv == BCM_E_NONE ) {
    930          sal_mutex_give(FLOW_INFO((unit))->flow_mutex);
    931     }
    932 }
    933 
    934 #ifdef BCM_WARM_BOOT_SUPPORT_SW_DUMP
    935 STATIC
    936 void _bcmi_esw_flow_sw_dump(int unit)
    937 {
    938     int num_dvp = 0;
    939     int num_iif = 0;
    940     int num_vp  = 0;
    941     int num_vfi = 0;
    942     int num_soft_tnl = 0;
    943     _bcm_flow_bookkeeping_t *flow_info = NULL;
    944     int i = 0;
    945     uint16 flag = FALSE;
    946 
    947     flow_info = FLOW_INFO(unit);
    948 
    949     num_dvp = soc_mem_index_count(unit, EGR_DVP_ATTRIBUTEm);
    950     num_soft_tnl = num_dvp + soc_mem_index_count(unit, EGR_L3_INTFm);
    951     num_vp = soc_mem_index_count(unit, SOURCE_VPm);
    952     num_iif = soc_mem_index_count(unit, L3_IIFm);
    953     num_vfi = soc_mem_index_count(unit, VFIm);
    954 
    955     for (i = 0, flag = FALSE; i < num_vfi; i++) {
    956         if (VIRTUAL_INFO(unit)->flow_vfi_bitmap) {
    957             if (SHR_BITGET(VIRTUAL_INFO(unit)->flow_vfi_bitmap, i)) {
    958                 if (flag == TRUE) {
    959                     LOG_CLI((BSL_META_U(unit," , %d"), i));
    960                 } else {
    961                     LOG_CLI((BSL_META_U(unit,
    962                       "%-32s : %d \n"),"Flow VFI", i));
    963                 }
    964                 flag = TRUE;
    965             }
    966         }
    967     }
    968 
    969     for (i = 0, flag = FALSE; i < num_vp; i++) {
    970         if (VIRTUAL_INFO(unit)->flow_vp_bitmap) {
    971             if (SHR_BITGET(VIRTUAL_INFO(unit)->flow_vp_bitmap, i)) {
    972                 if (flag == TRUE) {
    973                     LOG_CLI((BSL_META_U(unit," , %d"), i));
    974                 } else {
    975                     LOG_CLI((BSL_META_U(unit,
    976                          "\n%-32s : %d"), "Flow VP", i));
    977                 }
    978                 flag = TRUE;
    979             }
    980         }
    981     }
    982 
    983     for (i = 0, flag = FALSE; i < num_soft_tnl; i++) {
    984         if(flow_info->init_tunnel[i].idx) {
    985             if (flag == TRUE) {
    986                 LOG_CLI((BSL_META_U(unit," , %d"), i));
    987             } else {
    988                 LOG_CLI((BSL_META_U(unit,
    989                     "\n%-32s : %d"),
    990                     "init_tunnel soft index",
    991                     num_soft_tnl));
    992             }
    993             flag = TRUE;
    994         }
    995     }
    996 
    997     LOG_CLI((BSL_META_U(unit,
    998              "\n%-32s : 0x%x"),
    999              "DVP Attribute bitmap",*flow_info->dvp_attr_bitmap));
   1000 
   1001     for (i = 0; i < num_iif;  i++) {
   1002         if (flow_info->iif_ref_cnt[i]) {
   1003             LOG_CLI((BSL_META_U(unit,
   1004                  "\n %-10s : %d, %-14s : %d"),
   1005                  "IIF index", i, "IIF use count", flow_info->iif_ref_cnt[i]));
   1006         }
   1007     }
   1008 
   1009     for (i = 0; i < num_vp; i++) {
   1010         if (flow_info->vp_ref_cnt[i]) {
   1011             LOG_CLI((BSL_META_U(unit,
   1012                  "\n%-10s : %d,  %-14s : %d"),
   1013                  "VP index", i, "VP use count", flow_info->vp_ref_cnt[i]));
   1014         }
   1015     }
   1016 
   1017     LOG_CLI((BSL_META_U(unit,"\n")));
   1018     return;
   1019 }
   1020 /*
   1021  * Function:
   1022  *     bcmi_esw_flow_sw_dump
   1023  * Purpose:
   1024  *     Displays flow information maintained by software.
   1025  * Parameters:
   1026  *     unit - Device unit number
   1027  * Returns:
   1028  *     None
   1029  */
   1030 void
   1031 bcmi_esw_flow_sw_dump(int unit)
   1032 {
   1033     if (soc_feature(unit, soc_feature_flex_flow)) {
   1034         _bcmi_esw_flow_sw_dump(unit);
   1035     }
   1036     return;
   1037 }
   1038 #endif /* BCM_WARM_BOOT_SUPPORT_SW_DUMP */
   1039 
   1040 #endif