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