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