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

alpm_wb.c (38509B)


      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  * File:    alpm_wb.c
      7  * Purpose: ALPM warmboot and update match
      8  */
      9 
     10 #include <shared/bsl.h>
     11 
     12 #include <soc/mem.h>
     13 #include <soc/drv.h>
     14 #include <soc/debug.h>
     15 #include <soc/error.h>
     16 #include <soc/format.h>
     17 #include <soc/lpm.h>
     18 #include <soc/trident2.h>
     19 #include <soc/tomahawk.h>
     20 #include <shared/bsl.h>
     21 
     22 #include <shared/util.h>
     23 #include <shared/l3.h>
     24 
     25 #if defined(ALPM_ENABLE)
     26 
     27 #include <bcm/l3.h>
     28 #include <bcm_int/esw/l3.h>
     29 #include <bcm_int/esw/firebolt.h>
     30 #include <bcm_int/esw/alpm.h>
     31 #include <bcm_int/esw/alpm_util.h>
     32 
     33 typedef struct alpm_def_rte_info_s {
     34     int vrf_id;
     35     int ipt;
     36     int bkt_idx;
     37     _alpm_bkt_adata_t adata;
     38 } alpm_def_rte_info_t;
     39 
     40 typedef struct _alpm_pfx_update_match_s {
     41     int unit;
     42     int vrf_id;
     43     int ipt;
     44     int *def_rte_cnt;
     45     alpm_def_rte_info_t *def_rte;
     46     _bcm_l3_trvrs_data_t *trv_data;
     47 } _alpm_pfx_update_match_t;
     48 
     49 extern int tcam_wb_reinit(int u, int vrf_id, int pkm, int idx, int key_len, int mc);
     50 extern int tcam_wb_reinit_done(int u);
     51 extern int alpm_vrf_deinit(int u, int vrf_id, int ipt);
     52 
     53 STATIC int
     54 alpm_pvt_bpm_len_cb(int u, _alpm_cb_t *acb,
     55                     _alpm_pvt_node_t *pvt_node, void *user_data)
     56 {
     57     alpm_lib_trie_t *pfx_trie = (alpm_lib_trie_t *)user_data;
     58     _alpm_pfx_node_t *pfx_node = NULL;
     59     int rv = BCM_E_NONE;
     60 
     61     /* Find LPM for this pivot key */
     62     rv = alpm_lib_trie_find_lpm(pfx_trie, pvt_node->key,
     63                        pvt_node->key_len, (alpm_lib_trie_node_t **)&pfx_node);
     64     if (rv == BCM_E_NONE) {
     65         PVT_BKT_DEF(pvt_node) = pfx_node->bkt_ptr;
     66         PVT_BPM_LEN(pvt_node) = pfx_node->key_len; /* this is pvt bpm_len */
     67         ALPM_INFO(("alpm_lib_trie_find_lpm() OK rv:%d key:0x%08x key_len:%d bpm_len:%d\n",
     68                 rv, pvt_node->key[1], pvt_node->key_len, PVT_BPM_LEN(pvt_node)));
     69     } else {
     70         ALPM_ERR(("alpm_lib_trie_find_lpm() Failed rv:%d key:0x%08x key_len:%d v6_key:%d\n",
     71                   rv, pvt_node->key[1], pvt_node->key_len, pfx_trie->v6_key));
     72     }
     73     return BCM_E_NONE;
     74 }
     75 
     76 /*
     77  * Function:
     78  *      alpm_pivot_bpm_len_update
     79  * Purpose:
     80  *      Update pivot bpm_length after prefix trie is obtained from warmboot.
     81  * Parameters:
     82  *      u        - Device unit
     83  * Returns:
     84  *      void
     85  */
     86 STATIC void
     87 alpm_pivot_bpm_len_update(int u)
     88 {
     89     int         i, vrf_id, ipt;
     90     _alpm_cb_t  *acb;
     91     alpm_lib_trie_t *pfx_trie;
     92 
     93     for (i = 0; i < ACB_CNT(u); i++) {
     94         acb = ACB(u, i);
     95         for (ipt = 0; ipt < ALPM_IPT_CNT; ipt++) {
     96             for (vrf_id = 0; vrf_id < ALPM_VRF_ID_MAX(u); vrf_id++) {
     97                 if (!ACB_VRF_INITED(u, acb, vrf_id, ipt)) {
     98                     continue;
     99                 }
    100                 pfx_trie = ALPM_VRF_TRIE(u, vrf_id, ipt);
    101                 /* For those entries which doesn't use alpm bucket
    102                  * e.g.: Global Low in ALPM_TCAM mode */
    103                 if (pfx_trie == NULL) {
    104                     continue;
    105                 }
    106 
    107                 ALPM_INFO(("LC(%d) VRF:%d IPT:%s\n",
    108                            i, vrf_id, alpm_util_ipt_str[ipt]));
    109                 (void)bcm_esw_alpm_pvt_traverse(u, i, vrf_id, ipt,
    110                                      alpm_pvt_bpm_len_cb, (void *)pfx_trie);
    111             }
    112         }
    113     }
    114 }
    115 
    116 /*
    117  * Function:
    118  *      alpm_wb_vrf_init
    119  * Purpose:
    120  *      ALPM VRF pvt and pfx trie init from warmboot.
    121  *      Add a VRF default route when a L3 VRF is added.
    122  *      Adds a 0.0 entry into VRF.
    123  * Parameters:
    124  *      u        - Device unit
    125  *      acb      - ALPM control block pointer
    126  *      vrf_id   - VRF ID
    127  *      pkm      - Packing mode (32B, 64B, 128)
    128  * Returns:
    129  *      BCM_E_XXX
    130  */
    131 STATIC int
    132 alpm_wb_vrf_init(int u, _alpm_cb_t *acb, int vrf_id, int ipt)
    133 {
    134     int     rv = BCM_E_NONE;
    135     uint32  max_key_len;
    136     alpm_lib_trie_t  *root = NULL;
    137     uint32  key[5] = {0, 0, 0, 0, 0};
    138     _alpm_pfx_node_t    *pfx_node = NULL;
    139 
    140     max_key_len = alpm_util_trie_max_key_len(u, ipt);
    141     ALPM_IER(
    142         alpm_lib_trie_init(max_key_len, &ACB_PVT_TRIE(acb, vrf_id, ipt)));
    143 
    144     ACB_VRF_INIT_SET(u, acb, vrf_id, ipt);
    145     ACB_DR_INIT_CLEAR(u, acb, vrf_id, ipt);
    146 
    147     if (ACB_HAS_RTE(acb, vrf_id)) {
    148         rv = alpm_lib_trie_init(max_key_len, &ALPM_VRF_TRIE(u, vrf_id, ipt));
    149         if (BCM_SUCCESS(rv)) {
    150             ALPM_ALLOC_EG(pfx_node, sizeof(*pfx_node), "Payload for pfx trie key");
    151             root = ALPM_VRF_TRIE(u, vrf_id, ipt);
    152             rv = alpm_lib_trie_insert(root, key, 0, &(pfx_node->node));
    153         }
    154         if (BCM_FAILURE(rv)) {
    155             alpm_util_free(pfx_node);
    156             if (root != NULL) {
    157                 alpm_lib_trie_destroy(root);
    158                 ALPM_VRF_TRIE(u, vrf_id, ipt) = NULL;
    159             }
    160         }
    161     }
    162 
    163 bad:
    164     return rv;
    165 }
    166 
    167 /*
    168  * Function:
    169  *      alpm_wb_pvt_insert
    170  * Purpose:
    171  *      ALPM pivot restore and insert from warmboot.
    172  * Parameters:
    173  *      u        - Device unit
    174  *      acb      - ALPM control blobk pointer
    175  *      vrf_id   - VRF ID
    176  *      pkm      - Packing mode (32B, 64B, 128)
    177  *      key      - (In)Key prefix
    178  *      key_len  - (In)Key prefix length
    179  *      idx      - (In)Memory Index
    180  *      sub_idx  - (In)Memory sub_idx (for half-entry) or ent index
    181  *      pvt_node - (Out)Pointer of new pvt node inserted
    182  * Returns:
    183  *      BCM_E_XXX
    184  */
    185 STATIC int
    186 alpm_wb_pvt_insert(int u, _alpm_cb_t *acb, int vrf_id, int pkm,
    187                        uint32 *key, int key_len, int idx, int sub_idx,
    188                        _alpm_pvt_node_t **pvt_node)
    189 {
    190     int                 rv = BCM_E_NONE;
    191     int                 ipt = ALPM_PKM2IPT(pkm);
    192     uint32              max_key_len;
    193     uint32              pvt_idx = idx;
    194     uint32              pfx[5];
    195     _alpm_pvt_node_t    *npvt_node = NULL;
    196     alpm_lib_trie_t     *pvt_trie = NULL;
    197 
    198     ALPM_ALLOC_EG(npvt_node, sizeof(_alpm_pvt_node_t), "pvt_node");
    199 
    200     max_key_len = alpm_util_trie_max_key_len(u, ipt);
    201     ALPM_IEG(alpm_lib_trie_init(max_key_len, &PVT_BKT_TRIE(npvt_node)));
    202 
    203     PVT_BKT_VRF(npvt_node)   = vrf_id;
    204     PVT_BKT_PKM(npvt_node)   = pkm;
    205     PVT_KEY_LEN(npvt_node)   = key_len;
    206 
    207     alpm_trie_key_to_pfx(u, ipt, key, key_len, pfx);
    208     PVT_KEY_CPY(npvt_node, pfx);
    209 
    210     /* pvt_idx format
    211      *  L3_DEFIP_LEVEL1:       idx << 1 | sub_idx
    212      *  L3_DEFIP_PAIR_LEVEL1:  idx
    213      *
    214      * Level2:
    215      * -------------------------------
    216      * | ent idx | bnk idx | bkt idx |
    217      * -------------------------------
    218      */
    219     if (ACB_HAS_TCAM(acb)) {
    220         if (ALPM_IS_IPV4(ipt)) {
    221             pvt_idx = idx << 1 | sub_idx;
    222         } else {
    223             pvt_idx = idx;
    224         }
    225     }
    226     PVT_IDX(npvt_node) = pvt_idx;
    227 
    228     pvt_trie = ACB_PVT_TRIE(acb, vrf_id, ipt);
    229     rv = alpm_lib_trie_insert(pvt_trie, npvt_node->key, key_len,
    230                               (alpm_lib_trie_node_t *)npvt_node);
    231 bad:
    232     if (BCM_FAILURE(rv)) {
    233         if (npvt_node != NULL) {
    234             alpm_util_free(npvt_node);
    235         }
    236     }
    237     *pvt_node = npvt_node;
    238     return rv;
    239 }
    240 
    241 /*
    242  * Function:
    243  *      alpm_wb_bkt_insert
    244  * Purpose:
    245  *      ALPM bucket restore and insert from warmboot.
    246  * Parameters:
    247  *      u        - Device unit
    248  *      vrf_id   - VRF ID
    249  *      ipt      - Packing mode (V4, V6)
    250  *      key      - (In)Key prefix
    251  *      key_len  - (In)Key prefix length
    252  *      ent_idx  - (In)Hw mem location
    253  *      adata    - (In)Assoc_Data of bucket node
    254  *      pvt_node - (In)Pointer of pvt node to insert for bucket
    255  *      bkt_node - (Out)Pointer of new bucket node inserted
    256  * Returns:
    257  *      BCM_E_XXX
    258  */
    259 STATIC int
    260 alpm_wb_bkt_insert(int u, int vrf_id, int ipt,
    261                        uint32 *key, int key_len, int ent_idx,
    262                        _alpm_bkt_adata_t *adata,
    263                        _alpm_pvt_node_t *pvt_node,
    264                        _alpm_bkt_node_t **bkt_node)
    265 {
    266     int                 rv = BCM_E_NONE;
    267     uint32              pfx[5];
    268     _alpm_bkt_node_t    *nbkt_node = NULL;
    269     alpm_lib_trie_t     *bkt_trie = NULL;
    270 
    271     ALPM_ALLOC_EG(nbkt_node, sizeof(_alpm_bkt_node_t), "bkt_node");
    272     alpm_trie_key_to_pfx(u, ipt, key, key_len, pfx);
    273     sal_memcpy(nbkt_node->key, pfx, sizeof(nbkt_node->key));
    274     nbkt_node->key_len = key_len;
    275     nbkt_node->ent_idx = ent_idx;
    276 
    277     sal_memcpy(&nbkt_node->adata, adata, sizeof(_alpm_bkt_adata_t));
    278     bkt_trie = PVT_BKT_TRIE(pvt_node);
    279     rv = alpm_lib_trie_insert(bkt_trie, nbkt_node->key, key_len,
    280                               (alpm_lib_trie_node_t *)nbkt_node);
    281 bad:
    282     if (BCM_FAILURE(rv)) {
    283         if (nbkt_node != NULL) {
    284             alpm_util_free(nbkt_node);
    285         }
    286     }
    287     *bkt_node = nbkt_node;
    288     return rv;
    289 }
    290 
    291 /*
    292  * Function:
    293  *      alpm_wb_pfx_trie_add
    294  * Purpose:
    295  *      ALPM prefix restore and insert from warmboot.
    296  * Parameters:
    297  *      u        - Device unit
    298  *      vrf_id   - VRF ID
    299  *      pkm      - Packing mode (32B, 64B, 128)
    300  *      key      - (In)Key prefix
    301  *      key_len  - (In)Key prefix length
    302  *      ent_idx  - (In)Hw mem location
    303  *      adata    - (In)Assoc_Data of prefix node
    304  *      bkt_node - (In)Pointer of bkt node for prefix node inserted
    305  * Returns:
    306  *      BCM_E_XXX
    307  */
    308 int
    309 alpm_wb_pfx_trie_add(int u, int vrf_id, int ipt,
    310                      uint32 *key, int key_len, int ent_idx,
    311                      _alpm_bkt_adata_t *adata,
    312                      _alpm_bkt_node_t *bkt_node)
    313 {
    314     int                 rv = BCM_E_NONE;
    315     uint32              pfx[5];
    316     _alpm_pfx_node_t    *pfx_node = NULL, *tmp_node;
    317     alpm_lib_trie_t     *pfx_trie = NULL;
    318     alpm_lib_trie_node_t         *lpmp;
    319 
    320     ALPM_ALLOC_EG(pfx_node, sizeof(_alpm_pfx_node_t), "VRF_trie_node");
    321     alpm_trie_key_to_pfx(u, ipt, key, key_len, pfx);
    322     sal_memcpy(pfx_node->key, pfx, sizeof(pfx_node->key));
    323     pfx_node->key_len = key_len;
    324     pfx_node->ent_idx = ent_idx;
    325 
    326     sal_memcpy(&pfx_node->adata, adata, sizeof(_alpm_bkt_adata_t));
    327     pfx_node->bkt_ptr = bkt_node;
    328     pfx_trie = ALPM_VRF_TRIE(u, vrf_id, ipt);
    329     if (key_len == 0) {
    330         /* Add a route already in trie */
    331         lpmp = NULL;
    332         rv = alpm_lib_trie_find_lpm(pfx_trie, 0, 0, &lpmp);
    333         if (BCM_SUCCESS(rv)) {
    334             tmp_node = (_alpm_bkt_node_t *)lpmp;
    335             tmp_node->bkt_ptr = bkt_node;
    336             return rv;
    337         }
    338     }
    339     rv = alpm_lib_trie_insert(pfx_trie, pfx_node->key, key_len,
    340                               (alpm_lib_trie_node_t *)pfx_node);
    341 bad:
    342     if (BCM_FAILURE(rv)) {
    343         if (pfx_node != NULL) {
    344             alpm_util_free(pfx_node);
    345         }
    346     }
    347     return rv;
    348 }
    349 
    350 /*
    351  * Function:
    352  *      alpm_cb_wb_process
    353  * Purpose:
    354  *      ALPM warmboot CB process (recursive from top to bottom).
    355  *      Read HW mem and restore SW state and tries.
    356  * Parameters:
    357  *      u        - Device unit
    358  *      vrf_id   - VRF ID
    359  *      pkm      - Packing mode (32B, 64B, 128)
    360  *      acb      - ALPM control block pointer
    361  *      fent     - (In)ALPM_DATA entry
    362  *      key      - (In)Key prefix
    363  *      key_len  - (In)Key prefix length
    364  *      idx      - (In)Memory Index
    365  *      sub_idx  - (In)Memory sub_idx (for half-entry) or ent index
    366  *      adata    - (In)Assoc Data structure pointer
    367  *      route_cnt- (Out)Accumulated total route count pointer
    368  *      trv_data - (In)pattern + compare,act,notify routines.
    369  * Returns:
    370  *      BCM_E_XXX
    371  */
    372 STATIC int
    373 alpm_cb_wb_process(int u, int vrf_id, int pkm, _alpm_cb_t *acb,
    374                    void *fent, uint32 *key, int key_len, int idx,
    375                    int sub_idx, _alpm_bkt_adata_t *adata,
    376                    uint32 *route_cnt, _bcm_l3_trvrs_data_t *trv_data)
    377 {
    378     uint32 bkt_entry[ALPM_MEM_ENT_MAX];
    379     uint32 fent1[ALPM_MEM_ENT_MAX];
    380     uint32 ftmp[ALPM_MEM_ENT_MAX];
    381     uint32 new_key[4];
    382     uint32 fmt, valid;
    383     int ipt, pvt_pkm = pkm;
    384     int sublen, new_len, def_miss;
    385     int idx1, eid, bnk, ent_idx;
    386     int nh_ecmp_idx, cmp_result;
    387     int bank_occupied;
    388     _alpm_bkt_adata_t adata1;
    389     char ip_buf[IP6ADDR_STR_LEN];
    390     _bcm_defip_cfg_t lpm_cfg;
    391     _alpm_bkt_info_t bkt_info;
    392     _alpm_pvt_node_t *pvt_node = NULL;
    393     _alpm_bkt_node_t *bkt_node = NULL;
    394     _alpm_tbl_t bkt_tbl;
    395     _alpm_tbl_t pvt_tbl;
    396 
    397     if (ACB_IDX(acb) >= ACB_CNT(u)) {
    398         return BCM_E_INTERNAL; /* wrong ALPM control level called */
    399     }
    400 
    401     ipt = ALPM_PKM2IPT(pkm);
    402     bkt_tbl = ACB_BKT_TBL(acb, vrf_id);
    403     pvt_tbl = (ACB_HAS_TCAM(acb) ? acb->pvt_tbl[pvt_pkm] :
    404                     ACB_BKT_TBL(ACB_UPR(u, acb), vrf_id));
    405     /**** Pivot level ****/
    406     alpm_util_bkt_info_get(u, vrf_id, ipt, pvt_pkm, acb, fent, sub_idx,
    407                            &bkt_info, &sublen, &def_miss);
    408 
    409     ALPM_INFO(("%s: Pivot idx:%d.%d key:0x%08x len:%d dest:%d\n",
    410                ALPM_TBL_NAME(pvt_tbl), idx, sub_idx, key[0], sublen,
    411                adata->defip_ecmp_index));
    412     /* kshift=sublen, must be same as previous key_len */
    413     if (!ACB_BKT_FIXED_FMT(acb, 1) && sublen != key_len) {
    414         ALPM_ERR(("%s: ALPM_DATA invalid kshift:%d vs pivot len:%d at %d.%d (%d)\n",
    415                   ALPM_TBL_NAME(pvt_tbl), sublen, key_len, idx, sub_idx, BI_BKT_IDX(&bkt_info)));
    416         return BCM_E_NONE; /* just skip the pivot */
    417     }
    418     if (BI_BKT_IDX(&bkt_info) >= ACB_BKT_CNT(acb)) {
    419         ALPM_ERR(("%s: ALPM_DATA invalid bkt_ptr at %d.%d (%d)\n",
    420                   ALPM_TBL_NAME(pvt_tbl), idx, sub_idx, BI_BKT_IDX(&bkt_info)));
    421         return BCM_E_NONE; /* just skip the pivot */
    422     }
    423 
    424     /**** 0) ALPM VRF init ****/
    425     if (!ACB_VRF_INITED(u, acb, vrf_id, ipt)) {
    426         ALPM_IER(alpm_wb_vrf_init(u, acb, vrf_id, ipt));
    427     }
    428 
    429     /**** 1) Pivot trie restore ****/
    430     ALPM_IER(alpm_wb_pvt_insert(u, acb, vrf_id, pkm, key, key_len, idx, sub_idx, &pvt_node));
    431     /* Restore pvt_node->bkt_info: rofs & bkt_idx */
    432     PVT_ROFS(pvt_node) = BI_ROFS(&bkt_info);
    433     PVT_BKT_IDX(pvt_node) = BI_BKT_IDX(&bkt_info);
    434     PVT_SUB_BKT_IDX(pvt_node) = BI_SUB_BKT_IDX(&bkt_info);
    435 
    436     for (bnk = 0; bnk < ACB_BNK_PER_BKT(acb, vrf_id); bnk++) {
    437         fmt = bkt_info.bnk_fmt[bnk];
    438         if ((fmt == 0) ||  (fmt > ACB_FMT_CNT(acb, vrf_id))) {
    439             if (fmt > ACB_FMT_CNT(acb, vrf_id)) {
    440                 ALPM_ERR(("%s: ALPM_DATA format wrong idx:%d.%d (bank=%d fmt=%d).\n",
    441                           ALPM_TBL_NAME(pvt_tbl), idx, sub_idx, bnk, fmt));
    442             }
    443             continue;
    444         }
    445         /* Restore pvt_node->bkt_info: bnk_fmt[bnk] */
    446         pvt_node->bkt_info.bnk_fmt[bnk] = fmt;
    447 
    448         /* Restore ACB_VRF_DB_TYPE(u, acb, vrf_id, pkm) given fmt */
    449         ACB_VRF_DB_TYPE(u, acb, vrf_id, ipt) =
    450             (uint8) alpm_util_bkt_fmt_type_get(u, vrf_id, acb, (uint8)fmt);
    451 
    452         /**** Bucket Level ****/
    453         idx1 = ALPM_TAB_IDX_GET_BKT_BNK(acb, BI_ROFS(&bkt_info), BI_BKT_IDX(&bkt_info), bnk);
    454         ALPM_IER(alpm_bkt_entry_read_no_cache(u, ACB_BKT_TBL(acb, vrf_id),
    455                                               acb, bkt_entry, idx1));
    456         bank_occupied = 0;
    457         for (eid = 0; eid < ACB_FMT_ENT_MAX(acb, vrf_id, fmt); eid++) {
    458             uint32 key2[4] = {0};
    459             int len2 = 0;
    460             int sub_bkt_ptr = 0;
    461 
    462             /* process bucket entry Prefix */
    463             alpm_util_ent_ent_get(u, vrf_id, acb, bkt_entry, fmt, eid, ftmp);
    464             alpm_util_bkt_pfx_get(u, vrf_id, acb, ftmp, fmt, key2, &len2, &valid);
    465 
    466             /* process bucket entry ASSOC_DATA */
    467             alpm_util_bkt_adata_get(u, vrf_id, ipt, acb, ftmp, fmt, &adata1, &sub_bkt_ptr);
    468 
    469             if (!valid || BI_SUB_BKT_IDX(&bkt_info) != sub_bkt_ptr) {
    470                 continue;
    471             } else {
    472                 if (ACB_BKT_FIXED_FMT(acb, 1)) {
    473                     new_len = len2;
    474                     sal_memcpy(new_key, key2, sizeof(new_key));
    475                 } else {
    476                     alpm_util_pfx_cat(u, ipt, key, sublen, key2, len2, new_key, &new_len);
    477                 }
    478                 bank_occupied = 1;
    479             }
    480             /* Restore pvt_node->bkt_info: vet_bmp[bnk] */
    481             pvt_node->bkt_info.vet_bmp[bnk] |= 1 << eid;
    482             ent_idx = ALPM_IDX_MAKE(acb, &pvt_node->bkt_info, bnk, eid);
    483 
    484             /**** 2) Bucket trie restore ****/
    485             ALPM_IER(alpm_wb_bkt_insert(u, vrf_id, ipt, new_key, new_len,
    486                                      ent_idx, &adata1, pvt_node, &bkt_node));
    487 
    488             ACB_PVT_PTR(acb, pvt_node, idx1) = pvt_node;
    489 
    490             /* end recursion here if reach to route level (last level) */
    491             if (ACB_HAS_RTE(acb, vrf_id)) {
    492                 VRF_ROUTE_ADD(acb, vrf_id, ipt);
    493                 alpm_util_cfg_construct(u, vrf_id, ipt, new_key, new_len,
    494                                         &adata1, &lpm_cfg);
    495                 nh_ecmp_idx = lpm_cfg.defip_ecmp_index;
    496                 if (ALPM_IS_IPV4(ipt)) {
    497                     alpm_util_fmt_ipaddr(ip_buf, lpm_cfg.defip_ip_addr);
    498                 } else {
    499                     alpm_util_fmt_ip6addr(ip_buf, lpm_cfg.defip_ip6_addr);
    500                 }
    501 
    502                 (*route_cnt)++;
    503                 ALPM_INFO(("%s: Route idx:%d.%d key:0x%08x len:%d ",
    504                       ALPM_TBL_NAME(bkt_tbl), idx1, eid, new_key[0], new_len));
    505                 ALPM_INFO(("=> Found route %d: IP_addr:%s Sublen:%d Dest:%d\n",
    506                       *route_cnt, ip_buf, new_len, adata1.defip_ecmp_index));
    507 
    508                 /* Execute operation routine if any. */
    509                 if (trv_data && trv_data->op_cb) {
    510                     (void)(*trv_data->op_cb)(u, (void *)trv_data,
    511                                                 (void *)&lpm_cfg,
    512                                                 (void *)&nh_ecmp_idx,
    513                                                 &cmp_result);
    514                 }
    515 
    516                 /**** 3) Prefix trie restore ****/
    517                 ALPM_IER(alpm_wb_pfx_trie_add(u, vrf_id, ipt, new_key,
    518                                       new_len, ent_idx, &adata1, bkt_node));
    519                 continue;
    520             }
    521 
    522             /* prevent going further down if somehow last level
    523                is not Route level due to internal failure */
    524             if ((ACB_IDX(acb) + 1) >= ACB_CNT(u)) {
    525                 return BCM_E_INTERNAL;
    526             }
    527 
    528             /* get ALPM Data entry ready for next level */
    529             alpm_util_ent_data_get(u, vrf_id, ipt, acb, ftmp, fmt, fent1);
    530             ALPM_IER(alpm_cb_wb_process(u, vrf_id, pkm, ACB_DWN(u, acb),
    531                                         fent1, new_key, new_len, idx1, eid,
    532                                         &adata1, route_cnt, trv_data));
    533 
    534         } /* for ent */
    535         if (!bank_occupied) {
    536             pvt_node->bkt_info.bnk_fmt[bnk] = 0;
    537         } else {
    538             SHR_BITDCL *bnk_bmp;
    539             _alpm_bkt_pool_conf_t *bp_conf;
    540             uint32 bank_idx = 0;
    541             int bnkpb;
    542             bp_conf = ACB_BKT_VRF_POOL(acb, PVT_BKT_VRF(pvt_node));
    543             bnk_bmp = BPC_BNK_BMP(bp_conf, ipt);
    544             bnkpb = BPC_BNK_PER_BKT(bp_conf);
    545             bank_idx = BI_BKT_IDX(&bkt_info) * bnkpb + bnk;
    546             if (BI_ROFS(&bkt_info) > bnk) {
    547                 bank_idx += bnkpb;
    548             }
    549             SHR_BITSET(bnk_bmp, bank_idx);
    550             BPC_BNK_USED(bp_conf, ipt) ++;
    551         }
    552     } /* for bnk */
    553 
    554     return BCM_E_NONE;
    555 }
    556 
    557 /*
    558  * Function:
    559  *      bcm_esw_alpm_warmboot_walk
    560  * Purpose:
    561  *      Recover LPM and ALPM entries for both IPv4 and IPv6
    562  * Parameters:
    563  *      u        - (IN)Device unit number.
    564  *      trv_data - (IN)pattern + compare,act,notify routines.
    565  * Returns:
    566  *      BCM_E_XXX
    567  */
    568 int
    569 bcm_esw_alpm_warmboot_walk(int u, _bcm_l3_trvrs_data_t *trv_data)
    570 {
    571     int ipv6, key_mode;
    572     int idx, sub_idx;
    573     int vrf_id;
    574     int idx_end;
    575     int nh_ecmp_idx;
    576     int step_size;
    577     int cmp_result;
    578     int rv = BCM_E_FAIL;
    579     uint32 lpm_entry[ALPM_MEM_ENT_MAX];
    580     uint32 fent[ALPM_MEM_ENT_MAX];
    581     _bcm_defip_cfg_t lpm_cfg;
    582     _alpm_cb_t *acb;
    583     _alpm_bkt_adata_t adata0;
    584     int pk, pkm, use_alpm;
    585     uint32 route_cnt = 0;
    586     uint32 key[4];
    587     int key_pfx_len;
    588     int tcam_idx_reinit;
    589     int rv_tcam;
    590 
    591     if (ALPMC(u) == NULL || !ALPMC(u)->_alpm_inited) {
    592         return BCM_E_INIT;
    593     }
    594 
    595     acb = ACB_TOP(u); /* from top to bottom */
    596 
    597     for (pk = 0; pk < ALPM_PKM_CNT; pk++) {
    598         if (ALPM_TCAM_TBL_SKIP(u, pk)) {
    599             continue; /* skip duplicated or invalid TCAM table */
    600         }
    601 
    602         idx_end = tcam_table_size(u, pk);
    603         /* Walk all TCAM entries */
    604         for (idx = 0; idx < idx_end; idx++) {
    605             ALPM_IEG(tcam_entry_read_no_cache(u, pk, lpm_entry, idx, idx));
    606 
    607             /* to avoid double TCAM reinit if both sub_idx are valid */
    608             tcam_idx_reinit = FALSE;
    609             for (sub_idx = 0; sub_idx < ALPM_TCAM_SUBCNT; sub_idx += step_size) {
    610                 int ipt;
    611                 rv_tcam = tcam_valid_entry_mode_get(u, pk, lpm_entry,
    612                               &step_size, &pkm, &ipv6, &key_mode, sub_idx);
    613                 if (BCM_FAILURE(rv_tcam)) {
    614                     if (rv_tcam == BCM_E_INTERNAL) {
    615                         ALPM_ERR(("%s: Invalid Key Mode:%d or Key Type (IPv6):%d in idx:%d.%d\n",
    616                                   TCAM_TBL_NAME(acb, pk), key_mode, ipv6, idx, sub_idx));
    617                     }
    618                     continue;
    619                 }
    620 
    621                 ipt = ALPM_PKM2IPT(pkm);
    622 
    623                 tcam_entry_vrf_id_get(u, pkm, lpm_entry, sub_idx, &vrf_id);
    624                 /* process pre-pivot ASSOC_DATA */
    625                 tcam_entry_adata_get(u, pkm, lpm_entry, sub_idx, &adata0);
    626                 use_alpm = !(adata0.defip_flags & BCM_L3_IPMC) &&
    627                            ALPM_VRF_ID_HAS_BKT(u, vrf_id);
    628 
    629                 /* Get Pre-pivot key IP_ADDR and prefix length (mask) */
    630                 sal_memset(key, 0, sizeof(key));
    631                 key_pfx_len = 0;
    632 
    633                 tcam_entry_to_key(u, pkm, lpm_entry, sub_idx, key);
    634                 tcam_entry_pfx_len_get(u, pkm, lpm_entry, sub_idx, &key_pfx_len);
    635 
    636                 /* only do tcam_reinit once per TCAM index */
    637                 if (tcam_idx_reinit == FALSE) {
    638                     tcam_wb_reinit(u, vrf_id, pkm, idx, key_pfx_len,
    639                                    !!(adata0.defip_flags & BCM_L3_IPMC));
    640                     tcam_idx_reinit = TRUE;
    641                 }
    642 
    643                 /* VRF_OVERRIDE (Global High) entries, and IP multicast prefix
    644                  * resides in TCAM */
    645                 if (!use_alpm) {
    646                     alpm_util_cfg_construct(u, vrf_id, ipt, key, key_pfx_len,
    647                                             &adata0, &lpm_cfg);
    648 
    649                     if (!ALPM_HIT_SKIP(u) &&
    650                         tcam_entry_hit_get(u, pkm, lpm_entry, sub_idx)) {
    651                         lpm_cfg.defip_flags |= BCM_L3_HIT;
    652                     }
    653 
    654                     if (ALPM_IS_IPV4(ipt)) {
    655                         lpm_cfg.defip_index = idx << 1 | sub_idx;
    656                     } else {
    657                         lpm_cfg.defip_index = idx;
    658                     }
    659                     nh_ecmp_idx = lpm_cfg.defip_ecmp_index;
    660                     route_cnt++;
    661 
    662                     /* TCAM pvt trie restore for Direct Routes only */
    663                     if (!ACB_VRF_INITED(u, acb, vrf_id, ipt)) {
    664                         (void)alpm_pvt_trie_init(u, vrf_id, ipt);
    665                     }
    666                     alpm_trie_key_to_pfx(u, ipt, key, key_pfx_len, lpm_cfg.user_data);
    667                     (void)alpm_pvt_trie_insert(u, &lpm_cfg);
    668                     VRF_ROUTE_ADD(acb, vrf_id, ipt);
    669 
    670                     if (trv_data && trv_data->op_cb) {
    671                         (void) (*trv_data->op_cb)(u, (void *)trv_data,
    672                                                   (void *)&lpm_cfg,
    673                                                   (void *)&nh_ecmp_idx,
    674                                                   &cmp_result);
    675                     }
    676                     continue;
    677                 }
    678 
    679                 ALPM_INFO(("VRF:%d %s\n", vrf_id, alpm_util_pkm_str[pkm]));
    680 
    681                 /* process ALPM_DATA level recursively from top to bottom */
    682                 tcam_entry_bdata_get(u, pkm, lpm_entry, sub_idx, fent);
    683 
    684                 ALPM_IEG(alpm_cb_wb_process(u, vrf_id, pkm, acb, fent,
    685                                             key, key_pfx_len, idx, sub_idx,
    686                                             &adata0, &route_cnt, trv_data));
    687             } /* for sub_idx */
    688         } /* for idx */
    689     } /* for pk */
    690 
    691     /* Update bpm_len of pivot after perfix trie is restored */
    692     alpm_pivot_bpm_len_update(u);
    693 
    694     /* Update TCAM state after tcam_reinit */
    695     ALPM_IEG(tcam_wb_reinit_done(u));
    696 
    697 #ifdef ALPM_WARM_BOOT_DEBUG
    698     /* TD3ALPMTBD */
    699     /* bcm_esw_alpm_sw_dump(u); */
    700 #endif /* ALPM_WARM_BOOT_DEBUG  */
    701 
    702     rv = BCM_E_NONE;
    703 bad:
    704     return (rv);
    705 }
    706 
    707 /*
    708  * Function:
    709  *      alpm_wb_test
    710  * Purpose:
    711  *      ALPM warmboot walk test function (simulates with ALPM soft-reinit).
    712  * Parameters:
    713  *      u        - (IN)Device unit number.
    714  * Returns:
    715  *      BCM_E_XXX
    716  */
    717 int
    718 alpm_wb_test(int u)
    719 {
    720     int vrf_id, ipt;
    721     int rv = BCM_E_NONE;
    722 
    723     /* Do ALPM module soft-reinit (ALPM HW mem untouched) */
    724     if (ALPMC(u) && ALPMC(u)->_alpm_inited) {
    725         for (vrf_id = 0; vrf_id <= ALPM_VRF_ID_MAX(u); vrf_id++) {
    726             for (ipt = 0; ipt < ALPM_IPT_CNT; ipt++) {
    727                 alpm_vrf_deinit(u, vrf_id, ipt);
    728             }
    729         }
    730 
    731         bcm_esw_alpm_tcam_deinit(u);
    732         ALPM_DRV(u)->alpm_ctrl_deinit(u);
    733 
    734         if (ALPMC(u)->_vrf_pfx_hdl != NULL) {
    735             alpm_util_free(ALPMC(u)->_vrf_pfx_hdl);
    736         }
    737 
    738         if (ALPMC(u)->_alpm_merge_state != NULL) {
    739             alpm_util_free(ALPMC(u)->_alpm_merge_state);
    740         }
    741 
    742         if (ALPMC(u)->_alpm_err_msg_buf != NULL) {
    743             alpm_util_free(ALPMC(u)->_alpm_err_msg_buf);
    744         }
    745 
    746         if (ALPMC(u) != NULL) {
    747             alpm_util_free(ALPMC(u));
    748             ALPMC(u) = NULL;
    749         }
    750     }
    751     /* TD3ALPMTBD: assuming bcm_esw_alpm_init() doesn't clear Hw memories */
    752     bcm_esw_alpm_init(u);
    753     LOG_CLI(("ALPM module soft-reset!\n"));
    754     LOG_CLI(("ALPM warmboot walk: restoring from Hw mem ...\n"));
    755     rv = bcm_esw_alpm_warmboot_walk(u, NULL);
    756 
    757     return rv;
    758 }
    759 
    760 STATIC int
    761 alpm_pfx_update_match_cb(_alpm_pfx_node_t *pfx_node, void *user_data)
    762 {
    763     _bcm_defip_cfg_t lpm_cfg;
    764     _alpm_pfx_update_match_t *upd_data = (_alpm_pfx_update_match_t *)user_data;
    765     _bcm_l3_trvrs_data_t *trv_data = upd_data->trv_data;
    766     int *def_rte_cnt = upd_data->def_rte_cnt;
    767     alpm_def_rte_info_t *def_rte = upd_data->def_rte;
    768     int u = upd_data->unit;
    769     int vrf_id = upd_data->vrf_id;
    770     int ipt = upd_data->ipt;
    771 
    772     int idx;
    773     int ent;
    774     _alpm_bkt_adata_t adata;
    775     int nh_ecmp_idx, cmp_result;
    776     char ip_buf[IP6ADDR_STR_LEN];
    777 
    778     _alpm_cb_t *acb = ACB_VRF_BTM(u, vrf_id);
    779     _alpm_tbl_t bkt_tbl = ACB_BKT_TBL(acb, vrf_id);
    780     uint32 key[5] = {0};
    781 
    782     if (pfx_node->bkt_ptr == NULL) {
    783         /* VRF global low "virtual def rte" */
    784         return BCM_E_NONE;
    785     }
    786 
    787     idx = ALPM_TAB_IDX_GET(pfx_node->bkt_ptr->ent_idx);
    788     ent = ALPM_IDX_TO_ENT(pfx_node->bkt_ptr->ent_idx);
    789     adata = pfx_node->bkt_ptr->adata;
    790 
    791     alpm_trie_pfx_to_key(u, ipt, pfx_node->key, pfx_node->key_len, key);
    792     alpm_util_cfg_construct(u, vrf_id, ipt, key, pfx_node->key_len,
    793                             &adata, &lpm_cfg);
    794 
    795     if ((trv_data->flags & BCM_L3_IP6) != (lpm_cfg.defip_flags & BCM_L3_IP6)) {
    796         return BCM_E_NONE;
    797     }
    798 
    799     /* Dist hitbit (skip if def_rte==NULL for fast delete_all) */
    800     if (!ALPM_HIT_SKIP(u) && def_rte) {
    801         int hit_val;
    802         ALPM_HIT_LOCK(u);
    803         hit_val = alpm_rte_hit_get(u, vrf_id, bkt_tbl, idx, ent);
    804         if (hit_val > 0) {
    805             lpm_cfg.defip_flags |= BCM_L3_HIT;
    806         }
    807         ALPM_HIT_UNLOCK(u);
    808     }
    809 
    810     lpm_cfg.defip_index = alpm_util_ent_phy_idx_get(u, acb, vrf_id, idx);
    811     nh_ecmp_idx = lpm_cfg.defip_ecmp_index;
    812     adata.defip_flags = lpm_cfg.defip_flags;
    813 
    814     if (ALPM_IS_IPV4(ipt)) {
    815         alpm_util_fmt_ipaddr(ip_buf, lpm_cfg.defip_ip_addr);
    816     } else {
    817         alpm_util_fmt_ip6addr(ip_buf, lpm_cfg.defip_ip6_addr);
    818     }
    819 
    820     ALPM_INFO(("%s: Route idx:%d.%d IP_addr:%s Sublen:%d Dest:%d\n",
    821                ALPM_TBL_NAME(bkt_tbl), idx, ent,
    822                ip_buf, pfx_node->key_len, lpm_cfg.defip_ecmp_index));
    823 
    824     /* Check if this is default route (skip if def_rte==NULL for fast delete_all) */
    825     /* Subnet length zero will indicate default route */
    826     if (def_rte && (lpm_cfg.defip_sub_len == 0)) {
    827         if (*def_rte_cnt < ALPM_VRF_ID_CNT(u) * 2) {
    828             def_rte[*def_rte_cnt].vrf_id = vrf_id;
    829             def_rte[*def_rte_cnt].ipt = ipt;
    830             def_rte[*def_rte_cnt].bkt_idx = idx;
    831             sal_memcpy(&def_rte[*def_rte_cnt].adata,
    832                        &adata, sizeof(adata));
    833             (*def_rte_cnt)++;
    834         }
    835     } else {
    836         /* Execute operation routine if any. */
    837         if (trv_data && trv_data->op_cb) {
    838             (void)(*trv_data->op_cb)(u, (void *)trv_data,
    839                                         (void *)&lpm_cfg,
    840                                         (void *)&nh_ecmp_idx,
    841                                         &cmp_result);
    842         }
    843     }
    844     return BCM_E_NONE;
    845 }
    846 
    847 STATIC void
    848 alpm_pfx_trav_update_match(int u,
    849                            alpm_def_rte_info_t *def_rte,
    850                            int *def_rte_cnt,
    851                            _bcm_l3_trvrs_data_t *trv_data)
    852 {
    853     int         vrf_id, ipt;
    854     _alpm_pfx_update_match_t upd_data;
    855 
    856     upd_data.unit = u;
    857     upd_data.trv_data = trv_data;
    858     upd_data.def_rte = def_rte;
    859     upd_data.def_rte_cnt = def_rte_cnt;
    860 
    861     for (ipt = 0; ipt < ALPM_IPT_CNT; ipt++) {
    862         upd_data.ipt = ipt;
    863         for (vrf_id = 0; vrf_id <= ALPM_VRF_ID_MAX(u); vrf_id++) {
    864             if (!ACB_VRF_INITED(u, ACB_VRF_BTM(u, vrf_id), vrf_id, ipt)) {
    865                 continue;
    866             }
    867             upd_data.vrf_id = vrf_id;
    868             (void)bcm_esw_alpm_pfx_traverse(u, vrf_id, ipt,
    869                                             alpm_pfx_update_match_cb,
    870                                             &upd_data);
    871         }
    872     }
    873 }
    874 
    875 /*
    876  * Function:
    877  *      tcam_direct_route_update_match
    878  * Purpose:
    879  *      Update/Delete all TCAM direct route entries matching certain rule.
    880  * Parameters:
    881  *      u        - (IN)Device unit number.
    882  *      trv_data - (IN)Delete pattern + compare,act,notify routines.
    883  * Returns:
    884  *      VOID
    885  */
    886 STATIC int
    887 tcam_direct_route_update_match(int u, _bcm_l3_trvrs_data_t *trv_data)
    888 {
    889     int ipv6, key_mode;
    890     int idx, sub_idx;
    891     int vrf_id;
    892     int idx_end;
    893     int nh_ecmp_idx;
    894     int step_size;
    895     int cmp_result;
    896     uint32 lpm_entry[ALPM_MEM_ENT_MAX];
    897     _bcm_defip_cfg_t lpm_cfg;
    898     _alpm_cb_t *acb;
    899     _alpm_bkt_adata_t adata0;
    900     int pk, ipt, pkm, use_alpm;
    901     uint32 key[4];
    902     int key_pfx_len;
    903     int rv_tcam;
    904     int val_sub_idx_cnt, val_sub_idx[4];
    905     int ipv6_req;
    906     int rv = BCM_E_NONE;
    907 
    908     ipv6_req = trv_data->flags & BCM_L3_IP6 ? TRUE : FALSE;
    909 
    910     acb = ACB_TOP(u); /* TCAM level */
    911 
    912     for (pk = 0; pk < ALPM_PKM_CNT; pk++) {
    913         if (ALPM_TCAM_TBL_SKIP(u, pk)) {
    914             continue; /* skip duplicated or invalid TCAM table */
    915         }
    916 
    917         idx_end = tcam_table_size(u, pk);
    918         /* Walk all TCAM entries (backward) */
    919         for (idx = (idx_end - 1); idx >= 0; idx--) {
    920             ALPM_IEG(tcam_entry_read_no_cache(u, pk, lpm_entry, idx, idx));
    921 
    922             /* pre-process valid sub_idx (to process backward) */
    923             val_sub_idx_cnt = 0;
    924             for (sub_idx = 0; sub_idx < ALPM_TCAM_SUBCNT; sub_idx += step_size) {
    925                 rv_tcam = tcam_valid_entry_mode_get(u, pk, lpm_entry,
    926                               &step_size, &pkm, &ipv6, &key_mode, sub_idx);
    927                 if (BCM_FAILURE(rv_tcam)) {
    928                     if (rv_tcam == BCM_E_INTERNAL) {
    929                         ALPM_ERR(("%s: Invalid Key Mode:%d or Key Type (IPv6):%d in idx:%d.%d\n",
    930                           TCAM_TBL_NAME(acb, pk), key_mode, ipv6, idx, sub_idx));
    931                     }
    932                     continue;
    933                 } else {
    934                     if (ipv6 != ipv6_req) {
    935                         continue;
    936                     }
    937                     val_sub_idx[val_sub_idx_cnt++] = sub_idx;
    938                 }
    939             }
    940 
    941             /* walk backward valid sub_idx */
    942             while (val_sub_idx_cnt > 0) {
    943                 sub_idx = val_sub_idx[--val_sub_idx_cnt];
    944                 rv_tcam = tcam_valid_entry_mode_get(u, pk, lpm_entry,
    945                               &step_size, &pkm, &ipv6, &key_mode, sub_idx);
    946                 if (BCM_FAILURE(rv_tcam)) {
    947                     continue;
    948                 }
    949 
    950                 ipt = ALPM_PKM2IPT(pkm);
    951 
    952                 tcam_entry_vrf_id_get(u, pkm, lpm_entry, sub_idx, &vrf_id);
    953 
    954                 /* Get Pre-pivot key IP_ADDR and prefix length (mask) */
    955                 sal_memset(key, 0, sizeof(key));
    956                 key_pfx_len = 0;
    957 
    958                 tcam_entry_to_key(u, pkm, lpm_entry, sub_idx, key);
    959                 tcam_entry_pfx_len_get(u, pkm, lpm_entry, sub_idx, &key_pfx_len);
    960 
    961                 /* process pre-pivot ASSOC_DATA */
    962                 tcam_entry_adata_get(u, pkm, lpm_entry, sub_idx, &adata0);
    963                 use_alpm = !(adata0.defip_flags & BCM_L3_IPMC) &&
    964                            ALPM_VRF_ID_HAS_BKT(u, vrf_id);
    965 
    966                 /* VRF_OVERRIDE (Global High) entries, and IP multicast prefix
    967                  * resides in TCAM */
    968                 if (!use_alpm) {
    969                     alpm_util_cfg_construct(u, vrf_id, ipt, key, key_pfx_len,
    970                                             &adata0, &lpm_cfg);
    971 
    972                     if (!ALPM_HIT_SKIP(u) &&
    973                         tcam_entry_hit_get(u, pkm, lpm_entry, sub_idx)) {
    974                         lpm_cfg.defip_flags |= BCM_L3_HIT;
    975                     }
    976 
    977                     lpm_cfg.defip_index = idx;
    978                     nh_ecmp_idx = lpm_cfg.defip_ecmp_index;
    979 
    980                     if (trv_data && trv_data->op_cb) {
    981                         (void) (*trv_data->op_cb)(u, (void *)trv_data,
    982                                                   (void *)&lpm_cfg,
    983                                                   (void *)&nh_ecmp_idx,
    984                                                   &cmp_result);
    985                     }
    986                     continue;
    987                 }
    988             } /* while val_sub_idx_cnt */
    989         } /* for idx */
    990     } /* for pk */
    991 
    992 bad:
    993     return rv;
    994 }
    995 
    996 /*
    997  * Function:
    998  *      bcm_esw_alpm_update_match
    999  * Purpose:
   1000  *      Update/Delete all entries in defip table matching a certain rule.
   1001  * Parameters:
   1002  *      u        - (IN)Device unit number.
   1003  *      trv_data - (IN)Delete pattern + compare,act,notify routines.
   1004  * Returns:
   1005  *      BCM_E_XXX
   1006  */
   1007 int
   1008 bcm_esw_alpm_update_match(int u, _bcm_l3_trvrs_data_t *trv_data)
   1009 {
   1010     int idx;
   1011     int nh_ecmp_idx;
   1012     int cmp_result;
   1013     int rv = BCM_E_NONE;
   1014     _bcm_defip_cfg_t lpm_cfg;
   1015     uint32 key[4];
   1016     int key_pfx_len;
   1017     int def_rte_cnt = 0;
   1018     int def_rte_sz;
   1019     alpm_def_rte_info_t *def_rte = NULL;
   1020 
   1021     if (ALPMC(u) == NULL || !ALPMC(u)->_alpm_inited) {
   1022         return BCM_E_INIT;
   1023     }
   1024 
   1025 #ifdef BCM_WARM_BOOT_SUPPORT
   1026     if (SOC_WARM_BOOT(u)) {
   1027         rv = bcm_esw_alpm_warmboot_walk(u, trv_data);
   1028         if (BCM_FAILURE(rv)) {
   1029             ALPM_ERR(("ERROR!  ALPM Warmboot recovery failed\n"));
   1030         }
   1031         return (rv);
   1032     }
   1033 #endif
   1034 
   1035     /* Update match for all TCAM direct routes */
   1036     ALPM_IEG(tcam_direct_route_update_match(u, trv_data));
   1037 
   1038     /* Allocate memory to store default route meta data,
   1039      * x2 means v4 and v6 */
   1040     def_rte_sz = 2 * ALPM_VRF_ID_CNT(u) * sizeof(alpm_def_rte_info_t);
   1041     ALPM_ALLOC_EG(def_rte, def_rte_sz, "def_rte");
   1042 
   1043     /* ALPM routes use prefix trie traverse for update match,
   1044        to overcome bkt bnk shrinking during update match */
   1045     alpm_pfx_trav_update_match(u, def_rte, &def_rte_cnt, trv_data);
   1046 
   1047     /* Process Default routes */
   1048     sal_memset(key, 0, sizeof(key));
   1049     key_pfx_len = 0;
   1050     for (idx = 0; idx < def_rte_cnt; idx++) {
   1051         alpm_util_cfg_construct(u, def_rte[idx].vrf_id, def_rte[idx].ipt, key,
   1052                                 key_pfx_len, &def_rte[idx].adata, &lpm_cfg);
   1053 
   1054         /* TD3ALPMTBD: add Hitbit */
   1055         lpm_cfg.defip_index = def_rte[idx].bkt_idx;
   1056         nh_ecmp_idx = lpm_cfg.defip_ecmp_index;
   1057 
   1058         /* Execute operation routine if any. */
   1059         if (trv_data->op_cb) {
   1060             rv = (*trv_data->op_cb)(u, (void *)trv_data,
   1061                                     (void *)&lpm_cfg,
   1062                                     (void *)&nh_ecmp_idx,
   1063                                      &cmp_result);
   1064         }
   1065     }
   1066 
   1067 #ifdef ALPM_WARM_BOOT_DEBUG
   1068     /* TD3ALPMTBD */
   1069     /* bcm_esw_alpm_sw_dump(u); */
   1070 #endif
   1071 
   1072 bad:
   1073     if (def_rte != NULL) {
   1074         alpm_util_free(def_rte);
   1075     }
   1076 
   1077     return (rv);
   1078 }
   1079 
   1080 /*
   1081  * Function:
   1082  *      bcm_esw_alpm_fast_delete_all
   1083  * Purpose:
   1084  *      Fast delete all entries in defip table using different methods:
   1085  *      - Direct routes: normal delete (route + ecmp_nh)
   1086  *      - TCAM Hw table delete
   1087  *      - ALPM routes: delete only ecmp_nh
   1088  * Parameters:
   1089  *      u         - (IN)Device unit number.
   1090  *      trv_data  - (IN)Delete pattern + compare,act,notify routines for TCAM Direct routes.
   1091  *      trv_data1 - (IN)Delete pattern + compare,act,notify routines for ALPM routes.
   1092  * Returns:
   1093  *      BCM_E_XXX
   1094  */
   1095 int
   1096 bcm_esw_alpm_fast_delete_all(int u, _bcm_l3_trvrs_data_t *trv_data,
   1097                              _bcm_l3_trvrs_data_t *trv_data1)
   1098 {
   1099     int rv = BCM_E_NONE;
   1100 
   1101     /* TCAM direct routes: delete route + nh */
   1102     if (BCM_XGS3_L3_DEFIP_IP4_CNT(u)) {
   1103         trv_data->flags = 0;
   1104         ALPM_IEG(tcam_direct_route_update_match(u, trv_data));
   1105     }
   1106     if (BCM_XGS3_L3_DEFIP_IP6_CNT(u)) {
   1107         trv_data->flags |= BCM_L3_IP6;
   1108         ALPM_IEG(tcam_direct_route_update_match(u, trv_data));
   1109     }
   1110 
   1111     /* Cleanup TCAM Hw table to avoid wrong routing traffic
   1112        when delete_all ecmp_nh_idx without delete ALPM routes */
   1113     ALPM_DRV(u)->tcam_hw_cleanup(u);
   1114 
   1115     /* ALPM routes fast delete_all using prefix trie traverse */
   1116     if (BCM_XGS3_L3_DEFIP_IP4_CNT(u)) {
   1117         trv_data1->flags = 0;
   1118         alpm_pfx_trav_update_match(u, NULL, NULL, trv_data1);
   1119     }
   1120 
   1121     if (BCM_XGS3_L3_DEFIP_IP6_CNT(u)) {
   1122         trv_data1->flags |= BCM_L3_IP6;
   1123         alpm_pfx_trav_update_match(u, NULL, NULL, trv_data1);
   1124     }
   1125 
   1126 bad:
   1127     return (rv);
   1128 }
   1129 
   1130 #endif /* ALPM_ENABLE */