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


      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  * File:    alpm.c
      7  * Purpose: ALPM device independent implementation.
      8  * Requires:
      9  */
     10 
     11 /* Implementation notes:
     12  */
     13 #include <shared/bsl.h>
     14 
     15 #include <soc/mem.h>
     16 #include <soc/drv.h>
     17 #include <soc/debug.h>
     18 #include <soc/error.h>
     19 #include <soc/lpm.h>
     20 #include <soc/trident2.h>
     21 #include <soc/tomahawk.h>
     22 #include <shared/bsl.h>
     23 
     24 #include <shared/util.h>
     25 #include <shared/l3.h>
     26 
     27 #if defined(ALPM_ENABLE)
     28 
     29 #include <bcm/l3.h>
     30 
     31 #include <bcm_int/esw/l3.h>
     32 #include <bcm_int/esw/firebolt.h>
     33 #include <bcm_int/esw/alpm.h>
     34 #include <bcm_int/esw/alpm_util.h>
     35 
     36 /* Internal use only */
     37 typedef struct alpm_pvt_trav_cb_data_s {
     38     int         unit;
     39     _alpm_cb_t  *acb;
     40     int         bkt_idx;
     41 
     42     SHR_BITDCL  bkt[256];                   /* 1K|8K, Max: 13 bits */
     43     SHR_BITDCL  bnk[ALPM_BPB_MAX * 256];    /* bnk|bkt 1K|5 or 8K|8 */
     44     SHR_BITDCL  ent[ALPM_BPB_MAX * 8192];   /* 10b/13b(bkt) |3b(bnk)| 5b(ent) */
     45     uint8       bnkfmt[ALPM_BPB_MAX * 8192];/* Bank format type */
     46 } alpm_pvt_trav_cb_data_t;
     47 
     48 char *alpm_tbl_str[] = {
     49     "alpmTblInvalid",
     50     "alpmTblPvtCmodeL1",
     51     "alpmTblPvtPmodeL1",
     52     "alpmTblPvtCmodeL1P128",
     53     "alpmTblPvtPmodeL1P128",
     54     "alpmTblBktCmodeL2",
     55     "alpmTblBktPmodeL2",
     56     "alpmTblBktPmodeGblL2",
     57     "alpmTblBktPmodePrtL2",
     58     "alpmTblBktCmodeL3",
     59     "alpmTblBktPmodeGblL3",
     60     "alpmTblBktPmodePrtL3",
     61     "alpmTblCount"
     62 };
     63 
     64 _alpm_ctrl_t *alpm_control[SOC_MAX_NUM_DEVICES];
     65 
     66 /* Internal functions */
     67 static int alpm_pvt_update_by_pvt_node(int, _alpm_cb_t *, _alpm_pvt_node_t *, uint32);
     68 static int alpm_bkt_pfx_shrink(int u, _alpm_cb_t *acb, _alpm_pvt_node_t *pvt_node, void *user_data);
     69 static int alpm_vrf_pfx_trie_add(int u, _alpm_cb_t *acb, _bcm_defip_cfg_t *lpm_cfg, void *udata);
     70 static int alpm_cb_split(int u, _alpm_cb_t *acb, _bcm_defip_cfg_t *lpm_cfg,
     71                          _alpm_bkt_info_t *nbkt_info, int max_spl_cnt);
     72 
     73 /* External functions */
     74 
     75 /*
     76  *           key[4] = {key[0], key[1], key[2], key[3]}
     77  * ipv4:     key[4] = {IP_ADDR0f, 0, 0, 0}
     78  * ipv6-64:  key[4] = {0, 0, IP_ADDR0f, IP_ADDR1f}
     79  * ipv6-128: key[4] = {IP_ADDR0_LWRf, IP_ADDR1_LWRf, IP_ADDR0_UPRf, IP_ADDR1_UPRf}
     80  */
     81 void
     82 alpm_trie_key_to_pfx(int u, int ipt, uint32 *key, uint32 len, uint32 *pfx)
     83 {
     84     int i;
     85     uint32 pfx_shift, tmp;
     86 
     87     pfx[0] = pfx[1] = pfx[2] = pfx[3] = pfx[4] = 0;
     88     /* Obtain prefix length */
     89     if (ALPM_IS_IPV4(ipt)) {
     90         pfx[1] = _SHIFT_RIGHT(key[0], 32 - len);
     91         pfx[0] = 0;
     92     } else {
     93         /* PAIR_128 style, for both mode==2 and mode==3  */
     94         int start;
     95         uint32 tmp_pfx[5] = {0};
     96         tmp_pfx[0] = key[0];
     97         tmp_pfx[1] = key[1];
     98         tmp_pfx[2] = key[2];
     99         tmp_pfx[3] = key[3];
    100 
    101         /* shift entire prefix right to remove trailing 0s in prefix */
    102         /* to simplify, words which are all 0s are ignored to begin with, so
    103          * a right shift of say 46 is a right shift of 46-32 = 14, but starting
    104          * from word 1. Once all shifting is done, shift all words to right by 1
    105          */
    106         pfx_shift = 128 - len;
    107         start = pfx_shift / 32;
    108         pfx_shift = pfx_shift % 32;
    109         for (i = start; i < 4; i++) {
    110             tmp_pfx[i] >>= pfx_shift;
    111             tmp = tmp_pfx[i+1] & ((1 << pfx_shift) - 1);
    112             tmp = _SHIFT_LEFT(tmp, 32 - pfx_shift);
    113             tmp_pfx[i] |= tmp;
    114         }
    115         /* make shift right justified and also reverse order for trie.
    116          * Also, note trie sees key only in words 1 to 4
    117          */
    118         for (i = start; i < 4; i++) {
    119             pfx[4 - (i - start)] = tmp_pfx[i];
    120         }
    121     }
    122     return ;
    123 }
    124 
    125 /*
    126  *           key[4] = {key[0], key[1], key[2], key[3]}
    127  * ipv4:     key[4] = {IP_ADDR0f, 0, 0, 0}
    128  * ipv6:
    129  *    64:    key[4] = {0, 0, IP_ADDR0f, IP_ADDR1f}
    130  *   128:    key[4] = {IP_ADDR0_LWRf, IP_ADDR1_LWRf, IP_ADDR0_UPRf, IP_ADDR1_UPRf}
    131  */
    132 void
    133 alpm_trie_pfx_to_key(int u, int ipt, uint32 *pfx, uint32 len, uint32 *key)
    134 {
    135     int key_bytes = sizeof(uint32) * BITS2WORDS(_MAX_KEY_LEN_144_);
    136 
    137     sal_memcpy(key, pfx, key_bytes);
    138     if (ALPM_IS_IPV6(ipt)) {
    139         uint32 pfx_shift, tmp, start, pfx_tmp[6];
    140         int i;
    141 
    142         sal_memcpy(pfx_tmp, key, key_bytes);
    143         sal_memset(key, 0, key_bytes);
    144 
    145         /* shift entire prefix left to add trailing 0s in prefix */
    146         pfx_shift = 128 - len;
    147         start = (pfx_shift + 31) / 32;
    148         /* fix corner case: */
    149         if ((pfx_shift % 32) == 0) {
    150             start++;
    151         }
    152         pfx_shift = pfx_shift % 32;
    153         for (i = start; i <= 4; i++) {
    154             pfx_tmp[i] <<= pfx_shift;
    155             tmp = pfx_tmp[i+1] & ~(0xffffffff >> pfx_shift);
    156             tmp = _SHIFT_RIGHT(tmp, 32 - pfx_shift);
    157             if (i < 4) {
    158                 pfx_tmp[i] |= tmp;
    159             }
    160         }
    161         /* make shift left justified and reversed,
    162          * i.e, lsw goes to index 0 */
    163         for (i = start; i <= 4; i++) {
    164             key[3 - (i - start)] = pfx_tmp[i];
    165         }
    166     } else {
    167         key[0] = _SHIFT_LEFT(key[1], 32 - len);
    168         key[1] = 0;
    169     }
    170 }
    171 
    172 /* ip_addr => lpm_cfg->user_data
    173  * OUT: pfx in tire format
    174  */
    175 void
    176 alpm_trie_cfg_to_pfx(int u, _bcm_defip_cfg_t *lpm_cfg, uint32 *pfx)
    177 {
    178     /* Create Prefix */
    179     uint32 key[4] = {0};
    180     uint32 ipt;
    181 
    182     ipt = ALPM_LPM_IPT(u, lpm_cfg);
    183     alpm_util_cfg_to_key(u, ipt, lpm_cfg, key);
    184     alpm_trie_key_to_pfx(u, ipt, key, lpm_cfg->defip_sub_len, pfx);
    185 
    186     return ;
    187 }
    188 
    189 /* pfx in trie format => ip_addr
    190  * OUT: lpm_cfg->defip_ip6_addr/defip_ip_addr from trie format
    191  */
    192 void
    193 alpm_trie_pfx_to_cfg(int u, uint32 *pfx, int pfx_len, _bcm_defip_cfg_t *lpm_cfg)
    194 {
    195     /* Create Prefix */
    196     uint32 key[5] = {0};
    197     uint32 ipt = ALPM_LPM_IPT(u, lpm_cfg);
    198 
    199     alpm_trie_pfx_to_key(u, ipt, pfx, pfx_len, key);
    200     alpm_util_key_to_cfg(u, ipt, key, lpm_cfg);
    201     lpm_cfg->defip_sub_len = pfx_len;
    202     return ;
    203 }
    204 
    205 /* Convert TCAM entry to trie pfx format */
    206 int
    207 alpm_trie_ent_to_pfx(int u, int pkm, void *e, int sub_idx, int pfx_len,
    208                      uint32 *pfx)
    209 {
    210     int rv = BCM_E_UNAVAIL;
    211     uint32 key[4] = {0};
    212 
    213     rv = tcam_entry_to_key(u, pkm, e, sub_idx, key);
    214 
    215     if (BCM_SUCCESS(rv)) {
    216         alpm_trie_key_to_pfx(u, ALPM_PKM2IPT(pkm), key, pfx_len, pfx);
    217     }
    218 
    219     return rv;
    220 }
    221 
    222 static int
    223 alpm_trie_pfx_cb(alpm_lib_trie_node_t *node, void *user_data)
    224 {
    225     _alpm_bkt_pfx_arr_t *pfx_arr = (_alpm_bkt_pfx_arr_t *)user_data;
    226     if (node->type == trieNodeTypePayload) {
    227         pfx_arr->pfx[pfx_arr->pfx_cnt] = (_alpm_bkt_node_t *)node;
    228         pfx_arr->pfx_cnt++;
    229     }
    230     return BCM_E_NONE;
    231 }
    232 
    233 static int
    234 alpm_trie_max_split_len_cb(alpm_lib_trie_node_t *node, void *user_data)
    235 {
    236     int *pkm;
    237     int *pfx_len;
    238 
    239     if (node->type == trieNodeTypePayload) {
    240         uint32 key_len = ((_alpm_bkt_node_t *)node)->key_len;
    241         int max_pfx_len[] = {32, 64, 128};
    242         pkm     = (int *)user_data;
    243         pfx_len = (int *)user_data + 1;
    244 
    245         if (key_len == max_pfx_len[*pkm]) {
    246             *pfx_len = key_len;
    247             return BCM_E_BUSY;
    248         }
    249         if (*pfx_len < key_len) {
    250             *pfx_len = key_len;
    251         }
    252     }
    253     return BCM_E_NONE;
    254 }
    255 
    256 static void
    257 alpm_trie_max_split_attr(int u, _alpm_cb_t *acb, _alpm_pvt_node_t *pvt_node,
    258                          int *split_len,  int *split_cnt)
    259 {
    260     int splen = 0;
    261     int rv, pvt_len = 0;
    262     int kl, key_len[2] = {0};
    263     alpm_lib_trie_t  *bkt_trie = NULL;
    264     int vrf_id = PVT_BKT_VRF(pvt_node);
    265     int pkm, ipt = PVT_BKT_IPT(pvt_node);
    266 
    267     if (ALPM_IS_IPV6(ipt) && ALPM_128B(u)) {
    268         pkm = ALPM_PKM_128;
    269     } else {
    270         pkm = ipt;
    271     }
    272 
    273     if (ACB_BKT_FIXED_FMT(acb, vrf_id)) {
    274         int max_split_len[] = {32, 64, 128};
    275         splen = max_split_len[pkm] - 1;
    276     } else {
    277         pvt_len = PVT_KEY_LEN(pvt_node);
    278         bkt_trie = PVT_BKT_TRIE(pvt_node);
    279         key_len[0] = pkm;
    280 
    281         rv = alpm_lib_trie_traverse(bkt_trie, alpm_trie_max_split_len_cb, key_len,
    282                                     trieTraverseOrderIn);
    283         if (BCM_FAILURE(rv) && rv != BCM_E_BUSY) {
    284             ALPM_ERR(("alpm_lib_trie_traverse(bkt_trie) failed (%d)", rv));
    285         }
    286 
    287         kl = key_len[1];
    288         if (acb->acb_idx == 0) {
    289             splen = (pvt_len + kl + 1) * 1 / 2;
    290         } else {
    291             int splen1, splen2;
    292             splen1 = (int)ACB_VRF_SPLEN_DIFF1(u, acb, vrf_id, ipt);
    293             splen2 = (int)ACB_VRF_SPLEN_DIFF2(u, acb, vrf_id, ipt);
    294 
    295             if ((kl - pvt_len) <= splen1) {
    296                 splen = kl - splen2;
    297                 *split_cnt = 1 << splen2;
    298             } else {
    299                 splen = kl - splen1;
    300             }
    301             if (splen <= pvt_len) {
    302                 splen = (pvt_len + kl + 1) * 1 / 2;
    303             }
    304         }
    305     }
    306 
    307     *split_len = splen;
    308 
    309     return ;
    310 }
    311 
    312 static int
    313 alpm_trie_node_delete_cb(alpm_lib_trie_node_t *node, void *info)
    314 {
    315     if (node != NULL) {
    316         alpm_util_free(node);
    317     }
    318     return BCM_E_NONE;
    319 }
    320 
    321 static int
    322 alpm_trie_tree_destroy(int u, alpm_lib_trie_t *trie)
    323 {
    324     int rv = BCM_E_NONE;
    325     if (trie != NULL) {
    326         /* traverse bucket trie and clear it */
    327         rv = alpm_lib_trie_traverse(trie, alpm_trie_node_delete_cb,
    328                            NULL, trieTraverseOrderIn);
    329         if (BCM_SUCCESS(rv)) {
    330             alpm_lib_trie_destroy(trie);
    331         }
    332     }
    333 
    334     return rv;
    335 }
    336 
    337 static int
    338 alpm_trie_pvt_bkt_clear_cb(int u, _alpm_cb_t *acb,
    339                            _alpm_pvt_node_t *pvt_node, void *datum)
    340 {
    341     int rv = BCM_E_NONE;
    342     alpm_lib_trie_t *bkt_trie;
    343 
    344     bkt_trie = PVT_BKT_TRIE(pvt_node);
    345     ALPM_IER(alpm_trie_tree_destroy(u, bkt_trie));
    346     PVT_BKT_TRIE(pvt_node) = NULL;
    347 
    348     return rv;
    349 }
    350 
    351 static int
    352 alpm_trie_clear_all(int u)
    353 {
    354     int i, rv = BCM_E_NONE;
    355     int ipt, vrf_id;
    356     _alpm_cb_t *acb;
    357     alpm_lib_trie_t *pvt_trie = NULL, *vrf_trie = NULL;
    358 
    359     for (ipt = 0; ipt < ALPM_IPT_CNT; ipt ++) {
    360         for (vrf_id = 0; vrf_id <= ALPM_VRF_ID_MAX(u); vrf_id++) {
    361             for (i = 0; i < ACB_CNT(u); i++) {
    362                 acb = ACB(u, i);
    363                 if (!ACB_VRF_INITED(u, acb, vrf_id, ipt)) {
    364                     continue;
    365                 }
    366                 /* Clear Bucket Trie-tree */
    367                 rv = bcm_esw_alpm_pvt_traverse(u, i, vrf_id, ipt,
    368                         alpm_trie_pvt_bkt_clear_cb, NULL);
    369                 ALPM_IER(rv);
    370 
    371                 /* Clear PVT Trie-tree */
    372                 pvt_trie = ACB_PVT_TRIE(acb, vrf_id, ipt);
    373                 ALPM_IER(alpm_trie_tree_destroy(u, pvt_trie));
    374                 ACB_PVT_TRIE(acb, vrf_id, ipt) = NULL;
    375             }
    376 
    377             /* Clear Prefix Trie-tree */
    378             vrf_trie = ALPM_VRF_TRIE(u, vrf_id, ipt);
    379             ALPM_IER(alpm_trie_tree_destroy(u, vrf_trie));
    380             ALPM_VRF_TRIE(u, vrf_id, ipt) = NULL;
    381         }
    382     }
    383 
    384     return rv;
    385 }
    386 
    387 /* Fill Aux entry for operation */
    388 static void
    389 alpm_ppg_prepare(int u, _bcm_defip_cfg_t *lpm_cfg, int replace_len,
    390                  void *def_bkt_node, _alpm_ppg_data_t *ppg_data)
    391 {
    392     sal_memset(ppg_data, 0, sizeof(_alpm_ppg_data_t));
    393 
    394     ppg_data->vrf_id = ALPM_LPM_VRF_ID(u, lpm_cfg);
    395     ppg_data->ipt    = ALPM_LPM_IPT(u, lpm_cfg);
    396     ppg_data->key_len = lpm_cfg->defip_sub_len;
    397     ppg_data->bpm_len = replace_len;
    398     sal_memcpy(ppg_data->key, lpm_cfg->user_data, sizeof(ppg_data->key));
    399     /* Get assoc_data */
    400     ppg_data->bkt_def = def_bkt_node;
    401 
    402     return ;
    403 }
    404 
    405 static int
    406 alpm_ppg(int u, alpm_lib_trie_t *pivot, void *prefix, uint32 len,
    407          int insert, void *cb, void *user_data)
    408 {
    409     int rv = BCM_E_NONE;
    410     uint32 pvt_len = 0;
    411     alpm_lib_trie_node_t *lpm_pvt = NULL;
    412     alpm_lib_trie_bpm_cb_info_t cb_info;
    413 
    414     cb_info.pfx = (void *)prefix;
    415     cb_info.len = len;
    416     cb_info.user_data = user_data;
    417 
    418     /* Find longest prefix match(pivot) of route */
    419     ALPM_IER(alpm_lib_trie_find_lpm(pivot, prefix, len, &lpm_pvt));
    420     pvt_len = (TRIE_ELEMENT_GET(_alpm_pvt_node_t *, lpm_pvt, node))->key_len;
    421 
    422     if (pivot->v6_key) {
    423         rv = _alpm_lib_trie_v6_ppg_prefix(lpm_pvt, pvt_len,
    424                 (void *)prefix, len, cb, &cb_info);
    425     } else {
    426         rv = _alpm_lib_trie_ppg_prefix(lpm_pvt, pvt_len,
    427                 (void *)prefix, len, cb, &cb_info);
    428     }
    429 
    430     return rv;
    431 }
    432 
    433 static int
    434 alpm_ppg_assoc_data_cb(alpm_lib_trie_node_t *trie, alpm_lib_trie_bpm_cb_info_t *info)
    435 {
    436     int rv = BCM_E_NONE, unit;
    437     int update_pvt = 0;
    438     uint32 pfx_len, rpl_bpm_len, pvt_bpm_len;
    439 
    440     _alpm_cb_t *acb;
    441     _alpm_ppg_cb_user_data_t *user_data;
    442     _alpm_ppg_data_t *ppg_data;
    443     _alpm_pvt_node_t *pvt_node;
    444     _alpm_bkt_node_t *pvt_def, *ppg_def;
    445 
    446     user_data = info->user_data;
    447     unit     = user_data->unit;
    448     ppg_data = user_data->ppg_data;
    449     acb      = user_data->ppg_acb;
    450 
    451     pvt_node    = (_alpm_pvt_node_t *)trie;
    452     pvt_bpm_len = PVT_BPM_LEN(pvt_node);
    453     pfx_len     = ppg_data->key_len;
    454     rpl_bpm_len = ppg_data->bpm_len;
    455 
    456     /* bypass MC (direct route) for ppg in case of mix UC & MC in same VRF */
    457     if (PVT_IS_IPMC(pvt_node)) {
    458         return rv;
    459     }
    460 
    461     if (user_data->ppg_op == ALPM_PPG_INSERT) {
    462         rpl_bpm_len = pfx_len;
    463     }
    464 
    465     /* Addr & Mask has been screened by propagate function,
    466      * no need to do it again */
    467     if (user_data->ppg_op == ALPM_PPG_INSERT) {
    468         if (pvt_bpm_len > pfx_len) {
    469             /* Not qualified and stop from traversing its child nodes */
    470             return SOC_E_LIMIT;
    471         }
    472     }
    473 
    474     if (user_data->ppg_op == ALPM_PPG_DELETE) {
    475         if (pvt_bpm_len != pfx_len) {
    476             /* Not qualified and stop from traversing its child nodes */
    477             return (pvt_bpm_len > pfx_len) ? SOC_E_LIMIT : SOC_E_NONE;
    478         }
    479     }
    480 
    481     /* Update bpm_length accordingly */
    482     PVT_BPM_LEN(pvt_node) = rpl_bpm_len;
    483 
    484     /* Update PVT_BKT_DEF for pvt_node and do PPG again */
    485     pvt_def = PVT_BKT_DEF(pvt_node);
    486     ppg_def = (_alpm_bkt_node_t *)ppg_data->bkt_def;
    487     if (pvt_def == NULL || ppg_def == NULL || pvt_def == ppg_def) {
    488         update_pvt = 1;
    489     } else {
    490         if (sal_memcmp(&pvt_def->adata, &ppg_def->adata,
    491                        sizeof(_alpm_bkt_adata_t)) != 0) {
    492             update_pvt = 1;
    493         }
    494     }
    495 
    496     PVT_BKT_DEF(pvt_node) = ppg_def;
    497     if (update_pvt) {
    498         rv = alpm_pvt_update_by_pvt_node(unit, acb, pvt_node,
    499                 ALPM_PVT_UPDATE_ASSOC_DATA | ALPM_PVT_UPDATE_ALPM_DATA);
    500     }
    501 
    502     /* Update callback count */
    503     user_data->ppg_cnt++;
    504 
    505     return rv;
    506 }
    507 
    508 static int
    509 alpm_ppg_hitbit_cb(alpm_lib_trie_node_t *trie, alpm_lib_trie_bpm_cb_info_t *info)
    510 {
    511     int rv = BCM_E_NONE, unit;
    512     uint32 pfx_len, pvt_bpm_len;
    513 
    514     _alpm_cb_t *acb;
    515     _alpm_ppg_cb_user_data_t *user_data;
    516     _alpm_ppg_data_t *ppg_data;
    517     _alpm_pvt_node_t *pvt_node;
    518 
    519     user_data = info->user_data;
    520     unit     = user_data->unit;
    521     ppg_data = user_data->ppg_data;
    522     acb      = user_data->ppg_acb;
    523 
    524     pvt_node    = (_alpm_pvt_node_t *)trie;
    525     pvt_bpm_len = PVT_BPM_LEN(pvt_node);
    526     pfx_len     = ppg_data->key_len;
    527 
    528     /* Addr & Mask has been screened by propagate function,
    529      * no need to do it again */
    530     if (pvt_bpm_len != pfx_len) {
    531         /* Not qualified and stop from traversing its child nodes */
    532         return BCM_E_NONE;
    533     }
    534 
    535     /* New idx of def_pfx was already updated in regular routine,
    536      * Just simply update pivot */
    537     rv = alpm_pvt_update_by_pvt_node(unit, acb, pvt_node, ALPM_PVT_UPDATE_ASSOC_DATA);
    538 
    539     /* Update callback count */
    540     user_data->ppg_cnt++;
    541 
    542     return rv;
    543 }
    544 
    545 /* Software propagation */
    546 int
    547 alpm_ppg_op(int u, int ppg_op, void *cb, _alpm_ppg_data_t *ppg_data)
    548 {
    549     int i, rv = BCM_E_NONE;
    550     int insert = 0;
    551     uint32 vrf_id = 0;
    552     uint32 ipt;
    553 
    554     alpm_lib_trie_t *pvt_trie;
    555     _alpm_cb_t *acb;
    556     _alpm_ppg_cb_user_data_t user_data;
    557 
    558     switch (ppg_op) {
    559         case ALPM_PPG_INSERT:
    560             insert = 1;
    561             break;
    562         case ALPM_PPG_DELETE:
    563             insert = 0;
    564             break;
    565         case ALPM_PPG_HBP:
    566             insert = 0;
    567             break;
    568         default:
    569             return BCM_E_NONE;
    570     }
    571 
    572     vrf_id   = ppg_data->vrf_id;
    573     ipt      = ppg_data->ipt;
    574 
    575     user_data.unit     = u;
    576     user_data.ppg_data = ppg_data;
    577     user_data.ppg_op   = ppg_op;
    578     user_data.ppg_cnt  = 0;
    579 
    580     for (i = 0; i < ACB_CNT(u); i++) {
    581         acb = ACB(u, i);
    582         if (ACB_VRF_EMPTY(acb, vrf_id)) {
    583             continue;
    584         }
    585         user_data.ppg_acb  = acb;
    586 
    587         pvt_trie = ACB_PVT_TRIE(acb, vrf_id, ipt);
    588         if (pvt_trie) {
    589             rv = alpm_ppg(u, pvt_trie, ppg_data->key, ppg_data->key_len,
    590                           insert, cb, &user_data);
    591         }
    592     }
    593 
    594     return rv;
    595 
    596 }
    597 
    598 int
    599 alpm_ppg_assoc_data(int u, int ppg_op, _alpm_ppg_data_t *ppg_data)
    600 {
    601     return alpm_ppg_op(u, ppg_op, alpm_ppg_assoc_data_cb, ppg_data);
    602 }
    603 
    604 int
    605 alpm_ppg_hitbit(int u, int vrf_id, int ipt, uint32 *key, int key_len)
    606 {
    607     _alpm_ppg_data_t ppg_data;
    608 
    609     if (ALPM_HIT_SKIP(u)) {
    610         return BCM_E_NONE;
    611     }
    612 
    613     if (!ALPM_TCAM_HB_IS_PTR(u)) {
    614         return BCM_E_NONE;
    615     }
    616 
    617     sal_memset(&ppg_data, 0, sizeof(_alpm_ppg_data_t));
    618     ppg_data.ipt     = ipt;
    619     ppg_data.vrf_id  = vrf_id;
    620     ppg_data.key_len = key_len;
    621     sal_memcpy(ppg_data.key, key, sizeof(ppg_data.key));
    622 
    623     return alpm_ppg_op(u, ALPM_PPG_HBP, alpm_ppg_hitbit_cb, &ppg_data);
    624 }
    625 
    626 /* Delete ALPM pvt trie only for Direct Routes */
    627 int
    628 alpm_pvt_trie_delete(int u, _bcm_defip_cfg_t *lpm_cfg)
    629 {
    630     int                 rv = BCM_E_NONE;
    631     int                 vrf_id = ALPM_LPM_VRF_ID(u, lpm_cfg);
    632     int                 ipt = ALPM_LPM_IPT(u, lpm_cfg);
    633     alpm_lib_trie_t              *pvt_trie = NULL;
    634     _alpm_pvt_node_t    *pvt_node = NULL;
    635 
    636     pvt_trie = ACB_PVT_TRIE(ACB_TOP(u), vrf_id, ipt);
    637     rv = alpm_lib_trie_delete(pvt_trie, lpm_cfg->user_data,
    638                      lpm_cfg->defip_sub_len, (alpm_lib_trie_node_t **)&pvt_node);
    639     if (BCM_FAILURE(rv)) {
    640         ALPM_ERR(("Trie delete node failure\n"));
    641     }
    642 
    643     alpm_util_free(pvt_node);
    644     return rv;
    645 }
    646 
    647 /* Insert ALPM pvt trie only for Direct Routes which is needed in _tcam_match */
    648 int
    649 alpm_pvt_trie_insert(int u, _bcm_defip_cfg_t *lpm_cfg)
    650 {
    651     int                 rv = BCM_E_NONE;
    652     int                 vrf_id = ALPM_LPM_VRF_ID(u, lpm_cfg);
    653     alpm_lib_trie_t              *pvt_trie = NULL;
    654     _alpm_pvt_node_t    *pvt_node = NULL;
    655 
    656     ALPM_ALLOC_EG(pvt_node, sizeof(_alpm_pvt_node_t), "pvt_node");
    657     PVT_BKT_VRF(pvt_node) = vrf_id;
    658     PVT_BKT_PKM(pvt_node) = ALPM_LPM_PKM(u, lpm_cfg);
    659     PVT_IDX(pvt_node)     = lpm_cfg->defip_index;
    660     /* Direct route pvt_node doesn't use bkt_trie, def_pfx & bkt_info */
    661     PVT_KEY_LEN(pvt_node) = lpm_cfg->defip_sub_len;
    662     PVT_KEY_CPY(pvt_node, lpm_cfg->user_data);
    663     PVT_FLAGS(pvt_node) = lpm_cfg->defip_flags;
    664 
    665     pvt_trie = ACB_PVT_TRIE(ACB_TOP(u), vrf_id, PVT_BKT_IPT(pvt_node));
    666     rv = alpm_lib_trie_insert(pvt_trie, lpm_cfg->user_data,
    667                               lpm_cfg->defip_sub_len, (alpm_lib_trie_node_t *)pvt_node);
    668     return rv;
    669 
    670 bad:
    671     if (pvt_node != NULL) {
    672         alpm_util_free(pvt_node);
    673     }
    674     return rv;
    675 }
    676 
    677 /* ALPM pvt trie init only for Direct Routes */
    678 int
    679 alpm_pvt_trie_init(int u, int vrf_id, int ipt)
    680 {
    681     int         rv = BCM_E_NONE;
    682     uint32      max_key_len;
    683     _alpm_cb_t  *acb = ACB_TOP(u);
    684 
    685     max_key_len = alpm_util_trie_max_key_len(u, ipt);
    686     ALPM_IER(alpm_lib_trie_init(max_key_len, &ACB_PVT_TRIE(acb, vrf_id, ipt)));
    687     ACB_VRF_INIT_SET(u, acb, vrf_id, ipt);
    688     /* VRF DR partially inited: help to decide alpm_vrf_init
    689        for case of mix MC & UC, in alpm_cb_insert */
    690     ACB_DR_INIT_SET(u, acb, vrf_id, ipt);
    691 
    692     return rv;
    693 }
    694 
    695 static int
    696 alpm_pvt_find_by_key(int u, _alpm_cb_t *acb, int vrf_id, int ipt,
    697                      uint32 *key, uint32 key_len, _alpm_pvt_node_t **pvt_node)
    698 {
    699     int             rv = BCM_E_NONE;
    700     alpm_lib_trie_t          *pvt_trie;
    701 
    702     pvt_trie = ACB_PVT_TRIE(acb, vrf_id, ipt);
    703     rv = alpm_lib_trie_find_lpm(pvt_trie, key, key_len,
    704                        (alpm_lib_trie_node_t **)pvt_node);
    705     if (BCM_FAILURE(rv)) {
    706         ALPM_INFO(("**ACB(%d).PVT.FIND failed %d\n", ACB_IDX(acb), rv));
    707     }
    708 
    709     return rv;
    710 }
    711 
    712 /*
    713  * OUT: pvt_node
    714  */
    715 static int
    716 alpm_pvt_find(int u, _alpm_cb_t *acb, _bcm_defip_cfg_t *lpm_cfg,
    717               _alpm_pvt_node_t **pvt_node)
    718 {
    719     int rv;
    720     rv = alpm_pvt_find_by_key(u, acb, ALPM_LPM_VRF_ID(u, lpm_cfg),
    721                               ALPM_LPM_IPT(u, lpm_cfg), lpm_cfg->user_data,
    722                               lpm_cfg->defip_sub_len, pvt_node);
    723     return rv;
    724 }
    725 
    726 static int
    727 alpm_pvt_insert(int u, _alpm_cb_t *acb,
    728                 _bcm_defip_cfg_t *lpm_cfg)
    729 {
    730     int rv = 0;
    731 
    732     if (ACB_HAS_TCAM(acb)) {
    733         rv = bcm_esw_alpm_tcam_insert(u, lpm_cfg, ALPM_PVT_UPDATE_ALL);
    734     } else {
    735         rv = alpm_cb_insert(u, ACB_UPR(u, acb), lpm_cfg);
    736     }
    737 
    738     ALPM_INFO(("**ACB(%d).PVT.ADD rv %d\n", ACB_IDX(acb), rv));
    739 
    740     if (BCM_SUCCESS(rv)) {
    741         VRF_PVT_LEN_CNT_ADD(acb, ALPM_LPM_VRF_ID(u, lpm_cfg),
    742             ALPM_LPM_IPT(u, lpm_cfg), lpm_cfg->defip_sub_len);
    743     }
    744 
    745     return rv;
    746 }
    747 
    748 static int
    749 alpm_pvt_delete(int u, _alpm_cb_t *acb, _bcm_defip_cfg_t *lpm_cfg)
    750 {
    751     int rv = 0;
    752 
    753     if (ACB_HAS_TCAM(acb)) {
    754         rv = bcm_esw_alpm_tcam_delete(u, lpm_cfg);
    755         if (BCM_FAILURE(rv)) {
    756             ALPM_ERR(("**ACB(%d).PVT.DEL tcam_delete 0x%x/%d vrf %d failed %d\n",
    757                       ACB_IDX(acb), lpm_cfg->defip_ip_addr,
    758                       lpm_cfg->defip_sub_len, lpm_cfg->defip_vrf, rv));
    759         }
    760     } else {
    761         rv = alpm_cb_delete(u, ACB_UPR(u, acb), lpm_cfg);
    762     }
    763 
    764     ALPM_INFO(("**ACB(%d).PVT.DEL rv %d\n", ACB_IDX(acb), rv));
    765 
    766     if (BCM_SUCCESS(rv)) {
    767         VRF_PVT_LEN_CNT_DEC(acb, ALPM_LPM_VRF_ID(u, lpm_cfg),
    768             ALPM_LPM_IPT(u, lpm_cfg), lpm_cfg->defip_sub_len);
    769     }
    770 
    771     return rv;
    772 }
    773 
    774 static int
    775 alpm_pvt_delete_by_pvt_node(int u, _alpm_cb_t *acb, _alpm_pvt_node_t *pvt_node)
    776 {
    777     int rv = BCM_E_NONE;
    778     _bcm_defip_cfg_t lpm_cfg;
    779 
    780     sal_memset(&lpm_cfg, 0, sizeof(lpm_cfg));
    781 
    782     /* defip_flags */
    783     if (PVT_BKT_TRIE(pvt_node) &&
    784         PVT_BKT_TRIE(pvt_node)->v6_key) {
    785         lpm_cfg.defip_flags |= BCM_L3_IP6;
    786     }
    787 
    788     /* Key & Length */
    789     alpm_trie_pfx_to_cfg(u, pvt_node->key, PVT_KEY_LEN(pvt_node), &lpm_cfg);
    790     sal_memcpy(lpm_cfg.user_data, pvt_node->key, sizeof(pvt_node->key));
    791     lpm_cfg.defip_vrf = ALPM_VRF_ID_TO_VRF(u, PVT_BKT_VRF(pvt_node));
    792 
    793     /* Assoc-data */
    794     if (PVT_BKT_DEF(pvt_node) != NULL) {
    795         alpm_util_adata_trie_to_cfg(u, &PVT_BKT_DEF(pvt_node)->adata, &lpm_cfg);
    796     } else {
    797         lpm_cfg.default_miss = 1;
    798     }
    799 
    800     rv = alpm_pvt_delete(u, acb, &lpm_cfg);
    801 
    802     return rv;
    803 }
    804 
    805 /* delete newly created pivot from alpm_cb_path_construct if bucket is empty:
    806    unable to insert route in Level3 due to FULL */
    807 static int
    808 alpm_pvt_delete_by_empty_bkt(int u, _alpm_cb_t *acb, _bcm_defip_cfg_t *lpm_cfg)
    809 {
    810     int rv = BCM_E_NONE;
    811     int vrf_id, ipt;
    812     int bkt_empty;
    813     alpm_lib_trie_t *bkt_trie = NULL;
    814     alpm_lib_trie_node_t *tn = NULL;
    815     _alpm_pvt_node_t *pvt_node = lpm_cfg->pvt_node;
    816 
    817     if (ACB_HAS_TCAM(acb) || pvt_node == NULL) {
    818         return rv; /* no need to check */
    819     }
    820 
    821     vrf_id = ALPM_LPM_VRF_ID(u, lpm_cfg);
    822     ipt    = ALPM_LPM_IPT(u, lpm_cfg);
    823     bkt_trie = PVT_BKT_TRIE(pvt_node);
    824 
    825     /* Delete pvt entry if bucket is empty */
    826     bkt_empty = (PVT_KEY_LEN(pvt_node) != 0 && bkt_trie->trie == NULL);
    827     if (!bkt_empty) {
    828         return rv; /* no need to delete pvt if bkt is not empty */
    829     }
    830 
    831     rv = alpm_pvt_delete_by_pvt_node(u, acb, pvt_node);
    832     ALPM_IER(rv);
    833 
    834     rv = alpm_lib_trie_delete(ACB_PVT_TRIE(acb, vrf_id, ipt), pvt_node->key,
    835                      PVT_KEY_LEN(pvt_node), &tn);
    836     if (BCM_FAILURE(rv)) {
    837         ALPM_ERR(("Trie delete node failure\n"));
    838     }
    839 
    840     (void)alpm_lib_trie_destroy(bkt_trie);
    841     alpm_util_free(pvt_node);
    842 
    843     return rv;
    844 }
    845 
    846 static int
    847 alpm_pvt_update(int u, _alpm_cb_t *acb, _bcm_defip_cfg_t *lpm_cfg, uint32 write_flags)
    848 {
    849     int rv = BCM_E_NONE;
    850 
    851     _alpm_cb_t *upr_acb = NULL;
    852     _alpm_pvt_node_t *pvt_node = NULL;
    853     _alpm_bkt_node_t *bkt_node = NULL;
    854 
    855     if (ACB_HAS_TCAM(acb)) {
    856         /* Use insert routine to update */
    857         rv = bcm_esw_alpm_tcam_insert(u, lpm_cfg, write_flags);
    858         if (BCM_FAILURE(rv)) {
    859             ALPM_ERR(("**ACB(%d).PVT.UPD tcam_insert failed %d\n",
    860                       ACB_IDX(acb), rv));
    861         }
    862     } else {
    863         upr_acb = ACB_UPR(u, acb);
    864         rv = alpm_cb_find(u, upr_acb, lpm_cfg, &pvt_node, &bkt_node);
    865         if (BCM_SUCCESS(rv)) {
    866             rv = alpm_bkt_ent_write(u, upr_acb, pvt_node, lpm_cfg,
    867                                     bkt_node->ent_idx, write_flags);
    868         } else {
    869             ALPM_ERR(("pvt_update->alpm_cb_find: rv %d, ACB.%d pvt_node=%p, bkt_node=%p\n",
    870                       rv, ACB_IDX(upr_acb), pvt_node, bkt_node));
    871         }
    872     }
    873 
    874     ALPM_INFO(("**ACB(%d).PVT.UPD rv %d\n", ACB_IDX(acb), rv));
    875 
    876     return rv;
    877 }
    878 
    879 static int
    880 alpm_pvt_update_by_pvt_node(int u, _alpm_cb_t *acb, _alpm_pvt_node_t *pvt_node, uint32 write_flags)
    881 {
    882     int rv = BCM_E_NONE;
    883     _bcm_defip_cfg_t lpm_cfg;
    884 
    885     if (ALPMC(u)->_alpm_dbg_bmp & _ALPM_DBG_PVT_UPDATE_SKIP) {
    886         return rv;
    887     }
    888 
    889     sal_memset(&lpm_cfg, 0, sizeof(lpm_cfg));
    890 
    891     /* defip_flags */
    892     if (PVT_BKT_TRIE(pvt_node) &&
    893         PVT_BKT_TRIE(pvt_node)->v6_key) {
    894         lpm_cfg.defip_flags |= BCM_L3_IP6;
    895     }
    896 
    897     /* Key & Length */
    898     alpm_trie_pfx_to_cfg(u, pvt_node->key, PVT_KEY_LEN(pvt_node), &lpm_cfg);
    899     sal_memcpy(lpm_cfg.user_data, pvt_node->key, sizeof(pvt_node->key));
    900     lpm_cfg.defip_vrf = ALPM_VRF_ID_TO_VRF(u, PVT_BKT_VRF(pvt_node));
    901 
    902     /* Assoc-data */
    903     if (PVT_BKT_DEF(pvt_node) != NULL) {
    904         alpm_util_adata_trie_to_cfg(u, &PVT_BKT_DEF(pvt_node)->adata, &lpm_cfg);
    905     } else {
    906         lpm_cfg.default_miss = 1;
    907     }
    908 
    909     if (ACB_HAS_TCAM(acb)) {
    910         lpm_cfg.pvt_node = (uint32 *)pvt_node;
    911     } else {
    912         if (ACB_BKT_FIXED_FMT(acb, 1)) {
    913             lpm_cfg.bkt_kshift = 0;
    914         } else {
    915             lpm_cfg.bkt_kshift = PVT_KEY_LEN(pvt_node); /* for upr acb bkt */
    916         }
    917     }
    918     lpm_cfg.bkt_info = &PVT_BKT_INFO(pvt_node);
    919 
    920     rv = alpm_pvt_update(u, acb, &lpm_cfg, write_flags);
    921 
    922     return rv;
    923 }
    924 
    925 static int
    926 alpm_bkt_find(int u, _alpm_cb_t *acb,
    927               _bcm_defip_cfg_t *lpm_cfg,
    928               _alpm_pvt_node_t *pvt_node,
    929               _alpm_bkt_node_t **bkt_node)
    930 {
    931     int rv = BCM_E_NOT_FOUND;
    932     alpm_lib_trie_t *bkt_trie = PVT_BKT_TRIE(pvt_node);
    933     if (bkt_trie) {
    934         rv = alpm_lib_trie_search(bkt_trie, lpm_cfg->user_data, lpm_cfg->defip_sub_len,
    935                          (alpm_lib_trie_node_t **)bkt_node);
    936     }
    937     return rv;
    938 }
    939 
    940 static int
    941 alpm_bkt_ent_del(int u, _alpm_cb_t *acb, _alpm_pvt_node_t *pvt_node,
    942                  int ent_idx)
    943 {
    944     int rv = BCM_E_NONE;
    945     /* ALPMTBD */
    946     return rv;
    947 }
    948 
    949 int
    950 alpm_bkt_ent_get_attempt(int u, _alpm_cb_t *acb, _alpm_bkt_pool_conf_t *bp_conf,
    951                  _alpm_bkt_info_t *bkt_info, uint8 def_fmt,
    952                  int pfx_len, uint32 *ent_idx, int *fmt_update, int bkt_test)
    953 {
    954     /* Start with shorter prefix fmt */
    955     int i, rv = BCM_E_NONE;
    956     uint8 min_fmt = 0xff;
    957     int start, close, step;
    958     int bnkpb = BPC_BNK_PER_BKT(bp_conf);
    959     int rofs  = BI_ROFS(bkt_info);
    960     uint32 eidx = 0;
    961 
    962     /* Different bucket use different method for allocation, then after split,
    963      * bank distribution will be like this:
    964      bank 1:
    965         ----> Bank 0: FMT1[*_______________]
    966         ----> Bank 1: FMT3[**********______]
    967         ----> Bank 2: FMT3[**********______]
    968         ----> Bank 3: FMT3[**********______]
    969         ----> Bank 4: FMT3[**********______]
    970         ----> Bank 5: FMT3[________________]
    971         ----> Bank 6: FMT3[________________]
    972         ----> Bank 7: FMT3[________________]
    973      bank 2:
    974         ----> Bank 0: FMT1[________________]
    975         ----> Bank 1: FMT1[________________]
    976         ----> Bank 2: FMT1[________________]
    977         ----> Bank 3: FMT1[________________]
    978         ----> Bank 4: FMT3[**______________]
    979         ----> Bank 5: FMT3[**********______]
    980         ----> Bank 6: FMT3[**********______]
    981         ----> Bank 7: FMT3[**********______]
    982      */
    983 
    984     if (!BPC_BKT_WRA(bp_conf) || bkt_info->reverse == 0) {
    985         start = rofs;
    986         close = rofs + bnkpb;
    987         step  = 1;
    988     } else {
    989         start = rofs + bnkpb - 1;
    990         close = rofs - 1;
    991         step  = -1;
    992     }
    993 
    994     /* First round is to get a bank that:
    995      *  with valid fmt type (assigned) AND
    996      *  proper prefix length AND
    997      *  bank is not full
    998      *
    999      *  go through each bank to find the most efficient fmt
   1000  */
   1001     for (i = start; ABS(i-close) > 0; i += step) {
   1002         uint8 bnk_fmt = bkt_info->bnk_fmt[i % bnkpb];
   1003         uint32 vet_bmp = bkt_info->vet_bmp[i % bnkpb];
   1004 
   1005         /* Ignore invalid fmt type */
   1006         if (!BI_BNK_IS_USED(bkt_info, i % bnkpb) ||
   1007             bnk_fmt > BPC_FMT_CNT(bp_conf)) {
   1008             continue;
   1009         }
   1010 
   1011         /* Ignore full bank */
   1012         if (vet_bmp == (1 << BPC_FMT_ENT_MAX(bp_conf, bnk_fmt)) - 1) {
   1013             continue;
   1014         }
   1015 
   1016         /* Ignore unfit fmt 1bit Length should be considered */
   1017         if (!BPC_BKT_FIXED_FMT(bp_conf) &&
   1018             pfx_len > BPC_FMT_PFX_LEN(bp_conf, bnk_fmt)) {
   1019             continue;
   1020         }
   1021 
   1022         if (bnk_fmt < min_fmt) {
   1023             min_fmt = bnk_fmt;
   1024             eidx = i % bnkpb;
   1025         }
   1026     }
   1027 
   1028     /* ent_idx format
   1029      * -------------------------------
   1030      * | ent idx | bnk idx | bkt idx |
   1031      * -------------------------------
   1032      */
   1033     /* Now we find the bank, also need to find the empty slot in this bank */
   1034     if (min_fmt != 0xff) {
   1035         for (i = 0; i < BPC_FMT_ENT_MAX(bp_conf, min_fmt); i++) {
   1036             if ((bkt_info->vet_bmp[eidx] & (1 << i)) == 0) {
   1037                 if (!bkt_test) {
   1038                     bkt_info->bnk_fmt[eidx] = min_fmt;
   1039                     bkt_info->vet_bmp[eidx] |= 1 << i;
   1040                     *ent_idx = ALPM_IDX_MAKE(acb, bkt_info, eidx, i);
   1041                 }
   1042                 goto end;
   1043             }
   1044         }
   1045     }
   1046 
   1047     if (BPC_BKT_FIXED_FMT(bp_conf)) {
   1048         rv = BCM_E_FULL;
   1049         goto end;
   1050     }
   1051 
   1052     /* do second round if missed in the first round:
   1053      *  bank fmt is not fit (e.g. prefix length is shorter) BUT
   1054      *  this bank is empty, SO
   1055      *  we change the bank fmt and make it available.
   1056      */
   1057     for (i = start; ABS(i-close) > 0; i += step) {
   1058         uint8 fmt, bnk_fmt = bkt_info->bnk_fmt[i % bnkpb];
   1059         uint32 vet_bmp = bkt_info->vet_bmp[i % bnkpb];
   1060 
   1061         /* Ignore invalid fmt type */
   1062         if (!BI_BNK_IS_USED(bkt_info, i % bnkpb) ||
   1063             bnk_fmt > BPC_FMT_CNT(bp_conf) ||
   1064             vet_bmp != 0) {
   1065             continue;
   1066         }
   1067 
   1068         /* vet_bmp is empty && bnk_fmt is valid
   1069          * from most efficient def_fmt (matches route mode) to least efficient fmt */
   1070         for (fmt = def_fmt; fmt <= BPC_FMT_CNT(bp_conf); fmt++) {
   1071             if (pfx_len <= BPC_FMT_PFX_LEN(bp_conf, fmt)) {
   1072                 /* Entry 0 of bank i */
   1073                 if (!bkt_test) {
   1074                     bkt_info->vet_bmp[i % bnkpb] |= 1;
   1075                     bkt_info->bnk_fmt[i % bnkpb] = fmt;
   1076                     *ent_idx = ALPM_IDX_MAKE(acb, bkt_info, i % bnkpb, 0);
   1077 
   1078                     if (bnk_fmt != fmt && fmt_update != NULL) {
   1079                         *fmt_update = TRUE;
   1080                     }
   1081                 }
   1082                 goto end;
   1083             }
   1084         }
   1085     }
   1086 
   1087     rv = BCM_E_FULL;
   1088 end:
   1089     if (rv == BCM_E_FULL) {
   1090         ALPM_VERB(("**ACB(%d).ENT.get: failed (FULL)\n", ACB_IDX(acb)));
   1091     }
   1092     return rv;
   1093 }
   1094 
   1095 int
   1096 alpm_bkt_ent_write(int u, _alpm_cb_t *acb,
   1097                    _alpm_pvt_node_t *pvt_node,
   1098                    _bcm_defip_cfg_t *lpm_cfg, int ent_idx, uint32 write_flags)
   1099 {
   1100     int rv;
   1101     rv = ALPM_DRV(u)->alpm_bkt_ent_write(u, acb, pvt_node, lpm_cfg, ent_idx, write_flags);
   1102     return rv;
   1103 }
   1104 
   1105 static int
   1106 alpm_bkt_bnks_get(int u, int vrf_id, _alpm_cb_t *acb,
   1107                   _alpm_bkt_info_t *bkt_info, int *count)
   1108 {
   1109     int rv = BCM_E_NONE;
   1110     int i, bnk_cnt = 0;
   1111 
   1112     for (i = 0; i < ALPM_BPB_MAX; i++) {
   1113         uint8 bnk_fmt = bkt_info->bnk_fmt[i];
   1114         if (BI_BNK_IS_USED(bkt_info, i) &&
   1115             bnk_fmt <= ACB_FMT_CNT(acb, vrf_id)) {
   1116             bnk_cnt ++;
   1117         }
   1118     }
   1119 
   1120     if (count) {
   1121         *count = bnk_cnt;
   1122     }
   1123 
   1124     return rv;
   1125 }
   1126 
   1127 static int
   1128 alpm_bkt_ent_get(int u, int vrf_id, _alpm_cb_t *acb,
   1129                  _alpm_pvt_node_t *pvt_node, int pfx_len,
   1130                  uint32 *ent_idx, int *fmt_update, int bkt_test)
   1131 {
   1132     int rv = BCM_E_NONE;
   1133     uint8 def_fmt;
   1134     _alpm_bkt_info_t *bkt_info = &PVT_BKT_INFO(pvt_node);
   1135 
   1136     def_fmt = alpm_util_bkt_def_fmt_get(u, acb, vrf_id, PVT_BKT_IPT(pvt_node));
   1137     rv = alpm_bkt_ent_get_attempt(u, acb, ACB_BKT_VRF_POOL(acb, vrf_id),
   1138                           bkt_info, def_fmt, pfx_len,
   1139                           ent_idx, fmt_update, bkt_test);
   1140     if (rv == BCM_E_FULL) {
   1141         int bnk_cnt = 0;
   1142         /* If all banks are full, check if bucket expansion is required */
   1143         alpm_bkt_bnks_get(u, vrf_id, acb, bkt_info, &bnk_cnt);
   1144         if (ACB_BNK_PER_BKT(acb, vrf_id) > bnk_cnt) {
   1145             if (bkt_test) {
   1146                 return BCM_E_NONE;
   1147             }
   1148             /* To do bucket expansion here */
   1149             if (ACB_BKT_FIXED_FMT(acb, vrf_id)) {
   1150                 rv = alpm_cb_expand_in_bkt(u, acb, pvt_node, bnk_cnt);
   1151             } else {
   1152                 rv = alpm_cb_expand(u, acb, pvt_node, bnk_cnt, fmt_update);
   1153             }
   1154             if (BCM_SUCCESS(rv)) {
   1155                 rv = alpm_bkt_ent_get_attempt(u, acb,
   1156                         ACB_BKT_VRF_POOL(acb, vrf_id),
   1157                         bkt_info, def_fmt, pfx_len,
   1158                         ent_idx, fmt_update, bkt_test);
   1159             }
   1160         }
   1161     }
   1162 
   1163     return rv;
   1164 }
   1165 
   1166 static int
   1167 alpm_bkt_bnk_chk_rsvd(int u, int ipt, _alpm_bkt_pool_conf_t *bp_conf, int bnk)
   1168 {
   1169     int rv = BCM_E_NONE;
   1170     int used = 0;
   1171     SHR_BITDCL *bnk_bmp;
   1172 
   1173     bnk_bmp = BPC_BNK_BMP(bp_conf, ipt);
   1174 
   1175     SHR_BITTEST_RANGE(bnk_bmp, bnk, 1, used);
   1176     if (used) {
   1177         rv = BCM_E_NOT_FOUND;
   1178     } else {
   1179         SHR_BITSET_RANGE(bnk_bmp, bnk, 1);
   1180         BPC_BNK_USED(bp_conf, ipt) += 1;
   1181     }
   1182 
   1183     return rv;
   1184 }
   1185 
   1186 static int
   1187 alpm_bkt_bnk_alloc_reverse(int u, int ipt, _alpm_bkt_pool_conf_t *bp_conf,
   1188                            int *bnk, int alloc_sz, int step)
   1189 {
   1190     int rv = BCM_E_NONE;
   1191     int i, bnk_cnt, bnk_end, used = 0;
   1192     SHR_BITDCL *bnk_bmp;
   1193 
   1194     bnk_bmp = BPC_BNK_BMP(bp_conf, ipt);
   1195     bnk_cnt = BPC_BNK_CNT(bp_conf);
   1196     bnk_end = bnk_cnt - alloc_sz + 1;
   1197     for (i = bnk_end - 1; i >= 0; i += step) {
   1198         SHR_BITTEST_RANGE(bnk_bmp, i, alloc_sz, used);
   1199         if (!used) {
   1200             break;
   1201         }
   1202     }
   1203 
   1204     if (i < 0) { /* include *start_bnk is used when step=0xfffffff */
   1205         rv = BCM_E_NOT_FOUND;
   1206     } else {
   1207         SHR_BITSET_RANGE(bnk_bmp, i, alloc_sz);
   1208         BPC_BNK_USED(bp_conf, ipt) += alloc_sz;
   1209         *bnk = i;
   1210     }
   1211 
   1212     if (rv == BCM_E_NONE) {
   1213         ALPM_INFO(("bnk alloc start %d sz %d\n", *bnk, alloc_sz));
   1214     }
   1215 
   1216     return rv;
   1217 }
   1218 
   1219 static int
   1220 alpm_bkt_bnk_alloc(int u, int ipt, _alpm_bkt_pool_conf_t *bp_conf,
   1221                    int *bnk, int alloc_sz, int step)
   1222 {
   1223     int rv = BCM_E_NONE;
   1224     int i, bnk_cnt, bnk_end, used = 0;
   1225     SHR_BITDCL *bnk_bmp;
   1226 
   1227     if (step < 0) {
   1228         return alpm_bkt_bnk_alloc_reverse(u, ipt, bp_conf, bnk, alloc_sz, step);
   1229     }
   1230 
   1231     bnk_bmp = BPC_BNK_BMP(bp_conf, ipt);
   1232     bnk_cnt = BPC_BNK_CNT(bp_conf);
   1233     bnk_end = bnk_cnt - alloc_sz + 1;
   1234     i = bnk_end;
   1235     if (step == BPC_BNK_PER_BKT(bp_conf)) {
   1236         for (i = 0; i < bnk_end; i += step) {
   1237             SHR_BITTEST_RANGE(bnk_bmp, i, step, used);
   1238             if (!used) {
   1239                 break;
   1240             }
   1241         }
   1242     }
   1243 
   1244     if (i >= bnk_end) {
   1245         for (i = 0; i < bnk_end; i += step) {
   1246             SHR_BITTEST_RANGE(bnk_bmp, i, alloc_sz, used);
   1247             if (!used) {
   1248                 break;
   1249             }
   1250         }
   1251     }
   1252 
   1253     if (i >= bnk_end) { /* include *start_bnk is used when step=0xfffffff */
   1254         rv = BCM_E_NOT_FOUND;
   1255     } else {
   1256         SHR_BITSET_RANGE(bnk_bmp, i, alloc_sz);
   1257         BPC_BNK_USED(bp_conf, ipt) += alloc_sz;
   1258         *bnk = i;
   1259     }
   1260 
   1261     if (rv == BCM_E_NONE) {
   1262         ALPM_INFO(("bnk alloc start %d sz %d\n", *bnk, alloc_sz));
   1263     }
   1264 
   1265     return rv;
   1266 }
   1267 
   1268 static void
   1269 alpm_bkt_sub_bkt_info(int u, _alpm_cb_t *acb, int vrf_id, int ipt,
   1270                      _alpm_bkt_pool_conf_t *bp_conf,
   1271                      int start_bnk, int range, int *rt_ipt, uint32 *sub_bkt_bmp)
   1272 {
   1273     int i, bnk_pbk;
   1274     SHR_BITDCL *bnk_bmp;
   1275     _alpm_pvt_node_t *pvt_node;
   1276 
   1277     bnk_bmp = BPC_BNK_BMP(bp_conf, ipt);
   1278     bnk_pbk = BPC_BNK_PER_BKT(bp_conf);
   1279     for (i = start_bnk; i < start_bnk + range; i++) {
   1280         if (SHR_BITGET(bnk_bmp, i)) {
   1281             int tab_idx =
   1282                 ALPM_TAB_IDX_GET_BKT_BNK(acb, 0, i / bnk_pbk, i % bnk_pbk);
   1283             pvt_node =
   1284                 (_alpm_pvt_node_t *)ACB_VRF_PVT_PTR(acb, vrf_id, tab_idx);
   1285             if (pvt_node != NULL) {
   1286                 *rt_ipt = PVT_BKT_IPT(pvt_node);
   1287                 *sub_bkt_bmp |= 1 << BI_SUB_BKT_IDX(&pvt_node->bkt_info);
   1288             }
   1289         }
   1290     }
   1291 
   1292     return ;
   1293 }
   1294 
   1295 static int
   1296 alpm_bkt_pkm_sbkt_chk(int u, _alpm_cb_t *acb, int vrf_id, int ipt,
   1297                       _alpm_bkt_pool_conf_t *bp_conf,
   1298                       int start_bnk, int range,
   1299                       uint16 *sub_bkt_idx, int *sub_bkt_ipt)
   1300 {
   1301     uint32 sub_bkt_bmp = 0;
   1302 
   1303     uint16 first_sub_bkt[] = {
   1304         0, /* 0b0000 */ 1, /* 0b0001 */ 0, /* 0b0010 */ 2, /* 0b0011 */
   1305         0, /* 0b0100 */ 1, /* 0b0101 */ 0, /* 0b0110 */ 3, /* 0b0111 */
   1306         0, /* 0b1000 */ 1, /* 0b1001 */ 0, /* 0b1010 */ 2, /* 0b1011 */
   1307         0, /* 0b1100 */ 1, /* 0b1101 */ 0, /* 0b1110 */
   1308     };
   1309 
   1310     *sub_bkt_ipt = -1;
   1311     alpm_bkt_sub_bkt_info(u, acb, vrf_id, ipt, bp_conf, start_bnk, range,
   1312                           sub_bkt_ipt, &sub_bkt_bmp);
   1313     /* All 4 sub-pkts are used */
   1314     if (sub_bkt_bmp >= 0xf) {
   1315         return BCM_E_NOT_FOUND;
   1316     }
   1317 
   1318     *sub_bkt_idx = first_sub_bkt[sub_bkt_bmp];
   1319     return BCM_E_NONE;
   1320 }
   1321 
   1322 /* step == 0xfffffff means check if *start_bnk is occupied */
   1323 static int
   1324 alpm_bkt_sharing_bnk_alloc(int u, _alpm_cb_t *acb, int vrf_id, int ipt,
   1325                            _alpm_bkt_pool_conf_t *bp_conf,
   1326                            _alpm_bkt_info_t *bkt_info, int *avl_sz,
   1327                            int start_bnk, int alloc_sz, int step)
   1328 {
   1329     int rv = BCM_E_NONE;
   1330     int i, j, bnks, bnk_cnt, bnk_end, bnk_pbk, used;
   1331     uint16 sub_bkt_idx = 0;
   1332     int count, range = 0;
   1333     int check_avl, max_avl_sz = 0;
   1334     SHR_BITDCL *bnk_bmp;
   1335 
   1336     sal_memset(bkt_info, 0, sizeof(_alpm_bkt_info_t));
   1337     bnk_bmp = BPC_BNK_BMP(bp_conf, ipt);
   1338     bnk_cnt = BPC_BNK_CNT(bp_conf);
   1339     bnk_pbk = BPC_BNK_PER_BKT(bp_conf);
   1340 
   1341     /* if step == 0xfffffff means check_exist */
   1342     check_avl = (alloc_sz == 1) && (step > (bnk_cnt + bnk_pbk));
   1343     assert(check_avl || (start_bnk == 0 && step == bnk_pbk));
   1344 
   1345     /* Case 1: Check if a bank is available */
   1346     if (check_avl) {
   1347         i = start_bnk;
   1348         range = alloc_sz;
   1349         if (!SHR_BITGET(bnk_bmp, i)) {
   1350             goto _done;
   1351         }
   1352 
   1353         return BCM_E_NOT_FOUND;
   1354     }
   1355 
   1356     /* Case 2: Allocate bank from empty buckets */
   1357     range = bnk_pbk;
   1358     bnk_end = bnk_cnt - range + 1;
   1359     for (i = 0; i < bnk_end; i += step) {
   1360         SHR_BITTEST_RANGE(bnk_bmp, i, range, used);
   1361         if (!used) {
   1362             break;
   1363         }
   1364     }
   1365     if (i < bnk_end) {
   1366         goto _done;
   1367     }
   1368 
   1369     /* Case 3: Allocate bank from non-empty buckets
   1370      * WARNING: V4/V6 should not be sharing same bucket */
   1371     i = 0;
   1372     while (i < bnk_end) {
   1373         SHR_BITCOUNT_RANGE(bnk_bmp, count, i, range);
   1374         if (range == count) {
   1375             i += step;
   1376             continue;
   1377         }
   1378 
   1379         if ((range - count) > max_avl_sz) {
   1380             int bkt_ipt;
   1381             rv = alpm_bkt_pkm_sbkt_chk(u, acb, vrf_id, ipt, bp_conf, i, range,
   1382                                        &sub_bkt_idx, &bkt_ipt);
   1383             if (rv == BCM_E_NOT_FOUND || bkt_ipt != ipt) {
   1384                 i += step;
   1385                 continue;
   1386             }
   1387 
   1388             max_avl_sz = range - count;
   1389             if (max_avl_sz >= alloc_sz) {
   1390                 /* Check available sub_bkt_idx,
   1391                  * total sub_bkt_idx cnt is 4,
   1392                  * check_exist case doesn't need sub_bkt_idx
   1393                  */
   1394                 break;
   1395             }
   1396         }
   1397 
   1398         i += step;
   1399     }
   1400 
   1401     if (i >= bnk_end) {
   1402         if (avl_sz != NULL) {
   1403             *avl_sz = max_avl_sz;
   1404         }
   1405         return BCM_E_NOT_FOUND;
   1406     }
   1407 
   1408 _done:
   1409     BI_ROFS(bkt_info) = 0;
   1410     BI_BKT_IDX(bkt_info) = i / bnk_pbk;
   1411     BI_SUB_BKT_IDX(bkt_info) = sub_bkt_idx;
   1412     bnks = 0;
   1413     for (j = i; j < i+range; j++) {
   1414         if (!SHR_BITGET(bnk_bmp, j)) {
   1415             bkt_info->bnk_fmt[j % bnk_pbk] =
   1416                 alpm_util_bkt_def_fmt_get(u, acb, vrf_id, ipt);
   1417             /* bkt_info->vet_bmp default to 0 */
   1418             SHR_BITSET(bnk_bmp, j);
   1419             if (++bnks >= alloc_sz) {
   1420                 break;
   1421             }
   1422         }
   1423     }
   1424 
   1425     BPC_BNK_USED(bp_conf, ipt) += alloc_sz;
   1426 
   1427     return rv;
   1428 }
   1429 
   1430 int
   1431 alpm_bkt_bnk_free(int u, int ipt, _alpm_cb_t *acb,
   1432                   _alpm_bkt_pool_conf_t *bp_conf,
   1433                   _alpm_bkt_info_t *bkt_info, int bnk)
   1434 {
   1435     int gbl_bnk, bkt_bnk, tab_idx;
   1436     SHR_BITDCL *bnk_bmp;
   1437 
   1438     bnk_bmp = BPC_BNK_BMP(bp_conf, ipt);
   1439     bkt_bnk = BPC_BNK_PER_BKT(bp_conf);
   1440     gbl_bnk = BI_BKT_IDX(bkt_info) * bkt_bnk + bnk;
   1441     if (BI_ROFS(bkt_info) > bnk) {
   1442         gbl_bnk += bkt_bnk;
   1443     }
   1444 
   1445     if (!SHR_BITGET(bnk_bmp, gbl_bnk)) {
   1446         return BCM_E_PARAM;
   1447     }
   1448     SHR_BITCLR(bnk_bmp, gbl_bnk);
   1449     BPC_BNK_USED(bp_conf, ipt) -= 1;
   1450 
   1451     tab_idx = ALPM_TAB_IDX_GET_BI_BNK(acb, bkt_info, bnk);
   1452     if (bp_conf->pvt_ptr != NULL) {
   1453         bp_conf->pvt_ptr[tab_idx] = NULL;
   1454     }
   1455 
   1456     /* Suppose to update bkt_info->rofs when bnk is freed */
   1457     if (BPC_BKT_WRA(bp_conf) && bnk == BI_ROFS(bkt_info) &&
   1458         (gbl_bnk < (BPC_BNK_CNT(bp_conf) - 1))) {
   1459         int new_rofs = (bnk + 1) % bkt_bnk;
   1460         if (new_rofs < BI_ROFS(bkt_info)) {
   1461             BI_BKT_IDX(bkt_info)++;
   1462         }
   1463         BI_ROFS(bkt_info) = new_rofs;
   1464     }
   1465 
   1466     BI_BNK_FREE(bkt_info, bnk);
   1467 
   1468     ALPM_INFO(("bnk  free bnk %d \n", gbl_bnk));
   1469 
   1470     acb->acb_cnt.c_bnkfree++;
   1471 
   1472     return BCM_E_NONE;
   1473 }
   1474 
   1475 static int
   1476 alpm_bkt_bnk_shrink(int u, int ipt, _alpm_cb_t *acb, _alpm_bkt_pool_conf_t *bp_conf,
   1477                     _alpm_bkt_info_t *bkt_info, int *fmt_update)
   1478 {
   1479     int i, bnkpb, bnk;
   1480     int bnks, bnke;
   1481 
   1482     bnkpb = BPC_BNK_PER_BKT(bp_conf);
   1483 
   1484     /* Store bnks and bnke because alpm_bkt_bnk_free could change rofs value */
   1485     bnks  = BI_ROFS(bkt_info);
   1486     bnke  = bnkpb + BI_ROFS(bkt_info);
   1487 
   1488     for (i = bnks; i < bnke; i++) {
   1489         bnk = i % bnkpb;
   1490         if (BI_BNK_IS_USED(bkt_info, bnk) && bkt_info->vet_bmp[bnk] == 0) {
   1491             /* Release bank bnk */
   1492             ALPM_INFO(("**ACB(%d).BNK.RLS: RBBE (%d %d %d *)\n",
   1493                        ACB_IDX(acb), -1, BI_BKT_IDX(bkt_info), bnk));
   1494 
   1495             if (fmt_update != NULL) {
   1496                 *fmt_update = 1;
   1497             }
   1498             ALPM_IER(alpm_bkt_bnk_free(u, ipt, acb, bp_conf, bkt_info, bnk));
   1499         }
   1500     }
   1501 
   1502     acb->acb_cnt.c_bnkshrk++;
   1503 
   1504     return BCM_E_NONE;
   1505 }
   1506 
   1507 /* _alpm_bkt_alloc_full to make sure a entire bucket
   1508  * is allocated or return FULL */
   1509 static int
   1510 alpm_bkt_alloc_attempt(int u, _alpm_cb_t *acb, int vrf_id, int ipt,
   1511                        int req_bnk_cnt, int step, _alpm_bkt_info_t *bkt_info,
   1512                        int *avl_bnk_cnt)
   1513 {
   1514     int rv;
   1515     int i, bnk = 0, bnkpb;
   1516 
   1517     if (ACB_BKT_FIXED_FMT(acb, vrf_id)) {
   1518         rv = alpm_bkt_sharing_bnk_alloc(u, acb, vrf_id, ipt,
   1519                     ACB_BKT_VRF_POOL(acb, vrf_id), bkt_info, avl_bnk_cnt,
   1520                     0, req_bnk_cnt, step);
   1521     } else {
   1522         rv = alpm_bkt_bnk_alloc(u, ipt, ACB_BKT_VRF_POOL(acb, vrf_id), &bnk,
   1523                                 req_bnk_cnt, bkt_info->reverse ? -1 : step);
   1524         if (BCM_SUCCESS(rv)) {
   1525             bnkpb = ACB_BNK_PER_BKT(acb, vrf_id);
   1526             BI_ROFS(bkt_info) = bnk % bnkpb;
   1527             BI_BKT_IDX(bkt_info) = bnk / bnkpb;
   1528             sal_memset(bkt_info->vet_bmp, 0, sizeof(bkt_info->vet_bmp));
   1529             sal_memset(bkt_info->bnk_fmt, 0, sizeof(bkt_info->bnk_fmt));
   1530             for (i = 0; i < req_bnk_cnt; i++) {
   1531                 bkt_info->bnk_fmt[(BI_ROFS(bkt_info) + i) % bnkpb]
   1532                     = alpm_util_bkt_def_fmt_get(u, acb, vrf_id, ipt);
   1533             }
   1534         }
   1535     }
   1536 
   1537     if (rv == BCM_E_NOT_FOUND) {
   1538         rv = BCM_E_FULL;
   1539     }
   1540 
   1541     return rv;
   1542 }
   1543 
   1544 int
   1545 alpm_bkt_bnk_nearest_get(int u, SHR_BITDCL *bnk_bmp, int bnk_sz,
   1546                          int left_bnk, int right_bnk, int *nst_bnk)
   1547 {
   1548     int i, rv = BCM_E_NONE;
   1549     int nst_left, nst_right;
   1550 
   1551     nst_left  = -1;
   1552     nst_right = bnk_sz;
   1553 
   1554     if (left_bnk >= 0) {
   1555         for (i = left_bnk; i >= 0; i--) {
   1556             if (!SHR_BITGET(bnk_bmp, i)) {  /* TBD performance */
   1557                 break;
   1558             }
   1559         }
   1560         nst_left = i;
   1561     }
   1562 
   1563     if (right_bnk < bnk_sz) {
   1564         for (i = right_bnk; i < bnk_sz; i++) {
   1565             if (!SHR_BITGET(bnk_bmp, i)) {  /* TBD performance */
   1566                 break;
   1567             }
   1568         }
   1569         nst_right = i;
   1570     }
   1571 
   1572     if (nst_left >= 0 && nst_right < bnk_sz) {
   1573         if ((left_bnk - nst_left) > (nst_right - right_bnk)) {
   1574             *nst_bnk = nst_right;
   1575         } else {
   1576             *nst_bnk = nst_left;
   1577         }
   1578     } else if (nst_left >= 0) {
   1579         *nst_bnk = nst_left;
   1580     } else if (nst_right < bnk_sz) {
   1581         *nst_bnk = nst_right;
   1582     } else {
   1583         rv = BCM_E_FULL;
   1584     }
   1585 
   1586     return rv;
   1587 }
   1588 
   1589 static int
   1590 alpm_bkt_pfx_ent_idx_update(int u, _alpm_cb_t *acb, _alpm_pvt_node_t *pvt_node,
   1591                             _alpm_bkt_info_t *src_bkt, int src_bnk,
   1592                             _alpm_bkt_info_t *dst_bkt, int dst_bnk)
   1593 {
   1594     int i, rv = BCM_E_UNAVAIL;
   1595     int sb = src_bnk;
   1596     int db = dst_bnk;
   1597     uint32 bak_idx;
   1598     _alpm_bkt_pfx_arr_t *pfx_arr = NULL;
   1599     _alpm_bkt_node_t *bkt_node = NULL;
   1600     alpm_lib_trie_t      *bkt_trie = NULL;
   1601 
   1602     bkt_trie = PVT_BKT_TRIE(pvt_node);
   1603     ALPM_ALLOC_EG(pfx_arr, sizeof(*pfx_arr), "pfx_arr");
   1604     rv = alpm_lib_trie_traverse(bkt_trie, alpm_trie_pfx_cb, pfx_arr,
   1605                        trieTraverseOrderIn);
   1606     ALPM_IEG(rv);
   1607     for (i = 0; i < pfx_arr->pfx_cnt; i++) {
   1608         int ent, bnk, bkt;
   1609 
   1610         bkt_node = pfx_arr->pfx[i];
   1611         ent = ALPM_IDX_TO_ENT(bkt_node->ent_idx);
   1612         bnk = ALPM_IDX_TO_BNK(acb, bkt_node->ent_idx);
   1613         bkt = ALPM_IDX_TO_BKT(acb, bkt_node->ent_idx);
   1614         if (bnk < PVT_ROFS(pvt_node)) {
   1615             bkt -= 1;
   1616         }
   1617 
   1618         if (src_bnk == -1) {
   1619             sb = bnk;
   1620             db = bnk;
   1621         }
   1622 
   1623         bak_idx = bkt_node->ent_idx;
   1624         if (bnk == sb && bkt == BI_BKT_IDX(src_bkt)) {
   1625             bkt_node->ent_idx = ALPM_IDX_MAKE(acb, dst_bkt, db, ent);
   1626             if (ALPM_TCAM_HB_IS_PTR(u) && bak_idx != bkt_node->ent_idx) {
   1627                 ALPM_IEG(alpm_ppg_hitbit(u, PVT_BKT_VRF(pvt_node),
   1628                             PVT_BKT_IPT(pvt_node), bkt_node->key, bkt_node->key_len));
   1629             }
   1630         }
   1631     }
   1632 
   1633 bad:
   1634     if (pfx_arr != NULL) {
   1635         alpm_util_free(pfx_arr);
   1636     }
   1637     return rv;
   1638 
   1639 }
   1640 
   1641 static int
   1642 alpm_bkt_bnk_copy(int u, _alpm_cb_t *acb, _alpm_pvt_node_t *pvt_node,
   1643                   _alpm_bkt_info_t *src_bkt, int src_bnk,
   1644                   _alpm_bkt_info_t *dst_bkt, int dst_bnk)
   1645 {
   1646     int rv = BCM_E_UNAVAIL;
   1647     int src_idx, dst_idx;
   1648 
   1649     src_idx = ALPM_TAB_IDX_GET_BI_BNK(acb, src_bkt, src_bnk);
   1650     dst_idx = ALPM_TAB_IDX_GET_BI_BNK(acb, dst_bkt, dst_bnk);
   1651     rv = ALPM_DRV(u)->alpm_bkt_bnk_copy(u, acb, pvt_node, src_bkt, dst_bkt,
   1652                                         src_idx, dst_idx);
   1653     if (BCM_SUCCESS(rv)) {
   1654         /* Performance improvement ALPMTBD in pfx_ent_idx_update */
   1655         rv = alpm_bkt_pfx_ent_idx_update(u, acb, pvt_node, src_bkt, src_bnk,
   1656                                          dst_bkt, dst_bnk);
   1657     }
   1658 
   1659     return rv;
   1660 }
   1661 
   1662 int
   1663 alpm_bkt_bnk_clear(int u, _alpm_cb_t *acb, _alpm_pvt_node_t *pvt_node,
   1664                    int tab_idx)
   1665 {
   1666     int rv = BCM_E_UNAVAIL;
   1667     rv = ALPM_DRV(u)->alpm_bkt_bnk_clear(u, acb, pvt_node, tab_idx);
   1668     return rv;
   1669 }
   1670 
   1671 /* Receive a new bank 'to_bnk' on one side and release old bank on
   1672  * another side
   1673  *
   1674  * When we reach here, to_bnk should be neighbour of pvt_node's bkt_info.
   1675  * After moving is done, free bank to free_bnk.
   1676  */
   1677 static int
   1678 alpm_bkt_bnk_ripple(int u, _alpm_cb_t *acb,
   1679                    _alpm_pvt_node_t *pvt_node, int to_bnk, int *free_bnk)
   1680 {
   1681     int i, ipt, rv = BCM_E_NONE;
   1682     int bnkpb, start_bnk, end_bnk, mv_bnk;
   1683     int mb, tb, tab_idx = 0;
   1684     uint8  bnk_fmt;
   1685     uint32 vet_bmp;
   1686     _alpm_bkt_info_t *bkt_info, dst_bkt;
   1687     int vrf_id;
   1688 
   1689     vrf_id = PVT_BKT_VRF(pvt_node);
   1690     ipt = PVT_BKT_IPT(pvt_node);
   1691     bkt_info = &PVT_BKT_INFO(pvt_node);
   1692     bnkpb = ACB_BNK_PER_BKT(acb, PVT_BKT_VRF(pvt_node));
   1693     start_bnk = PVT_ROFS(pvt_node);
   1694     /* Find end bank */
   1695     for (i = 1; i < bnkpb; i++) {
   1696         if (!BI_BNK_IS_USED(bkt_info, start_bnk % bnkpb)) {
   1697             start_bnk++;
   1698             i--;
   1699             continue;
   1700         }
   1701         if (!BI_BNK_IS_USED(bkt_info, (start_bnk+i) % bnkpb)) {
   1702             break;
   1703         }
   1704     }
   1705     start_bnk = PVT_BKT_IDX(pvt_node) * bnkpb + start_bnk;
   1706     end_bnk = start_bnk + i - 1;
   1707 
   1708     /* 1. copy bank on the other side to to_bnk */
   1709     /* S: start, E: end, T: to_bnk
   1710      -----------------     -----------------
   1711      | |#|#|#|#|#| | |  -> |#|#|#|#|#| | | |
   1712      -----------------     -----------------
   1713       ^ ^       ^                     ^
   1714       T S       E                     T
   1715      -----------------     -----------------
   1716      | |#|#|#|#|#| | |  -> | | |#|#|#|#|#| |
   1717      -----------------     -----------------
   1718         ^       ^ ^           ^
   1719         S       E T           T
   1720      */
   1721     if (to_bnk < start_bnk) {
   1722         mv_bnk = end_bnk;
   1723         /* Adjust start_bnk */
   1724         start_bnk = to_bnk;
   1725     } else {
   1726         mv_bnk = start_bnk;
   1727 
   1728         /* Adjust start_bnk */
   1729         start_bnk++;
   1730         while (start_bnk < end_bnk) {
   1731             if (!BI_BNK_IS_USED(bkt_info, start_bnk % bnkpb)) {
   1732                 start_bnk++;
   1733             } else {
   1734                 break;
   1735             }
   1736         }
   1737     }
   1738     mb = mv_bnk % bnkpb;
   1739     tb = to_bnk % bnkpb;
   1740 
   1741     /* Save src_idx before rofs, bkt-idx changes */
   1742     if (ACB_BKT_FIXED_FMT(acb, vrf_id)) {
   1743         tab_idx = ALPM_TAB_IDX_GET_BI_BNK(acb, bkt_info, mb);
   1744     }
   1745 
   1746     sal_memset(&dst_bkt, 0, sizeof(dst_bkt));
   1747     BI_ROFS(&dst_bkt)    = start_bnk % bnkpb;
   1748     BI_BKT_IDX(&dst_bkt) = start_bnk / bnkpb;
   1749 
   1750     ALPM_IER(alpm_bkt_bnk_copy(u, acb, pvt_node, bkt_info, mb,
   1751                                 &dst_bkt, tb));
   1752     /* 2. Update bkt_info info */
   1753     bnk_fmt = bkt_info->bnk_fmt[mb];
   1754     vet_bmp = bkt_info->vet_bmp[mb];
   1755     ALPM_IER(alpm_bkt_bnk_chk_rsvd(u, ipt, ACB_BKT_VRF_POOL(acb,
   1756              PVT_BKT_VRF(pvt_node)), to_bnk));
   1757     /* bkt_info could be changed here includes:
   1758      * rofs, bkt-idx, bnk_fmt, so we need to save those values.
   1759      */
   1760     ALPM_IER(alpm_bkt_bnk_free(u, ipt, acb,
   1761              ACB_BKT_VRF_POOL(acb, PVT_BKT_VRF(pvt_node)), bkt_info, mb));
   1762 
   1763     PVT_ROFS(pvt_node)    = BI_ROFS(&dst_bkt);
   1764     PVT_BKT_IDX(pvt_node) = BI_BKT_IDX(&dst_bkt);
   1765     bkt_info->bnk_fmt[tb] = bnk_fmt;
   1766     bkt_info->vet_bmp[tb] = vet_bmp;
   1767 
   1768     /* 3. Update PVT */
   1769     if (pvt_node != NULL) {
   1770         rv = alpm_pvt_update_by_pvt_node(u, acb, pvt_node, ALPM_PVT_UPDATE_ALPM_DATA);
   1771         ALPM_IER(rv);
   1772     }
   1773 
   1774     /* 4. invalidate old bnk */
   1775     if (ACB_BKT_FIXED_FMT(acb, vrf_id)) {
   1776         ALPM_IER(alpm_bkt_bnk_clear(u, acb, pvt_node, tab_idx));
   1777     }
   1778 
   1779     if (tb != mb) {
   1780         bkt_info->bnk_fmt[mb] = 0;
   1781         bkt_info->vet_bmp[mb] = 0;
   1782     }
   1783 
   1784     if (free_bnk != NULL) {
   1785         *free_bnk = mv_bnk;
   1786     }
   1787 
   1788     acb->acb_cnt.c_ripple++;
   1789 
   1790     return rv;
   1791 }
   1792 
   1793 static int
   1794 alpm_bkt_move(int u, _alpm_cb_t *acb, _alpm_pvt_node_t *pvt_node,
   1795               _alpm_bkt_info_t *src_bkt, _alpm_bkt_info_t *dst_bkt)
   1796 {
   1797     int rv = BCM_E_NONE;
   1798     int bnkpb, sbnk, dbnk;
   1799     int lsbnk, ldbnk; /* Local src/dst bnk */
   1800     _alpm_bkt_info_t tmp_bkt;
   1801     int vrf_id;
   1802 
   1803     vrf_id = PVT_BKT_VRF(pvt_node);
   1804     bnkpb = ACB_BNK_PER_BKT(acb, PVT_BKT_VRF(pvt_node));
   1805     dbnk  = BI_ROFS(dst_bkt);
   1806     ldbnk = dbnk % bnkpb;
   1807     while (!BI_BNK_IS_USED(dst_bkt, ldbnk)) {
   1808         dbnk ++;
   1809         ldbnk = dbnk % bnkpb;
   1810     }
   1811 
   1812     /* Copy */
   1813     for (sbnk = src_bkt->rofs; sbnk < src_bkt->rofs + bnkpb; sbnk++) {
   1814         lsbnk = sbnk % bnkpb;
   1815         ldbnk = dbnk % bnkpb;
   1816         if (!BI_BNK_IS_USED(src_bkt, lsbnk)) {
   1817             continue;
   1818         }
   1819 
   1820         dst_bkt->bnk_fmt[ldbnk] = src_bkt->bnk_fmt[lsbnk];
   1821         dst_bkt->vet_bmp[ldbnk] = src_bkt->vet_bmp[lsbnk];
   1822 
   1823         ALPM_IER(alpm_bkt_bnk_copy(u, acb, pvt_node, src_bkt, lsbnk,
   1824                                    dst_bkt, ldbnk));
   1825 
   1826         dbnk++;
   1827         ldbnk = dbnk % bnkpb;
   1828         while (!BI_BNK_IS_USED(dst_bkt, ldbnk)) {
   1829             dbnk++;
   1830             ldbnk = dbnk % bnkpb;
   1831         }
   1832     }
   1833 
   1834     /* swap src_bkt <-> dst_bkt info */
   1835     sal_memcpy(&tmp_bkt, src_bkt, sizeof(_alpm_bkt_info_t));
   1836     sal_memcpy(src_bkt, dst_bkt, sizeof(_alpm_bkt_info_t));
   1837     sal_memcpy(dst_bkt, &tmp_bkt, sizeof(_alpm_bkt_info_t));
   1838 
   1839     if (pvt_node != NULL) {
   1840         rv = alpm_pvt_update_by_pvt_node(u, acb, pvt_node, ALPM_PVT_UPDATE_ALPM_DATA);
   1841         ALPM_IER(rv);
   1842     }
   1843 
   1844     /* Invalidate src bucket */
   1845     for (sbnk = 0; sbnk < bnkpb; sbnk++) {
   1846         if (!BI_BNK_IS_USED(dst_bkt, sbnk)) {
   1847             continue;
   1848         }
   1849 
   1850         if (ACB_BKT_FIXED_FMT(acb, vrf_id)) {
   1851             ALPM_IER(alpm_bkt_bnk_clear(u, acb, pvt_node,
   1852                     ALPM_TAB_IDX_GET_BI_BNK(acb, dst_bkt, sbnk)));
   1853         }
   1854         dst_bkt->vet_bmp[sbnk] = 0;
   1855     }
   1856 
   1857     /* Release bnk to global pool */
   1858     ALPM_IER(alpm_bkt_bnk_shrink(u, PVT_BKT_IPT(pvt_node), acb,
   1859         ACB_BKT_VRF_POOL(acb, PVT_BKT_VRF(pvt_node)), dst_bkt, NULL));
   1860 
   1861     return rv;
   1862 }
   1863 
   1864 /*
   1865  *
   1866   0 1 2 3 4 5 6 7
   1867  -----------------
   1868  | |#|#|#|#|#|*|*|
   1869  -----------------
   1870   ^   --->  ^
   1871  from       to
   1872 
   1873  -----------------
   1874  | |*|*|*|#|#|#| |
   1875  -----------------
   1876           ^ <-- ^
   1877           to    from
   1878 
   1879  * PLEASE NOTICE THAT from_bnk AND to_bnk INDICATE FREE BANK LOCATION,
   1880  * NOT USED BANK LOCATION.
   1881  */
   1882 static int
   1883 alpm_bkt_free_bnk_move(int u, _alpm_cb_t *acb, _alpm_bkt_pool_conf_t *bp_conf,
   1884                        int from_bnk, int to_bnk)
   1885 {
   1886     int mv_bnk, step;
   1887     _alpm_pvt_node_t *pvt_node = NULL;
   1888     int tab_idx, free_bnk = -1, bnkpb;
   1889     int rv = BCM_E_NONE;
   1890 
   1891     bnkpb = BPC_BNK_PER_BKT(bp_conf);
   1892     step = from_bnk < to_bnk ? 1 : -1;
   1893     mv_bnk = from_bnk + step;
   1894     while (ABS(mv_bnk - to_bnk) >= 0) {
   1895         tab_idx = ALPM_TAB_IDX_GET_BKT_BNK(acb, 0,
   1896                     mv_bnk/bnkpb, mv_bnk%bnkpb);
   1897         if (bp_conf->pvt_ptr &&
   1898             bp_conf->pvt_ptr[tab_idx] == NULL) {
   1899             from_bnk = mv_bnk;
   1900             mv_bnk += step;
   1901             continue;
   1902         }
   1903 
   1904         if (bp_conf->pvt_ptr != NULL) {
   1905             pvt_node = (_alpm_pvt_node_t *)bp_conf->pvt_ptr[tab_idx];
   1906             rv = alpm_bkt_bnk_ripple(u, acb, pvt_node, from_bnk, &free_bnk);
   1907             ALPM_IEG(rv);
   1908             if (ALPMC(u)->_alpm_dbg_bmp & _ALPM_DBG_PVT_SANITY_NODE) {
   1909                 rv = alpm_cb_pvt_sanity_cb(u, acb, pvt_node, "FreeBnkMove");
   1910                 ALPM_IEG(rv);
   1911             }
   1912         }
   1913 
   1914         if (free_bnk == to_bnk) {
   1915             break;
   1916         } else {
   1917             from_bnk = free_bnk;
   1918             mv_bnk = from_bnk + step;
   1919         }
   1920     }
   1921 
   1922 bad:
   1923     return rv;
   1924 }
   1925 
   1926 /*
   1927  * To find a minimum range which contains req_cnt free banks
   1928  *
   1929  * min_left and min_right are return value indicate the range.
   1930  */
   1931 int
   1932 alpm_bkt_free_bnk_range_get(int u, SHR_BITDCL *bnk_bmp, int bnk_sz,
   1933                             int req_cnt, int *rng_left, int *rng_right,
   1934                             int *rng_mid)
   1935 {
   1936     int i, rv = BCM_E_NONE;
   1937     int alloc_sz, idx, free_cnt = 0;
   1938     int *free_bnk_arr = NULL;
   1939 
   1940     int min_idx = -1, min_range;
   1941 
   1942     alloc_sz = bnk_sz * sizeof(int);
   1943     ALPM_ALLOC_EG(free_bnk_arr, alloc_sz, "free_bnk_arr");
   1944     /*
   1945      -------------------------------------------------------------
   1946      | |#|#| | | |#|#|#|#| | |#|#| | |#|#| |#| |#| |#|#|#|#| | |#|
   1947      -------------------------------------------------------------
   1948       ^                                                         ^
   1949       0                                                        bnk_sz-1
   1950      */
   1951     min_range = bnk_sz;
   1952     for (i = 0; i < bnk_sz; i++) {
   1953         if (!SHR_BITGET(bnk_bmp, i)) {
   1954             free_bnk_arr[free_cnt] = i;
   1955             idx = free_cnt - (req_cnt - 1);
   1956             if (idx >= 0) {
   1957                 if (min_range > (free_bnk_arr[free_cnt] - free_bnk_arr[idx])) {
   1958                     min_range = (free_bnk_arr[free_cnt] - free_bnk_arr[idx]);
   1959                     min_idx = free_cnt;
   1960                 }
   1961             }
   1962             free_cnt ++;
   1963         }
   1964     }
   1965 
   1966     if (min_idx != -1) {
   1967         *rng_left = free_bnk_arr[min_idx - (req_cnt - 1)];
   1968         *rng_right = free_bnk_arr[min_idx];
   1969         *rng_mid = free_bnk_arr[min_idx - (req_cnt - 1) / 2];
   1970     } else {
   1971         rv = BCM_E_FULL;
   1972     }
   1973 
   1974 bad:
   1975     if (free_bnk_arr != NULL) {
   1976         alpm_util_free(free_bnk_arr);
   1977     }
   1978     return rv;
   1979 }
   1980 
   1981 static int
   1982 alpm_bkt_free(int u, _alpm_cb_t *acb, int vrf_id, int ipt,
   1983               _alpm_bkt_info_t *bkt_info)
   1984 {
   1985     int rv = BCM_E_NONE;
   1986     int bnk;
   1987     _alpm_bkt_pool_conf_t *bp_conf;
   1988 
   1989     bp_conf = ACB_BKT_VRF_POOL(acb, vrf_id);
   1990     for (bnk = 0; bnk < ALPM_BPB_MAX; bnk++) {
   1991         if (BI_BNK_IS_USED(bkt_info, bnk)) {
   1992             ALPM_IER(alpm_bkt_bnk_free(u, ipt, acb, bp_conf, bkt_info, bnk));
   1993         }
   1994     }
   1995     bkt_info->reverse = 0;
   1996 
   1997     return rv;
   1998 }
   1999 
   2000 /* OUT: bkt_info */
   2001 static int
   2002 alpm_bkt_alloc(int u, _alpm_cb_t *acb, int vrf_id, int ipt, int req_bnk_cnt,
   2003                _alpm_bkt_info_t *bkt_info, int *avl_bnk_cnt)
   2004 {
   2005     int rv = BCM_E_NONE;
   2006     rv = alpm_bkt_alloc_attempt(u, acb, vrf_id, ipt, req_bnk_cnt,
   2007                                 ACB_BNK_PER_BKT(acb, vrf_id), bkt_info,
   2008                                 avl_bnk_cnt);
   2009     if (rv != BCM_E_FULL) {
   2010         goto end;
   2011     }
   2012 
   2013     /* rv == BCM_E_FULL
   2014      *
   2015      * No free bkt available, start defragment process to create a
   2016      * new available bucket.
   2017      * It's also bucket sharing process for TH/TD3
   2018      */
   2019     if (ACB_BKT_FIXED_FMT(acb, vrf_id)) {
   2020         rv = alpm_cb_merge(u, acb, vrf_id, ipt);
   2021         return BCM_SUCCESS(rv) ? BCM_E_BUSY : rv;
   2022     }
   2023 
   2024     rv = alpm_cb_defrag(u, acb, vrf_id, ipt);
   2025     if (BCM_SUCCESS(rv)) {
   2026         rv = alpm_bkt_alloc_attempt(u, acb, vrf_id, ipt, req_bnk_cnt,
   2027                                     1, bkt_info, avl_bnk_cnt);
   2028     }
   2029 
   2030 end:
   2031     return rv;
   2032 }
   2033 
   2034 static int
   2035 alpm_bkt_insert(int u, _alpm_cb_t *acb,
   2036                 _bcm_defip_cfg_t *lpm_cfg, _alpm_pvt_node_t *pvt_node,
   2037                 uint32 *ent_idx)
   2038 {
   2039     int rv = BCM_E_NONE;
   2040     int fmt_update = 0;
   2041     int vrf_id = 0;
   2042     int pfx_len;
   2043 
   2044     vrf_id = PVT_BKT_VRF(pvt_node);
   2045     if (ACB_BKT_FIXED_FMT(acb, vrf_id)) {
   2046         pfx_len = lpm_cfg->defip_sub_len;
   2047     } else {
   2048         pfx_len = lpm_cfg->defip_sub_len - PVT_KEY_LEN(pvt_node);
   2049     }
   2050 
   2051     rv = alpm_bkt_ent_get(u, vrf_id, acb, pvt_node, pfx_len, ent_idx,
   2052                           &fmt_update, 0);
   2053     if (BCM_SUCCESS(rv)) {
   2054         rv = alpm_bkt_ent_write(u, acb, pvt_node, lpm_cfg, *ent_idx, ALPM_PVT_UPDATE_ALL);
   2055         if (BCM_SUCCESS(rv) && fmt_update && !ACB_BKT_FIXED_FMT(acb, vrf_id)) {
   2056             _alpm_tcam_write_t *tcam_write = lpm_cfg->tcam_write;
   2057 
   2058             if (tcam_write && (tcam_write->hw_idx >= 0)) {
   2059                 int rv1, pkm, ipt;
   2060                 ipt = PVT_BKT_IPT(pvt_node);
   2061                 pkm = ALPM_PKM_RECOVER(u, ipt);
   2062                 rv1 = _tcam_entry_write(u, pkm, tcam_write->ent, tcam_write->hw_idx,
   2063                                         tcam_write->hw_idx);
   2064                 ALPM_INFO(("Write to TCAM HW at hw_idx %d by pvt update (%d)\n",
   2065                            tcam_write->hw_idx, rv1));
   2066                 tcam_write->hw_idx = -1; /* avoid write again */
   2067             }
   2068 
   2069             rv = alpm_pvt_update_by_pvt_node(u, acb, pvt_node, ALPM_PVT_UPDATE_ALPM_DATA);
   2070         }
   2071         if (BCM_FAILURE(rv)) {
   2072             rv = alpm_bkt_ent_del(u, acb, pvt_node, *ent_idx);
   2073         }
   2074     }
   2075 
   2076     if (BCM_FAILURE(rv)) {
   2077         ALPM_VERB(("**ACB(%d).BKT.INS: failed %d\n", ACB_IDX(acb), rv));
   2078     }
   2079 
   2080     return rv;
   2081 }
   2082 
   2083 int
   2084 alpm_bkt_delete(int u, _alpm_cb_t *acb,
   2085                 _bcm_defip_cfg_t *lpm_cfg, _alpm_pvt_node_t *pvt_node,
   2086                 uint32 *key_idx)
   2087 {
   2088     int rv = BCM_E_NONE;
   2089 
   2090     /* ALPMTBD */
   2091 
   2092     return rv;
   2093 }
   2094 
   2095 static int
   2096 alpm_bkt_pfx_idx_backup(int u, _alpm_bkt_pfx_arr_t *pfx_arr, uint32 **bak_idx)
   2097 {
   2098     int i, rv = BCM_E_NONE;
   2099     int count = pfx_arr->pfx_cnt;
   2100     uint32 *pfx_idx;
   2101 
   2102     ALPM_ALLOC_EG(pfx_idx, count * sizeof(uint32), "bak_idx");
   2103 
   2104     for (i = 0; i < count; i++) {
   2105         pfx_idx[i] = pfx_arr->pfx[i]->ent_idx;
   2106     }
   2107 
   2108     if (bak_idx != NULL) {
   2109         *bak_idx = pfx_idx;
   2110     }
   2111 
   2112 bad:
   2113     return rv;
   2114 }
   2115 
   2116 static void
   2117 alpm_bkt_pfx_idx_restore(int u, _alpm_bkt_pfx_arr_t *pfx_arr, uint32 *bak_idx)
   2118 {
   2119     int i;
   2120     uint32 tmp_idx;
   2121     int count = pfx_arr->pfx_cnt;
   2122 
   2123     for (i = 0; i < count; i++) {
   2124         tmp_idx = pfx_arr->pfx[i]->ent_idx;
   2125         pfx_arr->pfx[i]->ent_idx = bak_idx[i];
   2126         bak_idx[i] = tmp_idx;
   2127     }
   2128 
   2129     return ;
   2130 }
   2131 
   2132 static int
   2133 alpm_bkt_pfx_copy(int u, _alpm_cb_t *acb,
   2134                   _alpm_bkt_pfx_arr_t *pfx_arr,
   2135                   _alpm_pvt_node_t *opvt_node,
   2136                   _alpm_pvt_node_t *npvt_node)
   2137 {
   2138     int i;
   2139     int rv = BCM_E_UNAVAIL;
   2140 
   2141     rv = ALPM_DRV(u)->alpm_bkt_pfx_copy(u, acb, pfx_arr, opvt_node,
   2142                                         npvt_node);
   2143     if (ALPM_TCAM_HB_IS_PTR(u)) {
   2144         for (i = 0; i < pfx_arr->pfx_cnt; i++) {
   2145             ALPM_IER(alpm_ppg_hitbit(u, PVT_BKT_VRF(opvt_node), PVT_BKT_IPT(opvt_node),
   2146                                   pfx_arr->pfx[i]->key, pfx_arr->pfx[i]->key_len));
   2147         }
   2148     }
   2149     return rv;
   2150 }
   2151 
   2152 static int
   2153 alpm_bkt_pfx_clean(int u, _alpm_cb_t *acb,
   2154                    _alpm_pvt_node_t *pvt_node,
   2155                    int count, uint32 *ent_idx)
   2156 {
   2157     int rv = BCM_E_UNAVAIL;
   2158 
   2159     rv = ALPM_DRV(u)->alpm_bkt_pfx_clean(u, acb, pvt_node, count, ent_idx);
   2160 
   2161     return rv;
   2162 }
   2163 
   2164 static int
   2165 alpm_bkt_pfx_shrink(int u, _alpm_cb_t *acb, _alpm_pvt_node_t *pvt_node, void *user_data)
   2166 {
   2167     int         i, rv = BCM_E_NONE;
   2168     uint32      *bak_idx = NULL;
   2169     alpm_lib_trie_t      *bkt_trie = NULL;
   2170     _alpm_bkt_pfx_arr_t *pfx_arr = NULL;
   2171     _alpm_bkt_info_t *bkt_info = NULL;
   2172     int         shrink_empty_only;
   2173     int         from_bkt_split = 0;
   2174 
   2175     bkt_info = &PVT_BKT_INFO(pvt_node);
   2176     shrink_empty_only = *(int *)user_data;
   2177     from_bkt_split = (shrink_empty_only == 2);
   2178     if (shrink_empty_only) {
   2179         int tb, tbnk;
   2180         int has_empty_bnk = 0;
   2181         int bnkpb = ACB_BNK_PER_BKT(acb, PVT_BKT_VRF(pvt_node));
   2182 
   2183         for (tb = BI_ROFS(bkt_info); tb < BI_ROFS(bkt_info) + bnkpb; tb++) {
   2184             tbnk = tb % bnkpb;
   2185             if (!BI_BNK_IS_USED(bkt_info, tbnk)) {
   2186                 continue;
   2187             }
   2188     	    if (bkt_info->vet_bmp[tbnk] == 0) {
   2189                 has_empty_bnk = 1;
   2190                 break;
   2191             }
   2192         }
   2193         if (!has_empty_bnk) {
   2194             if (from_bkt_split) {
   2195                 shrink_empty_only = 0;
   2196             } else {
   2197                 return rv;
   2198             }
   2199         }
   2200     }
   2201 
   2202     ALPM_ALLOC_EG(pfx_arr, sizeof(*pfx_arr), "pfx_arr");
   2203     bkt_trie = PVT_BKT_TRIE(pvt_node);
   2204     rv = alpm_lib_trie_traverse(bkt_trie, alpm_trie_pfx_cb, pfx_arr,
   2205                        trieTraverseOrderIn);
   2206     ALPM_IEG(rv);
   2207     rv = alpm_bkt_pfx_idx_backup(u, pfx_arr, &bak_idx);
   2208     ALPM_IEG(rv);
   2209 
   2210     rv = ALPM_DRV(u)->alpm_bkt_pfx_shrink(u, acb, pvt_node, pfx_arr,
   2211                                           shrink_empty_only);
   2212 
   2213     if (BCM_SUCCESS(rv)) {
   2214         int fmt_update = 0;
   2215         rv = alpm_bkt_bnk_shrink(u, PVT_BKT_IPT(pvt_node), acb,
   2216                 ACB_BKT_VRF_POOL(acb, PVT_BKT_VRF(pvt_node)),
   2217                 bkt_info, &fmt_update);
   2218         ALPM_IEG(rv);
   2219         if (fmt_update && !ACB_BKT_FIXED_FMT(acb, PVT_BKT_VRF(pvt_node))) {
   2220             rv = alpm_pvt_update_by_pvt_node(u, acb, pvt_node, ALPM_PVT_UPDATE_ALPM_DATA);
   2221             ALPM_IEG(rv);
   2222         }
   2223     }
   2224 
   2225     if (ALPM_TCAM_HB_IS_PTR(u)) {
   2226         for (i = 0; i < pfx_arr->pfx_cnt; i++) {
   2227             if (bak_idx[i] == pfx_arr->pfx[i]->ent_idx) {
   2228                 continue;
   2229             }
   2230             rv = alpm_ppg_hitbit(u, PVT_BKT_VRF(pvt_node), PVT_BKT_IPT(pvt_node),
   2231                                  pfx_arr->pfx[i]->key, pfx_arr->pfx[i]->key_len);
   2232             ALPM_IEG(rv);
   2233         }
   2234     }
   2235 
   2236 bad:
   2237 
   2238     if (bak_idx != NULL) {
   2239         alpm_util_free(bak_idx);
   2240     }
   2241 
   2242     if (pfx_arr != NULL) {
   2243         alpm_util_free(pfx_arr);
   2244     }
   2245 
   2246     return rv;
   2247 }
   2248 
   2249 static int
   2250 alpm_bkt_trie_split_cb(alpm_lib_trie_node_t *trie, alpm_lib_trie_bpm_cb_info_t *info)
   2251 {
   2252     /* trieNodeTypeInternalPpg indicates internally created node for ppg */
   2253     if (trie->type != trieNodeTypeInternalPpg) {
   2254         return alpm_trie_pfx_cb(trie, (void *)info->user_data);
   2255     }
   2256 
   2257     return BCM_E_NONE;
   2258 }
   2259 
   2260 int
   2261 alpm_bkt_split_cb(alpm_lib_trie_node_t *ptrie, alpm_lib_trie_node_t *trie,
   2262                   alpm_lib_trie_traverse_state_t *state, void *info)
   2263 {
   2264     _alpm_bkt_split_cb_data_t *cb_data = (_alpm_bkt_split_cb_data_t *)info;
   2265     /* Split from default bkt */
   2266     if (ACB_IDX(cb_data->acb) > 0 && cb_data->pvt_len == 0) {
   2267         if (ptrie->count < cb_data->bkt_cur_cnt &&
   2268             trie->count < ptrie->count) {
   2269             return 1;
   2270         }
   2271     }
   2272 
   2273     return 0;
   2274 }
   2275 
   2276 static int
   2277 alpm_bkt_trie_split(int u, _alpm_cb_t *acb,
   2278                     _bcm_defip_cfg_t *lpm_cfg,
   2279                     alpm_lib_trie_t **spl_bkt_trie,
   2280                     _alpm_pvt_node_t **spl_pvt_node,
   2281                     int max_key_len,
   2282                     int *max_spl_cnt)
   2283 {
   2284     int                 rv;
   2285     int                 pkm, ipt, vrf_id, max_split_len, bkt_cnt;
   2286     uint32              pvt_len, pvt_key[5] = {0};
   2287 
   2288     _alpm_pvt_node_t    *ppn = NULL, *cpn = NULL;
   2289     alpm_lib_trie_t     *pbt = NULL, *cbt = NULL;
   2290 
   2291     if (lpm_cfg->spl_pn != NULL) {
   2292         ppn = (_alpm_pvt_node_t *)lpm_cfg->spl_pn;
   2293     } else {
   2294         ppn = ACB_HAS_TCAM(acb) ? lpm_cfg->l1_pvt_node : lpm_cfg->pvt_node;
   2295     }
   2296     pbt = PVT_BKT_TRIE(ppn);
   2297     bkt_cnt = pbt->trie->count;
   2298     ALPM_IEG(alpm_lib_trie_init(max_key_len, &cbt));
   2299     pkm = ALPM_LPM_PKM(u, lpm_cfg);
   2300     ipt = ALPM_PKM2IPT(pkm);
   2301     vrf_id = ALPM_LPM_VRF_ID(u, lpm_cfg);
   2302 
   2303     if (lpm_cfg->spl_key_len != 0) {
   2304         rv = alpm_lib_trie_split2(pbt, lpm_cfg->spl_key, lpm_cfg->spl_key_len,
   2305                                   pvt_key, &pvt_len, &cbt->trie, 0xfffffff,
   2306                                   TRUE);
   2307     } else {
   2308         _alpm_bkt_split_cb_data_t scb_data;
   2309         scb_data.acb = acb;
   2310         scb_data.bkt_cur_cnt = pbt->trie->count;
   2311         scb_data.pvt_len = PVT_KEY_LEN(ppn);
   2312         alpm_trie_max_split_attr(u, acb, ppn, &max_split_len, max_spl_cnt);
   2313         rv = alpm_lib_trie_split(pbt, max_split_len, pvt_key, &pvt_len,
   2314                  &cbt->trie, FALSE,
   2315                  ACB_BKT_FIXED_FMT(acb, vrf_id) ? NULL : alpm_bkt_split_cb,
   2316                  &scb_data, *max_spl_cnt);
   2317     }
   2318     ALPM_IEG(rv);
   2319 
   2320     /* Split bucket2A in non-last level could cause misplaced routes in other
   2321      * buckets in next level of current level.
   2322      *   Note: bucket2A: bucketA in Level 2.
   2323      *         bucket3B: bucketB in Level 3.
   2324      *   Case 1:
   2325      *       If split node is trieNodeTypePayload node, no misplaced routes are generated.
   2326      *   Case 2:
   2327      *       If split node is trieNodeTypeInternal node, then:
   2328      *       Case 2.1:
   2329      *           If lpm of split node doesn't exist in this bucket2A, Good.
   2330      *       Case 2.2:
   2331      *           If lpm of split node(Say it's pivot of bucket3B) exists in this
   2332      *           bucket2A, then:
   2333      *
   2334      *           Case 2.2.1:
   2335      *               no route in bucket3B is covered by split node. Good.
   2336      *           Case 2.2.2:
   2337      *               routes in bucket3B are covered by split node.
   2338      *               ====> Misplaced Routes (Need to move them to new location)
   2339      */
   2340     if (ACB_HAS_PVT(acb, vrf_id)) {
   2341         if (cbt->trie->type == trieNodeTypeInternal) {
   2342             _alpm_pvt_node_t *spl_npn = NULL;
   2343             _alpm_bkt_node_t *lpm_bn = NULL;
   2344             _alpm_bkt_node_t tmp_bn;
   2345             /* Case 2 */
   2346             spl_npn = lpm_cfg->spl_npn;
   2347             if (spl_npn) {
   2348                 sal_memcpy(tmp_bn.key, spl_npn->key, sizeof(tmp_bn.key));
   2349                 tmp_bn.key_len = spl_npn->key_len;
   2350             }
   2351             if (spl_npn && spl_npn->key_len < pvt_len) {
   2352                 (void)alpm_lib_trie_insert(pbt, tmp_bn.key,
   2353                                            tmp_bn.key_len, (alpm_lib_trie_node_t *)&tmp_bn);
   2354             }
   2355             rv = alpm_lib_trie_find_lpm(pbt, pvt_key, pvt_len, (alpm_lib_trie_node_t **)&lpm_bn);
   2356             if (spl_npn && spl_npn->key_len < pvt_len) {
   2357                 (void)alpm_lib_trie_delete(pbt, tmp_bn.key,
   2358                                   tmp_bn.key_len, (alpm_lib_trie_node_t **)&tmp_bn);
   2359             }
   2360             if (BCM_FAILURE(rv)) {
   2361                 acb->acb_cnt.c_spl_mp_cs21++;
   2362                 rv = BCM_E_NONE;
   2363             } else {
   2364                 /* Case 2.2 */
   2365                 _alpm_cb_t *nxt_cb = NULL;
   2366                 _alpm_pvt_node_t *lpm_pn = NULL;
   2367                 _alpm_bkt_pfx_arr_t *pfx_arr = NULL;
   2368                 alpm_lib_trie_t      *pvt_trie;
   2369                 alpm_lib_trie_node_t *tmp_node;
   2370 
   2371                 nxt_cb = ACB_DWN(u, acb);
   2372                 pvt_trie = ACB_PVT_TRIE(nxt_cb, vrf_id, ipt);
   2373                 if (spl_npn && spl_npn->key_len < pvt_len) {
   2374                     (void)alpm_lib_trie_insert(pvt_trie, spl_npn->key,
   2375                                                spl_npn->key_len, (alpm_lib_trie_node_t *)spl_npn);
   2376                 }
   2377                 rv = alpm_pvt_find_by_key(u, nxt_cb, vrf_id, ipt,
   2378                         lpm_bn->key, lpm_bn->key_len, &lpm_pn);
   2379                 if (BCM_SUCCESS(rv) && PVT_BKT_TRIE(lpm_pn)->trie) {
   2380                     alpm_lib_trie_bpm_cb_info_t cb_info;
   2381                     ALPM_ALLOC_EG(pfx_arr, sizeof(*pfx_arr), "pfx_arr");
   2382                     cb_info.pfx = pvt_key;
   2383                     cb_info.len = pvt_len;
   2384                     cb_info.user_data = pfx_arr;
   2385                     /* PERF OPT point */
   2386                     rv = alpm_lib_trie_ppg(PVT_BKT_TRIE(lpm_pn), 0,
   2387                              pvt_key, pvt_len, alpm_bkt_trie_split_cb,
   2388                              &cb_info);
   2389                     if (BCM_SUCCESS(rv)) {
   2390                         if (pfx_arr->pfx_cnt == 0) {
   2391                             acb->acb_cnt.c_spl_mp_cs221++;
   2392                         } else {
   2393                             acb->acb_cnt.c_spl_mp_cs222++;
   2394 
   2395                             rv = BCM_E_BUSY;
   2396                             if (spl_npn && spl_npn == lpm_pn) {
   2397                                 lpm_cfg->spl_pn = lpm_cfg->spl_opn;
   2398                             } else {
   2399                                 lpm_cfg->spl_pn = lpm_pn;
   2400                             }
   2401                             sal_memcpy(lpm_cfg->spl_key, pvt_key, sizeof(lpm_cfg->spl_key));
   2402                             lpm_cfg->spl_key_len = pvt_len;
   2403                         }
   2404                     }
   2405                     alpm_util_free(pfx_arr);
   2406                 }
   2407                 if (spl_npn && spl_npn->key_len < pvt_len) {
   2408                     (void)alpm_lib_trie_delete(pvt_trie, spl_npn->key,
   2409                                       spl_npn->key_len, &tmp_node);
   2410                 }
   2411             }
   2412         } else {
   2413             /* Case 1: split node is trieNodeTypePayload node. */
   2414             acb->acb_cnt.c_spl_mp_cs1++;
   2415         }
   2416     }
   2417 
   2418     ALPM_IEG(rv);
   2419 
   2420     ALPM_ALLOC_EG(cpn, sizeof(_alpm_pvt_node_t), "pvt_node");
   2421     PVT_BKT_TRIE(cpn)  = cbt;
   2422     PVT_BKT_VRF(cpn)   = vrf_id;
   2423     PVT_BKT_PKM(cpn)   = pkm;
   2424     PVT_KEY_CPY(cpn, pvt_key);
   2425     PVT_KEY_LEN(cpn)   = pvt_len;
   2426     PVT_FLAGS(cpn)     = lpm_cfg->defip_flags;
   2427     *spl_pvt_node = cpn;
   2428     *spl_bkt_trie = cbt;
   2429 
   2430     ALPM_INFO(("**ACB(%d).BKT.SPLIT %d entries from bkt %d(cnt %d)\n",
   2431                ACB_IDX(acb), cbt->trie->count,
   2432                PVT_BKT_IDX(ppn), bkt_cnt));
   2433 
   2434     return rv;
   2435 
   2436 bad:
   2437 
   2438     if (cbt != NULL) {
   2439         if (cbt->trie != NULL) {
   2440             int rv2;
   2441             rv2 = alpm_lib_trie_merge(pbt, cbt->trie, pvt_key, pvt_len);
   2442             if (BCM_FAILURE(rv2)) {
   2443                 ALPM_ERR(("alpm_lib_trie_merge error in trie split, rv %d\n", rv2));
   2444             }
   2445         }
   2446 
   2447         alpm_lib_trie_destroy(cbt);
   2448     }
   2449 
   2450     if (cpn != NULL) {
   2451         alpm_util_free(cpn);
   2452     }
   2453 
   2454     return rv;
   2455 }
   2456 
   2457 static int
   2458 alpm_bkt_split_pvt_add(int u, _alpm_cb_t *acb,
   2459                        _bcm_defip_cfg_t *pvt_lpm_cfg,
   2460                        _alpm_pvt_node_t *pvt_node)
   2461 {
   2462     int                 rv = BCM_E_NONE;
   2463     int                 ipt, vrf_id;
   2464     int                 pvt_len = 0;
   2465     alpm_lib_trie_t     *pfx_trie = NULL;
   2466     _alpm_pfx_node_t    *pfx_node = NULL;
   2467 
   2468     pvt_len = PVT_KEY_LEN(pvt_node);
   2469     ipt     = ALPM_LPM_IPT(u, pvt_lpm_cfg);
   2470     vrf_id  = ALPM_LPM_VRF_ID(u, pvt_lpm_cfg);
   2471     pfx_trie = ALPM_VRF_TRIE(u, vrf_id, ipt);
   2472 
   2473     /* Assoc-data and bpm_len info of pvt_lpm_cfg comes from alpm_lib_trie_find_lpm */
   2474     ALPM_IER(alpm_lib_trie_find_lpm(pfx_trie, pvt_node->key, pvt_len,
   2475                               (alpm_lib_trie_node_t **)&pfx_node));
   2476     PVT_BPM_LEN(pvt_node) = pfx_node->key_len;
   2477     PVT_BKT_DEF(pvt_node) = pfx_node->bkt_ptr;
   2478 
   2479     /* Construct KEY(IP address), should come from pvt_key */
   2480     alpm_trie_pfx_to_cfg(u, pvt_node->key, pvt_len, pvt_lpm_cfg);
   2481     sal_memcpy(pvt_lpm_cfg->user_data, pvt_node->key, sizeof(uint32) * 5);
   2482     /* Construct Assoc-data */
   2483     if (pfx_node->bkt_ptr != NULL) {
   2484         alpm_util_adata_trie_to_cfg(u, &pfx_node->bkt_ptr->adata, pvt_lpm_cfg);
   2485         pvt_lpm_cfg->default_miss = 0;
   2486     } else {
   2487         alpm_util_adata_zero_cfg(u, pvt_lpm_cfg);
   2488         pvt_lpm_cfg->default_miss = 1;
   2489     }
   2490     rv = alpm_pvt_insert(u, acb, pvt_lpm_cfg);
   2491     if (BCM_SUCCESS(rv)) {
   2492         PVT_IDX(pvt_node) = pvt_lpm_cfg->defip_index;
   2493         rv = alpm_lib_trie_insert(ACB_PVT_TRIE(acb, vrf_id, ipt), pvt_node->key, pvt_len,
   2494                                   (alpm_lib_trie_node_t *)pvt_node);
   2495     }
   2496     /* rv = *_E_FULL is allowed here */
   2497 
   2498     return rv;
   2499 }
   2500 
   2501 /* Case of add new L1 pvt during L2 bkt split:
   2502    If new L2 bkt belongs to new L1 pvt, add new L2 bkt.
   2503 */
   2504 static int
   2505 alpm_bkt_add_to_npvt(int u, _alpm_cb_t *acb,
   2506                      _bcm_defip_cfg_t *lpm_cfg,
   2507                      _alpm_pvt_node_t *npvt_node)
   2508 {
   2509     int                  rv = BCM_E_NONE;
   2510     int                  vrf_id = ALPM_LPM_VRF_ID(u, lpm_cfg);
   2511     int                  ipt = ALPM_LPM_IPT(u, lpm_cfg);
   2512     uint32               *prefix, length;
   2513     uint32               ent_idx;
   2514     int                  bkt_trie_added = 0;
   2515 
   2516     alpm_lib_trie_t      *bkt_trie = NULL;
   2517     alpm_lib_trie_node_t *tmp_node = NULL;
   2518     _alpm_bkt_node_t     *bkt_node = NULL;
   2519     _alpm_pvt_node_t     *pvt_node;
   2520 
   2521     _alpm_tcam_write_t *tcam_write = lpm_cfg->tcam_write;
   2522 
   2523     ALPM_IEG(alpm_pvt_find(u, acb, lpm_cfg, &pvt_node));
   2524     if (pvt_node == npvt_node) { /* belongs to new L1 pvt */
   2525         lpm_cfg->l1_pvt_node = pvt_node;
   2526         /* lpm_cfg->tcam_write may update here due to new L2 pvt added */
   2527 
   2528         rv = alpm_bkt_insert(u, acb, lpm_cfg, pvt_node, &ent_idx);
   2529 
   2530         tcam_write->rv = rv;
   2531         if (BCM_FAILURE(rv)) {
   2532             /* If FULL, return no error, continue and will try again
   2533                bkt split when back to alpm_cb_insert */
   2534             if (rv == BCM_E_FULL) {
   2535                 ALPM_INFO(("ACB(%d): new L2 bkt add FULL (%d) and retry\n", ACB_IDX(acb), rv));
   2536                 return BCM_E_NONE;
   2537             } else {
   2538                 ALPM_ERR(("ACB(%d): new L2 bkt add failed (%d)\n", ACB_IDX(acb), rv));
   2539             }
   2540         } else {
   2541             ALPM_INFO(("ACB(%d): new L2 bkt add OK\n", ACB_IDX(acb)));
   2542         }
   2543     } else {
   2544         return BCM_E_NONE; /* exit */
   2545     }
   2546 
   2547     /* return FULL when Expand exceeds bnk_threshold */
   2548     if (rv == BCM_E_RESOURCE) {
   2549         rv = BCM_E_FULL;
   2550     }
   2551 
   2552     ALPM_IEG_PRT_EXCEPT(rv, BCM_E_FULL);
   2553 
   2554     lpm_cfg->defip_index = ent_idx;
   2555 
   2556     /* Allocate Payload */
   2557     ALPM_ALLOC_EG(bkt_node, sizeof(_alpm_bkt_node_t), "bkt_node");
   2558     prefix = lpm_cfg->user_data;
   2559     length = lpm_cfg->defip_sub_len;
   2560     sal_memcpy(bkt_node->key, prefix, sizeof(bkt_node->key));
   2561     bkt_node->key_len   = length;
   2562     bkt_node->ent_idx   = ent_idx;
   2563     alpm_util_adata_cfg_to_trie(u, lpm_cfg, &bkt_node->adata);
   2564     /* Insert the prefix */
   2565     /* bucket trie insert */
   2566     bkt_trie = PVT_BKT_TRIE(pvt_node);
   2567     rv = alpm_lib_trie_insert(bkt_trie, prefix, length, (alpm_lib_trie_node_t *)bkt_node);
   2568     ALPM_IEG(rv);
   2569     bkt_trie_added = 1;
   2570 
   2571     ALPM_IEG(alpm_vrf_pfx_trie_add(u, acb, lpm_cfg, bkt_node));
   2572 
   2573     if (BCM_SUCCESS(rv) &&
   2574         ALPMC(u)->_alpm_dbg_bmp & _ALPM_DBG_PVT_SANITY_NODE) {
   2575         rv = alpm_cb_pvt_sanity_cb(u, acb, pvt_node, "CBInsert");
   2576     }
   2577 
   2578     VRF_ROUTE_ADD(acb, vrf_id, ipt);
   2579 
   2580     return rv;
   2581 
   2582 bad:
   2583     if (bkt_trie_added) {
   2584         (void)alpm_lib_trie_delete(bkt_trie, prefix, length, &tmp_node);
   2585     }
   2586     if (bkt_node != NULL) {
   2587         alpm_util_free(bkt_node);
   2588     }
   2589 
   2590     return rv;
   2591 }
   2592 
   2593 /*
   2594  * OUT pvt_node,
   2595  * OUT bkt_node
   2596  */
   2597 
   2598 int
   2599 alpm_cb_find(int u, _alpm_cb_t *acb, _bcm_defip_cfg_t *lpm_cfg,
   2600              _alpm_pvt_node_t **pvt_node, _alpm_bkt_node_t **bkt_node)
   2601 {
   2602     int rv = BCM_E_NONE;
   2603 
   2604     rv = alpm_pvt_find(u, acb, lpm_cfg, pvt_node);
   2605     if (BCM_SUCCESS(rv)) {
   2606         rv = alpm_bkt_find(u, acb, lpm_cfg, *pvt_node, bkt_node);
   2607     } else {
   2608         rv = BCM_E_NOT_FOUND;
   2609     }
   2610 
   2611     return rv;
   2612 }
   2613 
   2614 /*
   2615  * Find and update the match in the database.
   2616  * Returns BCM_E_NONE, if found and updated.
   2617  * BCM_E_NOT_FOUND if not found
   2618  * BCM_E_FAIL, if update failed.
   2619  */
   2620 static int
   2621 alpm_cb_update(int u, _alpm_cb_t *acb,
   2622                _bcm_defip_cfg_t *lpm_cfg)
   2623 {
   2624     _alpm_ppg_data_t pdata;
   2625     _alpm_pvt_node_t *pvt_node;
   2626     _alpm_bkt_node_t *bkt_node;
   2627     int         rv = BCM_E_NONE;
   2628 
   2629     /* Find and update the entry */
   2630     pvt_node = (_alpm_pvt_node_t *)lpm_cfg->pvt_node;
   2631     bkt_node = (_alpm_bkt_node_t *)lpm_cfg->bkt_node;
   2632     if (bkt_node == NULL) {
   2633         ALPM_ERR(("**ACB(%d).FIND.UPDATE bkt_node == NULL...\n",
   2634                   ACB_IDX(acb)));
   2635         return BCM_E_FAIL;
   2636     }
   2637     alpm_util_adata_cfg_to_trie(u, lpm_cfg, &bkt_node->adata);
   2638     ALPM_IER(alpm_bkt_ent_write(u, acb, pvt_node, lpm_cfg, bkt_node->ent_idx, ALPM_PVT_UPDATE_ASSOC_DATA));
   2639 
   2640     if (ACB_HAS_RTE(acb, ALPM_LPM_VRF_ID(u, lpm_cfg))) {
   2641         /* Perform INSERT propagation to update assoc_data */
   2642         alpm_ppg_prepare(u, lpm_cfg, lpm_cfg->defip_sub_len, bkt_node, &pdata);
   2643         ALPM_IER(alpm_ppg_assoc_data(u, ALPM_PPG_INSERT, &pdata));
   2644     }
   2645     return rv;
   2646 }
   2647 
   2648 static int
   2649 alpm_vrf_pfx_trie_add(int u, _alpm_cb_t *acb,
   2650                       _bcm_defip_cfg_t *lpm_cfg, void *udata)
   2651 {
   2652     int         rv = BCM_E_NONE, ipt, vrf_id;
   2653     uint32      *prefix;
   2654     uint32      length;
   2655 
   2656     alpm_lib_trie_t      *pfx_trie = NULL;
   2657     alpm_lib_trie_node_t *lpmp;
   2658     _alpm_pfx_node_t *pfx_node = NULL, *tmp_node;
   2659 
   2660     vrf_id = lpm_cfg->defip_vrf;
   2661     if (vrf_id == BCM_L3_VRF_GLOBAL) {
   2662         /* GLobal low */
   2663         vrf_id = ALPM_VRF_ID_GLO(u);
   2664     } else if (vrf_id < 0) {
   2665         assert(0);
   2666     }
   2667 
   2668     if (ACB_HAS_PVT(acb, vrf_id)) {
   2669         return rv;
   2670     }
   2671 
   2672     ipt = ALPM_LPM_IPT(u, lpm_cfg);
   2673     pfx_trie = ALPM_VRF_TRIE(u, vrf_id, ipt);
   2674 
   2675     if (lpm_cfg->defip_sub_len == 0) {
   2676         /* Add a route already in trie */
   2677         lpmp = NULL;
   2678         rv = alpm_lib_trie_find_lpm(pfx_trie, 0, 0, &lpmp);
   2679         if (BCM_SUCCESS(rv)) {
   2680             tmp_node = (_alpm_bkt_node_t *)lpmp;
   2681             tmp_node->bkt_ptr = udata;
   2682         }
   2683 
   2684         return rv;
   2685     }
   2686 
   2687     /* Non default route start from here */
   2688     prefix = lpm_cfg->user_data;
   2689     length = lpm_cfg->defip_sub_len;
   2690 
   2691     ALPM_ALLOC_EG(pfx_node, sizeof(_alpm_pfx_node_t), "VRF_trie_node");
   2692 
   2693     sal_memcpy(pfx_node->key, prefix, sizeof(pfx_node->key));
   2694     pfx_node->key_len = length;
   2695     pfx_node->ent_idx = lpm_cfg->defip_index;
   2696     pfx_node->bkt_ptr = udata;
   2697 
   2698     rv = alpm_lib_trie_insert(pfx_trie, prefix, length, (alpm_lib_trie_node_t *)pfx_node);
   2699     if (BCM_FAILURE(rv)) {
   2700         if (pfx_node != NULL) {
   2701             alpm_util_free(pfx_node);
   2702         }
   2703     }
   2704 
   2705 bad:
   2706     return rv;
   2707 }
   2708 
   2709 static int
   2710 alpm_vrf_pfx_trie_delete(int u, _alpm_cb_t *acb,
   2711                          _bcm_defip_cfg_t *lpm_cfg, void *udata,
   2712                          _alpm_bkt_node_t **alt_def_pfx,
   2713                          uint32 *alt_bpm_len)
   2714 {
   2715     int         rv = BCM_E_NONE, rv2, ipt, vrf_id;
   2716     uint32      *prefix;
   2717     uint32      pfx_len, bpm_len;
   2718 
   2719     alpm_lib_trie_t      *pfx_trie = NULL;
   2720     alpm_lib_trie_node_t *lpmp = NULL;
   2721     _alpm_pfx_node_t *pfx_node = NULL, *tmp_node;
   2722 
   2723     vrf_id = lpm_cfg->defip_vrf;
   2724     if (vrf_id == BCM_L3_VRF_GLOBAL) {
   2725         /* Global low */
   2726         vrf_id = ALPM_VRF_ID_GLO(u);
   2727     } else if (vrf_id < 0) {
   2728         assert(0);
   2729     }
   2730 
   2731     if (ACB_HAS_PVT(acb, vrf_id)) {
   2732         return rv;
   2733     }
   2734 
   2735     ipt = ALPM_LPM_IPT(u, lpm_cfg);
   2736     pfx_trie = ALPM_VRF_TRIE(u, vrf_id, ipt);
   2737     prefix      = lpm_cfg->user_data;
   2738     pfx_len     = lpm_cfg->defip_sub_len;
   2739 
   2740     if (pfx_len != 0) {
   2741         rv = alpm_lib_trie_delete(pfx_trie, prefix, pfx_len, &lpmp);
   2742         pfx_node = (_alpm_bkt_node_t *)lpmp;
   2743         ALPM_IEG(rv);
   2744 
   2745         /* Find the alternative best prefix match node */
   2746         lpmp = NULL;
   2747         rv = alpm_lib_trie_find_lpm(pfx_trie, prefix, pfx_len, &lpmp);
   2748         tmp_node = (_alpm_pfx_node_t *)lpmp;
   2749         if (BCM_SUCCESS(rv)) {
   2750             _alpm_bkt_node_t *t = (_alpm_bkt_node_t *)(tmp_node->bkt_ptr);
   2751             if (t != NULL) {
   2752                 /* Means default route exists */
   2753                 bpm_len = t->key_len;
   2754             } else {
   2755                 /* This should happen only if the lpm is a default route */
   2756                 bpm_len = 0;
   2757             }
   2758 
   2759             *alt_def_pfx = t;
   2760             *alt_bpm_len = bpm_len;
   2761         } else {
   2762             /* Not expected */
   2763             ALPM_IEG(rv);
   2764         }
   2765     } else {
   2766         /* Delete a default route */
   2767         lpmp = NULL;
   2768         rv = alpm_lib_trie_find_lpm(pfx_trie, prefix, pfx_len, &lpmp);
   2769         tmp_node = (_alpm_pfx_node_t *)lpmp;
   2770         tmp_node->bkt_ptr = NULL;
   2771     }
   2772 
   2773     if (pfx_node != NULL) {
   2774         alpm_util_free(pfx_node);
   2775     }
   2776 
   2777     return rv;
   2778 
   2779 bad:
   2780     /* Recover if necessary */
   2781     if (pfx_node != NULL) {
   2782         rv2 = alpm_lib_trie_insert(pfx_trie, prefix,
   2783                                    pfx_len, (alpm_lib_trie_node_t *)pfx_node);
   2784         if (BCM_FAILURE(rv2)) {
   2785             ALPM_ERR(("Recover failed\n"));
   2786         }
   2787     }
   2788     return rv;
   2789 }
   2790 
   2791 static int
   2792 alpm_vrf_pfx_trie_init(int u, int vrf_id, int ipt)
   2793 {
   2794     int rv = BCM_E_NONE;
   2795     alpm_lib_trie_t  *root = NULL;
   2796     uint32  max_key_len;
   2797     uint32  key[5] = {0};
   2798     _alpm_pfx_node_t    *pfx_node = NULL;
   2799 
   2800     max_key_len = alpm_util_trie_max_key_len(u, ipt);
   2801 
   2802     ALPM_ALLOC_EG(pfx_node, sizeof(*pfx_node), "Payload for pfx trie key");
   2803     sal_memset(pfx_node, 0, sizeof(*pfx_node));
   2804     rv = alpm_lib_trie_init(max_key_len, &ALPM_VRF_TRIE(u, vrf_id, ipt));
   2805     if (BCM_SUCCESS(rv)) {
   2806         root = ALPM_VRF_TRIE(u, vrf_id, ipt);
   2807         rv = alpm_lib_trie_insert(root, key, 0, &(pfx_node->node));
   2808     }
   2809 
   2810     if (BCM_FAILURE(rv)) {
   2811         alpm_util_free(pfx_node);
   2812         if (root != NULL) {
   2813             alpm_lib_trie_destroy(root);
   2814             ALPM_VRF_TRIE(u, vrf_id, ipt) = NULL;
   2815         }
   2816     }
   2817 
   2818 bad:
   2819     return rv;
   2820 }
   2821 
   2822 int
   2823 alpm_vrf_pfx_trie_deinit(int u, int vrf_id, int ipt)
   2824 {
   2825     int rv = BCM_E_NONE;
   2826     alpm_lib_trie_t  *root = NULL;
   2827     uint32  key[5] = {0};
   2828     _alpm_pfx_node_t    *pfx_node = NULL;
   2829 
   2830     root = ALPM_VRF_TRIE(u, vrf_id, ipt);
   2831     if (root == NULL) {
   2832         return rv;
   2833     }
   2834     rv = alpm_lib_trie_delete(root, key, 0, (alpm_lib_trie_node_t **)&pfx_node);
   2835     if (BCM_SUCCESS(rv)) {
   2836         alpm_util_free(pfx_node);
   2837         ALPM_IER(alpm_lib_trie_destroy(root));
   2838         ALPM_VRF_TRIE(u, vrf_id, ipt) = NULL;
   2839     }
   2840 
   2841     return rv;
   2842 }
   2843 
   2844 int
   2845 alpm_vrf_pvt_node_init(int u, _alpm_cb_t *acb,
   2846                        alpm_lib_trie_t *pvt_root,
   2847                        _bcm_defip_cfg_t *pvt_cfg,
   2848                        _alpm_pvt_node_t **pvt_node)
   2849 {
   2850     int                 rv = BCM_E_NONE;
   2851     int                 vrf_id;
   2852     int                 ipt;
   2853     uint32              max_key_len;
   2854     _alpm_pvt_node_t    *tmp_node = NULL;
   2855 
   2856     ipt = ALPM_LPM_IPT(u, pvt_cfg);
   2857     vrf_id = ALPM_LPM_VRF_ID(u, pvt_cfg);
   2858 
   2859     ALPM_ALLOC_EG(tmp_node, sizeof(_alpm_pvt_node_t), "pvt_node");
   2860 
   2861     /* kshift = 0 */
   2862     max_key_len = alpm_util_trie_max_key_len(u, ipt);
   2863     ALPM_IEG(alpm_lib_trie_init(max_key_len, &PVT_BKT_TRIE(tmp_node)));
   2864     if (pvt_cfg->bkt_info) {
   2865         sal_memcpy(&PVT_BKT_INFO(tmp_node), pvt_cfg->bkt_info, sizeof(_alpm_bkt_info_t));
   2866     }
   2867     PVT_BKT_VRF(tmp_node)   = vrf_id;
   2868     PVT_BKT_PKM(tmp_node)   = ALPM_LPM_PKM(u, pvt_cfg);
   2869     PVT_BKT_DEF(tmp_node)   = NULL;
   2870     PVT_BPM_LEN(tmp_node)   = 0;
   2871     PVT_KEY_LEN(tmp_node)   = pvt_cfg->defip_sub_len;
   2872     PVT_KEY_CPY(tmp_node,  pvt_cfg->user_data);
   2873     PVT_FLAGS(tmp_node)     = pvt_cfg->defip_flags;
   2874 
   2875     PVT_IDX(tmp_node)       = pvt_cfg->defip_index;
   2876 
   2877     *pvt_node = tmp_node;
   2878 
   2879     return rv;
   2880 
   2881 bad:
   2882     if (tmp_node != NULL) {
   2883         alpm_util_free(tmp_node);
   2884     }
   2885 
   2886     if (PVT_BKT_TRIE(tmp_node) != NULL) {
   2887         alpm_lib_trie_destroy(PVT_BKT_TRIE(tmp_node));
   2888         PVT_BKT_TRIE(tmp_node) = NULL;
   2889     }
   2890 
   2891     return rv;
   2892 }
   2893 
   2894 static int
   2895 alpm_vrf_pvt_node_delete(int u, _alpm_cb_t *acb, int vrf_id, int ipt,
   2896                          _bcm_defip_cfg_t *lpm_cfg)
   2897 {
   2898     int                 rv = BCM_E_NONE;
   2899     _alpm_pvt_node_t    *pvt_node = NULL;
   2900     alpm_lib_trie_t              *pvt_root = NULL;
   2901 
   2902     pvt_root = ACB_PVT_TRIE(acb, vrf_id, ipt);
   2903     if (pvt_root == NULL) {
   2904         return rv;
   2905     }
   2906     rv = alpm_lib_trie_delete(pvt_root, lpm_cfg->user_data, lpm_cfg->defip_sub_len,
   2907                      (alpm_lib_trie_node_t **)&pvt_node);
   2908     if (BCM_SUCCESS(rv)) {
   2909         ALPM_IER(alpm_lib_trie_destroy(PVT_BKT_TRIE(pvt_node)));
   2910         alpm_util_free(pvt_node);
   2911     }
   2912 
   2913     return rv;
   2914 }
   2915 
   2916 int
   2917 alpm_vrf_pvt_trie_deinit(int u, _alpm_cb_t *acb, int vrf_id, int ipt,
   2918                          _bcm_defip_cfg_t *lpm_cfg)
   2919 {
   2920     int                 rv = BCM_E_NONE;
   2921 
   2922     rv = alpm_vrf_pvt_node_delete(u, acb, vrf_id, ipt, lpm_cfg);
   2923     if (BCM_SUCCESS(rv)) {
   2924         ALPM_IER(alpm_lib_trie_destroy(ACB_PVT_TRIE(acb, vrf_id, ipt)));
   2925         ACB_PVT_TRIE(acb, vrf_id, ipt) = NULL;
   2926     }
   2927 
   2928     return rv;
   2929 }
   2930 
   2931 static int
   2932 alpm_cb_pvt_add(int u, _alpm_cb_t *acb, int vrf_id, int ipt,
   2933                 _bcm_defip_cfg_t *lpm_cfg)
   2934 {
   2935     int rv = BCM_E_NONE;
   2936     int pvt_node_inited = 0, pvt_root_inited = 0;
   2937 
   2938     uint32              max_key_len;
   2939     alpm_lib_trie_t     *pvt_root;
   2940     _alpm_bkt_info_t    bkt_info;
   2941     _alpm_pvt_node_t    *pvt_node = NULL;
   2942 
   2943     pvt_root = ACB_PVT_TRIE(acb, vrf_id, ipt);
   2944     if (pvt_root == NULL) {
   2945         max_key_len = alpm_util_trie_max_key_len(u, ipt);
   2946         ALPM_IEG(alpm_lib_trie_init(max_key_len, &ACB_PVT_TRIE(acb, vrf_id, ipt)));
   2947         pvt_root = ACB_PVT_TRIE(acb, vrf_id, ipt);
   2948         pvt_root_inited = 1;
   2949     }
   2950     ALPM_IEG(alpm_vrf_pvt_node_init(u, acb, pvt_root, lpm_cfg, &pvt_node));
   2951     pvt_node_inited = 1;
   2952     if (!pvt_root_inited) {
   2953         _alpm_pfx_node_t    *pfx_node = NULL;
   2954         alpm_lib_trie_t              *pfx_trie = NULL;
   2955 
   2956         pfx_trie = ALPM_VRF_TRIE(u, vrf_id, ipt);
   2957         if (pfx_trie != NULL) {
   2958             ALPM_IER(alpm_lib_trie_find_lpm(pfx_trie, pvt_node->key, pvt_node->key_len,
   2959                                    (alpm_lib_trie_node_t **)&pfx_node));
   2960             PVT_BPM_LEN(pvt_node) = pfx_node->key_len;
   2961             PVT_BKT_DEF(pvt_node) = pfx_node->bkt_ptr;
   2962         }
   2963     }
   2964 
   2965     if (ACB_HAS_TCAM(acb)) { /* need for TCAM write */
   2966         lpm_cfg->pvt_node = (uint32 *)pvt_node;
   2967     }
   2968 
   2969 retry:
   2970     sal_memset(&bkt_info, 0, sizeof(_alpm_bkt_info_t));
   2971     rv = alpm_bkt_alloc(u, acb, vrf_id, ipt, 1, &bkt_info, NULL);
   2972     if (rv == BCM_E_BUSY) {
   2973         ALPM_IEG_PRT_EXCEPT(alpm_bkt_alloc(u, acb, vrf_id, ipt, 1, &bkt_info, NULL), BCM_E_FULL);
   2974     }
   2975     ALPM_IEG_PRT_EXCEPT(rv, BCM_E_FULL);
   2976     lpm_cfg->bkt_info = &bkt_info;
   2977     sal_memcpy(&PVT_BKT_INFO(pvt_node), &bkt_info, sizeof(_alpm_bkt_info_t));
   2978 
   2979     rv = alpm_pvt_insert(u, acb, lpm_cfg);
   2980     /* Upper level of BCM_E_BUSY point,
   2981      * ACB_HAS_RTE may not be a good condition, but considering
   2982      * it's only 3 levels so it also works.
   2983      */
   2984     if (rv == BCM_E_BUSY && lpm_cfg->spl_pn && ACB_HAS_RTE(acb, vrf_id)) {
   2985         ALPM_IEG(alpm_bkt_free(u, acb, vrf_id, ipt, &bkt_info));
   2986         sal_memset(&bkt_info, 0, sizeof(_alpm_bkt_info_t));
   2987         rv = alpm_bkt_alloc(u, acb, vrf_id, ipt,
   2988                             ACB_BNK_PER_BKT(acb, vrf_id),
   2989                             &bkt_info, NULL);
   2990         ALPM_IEG_PRT_EXCEPT(rv, BCM_E_FULL);
   2991 
   2992         /* Case 2.2.2, split given l3 pvt_node first */
   2993         rv = alpm_cb_split(u, acb, lpm_cfg, &bkt_info, 0xffff);
   2994 
   2995         if (BCM_SUCCESS(rv)) {
   2996             lpm_cfg->spl_pn = NULL;
   2997             lpm_cfg->spl_key_len = 0;
   2998             lpm_cfg->l1_pvt_node = NULL;
   2999             /* PERF OPT point */
   3000             goto retry;
   3001         }
   3002     }
   3003     ALPM_IEG_PRT_EXCEPT(rv, BCM_E_FULL);
   3004 
   3005     PVT_IDX(pvt_node) = lpm_cfg->defip_index;
   3006     lpm_cfg->pvt_node = (uint32 *)pvt_node;
   3007     ALPM_IEG(alpm_lib_trie_insert(ACB_PVT_TRIE(acb, vrf_id, ipt),
   3008              pvt_node->key, pvt_node->key_len,
   3009              (void *)pvt_node));
   3010 
   3011 bad:
   3012     if (BCM_FAILURE(rv)) {
   3013         /* ALPMTBD rollback */
   3014         if (lpm_cfg->bkt_info != NULL) {
   3015             (void)alpm_bkt_free(u, acb, vrf_id, ipt, &bkt_info);
   3016             lpm_cfg->bkt_info = NULL;
   3017         }
   3018 
   3019         if (pvt_root_inited) {
   3020             (void)alpm_vrf_pvt_trie_deinit(u, acb, vrf_id, ipt, lpm_cfg);
   3021         } else if (pvt_node_inited) {
   3022             (void)alpm_vrf_pvt_node_delete(u, acb, vrf_id, ipt, lpm_cfg);
   3023         }
   3024     }
   3025 
   3026     return rv;
   3027 
   3028 }
   3029 
   3030 static void
   3031 alpm_vrf_spl_len_calc(int u, _alpm_cb_t *acb, int vrf_id, uint8 db_type,
   3032                       uint32 *splen1, uint32 *splen2)
   3033 {
   3034     int idx, bpb;
   3035     uint32 diff1[5] = {6, 5, 7, 6, 0};
   3036     uint32 diff2[5] = {2, 3, 3, 4, 0};
   3037 
   3038     bpb = ACB_BNK_PER_BKT(acb, vrf_id) > 4;
   3039 
   3040     if (ACB_IDX(acb) > 0) {
   3041         idx = bpb << 1 | db_type;
   3042     } else {
   3043         idx = 4;
   3044     }
   3045     *splen1 = diff1[idx];
   3046     *splen2 = diff2[idx];
   3047 
   3048     return;
   3049 }
   3050 
   3051 /*
   3052  * alpm_vrf_init
   3053  * Add a VRF default route when a L3 VRF is added
   3054  * Adds a 0.0 entry into VRF
   3055  */
   3056 static int
   3057 alpm_vrf_init(int u, _alpm_cb_t *acb, int vrf_id, int ipt, uint8 db_type)
   3058 {
   3059     int                 rv = BCM_E_NONE;
   3060     _bcm_defip_cfg_t    pvt_cfg;
   3061 
   3062     /* Need to set db_type at the beginning */
   3063     ACB_VRF_DB_TYPE_SET(u, acb, vrf_id, ipt, db_type);
   3064 
   3065     sal_memset(&pvt_cfg, 0, sizeof(pvt_cfg));
   3066     pvt_cfg.defip_vrf = ALPM_VRF_ID_TO_VRF(u, vrf_id);
   3067     pvt_cfg.defip_flags |= ALPM_IS_IPV6(ipt) ? BCM_L3_IP6 : 0;
   3068 
   3069     if (ALPM_TCAM_ZONED(u)) {
   3070         pvt_cfg.default_miss = 1;
   3071     }
   3072 
   3073     ALPM_IEG_PRT_EXCEPT(alpm_cb_pvt_add(u, acb, vrf_id, ipt, &pvt_cfg), BCM_E_FULL);
   3074 
   3075     ACB_VRF_INIT_SET(u, acb, vrf_id, ipt);
   3076     ACB_DR_INIT_CLEAR(u, acb, vrf_id, ipt); /* clear DR partially inited */
   3077 
   3078     alpm_vrf_spl_len_calc(u, acb, vrf_id, db_type,
   3079                           &ACB_VRF_SPLEN_DIFF1(u, acb, vrf_id, ipt),
   3080                           &ACB_VRF_SPLEN_DIFF2(u, acb, vrf_id, ipt));
   3081 
   3082     if (ACB_HAS_RTE(acb, vrf_id)) {
   3083         rv = alpm_vrf_pfx_trie_init(u, vrf_id, ipt);
   3084     }
   3085 
   3086 bad:
   3087     if (BCM_FAILURE(rv)) {
   3088         /* ALPMTBD rollback */
   3089         if (pvt_cfg.bkt_info != NULL) {
   3090             (void)alpm_bkt_free(u, acb, vrf_id, ipt,
   3091                                 (_alpm_bkt_info_t *)pvt_cfg.bkt_info);
   3092         }
   3093         (void)alpm_vrf_pvt_trie_deinit(u, acb, vrf_id, ipt, &pvt_cfg);
   3094         ACB_VRF_INIT_CLEAR(u, acb, vrf_id, ipt);
   3095     }
   3096     return rv;
   3097 
   3098 }
   3099 
   3100 /*
   3101  * alpm_vrf_deinit
   3102  * Delete the VRF default route when a L3 VRF is destroyed
   3103  */
   3104 int
   3105 alpm_vrf_deinit(int u, int vrf_id, int ipt)
   3106 {
   3107     int                 i, rv = BCM_E_NONE;
   3108     _bcm_defip_cfg_t    lpm_cfg;
   3109     _alpm_pvt_node_t    *pvt_node = NULL;
   3110     _alpm_cb_t          *acb;
   3111 
   3112     sal_memset(&lpm_cfg, 0, sizeof(lpm_cfg));
   3113     lpm_cfg.defip_vrf = ALPM_VRF_ID_TO_VRF(u, vrf_id);
   3114     if (ALPM_IS_IPV6(ipt)) {
   3115         lpm_cfg.defip_flags |= BCM_L3_IP6;
   3116     }
   3117     if (ALPM_TCAM_ZONED(u)) {
   3118         lpm_cfg.default_miss = 1;
   3119     }
   3120 
   3121     for (i = ACB_CNT(u) - 1; i >= 0; i--) {
   3122         acb = ACB(u, i);
   3123         if (!ACB_VRF_INITED(u, acb, vrf_id, ipt)) {
   3124             continue;
   3125         }
   3126 
   3127         ALPM_IER(alpm_pvt_find(u, acb, &lpm_cfg, &pvt_node));
   3128         /* Banks are already freed via _pfx_shrink */
   3129         /* add Entry into tcam as default routes for the VRF */
   3130         if (ACB_HAS_TCAM(acb)) {
   3131             lpm_cfg.pvt_node = pvt_node;
   3132             ALPM_IER(alpm_bkt_bnk_shrink(u, ipt, acb,
   3133                        ACB_BKT_VRF_POOL(acb, vrf_id),
   3134                        &PVT_BKT_INFO(pvt_node), NULL));
   3135         } else {
   3136             lpm_cfg.pvt_node = NULL;
   3137         }
   3138         lpm_cfg.bkt_node = NULL;
   3139         ALPM_IER(alpm_pvt_delete(u, acb, &lpm_cfg));
   3140         ALPM_IER(alpm_vrf_pvt_trie_deinit(u, acb, vrf_id, ipt, &lpm_cfg));
   3141         ACB_VRF_INIT_CLEAR(u, acb, vrf_id, ipt);
   3142     }
   3143 
   3144     rv = alpm_vrf_pfx_trie_deinit(u, vrf_id, ipt);
   3145 
   3146     return rv;
   3147 }
   3148 
   3149 /* Check the bank usage against threshold for TH3 only when bnk_cnt > 8K */
   3150 static int
   3151 alpm_cb_bnk_threshold_exceed(int u, _alpm_cb_t *acb, int vrf_id, int ipt)
   3152 {
   3153     _alpm_bkt_pool_conf_t *bp_conf = ACB_BKT_VRF_POOL(acb, vrf_id);
   3154 
   3155     if (!ACB_BKT_FIXED_FMT(acb, 1) &&
   3156         ACB_HAS_RTE(acb, vrf_id) &&
   3157         (BPC_BNK_CNT(bp_conf) > 8192) &&
   3158         ((BPC_BNK_USED(bp_conf, ipt) * 100 / BPC_BNK_CNT(bp_conf)) >
   3159         ALPMC(u)->_alpm_bnk_threshold)) {
   3160         return TRUE;
   3161     }
   3162 
   3163     return FALSE;
   3164 }
   3165 
   3166 /* What is expected here when entering this function:
   3167  * all occupied banks are continuous.
   3168  *    all i in {i | bkt_info->bnk_fmt[i] is used} are continuous AND
   3169  *    foreach i belongs to {i | bkt_info->bnk_fmt[i] is used}:
   3170  *        bkt_info->vet_bmp[i]!=0
   3171  */
   3172 int
   3173 alpm_cb_expand(int u, _alpm_cb_t *acb, _alpm_pvt_node_t *pvt_node, int bnk_cnt, int *fmt_update)
   3174 {
   3175     int i, ipt, rv = BCM_E_FULL;
   3176     _alpm_bkt_info_t *bkt_info;
   3177     _alpm_bkt_pool_conf_t *bp_conf;
   3178     int bnkpb, start, end;
   3179     int leftnb, rightnb;
   3180     int def_fmt;
   3181 
   3182     ipt = PVT_BKT_IPT(pvt_node);
   3183     def_fmt = alpm_util_bkt_def_fmt_get(u, acb, PVT_BKT_VRF(pvt_node), ipt);
   3184     *fmt_update = FALSE;
   3185 
   3186     ALPM_VERB(("Expanding ALPM CB %d bkt %d......\n",
   3187                acb->acb_idx, PVT_BKT_IDX(pvt_node)));
   3188 
   3189     /* There 4 cases when expanding a bucket */
   3190     /* Case 1: neighbour bank available
   3191      *         -> occupy neighbour bank */
   3192     /*
   3193       0 1 2 3 4 5 6 7
   3194      -----------------
   3195      |#|#|#|#|#| | | |
   3196      -----------------
   3197       ^
   3198      rofs=0
   3199      -----------------
   3200      | | |#|#|#|#| | |
   3201      -----------------
   3202           ^
   3203          rofs=2
   3204      -----------------
   3205      | | | |#|#|#|#|#|
   3206      -----------------
   3207             ^
   3208            rofs=3          bkt+1
   3209      -----------------     -----------------
   3210      | | | | | |#|#|#|     |#|#| | | | | | |
   3211      -----------------     -----------------
   3212                 ^
   3213                rofs=5
   3214      */
   3215 
   3216     /* There is a neighbour */
   3217     bkt_info = &PVT_BKT_INFO(pvt_node);
   3218     bp_conf  = ACB_BKT_VRF_POOL(acb, PVT_BKT_VRF(pvt_node));
   3219     bnkpb = BPC_BNK_PER_BKT(bp_conf);
   3220     start = PVT_ROFS(pvt_node);
   3221     end   = PVT_ROFS(pvt_node) + bnkpb;
   3222 
   3223     /* Get neighbour bank offset based on bkt-idx */
   3224     for (i = start; i < end; i++) {
   3225         if (!BI_BNK_IS_USED(bkt_info, i % bnkpb)) {
   3226             break;
   3227         }
   3228     }
   3229 
   3230     leftnb  = PVT_BKT_IDX(pvt_node) * bnkpb + start - 1;
   3231     rightnb = PVT_BKT_IDX(pvt_node) * bnkpb + i;
   3232     if (leftnb >= 0) {
   3233         rv = alpm_bkt_bnk_chk_rsvd(u, ipt, bp_conf, leftnb);
   3234         if (BCM_SUCCESS(rv)) {
   3235             if (PVT_BKT_IDX(pvt_node) != (leftnb / bnkpb)) {
   3236                 /* Update */
   3237                 PVT_BKT_IDX(pvt_node) = leftnb / bnkpb;
   3238             }
   3239 
   3240             PVT_ROFS(pvt_node) = leftnb % bnkpb;
   3241             bkt_info->bnk_fmt[PVT_ROFS(pvt_node)] = def_fmt;
   3242             *fmt_update = TRUE;
   3243             goto end;
   3244         }
   3245     }
   3246 
   3247     if (rightnb < BPC_BNK_CNT(bp_conf)) {
   3248         rv = alpm_bkt_bnk_chk_rsvd(u, ipt, bp_conf, rightnb);
   3249         if (BCM_SUCCESS(rv)) {
   3250             bkt_info->bnk_fmt[rightnb % bnkpb] = def_fmt;
   3251             *fmt_update = TRUE;
   3252             goto end;
   3253         }
   3254     }
   3255 
   3256     /* Case 2: No neighbour bank, but there are other
   3257      * continuous banks available:
   3258      *         -> Move banks to other area */
   3259     start = 0;
   3260     rv = alpm_bkt_bnk_alloc(u, ipt, bp_conf, &start, bnk_cnt+1, 1);
   3261     if (BCM_SUCCESS(rv)) {
   3262         _alpm_bkt_info_t dst_bkt;
   3263 
   3264         sal_memset(&dst_bkt, 0, sizeof(dst_bkt));
   3265         BI_ROFS(&dst_bkt) = start % bnkpb;
   3266         BI_BKT_IDX(&dst_bkt) = start / bnkpb;
   3267         for (i = 0; i <= bnk_cnt; i++) {
   3268             dst_bkt.bnk_fmt[(BI_ROFS(&dst_bkt) + i) % bnkpb] = def_fmt;
   3269         }
   3270 
   3271         /* Move banks */
   3272         rv = alpm_bkt_move(u, acb, pvt_node, bkt_info, &dst_bkt);
   3273         goto end;
   3274     }
   3275 
   3276     /* Check bank usage threshold */
   3277     if (alpm_cb_bnk_threshold_exceed(u, acb, PVT_BKT_VRF(pvt_node), ipt)) {
   3278         /* return E_RESOURCE in ALPM.expand to no split with unexpected
   3279            bucket situation. It will change to E_FULL outside */
   3280         return BCM_E_RESOURCE;
   3281     }
   3282 
   3283     /* Case 3: No neighbour bank, no continuous banks available
   3284      *         -> move empty bank to neighbour bank */
   3285     /* ALPMTBD, can be optimized by using partial defragmentation to
   3286      * create a free bucket then do Case 2.
   3287      */
   3288 
   3289     /* Find nearest unused bit position */
   3290     if (leftnb >= 0 || rightnb < BPC_BNK_CNT(bp_conf)) {
   3291         int nst_bnk = -1;
   3292         rv = alpm_bkt_bnk_nearest_get(u,
   3293                     BPC_BNK_BMP(bp_conf, ipt),
   3294                     BPC_BNK_CNT(bp_conf),
   3295                     leftnb, rightnb, &nst_bnk);
   3296         if (BCM_SUCCESS(rv)) {
   3297             /* Move unused nst_bnk */
   3298             if (nst_bnk > rightnb) {
   3299                 /* Move nst_bnk to rightnb */
   3300                 rv = alpm_bkt_free_bnk_move(u, acb, bp_conf, nst_bnk, rightnb);
   3301                 ALPM_IER(rv);
   3302                 /* Now rightnb is free */
   3303                 rv = alpm_bkt_bnk_chk_rsvd(u, ipt, bp_conf, rightnb);
   3304                 if (BCM_SUCCESS(rv)) {
   3305                     bkt_info->bnk_fmt[rightnb % bnkpb] = def_fmt;
   3306                     *fmt_update = TRUE;
   3307                     goto end;
   3308                 }
   3309             } else if (nst_bnk < leftnb) {
   3310                 /* Move nst_bnk to leftnb */
   3311                 rv = alpm_bkt_free_bnk_move(u, acb, bp_conf, nst_bnk, leftnb);
   3312                 ALPM_IER(rv);
   3313                 /* Now leftnb is free */
   3314                 rv = alpm_bkt_bnk_chk_rsvd(u, ipt, bp_conf, leftnb);
   3315                 if (BCM_SUCCESS(rv)) {
   3316                     if (PVT_BKT_IDX(pvt_node) != (leftnb / bnkpb)) {
   3317                         /* Update */
   3318                         PVT_BKT_IDX(pvt_node) = leftnb / bnkpb;
   3319                     }
   3320                     PVT_ROFS(pvt_node) = leftnb % bnkpb;
   3321                     bkt_info->bnk_fmt[PVT_ROFS(pvt_node)] = def_fmt;
   3322 
   3323                     *fmt_update = TRUE;
   3324                     goto end;
   3325                 }
   3326             } else {
   3327                 /* Shouldn't be here */
   3328                 rv = BCM_E_FULL;
   3329             }
   3330         }
   3331     }
   3332 
   3333     /* Case 4: table full */
   3334 
   3335 end:
   3336     if (BCM_SUCCESS(rv)) {
   3337         if (ALPMC(u)->_alpm_dbg_bmp & _ALPM_DBG_PVT_SANITY_NODE) {
   3338             rv = alpm_cb_pvt_sanity_cb(u, acb, pvt_node, "Expand");
   3339         }
   3340         acb->acb_cnt.c_expand++;
   3341     }
   3342     return rv;
   3343 }
   3344 
   3345 /* What is expected here when entering this function:
   3346  * all occupied banks are continuous.
   3347  *    all i in {i | bkt_info->bnk_fmt[i] is used} are continuous AND
   3348  *    foreach i belongs to {i | bkt_info->bnk_fmt[i] is used}:
   3349  *        bkt_info->vet_bmp[i]!=0
   3350  */
   3351 int
   3352 alpm_cb_expand_in_bkt(int u, _alpm_cb_t *acb,
   3353                       _alpm_pvt_node_t *pvt_node, int bnk_cnt)
   3354 {
   3355     int i, rv = BCM_E_FULL;
   3356     int bnkpb, end;
   3357     _alpm_bkt_info_t *bkt_info;
   3358     _alpm_bkt_pool_conf_t *bp_conf;
   3359     _alpm_bkt_info_t dst_bkt;
   3360 
   3361     ALPM_VERB(("Expanding ALPM CB %d bkt %d......\n",
   3362                acb->acb_idx, PVT_BKT_IDX(pvt_node)));
   3363 
   3364     /* Case 1: bank available in the same bucket
   3365      *         -> occupy the free bank */
   3366 
   3367     bkt_info = &PVT_BKT_INFO(pvt_node);
   3368     bp_conf  = ACB_BKT_VRF_POOL(acb, PVT_BKT_VRF(pvt_node));
   3369     bnkpb = BPC_BNK_PER_BKT(bp_conf);
   3370     end   = bnkpb;
   3371 
   3372     /* Occupy the free bank in the same bucket based on bkt_idx */
   3373     for (i = 0; i < end; i++) {
   3374         int glb_bnk;
   3375         if (BI_BNK_IS_USED(bkt_info, i)) {
   3376             continue;
   3377         }
   3378 
   3379         glb_bnk = PVT_BKT_IDX(pvt_node) * bnkpb + i;
   3380         rv = alpm_bkt_sharing_bnk_alloc(u, acb, PVT_BKT_VRF(pvt_node),
   3381                     PVT_BKT_IPT(pvt_node),
   3382                     bp_conf, &dst_bkt, NULL,
   3383                     glb_bnk, 1, 0xfffffff);
   3384         if (BCM_SUCCESS(rv)) {
   3385             BI_ROFS(bkt_info) = 0;
   3386             bkt_info->bnk_fmt[glb_bnk % bnkpb] =
   3387                 dst_bkt.bnk_fmt[glb_bnk % bnkpb];
   3388             goto end;
   3389         }
   3390     }
   3391 
   3392     /* Case 2: No free bank in the same bucket, but there are other
   3393      * continuous banks available:
   3394      *         -> Move banks to other area */
   3395     rv = alpm_bkt_sharing_bnk_alloc(u, acb, PVT_BKT_VRF(pvt_node),
   3396                 PVT_BKT_IPT(pvt_node),
   3397                 bp_conf, &dst_bkt, NULL,
   3398                 0, bnk_cnt+1, bnkpb);
   3399     if (BCM_SUCCESS(rv)) {
   3400         /* Move banks */
   3401         rv = alpm_bkt_move(u, acb, pvt_node, bkt_info, &dst_bkt);
   3402         goto end;
   3403     }
   3404 
   3405     /* Other case: table full */
   3406 
   3407 end:
   3408     if (BCM_SUCCESS(rv)) {
   3409         if (ALPMC(u)->_alpm_dbg_bmp & _ALPM_DBG_PVT_SANITY_NODE) {
   3410             rv = alpm_cb_pvt_sanity_cb(u, acb, pvt_node, "Expand");
   3411         }
   3412         acb->acb_cnt.c_expand++;
   3413     } else if (rv == BCM_E_NOT_FOUND) {
   3414         rv = BCM_E_FULL;
   3415     }
   3416     return rv;
   3417 }
   3418 
   3419 int
   3420 alpm_cb_defrag(int u, _alpm_cb_t *acb, int vrf_id, int ipt)
   3421 {
   3422     int rv = BCM_E_NONE;
   3423     int i, j, bnkpb;
   3424     int rngl, rngr, rngm;
   3425     _alpm_bkt_pool_conf_t *bp_conf;
   3426     SHR_BITDCL *bnk_bmp;
   3427 
   3428     bp_conf = ACB_BKT_VRF_POOL(acb, vrf_id);
   3429     bnkpb   = BPC_BNK_PER_BKT(bp_conf);
   3430 
   3431     if (BPC_BNK_CNT(bp_conf) - BPC_BNK_USED(bp_conf, ipt) < bnkpb) {
   3432         return BCM_E_FULL;
   3433     }
   3434 
   3435    /* Check bank usage threshold */
   3436     if (alpm_cb_bnk_threshold_exceed(u, acb, vrf_id, ipt)) {
   3437         return BCM_E_FULL;
   3438     }
   3439 
   3440     /* Find best zone for defragmentation */
   3441     bnk_bmp = BPC_BNK_BMP(bp_conf, ipt);
   3442     rv = alpm_bkt_free_bnk_range_get(u,
   3443             bnk_bmp, BPC_BNK_CNT(bp_conf),
   3444             bnkpb, &rngl, &rngr, &rngm);
   3445 
   3446     ALPM_IEG_PRT_EXCEPT(rv, BCM_E_FULL);
   3447 
   3448     if (ALPMC(u)->_alpm_dbg_bmp & _ALPM_DBG_PVT_DEFRAG) {
   3449         cli_out("free range get: bpb %d, range left %d, right %d, mid %d\n",
   3450                 bnkpb, rngl, rngr, rngm);
   3451         alpm_util_bnk_range_print(u, bnk_bmp, 0xfffffff, 32, rngl, rngr);
   3452     }
   3453 
   3454     /*
   3455      ---------------------------
   3456      | |#|#| | | | |#|#|#| | | |
   3457      ---------------------------
   3458       ^         ^             ^
   3459       rngl      rngm          rngr
   3460 
   3461      ---------------------------
   3462      | |#| |#| |#| |#| |#| |#| |
   3463      ---------------------------
   3464       ^           ^           ^
   3465       rngl        rngm        rngr
   3466      */
   3467     for (i = rngm - 1; i > rngl; i--) {
   3468         if (!SHR_BITGET(bnk_bmp, i)) {
   3469             continue;
   3470         }
   3471         for (j = i - 1; j >= rngl; j--) {
   3472             if (SHR_BITGET(bnk_bmp, j)) {
   3473                 continue;
   3474             }
   3475 
   3476             /* bnk_bmp could be changed here */
   3477             rv = alpm_bkt_free_bnk_move(u, acb, bp_conf, j, i);
   3478             ALPM_IEG(rv);
   3479             break;
   3480         }
   3481     }
   3482 
   3483     for (i = rngm + 1; i < rngr; i++) {
   3484         if (!SHR_BITGET(bnk_bmp, i)) {
   3485             continue;
   3486         }
   3487         for (j = i + 1; j <= rngr; j++) {
   3488             if (SHR_BITGET(bnk_bmp, j)) {
   3489                 continue;
   3490             }
   3491 
   3492             /* bnk_bmp could be changed here */
   3493             rv = alpm_bkt_free_bnk_move(u, acb, bp_conf, j, i);
   3494             ALPM_IEG(rv);
   3495             break;
   3496         }
   3497     }
   3498 
   3499     if (ALPMC(u)->_alpm_dbg_bmp & _ALPM_DBG_PVT_DEFRAG) {
   3500         cli_out("After Defrag: \n");
   3501         alpm_util_bnk_range_print(u, bnk_bmp, 0xfffffff, 32,
   3502                                   rngl, rngr);
   3503     }
   3504 
   3505     acb->acb_cnt.c_defrag++;
   3506 
   3507 bad:
   3508     return rv;
   3509 }
   3510 
   3511 static int
   3512 alpm_cb_split(int u, _alpm_cb_t *acb, _bcm_defip_cfg_t *lpm_cfg,
   3513               _alpm_bkt_info_t *nbkt_info, int max_spl_cnt)
   3514 {
   3515     int     rv = BCM_E_NONE;
   3516     int     max_key_len, ipt;
   3517     int     bkt_allocated = 0;
   3518     int     vrf_id = 0;
   3519     int     shrink_empty_only = 2;
   3520 
   3521     uint32  *bak_idx = NULL;
   3522 
   3523     alpm_lib_trie_t      *nbkt_trie = NULL;
   3524 
   3525     _alpm_bkt_pfx_arr_t *pfx_arr = NULL;
   3526     _alpm_pvt_node_t    *opvt_node = NULL;
   3527     _alpm_pvt_node_t    *npvt_node = NULL;
   3528     _bcm_defip_cfg_t    pvt_lpm_cfg;
   3529     _alpm_tcam_write_t  *tcam_write = lpm_cfg->tcam_write;
   3530 
   3531     ipt    = ALPM_LPM_IPT(u, lpm_cfg);
   3532     vrf_id = ALPM_LPM_VRF_ID(u, lpm_cfg);
   3533 
   3534     max_key_len = alpm_util_trie_max_key_len(u, ipt);
   3535     /* 1. alpm_lib_trie_split to get split-prefix set
   3536      * Allocate a new bucket based on the split prefixes
   3537      * min_sz, in TH-style-ALPM devices, it's entry count,
   3538      * in FMT-enabled deivces, it's bank count */
   3539     rv = alpm_bkt_trie_split(u, acb, lpm_cfg, &nbkt_trie, &npvt_node,
   3540                              max_key_len, &max_spl_cnt);
   3541     ALPM_IEG(rv);
   3542 
   3543     if (max_spl_cnt < 0xffff && !ACB_BKT_FIXED_FMT(acb, 1)) {
   3544         rv = alpm_bkt_free(u, acb, vrf_id, ipt, nbkt_info);
   3545         ALPM_IEG(rv);
   3546         sal_memset(nbkt_info, 0, sizeof(_alpm_bkt_info_t));
   3547         nbkt_info->reverse = 1;
   3548         rv = alpm_bkt_alloc(u, acb, vrf_id, ipt, ACB_BNK_PER_BKT(acb, vrf_id),
   3549                             nbkt_info, NULL);
   3550         /* Should not see error here */
   3551         ALPM_IEG_PRT_EXCEPT(rv, BCM_E_FULL);
   3552     }
   3553 
   3554     /* 3. HW: Copy split prefixes from old bucket to new bucket */
   3555     sal_memcpy(&PVT_BKT_INFO(npvt_node), nbkt_info, sizeof(_alpm_bkt_info_t));
   3556     bkt_allocated = TRUE;
   3557 
   3558     ALPM_ALLOC_EG(pfx_arr, sizeof(*pfx_arr), "pfx_arr");
   3559     rv = alpm_lib_trie_traverse(nbkt_trie, alpm_trie_pfx_cb, pfx_arr,
   3560                        trieTraverseOrderIn);
   3561     ALPM_IEG(rv);
   3562 
   3563     /* for !FIXED_FMT:
   3564      * Need to sort pfx_arr here, node with longer prefix length comes first,
   3565      * Should let longer bkt node to choose bkt_ent_get first
   3566      */
   3567     if (!ACB_BKT_FIXED_FMT(acb, 1)) {
   3568         _shr_sort(pfx_arr->pfx, pfx_arr->pfx_cnt, sizeof(_alpm_bkt_node_t *),
   3569                   alpm_util_pfx_len_cmp);
   3570     }
   3571 
   3572     /* 3. Save old ent_idx of prefixes for recovery */
   3573     rv = alpm_bkt_pfx_idx_backup(u, pfx_arr, &bak_idx);
   3574     ALPM_IEG(rv);
   3575 
   3576     if (lpm_cfg->spl_pn != NULL) {
   3577         opvt_node = (_alpm_pvt_node_t *)lpm_cfg->spl_pn;
   3578     } else {
   3579         opvt_node = ACB_HAS_TCAM(acb) ? lpm_cfg->l1_pvt_node : lpm_cfg->pvt_node;
   3580     }
   3581 
   3582     /* bkt_pfx_copy updates ent_idx of each prefix in the new trie */
   3583     rv = alpm_bkt_pfx_copy(u, acb, pfx_arr, opvt_node, npvt_node);
   3584     ALPM_IEG(rv);
   3585 
   3586     /* Free unused banks of new pivot to Global bank pool */
   3587     rv = alpm_bkt_bnk_shrink(u, ipt, acb, ACB_BKT_VRF_POOL(acb, vrf_id),
   3588                              &PVT_BKT_INFO(npvt_node), NULL);
   3589     ALPM_IEG(rv);
   3590 
   3591     if (!ACB_BKT_FIXED_FMT(acb, 1) && ACB_HAS_TCAM(acb)) {
   3592         /* Check if an extra split is required */
   3593         rv = alpm_bkt_ent_get(u, vrf_id, acb, npvt_node, lpm_cfg->defip_sub_len, NULL, NULL, 1);
   3594         if (rv == BCM_E_FULL) {
   3595             int rsvd = (ipt == ALPM_IPT_V6) ? 1 : 0;
   3596             /* Cannot affort another split, so should return here */
   3597             if (bcm_esw_alpm_tcam_avail(u, vrf_id, ipt, PVT_KEY_LEN(npvt_node), 0) <= rsvd) {
   3598                 ALPM_IEG_PRT_EXCEPT(rv, BCM_E_FULL);
   3599             }
   3600         }
   3601     }
   3602 
   3603     /* 4. HW: insert new pivot
   3604      *    recursion happens here: BCM_E_FULL is expected
   3605      */
   3606     sal_memcpy(&pvt_lpm_cfg, lpm_cfg, sizeof(pvt_lpm_cfg));
   3607     /* never insert new pvt with HIT=1 (from original lpm_cfg->defip_flags) */
   3608     pvt_lpm_cfg.defip_flags &= ~BCM_L3_HIT;
   3609     if (ACB_HAS_TCAM(acb)) {
   3610         pvt_lpm_cfg.pvt_node = (uint32 *)npvt_node;
   3611         pvt_lpm_cfg.bkt_info = NULL;
   3612     } else {
   3613         pvt_lpm_cfg.l1_pvt_node = NULL;
   3614         pvt_lpm_cfg.pvt_node = NULL;
   3615         pvt_lpm_cfg.spl_pn = NULL;
   3616         pvt_lpm_cfg.spl_opn = opvt_node;
   3617         pvt_lpm_cfg.spl_npn = npvt_node;
   3618         pvt_lpm_cfg.bkt_info = (uint32 *)&PVT_BKT_INFO(npvt_node);
   3619         if (ACB_BKT_FIXED_FMT(acb, 1)) {
   3620             pvt_lpm_cfg.bkt_kshift = 0;
   3621         } else {
   3622             /* for upr acb bkt */
   3623             pvt_lpm_cfg.bkt_kshift = PVT_KEY_LEN(npvt_node);
   3624         }
   3625     }
   3626     pvt_lpm_cfg.bkt_node = NULL;
   3627 
   3628     /* pvt_lpm_cfg.tcam_write has same pointer as lpm_cfg->tcam_write */
   3629     rv = alpm_bkt_split_pvt_add(u, acb, &pvt_lpm_cfg, npvt_node);
   3630     /* rv = *_E_FULL is allowed here */
   3631     if (rv == BCM_E_FULL) {
   3632         ALPM_INFO(("**ACB(%d).BKT.SPLIT return Full\n", ACB_IDX(acb)));
   3633     } else if (rv == BCM_E_BUSY) {
   3634         lpm_cfg->spl_pn = pvt_lpm_cfg.spl_pn;
   3635         sal_memcpy(lpm_cfg->spl_key, pvt_lpm_cfg.spl_key, sizeof(lpm_cfg->spl_key));
   3636         lpm_cfg->spl_key_len = pvt_lpm_cfg.spl_key_len;
   3637     }
   3638 
   3639     ALPM_IEG_PRT_EXCEPT(rv, BCM_E_FULL);
   3640 
   3641     /* Case of add new L1 pvt during L2 bkt split:
   3642        - If new L2 bkt belongs to new L1 pvt, add new L2 bkt first.
   3643        - Then write returned lpm_cfg->tcam_write to TCAM HW */
   3644     if (tcam_write != NULL) {
   3645         rv = alpm_bkt_add_to_npvt(u, acb, lpm_cfg, npvt_node);
   3646         if (tcam_write->hw_idx >= 0) {
   3647             int rv1;
   3648             rv1 = _tcam_entry_write(u, ALPM_LPM_PKM(u, lpm_cfg), tcam_write->ent,
   3649                                     tcam_write->hw_idx, tcam_write->hw_idx);
   3650             ALPM_INFO(("Write to TCAM HW at hw_idx %d after add new L2 bkt\n",
   3651                        tcam_write->hw_idx));
   3652             ALPM_IEG(rv1);
   3653         }
   3654         /* check returned rv after _tcam_entry_write done */
   3655         ALPM_IEG_PRT_EXCEPT(rv, BCM_E_FULL);
   3656     }
   3657 
   3658     /*
   3659      * In case of pivot insert failure, we need to :
   3660      *     a). recover split_trie
   3661      *     b). Invalidate new bucket.
   3662      */
   3663 
   3664     /* 5. HW: Invalidate split prefixes in the old bucket */
   3665     rv = alpm_bkt_pfx_clean(u, acb, opvt_node, pfx_arr->pfx_cnt, bak_idx);
   3666     ALPM_IEG(rv);
   3667 
   3668     /* 6. SW: Shrink old bucket,
   3669      * A important step to make sure banks are continuously occupied by pivot
   3670      */
   3671     rv = alpm_bkt_pfx_shrink(u, acb, opvt_node, &shrink_empty_only);
   3672     ALPM_IEG(rv);
   3673 
   3674     /* 7. SW: release temporary resources */
   3675     alpm_util_free(bak_idx);
   3676     alpm_util_free(pfx_arr);
   3677 
   3678     if (ALPMC(u)->_alpm_dbg_bmp & _ALPM_DBG_PVT_SANITY_NODE) {
   3679         rv = alpm_cb_pvt_sanity_cb(u, acb, opvt_node, "SplitOpvt");
   3680         if (BCM_SUCCESS(rv)) {
   3681             rv = alpm_cb_pvt_sanity_cb(u, acb, npvt_node, "SplitNpvt");
   3682         }
   3683     }
   3684 
   3685     if ((PVT_KEY_LEN(opvt_node) != 0 &&
   3686         PVT_BKT_TRIE(opvt_node)->trie == NULL)) {
   3687         alpm_lib_trie_node_t *tn = NULL;
   3688         rv = alpm_pvt_delete_by_pvt_node(u, acb, opvt_node);
   3689         if (BCM_FAILURE(rv)) {
   3690             ALPM_ERR(("alpm_pvt_delete_by_pvt_node(trie==NULL) failure\n"));
   3691         }
   3692         rv = alpm_lib_trie_delete(ACB_PVT_TRIE(acb, vrf_id, ipt), opvt_node->key,
   3693                          PVT_KEY_LEN(opvt_node), &tn);
   3694         if (BCM_FAILURE(rv)) {
   3695             ALPM_ERR(("Trie delete node failure\n"));
   3696         }
   3697         (void)alpm_lib_trie_destroy(PVT_BKT_TRIE(opvt_node));
   3698         alpm_util_free(tn);
   3699 
   3700         /* Set lpm_cfg the corresponding opvt_node pointer to NULL */
   3701         if (lpm_cfg->spl_pn == opvt_node) {
   3702             lpm_cfg->spl_pn = NULL;
   3703         }
   3704         if (lpm_cfg->l1_pvt_node == opvt_node) {
   3705             lpm_cfg->l1_pvt_node = NULL;
   3706         }
   3707         if (lpm_cfg->pvt_node == opvt_node) {
   3708             lpm_cfg->pvt_node = NULL;
   3709         }
   3710     }
   3711 
   3712     acb->acb_cnt.c_split++;
   3713     if (BCM_SUCCESS(rv)) {
   3714         ALPM_MERGE_STATE_CHANGED(u, vrf_id);
   3715     }
   3716 
   3717     return rv;
   3718 
   3719 bad:
   3720     /* Clean new bucket */
   3721     if (bak_idx != NULL) {
   3722         alpm_bkt_pfx_idx_restore(u, pfx_arr, bak_idx);
   3723         (void)alpm_bkt_pfx_clean(u, acb, npvt_node, pfx_arr->pfx_cnt, bak_idx);
   3724         alpm_util_free(bak_idx);
   3725     }
   3726 
   3727     if (pfx_arr != NULL) {
   3728         alpm_util_free(pfx_arr);
   3729     }
   3730 
   3731     /* free allocated bucket */
   3732     if (bkt_allocated) {
   3733         sal_memcpy(nbkt_info, &PVT_BKT_INFO(npvt_node), sizeof(_alpm_bkt_info_t));
   3734     }
   3735     (void)alpm_bkt_free(u, acb, vrf_id, ipt, nbkt_info);
   3736 
   3737     if (nbkt_trie != NULL) {
   3738         if (nbkt_trie->trie != NULL) {
   3739             (void)alpm_lib_trie_merge(PVT_BKT_TRIE(opvt_node), nbkt_trie->trie,
   3740                                       npvt_node->key, PVT_KEY_LEN(npvt_node));
   3741         }
   3742 
   3743         alpm_lib_trie_destroy(nbkt_trie);
   3744     }
   3745 
   3746     if (npvt_node != NULL) {
   3747         alpm_util_free(npvt_node);
   3748     }
   3749 
   3750     return rv;
   3751 }
   3752 
   3753 static int
   3754 alpm_cb_merge_pvt(int u, _alpm_cb_t *acb, _alpm_pvt_node_t *src_pvt,
   3755                   _alpm_pvt_node_t *dst_pvt, int merge_dir)
   3756 {
   3757     int rv = BCM_E_NONE;
   3758     int i, bnk_pbk;
   3759     int ipt, vrf_id;
   3760     uint32  *bak_idx = NULL;
   3761 
   3762     int step_trie_merged = 0;
   3763 
   3764     SHR_BITDCL *bnk_bmp;
   3765     alpm_lib_trie_node_t *tn = NULL;
   3766     _alpm_pvt_node_t *prt_pvt, *chd_pvt, *tmp_pvt;
   3767     _alpm_bkt_info_t tmp_bi;
   3768     _alpm_bkt_pool_conf_t *bp_conf;
   3769     _alpm_bkt_pfx_arr_t *pfx_arr = NULL;
   3770 
   3771     ipt    = PVT_BKT_IPT(src_pvt);
   3772     vrf_id = PVT_BKT_VRF(src_pvt);
   3773     bp_conf = ACB_BKT_VRF_POOL(acb, vrf_id);
   3774     bnk_pbk = BPC_BNK_PER_BKT(bp_conf);
   3775     bnk_bmp = BPC_BNK_BMP(bp_conf, ipt);
   3776 
   3777     /* 1. Expand the bkt of dst_pvt */
   3778     for (i = PVT_BKT_IDX(dst_pvt) * bnk_pbk;
   3779          i < (PVT_BKT_IDX(dst_pvt) + 1) * bnk_pbk; i++) {
   3780         if (SHR_BITGET(bnk_bmp, i)) {
   3781             continue;
   3782         }
   3783 
   3784         PVT_BKT_INFO(dst_pvt).bnk_fmt[i % bnk_pbk] =
   3785             alpm_util_bkt_def_fmt_get(u, acb, vrf_id, ipt);
   3786         SHR_BITSET(bnk_bmp, i);
   3787         BPC_BNK_USED(bp_conf, ipt) += 1;
   3788     }
   3789 
   3790     /* 2. Copy pfx from src_pvt to dst_pvt */
   3791     ALPM_ALLOC_EG(pfx_arr, sizeof(*pfx_arr), "pfx_arr");
   3792     rv = alpm_lib_trie_traverse(PVT_BKT_TRIE(src_pvt), alpm_trie_pfx_cb, pfx_arr,
   3793                        trieTraverseOrderIn);
   3794     ALPM_IEG(rv);
   3795     rv = alpm_bkt_pfx_idx_backup(u, pfx_arr, &bak_idx);
   3796     ALPM_IEG(rv);
   3797     rv = alpm_bkt_pfx_copy(u, acb, pfx_arr, src_pvt, dst_pvt);
   3798     ALPM_IEG(rv);
   3799 
   3800     if (merge_dir == ACB_MERGE_PARENT_TO_CHILD) {
   3801         prt_pvt = src_pvt;
   3802         chd_pvt = dst_pvt;
   3803     } else {
   3804         prt_pvt = dst_pvt;
   3805         chd_pvt = src_pvt;
   3806     }
   3807 
   3808     /* 3. Merge trie */
   3809     rv = alpm_lib_trie_merge(PVT_BKT_TRIE(prt_pvt), PVT_BKT_TRIE(chd_pvt)->trie,
   3810                              chd_pvt->key, chd_pvt->key_len);
   3811     ALPM_IEG(rv);
   3812     step_trie_merged = 1;
   3813 
   3814     if (merge_dir == ACB_MERGE_PARENT_TO_CHILD) {
   3815         /* 4. Update pvt bkt_ptr if copy from parent to child */
   3816         sal_memcpy(&tmp_bi, &PVT_BKT_INFO(prt_pvt), sizeof(_alpm_bkt_info_t));
   3817         sal_memcpy(&PVT_BKT_INFO(prt_pvt), &PVT_BKT_INFO(chd_pvt),
   3818                    sizeof(_alpm_bkt_info_t));
   3819         rv = alpm_pvt_update_by_pvt_node(u, acb, prt_pvt, ALPM_PVT_UPDATE_ALPM_DATA);
   3820         if (BCM_FAILURE(rv)) {
   3821             /* Not expecting delete failure here */
   3822             ALPM_ERR(("cb_merge pvt update failed, rv=%d\n", rv));
   3823         }
   3824         /* Recovery bkt info for invalidation */
   3825         sal_memcpy(&PVT_BKT_INFO(prt_pvt), &tmp_bi, sizeof(_alpm_bkt_info_t));
   3826     }
   3827 
   3828     /* 5. Invalid old entries
   3829      *    Not expecting failures on invalidation */
   3830     rv = alpm_bkt_pfx_clean(u, acb, src_pvt, pfx_arr->pfx_cnt, bak_idx);
   3831     ALPM_IEG(rv);
   3832     rv = alpm_bkt_bnk_shrink(u, ipt, acb, ACB_BKT_VRF_POOL(acb, vrf_id),
   3833                              &PVT_BKT_INFO(src_pvt), NULL);
   3834     ALPM_IEG(rv);
   3835     rv = alpm_bkt_bnk_shrink(u, ipt, acb, ACB_BKT_VRF_POOL(acb, vrf_id),
   3836                              &PVT_BKT_INFO(dst_pvt), NULL);
   3837     ALPM_IEG(rv);
   3838 
   3839     /* 6. Delete child pvt entry from pvt table */
   3840     rv = alpm_pvt_delete_by_pvt_node(u, acb, chd_pvt);
   3841     if (BCM_FAILURE(rv)) {
   3842         /* Not expecting delete failure here */
   3843         ALPM_ERR(("cb_merge pvt delete failed, rv=%d\n", rv));
   3844     }
   3845 
   3846     /* 7. Destroy child pvt from trie, tn is chd_pvt */
   3847     rv = alpm_lib_trie_delete(ACB_PVT_TRIE(acb, vrf_id, ipt), chd_pvt->key,
   3848                      PVT_KEY_LEN(chd_pvt), &tn);
   3849     if (BCM_FAILURE(rv)) {
   3850         /* Not expecting delete failure here */
   3851         ALPM_ERR(("cb_merge alpm_lib_trie_delete failed, rv=%d\n", rv));
   3852     }
   3853     /* Should copy bi before alpm_lib_trie_destroy tn */
   3854     if (merge_dir == ACB_MERGE_PARENT_TO_CHILD) {
   3855         int tab_idx, bnk;
   3856         _alpm_bkt_info_t *bi;
   3857         bi = &PVT_BKT_INFO(prt_pvt);
   3858         sal_memcpy(bi, &PVT_BKT_INFO(chd_pvt), sizeof(_alpm_bkt_info_t));
   3859 
   3860         /* Update pvt_ptr for child bucket */
   3861         for (bnk = 0; bnk < bnk_pbk; bnk++) {
   3862             if (BI_BNK_IS_USED(bi, bnk)) {
   3863                 tab_idx = ALPM_TAB_IDX_GET_BI_BNK(acb, bi, bnk);
   3864                 bp_conf->pvt_ptr[tab_idx] = prt_pvt;
   3865             }
   3866         }
   3867     }
   3868 
   3869     tmp_pvt = (_alpm_pvt_node_t *)tn;
   3870     alpm_lib_trie_destroy(PVT_BKT_TRIE(tmp_pvt));
   3871     alpm_util_free(tmp_pvt);
   3872     alpm_util_free(bak_idx);
   3873     alpm_util_free(pfx_arr);
   3874 
   3875     return rv;
   3876 
   3877 bad:
   3878     if (step_trie_merged) {
   3879         uint32  pvt[5], len;
   3880         alpm_lib_trie_split2(PVT_BKT_TRIE(prt_pvt), chd_pvt->key,
   3881                              chd_pvt->key_len, pvt, &len,
   3882                              &(PVT_BKT_TRIE(chd_pvt)->trie),
   3883                              PVT_BKT_TRIE(chd_pvt)->trie->count, 1);
   3884     }
   3885 
   3886     /* Clean new bucket */
   3887     if (bak_idx != NULL) {
   3888         alpm_bkt_pfx_idx_restore(u, pfx_arr, bak_idx);
   3889         (void)alpm_bkt_pfx_clean(u, acb, dst_pvt, pfx_arr->pfx_cnt, bak_idx);
   3890         alpm_util_free(bak_idx);
   3891     }
   3892 
   3893     if (pfx_arr != NULL) {
   3894         alpm_util_free(pfx_arr);
   3895     }
   3896     return rv;
   3897 }
   3898 
   3899 static int
   3900 alpm_cb_merge_cb(alpm_lib_trie_node_t *ptrie, alpm_lib_trie_node_t *trie,
   3901                  alpm_lib_trie_traverse_state_t *state, void *info)
   3902 {
   3903     int u, rv;
   3904     int bnkpb, entpb;
   3905     int vrf_id;
   3906     _alpm_cb_t *acb;
   3907     _alpm_pvt_node_t *prt_pvt, *chd_pvt, *src_pvt, *dst_pvt;
   3908     _alpm_cb_merge_ctrl_t *merge_ctrl;
   3909     _alpm_cb_merge_type_t merge_dir = ACB_MERGE_INVALID;
   3910 
   3911     prt_pvt = (_alpm_pvt_node_t *)ptrie;
   3912     chd_pvt = (_alpm_pvt_node_t *)trie;
   3913     if (!prt_pvt) {
   3914         return BCM_E_NONE;
   3915     }
   3916 
   3917     if (PVT_BKT_TRIE(prt_pvt)->trie == NULL) {
   3918         merge_dir = ACB_MERGE_PARENT_TO_CHILD;
   3919     }
   3920 
   3921     if (PVT_BKT_TRIE(chd_pvt)->trie == NULL) {
   3922         merge_dir = ACB_MERGE_CHILD_TO_PARENT;
   3923     }
   3924 
   3925     merge_ctrl = (_alpm_cb_merge_ctrl_t *)info;
   3926     u   = merge_ctrl->unit;
   3927     acb = merge_ctrl->acb;
   3928     vrf_id = merge_ctrl->vrf_id;
   3929     bnkpb  = merge_ctrl->bnk_pbkt;
   3930     entpb  = merge_ctrl->ent_pbnk;
   3931 
   3932     if (merge_dir == ACB_MERGE_INVALID) {
   3933         int mrts, prt_bnks, chd_bnks;
   3934 
   3935         mrts = PVT_BKT_TRIE(prt_pvt)->trie->count +
   3936                PVT_BKT_TRIE(chd_pvt)->trie->count;
   3937         if (mrts > bnkpb * entpb) {
   3938             return BCM_E_NONE;
   3939         }
   3940 
   3941         prt_bnks = bnkpb - alpm_util_bkt_token_bnks(u, acb, vrf_id, prt_pvt);
   3942         chd_bnks = bnkpb - alpm_util_bkt_token_bnks(u, acb, vrf_id, chd_pvt);
   3943 
   3944         if (mrts <= prt_bnks * entpb) {
   3945             merge_dir   = ACB_MERGE_CHILD_TO_PARENT;
   3946         } else if (mrts <= chd_bnks * entpb) {
   3947             merge_dir   = ACB_MERGE_PARENT_TO_CHILD;
   3948         } else {
   3949             return BCM_E_NONE;
   3950         }
   3951     }
   3952 
   3953     if (merge_dir == ACB_MERGE_PARENT_TO_CHILD) {
   3954         src_pvt = prt_pvt;
   3955         dst_pvt = chd_pvt;
   3956     } else {
   3957         src_pvt = chd_pvt;
   3958         dst_pvt = prt_pvt;
   3959     }
   3960 
   3961     rv = alpm_cb_merge_pvt(u, acb, src_pvt, dst_pvt, merge_dir);
   3962 
   3963     if (BCM_FAILURE(rv)) {
   3964         ALPM_ERR(("alpm merge failed rv %d\n", rv));
   3965         return rv;
   3966     }
   3967 
   3968     *state = trieTraverseStateDel;
   3969     if (++merge_ctrl->merge_count >= ACB_MERGE_THRESHOLD) {
   3970         *state = trieTraverseStateDone;
   3971     }
   3972 
   3973     acb->acb_cnt.c_merge++;
   3974 
   3975     return BCM_E_NONE;
   3976 
   3977 }
   3978 
   3979 int
   3980 alpm_cb_merge(int u, _alpm_cb_t *acb, int vrf_id, int ipt)
   3981 {
   3982     int rv = BCM_E_NONE;
   3983     uint8 fmt;
   3984     alpm_lib_trie_t *pvt_trie;
   3985     _alpm_cb_merge_ctrl_t merge_ctrl;
   3986 
   3987     pvt_trie = ACB_PVT_TRIE(acb, vrf_id, ipt);
   3988     if (!ALPM_MERGE_REQD(u, vrf_id) ||
   3989         pvt_trie == NULL ||
   3990         pvt_trie->trie == NULL) {
   3991         return BCM_E_FULL;
   3992     }
   3993 
   3994     sal_memset(&merge_ctrl, 0, sizeof(merge_ctrl));
   3995     merge_ctrl.unit     = u;
   3996     merge_ctrl.ipt      = ipt;
   3997     merge_ctrl.vrf_id   = vrf_id;
   3998     merge_ctrl.acb      = acb;
   3999 
   4000     fmt = alpm_util_bkt_def_fmt_get(u, acb, vrf_id, ipt);
   4001     merge_ctrl.bnk_pbkt = ACB_BNK_PER_BKT(acb, vrf_id);
   4002     merge_ctrl.ent_pbnk = ACB_FMT_ENT_MAX(acb, vrf_id, fmt);
   4003 
   4004     rv = alpm_lib_trie_traverse2(pvt_trie, alpm_cb_merge_cb, &merge_ctrl,
   4005                         trieTraverseOrderPost);
   4006 
   4007     if (BCM_FAILURE(rv)) {
   4008         ALPM_ERR(("Logic bucket merge failed, ipt %d vrf_id %d rv %d.\n",
   4009                   ipt, vrf_id, rv));
   4010     }
   4011 
   4012     if (merge_ctrl.merge_count == 0) {
   4013         ALPM_MERGE_STATE_CHKED(u, vrf_id);
   4014         rv = BCM_E_FULL;
   4015     }
   4016 
   4017     return rv;
   4018 }
   4019 
   4020 int
   4021 alpm_cb_delete(int u, _alpm_cb_t *acb, _bcm_defip_cfg_t *lpm_cfg)
   4022 {
   4023     int rv = BCM_E_NONE;
   4024     int ipt, vrf_id, pfx_len;
   4025     int bkt_empty;
   4026     uint32 *prefix;
   4027     int shrink_empty_only = 1;
   4028 
   4029     _alpm_ppg_data_t ppg_data;
   4030     _alpm_pvt_node_t *pvt_node;
   4031     _alpm_bkt_node_t *bkt_node = NULL;
   4032     _alpm_bkt_node_t *alt_def_pfx = NULL;
   4033     uint32           alt_bmp_len = 0;
   4034 
   4035     alpm_lib_trie_t *bkt_trie = NULL;
   4036     alpm_lib_trie_node_t *tn = NULL;
   4037 
   4038     ipt     = ALPM_LPM_IPT(u, lpm_cfg);
   4039     vrf_id  = ALPM_LPM_VRF_ID(u, lpm_cfg);
   4040     prefix  = lpm_cfg->user_data;
   4041     pfx_len = lpm_cfg->defip_sub_len;
   4042 
   4043     /* Check Init */
   4044     if (!ACB_VRF_INITED(u, acb, vrf_id, ipt)) {
   4045         return BCM_E_PARAM;
   4046     }
   4047 
   4048     pvt_node = ACB_HAS_TCAM(acb) ? lpm_cfg->l1_pvt_node : lpm_cfg->pvt_node;
   4049     if (pvt_node == NULL) {
   4050         ALPM_IEG(alpm_pvt_find(u, acb, lpm_cfg, &pvt_node));
   4051     }
   4052 
   4053     bkt_trie = PVT_BKT_TRIE(pvt_node);
   4054     rv = alpm_lib_trie_delete(bkt_trie, prefix, pfx_len, &tn);
   4055     ALPM_IEG(rv);
   4056     bkt_node = (_alpm_bkt_node_t *)tn;
   4057 
   4058     rv = alpm_vrf_pfx_trie_delete(u, acb, lpm_cfg, pvt_node,
   4059                                   &alt_def_pfx, &alt_bmp_len);
   4060     ALPM_IEG(rv);
   4061 
   4062     /* do insert propagation to update existing default datas */
   4063     if (ACB_HAS_RTE(acb, vrf_id)) {
   4064         /* Fill in AUX Scratch and perform PREFIX Operation */
   4065         alpm_ppg_prepare(u, lpm_cfg, alt_bmp_len, alt_def_pfx, &ppg_data);
   4066         rv = alpm_ppg_assoc_data(u, ALPM_PPG_DELETE, &ppg_data);
   4067         ALPM_IEG(rv);
   4068     }
   4069 
   4070     /* Delete pvt entry if bucket is empty */
   4071     bkt_empty = (PVT_KEY_LEN(pvt_node) != 0 && bkt_trie->trie == NULL);
   4072     if (bkt_empty) {
   4073         rv = alpm_pvt_delete_by_pvt_node(u, acb, pvt_node);
   4074         ALPM_IEG(rv);
   4075     }
   4076 
   4077     /* Invalid the bucket entry */
   4078     rv = alpm_bkt_pfx_clean(u, acb, pvt_node, 1, &bkt_node->ent_idx);
   4079     ALPM_IEG(rv);
   4080 
   4081     if (ACB_BKT_WRA(acb, PVT_BKT_VRF(pvt_node))) {
   4082         if (bkt_empty) {
   4083             rv = alpm_bkt_bnk_shrink(u, ipt, acb,
   4084                     ACB_BKT_VRF_POOL(acb, PVT_BKT_VRF(pvt_node)),
   4085                     &PVT_BKT_INFO(pvt_node), NULL);
   4086             ALPM_IEG(rv);
   4087         } else {
   4088             rv = alpm_bkt_pfx_shrink(u, acb, pvt_node, &shrink_empty_only);
   4089             ALPM_IEG(rv);
   4090         }
   4091     } else {
   4092         if (bkt_empty || bkt_trie->trie != NULL ||
   4093             VRF_ROUTE_CNT(acb, vrf_id, ipt) == 0) {
   4094             rv = alpm_bkt_bnk_shrink(u, ipt, acb,
   4095                     ACB_BKT_VRF_POOL(acb, PVT_BKT_VRF(pvt_node)),
   4096                     &PVT_BKT_INFO(pvt_node), NULL);
   4097             ALPM_IEG(rv);
   4098         }
   4099     }
   4100 
   4101     alpm_util_free(bkt_node);
   4102 
   4103     if (bkt_empty) {
   4104         rv = alpm_lib_trie_delete(ACB_PVT_TRIE(acb, vrf_id, ipt), pvt_node->key,
   4105                          PVT_KEY_LEN(pvt_node), &tn);
   4106         if (BCM_FAILURE(rv)) {
   4107             ALPM_ERR(("Trie delete node failure\n"));
   4108         }
   4109 
   4110         (void)alpm_lib_trie_destroy(bkt_trie);
   4111         alpm_util_free(pvt_node);
   4112     } else {
   4113         if (BCM_SUCCESS(rv) &&
   4114             ALPMC(u)->_alpm_dbg_bmp & _ALPM_DBG_PVT_SANITY_NODE) {
   4115             rv = alpm_cb_pvt_sanity_cb(u, acb, pvt_node, "CBDelete");
   4116         }
   4117     }
   4118 
   4119     if (BCM_SUCCESS(rv)) {
   4120         ALPM_MERGE_STATE_CHANGED(u, vrf_id);
   4121     }
   4122 
   4123     VRF_ROUTE_DEC(acb, vrf_id, ipt);
   4124 
   4125     return rv;
   4126 
   4127 bad:
   4128     /* Roll back ? */
   4129     return rv;
   4130 }
   4131 
   4132 uint32
   4133 alpm_cb_pvt_most_ref_len_get(int u, uint32 *pvt_len_cnt, int max_len)
   4134 {
   4135     int i;
   4136     int max_cnt = 0, max_ref_len = 0;
   4137 
   4138     for (i = 0; i < 128; i++) {
   4139         if (i >= max_len) {
   4140             break;
   4141         }
   4142         if (max_cnt < pvt_len_cnt[i]) {
   4143             max_cnt = pvt_len_cnt[i];
   4144             max_ref_len = i;
   4145         }
   4146     }
   4147     return max_ref_len;
   4148 }
   4149 
   4150 static int
   4151 alpm_trie_pfx_len_ref_cnt_cb(alpm_lib_trie_node_t *node, void *user_data)
   4152 {
   4153     uint32 *pl_ref_cnt;
   4154 
   4155     pl_ref_cnt = (uint32 *)user_data;
   4156     if (node->type == trieNodeTypePayload) {
   4157         uint32 key_len = ((_alpm_bkt_node_t *)node)->key_len;
   4158         pl_ref_cnt[key_len]++;
   4159     }
   4160     return BCM_E_NONE;
   4161 }
   4162 
   4163 int
   4164 alpm_cb_path_construct(int u, _alpm_cb_t *acb, _bcm_defip_cfg_t *lpm_cfg)
   4165 {
   4166     int rv = BCM_E_NONE;
   4167     int vrf_id, ipt;
   4168     int fmt_update = 0;
   4169 
   4170     vrf_id = ALPM_LPM_VRF_ID(u, lpm_cfg);
   4171     ipt    = ALPM_LPM_IPT(u, lpm_cfg);
   4172 
   4173     if (lpm_cfg->l1_pvt_node != NULL && !ACB_HAS_TCAM(acb)) {
   4174         _alpm_bkt_info_t bkt_info;
   4175         _alpm_cb_t *top_cb = ACB_TOP(u);
   4176         _alpm_pvt_node_t *l1_pvt_node = lpm_cfg->l1_pvt_node;
   4177         rv = alpm_bkt_ent_get(u, vrf_id, top_cb, l1_pvt_node,
   4178                               l1_pvt_node->key_len, NULL, &fmt_update, 1);
   4179         /* return FULL when Expand exceeds bnk_threshold */
   4180         if (rv == BCM_E_RESOURCE) {
   4181             return BCM_E_FULL;
   4182         }
   4183 
   4184         if (rv == BCM_E_FULL) {
   4185             sal_memset(&bkt_info, 0, sizeof(_alpm_bkt_info_t));
   4186             rv = alpm_bkt_alloc(u, top_cb, vrf_id, ipt,
   4187                                 ACB_BNK_PER_BKT(top_cb, vrf_id),
   4188                                 &bkt_info, NULL);
   4189             ALPM_IER_PRT_EXCEPT(rv, BCM_E_FULL);
   4190             rv = alpm_cb_split(u, top_cb, lpm_cfg, &bkt_info, 0xffff);
   4191             if (rv == BCM_E_BUSY && ACB_HAS_RTE(acb, vrf_id) && lpm_cfg->spl_pn) {
   4192                 sal_memset(&bkt_info, 0, sizeof(_alpm_bkt_info_t));
   4193                 rv = alpm_bkt_alloc(u, acb, vrf_id, ipt,
   4194                                     ACB_BNK_PER_BKT(acb, vrf_id),
   4195                                     &bkt_info, NULL);
   4196                 ALPM_IER_PRT_EXCEPT(rv, BCM_E_FULL);
   4197                 /* Case 2.2.2, split given l3 pvt_node first */
   4198                 rv = alpm_cb_split(u, acb, lpm_cfg, &bkt_info, 0xffff);
   4199                 ALPM_IER_PRT_EXCEPT(rv, BCM_E_FULL);
   4200                 lpm_cfg->spl_pn = NULL;
   4201                 lpm_cfg->spl_key_len = 0;
   4202             } else if (BCM_FAILURE(rv)) {
   4203                 ALPM_IER_PRT_EXCEPT(rv, BCM_E_FULL);
   4204             } else {
   4205                 lpm_cfg->pvt_node = NULL;
   4206             }
   4207             lpm_cfg->l1_pvt_node = NULL;
   4208         } else {
   4209             int most_ref_len = 0;
   4210             uint32 pl_ref_cnt[128];
   4211             _bcm_defip_cfg_t l2_lpm_cfg;
   4212             _alpm_pvt_node_t *pvt_node;
   4213 
   4214             pvt_node = lpm_cfg->l1_pvt_node;
   4215             sal_memcpy(&l2_lpm_cfg, lpm_cfg, sizeof(l2_lpm_cfg));
   4216 
   4217             sal_memset(pl_ref_cnt, 0, sizeof(pl_ref_cnt));
   4218             rv = alpm_lib_trie_traverse(PVT_BKT_TRIE(pvt_node),
   4219                         alpm_trie_pfx_len_ref_cnt_cb, pl_ref_cnt,
   4220                         trieTraverseOrderIn);
   4221             if (BCM_SUCCESS(rv)) {
   4222                 most_ref_len = alpm_cb_pvt_most_ref_len_get(u, pl_ref_cnt,
   4223                                     l2_lpm_cfg.defip_sub_len);
   4224             }
   4225             if (most_ref_len == 0) {
   4226                 most_ref_len = alpm_cb_pvt_most_ref_len_get(u,
   4227                                     VRF_PVT_LEN_CNT_PTR(acb, vrf_id, ipt),
   4228                                     l2_lpm_cfg.defip_sub_len);
   4229             }
   4230 
   4231             if (pvt_node->key_len < most_ref_len &&
   4232                 most_ref_len < l2_lpm_cfg.defip_sub_len) {
   4233                 l2_lpm_cfg.defip_sub_len = most_ref_len;
   4234             } else {
   4235                 l2_lpm_cfg.defip_sub_len = pvt_node->key_len;
   4236             }
   4237             l2_lpm_cfg.bkt_kshift = l2_lpm_cfg.defip_sub_len;
   4238             alpm_util_ipmask_apply(u, &l2_lpm_cfg);
   4239             alpm_trie_cfg_to_pfx(u, &l2_lpm_cfg, l2_lpm_cfg.user_data);
   4240             if (PVT_BKT_DEF(pvt_node)) {
   4241                 alpm_util_adata_trie_to_cfg(u, &PVT_BKT_DEF(pvt_node)->adata,
   4242                                             &l2_lpm_cfg);
   4243                 l2_lpm_cfg.default_miss = 0;
   4244             } else {
   4245                 alpm_util_adata_zero_cfg(u, &l2_lpm_cfg);
   4246                 l2_lpm_cfg.default_miss = 1;
   4247             }
   4248             rv = alpm_cb_pvt_add(u, acb, vrf_id, ipt, &l2_lpm_cfg);
   4249             if (BCM_FAILURE(rv)) {
   4250                 ALPM_IER_PRT_EXCEPT(rv, BCM_E_FULL);
   4251             } else {
   4252                 lpm_cfg->pvt_node = l2_lpm_cfg.pvt_node;
   4253             }
   4254             lpm_cfg->l1_pvt_node = NULL;
   4255         }
   4256     }
   4257 
   4258     return rv;
   4259 }
   4260 
   4261 int
   4262 alpm_cb_insert(int u, _alpm_cb_t *acb, _bcm_defip_cfg_t *lpm_cfg)
   4263 {
   4264     int                 rv = BCM_E_NONE;
   4265     int                 vrf_id = ALPM_LPM_VRF_ID(u, lpm_cfg);
   4266     int                 ipt = ALPM_LPM_IPT(u, lpm_cfg);
   4267     uint32              *prefix, length;
   4268     uint32              ent_idx;
   4269     int                 retry_count = 0, retry_max = 3;
   4270     int                 bkt_trie_added = 0;
   4271 
   4272     alpm_lib_trie_t              *bkt_trie = NULL;
   4273     alpm_lib_trie_node_t         *tmp_node = NULL;
   4274 
   4275     _alpm_ppg_data_t    ppg_data;
   4276     _alpm_bkt_node_t    *bkt_node = NULL;
   4277     _alpm_pvt_node_t    *pvt_node, *upr_pvt_node;
   4278     _alpm_tcam_write_t  tcam_write;
   4279 
   4280     /* Init ALPM structure for first insert or was DR partially inited (MC first) */
   4281     if (!ACB_VRF_INITED(u, acb, vrf_id, ipt) || ACB_DR_INITED(u, acb, vrf_id, ipt)) {
   4282         uint8 db_type = alpm_util_route_type_get(u, lpm_cfg);
   4283         ALPM_IEG(alpm_vrf_init(u, acb, vrf_id, ipt, db_type));
   4284     }
   4285 
   4286     if (ACB_BKT_FIXED_FMT(acb, vrf_id)) {
   4287         retry_max = 1;
   4288     }
   4289 
   4290     pvt_node = ACB_HAS_TCAM(acb) ? lpm_cfg->l1_pvt_node : lpm_cfg->pvt_node;
   4291 
   4292 retry:
   4293     if (pvt_node == NULL) {
   4294         ALPM_IEG(alpm_pvt_find(u, acb, lpm_cfg, &pvt_node));
   4295         if (ACB_HAS_TCAM(acb)) {
   4296             lpm_cfg->l1_pvt_node = pvt_node;
   4297         } else {
   4298             rv = alpm_pvt_find(u, ACB_UPR(u, acb), lpm_cfg, &upr_pvt_node);
   4299             ALPM_IEG(rv);
   4300             if (pvt_node && upr_pvt_node) {
   4301                 if (upr_pvt_node->key_len <= pvt_node->key_len) {
   4302                     lpm_cfg->pvt_node = pvt_node;
   4303                 } else {
   4304                     lpm_cfg->l1_pvt_node = upr_pvt_node;
   4305                     ALPM_IEG_PRT_EXCEPT(alpm_cb_path_construct(u, acb, lpm_cfg), BCM_E_FULL);
   4306                     pvt_node = lpm_cfg->pvt_node;
   4307                     if (pvt_node == NULL) {
   4308                         goto retry;
   4309                     }
   4310                 }
   4311             }
   4312         }
   4313     }
   4314 
   4315     /* entry shouldn't exist, insert the entry into the RAM */
   4316     rv = alpm_bkt_insert(u, acb, lpm_cfg, pvt_node, &ent_idx);
   4317 
   4318     /* return FULL when Expand exceeds bnk_threshold */
   4319     if (rv == BCM_E_RESOURCE) {
   4320         rv = BCM_E_FULL;
   4321         ALPM_IEG_PRT_EXCEPT(rv, BCM_E_FULL);
   4322     }
   4323 
   4324 retry_spl:
   4325     if (rv == BCM_E_FULL && retry_count < retry_max) {
   4326         int     avl_bnk_cnt = 0;
   4327         int     max_spl_cnt = 0xffff;
   4328         _alpm_bkt_info_t bkt_info;
   4329         _alpm_tcam_write_t *ptcam_write;
   4330 
   4331         /* Case of add new L1 pvt from L2 bkt split:
   4332            This is only for 3-lvl ALPM (TH3).
   4333            TCAM entry pending to write to HW until add new L2 bkt if it
   4334            belongs to new L1 pvt (otherwise mis-forwarding may happen) */
   4335         if (ACB_IDX(acb) != ACB_VRF_BTM_IDX(u, vrf_id)) {
   4336             tcam_write.hw_idx = -1; /* initialized as invalid */
   4337             tcam_write.rv = 0xffff; /* init tcam_write.rv with 0xffff, will be changed
   4338                                        to BCM_E_XXX in L2 bkt insert within L2 bkt split */
   4339             lpm_cfg->tcam_write = &tcam_write;
   4340         } else {
   4341             lpm_cfg->tcam_write = NULL;
   4342         }
   4343 
   4344         /* Perform bucket merge before allocation only for fixed fmt */
   4345         if (ACB_BKT_FIXED_FMT(acb, vrf_id)) {
   4346             uint8 def_fmt;
   4347             if (!bcm_esw_alpm_tcam_avail(u, vrf_id, ipt, lpm_cfg->defip_sub_len, 0) &&
   4348                 ACB_HAS_TCAM(acb)) {
   4349                 rv = alpm_cb_merge(u, acb, vrf_id, ipt);
   4350                 ALPM_IEG(rv);
   4351                 /* pvt node could be merged and freed,
   4352                  * Need a faster version ALPMTBD */
   4353                 pvt_node = NULL;
   4354                 goto retry;
   4355             }
   4356             sal_memset(&bkt_info, 0, sizeof(_alpm_bkt_info_t));
   4357             rv = alpm_bkt_alloc(u, acb, vrf_id, ipt,
   4358                                 ACB_BNK_PER_BKT(acb, vrf_id),
   4359                                 &bkt_info, &avl_bnk_cnt);
   4360             if (rv == BCM_E_BUSY) {
   4361                 /* pvt node could be merged and freed,
   4362                  * Need a faster version ALPMTBD */
   4363                 pvt_node = NULL;
   4364                 goto retry;
   4365             } else if (rv == BCM_E_FULL) {
   4366                 if (avl_bnk_cnt > 0) {
   4367                     sal_memset(&bkt_info, 0, sizeof(_alpm_bkt_info_t));
   4368                     rv = alpm_bkt_alloc(u, acb, vrf_id, ipt,
   4369                                         avl_bnk_cnt, &bkt_info, NULL);
   4370                     if (rv == BCM_E_BUSY) {
   4371                         /* pvt node could be merged and freed,
   4372                          * Need a faster version ALPMTBD */
   4373                         pvt_node = NULL;
   4374                         goto retry;
   4375                     }
   4376                 }
   4377                 ALPM_IEG_PRT_EXCEPT(rv, BCM_E_FULL);
   4378             } else {
   4379                 avl_bnk_cnt = ACB_BNK_PER_BKT(acb, vrf_id);
   4380             }
   4381 
   4382             def_fmt = alpm_util_bkt_def_fmt_get(u, acb, vrf_id, ipt);
   4383             max_spl_cnt = avl_bnk_cnt * ACB_FMT_ENT_MAX(acb, vrf_id, def_fmt) - 1;
   4384         } else {
   4385             sal_memset(&bkt_info, 0, sizeof(_alpm_bkt_info_t));
   4386             rv = alpm_bkt_alloc(u, acb, vrf_id, ipt,
   4387                                 ACB_BNK_PER_BKT(acb, vrf_id),
   4388                                 &bkt_info, &avl_bnk_cnt);
   4389             ALPM_IEG_PRT_EXCEPT(rv, BCM_E_FULL);
   4390         }
   4391 
   4392         rv = alpm_cb_split(u, acb, lpm_cfg, &bkt_info, max_spl_cnt);
   4393         /* Upper level of BCM_E_BUSY point,
   4394          * ACB_HAS_RTE may not be a good condition, but considering
   4395          * it's only 3 levels so it also works.
   4396          */
   4397         if (rv == BCM_E_BUSY && ACB_HAS_RTE(acb, vrf_id) && lpm_cfg->spl_pn) {
   4398             sal_memset(&bkt_info, 0, sizeof(_alpm_bkt_info_t));
   4399             rv = alpm_bkt_alloc(u, acb, vrf_id, ipt,
   4400                                 ACB_BNK_PER_BKT(acb, vrf_id),
   4401                                 &bkt_info, &avl_bnk_cnt);
   4402             ALPM_IEG_PRT_EXCEPT(rv, BCM_E_FULL);
   4403 
   4404             /* Case 2.2.2, split given l3 pvt_node first */
   4405             rv = alpm_cb_split(u, acb, lpm_cfg, &bkt_info, max_spl_cnt);
   4406             if (BCM_SUCCESS(rv)) {
   4407                 lpm_cfg->spl_pn = NULL;
   4408                 lpm_cfg->spl_key_len = 0;
   4409                 /* PERF OPT point */
   4410                 pvt_node = NULL;
   4411                 goto retry;
   4412             }
   4413         }
   4414 
   4415         ALPM_IEG_PRT_EXCEPT(rv, BCM_E_FULL);
   4416 
   4417         ptcam_write = lpm_cfg->tcam_write;
   4418         if (ptcam_write != NULL) {
   4419             if (ptcam_write->rv == BCM_E_NONE) {
   4420                 goto _exit; /* already done in alpm_bkt_add_to_npvt */
   4421             } else if (ptcam_write->rv == BCM_E_FULL) {
   4422                 rv = BCM_E_FULL;
   4423                 retry_count ++;
   4424                 goto retry_spl; /* skip alpm_bkt_insert */
   4425             }
   4426         }
   4427 
   4428         /* Need a faster version ALPMTBD */
   4429         pvt_node = NULL;
   4430         retry_count ++;
   4431         goto retry;
   4432     }
   4433 
   4434     ALPM_IEG_PRT_EXCEPT(rv, BCM_E_FULL);
   4435 
   4436     lpm_cfg->defip_index = ent_idx;
   4437 
   4438     /* Allocate Payload */
   4439     ALPM_ALLOC_EG(bkt_node, sizeof(_alpm_bkt_node_t), "bkt_node");
   4440     prefix = lpm_cfg->user_data;
   4441     length = lpm_cfg->defip_sub_len;
   4442     sal_memcpy(bkt_node->key, prefix, sizeof(bkt_node->key));
   4443     bkt_node->key_len   = length;
   4444     bkt_node->ent_idx   = ent_idx;
   4445     alpm_util_adata_cfg_to_trie(u, lpm_cfg, &bkt_node->adata);
   4446     /* Insert the prefix */
   4447     /* bucket trie insert */
   4448     bkt_trie = PVT_BKT_TRIE(pvt_node);
   4449     rv = alpm_lib_trie_insert(bkt_trie, prefix, length, (alpm_lib_trie_node_t *)bkt_node);
   4450     ALPM_IEG(rv);
   4451     bkt_trie_added = 1;
   4452 
   4453     rv = alpm_vrf_pfx_trie_add(u, acb, lpm_cfg, bkt_node);
   4454     ALPM_IEG(rv);
   4455 
   4456     /* do insert propagation to update existing default datas */
   4457     if (ACB_HAS_RTE(acb, vrf_id)) {
   4458         /* Fill in AUX Scratch and perform PREFIX Operation */
   4459         alpm_ppg_prepare(u, lpm_cfg, 0, bkt_node, &ppg_data);
   4460         rv = alpm_ppg_assoc_data(u, ALPM_PPG_INSERT, &ppg_data);
   4461     }
   4462     if (BCM_SUCCESS(rv) &&
   4463         ALPMC(u)->_alpm_dbg_bmp & _ALPM_DBG_PVT_SANITY_NODE) {
   4464         rv = alpm_cb_pvt_sanity_cb(u, acb, pvt_node, "CBInsert");
   4465     }
   4466 
   4467     VRF_ROUTE_ADD(acb, vrf_id, ipt);
   4468 _exit:
   4469     lpm_cfg->tcam_write = NULL;
   4470     if (rv == BCM_E_FULL) {
   4471         acb->acb_cnt.c_full++;
   4472     }
   4473     return rv;
   4474 
   4475 bad:
   4476     if (bkt_trie_added) {
   4477         (void)alpm_lib_trie_delete(bkt_trie, prefix, length, &tmp_node);
   4478     }
   4479     if (bkt_node != NULL) {
   4480         alpm_util_free(bkt_node);
   4481     }
   4482     lpm_cfg->tcam_write = NULL;
   4483     if (rv == BCM_E_FULL) {
   4484         acb->acb_cnt.c_full++;
   4485     }
   4486     return rv;
   4487 }
   4488 
   4489 static int
   4490 bcm_esw_alpm_ctrl_deinit(int u)
   4491 {
   4492     int rv = BCM_E_NONE;
   4493 
   4494     if (ALPM_DRV(u)) {
   4495         ALPM_DRV(u)->alpm_ctrl_deinit(u);
   4496     }
   4497 
   4498     if (ALPMC(u)->_vrf_pfx_hdl != NULL) {
   4499         alpm_util_free(ALPMC(u)->_vrf_pfx_hdl);
   4500     }
   4501 
   4502     if (ALPMC(u)->_alpm_merge_state != NULL) {
   4503         alpm_util_free(ALPMC(u)->_alpm_merge_state);
   4504     }
   4505 
   4506     if (ALPMC(u)->_alpm_err_msg_buf != NULL) {
   4507         alpm_util_free(ALPMC(u)->_alpm_err_msg_buf);
   4508     }
   4509 
   4510     if (ALPMC(u) != NULL) {
   4511         alpm_util_free(ALPMC(u));
   4512         ALPMC(u) = NULL;
   4513     }
   4514 
   4515     return rv;
   4516 }
   4517 
   4518 int
   4519 bcm_esw_alpm_ctrl_init(int u)
   4520 {
   4521     int rv = BCM_E_NONE;
   4522     int vrf_id_cnt;
   4523     int alloc_sz;
   4524     int pair_ent_cnt = 0;
   4525     int bnk_thres;
   4526     int max_tcams = SOC_L3_DEFIP_MAX_TCAMS_GET(u);
   4527     int tcam_depth = SOC_L3_DEFIP_TCAM_DEPTH_GET(u);
   4528     int def_ipv6_128b_entries = tcam_depth * max_tcams / 4;
   4529 
   4530     alloc_sz = sizeof(_alpm_ctrl_t);
   4531     ALPM_ALLOC_EG(ALPMC(u), alloc_sz, "ALPMC");
   4532 
   4533     ALPMC(u)->_alpm_max_vrf_id = SOC_VRF_MAX(u);
   4534 
   4535     /* Init ALPMC variables */
   4536     if (SAL_BOOT_SIMULATION && SOC_IS_TOMAHAWK3(u)) {
   4537         ALPM_HIT_SKIP(u) = soc_property_get(u, spn_L3_ALPM_HIT_SKIP, 1);
   4538     } else {
   4539         ALPM_HIT_SKIP(u) = soc_property_get(u, spn_L3_ALPM_HIT_SKIP, 0);
   4540     }
   4541     ALPM_MODE(u) = soc_alpm_cmn_mode_get(u);
   4542     if (ALPM_MODE_CHK(u, BCM_ALPM_MODE_PARALLEL) ||
   4543         ALPM_MODE_CHK(u, BCM_ALPM_MODE_TCAM_ALPM)) {
   4544         ALPM_TCAM_ZONED(u) = TRUE;
   4545     }
   4546 
   4547     /* Due to swith control L3Max128BV6Entries, pair_ent_cnt
   4548        shouldn't come directly from spn_NUM_IPV6_LPM_128B_ENTRIES */
   4549     ALPM_128B(u) = SOC_ALPM_128B_ENABLE(u);
   4550     pair_ent_cnt = SOC_L3_DEFIP_MAX_128B_ENTRIES(u);
   4551     if (pair_ent_cnt > (def_ipv6_128b_entries * 2)) {
   4552         pair_ent_cnt = def_ipv6_128b_entries * 2;
   4553     }
   4554 
   4555     ALPM_TCAM_PAIR_BLK_CNT(u) = (pair_ent_cnt + (tcam_depth - 1)) / tcam_depth;
   4556 
   4557     /* these two thresholds are applicable only for TH3 */
   4558     ALPMC(u)->_alpm_bulk_wr_threshold =
   4559         soc_property_get(u, "l3_alpm2_bulk_wr_threshold", 16);
   4560     bnk_thres = soc_property_get(u, spn_L3_ALPM2_BNK_THRESHOLD, 95);
   4561     if (bnk_thres <= 0 || bnk_thres > 100) {
   4562         bnk_thres = 95;
   4563     }
   4564     ALPMC(u)->_alpm_bnk_threshold = bnk_thres;
   4565 
   4566     ALPMC(u)->_alpm_spl[ALPM_PKM_32B] =
   4567         soc_property_get(u, "l3_alpm2_spl_hw", 24);
   4568     ALPMC(u)->_alpm_spl[ALPM_PKM_64B] =
   4569         soc_property_get(u, "l3_alpm2_spl_sw", 56);
   4570     ALPMC(u)->_alpm_spl[ALPM_PKM_128] =
   4571         soc_property_get(u, "l3_alpm2_spl_dw", 120);
   4572 
   4573     ALPMC(u)->_alpm_dbg_bmp = soc_property_get(u, "l3_alpm2_dbg_bmp", 0x0);
   4574     if (ALPMC(u)->_alpm_dbg_bmp != 0) {
   4575         int i;
   4576         ALPM_INFO(("[ALPM-INIT] _alpm_dbg_bmp enabled bit(s) ["));
   4577         for (i = 0; i < 32; i++) {
   4578             if (ALPMC(u)->_alpm_dbg_bmp & (1 << i)) {
   4579                 ALPM_INFO(("%d ", i));
   4580             }
   4581         }
   4582         ALPM_INFO(("]\n"));
   4583     }
   4584 
   4585     ALPMC(u)->_alpm_dbg_info_bmp = soc_property_get(u, "l3_alpm2_dbg_info_bmp", 0x07);
   4586 
   4587     /* Private VRFs + 2 Global VRFs */
   4588     vrf_id_cnt = ALPM_VRF_ID_CNT(u);
   4589     alloc_sz = sizeof(_alpm_pfx_ctrl_t) * vrf_id_cnt;
   4590     ALPM_ALLOC_EG(ALPMC(u)->_vrf_pfx_hdl, alloc_sz, "_vrf_pfx_hdl");
   4591 
   4592     alloc_sz = sizeof(int) * vrf_id_cnt;
   4593     ALPM_ALLOC_EG(ALPMC(u)->_alpm_merge_state, alloc_sz, "_alpm_merge_state");
   4594 
   4595     alloc_sz = _ALPM_ERR_MSG_BUF_CNT * _ALPM_ERR_MSG_BUF_ENT_SZ;
   4596     ALPM_ALLOC_EG(ALPMC(u)->_alpm_err_msg_buf, alloc_sz, "_alpm_err_msg_buf");
   4597 
   4598     if (soc_feature(u, soc_feature_alpm2)) {
   4599         if (SOC_IS_TOMAHAWK3(u)) {
   4600             ALPMC(u)->alpm_driver = &th3_alpm_driver;
   4601         } else
   4602         {
   4603             ALPMC(u)->alpm_driver = &th_alpm_driver;
   4604         }
   4605     }
   4606 
   4607     if (ALPM_128B(u)) {
   4608         ALPM_BKT_RSVD(u) = soc_property_get(u, spn_L3_ALPM_IPV6_128B_BKT_RSVD, 0);
   4609         if (ALPM_BKT_RSVD(u)) {
   4610             /* Based on 8K Buckets */
   4611             ALPM_BKT_RSVD_CNT(u) =
   4612                 pair_ent_cnt * 2 * 8192 / (tcam_depth * max_tcams);
   4613         }
   4614     }
   4615 
   4616     rv = ALPM_DRV(u)->alpm_ctrl_init(u);
   4617     if (BCM_FAILURE(rv)) {
   4618         goto bad;
   4619     }
   4620 
   4621     return rv;
   4622 
   4623 bad:
   4624     bcm_esw_alpm_ctrl_deinit(u);
   4625     return rv;
   4626 }
   4627 
   4628 /* ALPM ctrl cleanup for faster delete_all */
   4629 int
   4630 bcm_esw_alpm_ctrl_cleanup(int u)
   4631 {
   4632     int rv = BCM_E_NONE;
   4633     int vrf_id_cnt;
   4634     int alloc_sz;
   4635 
   4636     rv = alpm_trie_clear_all(u);
   4637 
   4638     vrf_id_cnt = ALPM_VRF_ID_CNT(u);
   4639     alloc_sz = sizeof(int) * vrf_id_cnt;
   4640     sal_memset(ALPMC(u)->_alpm_merge_state, 0, alloc_sz);
   4641 
   4642     alloc_sz = _ALPM_ERR_MSG_BUF_CNT * _ALPM_ERR_MSG_BUF_ENT_SZ;
   4643     sal_memset(ALPMC(u)->_alpm_err_msg_buf, 0, alloc_sz);
   4644 
   4645     rv = ALPM_DRV(u)->alpm_ctrl_cleanup(u);
   4646     return rv;
   4647 }
   4648 
   4649 /* Initialize ALPM Subsytem */
   4650 
   4651 int
   4652 bcm_esw_alpm_deinit(int u)
   4653 {
   4654     int rv = BCM_E_NONE;
   4655 
   4656     BCM_IF_ERROR_RETURN(alpm_trie_clear_all(u));
   4657     BCM_IF_ERROR_RETURN(bcm_esw_alpm_trace_deinit(u));
   4658     BCM_IF_ERROR_RETURN(bcm_esw_alpm_hit_deinit(u));
   4659     BCM_IF_ERROR_RETURN(bcm_esw_alpm_ctrl_deinit(u));
   4660     BCM_IF_ERROR_RETURN(bcm_esw_alpm_tcam_deinit(u));
   4661     alpm_util_mem_stat_clear();
   4662 
   4663     return rv;
   4664 }
   4665 
   4666 static void
   4667 bcm_esw_alpm_init_done(int u, int rv)
   4668 {
   4669     int i;
   4670     int banks, mode, urpf;
   4671     char *mode_str[] = {
   4672         "invalid",
   4673         "combined",
   4674         "parallel",
   4675         "mixed"
   4676     };
   4677 
   4678     if (BCM_FAILURE(rv)) {
   4679         LOG_CLI(("*** unit %d: alpm init failed\n", u));
   4680         return;
   4681     }
   4682 
   4683     /* pass */
   4684     /* *** unit 0: alpm level 2 loaded: 4 banks in combined-128 (urpf) */
   4685     urpf = SOC_URPF_STATUS_GET(u);
   4686     mode = ALPM_MODE(u);
   4687 
   4688     for (i = 0; i < ACB_CNT(u); i++) {
   4689         banks = ACB_PHY_BNK_PER_BKT(ACB(u, i));
   4690         LOG_CLI(("*** unit %d: alpm level %d loaded: %d banks in %s-%s %s\n",
   4691                  u, i+2, banks, mode_str[mode+1], ALPM_128B(u) ? "128" : "64",
   4692                  urpf ? "(urpf)" : ""));
   4693 
   4694     }
   4695 }
   4696 
   4697 int
   4698 bcm_esw_alpm_init(int u)
   4699 {
   4700     int rv = BCM_E_NONE;
   4701 
   4702     if (ALPMC(u) && ALPMC(u)->_alpm_inited) {
   4703         ALPM_IEG(bcm_esw_alpm_deinit(u));
   4704     }
   4705 
   4706     ALPM_IEG(bcm_esw_alpm_ctrl_init(u));
   4707     ALPM_IEG(bcm_esw_alpm_tcam_init(u));
   4708     ALPM_IEG(bcm_esw_alpm_hit_init(u));
   4709     ALPM_IEG(bcm_esw_alpm_trace_init(u));
   4710 
   4711     ALPMC(u)->_alpm_inited = TRUE;
   4712 
   4713 bad:
   4714     bcm_esw_alpm_init_done(u, rv);
   4715     return rv;
   4716 }
   4717 
   4718 /*
   4719  * Function:
   4720  *      bcm_esw_alpm_cleanup
   4721  * Purpose:
   4722  *      Fast ALPM delete all
   4723  * Parameters:
   4724  *      u         - (IN)Device unit number.
   4725  *      trv_data  - (IN)Delete pattern + compare,act,notify routines for TCAM Direct routes.
   4726  *      trv_data1 - (IN)Delete pattern + compare,act,notify routines for ALPM routes.
   4727  * Returns:
   4728  *      BCM_E_XXX
   4729  */
   4730 int
   4731 bcm_esw_alpm_cleanup(int u, _bcm_l3_trvrs_data_t *trv_data,
   4732                      _bcm_l3_trvrs_data_t *trv_data1)
   4733 {
   4734     int rv = BCM_E_NONE;
   4735     int us = 0;
   4736 
   4737     if (ALPMC(u) && ALPMC(u)->_alpm_inited) {
   4738 
   4739         if (!ALPM_HIT_SKIP(u) && ALPMDH(u)) {
   4740             us = ALPMDH(u)->interval; /* save */
   4741             rv = alpm_dist_hitbit_enable_set(u, 0);
   4742         }
   4743 
   4744         /* Fast delete all by travel data in below order:
   4745            1) TCAM direct routes + ecmp_nh (trv_data)
   4746            2) TCAM Hw table
   4747            3) ALPM ecmp_nh (trv_data1) */
   4748         rv = bcm_esw_alpm_fast_delete_all(u, trv_data, trv_data1);
   4749         if (BCM_FAILURE(rv)) {
   4750             ALPM_ERR(("ALPM/TCAM fast_delete_all travel failed (%d)", rv));
   4751         }
   4752 
   4753         rv = bcm_esw_alpm_ctrl_cleanup(u);
   4754         if (BCM_FAILURE(rv)) {
   4755             ALPM_ERR(("ALPM ctrl cleanup failed (%d)", rv));
   4756         }
   4757 
   4758         rv = bcm_esw_alpm_tcam_cleanup(u);
   4759         if (BCM_FAILURE(rv)) {
   4760             ALPM_ERR(("ALPM tcam cleanup failed (%d)", rv));
   4761         }
   4762 
   4763         if (!ALPM_HIT_SKIP(u) && ALPMDH(u)) {
   4764             rv = ALPM_DRV(u)->alpm_hit_cleanup(u);
   4765             if (BCM_FAILURE(rv)) {
   4766                 ALPM_ERR(("ALPM hitbit cleanup failed (%d)", rv));
   4767             }
   4768             rv = alpm_dist_hitbit_enable_set(u, us);
   4769         }
   4770 
   4771         alpm_trace_log(u, ALPM_TRACE_OP_DELETE_ALL, NULL, 0, rv);
   4772     }
   4773 
   4774     return rv;
   4775 }
   4776 
   4777 /*
   4778  * bcm_esw_alpm_insert
   4779  * For IPV4 assume only both IP_ADDR0 is valid
   4780  * Moving multiple entries around in h/w vs  doing a linear search in s/w
   4781  */
   4782 int
   4783 bcm_esw_alpm_insert(int u, _bcm_defip_cfg_t *lpm_cfg)
   4784 {
   4785     int                 rv = BCM_E_NONE, rv2;
   4786     int                 vrf_id = ALPM_LPM_VRF_ID(u, lpm_cfg);
   4787     int                 ipt = ALPM_LPM_IPT(u, lpm_cfg);
   4788     int                 pvt_info = lpm_cfg->defip_alpm_cookie;
   4789     _alpm_cb_t          *acb = NULL;
   4790 
   4791     alpm_util_ipmask_apply(u, lpm_cfg);
   4792     alpm_trie_cfg_to_pfx(u, lpm_cfg, lpm_cfg->user_data);
   4793 
   4794     /* Routes reside in TCAM only in below cases:
   4795      *   Global High routes
   4796      *   Global low routes in Mixed mode
   4797      */
   4798     if (ALPM_LPM_DIRECT_RTE(u, lpm_cfg)) {
   4799         /* Init pvt_trie for direct routes */
   4800         acb = ACB_TOP(u);
   4801         if (!ACB_VRF_INITED(u, acb, vrf_id, ipt)) {
   4802             ALPM_IER(alpm_pvt_trie_init(u, vrf_id, ipt));
   4803         }
   4804 
   4805         /* Insert into TCAM directly and return */
   4806         rv = bcm_esw_alpm_tcam_insert(u, lpm_cfg, ALPM_PVT_UPDATE_ALL);
   4807         if (BCM_SUCCESS(rv)) {
   4808             if (!(pvt_info & BCM_ALPM_LPM_LOOKUP_HIT)) {
   4809                 VRF_ROUTE_ADD(acb, vrf_id, ipt);
   4810             }
   4811             /* Insert only Direct route pvt trie */
   4812             rv = alpm_pvt_trie_insert(u, lpm_cfg);
   4813             if (rv == BCM_E_EXISTS &&
   4814                 (lpm_cfg->defip_flags & BCM_L3_REPLACE)) {
   4815                 rv = BCM_E_NONE;
   4816             }
   4817         }
   4818         if (rv == BCM_E_FULL) {
   4819             acb->acb_cnt.c_full++;
   4820         }
   4821         return(rv);
   4822     }
   4823 
   4824     /* Route mode and default route validation */
   4825     ALPM_IER(alpm_util_route_type_check(u, lpm_cfg));
   4826     ALPM_IER(alpm_util_def_check(u, lpm_cfg, TRUE));
   4827     acb = ACB_VRF_BTM(u, vrf_id);
   4828 
   4829     /* Find and update the entry */
   4830     if (pvt_info & BCM_ALPM_LOOKUP_HIT) {
   4831         rv = alpm_cb_update(u, acb, lpm_cfg);
   4832         return rv;
   4833     }
   4834 
   4835     /* entry is not found in database */
   4836     /* Insert the entry into the database, if FULL, split the bucket */
   4837     /* Insert prefix into trie */
   4838     /* Split trie : Insertion into trie results into Split */
   4839     /* Allocate a TCAM entry for PIVOT and bucket and move entries */
   4840     rv = alpm_cb_path_construct(u, acb, lpm_cfg);
   4841     if (rv == BCM_E_FULL) {
   4842         acb->acb_cnt.c_full++;
   4843     }
   4844     ALPM_IER_PRT_EXCEPT(rv, BCM_E_FULL);
   4845 
   4846     rv = alpm_cb_insert(u, acb, lpm_cfg);
   4847     if (BCM_SUCCESS(rv)) {
   4848         lpm_cfg->defip_index =
   4849             alpm_util_ent_phy_idx_get(u, acb, vrf_id, lpm_cfg->defip_index);
   4850     } else if (rv != BCM_E_FULL) {
   4851         ALPM_ERR(("**ACB(%d).INSERT: Failed %d\n", ACB_IDX(acb), rv));
   4852     } else { /* FULL */
   4853         int rv3;
   4854         rv3 = alpm_pvt_delete_by_empty_bkt(u, acb, lpm_cfg);
   4855         if (BCM_FAILURE(rv3)) {
   4856             ALPM_ERR(("**ACB(%d).INSERT: Full. "
   4857                       "Pvt delete by empty bkt: Failed %d\n", ACB_IDX(acb), rv3));
   4858         }
   4859     }
   4860 
   4861     rv2 = alpm_cb_sanity(u, 0x3, vrf_id, ipt);
   4862     rv = (rv == BCM_E_NONE) ? rv2 : rv;
   4863 
   4864     return(rv);
   4865 }
   4866 
   4867 /*
   4868  * bcm_esw_alpm_lookup
   4869  * For IPV4 assume only both IP_ADDR0 is valid
   4870  * Moving multiple entries around in h/w vs  doing a linear search in s/w
   4871  */
   4872 int
   4873 bcm_esw_alpm_lookup(int u, _bcm_defip_cfg_t *lpm_cfg)
   4874 {
   4875     int                 rv = BCM_E_NONE;
   4876     _alpm_cb_t          *acb = NULL;
   4877     _alpm_pvt_node_t    *pvt_node = NULL, *upr_pvt_node = NULL;
   4878     _alpm_bkt_node_t    *bkt_node = NULL, *upr_bkt_node = NULL;
   4879     int                 ipt = ALPM_LPM_IPT(u, lpm_cfg);
   4880     int                 vrf_id = ALPM_LPM_VRF_ID(u, lpm_cfg);
   4881 
   4882     alpm_util_ipmask_apply(u, lpm_cfg);
   4883 
   4884     /* Prepare trie key format in lpm_cfg->user_data for further use */
   4885     alpm_trie_cfg_to_pfx(u, lpm_cfg, lpm_cfg->user_data);
   4886 
   4887     if (ALPM_LPM_DIRECT_RTE(u, lpm_cfg)) {
   4888         if (!ACB_VRF_INITED(u, ACB_TOP(u), vrf_id, ipt)) {
   4889             ALPM_VERB(("**LOOKUP:VRF %d is not initialized\n", vrf_id));
   4890             return BCM_E_NOT_FOUND;
   4891         }
   4892         rv = bcm_esw_alpm_tcam_match(u, lpm_cfg, &lpm_cfg->defip_index);
   4893         if (BCM_SUCCESS(rv)) {
   4894             lpm_cfg->defip_alpm_cookie = BCM_ALPM_LPM_LOOKUP_HIT;
   4895         }
   4896         return rv;
   4897     }
   4898 
   4899     acb = ACB_VRF_BTM(u, vrf_id);
   4900 
   4901     /* Check VRF/Key_mode based initialization */
   4902     if (!ACB_VRF_INITED(u, acb, vrf_id, ipt)) {
   4903         ALPM_VERB(("**LOOKUP:VRF %d is not initialized\n", vrf_id));
   4904         return BCM_E_NOT_FOUND;
   4905     }
   4906 
   4907     /* Find and update the entry */
   4908     rv = alpm_cb_find(u, acb, lpm_cfg, &pvt_node, &bkt_node);
   4909     if (!ACB_HAS_TCAM(acb)) {
   4910         (void)alpm_cb_find(u, ACB_UPR(u, acb), lpm_cfg,
   4911                            &upr_pvt_node, &upr_bkt_node);
   4912         if (pvt_node && upr_pvt_node) {
   4913             if (upr_pvt_node->key_len <= pvt_node->key_len) {
   4914                 lpm_cfg->pvt_node = (uint32 *)pvt_node;
   4915                 lpm_cfg->bkt_node = (uint32 *)bkt_node;
   4916                 lpm_cfg->l1_pvt_node = NULL;
   4917             } else {
   4918                 lpm_cfg->pvt_node = NULL;
   4919                 lpm_cfg->bkt_node = NULL;
   4920                 lpm_cfg->l1_pvt_node = (uint32 *)upr_pvt_node;
   4921                 rv = BCM_E_NOT_FOUND;
   4922             }
   4923         }
   4924     } else {
   4925         lpm_cfg->l1_pvt_node = (uint32 *)pvt_node;
   4926         lpm_cfg->pvt_node = (uint32 *)pvt_node;
   4927         lpm_cfg->bkt_node = (uint32 *)bkt_node;
   4928     }
   4929 
   4930     if (BCM_SUCCESS(rv)) {
   4931         /* Copy ALPM memory to LPM entry */
   4932         alpm_util_adata_trie_to_cfg(u, &bkt_node->adata, lpm_cfg);
   4933         lpm_cfg->defip_index =
   4934             alpm_util_ent_phy_idx_get(u, acb, vrf_id, bkt_node->ent_idx);
   4935         lpm_cfg->defip_alpm_cookie = BCM_ALPM_LOOKUP_HIT;
   4936         if (ACB_VRF_DB_TYPE(u, acb, vrf_id, ipt)) {
   4937             lpm_cfg->defip_alpm_cookie |= ALPM_ROUTE_FULL_MD;
   4938         }
   4939         /* Get HIT bit from matched entry */
   4940         if (!ALPM_HIT_SKIP(u)) {
   4941             int idx, ent;
   4942             int hit_val;
   4943             _alpm_tbl_t tbl;
   4944             ent = ALPM_IDX_TO_ENT(bkt_node->ent_idx);
   4945             idx = ALPM_TAB_IDX_GET(bkt_node->ent_idx);
   4946             tbl = BPC_BKT_TBL(ACB_BKT_VRF_POOL(acb, vrf_id));
   4947             ALPM_HIT_LOCK(u);
   4948             hit_val = alpm_rte_hit_get(u, vrf_id, tbl, idx, ent);
   4949             lpm_cfg->defip_flags |= (hit_val > 0 ? BCM_L3_HIT : 0);
   4950             ALPM_HIT_UNLOCK(u);
   4951         }
   4952     }
   4953 
   4954     return(rv);
   4955 }
   4956 
   4957 /*
   4958  * bcm_esw_alpm_delete
   4959  */
   4960 int
   4961 bcm_esw_alpm_delete(int u, _bcm_defip_cfg_t *lpm_cfg)
   4962 {
   4963     int     rv = BCM_E_NONE;
   4964     _alpm_cb_t *acb;
   4965     _alpm_pvt_node_t *pvt_node;
   4966     _alpm_bkt_node_t *bkt_node;
   4967 
   4968     uint32  ipt = ALPM_LPM_IPT(u, lpm_cfg);
   4969     uint32  vrf_id = ALPM_LPM_VRF_ID(u, lpm_cfg);
   4970 
   4971     alpm_util_ipmask_apply(u, lpm_cfg);
   4972     /* ALPM prefix */
   4973     alpm_trie_cfg_to_pfx(u, lpm_cfg, lpm_cfg->user_data);
   4974 
   4975     /* Prefix resides in TCAM directly */
   4976     if (ALPM_LPM_DIRECT_RTE(u, lpm_cfg)) {
   4977         acb = ACB_TOP(u);
   4978         rv = bcm_esw_alpm_tcam_delete(u, lpm_cfg);
   4979 
   4980         if (BCM_SUCCESS(rv)) {
   4981             /* Delete only pvt trie for direct routes */
   4982             rv = alpm_pvt_trie_delete(u, lpm_cfg);
   4983             VRF_ROUTE_DEC(acb, vrf_id, ipt);
   4984             if (VRF_ROUTE_CNT(acb, vrf_id, ipt) == 0) {
   4985                 (void)alpm_lib_trie_destroy(ACB_PVT_TRIE(acb, vrf_id, ipt));
   4986                 ACB_VRF_INIT_CLEAR(u, acb, vrf_id, ipt);
   4987                 ACB_DR_INIT_CLEAR(u, acb, vrf_id, ipt);
   4988                 ACB_PVT_TRIE(acb, vrf_id, ipt) = NULL;
   4989             }
   4990         }
   4991         return rv;
   4992     }
   4993 
   4994     ALPM_IER(alpm_util_def_check(u, lpm_cfg, FALSE));
   4995 
   4996     acb = ACB_VRF_BTM(u, vrf_id);
   4997 
   4998     if (!ACB_VRF_INITED(u, acb, vrf_id, ipt)) {
   4999         ALPM_ERR(("**ACB(%d).DELETE:VRF %d/%d is not initialized\n",
   5000                   ACB_IDX(acb), vrf_id, ipt));
   5001         return BCM_E_NONE;
   5002     }
   5003 
   5004     pvt_node = (_alpm_pvt_node_t *)lpm_cfg->pvt_node;
   5005     bkt_node = (_alpm_bkt_node_t *)lpm_cfg->bkt_node;
   5006 
   5007     if (bkt_node == NULL) {
   5008         _alpm_pvt_node_t *upr_pvt_node = NULL;
   5009         _alpm_bkt_node_t *upr_bkt_node = NULL;
   5010 
   5011         (void)alpm_cb_find(u, acb, lpm_cfg, &pvt_node, &bkt_node);
   5012         if (!ACB_HAS_TCAM(acb)) {
   5013             (void)alpm_cb_find(u, ACB_UPR(u, acb), lpm_cfg,
   5014                                &upr_pvt_node, &upr_bkt_node);
   5015             if (pvt_node && upr_pvt_node) {
   5016                 if (upr_pvt_node->key_len <= pvt_node->key_len) {
   5017                     lpm_cfg->pvt_node = (uint32 *)pvt_node;
   5018                     lpm_cfg->bkt_node = (uint32 *)bkt_node;
   5019                     lpm_cfg->l1_pvt_node = NULL;
   5020                 } else {
   5021                     lpm_cfg->pvt_node = NULL;
   5022                     lpm_cfg->bkt_node = NULL;
   5023                     lpm_cfg->l1_pvt_node = (uint32 *)upr_pvt_node;
   5024                     bkt_node = NULL;
   5025                 }
   5026             }
   5027         } else {
   5028             lpm_cfg->l1_pvt_node = (uint32 *)pvt_node;
   5029             lpm_cfg->pvt_node = (uint32 *)pvt_node;
   5030             lpm_cfg->bkt_node = (uint32 *)bkt_node;
   5031         }
   5032     }
   5033 
   5034     if (bkt_node == NULL) {
   5035         lpm_cfg->pvt_node = NULL;
   5036         return BCM_E_NOT_FOUND;
   5037     }
   5038 
   5039     rv = alpm_cb_delete(u, acb, lpm_cfg);
   5040 
   5041     if (BCM_SUCCESS(rv) && VRF_ROUTE_CNT(acb, vrf_id, ipt) == 0) {
   5042         rv = alpm_vrf_deinit(u, vrf_id, ipt);
   5043     }
   5044 
   5045     return(rv);
   5046 }
   5047 
   5048 /*
   5049  * bcm_esw_alpm_update
   5050  */
   5051 int
   5052 bcm_esw_alpm_update(int u, _bcm_defip_cfg_t *lpm_cfg)
   5053 {
   5054     int rv;
   5055 
   5056     rv = bcm_esw_alpm_lookup(u, lpm_cfg);
   5057     if (BCM_SUCCESS(rv)) {
   5058         rv = bcm_esw_alpm_insert(u, lpm_cfg);
   5059     }
   5060 
   5061     return rv;
   5062 }
   5063 
   5064 /* Get current ALPM route data mode in the VRF and IP type */
   5065 int
   5066 bcm_esw_alpm_vrf_data_mode_get(int u, bcm_vrf_t vrf, uint32 flags,
   5067                                bcm_l3_vrf_route_data_mode_t *mode)
   5068 {
   5069     int ipt, vrf_id;
   5070     _alpm_cb_t *acb;
   5071 
   5072     if (ALPMC(u) && ALPMC(u)->_alpm_inited) {
   5073         vrf_id = ALPM_VRF_TO_VRFID(u, vrf);
   5074         ipt = (flags & BCM_L3_IP6) ? ALPM_IPT_V6 : ALPM_IPT_V4;
   5075 
   5076         acb = ACB_VRF_BTM(u, vrf_id);
   5077         *mode = (bcm_l3_vrf_route_data_mode_t) ACB_VRF_DB_TYPE(u, acb, vrf_id, ipt);
   5078         ALPM_INFO(("bcm_esw_alpm_vrf_data_mode_get(VRF:%d) = %d\n", vrf_id, *mode));
   5079         return BCM_E_NONE;
   5080     } else {
   5081         return BCM_E_UNAVAIL;
   5082     }
   5083 }
   5084 
   5085 /* Set ALPM route data mode in the VRF and IP type */
   5086 int
   5087 bcm_esw_alpm_vrf_data_mode_set(int u, bcm_vrf_t vrf, uint32 flags,
   5088                                bcm_l3_vrf_route_data_mode_t mode)
   5089 {
   5090     int i, ipt, vrf_id;
   5091     _alpm_cb_t *acb;
   5092     bcm_l3_vrf_route_data_mode_t cur_mode;
   5093 
   5094     if (ALPMC(u) && ALPMC(u)->_alpm_inited) {
   5095         vrf_id = ALPM_VRF_TO_VRFID(u, vrf);
   5096         ipt = (flags & BCM_L3_IP6) ? ALPM_IPT_V6 : ALPM_IPT_V4;
   5097 
   5098         /* Direct routes is always Full mode */
   5099         if (!ALPM_VRF_ID_HAS_BKT(u, vrf_id)) {
   5100             if (mode == bcmL3VrfRouteDataModeFull) {
   5101                 ALPM_INFO(("Direct route is always Full mode (VRF:%d)\n", vrf_id));
   5102                 return BCM_E_NONE;
   5103             } else {
   5104                 ALPM_ERR(("Direct route should be always Full mode (VRF:%d)\n", vrf_id));
   5105                 return BCM_E_FAIL;
   5106             }
   5107         }
   5108 
   5109         for (i = 0; i < ACB_CNT(u); i++) {
   5110             acb = ACB(u, i);
   5111             cur_mode = (bcm_l3_vrf_route_data_mode_t)
   5112                             ACB_VRF_DB_TYPE(u, acb, vrf_id, ipt);
   5113             if (mode == cur_mode) {
   5114                 return BCM_E_NONE; /* no change */
   5115             }
   5116 
   5117             /* ALPMTBD: initial implementation -
   5118                not allow to change once VRF initialized */
   5119             if (ACB_VRF_INITED(u, acb, vrf_id, ipt)) {
   5120                 ALPM_ERR(("VRF:%d IPT:%d ALPM route data mode unable to change once"
   5121                           " VRF initialized\n", vrf_id, ipt));
   5122                 return BCM_E_FAIL;
   5123             }
   5124 
   5125             ACB_VRF_DB_TYPE_SET(u, acb, vrf_id, ipt, (uint8) mode);
   5126             alpm_vrf_spl_len_calc(u, acb, vrf_id, (uint8) mode,
   5127                       &ACB_VRF_SPLEN_DIFF1(u, acb, vrf_id, ipt),
   5128                       &ACB_VRF_SPLEN_DIFF2(u, acb, vrf_id, ipt));
   5129 
   5130         }
   5131 
   5132         ALPM_INFO(("bcm_esw_alpm_vrf_data_mode_set(VRF:%d) = %d\n", vrf_id, mode));
   5133         return BCM_E_NONE;
   5134     } else {
   5135         return BCM_E_UNAVAIL;
   5136     }
   5137 }
   5138 
   5139 static int
   5140 bcm_esw_alpm_pvt_trav_int_cb(alpm_lib_trie_node_t *trie, void *datum)
   5141 {
   5142     int rv = BCM_E_NONE;
   5143     _alpm_pvt_trav_t    *trav_st;
   5144     _alpm_pvt_node_t    *pvt_node;
   5145 
   5146     trav_st = (_alpm_pvt_trav_t *)datum;
   5147     if (trie->type == trieNodeTypePayload) {
   5148         pvt_node = (_alpm_pvt_node_t *)trie;
   5149         rv = trav_st->user_cb(trav_st->acb->unit, trav_st->acb,
   5150                               pvt_node, trav_st->user_data);
   5151     }
   5152 
   5153     return rv;
   5154 }
   5155 
   5156 /* Traverse a given pivot trie-tree
   5157  */
   5158 int
   5159 bcm_esw_alpm_pvt_traverse(int u, int acb_idx, int vrf_id, int ipt,
   5160                           bcm_esw_alpm_pvt_trav_cb trav_fn, void *user_data)
   5161 {
   5162     int rv = BCM_E_NONE;
   5163     _alpm_cb_t        *acb;
   5164     _alpm_pvt_trav_t  trav_st;
   5165 
   5166     if (!trav_fn) {
   5167         return (BCM_E_PARAM);
   5168     }
   5169 
   5170     acb = ACB(u, acb_idx);
   5171 
   5172     sal_memset(&trav_st, 0, sizeof(trav_st));
   5173 
   5174     trav_st.acb       = acb;
   5175     trav_st.user_cb   = trav_fn;
   5176     trav_st.user_data = user_data;
   5177 
   5178     rv = alpm_lib_trie_traverse(ACB_PVT_TRIE(acb, vrf_id, ipt), bcm_esw_alpm_pvt_trav_int_cb,
   5179                        (void *)&trav_st, trieTraverseOrderIn);
   5180     return rv;
   5181 }
   5182 
   5183 STATIC int
   5184 bcm_esw_alpm_pfx_trav_int_cb(alpm_lib_trie_node_t *ptrie, alpm_lib_trie_node_t *trie,
   5185                              alpm_lib_trie_traverse_state_t *state, void *info)
   5186 {
   5187     int rv = BCM_E_NONE;
   5188     _alpm_pfx_trav_t    *trav_st;
   5189     _alpm_pfx_node_t    *pfx_node;
   5190 
   5191     /* Reset state everytime */
   5192     *state = trieTraverseStateNone;
   5193 
   5194     trav_st = (_alpm_pfx_trav_t *)info;
   5195     if (trie->type == trieNodeTypePayload) {
   5196         pfx_node = (_alpm_pfx_node_t *)trie;
   5197         rv = trav_st->user_cb(pfx_node, trav_st->user_data);
   5198     }
   5199 
   5200     return rv;
   5201 }
   5202 
   5203 /* Traverse a given prefix trie-tree
   5204  */
   5205 int
   5206 bcm_esw_alpm_pfx_traverse(int u, int vrf_id, int ipt,
   5207                           bcm_esw_alpm_pfx_trav_cb trav_fn, void *user_data)
   5208 {
   5209     _alpm_pfx_trav_t        trav_st;
   5210 
   5211     if (!trav_fn) {
   5212         return (BCM_E_PARAM);
   5213     }
   5214 
   5215     sal_memset(&trav_st, 0, sizeof(trav_st));
   5216 
   5217     trav_st.user_cb = trav_fn;
   5218     trav_st.user_data = user_data;
   5219 
   5220     /* Use delete safe _trie_postorder_traverse2() for update_match */
   5221     alpm_lib_trie_traverse2(ALPM_VRF_TRIE(u, vrf_id, ipt), bcm_esw_alpm_pfx_trav_int_cb,
   5222                   (void *)&trav_st, trieTraverseOrderPost);
   5223 
   5224     return BCM_E_NONE;
   5225 }
   5226 
   5227 STATIC int
   5228 bcm_esw_alpm_bkt_trav_int_cb(alpm_lib_trie_node_t *trie, void *datum)
   5229 {
   5230     int rv = BCM_E_NONE;
   5231     _alpm_bkt_trav_t    *trav_st;
   5232     _alpm_bkt_node_t    *bkt_node;
   5233 
   5234     trav_st = (_alpm_bkt_trav_t *)datum;
   5235     if (trie->type == trieNodeTypePayload) {
   5236         bkt_node = (_alpm_bkt_node_t *)trie;
   5237         rv = trav_st->user_cb(bkt_node, trav_st->user_data);
   5238     }
   5239 
   5240     return rv;
   5241 }
   5242 
   5243 /* Traverse a given bkt trie-tree
   5244  */
   5245 int
   5246 bcm_esw_alpm_bkt_traverse(alpm_lib_trie_t *bkt_trie,
   5247                           bcm_esw_alpm_bkt_trav_cb trav_fn, void *user_data)
   5248 {
   5249     _alpm_bkt_trav_t        trav_st;
   5250 
   5251     if (!trav_fn) {
   5252         return (BCM_E_PARAM);
   5253     }
   5254 
   5255     sal_memset(&trav_st, 0, sizeof(trav_st));
   5256 
   5257     trav_st.user_cb = trav_fn;
   5258     trav_st.user_data = user_data;
   5259 
   5260     alpm_lib_trie_traverse(bkt_trie, bcm_esw_alpm_bkt_trav_int_cb,
   5261                   (void *)&trav_st, trieTraverseOrderIn);
   5262 
   5263     return BCM_E_NONE;
   5264 }
   5265 
   5266 /* Get count for given pivot trie-tree */
   5267 int
   5268 bcm_esw_alpm_pvt_count_get(int u, _alpm_pvt_node_t *pvt_node, int *count)
   5269 {
   5270     int rv = BCM_E_NONE;
   5271     if (count && PVT_BKT_TRIE(pvt_node) && PVT_BKT_TRIE(pvt_node)->trie) {
   5272         *count = PVT_BKT_TRIE(pvt_node)->trie->count;
   5273     } else {
   5274         rv = BCM_E_PARAM;
   5275     }
   5276 
   5277     return rv;
   5278 }
   5279 
   5280 
   5281 /* Trouble-shooting helper functions */
   5282 
   5283 static int
   5284 alpm_cb_pvt_dump_cb(int u, _alpm_cb_t *acb,
   5285                     _alpm_pvt_node_t *pvt_node, void *datum)
   5286 {
   5287     int i, j, count = 0;
   5288     int index; /* for next level bkt index */
   5289     int idx, sub_idx;
   5290     _alpm_bkt_info_t *bkt_info;
   5291     char vet_str[ALPM_BPB_MAX*2+2] = {0};
   5292     alpm_pvt_trav_cb_data_t *cb_data;
   5293 
   5294     cb_data = (alpm_pvt_trav_cb_data_t *)datum;
   5295     (void)bcm_esw_alpm_pvt_count_get(u, pvt_node, &count);
   5296 
   5297     bkt_info = &PVT_BKT_INFO(pvt_node);
   5298     if (cb_data->bkt_idx == -1 ||
   5299         cb_data->bkt_idx == PVT_BKT_IDX(pvt_node)) {
   5300         ALPM_IER(alpm_util_pvt_idx_get(u, acb, pvt_node, &idx, &sub_idx));
   5301         cli_out("Level%d pvt_idx:%d.%d | bkt_info rofs:%d idx:%d total %d\n",
   5302                 acb->acb_idx + 1, idx, sub_idx,
   5303                 PVT_ROFS(pvt_node), PVT_BKT_IDX(pvt_node), count);
   5304         for (i = 0; i < ACB_BNK_PER_BKT(acb, PVT_BKT_VRF(pvt_node)); i++) {
   5305             for (j = 0; j < 16; j++) {
   5306                 if (bkt_info->vet_bmp[i] & (1 << j)) {
   5307                     vet_str[j] = '*';
   5308                 } else {
   5309                     vet_str[j] = '_';
   5310                 }
   5311             }
   5312             index = ALPM_TAB_IDX_GET_BKT_BNK(acb, PVT_ROFS(pvt_node),
   5313                                              PVT_BKT_IDX(pvt_node), i);
   5314             if (bkt_info->bnk_fmt[i] != 0) {
   5315                 cli_out("----> Bank %d: FMT%d[%s] index:%5d\n", i,
   5316                         bkt_info->bnk_fmt[i], vet_str, index);
   5317             }
   5318         }
   5319     }
   5320 
   5321     return 0;
   5322 }
   5323 
   5324 void
   5325 alpm_cb_pvt_dump(int u, int acb_bmp, int bkt_idx)
   5326 {
   5327     int i, vrf_id, ipt;
   5328     _alpm_cb_t *acb;
   5329     alpm_pvt_trav_cb_data_t *cb_data;
   5330 
   5331     if (ALPMC(u) == NULL) {
   5332         return ;
   5333     }
   5334 
   5335     cb_data = sal_alloc(sizeof(alpm_pvt_trav_cb_data_t), "cb_data");
   5336     if (cb_data == NULL) {
   5337         return ;
   5338     }
   5339 
   5340     for (i = 0; i < ACB_CNT(u); i++) {
   5341         if (!(acb_bmp & (1 << i))) {
   5342             continue;
   5343         }
   5344         acb = ACB(u, i);
   5345         cb_data->unit = u;
   5346         cb_data->acb = acb;
   5347         cb_data->bkt_idx = bkt_idx;
   5348         for (ipt = 0; ipt < ALPM_IPT_CNT; ipt ++) {
   5349             for (vrf_id = 0; vrf_id < ALPM_VRF_ID_CNT(u); vrf_id ++) {
   5350                 if (!ACB_VRF_INITED(u, acb, vrf_id, ipt)) {
   5351                     continue;
   5352                 }
   5353                 cli_out("ALPM CB[%d] Dumping Pivot vrf_id %d, ipt %s\n", i,
   5354                         vrf_id, alpm_util_ipt_str[ipt]);
   5355                 (void)bcm_esw_alpm_pvt_traverse(u, i, vrf_id, ipt,
   5356                         alpm_cb_pvt_dump_cb, cb_data);
   5357             }
   5358         }
   5359     }
   5360 
   5361     sal_free(cb_data);
   5362 
   5363     return ;
   5364 }
   5365 
   5366 static int
   5367 alpm_cb_bkt_dump_cb(int u, _alpm_cb_t *acb,
   5368                     _alpm_pvt_node_t *pvt_node, void *datum)
   5369 {
   5370     int rv = BCM_E_NONE;
   5371     int i, j, ent_bit, ent_shift;
   5372     uint8 bnk_fmt;
   5373 
   5374     _alpm_bkt_info_t    *bkt_info;
   5375     alpm_pvt_trav_cb_data_t *cb_data;
   5376 
   5377 #define _ENT_BITS   5
   5378 
   5379     cb_data = (alpm_pvt_trav_cb_data_t *)datum;
   5380     ent_shift = _shr_popcount(ALPM_BPB_MAX - 1) + _ENT_BITS;
   5381     bkt_info = &PVT_BKT_INFO(pvt_node);
   5382     SHR_BITSET(cb_data->bkt, PVT_BKT_IDX(pvt_node));
   5383 
   5384     for (i = 0; i < ALPM_BPB_MAX; i++) {
   5385         bnk_fmt = bkt_info->bnk_fmt[i];
   5386         if (BI_BNK_IS_USED(bkt_info, i)) {
   5387             int bnk_idx;
   5388             if (i < PVT_ROFS(pvt_node)) {
   5389                 bnk_idx =
   5390                     ((PVT_BKT_IDX(pvt_node) + 1) <<
   5391                     _shr_popcount(ALPM_BPB_MAX - 1) | i);
   5392             } else {
   5393                 bnk_idx =
   5394                     (PVT_BKT_IDX(pvt_node) <<
   5395                     _shr_popcount(ALPM_BPB_MAX - 1) | i);
   5396             }
   5397             SHR_BITSET(cb_data->bnk, bnk_idx);
   5398             cb_data->bnkfmt[bnk_idx] = bnk_fmt;
   5399         }
   5400         for (j = 0; j < sizeof(bkt_info->vet_bmp[0]) * 8; j++) {
   5401             if (SHR_BITGET(&bkt_info->vet_bmp[i], j)) {
   5402                 ent_bit = (i << _ENT_BITS) | j;
   5403                 if (i < PVT_ROFS(pvt_node)) {
   5404                     ent_bit = ((PVT_BKT_IDX(pvt_node) + 1) << ent_shift) | ent_bit;
   5405                 } else {
   5406                     ent_bit = (PVT_BKT_IDX(pvt_node) << ent_shift) | ent_bit;
   5407                 }
   5408                 SHR_BITSET(cb_data->ent, ent_bit);
   5409             }
   5410         }
   5411     }
   5412 
   5413     return rv;
   5414 }
   5415 
   5416 static void
   5417 alpm_cb_bkt_pool_dump(int u, int ipt, _alpm_cb_t *acb,
   5418                       _alpm_bkt_pool_conf_t *bp_conf,
   5419                       char *prefix)
   5420 {
   5421     int j, k;
   5422     int bnk_cnt, total_bnk_cnt, bkt_cnt;
   5423     SHR_BITDCL *bnk_bmp = BPC_BNK_BMP(bp_conf, ipt);
   5424 
   5425 #define BKT_PER_BLK 64
   5426 
   5427     bkt_cnt = ACB_BKT_CNT(acb);
   5428 
   5429     cli_out("  %s %s BANK POOL USAGE\n", prefix, alpm_util_ipt_str[ipt]);
   5430     cli_out("------------------------------------------------------------"
   5431             "-------------------------------\n");
   5432     for (j = 0; j < bkt_cnt / BKT_PER_BLK; j++) {
   5433         int tmp_bnk = 0;
   5434         total_bnk_cnt = 0;
   5435         cli_out("BKT%04d-%04d [", j * BKT_PER_BLK, (j+1) * BKT_PER_BLK - 1);
   5436         for (k = j * BKT_PER_BLK; k < (j+1) * BKT_PER_BLK; k++) {
   5437             SHR_BITCOUNT_RANGE(bnk_bmp, bnk_cnt,
   5438                 k * BPC_BNK_PER_BKT(bp_conf), BPC_BNK_PER_BKT(bp_conf));
   5439             total_bnk_cnt += bnk_cnt;
   5440             if (bnk_cnt >= 16) {
   5441                 cli_out("@");
   5442             } else {
   5443                 cli_out("%x", bnk_cnt);
   5444             }
   5445         }
   5446         tmp_bnk =
   5447             total_bnk_cnt * 1000 / (BPC_BNK_PER_BKT(bp_conf) * BKT_PER_BLK);
   5448         cli_out("] %2d.%d%%\n", tmp_bnk / 10, tmp_bnk % 10);
   5449     }
   5450 }
   5451 
   5452 static void
   5453 alpm_cb_bkt_bnk_dump(int u, int ipt, _alpm_cb_t *acb,
   5454                      _alpm_bkt_pool_conf_t *bp_conf, char *prefix)
   5455 {
   5456     int rv = BCM_E_NONE, j, k, bnk, vrf_id, ipt1;
   5457     int vrf_min, vrf_max;
   5458     int bnk_cnt, total_bnk_cnt;
   5459     int ent_cnt, total_ent_cnt, max_ent_cnt;
   5460     int bkt_cnt;
   5461 
   5462     alpm_pvt_trav_cb_data_t *cdata = NULL;
   5463 
   5464 #define BKT_PER_BLK 64
   5465 #define _ENT_BITS   5
   5466 
   5467     bkt_cnt = ACB_BKT_CNT(acb);
   5468 
   5469     ALPM_ALLOC_EG(cdata, sizeof(*cdata), "bktusage");
   5470 
   5471     if (ACB_BKT_VRF_POOL(acb, ALPM_VRF_ID_GLO(u)) ==
   5472         ACB_BKT_VRF_POOL(acb, 1)) {
   5473         vrf_min = 0;
   5474         vrf_max = ALPM_VRF_ID_GLO(u);
   5475     } else if (bp_conf == ACB_BKT_VRF_POOL(acb, ALPM_VRF_ID_GLO(u))) {
   5476         vrf_min = ALPM_VRF_ID_GLO(u);
   5477         vrf_max = ALPM_VRF_ID_GLO(u);
   5478     } else {
   5479         vrf_min = 0;
   5480         vrf_max = ALPMC(u)->_alpm_max_vrf_id;
   5481     }
   5482 
   5483     for (ipt1 = ipt; ipt1 < ALPM_IPT_CNT; ipt1++) {
   5484         if ((ipt1 == ipt) ||
   5485             (ipt1 > ipt && /* same pool case (V4/V6) */
   5486             BPC_BNK_INFO(bp_conf, ipt1) ==
   5487             BPC_BNK_INFO(bp_conf, ipt1 - 1))) {
   5488 
   5489             for (vrf_id = vrf_min; vrf_id <= vrf_max; vrf_id++) {
   5490                 if (!ACB_VRF_INITED(u, acb, vrf_id, ipt1)) {
   5491                     continue;
   5492                 }
   5493                 (void)bcm_esw_alpm_pvt_traverse(u, acb->acb_idx, vrf_id, ipt1,
   5494                         alpm_cb_bkt_dump_cb, cdata);
   5495             }
   5496         }
   5497     }
   5498 
   5499     cli_out("  BKT RANGE |[---------------- banks used per bucket(%7s %3s) -"
   5500             "-----------] AVGBK AVGET\n", prefix, alpm_util_ipt_str[ipt]);
   5501     cli_out("------------------------------------------------------------"
   5502             "-------------------------------\n");
   5503     for (j = 0; j < bkt_cnt / BKT_PER_BLK; j++) {
   5504         int tmp_bnk, tmp_ent;
   5505         total_bnk_cnt = 0;
   5506         total_ent_cnt = 0;
   5507         max_ent_cnt   = 0;
   5508         cli_out("BKT%04d-%04d [", j * BKT_PER_BLK, (j+1) * BKT_PER_BLK - 1);
   5509         for (k = j * BKT_PER_BLK; k < (j+1) * BKT_PER_BLK; k++) {
   5510             if (SHR_BITGET(cdata->bkt, k)) {
   5511                 SHR_BITCOUNT_RANGE(cdata->bnk, bnk_cnt,
   5512                     k << _shr_popcount(ALPM_BPB_MAX - 1), ALPM_BPB_MAX);
   5513                 total_bnk_cnt += bnk_cnt;
   5514                 if (bnk_cnt >= 16) {
   5515                     cli_out("@");
   5516                 } else {
   5517                     cli_out("%x", bnk_cnt);
   5518                 }
   5519             } else {
   5520                 cli_out("%s", "_");
   5521             }
   5522             for (bnk = 0; bnk < BPC_BNK_PER_BKT(bp_conf); bnk++) {
   5523                 int bnk_idx =
   5524                     (k << _shr_popcount(ALPM_BPB_MAX - 1) | bnk);
   5525                 SHR_BITCOUNT_RANGE(cdata->ent, ent_cnt, bnk_idx << _ENT_BITS, (2 << (_ENT_BITS - 1)));
   5526                 total_ent_cnt += ent_cnt;
   5527                 max_ent_cnt += BPC_FMT_ENT_MAX(bp_conf, cdata->bnkfmt[bnk_idx]);
   5528             }
   5529         }
   5530         tmp_bnk =
   5531             total_bnk_cnt * 1000 / (BPC_BNK_PER_BKT(bp_conf) * BKT_PER_BLK);
   5532         tmp_ent = (max_ent_cnt > 0)
   5533                     ? total_ent_cnt * 1000 / max_ent_cnt
   5534                     : 0;
   5535         cli_out("] %2d.%d%% %2d.%d%%\n", tmp_bnk / 10, tmp_bnk % 10,
   5536             tmp_ent / 10, tmp_ent % 10);
   5537     }
   5538 
   5539     alpm_util_free(cdata);
   5540 
   5541 bad:
   5542     if (BCM_FAILURE(rv)) {
   5543         ALPM_ERR(("alpm_cb_bkt_bnk_dump error %d\n", rv));
   5544     }
   5545     return;
   5546 
   5547 }
   5548 
   5549 /*
   5550  * 0-8/0-5 : count of occupied banks)
   5551  * _ : free bucket
   5552  * 30% : average bank percentage per 64 bucket
   5553  * 40% : average entry percentage per 64 bucket
   5554  *
   5555  * BKT0000-0063 [32458___________] 30% 40%
   5556  * BKT0064-0127 [_3133___________] 30% 40%
   5557  */
   5558 void
   5559 alpm_cb_bkt_dump(int u, int acb_bmp)
   5560 {
   5561     int i, ipt;
   5562     _alpm_cb_t *acb;
   5563     _alpm_bkt_pool_conf_t *gbl_bp = NULL;
   5564     _alpm_bkt_pool_conf_t *prt_bp = NULL;
   5565 
   5566 #define BKT_PER_BLK 64
   5567 
   5568     if (ALPMC(u) == NULL) {
   5569         return ;
   5570     }
   5571 
   5572     for (i = 0; i < ACB_CNT(u); i++) {
   5573         if (!(acb_bmp & (1 << i))) {
   5574             continue;
   5575         }
   5576         cli_out("ALPM CB[%d] Dumping BUCKET usage:\n", i);
   5577 
   5578         acb     = ACB(u, i);
   5579         gbl_bp  = ACB_BKT_VRF_POOL(acb, ALPM_VRF_ID_GLO(u));
   5580         prt_bp  = ACB_BKT_VRF_POOL(acb, 1);
   5581 
   5582         for (ipt = ALPM_IPT_V4; ipt < ALPM_IPT_CNT; ipt++) {
   5583             if (ipt > ALPM_IPT_V4 &&
   5584                 BPC_BNK_INFO(gbl_bp, ipt) ==
   5585                 BPC_BNK_INFO(gbl_bp, ipt - 1)) {
   5586                 continue;
   5587             }
   5588             alpm_cb_bkt_pool_dump(u, ipt, acb, gbl_bp,
   5589                                   gbl_bp == prt_bp ? "GLOBAL/PRIVATE" : "GLOBAL");
   5590             alpm_cb_bkt_bnk_dump(u, ipt, acb, gbl_bp,
   5591                                  gbl_bp == prt_bp ? "GLO/PRI" : "GLOBAL");
   5592         }
   5593 
   5594         if (gbl_bp == prt_bp) {
   5595             continue;
   5596         }
   5597 
   5598         for (ipt = ALPM_IPT_V4; ipt < ALPM_IPT_CNT; ipt++) {
   5599             if (ipt > ALPM_IPT_V4 &&
   5600                 BPC_BNK_INFO(prt_bp, ipt) ==
   5601                 BPC_BNK_INFO(prt_bp, ipt - 1)) {
   5602                 continue;
   5603             }
   5604 
   5605             alpm_cb_bkt_pool_dump(u, ipt, acb, prt_bp, "PRIVATE");
   5606             alpm_cb_bkt_bnk_dump(u, ipt, acb, prt_bp, "PRIVATE");
   5607         }
   5608     }
   5609 
   5610     return ;
   5611 }
   5612 
   5613 static int
   5614 alpm_cb_fmt_dump_cb(int u, _alpm_cb_t *acb,
   5615                     _alpm_pvt_node_t *pvt_node, void *datum)
   5616 {
   5617     int i;
   5618     _alpm_bkt_info_t *bkt_info;
   5619     uint32 *fmt = (uint32 *)datum;
   5620     uint8 bnk_fmt;
   5621 
   5622     bkt_info = &PVT_BKT_INFO(pvt_node);
   5623     for (i = 0; i < ALPM_BPB_MAX; i++) {
   5624         bnk_fmt = bkt_info->bnk_fmt[i];
   5625         if (BI_BNK_IS_USED(bkt_info, i)) {
   5626             fmt[bnk_fmt] ++;
   5627         }
   5628     }
   5629 
   5630     return 0;
   5631 }
   5632 
   5633 /*
   5634  * Pivot CB:
   5635  *  FMT 1: 10% (1)
   5636  *  FMT 2:  0%
   5637  *  FMT 3: 83%
   5638  *  FMT 4:
   5639  *  FMT 5:
   5640  *  FMT 6:
   5641  *  FMT 7:
   5642  *  FMT 8:
   5643  *
   5644  * Route CB:
   5645  *  FMT 1: 2O%
   5646  *  FMT 2:
   5647  *  ...
   5648  *  FMT 12:
   5649  */
   5650 void
   5651 alpm_cb_fmt_dump(int u, int acb_bmp)
   5652 {
   5653     int i, j, pid, vrf_id, ipt, fmt_sum;
   5654     _alpm_cb_t *acb;
   5655     uint32 fmt[2][16];
   5656 
   5657     if (ALPMC(u) == NULL) {
   5658         return ;
   5659     }
   5660 
   5661     sal_memset(fmt, 0, sizeof(fmt));
   5662     for (i = 0; i < ACB_CNT(u); i++) {
   5663         if (!(acb_bmp & (1 << i))) {
   5664             continue;
   5665         }
   5666 
   5667         acb = ACB(u, i);
   5668 
   5669         for (pid = 0; pid < ALPM_BKT_PID_CNT; pid++) {
   5670             _alpm_bkt_pool_conf_t *bp_conf;
   5671             bp_conf = ACB_BKT_POOL(acb, pid);
   5672 
   5673             if (pid > 0 &&
   5674                 ACB_BKT_POOL(acb, pid-1) == ACB_BKT_POOL(acb, pid)) {
   5675                 continue;
   5676             }
   5677 
   5678             cli_out("ALPM CB[%d.%d %s] Dumping FMT distribution:\n", i, pid,
   5679                     BPC_FMT_TYPE(bp_conf) == ALPM_FMT_RTE ? "Route" : "Pivot");
   5680             for (ipt = 0; ipt < ALPM_IPT_CNT; ipt ++) {
   5681                 for (vrf_id = 0; vrf_id < ALPM_VRF_ID_CNT(u); vrf_id ++) {
   5682                     if (!ACB_VRF_INITED(u, acb, vrf_id, ipt)) {
   5683                         continue;
   5684                     }
   5685                     (void)bcm_esw_alpm_pvt_traverse(u, i, vrf_id, ipt,
   5686                             alpm_cb_fmt_dump_cb, fmt[i]);
   5687                 }
   5688             }
   5689 
   5690             fmt_sum = 0;
   5691             for (j = 1; j <= BPC_FMT_CNT(bp_conf); j++) {
   5692                 fmt_sum += fmt[i][j];
   5693             }
   5694 
   5695             /* Avoid Floating point exception */
   5696             if (fmt_sum == 0) {
   5697                 fmt_sum = 0xdeadbee;
   5698             }
   5699 
   5700             if (fmt_sum == 0xdeadbee) {
   5701                 cli_out("\tAll ZERO\n\n");
   5702                 continue;
   5703             }
   5704 
   5705             for (j = 1; j <= BPC_FMT_CNT(bp_conf); j++) {
   5706                 if (fmt[i][j] != 0) {
   5707                     cli_out("\tFMT %2d(Len %3d): %2d.%d%% (Count %d)\n", j,
   5708                             BPC_FMT_PFX_LEN(bp_conf, j),
   5709                             fmt[i][j] * 100 / fmt_sum,
   5710                             (fmt[i][j] * 1000 / fmt_sum) % 10,
   5711                             fmt[i][j]);
   5712                 }
   5713             }
   5714         }
   5715     }
   5716 
   5717     return ;
   5718 }
   5719 
   5720 static int
   5721 alpm_cb_pvtlen_dump_cb(int u, _alpm_cb_t *acb,
   5722                        _alpm_pvt_node_t *pvt_node, void *datum)
   5723 {
   5724     uint32 *pvt_len = (uint32 *)datum;
   5725 
   5726     if (pvt_node && PVT_KEY_LEN(pvt_node) <= 128) {
   5727         pvt_len[PVT_KEY_LEN(pvt_node)]++;
   5728     }
   5729 
   5730     return 0;
   5731 }
   5732 
   5733 /*
   5734  * Pivot CB:
   5735  *  Pivot Len 0: 10% (1)
   5736  *  ......
   5737  *  Pivot Len 128: 20% (2)
   5738  *
   5739  * Route CB:
   5740  *  ......
   5741  */
   5742 void
   5743 alpm_cb_pvtlen_dump(int u, int acb_bmp)
   5744 {
   5745     int i, j, k, vrf_id, ipt, pvt_len_sum[2];
   5746     _alpm_cb_t *acb;
   5747     uint32 pvt_len[2][129];
   5748 
   5749     if (ALPMC(u) == NULL) {
   5750         return ;
   5751     }
   5752 
   5753     for (i = 0; i < ACB_CNT(u); i++) {
   5754         if (!(acb_bmp & (1 << i))) {
   5755             continue;
   5756         }
   5757 
   5758         acb = ACB(u, i);
   5759         sal_memset(pvt_len, 0, sizeof(pvt_len));
   5760         for (ipt = 0; ipt < ALPM_IPT_CNT; ipt ++) {
   5761             for (vrf_id = 0; vrf_id < ALPM_VRF_ID_CNT(u); vrf_id ++) {
   5762                 if (!ACB_VRF_INITED(u, acb, vrf_id, ipt)) {
   5763                     continue;
   5764                 }
   5765                 (void)bcm_esw_alpm_pvt_traverse(u, i, vrf_id, ipt,
   5766                         alpm_cb_pvtlen_dump_cb,
   5767                         pvt_len[ACB_FMT_TYPE(acb, vrf_id)]);
   5768             }
   5769         }
   5770 
   5771         for (k = 0; k < 2; k++) {
   5772             pvt_len_sum[k] = 0;
   5773             for (j = 0; j <= 128; j++) {
   5774                 pvt_len_sum[k] += pvt_len[k][j];
   5775             }
   5776             /* Avoid Floating point exception */
   5777             if (pvt_len_sum[k] == 0) {
   5778                 pvt_len_sum[k] = 0xdeadbee;
   5779             }
   5780             if (pvt_len_sum[k] == 0xdeadbee) {
   5781                 continue;
   5782             }
   5783 
   5784             cli_out("ALPM CB[%d %s] Dumping Pivot Length distribution:\n", i,
   5785                     k == 0 ? "Pivot" : "Route");
   5786             for (j = 0; j <= 128; j++) {
   5787                 if (pvt_len[k][j] != 0) {
   5788                     cli_out("\tPVT_LEN %3d: %2d.%d%% (Count %d)\n", j,
   5789                             pvt_len[k][j] * 100 / pvt_len_sum[k],
   5790                             (pvt_len[k][j] * 1000 / pvt_len_sum[k]) % 10,
   5791                             pvt_len[k][j]);
   5792                 }
   5793             }
   5794         }
   5795     }
   5796 
   5797     return ;
   5798 }
   5799 
   5800 /* BCM.0>alpm stat show <1|2|3> */
   5801 void
   5802 alpm_cb_stat_dump(int u, int acb_bmp)
   5803 {
   5804     int i, j, p, ipt;
   5805     uint32 alloc_cnt, free_cnt, dbg_bmp, dbg_on = 0;
   5806     _alpm_cb_t *acb;
   5807     _alpm_bkt_pool_conf_t *bp_conf = NULL;
   5808 
   5809 #define _DBG_BMP_STR_CNT    10
   5810     char *dbg_bmp_str[_DBG_BMP_STR_CNT] = {
   5811         "PvtSanity",
   5812         "PvtSanityLen",
   5813         "PvtDefrag",
   5814         "PvtSanityNode",
   5815         "PvtSanityCount",
   5816         "WriteCacheOnly",
   5817         "BnkConf",
   5818         "PvtUpdateSkip",
   5819         "HitBit",
   5820         ""
   5821     };
   5822 
   5823     if (ALPMC(u) == NULL) {
   5824         return ;
   5825     }
   5826 
   5827     dbg_bmp = ALPMC(u)->_alpm_dbg_bmp;
   5828 
   5829     cli_out("ALPM debug:\n");
   5830     for (i = 0; i < _DBG_BMP_STR_CNT; i++) {
   5831         if (dbg_bmp & (1 << i)) {
   5832             cli_out("\tbit %d %s\n", i, dbg_bmp_str[i]);
   5833             dbg_on = 1;
   5834         }
   5835     }
   5836     if (!dbg_on) {
   5837         cli_out("\toff\n");
   5838     }
   5839 
   5840     cli_out("ALPM recorded error messages:\n");
   5841     for (i = 0; i < _ALPM_ERR_MSG_CUR_IDX(u); i++) {
   5842         cli_out("%3d: %s", i, _ALPM_ERR_MSG_ENT(u, i));
   5843     }
   5844     cli_out("\n");
   5845 
   5846     alpm_util_mem_stat_get(&alloc_cnt, &free_cnt);
   5847     cli_out("ALPM Host mem: alloc %8d free %8d\n", alloc_cnt, free_cnt);
   5848     for (i = 0; i < ACB_CNT(u); i++) {
   5849         if (!(acb_bmp & (1 << i))) {
   5850             continue;
   5851         }
   5852         cli_out("ALPM CB[%d] Statistics:\n\n", i);
   5853         acb = ACB(u, i);
   5854 
   5855         if (ACB_HAS_TCAM(acb)) {
   5856             bcm_esw_alpm_tcam_zone_dump(u, "\t");
   5857             cli_out("\n");
   5858         }
   5859 
   5860 #define _BKT_POOL_USAGE_PRINT(acb_idx, pid, bp_conf, ipt)                   \
   5861         cli_out("\tBucket Pool %d(%s) Usage(Level%d): %6d/%6d = %d.%d%%\n", \
   5862             pid, alpm_util_ipt_str[ipt], acb_idx + 2,                       \
   5863             BPC_BNK_USED(bp_conf, ipt),                                     \
   5864             BPC_BNK_CNT(bp_conf),                                           \
   5865             BPC_BNK_CNT(bp_conf) ?                                          \
   5866                 (BPC_BNK_USED(bp_conf, ipt) * 100 / BPC_BNK_CNT(bp_conf)) : 0, \
   5867             BPC_BNK_CNT(bp_conf) ?                                          \
   5868                 ((BPC_BNK_USED(bp_conf, ipt) * 1000 / BPC_BNK_CNT(bp_conf)) % 10) : 0);
   5869         for (p = 0; p < ALPM_BKT_PID_CNT; p++) {
   5870             bp_conf = ACB_BKT_POOL(acb, p);
   5871             if (p > 0 && bp_conf == ACB_BKT_POOL(acb, p-1)) {
   5872                 continue;
   5873             }
   5874             for (ipt = ALPM_IPT_V4; ipt < ALPM_IPT_CNT; ipt++) {
   5875                 if (ipt > ALPM_IPT_V4 &&
   5876                     BPC_BNK_INFO(bp_conf, ipt) ==
   5877                     BPC_BNK_INFO(bp_conf, ipt - 1)) {
   5878                     continue;
   5879                 }
   5880                 _BKT_POOL_USAGE_PRINT(acb->acb_idx, p, bp_conf, ipt)
   5881             }
   5882         }
   5883 
   5884         cli_out("\tMemory Stats: \n");
   5885         for (j = 0; j < alpmTblCount; j++) {
   5886             if (acb->acb_cnt.c_mem[j][0] != 0 || acb->acb_cnt.c_mem[j][1] != 0) {
   5887                 cli_out("\t  %22s: RD %10d WR %10d\n", alpm_tbl_str[j],
   5888                         acb->acb_cnt.c_mem[j][0],
   5889                         acb->acb_cnt.c_mem[j][1]);
   5890             }
   5891         }
   5892         cli_out("\tDefrag : %8d\n", acb->acb_cnt.c_defrag);
   5893         cli_out("\tMerge  : %8d\n", acb->acb_cnt.c_merge);
   5894         cli_out("\tExpand : %8d\n", acb->acb_cnt.c_expand);
   5895         cli_out("\tSplit  : %8d\n", acb->acb_cnt.c_split);
   5896         cli_out("\tRipple : %8d\n", acb->acb_cnt.c_ripple);
   5897         cli_out("\tBNKshrk: %8d\n", acb->acb_cnt.c_bnkshrk);
   5898         cli_out("\tBNKfree: %8d\n", acb->acb_cnt.c_bnkfree);
   5899         cli_out("\tSMCS1  : %8d\n", acb->acb_cnt.c_spl_mp_cs1);
   5900         cli_out("\tSMCS21 : %8d\n", acb->acb_cnt.c_spl_mp_cs21);
   5901         cli_out("\tSMCS221: %8d\n", acb->acb_cnt.c_spl_mp_cs221);
   5902         cli_out("\tSMCS222: %8d\n", acb->acb_cnt.c_spl_mp_cs222);
   5903         cli_out("\tFULL:    %8d\n", acb->acb_cnt.c_full);
   5904         cli_out("\n");
   5905     }
   5906 }
   5907 
   5908 /* BCM.0>alpm config show <1|2|3> */
   5909 void
   5910 alpm_cb_conf_dump(int u, int acb_bmp)
   5911 {
   5912     int i, pid, ipt, fmt;
   5913     _alpm_cb_t *acb;
   5914 
   5915     if (ALPMC(u) == NULL) {
   5916         return ;
   5917     }
   5918 
   5919     for (i = 0; i < ACB_CNT(u); i++) {
   5920         if (!(acb_bmp & (1 << i))) {
   5921             continue;
   5922         }
   5923         cli_out("ALPM CB[%d] Bank Config:\n", i);
   5924         acb = ACB(u, i);
   5925 
   5926         cli_out("\t    bkt_bits: %d\n", ACB_BKT_BITS(acb));
   5927         cli_out("\t     bkt_cnt: %d\n", ACB_BKT_CNT(acb));
   5928 
   5929         for (pid = 0; pid < ALPM_BKT_PID_CNT; pid++) {
   5930             _alpm_bkt_pool_conf_t *bp_conf;
   5931 
   5932             if (pid > 0 &&
   5933                 ACB_BKT_POOL(acb, pid-1) == ACB_BKT_POOL(acb, pid)) {
   5934                 continue;
   5935             }
   5936 
   5937             bp_conf = ACB_BKT_POOL(acb, pid);
   5938             for (ipt = ALPM_IPT_V4; ipt < ALPM_IPT_CNT; ipt++) {
   5939                 if (ipt > ALPM_IPT_V4 &&
   5940                     BPC_BNK_INFO(bp_conf, ipt) ==
   5941                     BPC_BNK_INFO(bp_conf, ipt - 1)) {
   5942                     continue;
   5943                 }
   5944                 cli_out("\t%d.bnk_pool.%d: %p\n", ipt, pid, BPC_BNK_BMP(bp_conf, ipt));
   5945                 cli_out("\t%d.bnk_used.%d: %d\n", ipt, pid, BPC_BNK_USED(bp_conf, ipt));
   5946                 cli_out("\t%d.bnk_rsvd.%d: %d\n", ipt, pid, BPC_BNK_RSVD(bp_conf, ipt));
   5947             }
   5948 
   5949             cli_out("\t bnk_total.%d: %d\n", pid, BPC_BNK_CNT(bp_conf));
   5950             cli_out("\t  bnk_pbkt.%d: %d\n", pid, BPC_BNK_PER_BKT(bp_conf));
   5951             cli_out("\t wrap_arnd.%d: %d\n", pid, BPC_BKT_WRA(bp_conf));
   5952             cli_out("\t fixed_fmt.%d: %d\n", pid, BPC_BKT_FIXED_FMT(bp_conf));
   5953             cli_out("\t   fmt_cnt.%d: %d\n", pid, BPC_FMT_CNT(bp_conf));
   5954 
   5955             cli_out("\t----------------------------------------------------\n");
   5956             cli_out("\tFV |");
   5957             for (fmt = 0; fmt <= BPC_FMT_CNT(bp_conf); fmt++) {
   5958                 cli_out("%3d|", fmt);
   5959             }
   5960             cli_out("\n");
   5961             cli_out("\t----------------------------------------------------\n");
   5962             cli_out("\tCAP|");
   5963             for (fmt = 0; fmt <= BPC_FMT_CNT(bp_conf); fmt++) {
   5964                 cli_out("%3d|", BPC_FMT_ENT_MAX(bp_conf, fmt));
   5965             }
   5966             cli_out("\n");
   5967             cli_out("\t----------------------------------------------------\n");
   5968             cli_out("\tPfL|");
   5969             for (fmt = 0; fmt <= BPC_FMT_CNT(bp_conf); fmt++) {
   5970                 cli_out("%3d|", BPC_FMT_PFX_LEN(bp_conf, fmt));
   5971             }
   5972             cli_out("\n");
   5973             cli_out("\t----------------------------------------------------\n");
   5974 
   5975         }
   5976     }
   5977 }
   5978 
   5979 int alpm_table_dump(int u, int vrf_id, soc_mem_t mem, int copyno, int index,
   5980                     int fmt, int ent_idx, int flags)
   5981 {
   5982     return ALPM_DRV(u)->alpm_table_dump(u, vrf_id, mem, copyno, index, fmt, ent_idx, flags);
   5983 }
   5984 
   5985 static int
   5986 alpm_cb_ent_pfx_len_get(int u, _alpm_cb_t *acb,
   5987                         _alpm_pvt_node_t *pvt_node, int ent_idx)
   5988 {
   5989     return ALPM_DRV(u)->alpm_ent_pfx_len_get(u, acb, pvt_node, ent_idx);
   5990 }
   5991 
   5992 int
   5993 alpm_cb_pvt_sanity_cb(int u, _alpm_cb_t *acb,
   5994                       _alpm_pvt_node_t *pvt_node, void *datum)
   5995 {
   5996     int a, i, rv = BCM_E_NONE;
   5997     int bkt_node_cnt, bkt_info_cnt;
   5998     int vrf_id, ipt, err = 0;
   5999     int end_bnk, bnkpb, bnk_cnt;
   6000 
   6001     char        *pfx_str = datum;
   6002     alpm_lib_trie_t      *bkt_trie = NULL;
   6003     _alpm_cb_t  *acb_tmp = NULL;
   6004     _alpm_bkt_info_t *bkt_info;
   6005     _alpm_bkt_pfx_arr_t *pfx_arr = NULL;
   6006     _alpm_bkt_node_t *bkt_node;
   6007 
   6008     bkt_info = &PVT_BKT_INFO(pvt_node);
   6009     bkt_trie = PVT_BKT_TRIE(pvt_node);
   6010     vrf_id   = PVT_BKT_VRF(pvt_node);
   6011     ipt      = PVT_BKT_IPT(pvt_node);
   6012     bnkpb   = ACB_BNK_PER_BKT(acb, vrf_id);
   6013 
   6014     if (ALPMC(u)->_alpm_dbg_bmp & _ALPM_DBG_PVT_PTR_CHK) {
   6015 #define CORRUPT(p)                      \
   6016         (p[-1] != 0xaaaaaaaa ||         \
   6017         p[p[-2]] != 0xbbbbbbbb)
   6018 
   6019         int pid, pvt_cnt;
   6020         for (a = 0; a < ACB_CNT(u); a++) {
   6021             acb_tmp = ACB(u, a);
   6022             for (pid = 0; pid < ALPM_BKT_PID_CNT; pid++) {
   6023                 _alpm_bkt_pool_conf_t *bp_conf;
   6024                 uint32 *pvt_ptr;
   6025 
   6026                 if (pid > 0 &&
   6027                     ACB_BKT_POOL(acb_tmp, pid-1) ==
   6028                     ACB_BKT_POOL(acb_tmp, pid)) {
   6029                     continue;
   6030                 }
   6031 
   6032                 bp_conf = ACB_BKT_POOL(acb_tmp, pid);
   6033                 pvt_cnt = BPC_BNK_CNT(bp_conf);
   6034 
   6035                 for (i = 0; i < pvt_cnt; i++) {
   6036                     pvt_ptr = bp_conf->pvt_ptr[i];
   6037                     if (pvt_ptr == NULL) {
   6038                         continue;
   6039                     }
   6040 
   6041                     if (CORRUPT(pvt_ptr)) {
   6042                         cli_out("acb %d: pvt_ptr %p in pool %d bkt %d "
   6043                                 "bnk %d is corrupted\n",
   6044                                 a, pvt_ptr, pid, ALPM_IDX_TO_BKT(acb_tmp, i),
   6045                                 ALPM_IDX_TO_BNK(acb_tmp, i));
   6046                         err++;
   6047                         goto bad;
   6048                     }
   6049 
   6050                     pvt_ptr =
   6051                         (uint32 *)PVT_BKT_TRIE((_alpm_pvt_node_t *)pvt_ptr);
   6052                     if (CORRUPT(pvt_ptr)) {
   6053                         cli_out("acb %d: pvt_bkt_trie %p in pool %d bkt %d "
   6054                                 "bnk %d is corrupted\n",
   6055                                 a, pvt_ptr, pid, ALPM_IDX_TO_BKT(acb_tmp, i),
   6056                                 ALPM_IDX_TO_BNK(acb_tmp, i));
   6057                         err++;
   6058                         goto bad;
   6059                     }
   6060                 }
   6061             }
   6062         }
   6063     }
   6064 
   6065     /* Check Global bank usage and pvt_ptr */
   6066     if ((sal_strcmp(pfx_str, "CBInsert") == 0 ||
   6067          sal_strcmp(pfx_str, "CBDelete") == 0 ||
   6068          sal_strcmp(pfx_str, "SanityAll") == 0) &&
   6069         ALPMC(u)->_alpm_dbg_bmp & _ALPM_DBG_BNK_CONF_NULL_PVT) {
   6070         int tab_idx;
   6071         SHR_BITDCL *bnk_bmp;
   6072 
   6073         /* Private VRFs */
   6074         bnk_bmp = ACB_BNK_BMP(acb, vrf_id, ipt);
   6075         bnk_cnt = ACB_BNK_CNT(acb, vrf_id);
   6076 
   6077         for (i = 0; i < bnk_cnt; i++) {
   6078             if (SHR_BITGET(bnk_bmp, i)) {
   6079                 tab_idx = ALPM_TAB_IDX_GET_BKT_BNK(acb, 0, i/bnkpb, i%bnkpb);
   6080                 /* If bank is occupied but pvt_ptr is not set, report error
   6081                  * Skip examing bkt 0
   6082                  */
   6083                 if ((i/bnkpb) != 0 &&
   6084                     ACB_PVT_PTR(acb, pvt_node, tab_idx) == NULL) {
   6085                     cli_out("\n[%s]PVT-SANITY(CB%d): bkt %d bnk %d was used "
   6086                             "by NULL pvt_ptr\n", pfx_str, acb->acb_idx,
   6087                             i/bnkpb, i%bnkpb);
   6088                     err++;
   6089                     goto bad;
   6090                 }
   6091             }
   6092         }
   6093     }
   6094 
   6095     /* Check Global bank usage and pvt_ptr */
   6096     if ((sal_strcmp(pfx_str, "CBInsert") == 0 ||
   6097          sal_strcmp(pfx_str, "CBDelete") == 0 ||
   6098          sal_strcmp(pfx_str, "SanityAll") == 0) &&
   6099         ALPMC(u)->_alpm_dbg_bmp & _ALPM_DBG_BNK_CONF) {
   6100         SHR_BITDCL *bnk_bmp;
   6101 
   6102         /* Private VRFs */
   6103         bnk_bmp = ACB_BNK_BMP(acb, vrf_id, ipt);
   6104 
   6105         for (i = 0; i < bnkpb; i++) {
   6106             if (BI_BNK_IS_USED(bkt_info, i)) {
   6107                 int gbl_bnk =
   6108                     BI_BKT_IDX(bkt_info) * ACB_BNK_PER_BKT(acb, vrf_id) + i;
   6109                 if (BI_ROFS(bkt_info) > i) {
   6110                     gbl_bnk += ACB_BNK_PER_BKT(acb, vrf_id);
   6111                 }
   6112 
   6113                 if (!SHR_BITGET(bnk_bmp, gbl_bnk)) {
   6114                     cli_out("\n[%s]PVT-SANITY(CB%d): bkt %d bnk %d was used "
   6115                             "but global bit %d is not SET\n", pfx_str, acb->acb_idx,
   6116                             BI_BKT_IDX(bkt_info), i, gbl_bnk);
   6117                     err++;
   6118                     goto bad;
   6119                 }
   6120             }
   6121         }
   6122     }
   6123 
   6124     /* Check if used banks are coutinuous */
   6125     if (!ACB_BKT_FIXED_FMT(acb, 1)) {
   6126         end_bnk = -1;
   6127         for (i = PVT_ROFS(pvt_node); i < PVT_ROFS(pvt_node) + bnkpb; i++) {
   6128             if (bkt_info->bnk_fmt[i % bnkpb] == 0) {
   6129                 end_bnk = i;
   6130             } else if (end_bnk != -1) {
   6131                 /* Once end_bnk is settled, the rest bnks FMT should be 0 */
   6132                 cli_out("[%s]PVT-SANITY(CB%d): Used banks are not cont. rofs %d: ",
   6133                         pfx_str, acb->acb_idx, PVT_ROFS(pvt_node));
   6134                 for (i = 0; i < bnkpb; i++) {
   6135                     if (PVT_ROFS(pvt_node) == i) {
   6136                         cli_out("^");
   6137                     }
   6138                     cli_out("%d ", bkt_info->bnk_fmt[i]);
   6139                 }
   6140                 cli_out("\n");
   6141                 err++;
   6142                 goto bad;
   6143             }
   6144         }
   6145     }
   6146 
   6147     /* trie-tree count & vet_bmp count,
   6148      * SHOULD NOT be used in the middle of process, e.g. bucket split
   6149      */
   6150     if ((sal_strcmp(pfx_str, "CBInsert") == 0 ||
   6151          sal_strcmp(pfx_str, "CBDelete") == 0 ||
   6152          sal_strcmp(pfx_str, "SanityAll") == 0 ||
   6153          sal_strcmp(pfx_str, "SplitOpvt") == 0 ||
   6154          sal_strcmp(pfx_str, "SplitNpvt") == 0) &&
   6155         bkt_trie->trie &&
   6156         ALPMC(u)->_alpm_dbg_bmp & _ALPM_DBG_PVT_SANITY_COUNT) {
   6157         bkt_node_cnt = bkt_trie->trie->count;
   6158         bkt_info_cnt = 0;
   6159         for (i = 0; i < ALPM_BPB_MAX; i++) {
   6160             uint32 vet_bmp;
   6161             if (bkt_info->bnk_fmt[i] == 0) {
   6162                 continue;
   6163             }
   6164 
   6165             vet_bmp = bkt_info->vet_bmp[i];
   6166             bkt_info_cnt += _shr_popcount(vet_bmp);
   6167         }
   6168 
   6169         if (bkt_node_cnt != bkt_info_cnt) {
   6170             cli_out("\n[%s]PVT-SANITY(CB%d): entry cnt mismatch in trie %d, bkt_info %d\n",
   6171                     pfx_str, acb->acb_idx, bkt_node_cnt, bkt_info_cnt);
   6172             err++;
   6173             goto bad;
   6174         }
   6175     }
   6176 
   6177     /* bkt_info & ent_idx, tab_idx & pvt_node pointer
   6178      * SW prefix length & HW prefix length
   6179      *
   6180      * Contruct:
   6181      * - ALPM_IDX_MAKE
   6182      * - ALPM_TAB_IDX_GET(ent_idx)
   6183      *
   6184      * Resolve:
   6185      * - ALPM_IDX_TO_ENT
   6186      * - ALPM_IDX_TO_BNK
   6187      * - ALPM_IDX_TO_BKT
   6188      */
   6189     ALPM_ALLOC_EG(pfx_arr, sizeof(*pfx_arr), "pfx_arr");
   6190     rv = alpm_lib_trie_traverse(bkt_trie, alpm_trie_pfx_cb, pfx_arr,
   6191                        trieTraverseOrderIn);
   6192     ALPM_IEG(rv);
   6193 
   6194     for (i = 0; i < pfx_arr->pfx_cnt; i++) {
   6195         uint32 ent, bnk, bkt;
   6196         uint32 tab_idx;
   6197         uint32 vet_bmp;
   6198         int sw_len, hw_len;
   6199 
   6200         bkt_node = pfx_arr->pfx[i];
   6201 
   6202         /* SW Prefix Length & HW Prefix Length check */
   6203         if (ALPMC(u)->_alpm_dbg_bmp & _ALPM_DBG_PVT_SANITY_LEN) {
   6204             sw_len = bkt_node->key_len;
   6205             hw_len = alpm_cb_ent_pfx_len_get(u, acb, pvt_node,
   6206                                              bkt_node->ent_idx);
   6207             if (!ACB_BKT_FIXED_FMT(acb, 1)) {
   6208                 hw_len += PVT_KEY_LEN(pvt_node);
   6209             }
   6210             if (sw_len != hw_len) {
   6211                 cli_out("\n[%s]PVT-SANITY(CB%d): Prefix Length mismatch sw %d "
   6212                         "hw %d ent_idx 0x%x\n", pfx_str, acb->acb_idx, sw_len, hw_len,
   6213                         bkt_node->ent_idx);
   6214                 err++;
   6215                 goto bad;
   6216             }
   6217         }
   6218 
   6219         ent = ALPM_IDX_TO_ENT(bkt_node->ent_idx);
   6220         bnk = ALPM_IDX_TO_BNK(acb, bkt_node->ent_idx);
   6221         bkt = ALPM_IDX_TO_BKT(acb, bkt_node->ent_idx);
   6222         if (bnk < PVT_ROFS(pvt_node)) {
   6223             bkt -= 1;
   6224         }
   6225 
   6226         /* Bucket mismatch */
   6227         if (BI_BKT_IDX(bkt_info) != bkt) {
   6228             cli_out("\n[%s]PVT-SANITY(CB%d): Bucket idx mismatch in bkt-node %d, "
   6229                     "pvt_node %d\n", pfx_str, acb->acb_idx, bkt, BI_BKT_IDX(bkt_info));
   6230             err++;
   6231             goto bad;
   6232         }
   6233 
   6234         /* Ent, bnk mismatch */
   6235         vet_bmp = bkt_info->vet_bmp[bnk];
   6236         if (bkt_info->bnk_fmt[bnk] == 0 ||
   6237             !SHR_BITGET(&vet_bmp, ent)) {
   6238             cli_out("\n[%s]PVT-SANITY(CB%d): (ent,bnk) mismatch in trie-node (%d,%d)"
   6239                     ", but related valid in bkt_info is (%d, bnk%d-fmt%d)\n",
   6240                     pfx_str, acb->acb_idx, ent, bnk,
   6241                     SHR_BITGET(&vet_bmp, ent),
   6242                     bnk, bkt_info->bnk_fmt[bnk]);
   6243             err++;
   6244             goto bad;
   6245         }
   6246 
   6247         /* tab_idx and pvt_node pointer */
   6248         tab_idx = ALPM_TAB_IDX_GET(bkt_node->ent_idx);
   6249         if (tab_idx >= ACB_BNK_CNT(acb, PVT_BKT_VRF(pvt_node))) {
   6250             cli_out("\n[%s]PVT-SANITY(CB%d): Invalid tab_idx value %d "
   6251                     "(ent %d, bnk %d, bkt %d)\n", pfx_str, acb->acb_idx,
   6252                     tab_idx, ent, bnk, bkt);
   6253             err++;
   6254             goto bad;
   6255         } else if (ACB_PVT_PTR(acb, pvt_node, tab_idx) != pvt_node) {
   6256             _alpm_pvt_node_t *acb_pvt_node;
   6257             acb_pvt_node = (_alpm_pvt_node_t *)ACB_PVT_PTR(acb, pvt_node, tab_idx);
   6258 
   6259             cli_out("\n[%s]PVT-SANITY(CB%d): pvt_ptr of tab_idx %d mismatch "
   6260                     "in acb %p, trie-tree %p\n", pfx_str, acb->acb_idx, tab_idx,
   6261                     acb_pvt_node, pvt_node);
   6262             if (acb_pvt_node != NULL) {
   6263                 cli_out("\t- acb %p key_len %d, bkt_info(rofs %d, bkt %d)\n",
   6264                         acb_pvt_node, PVT_KEY_LEN(acb_pvt_node),
   6265                         PVT_ROFS(acb_pvt_node),
   6266                         PVT_BKT_IDX(acb_pvt_node));
   6267                 cli_out("\t-trie %p key_len %d, bkt_info(rofs %d, bkt %d)\n",
   6268                         pvt_node, PVT_KEY_LEN(pvt_node),
   6269                         PVT_ROFS(pvt_node),
   6270                         PVT_BKT_IDX(pvt_node));
   6271             }
   6272             err++;
   6273             goto bad;
   6274         }
   6275     }
   6276 
   6277 bad:
   6278     if (err > 0) {
   6279         rv = BCM_E_FAIL;
   6280     }
   6281 
   6282     if (pfx_arr != NULL) {
   6283         alpm_util_free(pfx_arr);
   6284     }
   6285 
   6286     return rv;
   6287 }
   6288 
   6289 /*
   6290  * Check software status
   6291  *
   6292  *  - trie-tree count & vet_bmp count
   6293  *  - bkt_info & ent_idx
   6294  */
   6295 int
   6296 alpm_cb_sanity(int u, int acb_bmp, int vrf_id, int ipt)
   6297 {
   6298     int rv = BCM_E_NONE;
   6299     int acb_idx;
   6300     _alpm_cb_t *acb = NULL;
   6301 
   6302     if (!(ALPMC(u)->_alpm_dbg_bmp & _ALPM_DBG_PVT_SANITY)) {
   6303         return rv;
   6304     }
   6305 
   6306     for (acb_idx = 0; acb_idx < ACB_CNT(u); acb_idx++) {
   6307         if (!(acb_bmp & (1 << acb_idx))) {
   6308             continue;
   6309         }
   6310 
   6311         acb = ACB(u, acb_idx);
   6312         if (!ACB_VRF_INITED(u, acb, vrf_id, ipt)) {
   6313             continue;
   6314         }
   6315 
   6316         rv = bcm_esw_alpm_pvt_traverse(u, acb->acb_idx, vrf_id, ipt,
   6317                                        alpm_cb_pvt_sanity_cb, "SanityAll");
   6318         BCM_IF_ERROR_RETURN(rv);
   6319     }
   6320 
   6321     return rv;
   6322 }
   6323 
   6324 #endif /* ALPM_ENABLE */
   6325