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


      1 /*
      2  * 
      3  * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file.
      4  * 
      5  * Copyright 2007-2019 Broadcom Inc. All rights reserved.
      6  * File:    alpm_ts.c
      7  * Purpose: ALPM trouble-shooting & sanity-check
      8  */
      9 
     10 #include <shared/bsl.h>
     11 
     12 #include <soc/mem.h>
     13 #include <soc/drv.h>
     14 #include <soc/debug.h>
     15 #include <soc/error.h>
     16 #include <soc/format.h>
     17 #include <soc/lpm.h>
     18 #include <soc/trident2.h>
     19 #include <soc/tomahawk.h>
     20 #include <shared/bsl.h>
     21 
     22 #include <shared/util.h>
     23 #include <shared/l3.h>
     24 
     25 #if defined(ALPM_ENABLE)
     26 
     27 #include <bcm/l3.h>
     28 #include <bcm_int/esw/l3.h>
     29 #include <bcm_int/esw/firebolt.h>
     30 #include <bcm_int/esw/alpm.h>
     31 #include <bcm_int/esw/alpm_util.h>
     32 
     33 #define ALPM_CB0 0x01
     34 #define ALPM_CB1 0x02
     35 #define ALPM_CB_ALL_BMP (ALPM_CB0 | ALPM_CB1)
     36 
     37 typedef struct _alpm_dbgcnt_s {
     38     uint32 pvt_used[ALPM_PKM_CNT];
     39     uint32 pvt_max[ALPM_PKM_CNT];
     40 
     41     uint32 bucket_used;
     42     uint32 bucket_max;
     43     uint32 bank_used;
     44     uint32 bank_max;
     45     uint32 ent_used[ALPM_PKM_CNT]; /* bkt entries */
     46     uint32 ent_max;
     47     uint32 bs[ALPM_BPB_MAX]; /* bucket share = #pvt share same bucket */
     48 } _alpm_dbgcnt_t;
     49 
     50 typedef struct _alpm_dbg_data_s {
     51     uint32 route_cnt;
     52     uint32 hit_cnt;
     53     _alpm_dbgcnt_t dc[ALPM_CB_CNT];
     54     int *bktref[ALPM_CB_CNT];
     55 } _alpm_dbg_data_t;
     56 
     57 typedef struct _alpm_sanity_s {
     58     int error;
     59     int *bktptr[ALPM_CB_CNT];
     60 } _alpm_sanity_t;
     61 
     62 typedef struct _alpm_pvt_bkt_cnt_s {
     63     uint32 pvt_cnt;
     64     uint32 bkt_cnt;
     65     uint32 add_cnt;
     66     uint32 del_cnt;
     67     uint32 route_cnt;
     68     uint8  db_type;
     69 } _alpm_pvt_bkt_cnt_t;
     70 
     71 typedef struct _alpm_trv_data_s {
     72     int unit;
     73     int vrf_id;
     74     int ipt;
     75     int err;
     76     _alpm_cb_t *acb;
     77 } _alpm_trv_data_t;
     78 
     79 typedef enum _alpm_lkup_res_e {
     80     ALPM_HIT = 1,           /* Hit */
     81     ALPM_MISS = 2,          /* Miss (Default Miss = 1) */
     82     ALPM_MISS_USE_AD = 3    /* Miss (Default Miss = 0) and use Assoc Data */
     83 } _alpm_lkup_res_t;
     84 
     85 #define VRF_NAME(u, vrf_id) ((vrf_id) == ALPM_VRF_ID_GHI(u) ? "GHi" :    \
     86                              (vrf_id) == ALPM_VRF_ID_GLO(u) ? "GLo" : "")
     87 
     88 #define ALPM_PVT_BKT_CNT_ADD(dst_dc, src_dc)   \
     89     do {                                        \
     90         (dst_dc)->pvt_cnt += (src_dc)->pvt_cnt; \
     91         (dst_dc)->bkt_cnt += (src_dc)->bkt_cnt; \
     92         (dst_dc)->add_cnt += (src_dc)->add_cnt; \
     93         (dst_dc)->del_cnt += (src_dc)->del_cnt; \
     94         (dst_dc)->route_cnt += (src_dc)->route_cnt; \
     95     } while (0)
     96 
     97 #define PRINT_SPLIT_LINE(u)    \
     98     LOG_CLI((BSL_META_U(u, "--------------------------------------------------------\n")))
     99 
    100 #define PRINT_VRF_NOT_FOUND(u) \
    101     LOG_CLI((BSL_META_U(u, "%9s\n"), "Specific VRF not found"))
    102 
    103 #define PRINT_ACB_HEADER(u, i) \
    104     LOG_CLI((BSL_META_U(u, "\n%s\n"), alpm_util_acb_str[(i)]))
    105 
    106 #define PRINT_PVT_BKT_HEADER(u) \
    107    do { \
    108         LOG_CLI((BSL_META_U(u, \
    109                  "\nVRF  PKM     Pivot   Bucket  Add     Delete  |   Comment\n"))); \
    110     } while (0)
    111 
    112 #define PRINT_PVT_BKT_ITEM(u, vrf, ipt, dc) \
    113     do { \
    114         LOG_CLI((BSL_META_U(u, \
    115                  "%-4d %-7s %-7d %-7d %-7d %-7d |   %-7s\n"), (vrf), \
    116                  alpm_util_ipt_str[(ipt)], (dc)->pvt_cnt, (dc)->bkt_cnt, \
    117                  (dc)->add_cnt, (dc)->del_cnt, VRF_NAME((u), (vrf)) )); \
    118     } while (0)
    119 
    120 #define PRINT_PVT_BKT_TOT(u, ipt, all) \
    121     do { \
    122         LOG_CLI((BSL_META_U(u, \
    123                  "Tot  %-7s %-7d %-7d %-7d %-7d |\n"), alpm_util_ipt_str[(ipt)], \
    124                  (all)->pvt_cnt, (all)->bkt_cnt, (all)->add_cnt, (all)->del_cnt)); \
    125     } while (0)
    126 
    127 /* according to ALPMC(u)->_alpm_dbg_info_bmp defines */
    128 char *alpm_dbg_info_str[_ALPM_DBG_INFO_MAX_NUM] = {
    129     "pvt",
    130     "rte",
    131     "cnt",
    132     "hit",
    133 };
    134 
    135 int
    136 alpm_dbg_info_bmp_show(int u)
    137 {
    138     int i;
    139     if (ALPMC(u) == NULL) {
    140         return BCM_E_INIT;
    141     }
    142 
    143     if (ALPMC(u)->_alpm_dbg_info_bmp != 0) {
    144         cli_out("alpm_info_bmp is on:");
    145 
    146         if (ALPMC(u)->_alpm_dbg_info_bmp == _ALPM_DBG_INFO_ALL) {
    147             cli_out(" all -");
    148         }
    149         for (i = 0; i < _ALPM_DBG_INFO_MAX_NUM; i++) {
    150             if (ALPMC(u)->_alpm_dbg_info_bmp & (1 << i)) {
    151                 cli_out(" %s", alpm_dbg_info_str[i]);
    152             }
    153         }
    154         cli_out(".\n");
    155     } else {
    156         cli_out("alpm_info_bmp is off.\n");
    157     }
    158 
    159     return BCM_E_NONE;
    160 
    161 }
    162 
    163 int
    164 alpm_dbg_info_bmp_set(int u, uint32 flags)
    165 {
    166     if (ALPMC(u) == NULL) {
    167         return BCM_E_INIT;
    168     }
    169 
    170     ALPMC(u)->_alpm_dbg_info_bmp = flags;
    171     (void)alpm_dbg_info_bmp_show(u);
    172 
    173     return BCM_E_NONE;
    174 }
    175 
    176 int
    177 alpm_find_best_match(int u, int vrf_id, int pkm, uint32 *sw_key,
    178                      int sw_len, _bcm_defip_cfg_t *lpm_cfg);
    179 
    180 STATIC int
    181 alpm_pvt_bkt_cnt_cb(int u, _alpm_cb_t *acb,
    182                     _alpm_pvt_node_t *pvt_node, void *user_data)
    183 {
    184     _alpm_pvt_bkt_cnt_t *data = (_alpm_pvt_bkt_cnt_t *)user_data;
    185     if (pvt_node->bkt_trie && pvt_node->bkt_trie->trie) {
    186         data->bkt_cnt += pvt_node->bkt_trie->trie->count; /* add bkt cnt */
    187     }
    188     return BCM_E_NONE;
    189 }
    190 
    191 STATIC void
    192 alpm_debug_count_dump(int u, int cb_bmp, int vrf_id, uint32 flags)
    193 {
    194     int found = FALSE;
    195     _alpm_pvt_bkt_cnt_t alpm_dc[ALPM_IPT_CNT];
    196     _alpm_pvt_bkt_cnt_t all_dc[ALPM_IPT_CNT];
    197     int                 i, vrf, ipt;
    198     _alpm_cb_t          *acb;
    199     alpm_lib_trie_t     *pvt_trie;
    200 
    201     for (i = 0; i < ACB_CNT(u); i++) {
    202         if (!(cb_bmp & (1 << i))) {
    203             continue;
    204         }
    205         PRINT_ACB_HEADER(u, i);
    206         PRINT_PVT_BKT_HEADER(u);
    207         PRINT_SPLIT_LINE(u);
    208 
    209         found = FALSE;
    210         acb = ACB(u, i);
    211         sal_memset(&all_dc, 0, sizeof(all_dc));
    212 
    213         for (vrf = 0; vrf <= ALPM_VRF_ID_MAX(u); vrf++) {
    214             if (vrf_id != -1 && vrf_id != vrf) {
    215                 continue;
    216             }
    217             sal_memset(&alpm_dc, 0, sizeof(alpm_dc));
    218 
    219             for (ipt = 0; ipt < ALPM_IPT_CNT; ipt++) {
    220                 if (!ACB_VRF_INITED(u, acb, vrf, ipt)) {
    221                     continue;
    222                 }
    223                 pvt_trie = ACB_PVT_TRIE(acb, vrf, ipt);
    224 
    225                 if ((pvt_trie == NULL) || (pvt_trie->trie == NULL)) {
    226                     continue;
    227                 }
    228                 alpm_dc[ipt].pvt_cnt = pvt_trie->trie->count;
    229                 alpm_dc[ipt].add_cnt = ACB_PVT_CTRL(acb, vrf, ipt).cnt_add;
    230                 alpm_dc[ipt].del_cnt = ACB_PVT_CTRL(acb, vrf, ipt).cnt_del;
    231                 alpm_dc[ipt].route_cnt = ACB_PVT_CTRL(acb, vrf, ipt).route_cnt;
    232                 alpm_dc[ipt].db_type = ACB_PVT_CTRL(acb, vrf, ipt).db_type;
    233 
    234                 (void)bcm_esw_alpm_pvt_traverse(u, i, vrf, ipt,
    235                            alpm_pvt_bkt_cnt_cb, (void *)&alpm_dc[ipt]);
    236                 found = TRUE;
    237 
    238                 if (flags & BCM_ALPM_DEBUG_SHOW_FLAG_BKT) {
    239                     PRINT_PVT_BKT_ITEM(u, vrf, ipt, &alpm_dc[ipt]);
    240                 }
    241                 ALPM_PVT_BKT_CNT_ADD(&all_dc[ipt], &alpm_dc[ipt]);
    242             }
    243         }
    244 
    245         if (found == FALSE) {
    246             PRINT_VRF_NOT_FOUND(u);
    247         } else {
    248             PRINT_SPLIT_LINE(u);
    249             for (ipt = 0; ipt < ALPM_IPT_CNT; ipt++) {
    250                 PRINT_PVT_BKT_TOT(u, ipt, &all_dc[ipt]);
    251             }
    252         }
    253     }
    254 }
    255 
    256 STATIC int
    257 alpm_pfx_debug_cb(_alpm_pfx_node_t *pfx_node, void *user_data)
    258 {
    259     _alpm_trv_data_t *trv_data = (_alpm_trv_data_t *)user_data;
    260     char ip_buf[IP6ADDR_STR_LEN];
    261     int u = trv_data->unit;
    262     int ipt = trv_data->ipt;
    263     /*int vrf_id = trv_data->vrf_id;*/
    264     _alpm_bkt_node_t *bkt_node = pfx_node->bkt_ptr;
    265     int idx, ent;
    266     _bcm_defip_cfg_t lpm_cfg;
    267 
    268     if (bkt_node == NULL) {
    269         /* VRF global low "virtual def rte" without true bucket */
    270         /* ALPM_INFO((" **PFX %p w/o BKT: Sublen:%d\n",
    271                    pfx_node, pfx_node->key_len)); */
    272         return BCM_E_NONE;
    273     }
    274 
    275     idx = ALPM_TAB_IDX_GET(bkt_node->ent_idx);
    276     ent = ALPM_IDX_TO_ENT(bkt_node->ent_idx);
    277     sal_memset(&lpm_cfg, 0, sizeof(lpm_cfg));
    278 
    279     /* defip_flags */
    280     if (ALPM_IS_IPV6(ipt)) {
    281         lpm_cfg.defip_flags |= BCM_L3_IP6;
    282     }
    283 
    284     /* Key & Length (lpm_cfg.user_data will be used in _alpm_find()) */
    285     alpm_trie_pfx_to_cfg(u, bkt_node->key, bkt_node->key_len, &lpm_cfg);
    286 
    287     if (ALPM_IS_IPV4(ipt)) {
    288         alpm_util_fmt_ipaddr(ip_buf, lpm_cfg.defip_ip_addr);
    289     } else {
    290         alpm_util_fmt_ip6addr(ip_buf, lpm_cfg.defip_ip6_addr);
    291     }
    292 
    293     if (bkt_node->key_len != pfx_node->key_len) {
    294         ALPM_INFO((" **PFX %p->BKT %p: idx:%d.%d Sublen:%d Dest:%d IP:%s"
    295                    " Error=(bkt_keylen:%d)\n",
    296                    pfx_node, bkt_node, idx, ent, pfx_node->key_len,
    297                    bkt_node->adata.defip_ecmp_index, ip_buf,
    298                    bkt_node->key_len));
    299     } else {
    300         ALPM_INFO((" **PFX %p->BKT %p: idx:%d.%d Sublen:%d Dest:%d IP:%s\n",
    301                    pfx_node, bkt_node, idx, ent, pfx_node->key_len,
    302                    bkt_node->adata.defip_ecmp_index, ip_buf));
    303     }
    304 
    305     return BCM_E_NONE;
    306 }
    307 
    308 STATIC int
    309 alpm_bkt_debug_cb(_alpm_bkt_node_t *bkt_node, void *user_data)
    310 {
    311     _alpm_trv_data_t *trv_data = (_alpm_trv_data_t *)user_data;
    312     char ip_buf[IP6ADDR_STR_LEN];
    313     int u = trv_data->unit;
    314     int ipt = trv_data->ipt;
    315     /*int vrf_id = trv_data->vrf_id;*/
    316     int idx = ALPM_TAB_IDX_GET(bkt_node->ent_idx);
    317     int ent = ALPM_IDX_TO_ENT(bkt_node->ent_idx);
    318     _bcm_defip_cfg_t lpm_cfg;
    319 
    320     sal_memset(&lpm_cfg, 0, sizeof(lpm_cfg));
    321 
    322     /* defip_flags */
    323     if (ALPM_IS_IPV6(ipt)) {
    324         lpm_cfg.defip_flags |= BCM_L3_IP6;
    325     }
    326 
    327     /* Key & Length (lpm_cfg.user_data will be used in _alpm_find()) */
    328     alpm_trie_pfx_to_cfg(u, bkt_node->key, bkt_node->key_len, &lpm_cfg);
    329 
    330     if (ALPM_IS_IPV4(ipt)) {
    331         alpm_util_fmt_ipaddr(ip_buf, lpm_cfg.defip_ip_addr);
    332     } else {
    333         alpm_util_fmt_ip6addr(ip_buf, lpm_cfg.defip_ip6_addr);
    334     }
    335 
    336     ALPM_INFO(("  >BKT %p: idx:%d.%d Sublen:%d Dest:%d IP:%s\n",
    337                bkt_node, idx, ent, bkt_node->key_len,
    338                bkt_node->adata.defip_ecmp_index, ip_buf));
    339 
    340     return BCM_E_NONE;
    341 }
    342 
    343 STATIC int
    344 alpm_pvt_node_dbg(int u, _alpm_cb_t *acb, _alpm_pvt_node_t *pvt_node,
    345                   _alpm_trv_data_t *trv_data)
    346 {
    347     char ip_buf[IP6ADDR_STR_LEN];
    348     int ipt = PVT_BKT_IPT(pvt_node);
    349     int vrf_id = PVT_BKT_VRF(pvt_node);
    350     int idx, sub_idx;
    351     int rv = BCM_E_NONE;
    352     _bcm_defip_cfg_t lpm_cfg;
    353 
    354     sal_memset(&lpm_cfg, 0, sizeof(lpm_cfg));
    355 
    356     /* defip_flags */
    357     if (ALPM_IS_IPV6(ipt)) {
    358         lpm_cfg.defip_flags |= BCM_L3_IP6;
    359     }
    360 
    361     if ((ipt != trv_data->ipt) ||
    362         (vrf_id != trv_data->vrf_id)) {
    363         rv = BCM_E_INTERNAL;
    364     }
    365 
    366     /* Key & Length (lpm_cfg.user_data will be used in _alpm_find()) */
    367     alpm_trie_pfx_to_cfg(u, pvt_node->key, pvt_node->key_len, &lpm_cfg);
    368 
    369     if (ALPM_IS_IPV4(ipt)) {
    370         alpm_util_fmt_ipaddr(ip_buf, lpm_cfg.defip_ip_addr);
    371     } else {
    372         alpm_util_fmt_ip6addr(ip_buf, lpm_cfg.defip_ip6_addr);
    373     }
    374 
    375     ALPM_IER(alpm_util_pvt_idx_get(u, acb, pvt_node, &idx, &sub_idx));
    376 
    377     if (PVT_BKT_TRIE(pvt_node) == NULL) {
    378         if (BCM_SUCCESS(rv)) {
    379             ALPM_INFO(("L%d PVT %p->BKT %p: idx:%d.%d Sublen:%d IP:%s w/o bkt\n",
    380                        ACB_IDX(acb)+1, pvt_node, PVT_BKT_DEF(pvt_node),
    381                        idx, sub_idx, pvt_node->key_len, ip_buf));
    382         } else {
    383             ALPM_ERR(("L%d PVT %p->BKT %p: idx:%d.%d Sublen:%d IP:%s w/o bkt"
    384                       " Error=(VRF:%d IPT:%d)\n",
    385                       ACB_IDX(acb)+1, pvt_node, PVT_BKT_DEF(pvt_node),
    386                       idx, sub_idx, pvt_node->key_len, ip_buf,
    387                       vrf_id, ipt));
    388         }
    389     } else if (PVT_BKT_DEF(pvt_node) == NULL) {
    390         if (BCM_SUCCESS(rv)) {
    391             ALPM_INFO(("\nL%d PVT %p->BKT %p: idx:%d.%d Sublen:%d IP:%s w/o def_rte\n",
    392                        ACB_IDX(acb)+1, pvt_node, PVT_BKT_DEF(pvt_node),
    393                        idx, sub_idx, pvt_node->key_len, ip_buf));
    394         } else {
    395             ALPM_ERR(("\nL%d PVT %p->BKT %p: idx:%d.%d Sublen:%d IP:%s w/o def_rte"
    396                       " Error=(VRF:%d IPT:%d)\n",
    397                       ACB_IDX(acb)+1, pvt_node, PVT_BKT_DEF(pvt_node),
    398                       idx, sub_idx, pvt_node->key_len, ip_buf,
    399                       vrf_id, ipt));
    400         }
    401     } else {
    402         if (BCM_SUCCESS(rv)) {
    403             ALPM_INFO(("\nL%d PVT %p->BKT %p: idx:%d.%d Sublen:%d bpmDest:%d IP:%s\n",
    404                        ACB_IDX(acb)+1, pvt_node, PVT_BKT_DEF(pvt_node),
    405                        idx, sub_idx, pvt_node->key_len,
    406                        PVT_BKT_DEF(pvt_node)->adata.defip_ecmp_index, ip_buf));
    407         } else {
    408             ALPM_ERR(("\nL%d PVT %p->BKT %p: idx:%d.%d Sublen:%d bpmDest:%d IP:%s"
    409                       " Error=(VRF:%d IPT:%d)\n",
    410                       ACB_IDX(acb)+1, pvt_node, PVT_BKT_DEF(pvt_node),
    411                       idx, sub_idx, pvt_node->key_len,
    412                       PVT_BKT_DEF(pvt_node)->adata.defip_ecmp_index, ip_buf,
    413                       vrf_id, ipt));
    414         }
    415     }
    416 
    417     return rv;
    418 }
    419 
    420 STATIC int
    421 alpm_pvt_debug_cb(int u, _alpm_cb_t *acb,
    422                   _alpm_pvt_node_t *pvt_node, void *user_data)
    423 {
    424     _alpm_trv_data_t *trv_data = (_alpm_trv_data_t *)user_data;
    425 
    426     alpm_pvt_node_dbg(u, acb, pvt_node, trv_data);
    427 
    428     if (PVT_BKT_TRIE(pvt_node)) {
    429         bcm_esw_alpm_bkt_traverse(pvt_node->bkt_trie,
    430                                   alpm_bkt_debug_cb, trv_data);
    431     }
    432     return BCM_E_NONE;
    433 }
    434 
    435 STATIC void
    436 alpm_trie_debug_dump(int u, int cb_bmp, int vrf_id)
    437 {
    438     int         i, vrf, ipt;
    439     _alpm_cb_t  *acb;
    440     _alpm_trv_data_t trv_data;
    441 
    442     trv_data.unit = u;
    443     for (i = 0; i < ACB_CNT(u); i++) {
    444         if (!(cb_bmp & (1 << i))) {
    445             continue;
    446         }
    447         acb = ACB(u, i);
    448         trv_data.acb = acb;
    449 
    450         for (vrf = 0; vrf <= ALPM_VRF_ID_MAX(u); vrf++) {
    451             if (vrf_id != -1 && vrf_id != vrf) {
    452                 continue;
    453             }
    454             trv_data.vrf_id = vrf;
    455 
    456             for (ipt = 0; ipt < ALPM_IPT_CNT; ipt++) {
    457                 if (!ACB_VRF_INITED(u, acb, vrf, ipt)) {
    458                     continue;
    459                 }
    460                 trv_data.ipt = ipt;
    461                 ALPM_INFO(("\n%s VRF:%d IPT:%s\n",
    462                            alpm_util_acb_str[i], vrf, alpm_util_ipt_str[ipt]));
    463                 (void)bcm_esw_alpm_pvt_traverse(u, i, vrf, ipt,
    464                                                 alpm_pvt_debug_cb, &trv_data);
    465 
    466                 if (ACB_HAS_RTE(acb, vrf)) {
    467                     ALPM_INFO(("\n"));
    468                     (void)bcm_esw_alpm_pfx_traverse(u, vrf, ipt,
    469                                                     alpm_pfx_debug_cb, &trv_data);
    470                 }
    471             }
    472         }
    473     }
    474 }
    475 
    476 /*
    477  * Function:
    478  *      bcm_esw_alpm_debug_show
    479  * Purpose:
    480  *      Show ALPM Sw counters for all levels per VRF.
    481  *      Detail debug info will be dumped if "debug bcm alpm".
    482  * Parameters:
    483  *      u        - (In)Device unit
    484  *      vrf_id   - (In)Show for a specific VRF ID, -1 for all VRFs.
    485  *      flags    - (In)Show flags or all.
    486  * Returns:
    487  *      BCM_E_XXX
    488  */
    489 int
    490 bcm_esw_alpm_debug_show(int u, int vrf_id, uint32 flags)
    491 {
    492     int rv = BCM_E_NONE;
    493 
    494     if (ALPMC(u) == NULL) {
    495         return BCM_E_INIT;
    496     }
    497 
    498     if ((vrf_id > ALPM_VRF_ID_MAX(u)) || !flags) {
    499         return BCM_E_PARAM;
    500     }
    501 
    502     if (flags & (BCM_ALPM_DEBUG_SHOW_FLAG_CNT | BCM_ALPM_DEBUG_SHOW_FLAG_BKT)) {
    503         alpm_debug_count_dump(u, ALPM_CB_ALL_BMP, vrf_id, flags);
    504     }
    505 
    506     if (flags & (BCM_ALPM_DEBUG_SHOW_FLAG_INTDBG)) {
    507         alpm_trie_debug_dump(u, ALPM_CB_ALL_BMP, vrf_id);
    508     }
    509 
    510     return rv;
    511 }
    512 /*
    513  * Function:
    514  *      alpm_cb_dbg_process
    515  * Purpose:
    516  *      ALPM control block (level) debug process.
    517  *      It's recursive from top to bottom.
    518  *      Get ALPM data and info from Hw mem at this level.
    519  * Parameters:
    520  *      u        - (In)Device unit
    521  *      vrf_id   - (In)VRF ID
    522  *      pkm      - (In)PKM
    523  *      acb      - (In)ALPM control block
    524  *      fent     - (In)ALPM_DATA entry
    525  *      pvtfmt   - (In)Pivot bank format (ignored for TCAM)
    526  *      key      - (In)Key prefix
    527  *      key_len  - (In)Key prefix length
    528  *      idx      - (In)Memory Index
    529  *      sub_idx  - (In)Memory sub_idx (for half-entry) or ent index
    530  *      adata    - (In)Assoc Data structure pointer
    531  *      dp       - (In/Out)Carrying debug counters
    532  * Returns:
    533  *      BCM_E_XXX
    534  */
    535 STATIC int
    536 alpm_cb_dbg_process(int u, int vrf_id, int pkm, _alpm_cb_t *acb, void *fent,
    537                     int pvtfmt, uint32 *key, int key_len, int idx, int sub_idx,
    538                     _alpm_bkt_adata_t *adata, _alpm_dbg_data_t *dp)
    539 {
    540     uint32 bkt_entry[ALPM_MEM_ENT_MAX];
    541     uint32 fent1[ALPM_MEM_ENT_MAX];
    542     uint32 ftmp[ALPM_MEM_ENT_MAX];
    543     uint32 new_key[4];
    544     uint32 fmt, valid;
    545     int sublen, new_len, def_miss;
    546     int idx1, eid, bnk;
    547     _alpm_bkt_adata_t adata1;
    548     _alpm_bkt_info_t bkt_info;
    549     char ip_buf[IP6ADDR_STR_LEN];
    550     _bcm_defip_cfg_t lpm_cfg;
    551     _alpm_tbl_t bkt_tbl;
    552     _alpm_tbl_t pvt_tbl;
    553     int ipt;
    554 
    555     if (ACB_IDX(acb) >= ACB_CNT(u)) {
    556         return BCM_E_INTERNAL; /* wrong ALPM control level called */
    557     }
    558 
    559     ipt = ALPM_PKM2IPT(pkm);
    560     bkt_tbl = ACB_BKT_TBL(acb, vrf_id);
    561     pvt_tbl = (ACB_HAS_TCAM(acb) ? acb->pvt_tbl[pkm] :
    562                 ACB_BKT_TBL(ACB_UPR(u, acb), vrf_id));
    563 
    564     /**** Pivot level ****/
    565     alpm_util_bkt_info_get(u, vrf_id, ipt, pkm, acb, fent, sub_idx,
    566                            &bkt_info, &sublen, &def_miss);
    567 
    568     /* kshift must be same as previous key_len */
    569     if (!ACB_BKT_FIXED_FMT(acb, 1) && sublen != key_len) {
    570         ALPM_ERR(("%s: ALPM_DATA invalid kshift:%d vs pivot len:%d"
    571                   " idx:%d.%d (%d)\n", ALPM_TBL_NAME(pvt_tbl), sublen,
    572                   key_len, idx, sub_idx, BI_BKT_IDX(&bkt_info)));
    573         return BCM_E_NONE; /* just skip the pivot */
    574     }
    575     if (BI_BKT_IDX(&bkt_info) >= ACB_BKT_CNT(acb)) {
    576         ALPM_ERR(("%s: ALPM_DATA invalid bkt_ptr idx:%d.%d (%d)\n",
    577                   ALPM_TBL_NAME(pvt_tbl), idx, sub_idx, BI_BKT_IDX(&bkt_info)));
    578         return BCM_E_NONE; /* just skip the pivot */
    579     }
    580     dp->dc[ACB_IDX(acb)].pvt_used[pkm]++;
    581     dp->bktref[ACB_IDX(acb)][BI_BKT_IDX(&bkt_info)]++;
    582     if (ALPMC(u)->_alpm_dbg_info_bmp & _ALPM_DBG_INFO_PVT) {
    583         alpm_util_cfg_construct(u, vrf_id, ipt, key, key_len, adata, &lpm_cfg);
    584         if (ALPM_IS_IPV4(ipt)) {
    585             alpm_util_fmt_ipaddr(ip_buf, lpm_cfg.defip_ip_addr);
    586         } else {
    587             alpm_util_fmt_ip6addr(ip_buf, lpm_cfg.defip_ip6_addr);
    588         }
    589         if (ACB_HAS_TCAM(acb)) {
    590             ALPM_INFO(("VRF:%d PKM:%s %s: idx:%d.%d Sublen:%d bpmDest:%d IP:%s\n",
    591                        vrf_id, alpm_util_pkm_str[pkm], ALPM_TBL_NAME(pvt_tbl),
    592                        idx, sub_idx, key_len,
    593                        adata->defip_ecmp_index, ip_buf));
    594         } else {
    595             ALPM_INFO(("VRF:%d PKM:%s %s: idx:%d.%d Sublen:%d fmt:%d bpmDest:%d IP:%s\n",
    596                        vrf_id, alpm_util_pkm_str[pkm], ALPM_TBL_NAME(pvt_tbl),
    597                        idx, sub_idx, key_len, pvtfmt,
    598                        adata->defip_ecmp_index, ip_buf));
    599         }
    600     }
    601 
    602     for (bnk = 0; bnk < ACB_BNK_PER_BKT(acb, vrf_id); bnk++) {
    603         fmt = bkt_info.bnk_fmt[bnk];
    604         if ((fmt == 0) || (fmt > ACB_FMT_CNT(acb, vrf_id))) {
    605             if (fmt > ACB_FMT_CNT(acb, vrf_id)) {
    606                 ALPM_ERR(("%s: ALPM_DATA format wrong idx:%d.%d (bank=%d fmt=%d).\n",
    607                           ALPM_TBL_NAME(pvt_tbl), idx, sub_idx, bnk, fmt));
    608             }
    609             continue;
    610         }
    611         dp->dc[ACB_IDX(acb)].bank_used++;
    612 
    613         /**** Bucket Level ****/
    614         idx1 = ALPM_TAB_IDX_GET_BKT_BNK(acb, BI_ROFS(&bkt_info), BI_BKT_IDX(&bkt_info), bnk);
    615         ALPM_IER(alpm_bkt_entry_read(u, ACB_BKT_TBL(acb, vrf_id),
    616                                      acb, bkt_entry, idx1));
    617 
    618         for (eid = 0; eid < ACB_FMT_ENT_MAX(acb, vrf_id, fmt); eid++) {
    619             uint32 key2[4] = {0};
    620             int len2 = 0;
    621             int sub_bkt_ptr = 0;
    622 
    623             /* process bucket entry Prefix */
    624             alpm_util_ent_ent_get(u, vrf_id, acb, bkt_entry, fmt, eid, ftmp);
    625             alpm_util_bkt_pfx_get(u, vrf_id, acb, ftmp, fmt, key2, &len2, &valid);
    626             alpm_util_bkt_adata_get(u, vrf_id, ipt, acb, ftmp, fmt, &adata1, &sub_bkt_ptr);
    627 
    628             if (!valid || BI_SUB_BKT_IDX(&bkt_info) != sub_bkt_ptr) {
    629                 continue;
    630             } else {
    631                 if (ACB_BKT_FIXED_FMT(acb, 1)) {
    632                     new_len = len2;
    633                     sal_memcpy(new_key, key2, sizeof(new_key));
    634                 } else {
    635                     alpm_util_pfx_cat(u, ipt, key, sublen, key2, len2, new_key, &new_len);
    636                 }
    637             }
    638 
    639             /* process bucket entry ASSOC_DATA */
    640             dp->dc[ACB_IDX(acb)].ent_used[pkm]++;
    641 
    642             /* end recursion here if reach to route level (last level) */
    643             if (ACB_HAS_RTE(acb, vrf_id)) {
    644                 dp->route_cnt++;
    645                 if (ALPMC(u)->_alpm_dbg_info_bmp & _ALPM_DBG_INFO_RTE) {
    646                     alpm_util_cfg_construct(u, vrf_id, ipt, new_key, new_len,
    647                                             &adata1, &lpm_cfg);
    648                     if (ALPM_IS_IPV4(ipt)) {
    649                         alpm_util_fmt_ipaddr(ip_buf, lpm_cfg.defip_ip_addr);
    650                     } else {
    651                         alpm_util_fmt_ip6addr(ip_buf, lpm_cfg.defip_ip6_addr);
    652                     }
    653 
    654                     if (!ALPM_HIT_SKIP(u)) {
    655                         int hit_val;
    656                         ALPM_HIT_LOCK(u);
    657                         hit_val = alpm_rte_hit_get(u, vrf_id, bkt_tbl, idx1, eid);
    658                         ALPM_HIT_UNLOCK(u);
    659 
    660                         if (hit_val > 0) {
    661                             dp->hit_cnt++;
    662                             ALPM_INFO(("! "));
    663                         }
    664                     }
    665                     ALPM_INFO(("VRF:%d PKM:%s %s: Route idx:%d.%d Sublen:%d"
    666                                " fmt:%d Dest:%d IP:%s\n",
    667                                vrf_id, alpm_util_pkm_str[pkm],
    668                                ALPM_TBL_NAME(bkt_tbl),
    669                                idx1, eid,
    670                                new_len, fmt, adata1.defip_ecmp_index, ip_buf));
    671                 }
    672                 continue;
    673             }
    674 
    675             /* prevent going further down if somehow last level is not
    676                Route level due to internal failure */
    677             if ((ACB_IDX(acb) + 1) >= ACB_CNT(u)) {
    678                 return BCM_E_INTERNAL;
    679             }
    680 
    681             /* get ALPM Data entry ready for next level */
    682             alpm_util_ent_data_get(u, vrf_id, ipt, acb, ftmp, fmt, fent1);
    683             ALPM_IER(alpm_cb_dbg_process(u, vrf_id, ipt, ACB_DWN(u, acb),
    684                         fent1, fmt, new_key, new_len, idx1, eid, &adata1, dp));
    685         } /* for ent */
    686     } /* for bnk */
    687 
    688     return BCM_E_NONE;
    689 }
    690 
    691 /*
    692  * Function:
    693  *      bcm_esw_alpm_debug_brief_show
    694  * Purpose:
    695  *      Show ALPM Hw mem debug information and counters.
    696  *      Process all ALPM levels from top to bottom.
    697  *      Detail debug info will be dumped if "debug bcm alpm".
    698  * Parameters:
    699  *      u        - (In)Device unit
    700  *      phy_bkt  - (In)Physical bucket (not in used)
    701  *      index    - (In)Memory index (not in used)
    702  * Returns:
    703  *      BCM_E_XXX
    704  */
    705 int
    706 bcm_esw_alpm_debug_brief_show(int u, int phy_bkt, int index)
    707 {
    708     int ipv6, key_mode;
    709     int idx, sub_idx;
    710     int vrf_id;
    711     int idx_end;
    712     int step_size;
    713     int rv = BCM_E_NONE;
    714     int rv_tcam;
    715     uint32 lpm_entry[ALPM_MEM_ENT_MAX];
    716     uint32 fent[ALPM_MEM_ENT_MAX];
    717     _bcm_defip_cfg_t lpm_cfg;
    718     _alpm_cb_t *acb;
    719     _alpm_bkt_adata_t adata0;
    720     int pk, pkm, use_alpm;
    721     uint32 key[4];
    722     int ipt, key_pfx_len;
    723     int i, j, bit128, pid, alloc_sz, k, ent_used_tot;
    724     uint32 glb_hi_cnt = 0, glb_lo_cnt = 0; /* TCAM direct routes */
    725     _alpm_dbg_data_t dbg[ALPM_BKT_PID_CNT]; /* per Private and Global */
    726     _alpm_dbg_data_t *dp;
    727     _alpm_bkt_pool_conf_t *bp_conf;
    728     char ip_buf[IP6ADDR_STR_LEN];
    729     char *lvl_str[] = {
    730         "2-Level",
    731         "3-Level"
    732     };
    733     char *mode_str[] = {
    734         "ALPM-Combined",
    735         "ALPM-Parallel",
    736         "ALPM-TCAM_ALPM"
    737     };
    738 #if defined(BCM_TRIDENT3_SUPPORT)
    739     uint32 urpf, alpm, fv, rval;
    740     uint32 mode = 0;
    741     uint32 bnkbits = 0;
    742     char *dw_str = "Double Wide";
    743     char *sw_str = "Single Wide";
    744     char *ipver_str[] = {
    745         "IPv4",
    746         "IPv6-64",
    747         "IPv6-128",
    748         "IPv4-1",
    749         "IPv6-64-1"
    750     };
    751     uint32 fmt_ent_max[] = {
    752         6,
    753         3,
    754         2,
    755         4,
    756         3
    757     };
    758 #endif
    759 
    760     if (ALPMC(u) == NULL) {
    761         return BCM_E_INIT;
    762     }
    763 
    764     for (i = 0; i < ACB_CNT(u); i++) {
    765         acb = ACB(u, i);
    766 
    767         for (pid = 0; pid < ALPM_BKT_PID_CNT; pid++) {
    768             bp_conf = ACB_BKT_POOL(acb, pid);
    769             if (pid > 0 && bp_conf == ACB_BKT_POOL(acb, pid - 1)) {
    770                 continue; /* Combined Mode uses PID=0 only for dbg counters */
    771             }
    772 
    773             dp = &dbg[pid];
    774             dp->route_cnt = 0;
    775             dp->hit_cnt = 0;
    776             sal_memset(&dp->dc[i], 0, sizeof(_alpm_dbgcnt_t));
    777             dp->dc[i].bucket_max = ACB_BKT_CNT(acb);
    778             dp->dc[i].bank_max = BPC_BNK_CNT(bp_conf);
    779             dp->dc[i].ent_max = dp->dc[i].bank_max * BPC_FMT_ENT_MAX(bp_conf, 1);
    780             alloc_sz = dp->dc[i].bucket_max * sizeof(int);
    781             ALPM_ALLOC_EG(dp->bktref[i], alloc_sz, "bktref");
    782 
    783             /* Calculate maximum pivot supported (only useful for TCAM level) */
    784             if (ACB_HAS_TCAM(acb)) {
    785                 for (pkm = 0; pkm < ALPM_PKM_CNT; pkm++) {
    786                     dp->dc[i].pvt_max[pkm] =
    787                        (pkm == ALPM_PKM_32B ? 2 : 1) * tcam_table_size(u, pkm);
    788                 }
    789             }
    790         }
    791     }
    792 
    793     acb = ACB_TOP(u); /* from top to bottom */
    794 
    795     for (pk = 0; pk < ALPM_PKM_CNT; pk++) {
    796         if (ALPM_TCAM_TBL_SKIP(u, pk)) {
    797             continue; /* skip duplicated or invalid TCAM table */
    798         }
    799 
    800         idx_end = tcam_table_size(u, pk);
    801         /* Walk all TCAM entries */
    802         for (idx = 0; idx < idx_end; idx++) {
    803             ALPM_IEG(tcam_entry_read(u, pk, lpm_entry, idx, idx));
    804 
    805             for (sub_idx = 0; sub_idx < ALPM_TCAM_SUBCNT; sub_idx += step_size) {
    806                 rv_tcam = tcam_valid_entry_mode_get(u, pk, lpm_entry,
    807                               &step_size, &pkm, &ipv6, &key_mode, sub_idx);
    808                 if (BCM_FAILURE(rv_tcam)) {
    809                     if (rv_tcam == BCM_E_INTERNAL) {
    810                         ALPM_ERR(("%s: Invalid Key Mode:%d or Key Type (IPv6):%d"
    811                                   " in idx:%d.%d\n",
    812                           TCAM_TBL_NAME(acb, pk), key_mode, ipv6, idx, sub_idx));
    813                     }
    814                     continue;
    815                 }
    816                 ipt = ALPM_PKM2IPT(pkm);
    817                 tcam_entry_vrf_id_get(u, pkm, lpm_entry, sub_idx, &vrf_id);
    818 
    819                 /* Combined Mode uses PID=0 only for dbg counters */
    820                 pid = ACB_BKT_VRF_PID(acb, vrf_id);
    821                 dp = &dbg[pid];
    822                 if (vrf_id == ALPM_VRF_ID_GHI(u)) {
    823                     glb_hi_cnt++;
    824                 } else if (vrf_id == ALPM_VRF_ID_GLO(u)) {
    825                     glb_lo_cnt++;
    826                 }
    827 
    828                 /* Get Pre-pivot key IP_ADDR and prefix length (mask) */
    829                 sal_memset(key, 0, sizeof(key));
    830                 key_pfx_len = 0;
    831                 tcam_entry_to_key(u, pkm, lpm_entry, sub_idx, key);
    832                 tcam_entry_pfx_len_get(u, pkm, lpm_entry, sub_idx, &key_pfx_len);
    833 
    834                 /* process pre-pivor ASSOC_DATA */
    835                 tcam_entry_adata_get(u, pkm, lpm_entry, sub_idx, &adata0);
    836                 use_alpm = !(adata0.defip_flags & BCM_L3_IPMC) &&
    837                            ALPM_VRF_ID_HAS_BKT(u, vrf_id);
    838 
    839                 /* VRF_OVERRIDE (Global High) entries, and IP multicast prefix
    840                  * resides in TCAM */
    841                 if (!use_alpm) {
    842                     dp->route_cnt++;
    843                     if (ALPMC(u)->_alpm_dbg_info_bmp &
    844                         (_ALPM_DBG_INFO_PVT | _ALPM_DBG_INFO_RTE)) {
    845                         alpm_util_cfg_construct(u, vrf_id, ipt, key, key_pfx_len,
    846                                                 &adata0, &lpm_cfg);
    847                         if (ALPM_IS_IPV4(ipt)) {
    848                             alpm_util_fmt_ipaddr(ip_buf, lpm_cfg.defip_ip_addr);
    849                         } else {
    850                             alpm_util_fmt_ip6addr(ip_buf, lpm_cfg.defip_ip6_addr);
    851                         }
    852 
    853                         if (!ALPM_HIT_SKIP(u) &&
    854                             tcam_entry_hit_get(u, pkm, lpm_entry, sub_idx)) {
    855                             dp->hit_cnt++;
    856                             ALPM_INFO(("! "));
    857                         }
    858 
    859                         ALPM_INFO(("VRF:%d PKM:%s TCAM: Direct Route"
    860                                    " idx:%d.%d Sublen:%d Dest:%d IP:%s\n",
    861                                    vrf_id, alpm_util_pkm_str[pkm], idx, sub_idx, key_pfx_len,
    862                                    adata0.defip_ecmp_index, ip_buf));
    863                     }
    864                     continue;
    865                 }
    866 
    867                 if (ALPMC(u)->_alpm_dbg_info_bmp &
    868                     (_ALPM_DBG_INFO_PVT | _ALPM_DBG_INFO_RTE)) {
    869                     ALPM_INFO(("\n"));
    870                 }
    871 
    872                 /* process ALPM_DATA level recursively from top to bottom */
    873                 tcam_entry_bdata_get(u, pkm, lpm_entry, sub_idx, fent);
    874 
    875                 ALPM_IEG(alpm_cb_dbg_process(u, vrf_id, pkm, acb, fent, 0,
    876                               key, key_pfx_len, idx, sub_idx, &adata0, dp));
    877 
    878             } /* for sub_idx */
    879         } /* for idx */
    880     } /* for pk */
    881 
    882     if (ALPMC(u)->_alpm_dbg_info_bmp & _ALPM_DBG_INFO_CNT) {
    883         bit128 = !!tcam_table_size(u, ALPM_PKM_128);
    884         /* count bkt sharing */
    885         for (i = 0; i < ACB_CNT(u); i++) {
    886             acb = ACB(u, i);
    887             for (pid = 0; pid < ALPM_BKT_PID_CNT; pid++) {
    888                 bp_conf = ACB_BKT_POOL(acb, pid);
    889                 if (pid > 0 && bp_conf == ACB_BKT_POOL(acb, pid - 1)) {
    890                     continue; /* Combined Mode uses PID=0 only */
    891                 }
    892                 dp = &dbg[pid];
    893                 for (j = 0; j < dp->dc[i].bucket_max; j++) {
    894                     if (dp->bktref[i][j] != 0) {
    895                         dp->dc[i].bucket_used++;
    896                     }
    897 
    898                     for (k = 0; k < ALPM_BPB_MAX; k++) {
    899                         if (dp->bktref[i][j] == (k+1)) {
    900                             dp->dc[i].bs[k]++;
    901                         }
    902                     }
    903                 }
    904             }
    905         }
    906 
    907         LOG_CLI(("\n"));
    908         LOG_CLI(("%-24s%s %s\n", "Mode:",
    909                  lvl_str[ACB_CNT(u) - 1], mode_str[ALPM_MODE(u)]));
    910         LOG_CLI(("%-24s%d\n", "IPv6 Bits:", bit128 ? 128 : 64));
    911 
    912 #if defined(BCM_TRIDENT3_SUPPORT)
    913         if (SOC_IS_TRIDENT3X(u)) { /* for TD3X specific only */
    914             urpf = SOC_URPF_STATUS_GET(u);
    915             LOG_CLI(("%-24s%s\n", "uRPF:", urpf ? "Enable" : "Disable"));
    916             for (i = 0; i < 5; i++) {
    917                 LOG_CLI(("%-24s%s | %2d EPBkt | %2d EPBnk\n",
    918                     ipver_str[i],
    919                     ACB_BKT_DW(acb) ? dw_str : sw_str,
    920                     (fmt_ent_max[i] * ACB_PHY_BNK_PER_BKT(acb)) << ACB_BKT_DW(acb),
    921                     fmt_ent_max[i]));
    922             }
    923             LOG_CLI(("\n"));
    924             LOG_CLI(("HW Status:\n"));
    925             SOC_IF_ERROR_RETURN(READ_L3_DEFIP_RPF_CONTROLr(u, &rval));
    926             alpm = soc_reg_field_get(u, L3_DEFIP_RPF_CONTROLr, rval, LPM_MODEf);
    927             if (alpm != 0) {
    928                 mode = soc_reg_field_get(u, L3_DEFIP_RPF_CONTROLr, rval, LOOKUP_MODEf);
    929             }
    930             urpf = soc_reg_field_get(u, L3_DEFIP_RPF_CONTROLr, rval, DEFIP_RPF_ENABLEf);
    931             LOG_CLI(("\n"));
    932             LOG_CLI(("%-24s%s\n", "Mode:", mode_str[mode]));
    933             bit128 = !!soc_mem_index_count(u, L3_DEFIP_PAIR_128m);
    934             LOG_CLI(("%-24s%d\n", "IPv6 Bits:", bit128 ? 128 : 64));
    935                 LOG_CLI(("%-24s%s\n", "uRPF:", urpf ? "Enable" : "Disable"));
    936                 if (alpm == 0) {
    937                 return SOC_E_NONE;
    938             }
    939             if (mode == 0 && !urpf) {       /* Combined mode && uRPF */
    940                 fv = 1;
    941             } else if (mode == 2) {         /* TCAM/ALPM mode */
    942                 fv = 1;
    943             } else {                        /* Parallel mode */
    944                 fv = 0;
    945             }
    946             LOG_CLI(("%-24s%s\n", "IPv4:", fv ? dw_str : sw_str));
    947             if (mode == 0 && !urpf) {       /* Combined mode && uRPF */
    948                 fv = 1;
    949             } else if (mode == 2) {         /* TCAM/ALPM mode */
    950                 fv = 1;
    951             } else {                        /* Parallel mode */
    952                 fv = 0;
    953             }
    954             LOG_CLI(("%-24s%s\n", "IPv6-64:", fv ? dw_str : sw_str));
    955             LOG_CLI(("%-24s%s\n", "IPv6-128:", fv ? dw_str : sw_str));
    956             if (SOC_REG_IS_VALID(u, ISS_LOG_TO_PHY_BANK_MAP_2r)) {
    957                 SOC_IF_ERROR_RETURN(READ_ISS_LOG_TO_PHY_BANK_MAP_2r(u, &rval));
    958                 bnkbits = soc_reg_field_get(u, ISS_LOG_TO_PHY_BANK_MAP_2r, rval,
    959                                             ALPM_BANK_MODEf);
    960             }
    961             LOG_CLI(("%-24s%d\n", "Num Banks:", bnkbits == 0 ? 8 : 4));
    962         }
    963 #endif
    964         LOG_CLI(("%-24s%s\n", "Bucket sharing:", "Enable"));
    965         LOG_CLI(("%-24s%s\n", "Global/Private Zoned:",
    966         ALPM_TCAM_ZONED(u) ? "Yes" : "No"));
    967         LOG_CLI(("%-24s%s\n", "SW Prefix Lookup:", "Yes"));
    968         LOG_CLI(("%-24s%d\n", "Direct Route Glb High:", glb_hi_cnt));
    969         LOG_CLI(("%-24s%d\n", "Direct Route Glb Low:", glb_lo_cnt));
    970         LOG_CLI(("---------------------------------------\n"));
    971         LOG_CLI(("\n"));
    972         for (i = 0; i < ACB_CNT(u); i++) {
    973             acb = ACB(u, i);
    974             LOG_CLI(("== %s\n", alpm_util_acb_str[i]));
    975             LOG_CLI(("%-24s%d\n", "Num Banks:", ACB_PHY_BNK_PER_BKT(acb)));
    976             LOG_CLI(("%-24s%d\n", "Bank bits:", ACB_BNK_BITS(acb)));
    977             LOG_CLI(("%-24s%d\n", "Num Buckets:", ACB_BKT_CNT(acb)));
    978             LOG_CLI(("%-24s%d\n", "Bucket bits:", ACB_BKT_BITS(acb)));
    979             LOG_CLI(("%-24s0x%x\n", "Bucket Mask:", ACB_BKT_CNT(acb) - 1));
    980             LOG_CLI(("\n"));
    981             for (pid = 0; pid < ALPM_BKT_PID_CNT; pid++) {
    982                 bp_conf = ACB_BKT_POOL(acb, pid);
    983                 if (pid > 0 && bp_conf == ACB_BKT_POOL(acb, pid - 1)) {
    984                     continue; /* Combined Mode uses PID=0 only */
    985                 }
    986                 dp = &dbg[pid];
    987 
    988                 if (ALPM_TCAM_ZONED(u)) {
    989                     LOG_CLI(("%s\n", (pid == 0 ? "-- Private:" : "-- Global:")));
    990                 } else {
    991                     LOG_CLI(("-- Private & Global:\n"));
    992                 }
    993 
    994                 LOG_CLI(("%-24s\n", "Pivots:"));
    995                 for (pkm = 0; pkm < ALPM_PKM_CNT; pkm++) {
    996                     if (ACB_HAS_TCAM(acb)) {
    997                         LOG_CLI(("  %-22s%d/%-4d\n", alpm_util_pkm_str[pkm],
    998                                  dp->dc[i].pvt_used[pkm],
    999                                  dp->dc[i].pvt_max[pkm]));
   1000                     } else {
   1001                         LOG_CLI(("  %-22s%d/%-4d\n", alpm_util_pkm_str[pkm],
   1002                                  dp->dc[i].pvt_used[pkm],
   1003                                  dp->dc[i-1].ent_max));
   1004                     }
   1005                 }
   1006 
   1007                 LOG_CLI(("%-24s%d/%-4d\n", "Buckets:",
   1008                          dp->dc[i].bucket_used, dp->dc[i].bucket_max));
   1009                 LOG_CLI(("%-24s%d/%-4d\n", "Banks:",
   1010                          dp->dc[i].bank_used, dp->dc[i].bank_max));
   1011                 ent_used_tot = dp->dc[i].ent_used[ALPM_PKM_32B] +
   1012                     dp->dc[i].ent_used[ALPM_PKM_64B] +
   1013                     dp->dc[i].ent_used[ALPM_PKM_128];
   1014                 LOG_CLI(("%-24s%d/%-4d\n", "Bucket Entries:",
   1015                          ent_used_tot, dp->dc[i].ent_max));
   1016                 for (pkm = 0; pkm < ALPM_PKM_CNT; pkm++) {
   1017                     LOG_CLI(("  %-22s%d\n", alpm_util_pkm_str[pkm],
   1018                              dp->dc[i].ent_used[pkm]));
   1019                 }
   1020 
   1021                 LOG_CLI(("%s\n", "Bucket Sharing Count:"));
   1022                 for (k = 0; k < BPC_BNK_PER_BKT(bp_conf); k++) {
   1023                     LOG_CLI(("  %1d%-21s%d\n", (k+1), "->1:", dp->dc[i].bs[k]));
   1024                 }
   1025 
   1026                 if (ACB_HAS_RTE(acb, ALPM_BPC_PID_TO_VRF_ID(u, pid))) {
   1027                     LOG_CLI(("%-24s%d\n", "Total Routes:", dp->route_cnt));
   1028                     LOG_CLI(("%-24s%d\n", "Total Hit Routes:", dp->hit_cnt));
   1029                 }
   1030                 LOG_CLI(("\n"));
   1031             }
   1032         }
   1033     }
   1034 
   1035 bad:
   1036     for (i = 0; i < ACB_CNT(u); i++) {
   1037         acb = ACB(u, i);
   1038         for (pid = 0; pid < ALPM_BKT_PID_CNT; pid++) {
   1039             bp_conf = ACB_BKT_POOL(acb, pid);
   1040             if (pid > 0 && bp_conf == ACB_BKT_POOL(acb, pid - 1)) {
   1041                 continue; /* Combined Mode uses PID=0 only */
   1042             }
   1043             dp = &dbg[pid];
   1044             if (dp->bktref[i]) {
   1045                 alpm_util_free(dp->bktref[i]);
   1046                 dp->bktref[i] = NULL;
   1047             }
   1048         }
   1049     }
   1050     return rv;
   1051 }
   1052 
   1053 /* Compare a prefix Hw lookup result (ip, sublen, intf) */
   1054 STATIC int
   1055 alpm_pfx_hw_route_cb(_alpm_pfx_node_t *pfx_node, void *user_data)
   1056 {
   1057     _alpm_trv_data_t    *trv_data = (_alpm_trv_data_t *)user_data;
   1058     int                 u = trv_data->unit;
   1059     int                 ipt = trv_data->ipt;
   1060     int                 vrf_id = trv_data->vrf_id;
   1061     int                 found_vrf_id;
   1062     int                 ipv6 = ALPM_IS_IPV6(ipt);
   1063     _alpm_bkt_node_t    *bkt_node = pfx_node->bkt_ptr;
   1064     _bcm_defip_cfg_t    lpm_cfg;
   1065     int                 nh_ecmp_idx, dest, err = 0;
   1066     bcm_ip_t            defip_ip_addr = 0;
   1067     bcm_ip6_t           defip_ip6_addr = {0};
   1068     int                 defip_sub_len;
   1069     char                ip_buf[IP6ADDR_STR_LEN];
   1070     int                 rv = BCM_E_NONE;
   1071 
   1072     if (bkt_node == NULL) {
   1073         return rv;
   1074     }
   1075 
   1076     sal_memset(&lpm_cfg, 0, sizeof(lpm_cfg));
   1077     lpm_cfg.defip_vrf = ALPM_VRF_ID_TO_VRF(u, vrf_id);
   1078     lpm_cfg.defip_flags |= (ipv6 ? BCM_L3_IP6 : 0);
   1079 
   1080     alpm_trie_pfx_to_cfg(u, pfx_node->key, pfx_node->key_len, &lpm_cfg);
   1081 
   1082     dest = bkt_node->adata.defip_ecmp_index;
   1083     defip_sub_len = lpm_cfg.defip_sub_len;
   1084     if (ipv6) {
   1085         sal_memcpy(&defip_ip6_addr, &lpm_cfg.defip_ip6_addr, sizeof(defip_ip6_addr));
   1086     } else {
   1087         defip_ip_addr = lpm_cfg.defip_ip_addr;
   1088     }
   1089 
   1090     rv = bcm_esw_alpm_find(u, &lpm_cfg, &nh_ecmp_idx);
   1091 
   1092     if (BCM_FAILURE(rv)) {
   1093         err = 1;
   1094     } else {
   1095         found_vrf_id = ALPM_LPM_VRF_ID(u, &lpm_cfg);
   1096         /* VRF override match is OK */
   1097         if (found_vrf_id != ALPM_VRF_ID_GHI(u)) {
   1098             if ((defip_sub_len != lpm_cfg.defip_sub_len) || (dest != nh_ecmp_idx)) {
   1099                 err = 2;
   1100             } else {
   1101                 if (ipv6) {
   1102                     if (sal_memcmp(&defip_ip6_addr, &lpm_cfg.defip_ip6_addr, sizeof(defip_ip6_addr))) {
   1103                         err = 3;
   1104                     }
   1105                 } else {
   1106                     if (defip_ip_addr != lpm_cfg.defip_ip_addr) {
   1107                         err = 3;
   1108                     }
   1109                 }
   1110             }
   1111         }
   1112     }
   1113 
   1114     if (err) {
   1115         if (ipv6) {
   1116             alpm_util_fmt_ip6addr(ip_buf, defip_ip6_addr);
   1117         } else {
   1118             alpm_util_fmt_ipaddr(ip_buf, defip_ip_addr);
   1119         }
   1120 
   1121         ALPM_ERR(("PFX %p->BKT %p: IP:%s Sublen:%d Dest:%d => ",
   1122                   pfx_node, bkt_node, ip_buf, defip_sub_len, dest));
   1123 
   1124         if (err == 1) {
   1125             ALPM_ERR(("couldn't find in Hw (%d)!\n", rv));
   1126         } else {
   1127             if (ipv6) {
   1128                 alpm_util_fmt_ip6addr(ip_buf, lpm_cfg.defip_ip6_addr);
   1129             } else {
   1130                 alpm_util_fmt_ipaddr(ip_buf, lpm_cfg.defip_ip_addr);
   1131             }
   1132             ALPM_ERR(("wrong Hw route!\n"));
   1133             ALPM_ERR(("   Current best match Hw route: IP:%s Sublen:%d Dest:%d\n",
   1134                       ip_buf, lpm_cfg.defip_sub_len, nh_ecmp_idx));
   1135         }
   1136 
   1137         trv_data->err++;
   1138     }
   1139 
   1140     return BCM_E_NONE;
   1141 }
   1142 
   1143 
   1144 /*
   1145  * Function:
   1146  *      alpm_pfx_hw_route_sanity
   1147  * Purpose:
   1148  *      Hw route lookup for all prefix trie routes.
   1149  * Parameters:
   1150  *      u        - (In)Device unit
   1151  *      tot_err  - (In/Out)Total errors during lookup
   1152  * Returns:
   1153  *      BCM_E_XXX
   1154  */
   1155 int
   1156 alpm_pfx_hw_route_sanity(int u, int *tot_err)
   1157 {
   1158     int vrf_id, ipt;
   1159     _alpm_trv_data_t trv_data;
   1160 
   1161     trv_data.err = 0;
   1162     trv_data.unit = u;
   1163     for (ipt = 0; ipt < ALPM_IPT_CNT; ipt++) {
   1164         trv_data.ipt = ipt;
   1165         for (vrf_id = 0; vrf_id <= ALPM_VRF_ID_MAX(u); vrf_id++) {
   1166             if (!ACB_VRF_INITED(u, ACB_VRF_BTM(u, vrf_id), vrf_id, ipt)) {
   1167                 continue;
   1168             }
   1169             trv_data.vrf_id = vrf_id;
   1170             (void)bcm_esw_alpm_pfx_traverse(u, vrf_id, ipt,
   1171                                             alpm_pfx_hw_route_cb, &trv_data);
   1172         }
   1173     }
   1174 
   1175     if (trv_data.err) {
   1176         ALPM_ERR(("\nNumber of routes with HW routing issue: %d\n", trv_data.err));
   1177         *tot_err += trv_data.err;
   1178     }
   1179 
   1180     return BCM_E_NONE;
   1181 }
   1182 
   1183 /*
   1184  * Function:
   1185  *      alpm_cb_sanity_process
   1186  * Purpose:
   1187  *      ALPM control block (level) sanity process.
   1188  *      It's recursive from top to bottom.
   1189  *      Detection of HW/Sw mismatch or conflict, entry data anormality etc.
   1190  * Parameters:
   1191  *      u        - (In)Device unit
   1192  *      vrf_id   - (In)VRF ID
   1193  *      pkm      - (In)PKM
   1194  *      acb      - (In)ALPM control block
   1195  *      pvtfmt   - (In)Pivot bank format (ignored for TCAM)
   1196  *      fent     - (In)ALPM_DATA entry
   1197  *      key      - (In)Key prefix
   1198  *      key_len  - (In)Key prefix length
   1199  *      idx      - (In)Memory Index
   1200  *      sub_idx  - (In)Memory sub_idx (for half-entry) or ent index
   1201  *      adata    - (In)Assoc Data structure pointer
   1202  *      sanity   - (Out)Carrying sanity check info
   1203  * Returns:
   1204  *      BCM_E_XXX
   1205  */
   1206 STATIC int
   1207 alpm_cb_sanity_process(int u, int vrf_id, int pkm, _alpm_cb_t *acb,
   1208                        int pvtfmt, void *fent, uint32 *key, int key_len,
   1209                        int idx, int sub_idx,
   1210                        _alpm_bkt_adata_t *adata, _alpm_sanity_t *sanity)
   1211 {
   1212     uint32 bkt_entry[ALPM_MEM_ENT_MAX];
   1213     uint32 fent1[ALPM_MEM_ENT_MAX];
   1214     uint32 ftmp[ALPM_MEM_ENT_MAX];
   1215     uint32 new_key[4];
   1216     uint32 pfx[5], pvt_idx, bkt_idx;
   1217     alpm_lib_trie_t *pvt_trie, *pfx_trie, *bkt_trie;
   1218     _alpm_pvt_node_t *pvt_node = NULL;
   1219     _alpm_pfx_node_t *bkt_node;
   1220     _alpm_pfx_node_t *pfx_node;
   1221     char ip_buf[IP6ADDR_STR_LEN];
   1222     char err_msg[160];
   1223     uint32 fmt, valid;
   1224     int sublen, new_len, def_miss;
   1225     int idx1, eid, bnk, trie_idx, trie_ent;
   1226     _alpm_bkt_adata_t adata1, bm_adata, adata_local;
   1227     int rv = BCM_E_NONE;
   1228     int bkt_empty;
   1229     _bcm_defip_cfg_t lpm_cfg;
   1230     _alpm_bkt_info_t bkt_info;
   1231     int pvt_node_pfx_cnt = 0;
   1232     int hw_bkt_pfx_cnt = 0;
   1233     _alpm_tbl_t bkt_tbl;
   1234     _alpm_tbl_t pvt_tbl;
   1235     int ipt;
   1236 
   1237     if (ACB_IDX(acb) >= ACB_CNT(u)) {
   1238         return BCM_E_INTERNAL; /* wrong ALPM control level called */
   1239     }
   1240 
   1241     ipt = ALPM_PKM2IPT(pkm);
   1242     pfx_trie = ALPM_VRF_TRIE(u, vrf_id, ipt);
   1243     bkt_tbl = ACB_BKT_TBL(acb, vrf_id);
   1244     pvt_tbl = (ACB_HAS_TCAM(acb) ? acb->pvt_tbl[pkm] :
   1245                 ACB_BKT_TBL(ACB_UPR(u, acb), vrf_id));
   1246 
   1247     /**** Pivot level ****/
   1248     alpm_util_bkt_info_get(u, vrf_id, ipt, pkm, acb, fent, sub_idx,
   1249                            &bkt_info, &sublen, &def_miss);
   1250 
   1251     /* kshift must be same as previous key_len */
   1252     if (!ACB_BKT_FIXED_FMT(acb, 1) && sublen != key_len) {
   1253         sanity->error++;
   1254         ALPM_ERR(("%s: ALPM_DATA invalid kshift:%d vs pivot len:%d"
   1255                   " idx:%d.%d (%d)\n", ALPM_TBL_NAME(pvt_tbl), sublen,
   1256                   key_len, idx, sub_idx, BI_BKT_IDX(&bkt_info)));
   1257         return BCM_E_NONE; /* just skip the pivot */
   1258     }
   1259     if (BI_BKT_IDX(&bkt_info) >= ACB_BKT_CNT(acb)) {
   1260         sanity->error++;
   1261         ALPM_ERR(("%s: ALPM_DATA invalid bkt_ptr idx:%d.%d (%d)\n",
   1262                   ALPM_TBL_NAME(pvt_tbl), idx, sub_idx, BI_BKT_IDX(&bkt_info)));
   1263         return BCM_E_NONE; /* just skip the pivot */
   1264     }
   1265 
   1266     /* HW pivot key vs SW pvt trie */
   1267     rv = BCM_E_NONE;
   1268     alpm_trie_key_to_pfx(u, ipt, key, key_len, pfx);
   1269     pvt_trie = ACB_PVT_TRIE(acb, vrf_id, ipt);
   1270     if (pvt_trie != NULL) {
   1271         rv = alpm_lib_trie_search(pvt_trie, pfx, key_len, (alpm_lib_trie_node_t **)&pvt_node);
   1272         if (BCM_SUCCESS(rv)) {
   1273             if (ACB_HAS_TCAM(acb)) { /* compare tcam_idx */
   1274                 if (pkm == ALPM_PKM_32B) {
   1275                     pvt_idx = idx << 1 | sub_idx;
   1276                     trie_idx = PVT_IDX(pvt_node) >> 1;
   1277                     trie_ent = PVT_IDX(pvt_node) & 1;
   1278                 } else {
   1279                     pvt_idx = idx;
   1280                     trie_idx = PVT_IDX(pvt_node);
   1281                     trie_ent = 0;
   1282                 }
   1283                 if (pvt_idx != PVT_IDX(pvt_node)) {
   1284                     rv = BCM_E_INTERNAL;
   1285                     sanity->error++;
   1286                     sal_sprintf(err_msg, "Error: duplicated key as pvt tcam_idx:%d.%d",
   1287                                 trie_idx, trie_ent);
   1288                 }
   1289             }
   1290         } else { /* rv = BCM_E_NOT_FOUND */
   1291             sanity->error++;
   1292             sal_sprintf(err_msg, "Error: not found in pvt trie");
   1293             pvt_node = NULL;
   1294         }
   1295     } else {
   1296         rv = BCM_E_INTERNAL;
   1297         sanity->error++;
   1298         sal_sprintf(err_msg, "Error: pvt trie doesn't exist");
   1299     }
   1300 
   1301     if (BCM_FAILURE(rv)) {
   1302         alpm_util_cfg_construct(u, vrf_id, ipt, key, key_len, adata, &lpm_cfg);
   1303         if (ALPM_IS_IPV4(ipt)) {
   1304             alpm_util_fmt_ipaddr(ip_buf, lpm_cfg.defip_ip_addr);
   1305         } else {
   1306             alpm_util_fmt_ip6addr(ip_buf, lpm_cfg.defip_ip6_addr);
   1307         }
   1308         if (ACB_HAS_TCAM(acb)) {
   1309             ALPM_ERR(("VRF:%d IPT:%s %s: TCAM idx:%d.%d Sublen:%d bpmDest:%d IP:%s\n ==> %s\n",
   1310                       vrf_id, alpm_util_ipt_str[ipt], ALPM_TBL_NAME(pvt_tbl),
   1311                       idx, sub_idx, key_len, adata->defip_ecmp_index,
   1312                       ip_buf, err_msg));
   1313         } else {
   1314             ALPM_ERR(("VRF:%d IPT:%s %s: PVT idx:%d.%d Sublen:%d fmt:%d bpmDest:%d IP:%s\n ==> %s\n",
   1315                        vrf_id, alpm_util_ipt_str[ipt], ALPM_TBL_NAME(pvt_tbl),
   1316                        idx, sub_idx, key_len, pvtfmt,
   1317                        adata->defip_ecmp_index, ip_buf, err_msg));
   1318         }
   1319     } else {
   1320         if (pvt_node && pvt_node->bkt_trie && pvt_node->bkt_trie->trie) {
   1321             pvt_node_pfx_cnt = pvt_node->bkt_trie->trie->count;
   1322         }
   1323     }
   1324 
   1325 #if 0
   1326     /* Pivot Assoc_Data Hw validation (only if Default_Miss==0) */
   1327     if (def_miss == FALSE) {
   1328         /* through Hw best match lookup */
   1329         ALPM_VERB(("%s: check Pivot idx:%d.%d def_rte => ",
   1330                       ALPM_TBL_NAME(pvt_tbl), idx, sub_idx));
   1331         sal_memset(&lpm_cfg, 0, sizeof(lpm_cfg));
   1332         /* ALPMTBD: find best match from ALPM only (exclude Direct Routes) */
   1333         rv = alpm_find_best_match(u, vrf_id, pkm, key, key_len, &lpm_cfg);
   1334 
   1335         if (BCM_FAILURE(rv)) {
   1336             sanity->error++;
   1337             ALPM_ERR(("%s: Pivot idx:%d.%d BPM missing (rv=%d)\n",
   1338                       ALPM_TBL_NAME(pvt_tbl), idx, sub_idx, rv));
   1339         } else {
   1340             alpm_util_adata_cfg_to_trie(u, &lpm_cfg, &bm_adata);
   1341             /* filter flags BCM_L3_HIT & BCM_L3_IP6 from
   1342                bm_adata.defip_flags before memcmp */
   1343             ALPM_FLAGS_FILTER(bm_adata.defip_flags);
   1344             if (sal_memcmp((void *)adata, (void *)&bm_adata,
   1345                            sizeof(_alpm_bkt_adata_t)) != 0) {
   1346                 sanity->error++;
   1347                 ALPM_ERR(("%s: Pivot idx:%d.%d Assoc Data mismatch"
   1348                           " (current vs best match):\n",
   1349                           ALPM_TBL_NAME(pvt_tbl), idx, sub_idx));
   1350                 ALPM_ERR((" defip_flags: %x vs %x, dest: %d vs %d\n",
   1351                           adata->defip_flags, bm_adata.defip_flags,
   1352                           adata->defip_ecmp_index, bm_adata.defip_ecmp_index));
   1353             }
   1354         }
   1355     }
   1356 #endif
   1357 
   1358     /* Pvt default route verification & Assoc_Data Sw validation */
   1359     if (pfx_trie != NULL) {
   1360         rv = alpm_lib_trie_find_lpm(pfx_trie, pfx, key_len,
   1361                        (alpm_lib_trie_node_t **)&pfx_node);
   1362         if (BCM_FAILURE(rv)) {
   1363             if (def_miss == 0) {
   1364                 sanity->error++;
   1365                 ALPM_ERR(("%s: Pivot idx:%d.%d BPM missing (rv=%d)\n",
   1366                             ALPM_TBL_NAME(pvt_tbl), idx, sub_idx, rv));
   1367             }
   1368         } else {
   1369             if (pvt_node != NULL) {
   1370                 if (PVT_BKT_DEF(pvt_node) != pfx_node->bkt_ptr) {
   1371                     sanity->error++;
   1372                     ALPM_ERR(("%s: Pivot idx:%d.%d key_len:%d bpm_len:%d DEF_PFX %p"
   1373                               " diff than BPM BKT %p\n",
   1374                               ALPM_TBL_NAME(pvt_tbl), idx, sub_idx,
   1375                               PVT_KEY_LEN(pvt_node), PVT_BPM_LEN(pvt_node),
   1376                               PVT_BKT_DEF(pvt_node), pfx_node->bkt_ptr));
   1377                 } else {
   1378                     if (def_miss == 1 && PVT_BKT_DEF(pvt_node)) {
   1379                         sanity->error++;
   1380                         ALPM_ERR(("%s: Pivot idx:%d.%d Default_Miss=1 but BPM route exits\n",
   1381                                    ALPM_TBL_NAME(pvt_tbl), idx, sub_idx));
   1382                     }
   1383                 }
   1384             }
   1385 
   1386             adata_local = *adata;
   1387             if (pfx_node->bkt_ptr) {
   1388                 bm_adata = pfx_node->bkt_ptr->adata;
   1389                 /*
   1390                  * filter flags BCM_L3_HIT & BCM_L3_IP6 from
   1391                  * bm_adata.defip_flags and adata.defip_flags
   1392                  * before memcmp.
   1393                  */
   1394                 ALPM_FLAGS_FILTER(bm_adata.defip_flags);
   1395                 ALPM_FLAGS_FILTER(adata_local.defip_flags);
   1396                 if (sal_memcmp((void *)&adata_local, (void *)&bm_adata,
   1397                                sizeof(_alpm_bkt_adata_t)) != 0) {
   1398                     sanity->error++;
   1399                     ALPM_ERR(("%s: Pivot idx:%d.%d Assoc Data mismatch"
   1400                               "(current vs bm) flags:%x vs %x dest:%d vs %d\n",
   1401                               ALPM_TBL_NAME(pvt_tbl), idx, sub_idx,
   1402                               adata_local.defip_flags, bm_adata.defip_flags,
   1403                               adata_local.defip_ecmp_index,
   1404                               bm_adata.defip_ecmp_index));
   1405                 }
   1406             } else {
   1407                  /* Parallel & TCAM mix mode, pivot sanity check:
   1408                     no best match def_rte but default_miss = 0 */
   1409                 if ((def_miss == 0) && ALPM_TCAM_ZONED(u)) {
   1410                     sanity->error++;
   1411                     ALPM_ERR(("%s: Pivot idx:%d.%d w/o bm_rte => "
   1412                               "wrong def_miss:0 dest:%d\n",
   1413                               ALPM_TBL_NAME(pvt_tbl), idx, sub_idx,
   1414                               adata_local.defip_ecmp_index));
   1415                 }
   1416             }
   1417         }
   1418     }
   1419 
   1420     bkt_empty = TRUE; /* each pivot must have at least one valid bucket entry */
   1421     for (bnk = 0; bnk < ACB_BNK_PER_BKT(acb, vrf_id); bnk++) {
   1422         fmt = bkt_info.bnk_fmt[bnk];
   1423         if ((fmt == 0) || (fmt > ACB_FMT_CNT(acb, vrf_id))) {
   1424             if (fmt > ACB_FMT_CNT(acb, vrf_id)) {
   1425                 sanity->error++;
   1426                 ALPM_ERR(("%s: ALPM_DATA format wrong idx:%d.%d (bank=%d fmt=%d).\n",
   1427                           ALPM_TBL_NAME(pvt_tbl), idx, sub_idx, bnk, fmt));
   1428             }
   1429             continue;
   1430         }
   1431 
   1432         /**** Bucket Level ****/
   1433         idx1 = ALPM_TAB_IDX_GET_BKT_BNK(acb, BI_ROFS(&bkt_info), BI_BKT_IDX(&bkt_info), bnk);
   1434         if (!ACB_BKT_FIXED_FMT(acb, 1)) { /* for TH3 only */
   1435             if (ACB_VRF_PVT_PTR(acb, vrf_id, idx1) == NULL) {
   1436                 sanity->error++;
   1437                 ALPM_ERR(("%s: bucket info -> pvt_ptr == NULL at bank %d\n",
   1438                           ALPM_TBL_NAME(bkt_tbl), idx1));
   1439             } else {
   1440                 _alpm_pvt_node_t *pvt_node2;
   1441 
   1442                 pvt_node2 = (_alpm_pvt_node_t *)ACB_VRF_PVT_PTR(acb, vrf_id, idx1);
   1443                 if (bkt_info.rofs != pvt_node2->bkt_info.rofs ||
   1444                     bkt_info.bkt_idx != pvt_node2->bkt_info.bkt_idx ||
   1445                     sal_memcmp(bkt_info.bnk_fmt, pvt_node2->bkt_info.bnk_fmt, sizeof(bkt_info.bnk_fmt)) != 0) {
   1446                     sanity->error++;
   1447                     ALPM_ERR(("\t%s: sw & hw bkt_info mismatch\n",
   1448                               ALPM_TBL_NAME(bkt_tbl)));
   1449                     ALPM_ERR(("\thw rofs %d bkt_idx %d fmt %d %d %d %d %d %d %d %d\n",
   1450                               bkt_info.rofs, bkt_info.bkt_idx,
   1451                               bkt_info.bnk_fmt[0],
   1452                               bkt_info.bnk_fmt[1],
   1453                               bkt_info.bnk_fmt[2],
   1454                               bkt_info.bnk_fmt[3],
   1455                               bkt_info.bnk_fmt[4],
   1456                               bkt_info.bnk_fmt[5],
   1457                               bkt_info.bnk_fmt[6],
   1458                               bkt_info.bnk_fmt[7]));
   1459                     ALPM_ERR(("\tsw rofs %d bkt_idx %d fmt %d %d %d %d %d %d %d %d\n",
   1460                               pvt_node2->bkt_info.rofs, pvt_node2->bkt_info.bkt_idx,
   1461                               pvt_node2->bkt_info.bnk_fmt[0],
   1462                               pvt_node2->bkt_info.bnk_fmt[1],
   1463                               pvt_node2->bkt_info.bnk_fmt[2],
   1464                               pvt_node2->bkt_info.bnk_fmt[3],
   1465                               pvt_node2->bkt_info.bnk_fmt[4],
   1466                               pvt_node2->bkt_info.bnk_fmt[5],
   1467                               pvt_node2->bkt_info.bnk_fmt[6],
   1468                               pvt_node2->bkt_info.bnk_fmt[7]));
   1469                 }
   1470             }
   1471         }
   1472         ALPM_IER(alpm_bkt_entry_read_no_cache(u, ACB_BKT_TBL(acb, vrf_id),
   1473                                               acb, bkt_entry, idx1));
   1474 
   1475         /* verify bucket bank ptr duplication */
   1476         if (sanity->bktptr[ACB_IDX(acb)][idx1] == -1) {
   1477             sanity->bktptr[ACB_IDX(acb)][idx1] = idx;
   1478         } else {
   1479             /* No need to check conflict bucket for bucket sharing */
   1480             if (!ACB_BKT_FIXED_FMT(acb, vrf_id) &&
   1481                 idx != sanity->bktptr[ACB_IDX(acb)][idx1]) {
   1482                 sanity->error++;
   1483                 ALPM_ERR(("%s: conflict bucket bank at %d (upr_idx %d vs %d)\n",
   1484                           ALPM_TBL_NAME(bkt_tbl), idx1, idx,
   1485                           sanity->bktptr[ACB_IDX(acb)][idx1]));
   1486             } /* else: conflict from higher CB, but this level is "OK" */
   1487         }
   1488 
   1489         for (eid = 0; eid < ACB_FMT_ENT_MAX(acb, vrf_id, fmt); eid++) {
   1490             uint32 key2[4] = {0};
   1491             int len2 = 0;
   1492             int sub_bkt_ptr = 0;
   1493 
   1494             /* process bucket entry Prefix */
   1495             alpm_util_ent_ent_get(u, vrf_id, acb, bkt_entry, fmt, eid, ftmp);
   1496             alpm_util_bkt_pfx_get(u, vrf_id, acb, ftmp, fmt, key2, &len2, &valid);
   1497             alpm_util_bkt_adata_get(u, vrf_id, ipt, acb, ftmp, fmt, &adata1, &sub_bkt_ptr);
   1498 
   1499             if (!valid || BI_SUB_BKT_IDX(&bkt_info) != sub_bkt_ptr) {
   1500                 continue;
   1501             } else {
   1502                 if (ACB_BKT_FIXED_FMT(acb, 1)) {
   1503                     new_len = len2;
   1504                     sal_memcpy(new_key, key2, sizeof(new_key));
   1505                 } else {
   1506                     alpm_util_pfx_cat(u, ipt, key, sublen, key2, len2, new_key, &new_len);
   1507                 }
   1508             }
   1509             bkt_empty = FALSE; /* at least one bucket entry */
   1510             hw_bkt_pfx_cnt ++;
   1511 
   1512             rv = BCM_E_NONE;
   1513             if (new_len == 0 &&
   1514                 (new_key[0] != 0 || new_key[1] != 0 ||
   1515                  new_key[2] != 0 || new_key[3] != 0)) {
   1516                 rv = BCM_E_INTERNAL;
   1517                 sanity->error++;
   1518                 sal_sprintf(err_msg,
   1519                     "Error: length is 0 but key is not, in bkt%d bnk%d ent%d",
   1520                     BI_BKT_IDX(&bkt_info), bnk, eid);
   1521             }
   1522 
   1523             if (BCM_SUCCESS(rv)) {
   1524                 /* process bucket entry ASSOC_DATA */
   1525                 alpm_trie_key_to_pfx(u, ipt, new_key, new_len, pfx);
   1526 
   1527                 /* HW bucket key vs SW bkt trie */
   1528                 if (pvt_node != NULL) {
   1529                     bkt_trie = PVT_BKT_TRIE(pvt_node);
   1530                     if (bkt_trie != NULL) {
   1531                         rv = alpm_lib_trie_search(bkt_trie, pfx, new_len,
   1532                                          (alpm_lib_trie_node_t **)&bkt_node);
   1533                         if (BCM_SUCCESS(rv)) {
   1534                             bkt_idx = idx1 | ((eid & ALPM_IDX_ENT_MASK)
   1535                                               << ALPM_IDX_ENT_SHIFT);
   1536                             if (bkt_idx != bkt_node->ent_idx) {
   1537                                 rv = BCM_E_INTERNAL;
   1538                                 sanity->error++;
   1539                                 trie_idx = ALPM_TAB_IDX_GET(bkt_node->ent_idx);
   1540                                 trie_ent = ALPM_IDX_TO_ENT(bkt_node->ent_idx);
   1541                                 sal_sprintf(err_msg,
   1542                                             "Error: duplicated key as bkt ent_idx:%d(bkt%d bnk%d).%d",
   1543                                             trie_idx, ALPM_IDX_TO_BKT(acb, bkt_node->ent_idx),
   1544                                             ALPM_IDX_TO_BNK(acb, bkt_node->ent_idx),
   1545                                             trie_ent);
   1546                             }
   1547                         } else {
   1548                             sanity->error++;
   1549                             sal_sprintf(err_msg, "Error: not found in bkt trie");
   1550                         }
   1551                     } else {
   1552                         rv = BCM_E_INTERNAL;
   1553                         sanity->error++;
   1554                         sal_sprintf(err_msg, "Error: bkt trie doesn't exist");
   1555                     }
   1556                 }
   1557             }
   1558 
   1559             if (BCM_FAILURE(rv)) {
   1560                 alpm_util_cfg_construct(u, vrf_id, ipt, new_key, new_len,
   1561                                         &adata1, &lpm_cfg);
   1562                 if (ALPM_IS_IPV4(ipt)) {
   1563                     alpm_util_fmt_ipaddr(ip_buf, lpm_cfg.defip_ip_addr);
   1564                 } else {
   1565                     alpm_util_fmt_ip6addr(ip_buf, lpm_cfg.defip_ip6_addr);
   1566                 }
   1567                 ALPM_ERR(("VRF:%d IPT:%s %s: BKT idx:%d(bkt%d bnk%d).%d Sublen:%d"
   1568                           " fmt:%d Dest:%d IP:%s\n ==> %s\n",
   1569                           vrf_id, alpm_util_ipt_str[ipt],
   1570                           ALPM_TBL_NAME(bkt_tbl),
   1571                           idx1, BI_BKT_IDX(&bkt_info), bnk, eid, new_len, fmt,
   1572                           adata1.defip_ecmp_index, ip_buf, err_msg));
   1573             }
   1574 
   1575             /* end recursion here if reach to route level (last level) */
   1576             if (ACB_HAS_RTE(acb, vrf_id)) {
   1577                 /* HW route vs SW prefix trie */
   1578                 if (BCM_SUCCESS(rv)) { /* if failed on bkt, bypass pfx check */
   1579                     if (pfx_trie != NULL) {
   1580                         rv = alpm_lib_trie_search(pfx_trie, pfx, new_len,
   1581                                          (alpm_lib_trie_node_t **)&pfx_node);
   1582                         if (BCM_SUCCESS(rv)) {
   1583                             bkt_idx = idx1 | ((eid & ALPM_IDX_ENT_MASK)
   1584                                               << ALPM_IDX_ENT_SHIFT);
   1585                             if (bkt_idx != pfx_node->bkt_ptr->ent_idx) {
   1586                                 rv = BCM_E_INTERNAL;
   1587                                 sanity->error++;
   1588                                 trie_idx = ALPM_TAB_IDX_GET(bkt_node->ent_idx);
   1589                                 trie_ent = ALPM_IDX_TO_ENT(bkt_node->ent_idx);
   1590                                 sal_sprintf(err_msg,
   1591                                             "Error: duplicated key as bkt ent_idx:%d.%d",
   1592                                             trie_idx, trie_ent);
   1593                             }
   1594                         } else {
   1595                             sanity->error++;
   1596                             sal_sprintf(err_msg, "Error: not found in prefix trie");
   1597                         }
   1598                     } else {
   1599                         rv = BCM_E_INTERNAL;
   1600                         sanity->error++;
   1601                         sal_sprintf(err_msg, "Error: pfx trie doesn't exist");
   1602                     }
   1603 
   1604                     if (BCM_FAILURE(rv)) {
   1605                         alpm_util_cfg_construct(u, vrf_id, ipt, new_key, new_len,
   1606                                                 &adata1, &lpm_cfg);
   1607                         if (ALPM_IS_IPV4(ipt)) {
   1608                             alpm_util_fmt_ipaddr(ip_buf, lpm_cfg.defip_ip_addr);
   1609                         } else {
   1610                             alpm_util_fmt_ip6addr(ip_buf, lpm_cfg.defip_ip6_addr);
   1611                         }
   1612                         ALPM_ERR(("VRF:%d IPT:%s %s: RTE idx:%d.%d Sublen:%d"
   1613                                   " fmt:%d Dest:%d IP:%s\n ==> %s\n",
   1614                                   vrf_id, alpm_util_ipt_str[ipt],
   1615                                   ALPM_TBL_NAME(bkt_tbl),
   1616                                   idx1, eid, new_len, fmt,
   1617                                   adata1.defip_ecmp_index, ip_buf, err_msg));
   1618                     }
   1619                 }
   1620                 continue;
   1621             }
   1622 
   1623             /* prevent going further down if somehow last level
   1624                is not Route level due to internal failure */
   1625             if ((ACB_IDX(acb) + 1) >= ACB_CNT(u)) {
   1626                 return BCM_E_INTERNAL;
   1627             }
   1628 
   1629             /* get ALPM Data entry ready for next level */
   1630             alpm_util_ent_data_get(u, vrf_id, ipt, acb, ftmp, fmt, fent1);
   1631             ALPM_IER(alpm_cb_sanity_process(u, vrf_id, ipt, ACB_DWN(u, acb),
   1632                                             fmt, fent1, new_key, new_len,
   1633                                             idx1, eid, &adata1, sanity));
   1634         } /* for eid */
   1635     } /* for bnk */
   1636 
   1637     if (hw_bkt_pfx_cnt != pvt_node_pfx_cnt) {
   1638         sanity->error++;
   1639         ALPM_ERR(("%s: Pivot idx:%d.%d pfx count(%d) does not match to hw bkt(bkt=%d,dw=%d) pfx count(%d)\n",
   1640                   ALPM_TBL_NAME(pvt_tbl), idx, sub_idx, pvt_node_pfx_cnt,
   1641                   PVT_BKT_IDX(pvt_node), ACB_BKT_DW(acb), hw_bkt_pfx_cnt));
   1642     }
   1643 
   1644     /* each pivot must have at least one valid bucket entry except
   1645      * default pivot */
   1646     if (bkt_empty && key_len != 0) {
   1647         sanity->error++;
   1648         ALPM_ERR(("%s: Pivot idx:%d.%d with empty bucket (or route).\n",
   1649                   ALPM_TBL_NAME(pvt_tbl), idx, sub_idx));
   1650     }
   1651     return BCM_E_NONE;
   1652 }
   1653 
   1654 /*
   1655  * Function:
   1656  *      bcm_esw_alpm_sanity_check
   1657  * Purpose:
   1658  *      Sanity check for ALPM
   1659  * Parameters:
   1660  *      u        - (In)Device unit
   1661  *      mem      - (In)TCAM memory (not in used)
   1662  *      index    - (In)Memory index (not in used)
   1663  *      check_sw - (In)check_sw = 0 for prefix Hw routing check
   1664  * Returns:
   1665  *      BCM_E_XXX
   1666  */
   1667 int
   1668 bcm_esw_alpm_sanity_check(int u, soc_mem_t mem, int index, int check_sw)
   1669 {
   1670     int ipv6, key_mode;
   1671     int idx, sub_idx;
   1672     int vrf_id;
   1673     int idx_end;
   1674     int step_size;
   1675     uint32 lpm_entry[ALPM_MEM_ENT_MAX];
   1676     uint32 fent[ALPM_MEM_ENT_MAX];
   1677     _alpm_cb_t *acb;
   1678     _alpm_bkt_adata_t adata0;
   1679     int pk, pkm, use_alpm;
   1680     uint32 key[4];
   1681     int key_pfx_len;
   1682     int i, alloc_sz, pid, tot_error = 0;
   1683     _alpm_sanity_t sanity[ALPM_BKT_PID_CNT];
   1684     _alpm_sanity_t *psanity;
   1685     int rv = BCM_E_NONE;
   1686     int rv_tcam;
   1687     _alpm_bkt_pool_conf_t *bp_conf;
   1688 
   1689     if (ALPMC(u) == NULL) {
   1690         return BCM_E_INIT;
   1691     }
   1692 
   1693     for (i = 0; i < ACB_CNT(u); i++) {
   1694         acb = ACB(u, i);
   1695 
   1696         for (pid = 0; pid < ALPM_BKT_PID_CNT; pid++) {
   1697             bp_conf = ACB_BKT_POOL(acb, pid);
   1698             if (pid > 0 && bp_conf == ACB_BKT_POOL(acb, pid - 1)) {
   1699                 continue; /* Combined Mode uses only PID=0 for sanity counters */
   1700             }
   1701 
   1702             psanity = &sanity[pid];
   1703             alloc_sz = BPC_BNK_CNT(bp_conf) * sizeof(int);
   1704             ALPM_ALLOC_EG(psanity->bktptr[i], alloc_sz, "bktptr");
   1705             /* initialized to -1 to distinguish index 0 */
   1706             sal_memset(psanity->bktptr[i], 0xff, alloc_sz);
   1707             psanity->error = 0;
   1708         }
   1709     }
   1710 
   1711     acb = ACB_TOP(u); /* from top to bottom */
   1712 
   1713     L3_LOCK(u);
   1714     for (pk = 0; pk < ALPM_PKM_CNT; pk++) {
   1715         if (ALPM_TCAM_TBL_SKIP(u, pk)) {
   1716             continue; /* skip duplicated or invalid TCAM table */
   1717         }
   1718 
   1719         /* LOG_CLI(("\n- Processing %s ...\n", TCAM_TBL_NAME(acb, pk))); */
   1720         idx_end = tcam_table_size(u, pk);
   1721         /* Walk all TCAM entries */
   1722         for (idx = 0; idx < idx_end; idx++) {
   1723             ALPM_IEG(tcam_entry_read_no_cache(u, pk, lpm_entry, idx, idx));
   1724 
   1725             for (sub_idx = 0; sub_idx < ALPM_TCAM_SUBCNT; sub_idx += step_size) {
   1726                 rv_tcam = tcam_valid_entry_mode_get(u, pk, lpm_entry,
   1727                               &step_size, &pkm, &ipv6, &key_mode, sub_idx);
   1728                 if (BCM_FAILURE(rv_tcam)) {
   1729                     if (rv_tcam == BCM_E_INTERNAL) {
   1730                         ALPM_ERR(("%s: Invalid Key Mode:%d or Key Type"
   1731                                   " (IPv6):%d in idx:%d.%d\n",
   1732                                   TCAM_TBL_NAME(acb, pk), key_mode,
   1733                                   ipv6, idx, sub_idx));
   1734                     }
   1735                     continue;
   1736                 }
   1737                 tcam_entry_vrf_id_get(u, pkm, lpm_entry, sub_idx, &vrf_id);
   1738 
   1739                 /* process pre-pivor ASSOC_DATA */
   1740                 tcam_entry_adata_get(u, pkm, lpm_entry, sub_idx, &adata0);
   1741                 use_alpm = !(adata0.defip_flags & BCM_L3_IPMC) &&
   1742                            ALPM_VRF_ID_HAS_BKT(u, vrf_id);
   1743                 if (!use_alpm) {
   1744                     continue;
   1745                 }
   1746 
   1747                 /* Get Pre-pivot key IP_ADDR and prefix length (mask) */
   1748                 sal_memset(key, 0, sizeof(key));
   1749                 key_pfx_len = 0;
   1750                 tcam_entry_to_key(u, pkm, lpm_entry, sub_idx, key);
   1751                 tcam_entry_pfx_len_get(u, pkm, lpm_entry, sub_idx, &key_pfx_len);
   1752 
   1753                 /* process ALPM_DATA level recursively from top to bottom */
   1754                 tcam_entry_bdata_get(u, pkm, lpm_entry, sub_idx, fent);
   1755 
   1756                 /* Combined Mode uses only PID=0 for sanity counters */
   1757                 pid = ACB_BKT_VRF_PID(acb, vrf_id);
   1758                 psanity = &sanity[pid];
   1759                 ALPM_IEG(alpm_cb_sanity_process(u, vrf_id, pkm, acb, 0, fent,
   1760                                             key, key_pfx_len, idx, sub_idx,
   1761                                             &adata0, psanity));
   1762             } /* for sub_idx */
   1763         } /* for idx */
   1764     } /* for pk */
   1765 
   1766     if (check_sw == 0) {
   1767         rv = alpm_pfx_hw_route_sanity(u, &tot_error);
   1768     }
   1769 
   1770 bad:
   1771     L3_UNLOCK(u);
   1772     for (i = 0; i < ACB_CNT(u); i++) {
   1773         acb = ACB(u, i);
   1774         for (pid = 0; pid < ALPM_BKT_PID_CNT; pid++) {
   1775             bp_conf = ACB_BKT_POOL(acb, pid);
   1776             if (pid > 0 && bp_conf == ACB_BKT_POOL(acb, pid - 1)) {
   1777                 continue; /* Combined Mode uses only PID=0 for sanity counters */
   1778             }
   1779 
   1780             psanity = &sanity[pid];
   1781             if (psanity->bktptr[i]) {
   1782                 alpm_util_free(psanity->bktptr[i]);
   1783                 psanity->bktptr[i] = NULL;
   1784             }
   1785             tot_error += psanity->error;
   1786         }
   1787     }
   1788 
   1789     if (rv == BCM_E_NONE) {
   1790         rv = (tot_error ? BCM_E_FAIL : BCM_E_NONE);
   1791         if (ALPMTR_TRACE_EN(u)) {
   1792             LOG_CLI(("RTE#%d ", ALPMTR_CNT(u)));
   1793         }
   1794         if (BCM_SUCCESS(rv)) {
   1795             LOG_CLI(("L3 ALPM sanity check: passed!\n"));
   1796         }
   1797     }
   1798 
   1799     return rv;
   1800 }
   1801 
   1802 /*
   1803  * Function:
   1804  *      alpm_cb_bm_lookup
   1805  * Purpose:
   1806  *      ALPM bucket best match lookup per CB by Hw (recursive from top to bottom).
   1807  * Parameters:
   1808  *      u        - (In)Device unit
   1809  *      vrf_id   - (In)VRF ID
   1810  *      pkm      - (In)PKM
   1811  *      acb      - (In)ALPM control block pointer
   1812  *      fent     - (In)ALPM_DATA entry
   1813  *      pvtfmt   - (In)Pivot bank format (ignored for TCAM)
   1814  *      key      - (In)Key prefix
   1815  *      key_len  - (In)Key prefix length
   1816  *      idx      - (In)Memory Index
   1817  *      sub_idx  - (In)Memory sub_idx (for half-entry) or ent index
   1818  *      adata    - (In)Assoc Data structure pointer
   1819  *      lpm_cfg  - (Out)BPM defip cfg info found
   1820  *      hit_res  - (Out)Lookup result in the bucket
   1821  *      sw_key   - (In)Key to lookup
   1822  *      sw_len   - (In)Key length to lookup
   1823  * Returns:
   1824  *      BCM_E_XXX
   1825  */
   1826 STATIC int
   1827 alpm_cb_bm_lookup(int u, int vrf_id, int pkm, _alpm_cb_t *acb, void *fent,
   1828                   int pvtfmt, uint32 *key, int key_len, int idx, int sub_idx,
   1829                   _alpm_bkt_adata_t *adata, _bcm_defip_cfg_t *lpm_cfg,
   1830                   _alpm_lkup_res_t *hit_res, uint32 *sw_key, int sw_len)
   1831 {
   1832     uint32 bkt_entry[ALPM_MEM_ENT_MAX];
   1833     uint32 ftmp[ALPM_MEM_ENT_MAX];
   1834     uint32 hw_mask[4];
   1835     uint32 hw_key[4];
   1836     uint32 fmt, valid;
   1837     int i, sublen, hw_len, key_ent_cnt;
   1838     int idx1, eid, bnk;
   1839     char ip_buf[IP6ADDR_STR_LEN];
   1840     _bcm_defip_cfg_t lpm_cfg_tmp;
   1841     _alpm_bkt_adata_t adata_tmp;
   1842     _alpm_bkt_adata_t adata1;
   1843     int def_miss = TRUE;
   1844     _alpm_lkup_res_t hit_res1 = ALPM_MISS; /* lookup result from next CB */
   1845     int hit_val;
   1846     /* Used for keeping Longest Matched entry in Bucket */
   1847     int    bm_len = -1;
   1848     int    bm_idx = 0;
   1849     int    bm_ent = 0;
   1850     uint32 bm_fmt = 0;
   1851     uint32 bm_key[4];
   1852     uint32 bm_fent[ALPM_MEM_ENT_MAX];
   1853     _alpm_bkt_info_t bkt_info;
   1854     _alpm_tbl_t bkt_tbl;
   1855     _alpm_tbl_t pvt_tbl;
   1856     int ipt = ALPM_PKM2IPT(pkm);
   1857 
   1858     if (ACB_IDX(acb) >= ACB_CNT(u)) {
   1859         return BCM_E_INTERNAL; /* wrong ALPM control level called */
   1860     }
   1861 
   1862     bkt_tbl = ACB_BKT_TBL(acb, vrf_id);
   1863     pvt_tbl = (ACB_HAS_TCAM(acb) ? acb->pvt_tbl[pkm] :
   1864                 ACB_BKT_TBL(ACB_UPR(u, acb), vrf_id));
   1865 
   1866     /**** Pivot level ****/
   1867     alpm_util_bkt_info_get(u, vrf_id, ipt, pkm, acb, fent, sub_idx,
   1868                            &bkt_info, &sublen, &def_miss);
   1869 
   1870     /* show pivot hit info */
   1871     alpm_util_cfg_construct(u, vrf_id, ipt, key, key_len, adata, &lpm_cfg_tmp);
   1872     if (ALPM_IS_IPV4(ipt)) {
   1873         alpm_util_fmt_ipaddr(ip_buf, lpm_cfg_tmp.defip_ip_addr);
   1874     } else {
   1875         alpm_util_fmt_ip6addr(ip_buf, lpm_cfg_tmp.defip_ip6_addr);
   1876     }
   1877 
   1878     /*if (ACB_HAS_TCAM(acb)) {
   1879         ALPM_VERB(("Hit pivot in %s: idx:%d.%d VRF:%d%s IP:%s Sublen:%d\n",
   1880                    ALPM_TBL_NAME(pvt_tbl), idx, sub_idx,
   1881                    vrf_id, (vrf_id == ALPM_VRF_ID_GLO(u)? "(Global low)" : ""),
   1882                    ip_buf, key_len));
   1883     } else {
   1884         ALPM_VERB(("Hit pivot in %s: idx:%d.%d fmt:%d IP:%s Sublen:%d\n",
   1885                    ALPM_TBL_NAME(pvt_tbl), idx, sub_idx, pvtfmt, ip_buf, key_len));
   1886     }*/
   1887 
   1888     /* kshift must be same as previous key_len */
   1889     if (!ACB_BKT_FIXED_FMT(acb, 1) && sublen != key_len) {
   1890         ALPM_ERR(("%s: ALPM_DATA invalid kshift:%d vs pivot len:%d"
   1891                   " idx:%d.%d (%d)\n", ALPM_TBL_NAME(pvt_tbl), sublen,
   1892                   key_len, idx, sub_idx, BI_BKT_IDX(&bkt_info)));
   1893         return BCM_E_NONE; /* just skip the pivot */
   1894     }
   1895     if (BI_BKT_IDX(&bkt_info) >= ACB_BKT_CNT(acb)) {
   1896         ALPM_ERR(("%s: ALPM_DATA invalid bkt_ptr idx:%d.%d (%d)\n",
   1897                   ALPM_TBL_NAME(pvt_tbl), idx, sub_idx, BI_BKT_IDX(&bkt_info)));
   1898         return BCM_E_NONE; /* just skip the pivot */
   1899     }
   1900 
   1901     for (bnk = 0; bnk < ACB_BNK_PER_BKT(acb, vrf_id); bnk++) {
   1902         fmt = bkt_info.bnk_fmt[bnk];
   1903         if ((fmt == 0) || (fmt > ACB_FMT_CNT(acb, vrf_id))) {
   1904             if (fmt > ACB_FMT_CNT(acb, vrf_id)) {
   1905                 ALPM_ERR(("%s: ALPM_DATA format wrong idx:%d.%d"
   1906                           " (bank=%d fmt=%d).\n", ALPM_TBL_NAME(pvt_tbl),
   1907                           idx, sub_idx, bnk, fmt));
   1908             }
   1909             continue;
   1910         }
   1911 
   1912         /**** Bucket Level ****/
   1913         idx1 = ALPM_TAB_IDX_GET_BKT_BNK(acb, BI_ROFS(&bkt_info), BI_BKT_IDX(&bkt_info), bnk);
   1914         ALPM_IER(alpm_bkt_entry_read(u, ACB_BKT_TBL(acb, vrf_id),
   1915                                      acb, bkt_entry, idx1));
   1916 
   1917         for (eid = 0; eid < ACB_FMT_ENT_MAX(acb, vrf_id, fmt); eid++) {
   1918             uint32 key2[4] = {0};
   1919             int len2 = 0;
   1920             int sub_bkt_ptr = 0;
   1921 
   1922             /* process bucket entry Prefix */
   1923             alpm_util_ent_ent_get(u, vrf_id, acb, bkt_entry, fmt, eid, ftmp);
   1924             alpm_util_bkt_pfx_get(u, vrf_id, acb, ftmp, fmt, key2, &len2, &valid);
   1925             alpm_util_bkt_adata_get(u, vrf_id, ipt, acb, ftmp, fmt, &adata_tmp, &sub_bkt_ptr);
   1926 
   1927             if (!valid || BI_SUB_BKT_IDX(&bkt_info) != sub_bkt_ptr) {
   1928                 continue;
   1929             }
   1930 
   1931             if (ACB_BKT_FIXED_FMT(acb, 1)) {
   1932                 hw_len = len2;
   1933                 sal_memcpy(hw_key, key2, sizeof(hw_key));
   1934             } else {
   1935                 alpm_util_pfx_cat(u, ipt, key, sublen, key2, len2, hw_key, &hw_len);
   1936             }
   1937 
   1938             if (hw_len > sw_len) { /* invalid or not match */
   1939                 continue;
   1940             }
   1941             alpm_util_len_to_mask(ipt, hw_len, hw_mask);
   1942 
   1943             /* new_len <= sw_len: compare all hw_masked key */
   1944             key_ent_cnt = ALPM_KEY_ENT_CNT(ipt);
   1945             for (i = 0; i < key_ent_cnt; i++) {
   1946                 if ((sw_key[i] & hw_mask[i]) != (hw_key[i] & hw_mask[i])) {
   1947                     break;
   1948                 }
   1949             }
   1950             /* Not match */
   1951             if (i < key_ent_cnt) {
   1952                 continue;
   1953             }
   1954 
   1955             /* Found a match, keep longest matched route */
   1956             if (hw_len > bm_len) {
   1957                 bm_len = hw_len;
   1958                 bm_fmt = fmt;
   1959                 bm_idx = idx1; /* ALPM bucket mem index */
   1960                 bm_ent = eid;
   1961                 sal_memcpy(bm_key, hw_key, sizeof(hw_key));
   1962                 sal_memcpy(bm_fent, ftmp, sizeof(ftmp));
   1963                 sal_memcpy(&adata1, &adata_tmp, sizeof(adata_tmp));
   1964             }
   1965         } /* for ent */
   1966     } /* for bnk */
   1967 
   1968     /* Hit in bucket */
   1969     if (bm_len != -1) {
   1970         /* end recursion down if reach route level (last level) */
   1971         if (ACB_HAS_RTE(acb, vrf_id)) {
   1972             *hit_res = ALPM_HIT;
   1973             alpm_util_cfg_construct(u, vrf_id, ipt, bm_key, bm_len,
   1974                                     &adata1, &lpm_cfg_tmp);
   1975             if (ALPM_IS_IPV4(ipt)) {
   1976                 alpm_util_fmt_ipaddr(ip_buf, lpm_cfg_tmp.defip_ip_addr);
   1977             } else {
   1978                 alpm_util_fmt_ip6addr(ip_buf, lpm_cfg_tmp.defip_ip6_addr);
   1979             }
   1980 
   1981             /*ALPM_VERB(("Hit route in %s idx:%d.%d fmt:%d IP:%s Sublen:%d\n",
   1982                        ALPM_TBL_NAME(bkt_tbl), bm_idx, bm_ent,
   1983                        bm_fmt, ip_buf, bm_len));*/
   1984         } else { /* go down CB */
   1985             /* prevent going further down if somehow last level
   1986                is not Route level due to internal failure */
   1987             if ((ACB_IDX(acb) + 1) >= ACB_CNT(u)) {
   1988                 return BCM_E_INTERNAL;
   1989             }
   1990 
   1991             /* get ALPM Data entry ftmp for next level using best match saved */
   1992             alpm_util_ent_data_get(u, vrf_id, ipt, acb, bm_fent, bm_fmt, ftmp);
   1993             ALPM_IER(alpm_cb_bm_lookup(u, vrf_id, ipt, ACB_DWN(u, acb),
   1994                                        ftmp, bm_fmt, bm_key, bm_len, bm_idx, bm_ent,
   1995                                        &adata1, lpm_cfg, &hit_res1, sw_key, sw_len));
   1996 
   1997             if (hit_res1 == ALPM_HIT) { /* Hit from next CB */
   1998                 *hit_res = ALPM_HIT;
   1999                 return BCM_E_NONE;
   2000             } else if ((hit_res1 == ALPM_MISS) && (def_miss == TRUE)) {
   2001                 *hit_res = ALPM_MISS;
   2002                 ALPM_VERB(("Miss in %s idx:%d.%d\n",
   2003                            ALPM_TBL_NAME(bkt_tbl), bm_idx, bm_ent));
   2004                 return BCM_E_NONE;
   2005             }
   2006             /* hit_res1 == ALPM_MISS_USE_AD or def_miss == FALSE */
   2007             *hit_res = ALPM_MISS_USE_AD;
   2008             ALPM_VERB(("Miss but use Associated data in %s idx:%d.%d\n",
   2009                        ALPM_TBL_NAME(bkt_tbl), bm_idx, bm_ent));
   2010         }
   2011 
   2012         /* Reached route level or hit_res1 == ALPM_MISS_USE_AD from next CB */
   2013         /* Get best match Assoc_Data and prepare returned lpm_cfg info*/
   2014         alpm_util_cfg_construct(u, vrf_id, ipt, bm_key, bm_len, &adata1, lpm_cfg);
   2015         lpm_cfg->defip_index =
   2016             alpm_util_ent_phy_idx_get(u, acb, vrf_id, bm_idx); /* ALPM mem index */
   2017 
   2018         /* Get HIT bit from best matched entry */
   2019         if (!ALPM_HIT_SKIP(u)) {
   2020             ALPM_HIT_LOCK(u);
   2021             hit_val = alpm_rte_hit_get(u, vrf_id, bkt_tbl, bm_idx, bm_ent);
   2022             lpm_cfg->defip_flags |= (hit_val > 0 ? BCM_L3_HIT : 0);
   2023             ALPM_HIT_UNLOCK(u);
   2024         }
   2025 
   2026         return BCM_E_NONE;
   2027     }
   2028 
   2029     /* Missed in this CB */
   2030     if (def_miss == TRUE) {
   2031         *hit_res = ALPM_MISS; /* Miss at all */
   2032     } else { /* Default Miss = 0 */
   2033         *hit_res = ALPM_MISS_USE_AD; /* Miss but upper CB should use Assoc Data */
   2034     }
   2035     return BCM_E_NONE;
   2036 }
   2037 
   2038 /*
   2039  * Function:
   2040  *      alpm_find_best_match
   2041  * Purpose:
   2042  *      Get best prefix match entry from DEFIP table (both IPv4 or IPv6).
   2043  *      It's an indenpendent routine, to simalute HW process for incoming
   2044  *      packets. Considering possible mismatch between SW and HW, we need
   2045  *      to go through hardware for lookup regardless of software state.
   2046  * Parameters:
   2047  *      u           - (IN)Device unit number
   2048  *      vrf_id      - (IN)VRF ID to lookup
   2049  *      pkm         - (IN)Packing mode to lookup
   2050  *      sw_key      - (IN)Key to lookup
   2051  *      sw_len      - (IN)Key length to lookup
   2052  *      lpm_cfg     - (OUT)BPM defip cfg info found
   2053  * Returns:
   2054  *      BCM_E_XXX
   2055  */
   2056 int
   2057 alpm_find_best_match(int u, int vrf_id, int pkm, uint32 *sw_key,
   2058                      int sw_len, _bcm_defip_cfg_t *lpm_cfg)
   2059 {
   2060     int i, ipv6, hw_pkm, step_size, key_ent_cnt;
   2061     int idx, sub_idx, idx_min, idx_cnt;
   2062     int idx_end;
   2063     int hw_len, hw_vrf_id;
   2064     int use_alpm, key_mode;
   2065     _alpm_lkup_res_t hit_res = ALPM_MISS;
   2066     uint32 hw_mask[4];
   2067     uint32 hw_key[4];
   2068     uint32 fent[ALPM_MEM_ENT_MAX];
   2069     _alpm_cb_t *acb;
   2070     uint32 lpm_entry[ALPM_MEM_ENT_MAX];
   2071     int do_urpf = 0; /* Find uRPF region */
   2072     int rv_tcam;
   2073     int ipt = ALPM_PKM2IPT(pkm);
   2074 
   2075     if (ALPMC(u) == NULL || !ALPMC(u)->_alpm_inited) {
   2076         return BCM_E_INIT;
   2077     }
   2078     if (!SOC_URPF_STATUS_GET(u) && do_urpf) {
   2079         return BCM_E_PARAM;
   2080     }
   2081 
   2082     acb = ACB_TOP(u); /* from top to bottom */
   2083 
   2084     idx_min = 0;
   2085     idx_cnt = tcam_table_size(u, pkm);
   2086     /* in Parallel or TCAM/ALPM mixed mode search Global High from second half */
   2087     if (ALPM_TCAM_ZONED(u)) {
   2088         idx_cnt >>= 1;
   2089         idx_min += idx_cnt;
   2090     }
   2091     if (do_urpf) {
   2092         idx_min += tcam_table_size(u, pkm);
   2093     }
   2094     idx_end = idx_min + idx_cnt;
   2095 
   2096     /* 1) Scanning for Global High routes first */
   2097     for (idx = idx_min; idx < idx_end; idx++) {
   2098         ALPM_IER(tcam_entry_read(u, pkm, lpm_entry, idx, idx));
   2099 
   2100         for (sub_idx = 0; sub_idx < ALPM_TCAM_SUBCNT; sub_idx += step_size) {
   2101             rv_tcam = tcam_valid_entry_mode_get(u, pkm, lpm_entry,
   2102                           &step_size, &hw_pkm, &ipv6, &key_mode, sub_idx);
   2103             if (BCM_FAILURE(rv_tcam)) {
   2104                 if (rv_tcam == BCM_E_INTERNAL) {
   2105                     ALPM_ERR(("%s: Invalid Key Mode:%d or Key Type"
   2106                               " (IPv6):%d in idx:%d.%d\n",
   2107                               TCAM_TBL_NAME(acb, pkm), key_mode,
   2108                               ipv6, idx, sub_idx));
   2109                 }
   2110                 continue;
   2111             }
   2112 
   2113             if (pkm != hw_pkm) {
   2114                 continue;
   2115             }
   2116 
   2117             tcam_entry_vrf_id_get(u, pkm, lpm_entry, sub_idx, &hw_vrf_id);
   2118             if (hw_vrf_id != ALPM_VRF_ID_GHI(u)) { /* only Global Hi */
   2119                 continue;
   2120             }
   2121 
   2122             sal_memset(hw_key, 0, sizeof(hw_key));
   2123             hw_len = 0;
   2124             tcam_entry_to_key(u, pkm, lpm_entry, sub_idx, hw_key);
   2125             tcam_entry_pfx_len_get(u, pkm, lpm_entry, sub_idx, &hw_len);
   2126             if (hw_len > sw_len) { /* not match */
   2127                 continue;
   2128             }
   2129             alpm_util_len_to_mask(ipt, hw_len, hw_mask);
   2130 
   2131             /* hw_len <= sw_len: compare all hw_masked key */
   2132             key_ent_cnt = ALPM_KEY_ENT_CNT(ipt);
   2133             for (i = 0; i < key_ent_cnt; i++) {
   2134                 if ((sw_key[i] & hw_mask[i]) != (hw_key[i] & hw_mask[i])) {
   2135                     break;
   2136                 }
   2137             }
   2138             /* Not match */
   2139             if (i < key_ent_cnt) {
   2140                 continue;
   2141             }
   2142 
   2143             /* Found all key matched (must be longest prefix due to order in TCAM) */
   2144             /* prepare returned lpm_cfg info */
   2145             tcam_entry_to_cfg(u, pkm, lpm_entry, sub_idx, lpm_cfg);
   2146             alpm_util_key_to_cfg(u, ipt, hw_key, lpm_cfg);
   2147             lpm_cfg->defip_sub_len = hw_len;
   2148             lpm_cfg->defip_vrf = ALPM_VRF_ID_TO_VRF(u, hw_vrf_id);
   2149             lpm_cfg->defip_flags |= (ipv6 ? BCM_L3_IP6 : 0);
   2150             lpm_cfg->defip_index = idx; /* TCAM table index */
   2151 
   2152             ALPM_VERB(("Hit Global High route in %s idx:%d.%d\n",
   2153                        TCAM_TBL_NAME(acb, pkm), idx, sub_idx));
   2154             return BCM_E_NONE;
   2155         }
   2156     }
   2157 
   2158     /* 2) Scanning for entire TCAM table sequentially
   2159        (Private VRF route has precedence over Global Low) */
   2160     idx_min = 0;
   2161     idx_cnt = tcam_table_size(u, pkm);
   2162     if (do_urpf) {
   2163         idx_min += tcam_table_size(u, pkm);
   2164     }
   2165     idx_end = idx_min + idx_cnt;
   2166 
   2167     for (idx = idx_min; idx < idx_end; idx++) {
   2168         _alpm_bkt_adata_t adata0;
   2169         ALPM_IER(tcam_entry_read(u, pkm, lpm_entry, idx, idx));
   2170 
   2171         for (sub_idx = 0; sub_idx < ALPM_TCAM_SUBCNT; sub_idx += step_size) {
   2172             rv_tcam = tcam_valid_entry_mode_get(u, pkm, lpm_entry,
   2173                           &step_size, &hw_pkm, &ipv6, &key_mode, sub_idx);
   2174             if (BCM_FAILURE(rv_tcam)) {
   2175                 if (rv_tcam == BCM_E_INTERNAL) {
   2176                     ALPM_ERR(("%s: Invalid Key Mode:%d or Key Type"
   2177                               " (IPv6):%d in idx:%d.%d\n",
   2178                               TCAM_TBL_NAME(acb, pkm), key_mode,
   2179                               ipv6, idx, sub_idx));
   2180                 }
   2181                 continue;
   2182             }
   2183 
   2184             if (pkm != hw_pkm) {
   2185                 continue;
   2186             }
   2187 
   2188             tcam_entry_vrf_id_get(u, pkm, lpm_entry, sub_idx, &hw_vrf_id);
   2189             if ((vrf_id != hw_vrf_id) && (hw_vrf_id < ALPM_VRF_ID_GLO(u))) {
   2190                 continue;
   2191             }
   2192             /* valid only when ((vrf_id == hw_vrf_id) ||
   2193                                 (hw_vrf_id >= ALPM_VRF_ID_GLO(u))) */
   2194             sal_memset(hw_key, 0, sizeof(hw_key));
   2195             hw_len = 0;
   2196             tcam_entry_to_key(u, pkm, lpm_entry, sub_idx, hw_key);
   2197             tcam_entry_pfx_len_get(u, pkm, lpm_entry, sub_idx, &hw_len);
   2198             if (hw_len > sw_len) { /* not match */
   2199                 continue;
   2200             }
   2201             alpm_util_len_to_mask(ipt, hw_len, hw_mask);
   2202 
   2203             /* hw_len <= sw_len: compare all hw_masked key */
   2204             key_ent_cnt = ALPM_KEY_ENT_CNT(ipt);
   2205             for (i = 0; i < key_ent_cnt; i++) {
   2206                 if ((sw_key[i] & hw_mask[i]) != (hw_key[i] & hw_mask[i])) {
   2207                     break;
   2208                 }
   2209             }
   2210             /* Not match */
   2211             if (i < key_ent_cnt) {
   2212                 continue;
   2213             }
   2214 
   2215             /* Hit in TCAM pivot (must be longest prefix due to order in TCAM) */
   2216             tcam_entry_adata_get(u, pkm, lpm_entry, sub_idx, &adata0);
   2217             use_alpm = !(adata0.defip_flags & BCM_L3_IPMC) &&
   2218                        ALPM_VRF_ID_HAS_BKT(u, vrf_id);
   2219             if (!use_alpm) {
   2220                 /* Global Low Direct route */
   2221                 ALPM_VERB(("Hit Global Low route in %s idx:%d.%d\n",
   2222                            TCAM_TBL_NAME(acb, pkm), idx, sub_idx));
   2223             } else {
   2224                 /* ALPM bucket lookup from top to bottom */
   2225                 tcam_entry_bdata_get(u, pkm, lpm_entry, sub_idx, fent);
   2226 
   2227                 alpm_util_cfg_to_key(u, ipt, lpm_cfg, sw_key);
   2228                 ALPM_IER(alpm_cb_bm_lookup(u, hw_vrf_id, pkm, acb, fent, 0,
   2229                                            hw_key, hw_len, idx, sub_idx, &adata0,
   2230                                            lpm_cfg, &hit_res, sw_key, sw_len));
   2231                 if (hit_res == ALPM_HIT) { /* Hit in bucket */
   2232                     return BCM_E_NONE;
   2233                 } else if (hit_res == ALPM_MISS) { /* Miss */
   2234                     ALPM_VERB(("Miss in %s idx:%d.%d\n",
   2235                                TCAM_TBL_NAME(acb, pkm), idx, sub_idx));
   2236                     return(BCM_E_NOT_FOUND);
   2237                 } else { /* hit_res == ALPM_MISS_USE_AD */
   2238                     ALPM_VERB(("Miss but use Associated data in %s idx:%d.%d\n",
   2239                                TCAM_TBL_NAME(acb, pkm), idx, sub_idx));
   2240                 }
   2241             }
   2242 
   2243             /* prepare returned lpm_cfg info */
   2244             tcam_entry_to_cfg(u, pkm, lpm_entry, sub_idx, lpm_cfg);
   2245             alpm_util_key_to_cfg(u, ipt, hw_key, lpm_cfg);
   2246             lpm_cfg->defip_sub_len = hw_len;
   2247             lpm_cfg->defip_vrf = ALPM_VRF_ID_TO_VRF(u, hw_vrf_id);
   2248             lpm_cfg->defip_flags |= (ipv6 ? BCM_L3_IP6 : 0);
   2249             lpm_cfg->defip_index = idx; /* TCAM Hw index */
   2250 
   2251             return BCM_E_NONE;
   2252         }
   2253     }
   2254 
   2255     /* Private VRF and Global Low Miss */
   2256     ALPM_VERB(("Search miss for given address\n"));
   2257 
   2258     return(BCM_E_NOT_FOUND);
   2259 }
   2260 
   2261 /*
   2262  * Function:
   2263  *      bcm_esw_alpm_find
   2264  * Purpose:
   2265  *      Get an entry from DEFIP table.
   2266  * Parameters:
   2267  *      u           - (IN)Device unit number.
   2268  *      lpm_cfg     - (IN/OUT)Key to lookup and found defip information.
   2269  *      nh_ecmp_idx - (OUT)Next hop or ecmp group index of bpm_route
   2270  * Returns:
   2271  *      BCM_E_XXX
   2272  */
   2273 int
   2274 bcm_esw_alpm_find(int u, _bcm_defip_cfg_t *lpm_cfg, int *nh_ecmp_idx)
   2275 {
   2276     int vrf_id = ALPM_LPM_VRF_ID(u, lpm_cfg);
   2277     int pkm = ALPM_LPM_PKM(u, lpm_cfg);
   2278     int ipt = ALPM_PKM2IPT(pkm);
   2279     uint32 sw_key[4] = {0};
   2280     int sw_len;
   2281 
   2282     /* Input parameters check */
   2283     if (NULL == lpm_cfg) {
   2284         return (BCM_E_PARAM);
   2285     }
   2286     alpm_util_ipmask_apply(u, lpm_cfg);
   2287 
   2288     sw_len = lpm_cfg->defip_sub_len;
   2289 
   2290     /* Perform hw lookup */
   2291     alpm_util_cfg_to_key(u, ipt, lpm_cfg, sw_key); /* get sw_key[4] */
   2292     ALPM_IER_PRT_EXCEPT(alpm_find_best_match(u, vrf_id, pkm, sw_key, sw_len, lpm_cfg), BCM_E_NOT_FOUND);
   2293     *nh_ecmp_idx = lpm_cfg->defip_ecmp_index;
   2294 
   2295     return (BCM_E_NONE);
   2296 }
   2297 
   2298 /*
   2299  * Function:
   2300  *      bcm_esw_alpm_sw_dump
   2301  * Purpose:
   2302  *      dump sw l3 (ALPM).
   2303  * Parameters:
   2304  *      u           - (IN)Device unit number.
   2305  */
   2306 void
   2307 bcm_esw_alpm_sw_dump(int u)
   2308 {
   2309     LOG_CLI((BSL_META_U(u, "\n  ALPM Info -\n")));
   2310     bcm_esw_alpm_debug_brief_show(u, 0, 0);
   2311     alpm_cb_stat_dump(u, 3);
   2312 }
   2313 
   2314 #endif /* ALPM_ENABLE */