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


      1 /*
      2  * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file.
      3  * 
      4  * Copyright 2007-2019 Broadcom Inc. All rights reserved.
      5  * 
      6  * File:    alpm_util.c
      7  * Purpose: ALPM util (device independent implementation).
      8  * Requires:
      9  */
     10 
     11 /* Implementation notes:
     12  */
     13 #include <shared/bsl.h>
     14 
     15 #include <soc/mem.h>
     16 #include <soc/drv.h>
     17 #include <soc/debug.h>
     18 #include <soc/error.h>
     19 #include <soc/lpm.h>
     20 #include <soc/trident2.h>
     21 #include <soc/tomahawk.h>
     22 #include <shared/bsl.h>
     23 
     24 #include <shared/util.h>
     25 #include <shared/l3.h>
     26 
     27 #if defined(ALPM_ENABLE)
     28 
     29 #include <bcm/l3.h>
     30 
     31 #include <bcm_int/esw/l3.h>
     32 #include <bcm_int/esw/firebolt.h>
     33 #include <bcm_int/esw/alpm.h>
     34 #include <bcm_int/esw/alpm_util.h>
     35 
     36 char *alpm_util_pkm_str[] = {
     37     "32B",
     38     "64B",
     39     "128"
     40 };
     41 
     42 char *alpm_util_ipt_str[] = {
     43     "V4",
     44     "V6"
     45 };
     46 
     47 char *alpm_util_acb_str[] = {
     48     "ACB.0",
     49     "ACB.1",
     50 };
     51 
     52 char alpm_tmpbuf[_ALPM_ERR_MSG_BUF_ENT_SZ];
     53 
     54 static uint32 alpm_mem_alloc_cnt;
     55 static uint32 alpm_mem_free_cnt;
     56 static uint32 alpm_mem_alloc_sz;
     57 
     58 void *
     59 alpm_util_alloc(unsigned int sz, char *s)
     60 {
     61     void *rv = NULL;
     62     rv = sal_alloc(sz, s);
     63     if (rv != NULL) {
     64         alpm_mem_alloc_cnt++;
     65         alpm_mem_alloc_sz += sz;
     66     }
     67 
     68     return rv;
     69 }
     70 
     71 void
     72 alpm_util_free(void *addr)
     73 {
     74     if (addr != NULL) {
     75         alpm_mem_free_cnt++;
     76         return sal_free(addr);
     77     }
     78 }
     79 
     80 void
     81 alpm_util_mem_stat_get(uint32 *alloc_cnt, uint32 *free_cnt)
     82 {
     83     if (alloc_cnt) {
     84         *alloc_cnt = alpm_mem_alloc_cnt;
     85     }
     86 
     87     if (free_cnt) {
     88         *free_cnt = alpm_mem_free_cnt;
     89     }
     90 }
     91 
     92 void
     93 alpm_util_mem_stat_clear()
     94 {
     95     alpm_mem_alloc_cnt = 0;
     96     alpm_mem_free_cnt = 0;
     97     alpm_mem_alloc_sz = 0;
     98 }
     99 
    100 void
    101 alpm_util_snprintf(const char *fmt, ...)
    102 {
    103     va_list ap;
    104 
    105     va_start(ap, fmt);
    106     sal_vsnprintf(alpm_tmpbuf + sal_strlen(alpm_tmpbuf), _ALPM_ERR_MSG_BUF_ENT_SZ - 1, fmt, ap);
    107     va_end(ap);
    108 }
    109 
    110 int
    111 alpm_util_trie_max_key_len(int u, int ipt)
    112 {
    113     int max_key_len;
    114 
    115     max_key_len = ALPM_IS_IPV4(ipt) ?
    116                        _MAX_KEY_LEN_48_ :
    117                        _MAX_KEY_LEN_144_;
    118     return max_key_len;
    119 }
    120 
    121 int
    122 alpm_util_trie_max_split_len(int u, int pkm)
    123 {
    124     int max_split_len;
    125 
    126     max_split_len = ALPMC(u)->_alpm_spl[pkm];
    127 
    128     return max_split_len;
    129 }
    130 
    131 void
    132 alpm_util_trie_pfx_print(int u, int ipt, uint32 *pfx, uint32 len, const char *str)
    133 {
    134     uint32 key[5];
    135 
    136     sal_memset(key, 0x0, sizeof(key));
    137     alpm_trie_pfx_to_key(u, ipt, pfx, len, key);
    138     if (ALPM_IS_IPV4(ipt)) {
    139         cli_out("%s v4 key = 0x%08x/%d\n", str, key[0], len);
    140     } else {
    141         cli_out("%s v6 key = 0x%08x 0x%08x 0x%08x 0x%08x/%d\n",
    142                 str, key[3], key[2], key[1], key[0], len);
    143     }
    144 }
    145 
    146 int
    147 alpm_util_trie_pvt_node_print(alpm_lib_trie_node_t *trie, void *datum)
    148 {
    149     if (trie != NULL) {
    150         cli_out("trie: %p, type %s, "
    151                 "count:%d Child[0]:%p Child[1]:%p ",
    152                 trie, (trie->type == trieNodeTypePayload) ? "P" : "I",
    153                 trie->count, trie->child[0],
    154                 trie->child[1]);
    155         if (trie->type == trieNodeTypePayload) {
    156             int ipt, vrf_id;
    157             char vrf_str[16] = {0};
    158             _alpm_pvt_node_t *pvt_node = (_alpm_pvt_node_t *)trie;
    159 
    160             ipt = PVT_BKT_IPT(pvt_node);
    161             vrf_id = pvt_node->vrf_id;
    162             sal_sprintf(vrf_str, "%d ", vrf_id);
    163             alpm_util_trie_pfx_print(0, ipt,
    164                 pvt_node->key, pvt_node->key_len, vrf_str);
    165         } else {
    166             cli_out("\n");
    167         }
    168     }
    169 
    170     return SOC_E_NONE;
    171 }
    172 
    173 int
    174 alpm_util_trie_bkt_node_print(alpm_lib_trie_node_t *trie, void *datum)
    175 {
    176     if (trie != NULL) {
    177         cli_out("trie: %p, type %s, "
    178                 "count:%d Child[0]:%p Child[1]:%p ",
    179                 trie, (trie->type == trieNodeTypePayload) ? "P" : "I",
    180                 trie->count, trie->child[0],
    181                 trie->child[1]);
    182         if (trie->type == trieNodeTypePayload) {
    183             int *ipt = (int *)datum;
    184             _alpm_bkt_node_t *bkt_node = (_alpm_bkt_node_t *)trie;
    185 
    186             alpm_util_trie_pfx_print(0, *ipt,
    187                 bkt_node->key, bkt_node->key_len, "vrf");
    188         } else {
    189             cli_out("\n");
    190         }
    191     }
    192 
    193     return SOC_E_NONE;
    194 }
    195 
    196 void
    197 alpm_util_adata_cfg_to_trie(int unit, _bcm_defip_cfg_t *lpm_cfg,
    198                             _alpm_bkt_adata_t *bkt_adata)
    199 {
    200     /* lpm_cfg->defip_ecmp_index is used to store nh_ecmp_idx */
    201     bkt_adata->defip_flags               = lpm_cfg->defip_flags;
    202     if (bkt_adata->defip_flags & BCM_L3_IPMC) {
    203         bkt_adata->defip_ecmp_index          = lpm_cfg->defip_mc_group;
    204     } else {
    205         bkt_adata->defip_ecmp_index          = lpm_cfg->defip_ecmp_index;
    206     }
    207     bkt_adata->defip_prio                = lpm_cfg->defip_prio;
    208     bkt_adata->defip_lookup_class        = lpm_cfg->defip_lookup_class;
    209     bkt_adata->defip_flex_ctr_pool       = lpm_cfg->defip_flex_ctr_pool;
    210     bkt_adata->defip_flex_ctr_mode       = lpm_cfg->defip_flex_ctr_mode;
    211     bkt_adata->defip_flex_ctr_base_id    = lpm_cfg->defip_flex_ctr_base_id;
    212     return ;
    213 }
    214 
    215 void
    216 alpm_util_adata_trie_to_cfg(int unit, _alpm_bkt_adata_t *bkt_adata,
    217                             _bcm_defip_cfg_t *lpm_cfg)
    218 {
    219     /* lpm_cfg->defip_ecmp_index is used to store nh_ecmp_idx */
    220     lpm_cfg->defip_flags               = bkt_adata->defip_flags;
    221     if (bkt_adata->defip_flags & BCM_L3_IPMC) {
    222         lpm_cfg->defip_mc_group            = bkt_adata->defip_ecmp_index;
    223     } else {
    224         lpm_cfg->defip_ecmp_index          = bkt_adata->defip_ecmp_index;
    225     }
    226     lpm_cfg->defip_prio                = bkt_adata->defip_prio;
    227     lpm_cfg->defip_lookup_class        = bkt_adata->defip_lookup_class;
    228     lpm_cfg->defip_flex_ctr_pool       = bkt_adata->defip_flex_ctr_pool;
    229     lpm_cfg->defip_flex_ctr_mode       = bkt_adata->defip_flex_ctr_mode;
    230     lpm_cfg->defip_flex_ctr_base_id    = bkt_adata->defip_flex_ctr_base_id;
    231     return ;
    232 }
    233 
    234 void
    235 alpm_util_adata_zero_cfg(int unit, _bcm_defip_cfg_t *lpm_cfg)
    236 {
    237     lpm_cfg->defip_flags &=
    238         ~(BCM_L3_RPE | BCM_L3_DST_DISCARD | BCM_L3_MULTIPATH);
    239     lpm_cfg->defip_ecmp_index = 0;
    240     lpm_cfg->defip_mc_group = 0;
    241     lpm_cfg->defip_prio = 0;
    242     lpm_cfg->defip_lookup_class = 0;
    243     lpm_cfg->defip_flex_ctr_pool = 0;
    244     lpm_cfg->defip_flex_ctr_mode = 0;
    245     lpm_cfg->defip_flex_ctr_base_id = 0;
    246     return ;
    247 }
    248 
    249 uint8
    250 alpm_util_route_type_get(int u, _bcm_defip_cfg_t *lpm_cfg)
    251 {
    252     int vrf_id = (lpm_cfg == NULL? 1 : ALPM_LPM_VRF_ID(u, lpm_cfg));
    253     int ipt = (lpm_cfg == NULL ? ALPM_IPT_V4 : ALPM_LPM_IPT(u, lpm_cfg));
    254     _alpm_cb_t *acb = ACB_VRF_BTM(u, vrf_id);
    255 
    256     if (ACB_BKT_FIXED_FMT(acb, vrf_id)) {
    257         return soc_feature(u, soc_feature_alpm_flex_stat) ? 1 : 0;
    258     } else {
    259         return ACB_VRF_DB_TYPE(u, acb, vrf_id, ipt);
    260     }
    261 }
    262 
    263 int
    264 alpm_util_route_type_check(int u, _bcm_defip_cfg_t *lpm_cfg)
    265 {
    266     uint8 my_route_md;
    267     _alpm_cb_t *acb = ACB_VRF_BTM(u, ALPM_LPM_VRF_ID(u, lpm_cfg));
    268 
    269     my_route_md = alpm_util_route_type_get(u, lpm_cfg);
    270 
    271     if (!ACB_BKT_FIXED_FMT(acb, 1)) {
    272         /* check non zero PRI or CLASS_ID */
    273         if (lpm_cfg->defip_prio || lpm_cfg->defip_lookup_class) {
    274             if (my_route_md == 0) {
    275                 ALPM_ERR(("**ROUTE.CHECK:route mode conflict - "
    276                           "non zero PRI or CLASS_ID in reduced mode\n"));
    277                 return BCM_E_PARAM;
    278             }
    279         }
    280     }
    281     return BCM_E_NONE;
    282 }
    283 
    284 int
    285 alpm_util_def_check(int u, _bcm_defip_cfg_t *lpm_cfg, int is_add)
    286 {
    287     _alpm_cb_t     *acb;
    288     int vrf_id = ALPM_LPM_VRF_ID(u, lpm_cfg);
    289     int ipt = ALPM_LPM_IPT(u, lpm_cfg);
    290 
    291     /* For routes go to SRAM */
    292     /* combined search mode protection */
    293     acb = ACB_VRF_BTM(u, vrf_id);
    294     if (is_add) {
    295         if (VRF_ROUTE_CNT(acb, vrf_id, ipt) == 0 &&
    296             ALPM_MODE_CHK(u, BCM_ALPM_MODE_COMBINED) &&
    297             lpm_cfg->defip_vrf != BCM_L3_VRF_GLOBAL &&
    298             lpm_cfg->defip_sub_len != 0) {
    299             ALPM_ERR(("**DEF.CHECK: First route in VRF %d has to "
    300                       "be a default route in this mode\n", vrf_id));
    301             return BCM_E_PARAM;
    302         }
    303     } else {
    304         if (VRF_ROUTE_CNT(acb, vrf_id, ipt) > 1 &&
    305             ALPM_MODE_CHK(u, BCM_ALPM_MODE_COMBINED) &&
    306             lpm_cfg->defip_vrf != BCM_L3_VRF_GLOBAL &&
    307             lpm_cfg->defip_sub_len == 0) {
    308             ALPM_ERR(("**DEF.CHECK: Default route in VRF %d has to "
    309                       "be the last route to delete in this mode\n", vrf_id));
    310             return BCM_E_PARAM;
    311         }
    312     }
    313 
    314     return BCM_E_NONE;
    315 }
    316 
    317 int
    318 alpm_util_is_my_pivot(int u, uint32 *trie_key, uint32 trie_len,
    319                       uint32 *pvt_key, uint32 pvt_len)
    320 {
    321     /* TD3ALPMTBD */
    322     /*     ALPM_IS_MY_PIVOT() */
    323     return BCM_E_NONE;
    324 }
    325 
    326 /* Return ip string from key and length, or bkt_node/pvt_node if not NULL */
    327 int
    328 alpm_util_key_to_str(int u, int ipt, char *ipstr, uint32 *key, uint32 key_len,
    329                      _alpm_bkt_node_t *bkt_node, _alpm_pvt_node_t *pvt_node)
    330 {
    331     char ip_buf[IP6ADDR_STR_LEN]; /* ipstr in format x.x.x.x/123 */
    332     _bcm_defip_cfg_t lpm_cfg;
    333 
    334     if (!ipstr) {
    335         return BCM_E_PARAM;
    336     }
    337 
    338     sal_memset(&lpm_cfg, 0, sizeof(lpm_cfg));
    339 
    340     /* defip_flags */
    341     if (ALPM_IS_IPV6(ipt)) {
    342         lpm_cfg.defip_flags |= BCM_L3_IP6;
    343     }
    344 
    345     if (bkt_node) {
    346         key_len = bkt_node->key_len;
    347         alpm_trie_pfx_to_cfg(u, bkt_node->key, bkt_node->key_len, &lpm_cfg);
    348     } else if (pvt_node) {
    349         key_len = pvt_node->key_len;
    350         alpm_trie_pfx_to_cfg(u, pvt_node->key, pvt_node->key_len, &lpm_cfg);
    351     } else if (key) {
    352         alpm_trie_pfx_to_cfg(u, key, key_len, &lpm_cfg);
    353     }
    354 
    355     if (ALPM_IS_IPV4(ipt)) {
    356         alpm_util_fmt_ipaddr(ip_buf, lpm_cfg.defip_ip_addr);
    357     } else {
    358         alpm_util_fmt_ip6addr(ip_buf, lpm_cfg.defip_ip6_addr);
    359     }
    360 
    361     sal_sprintf(ipstr, "%s/%d", ip_buf, key_len);
    362 
    363     return BCM_E_NONE;
    364 }
    365 
    366 void
    367 alpm_util_cfg_to_key(int u, int ipt, _bcm_defip_cfg_t *lpm_cfg, uint32 *key)
    368 {
    369     uint8  *ip6;
    370 
    371     if (ALPM_IS_IPV4(ipt)) {
    372         key[0] = lpm_cfg->defip_ip_addr;
    373     } else {
    374         ip6 = lpm_cfg->defip_ip6_addr;
    375         key[0] = ip6[12] << 24 | ip6[13] << 16 | ip6[14] << 8 | ip6[15];
    376         key[1] = ip6[8] << 24 | ip6[9] << 16 | ip6[10] << 8 | ip6[11];
    377         key[2] = ip6[4] << 24 | ip6[5] << 16 | ip6[6] << 8 | ip6[7];
    378         key[3] = ip6[0] << 24 | ip6[1] << 16 | ip6[2] << 8 | ip6[3];
    379     }
    380 
    381     return ;
    382 }
    383 
    384 void
    385 alpm_util_cfg_to_msk(int u, int ipt, _bcm_defip_cfg_t *lpm_cfg, uint32 *msk)
    386 {
    387     bcm_ip6_t ip6;
    388 
    389     if (ALPM_IS_IPV4(ipt)) {
    390         msk[0] = BCM_IP4_MASKLEN_TO_ADDR(lpm_cfg->defip_sub_len);
    391     } else {
    392         bcm_ip6_mask_create(ip6, lpm_cfg->defip_sub_len);
    393         msk[0] = ip6[12] << 24 | ip6[13] << 16 | ip6[14] << 8 | ip6[15];
    394         msk[1] = ip6[8] << 24 | ip6[9] << 16 | ip6[10] << 8 | ip6[11];
    395         msk[2] = ip6[4] << 24 | ip6[5] << 16 | ip6[6] << 8 | ip6[7];
    396         msk[3] = ip6[0] << 24 | ip6[1] << 16 | ip6[2] << 8 | ip6[3];
    397     }
    398 
    399     return ;
    400 }
    401 
    402 void
    403 alpm_util_ipmask_apply(int u, _bcm_defip_cfg_t *lpm_cfg)
    404 {
    405     uint8 *ip6;
    406     bcm_ip_t mask4;
    407     bcm_ip6_t mask6;
    408 
    409     if (lpm_cfg->defip_flags & BCM_L3_IP6) {
    410         /* Unchanged byte count.    */
    411         int idx = lpm_cfg->defip_sub_len / 8;
    412 
    413         bcm_ip6_mask_create(mask6, lpm_cfg->defip_sub_len);
    414         ip6 = lpm_cfg->defip_ip6_addr;
    415 
    416         /* Apply subnet mask */
    417         if (idx < BCM_IP6_ADDRLEN) {
    418             ip6[idx] &= mask6[idx];
    419             for (idx++; idx < BCM_IP6_ADDRLEN; idx++) {
    420                 ip6[idx] = 0;   /* Reset rest of bytes.     */
    421             }
    422         }
    423     } else {
    424         mask4 = BCM_IP4_MASKLEN_TO_ADDR(lpm_cfg->defip_sub_len);
    425         /* Apply subnet mask. */
    426         lpm_cfg->defip_ip_addr &= mask4;
    427     }
    428 
    429     return ;
    430 }
    431 
    432 void
    433 alpm_util_bnk_range_print(int u, SHR_BITDCL *bnk_bmp, int bnk_sz,
    434                           int bnk_per_row, int start, int end)
    435 {
    436     int i, k;
    437 
    438     assert(start >= 0);
    439     assert(end < bnk_sz);
    440 
    441     cli_out("%15s", "");
    442     for (k = 0; k < bnk_per_row; k++) {
    443         int val = (start + k) % 10;
    444         if (val == 0) {
    445             cli_out("%2d", (start + k) % 100);
    446         } else {
    447             cli_out(" %d", val);
    448         }
    449     }
    450     cli_out("\n");
    451 
    452     for (i = start; i <= end; i += bnk_per_row) {
    453         int row_end;
    454 
    455         cli_out("%15s", "");
    456         for (k = 0; k < bnk_per_row; k++) {
    457             cli_out("--");
    458         }
    459         cli_out("-\n");
    460         cli_out("BNK%05d-%05d |", i, i + bnk_per_row - 1);
    461         row_end = end > (i+bnk_per_row) ? i+bnk_per_row-1 : end;
    462         for (k = i; k <= row_end; k++) {
    463             cli_out("%s|", SHR_BITGET(bnk_bmp, k) ? "#" : " ");
    464         }
    465         cli_out("\n");
    466     }
    467     cli_out("%15s", "");
    468     for (k = 0; k < bnk_per_row; k++) {
    469         cli_out("--");
    470     }
    471     cli_out("-\n");
    472 
    473     return ;
    474 }
    475 
    476 void
    477 alpm_util_fmt_tbl_util(int unit, char *buf)
    478 {
    479     int i, ipt, p;
    480     int vcnt_all = 0;
    481     int cnt_all = 0;
    482 
    483     _alpm_cb_t *acb;
    484     _alpm_bkt_pool_conf_t *bpc;
    485 
    486     (void)bcm_esw_alpm_tcam_state_free_get(unit, -1, &cnt_all, &vcnt_all);
    487     cnt_all += vcnt_all;
    488 
    489     if (cnt_all != 0) {
    490         sal_sprintf(buf+strlen(buf), "L1:%d.%d%% ",
    491                     vcnt_all * 100 / cnt_all,
    492                     vcnt_all * 1000 / cnt_all % 10);
    493     }
    494 
    495     for (i = 0; i < ACB_CNT(unit); i++) {
    496         acb = ACB(unit, i);
    497         for (p = 0; p < ALPM_BKT_PID_CNT; p++) {
    498             bpc = ACB_BKT_POOL(acb, p);
    499             if (p > 0 && bpc == ACB_BKT_POOL(acb, p-1)) {
    500                 continue;
    501             }
    502             for (ipt = ALPM_IPT_V4; ipt < ALPM_IPT_CNT; ipt++) {
    503                 if (ipt > ALPM_IPT_V4 &&
    504                     BPC_BNK_INFO(bpc, ipt) ==
    505                     BPC_BNK_INFO(bpc, ipt - 1)) {
    506                     continue;
    507                 }
    508                 sal_sprintf(buf+strlen(buf), "L%d.P%d(%s):%d.%d%% ",
    509                     acb->acb_idx + 2, p,
    510                     alpm_util_ipt_str[ipt],
    511                     BPC_BNK_CNT(bpc) ?
    512                         (BPC_BNK_USED(bpc, ipt) * 100 / BPC_BNK_CNT(bpc)) : 0,
    513                     BPC_BNK_CNT(bpc) ?
    514                         (BPC_BNK_USED(bpc, ipt) * 1000 / BPC_BNK_CNT(bpc) % 10) : 0);
    515             }
    516         }
    517     }
    518 }
    519 
    520 void
    521 alpm_util_fmt_bkt_info(char *buf, int vrf_id, _alpm_cb_t *acb, _alpm_bkt_info_t *bkt_info)
    522 {
    523     int i;
    524     /* ACB.0 BNK%d[%d(%d %d)_%d(%d %d)_%d(%d %d)_%d(%d %d)] CNT[%d %d %d %d] */
    525     sal_sprintf(buf+strlen(buf), "ACB%d->", ACB_IDX(acb));
    526     sal_sprintf(buf+strlen(buf), "ROFS%d[", BI_ROFS(bkt_info));
    527     for (i = BI_ROFS(bkt_info); i < BI_ROFS(bkt_info) + ALPM_BPB_MAX; i++) {
    528         int bnk = i % ALPM_BPB_MAX;
    529         int fmt = bkt_info->bnk_fmt[bnk];
    530         if (!BI_BNK_IS_USED(bkt_info, bnk)) {
    531             continue;
    532         }
    533         sal_sprintf(buf+strlen(buf), "B%d(%d)(%d,%d/%d)_", bnk,
    534                     bkt_info->bnk_fmt[bnk],
    535                     ACB_FMT_PFX_LEN(acb, vrf_id, fmt),
    536                     _shr_popcount(bkt_info->vet_bmp[bnk]),
    537                     ACB_FMT_ENT_MAX(acb, vrf_id, fmt));
    538     }
    539     sal_sprintf(buf+strlen(buf), "]");
    540 }
    541 
    542 void
    543 alpm_util_fmt_ipaddr(char buf[SAL_IPADDR_STR_LEN], ip_addr_t ipaddr)
    544 {
    545     sal_sprintf(buf, "%d.%d.%d.%d",
    546             (ipaddr >> 24) & 0xff, (ipaddr >> 16) & 0xff,
    547             (ipaddr >> 8) & 0xff, ipaddr & 0xff);
    548 }
    549 
    550 void
    551 alpm_util_fmt_ip6addr(char buf[IP6ADDR_STR_LEN], ip6_addr_t ipaddr)
    552 {
    553     sal_sprintf(buf, "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x",
    554             (((uint16)ipaddr[0] << 8) | ipaddr[1]),
    555             (((uint16)ipaddr[2] << 8) | ipaddr[3]),
    556             (((uint16)ipaddr[4] << 8) | ipaddr[5]),
    557             (((uint16)ipaddr[6] << 8) | ipaddr[7]),
    558             (((uint16)ipaddr[8] << 8) | ipaddr[9]),
    559             (((uint16)ipaddr[10] << 8) | ipaddr[11]),
    560             (((uint16)ipaddr[12] << 8) | ipaddr[13]),
    561             (((uint16)ipaddr[14] << 8) | ipaddr[15]));
    562 }
    563 
    564 /* Get pivot index: idx & sub_idx (or ent)  */
    565 int
    566 alpm_util_pvt_idx_get(int u, _alpm_cb_t *acb, _alpm_pvt_node_t *pvt_node, int *idx, int *sub_idx)
    567 {
    568     int pvt_idx;
    569 
    570     if (ACB_HAS_TCAM(acb)) {
    571         pvt_idx = PVT_IDX(pvt_node); /* tcam_idx */
    572         if (PVT_BKT_PKM(pvt_node) == ALPM_PKM_32B) {
    573             *idx = pvt_idx >> 1;
    574             *sub_idx = pvt_idx & 0x01;
    575         } else {
    576             *idx = pvt_idx;
    577             *sub_idx = 0;
    578         }
    579     } else {
    580         /* Get upper CB bucket ent_idx for the pivot */
    581         ALPM_IER(alpm_pvt_ent_idx_get(u, acb, pvt_node, &pvt_idx));
    582         *idx = ALPM_TAB_IDX_GET(pvt_idx);
    583         *sub_idx = ALPM_IDX_TO_ENT(pvt_idx);
    584     }
    585 
    586     return BCM_E_NONE;
    587 }
    588 
    589 void
    590 alpm_util_key_to_cfg(int u, int ipt, uint32 *key, _bcm_defip_cfg_t *lpm_cfg)
    591 {
    592     uint8  *ip6 = lpm_cfg->defip_ip6_addr;
    593 
    594     if (ALPM_IS_IPV4(ipt)) {
    595         lpm_cfg->defip_ip_addr = key[0];
    596     } else {
    597         ip6[0]  = (uint8) (key[3] >> 24);
    598         ip6[1]  = (uint8) (key[3] >> 16 & 0xff);
    599         ip6[2]  = (uint8) (key[3] >> 8 & 0xff);
    600         ip6[3]  = (uint8) (key[3] & 0xff);
    601         ip6[4]  = (uint8) (key[2] >> 24);
    602         ip6[5]  = (uint8) (key[2] >> 16 & 0xff);
    603         ip6[6]  = (uint8) (key[2] >> 8 & 0xff);
    604         ip6[7]  = (uint8) (key[2] & 0xff);
    605         ip6[8]  = (uint8) (key[1] >> 24);
    606         ip6[9]  = (uint8) (key[1] >> 16 & 0xff);
    607         ip6[10] = (uint8) (key[1] >> 8 & 0xff);
    608         ip6[11] = (uint8) (key[1] & 0xff);
    609         ip6[12] = (uint8) (key[0] >> 24);
    610         ip6[13] = (uint8) (key[0] >> 16 & 0xff);
    611         ip6[14] = (uint8) (key[0] >> 8 & 0xff);
    612         ip6[15] = (uint8) (key[0] & 0xff);
    613     }
    614     return ;
    615 }
    616 
    617 /*
    618  * Function:
    619  *      alpm_util_len_to_mask
    620  * Purpose:
    621  *      Convert IPv4 or IPv6 key length to mask.
    622  * Parameters:
    623  *      ipt      - (IN)Packing mode (V4, V6)
    624  *      len      - (IN)Key length
    625  *      mask     - (OUT)Key mask
    626  */
    627 void
    628 alpm_util_len_to_mask(int ipt, uint32 len, uint32 *mask)
    629 {
    630     int i;
    631     int cnt = ALPM_KEY_ENT_CNT(ipt);
    632 
    633     for (i = 0; i < cnt; i++) { /* initialize all mask to 0 */
    634         mask[i] = 0;
    635     }
    636 
    637     for (i = cnt - 1; i >= 0; i--) {
    638         if (len <= 32) {
    639             break;
    640         }
    641         mask[i] = 0xffffffff;
    642         len -= 32;
    643     }
    644     mask[i] = ~_SHIFT_RIGHT(0xffffffff, len);
    645     return;
    646 }
    647 
    648 /* Convert ALPM ASSOC_DATA and KEY info into lpm_cfg */
    649 int
    650 alpm_util_cfg_construct(int u, int vrf_id, int ipt, uint32 *key, int key_len,
    651                         _alpm_bkt_adata_t *adata, _bcm_defip_cfg_t *lpm_cfg)
    652 {
    653     sal_memset(lpm_cfg, 0, sizeof(_bcm_defip_cfg_t));
    654     alpm_util_adata_trie_to_cfg(u, adata, lpm_cfg);
    655     alpm_util_key_to_cfg(u, ipt, key, lpm_cfg);
    656     lpm_cfg->defip_sub_len = key_len;
    657     lpm_cfg->defip_vrf = ALPM_VRF_ID_TO_VRF(u, vrf_id);
    658     /* TD3ALPMTBD, defip_flags is not determined by pkm */
    659     lpm_cfg->defip_flags |= (ALPM_IS_IPV4(ipt) ? 0 : BCM_L3_IP6);
    660     if (lpm_cfg->defip_flags & BCM_L3_MULTIPATH) {
    661         lpm_cfg->defip_ecmp = 1;
    662     }
    663 
    664     return BCM_E_NONE;
    665 }
    666 
    667 /*
    668  * Function:
    669  *      alpm_util_route_capacity_get
    670  * Purpose:
    671  *      Get the min or max capacity for ALPM routes from tables:
    672  * L3_DEFIP_ALPM_IPV4, L3_DEFIP_ALPM_IPV6_64, L3_DEFIP_ALPM_IPV6_128
    673  *
    674  * Parameters:
    675  *      u           - Device unit
    676  *      mem         - Legacy memory type
    677  *      max_entries - Maximum result returned.
    678  *      min_entries - Minimum result returned.
    679  */
    680 int
    681 alpm_util_route_capacity_get(int u, soc_mem_t mem,
    682                              int *max_entries, int *min_entries)
    683 {
    684     int rv = BCM_E_NONE;
    685 
    686     if (max_entries == NULL && min_entries == NULL) {
    687         return BCM_E_PARAM;
    688     }
    689 
    690     rv = ALPM_DRV(u)->alpm_cap_get(u, mem, max_entries, min_entries);
    691 
    692     return rv;
    693 }
    694 
    695 int
    696 alpm_util_bkt_info_get(int u, int vrf_id, int ipt, int pvt_pkm,
    697                        _alpm_cb_t *acb, void *e,
    698                        int sub_idx, _alpm_bkt_info_t *bkt_info,
    699                        int *kshift, int *def_miss)
    700 {
    701     int rv = BCM_E_UNAVAIL;
    702     _alpm_ent_info_t info;
    703 
    704     sal_memset(&info, 0, sizeof(info));
    705     info.action_mask = ALPM_INFO_MASK_ALPM_DATA;
    706     info.vrf_id = vrf_id;
    707     info.pvt_pkm = pvt_pkm;
    708     info.ipt = ipt;
    709     info.ent_fmt = sub_idx;
    710 
    711     rv = ALPM_DRV(u)->alpm_ent_selective_get(u, acb, e, &info);
    712     if (BCM_SUCCESS(rv)) {
    713         if (bkt_info) {
    714             sal_memcpy(bkt_info, &info.bkt_info, sizeof(_alpm_bkt_info_t));
    715         }
    716         if (kshift) {
    717             *kshift = info.kshift;
    718         }
    719         if (def_miss) {
    720             *def_miss = info.default_miss;
    721         }
    722     }
    723     return rv;
    724 }
    725 
    726 /* Return default (minimum) bank format */
    727 uint8
    728 alpm_util_bkt_def_fmt_get(int u, _alpm_cb_t *acb, int vrf_id, int ipt)
    729 {
    730     return ALPM_DRV(u)->alpm_bkt_def_fmt_get(u, acb, vrf_id, ipt);
    731 }
    732 
    733 /* Return Reduced/Full bank format type for a given fmt (for warmboot use) */
    734 int16
    735 alpm_util_bkt_fmt_type_get(int u, int vrf_id, _alpm_cb_t *acb, uint8 fmt)
    736 {
    737     return ALPM_DRV(u)->alpm_bkt_fmt_type_get(u, vrf_id, acb, fmt);
    738 }
    739 
    740 int
    741 alpm_util_bkt_token_bnks(int u, _alpm_cb_t *acb, int vrf_id,
    742                          _alpm_pvt_node_t *pvt_node)
    743 {
    744     int used_cnt = 0;
    745     int i, bnk_pbk;
    746     SHR_BITDCL *bnk_bmp;
    747     _alpm_bkt_pool_conf_t *bp_conf;
    748     _alpm_pvt_node_t *tmp_node;
    749 
    750     bp_conf = ACB_BKT_VRF_POOL(acb, vrf_id);
    751     bnk_bmp = BPC_BNK_BMP(bp_conf, PVT_BKT_IPT(pvt_node));
    752     bnk_pbk = BPC_BNK_PER_BKT(bp_conf);
    753 
    754     for (i = PVT_BKT_IDX(pvt_node) * bnk_pbk;
    755          i < (PVT_BKT_IDX(pvt_node) + 1) * bnk_pbk; i++) {
    756         if (SHR_BITGET(bnk_bmp, i)) {
    757             int tab_idx =
    758                 ALPM_TAB_IDX_GET_BKT_BNK(acb, 0, i / bnk_pbk, i % bnk_pbk);
    759             tmp_node =
    760                 (_alpm_pvt_node_t *)ACB_VRF_PVT_PTR(acb, vrf_id, tab_idx);
    761             if (tmp_node && tmp_node != pvt_node) {
    762                 used_cnt ++;
    763             }
    764         }
    765     }
    766 
    767     return used_cnt;
    768 }
    769 
    770 int
    771 alpm_util_ent_ent_get(int u, int vrf_id, _alpm_cb_t *acb, void *e,
    772                       uint32 fmt, int eid, void *entry)
    773 {
    774     int rv = BCM_E_UNAVAIL;
    775     rv = ALPM_DRV(u)->alpm_ent_ent_get(u, vrf_id, acb, e, fmt, eid, entry);
    776     return rv;
    777 }
    778 
    779 void
    780 alpm_util_pfx_cat(int u, int ipt, uint32 *pfx1, int len1, uint32 *pfx2, int len2,
    781                   uint32 *new_pfx, int *new_len)
    782 {
    783     int dst_offset;
    784     int max_pfx_len[] = {32, 128};
    785 
    786     *new_len = len1 + len2;
    787     dst_offset = max_pfx_len[ipt] - *new_len;
    788     sal_memcpy(new_pfx, pfx1, sizeof(uint32) * 4);
    789     SHR_BITCOPY_RANGE(new_pfx, dst_offset, pfx2, 0, len2);
    790 }
    791 
    792 /*
    793  * Function:
    794  *      alpm_util_pfx_len_cmp
    795  * Purpose:
    796  *      Compare two prefix length.
    797  * Returns:
    798  *      a<=>b
    799  */
    800 int
    801 alpm_util_pfx_len_cmp(void *a, void *b)
    802 {
    803     _alpm_bkt_node_t **first;
    804     _alpm_bkt_node_t **second;
    805 
    806     first = (_alpm_bkt_node_t **) a;
    807     second = (_alpm_bkt_node_t **) b;
    808 
    809     if ((*first)->key_len < (*second)->key_len) {
    810         return 1;
    811     } else if ((*first)->key_len > (*second)->key_len) {
    812         return -1;
    813     }
    814     return 0;
    815 }
    816 
    817 int
    818 alpm_util_bkt_pfx_get(int u, int vrf_id, _alpm_cb_t *acb, void *e, uint32 fmt,
    819                       uint32 *new_key, int *new_len, uint32 *valid)
    820 {
    821     int rv = BCM_E_UNAVAIL;
    822     _alpm_ent_info_t info;
    823 
    824     sal_memset(&info, 0, sizeof(info));
    825     info.action_mask = ALPM_INFO_MASK_VALID | ALPM_INFO_MASK_KEYLEN;
    826     info.ent_fmt = fmt;
    827     info.vrf_id  = vrf_id;
    828 
    829     rv = ALPM_DRV(u)->alpm_ent_selective_get(u, acb, e, &info);
    830     if (BCM_SUCCESS(rv)) {
    831         *valid = info.ent_valid;
    832         sal_memcpy(new_key, info.key, sizeof(uint32) * 4);
    833         *new_len = info.key_len;
    834     }
    835     return rv;
    836 }
    837 
    838 int
    839 alpm_util_bkt_adata_get(int u, int vrf_id, int ipt, _alpm_cb_t *acb, void *e,
    840                         int fmt, _alpm_bkt_adata_t *adata, int *arg1)
    841 {
    842     int rv = BCM_E_UNAVAIL;
    843     _alpm_ent_info_t info;
    844 
    845     sal_memset(&info, 0, sizeof(info));
    846     info.action_mask = ALPM_INFO_MASK_ASSOC_DATA;
    847     info.ent_fmt = fmt;
    848     info.ipt = ipt;
    849     info.vrf_id = vrf_id;
    850 
    851     rv = ALPM_DRV(u)->alpm_ent_selective_get(u, acb, e, &info);
    852     if (BCM_SUCCESS(rv)) {
    853         sal_memcpy(adata, &info.adata, sizeof(_alpm_bkt_adata_t));
    854         if (arg1 != NULL) {
    855             *arg1 = BI_SUB_BKT_IDX(&info.bkt_info);
    856         }
    857     }
    858     return rv;
    859 }
    860 
    861 int
    862 alpm_util_ent_data_get(int u, int vrf_id, int ipt, _alpm_cb_t *acb, void *e,
    863                        int fmt, void *fent1)
    864 {
    865 
    866     int rv = BCM_E_UNAVAIL;
    867     _alpm_ent_info_t info;
    868 
    869     sal_memset(&info, 0, sizeof(info));
    870     info.action_mask = ALPM_INFO_MASK_ALPM_DATA_RAW;
    871     info.alpm_data_raw = fent1;
    872     info.ent_fmt = fmt;
    873     info.ipt = ipt;
    874     info.vrf_id = vrf_id;
    875 
    876     rv = ALPM_DRV(u)->alpm_ent_selective_get(u, acb, e, &info);
    877     return rv;
    878 }
    879 
    880 int
    881 alpm_util_ent_phy_idx_get(int u, _alpm_cb_t *acb, int vrf_id, int index)
    882 {
    883     int phy_index;
    884     _alpm_tbl_t tbl;
    885 
    886     tbl = ACB_BKT_TBL(acb, vrf_id);
    887     phy_index = ALPM_DRV(u)->mem_ent_phy_idx_get(u, acb, tbl, index);
    888 
    889     return phy_index;
    890 }
    891 
    892 int
    893 tcam_table_size(int u, int pkm)
    894 {
    895     int rv = BCM_E_UNAVAIL;
    896     rv = ALPM_DRV(u)->tcam_table_sz(u, pkm);
    897     return rv;
    898 }
    899 
    900 int
    901 tcam_valid_entry_mode_get(int u, int pk, void *e, int *step_size,
    902                           int *pkm, int *ipv6, int *key_mode, int sub_idx)
    903 {
    904     int rv = BCM_E_UNAVAIL;
    905     *step_size = 2; /* default step_size */
    906     rv = ALPM_DRV(u)->tcam_entry_mode_get(u, pk, e, step_size, pkm,
    907                                           ipv6, key_mode, sub_idx);
    908     return rv;
    909 }
    910 
    911 int
    912 tcam_entry_adata_get(int u, int pkm, void *e,
    913                      int sub_idx, _alpm_bkt_adata_t *adata)
    914 {
    915     int rv = BCM_E_UNAVAIL;
    916     rv = ALPM_DRV(u)->tcam_entry_adata_get(u, pkm, e, sub_idx, adata);
    917     return rv;
    918 }
    919 
    920 int
    921 tcam_entry_bdata_get(int u, int pkm, void *e, int sub_idx,  void *fent)
    922 {
    923     int rv = BCM_E_UNAVAIL;
    924     rv = ALPM_DRV(u)->tcam_entry_bdata_get(u, pkm, e, sub_idx, fent);
    925     return rv;
    926 }
    927 
    928 int
    929 alpm_bkt_entry_read(int u, _alpm_tbl_t tbl, _alpm_cb_t *acb, void *e, int index)
    930 {
    931     int         rv = BCM_E_UNAVAIL;
    932 
    933     rv = ALPM_DRV(u)->mem_entry_read(u, acb, tbl, index, e, FALSE);
    934 
    935     return rv;
    936 }
    937 
    938 int
    939 alpm_bkt_entry_read_no_cache(int u, _alpm_tbl_t tbl, _alpm_cb_t *acb, void *e, int index)
    940 {
    941     int         rv = BCM_E_UNAVAIL;
    942 
    943     rv = ALPM_DRV(u)->mem_entry_read(u, acb, tbl, index, e, TRUE);
    944 
    945     return rv;
    946 }
    947 
    948 #endif /* ALPM_ENABLE */
    949