l3.c (57621B)
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 * 7 * File: l3.c 8 * Purpose: Katana L3 function implementations 9 */ 10 11 12 #include <soc/defs.h> 13 14 #include <assert.h> 15 #include <shared/bsl.h> 16 #include <sal/core/libc.h> 17 #if defined(BCM_KATANA_SUPPORT) && defined(INCLUDE_L3) 18 19 #include <shared/util.h> 20 #include <soc/mem.h> 21 #include <soc/cm.h> 22 #include <soc/drv.h> 23 #include <soc/register.h> 24 #include <soc/memory.h> 25 #include <soc/l3x.h> 26 #include <soc/lpm.h> 27 #include <soc/tnl_term.h> 28 29 #include <bcm/l3.h> 30 #include <bcm/debug.h> 31 #include <bcm/error.h> 32 #include <bcm/stack.h> 33 34 #include <bcm_int/esw/mbcm.h> 35 #include <bcm_int/esw/firebolt.h> 36 #include <bcm_int/esw/trx.h> 37 #include <bcm_int/esw/katana.h> 38 #include <bcm_int/esw/l3.h> 39 #include <bcm_int/esw/xgs3.h> 40 #include <bcm_int/esw_dispatch.h> 41 42 43 _bcm_l3_defip_pair128_table_t *l3_kt_defip_pair128[BCM_MAX_NUM_UNITS]; 44 45 /* 46 * Function: 47 * _kt_defip_pair128_hash 48 * Purpose: 49 * Calculate an entry 8 bit hash. 50 * Parameters: 51 * unit - (IN)SOC unit number. 52 * lpm_cfg - (IN)Buffer to fill defip information. 53 * entry_hash - (OUT)Entry hash 54 * Returns: 55 * BCM_E_XXX 56 */ 57 STATIC int 58 _kt_defip_pair128_hash(int unit, _bcm_defip_cfg_t *lpm_cfg, uint8 *hash) 59 { 60 uint32 key[BCM_KT_DEFIP_PAIR128_HASH_SZ]; 61 62 if (hash == NULL) { 63 return (BCM_E_PARAM); 64 } 65 66 SAL_IP6_ADDR_TO_UINT32(lpm_cfg->defip_ip6_addr, key); 67 key[4] = lpm_cfg->defip_sub_len; 68 key[5] = lpm_cfg->defip_vrf; 69 70 *hash = (_shr_crc16b(0, (void *)key, 71 WORDS2BITS((BCM_KT_DEFIP_PAIR128_HASH_SZ))) & 0xff); 72 return (BCM_E_NONE); 73 } 74 75 #ifdef BCM_WARM_BOOT_SUPPORT 76 /* 77 * Function: 78 * _kt_defip_pair128_reinit 79 * Purpose: 80 * Re-Initialize sw image for L3_DEFIP_PAIR_128 internal tcam. 81 * during warm boot. 82 * Parameters: 83 * unit - (IN)SOC unit number. 84 * idx - (IN)Entry index 85 * lpm_cfg - (IN)Inserted entry. 86 * Returns: 87 * BCM_E_XXX 88 */ 89 STATIC int 90 _kt_defip_pair128_reinit(int unit, int idx, _bcm_defip_cfg_t *lpm_cfg) 91 { 92 int lkup_plen; /* Vrf weighted lookup prefix. */ 93 uint8 hash; /* Entry hash value. */ 94 95 /* Calculate vrf weighted prefix length. */ 96 lkup_plen = lpm_cfg->defip_sub_len * 97 ((BCM_L3_VRF_OVERRIDE == lpm_cfg->defip_vrf) ? 2 : 1); 98 99 /* Calculate entry lookup hash. */ 100 BCM_IF_ERROR_RETURN(_kt_defip_pair128_hash(unit, lpm_cfg, &hash)); 101 102 /* Set software structure info. */ 103 BCM_KT_DEFIP_PAIR128_ENTRY_SET(unit, idx, lkup_plen, hash); 104 105 /* Update software usage counter. */ 106 BCM_KT_DEFIP_PAIR128_USED_COUNT(unit)++; 107 108 return (BCM_E_NONE); 109 } 110 111 #endif /* BCM_WARM_BOOT_SUPPORT */ 112 113 /* 114 * Function: 115 * _bcm_kt_defip_pair128_init 116 * Purpose: 117 * Initialize sw image for L3_DEFIP_PAIR_128 internal tcam. 118 * Parameters: 119 * unit - (IN)SOC unit number. 120 * Returns: 121 * BCM_E_XXX 122 */ 123 int 124 _bcm_kt_defip_pair128_init(int unit) 125 { 126 int mem_sz; /* Memory allocation size */ 127 int rv; /* Internal operation status. */ 128 soc_kt_lpm_ipv6_info_t *lpm_ipv6_info = soc_kt_lpm_ipv6_info_get(unit); 129 130 if (lpm_ipv6_info->ipv6_128b.depth == 0) { 131 /* We cannot use L3_DEFIP for storing IPv6 LPM 128b entries */ 132 return BCM_E_NONE; 133 } 134 135 /* De-allocate any existing structures. */ 136 if (BCM_KT_DEFIP_PAIR128(unit) != NULL) { 137 rv = _bcm_kt_defip_pair128_deinit(unit); 138 BCM_IF_ERROR_RETURN(rv); 139 } 140 141 /* Allocate cam control structure. */ 142 mem_sz = sizeof(_bcm_l3_defip_pair128_table_t); 143 BCM_KT_DEFIP_PAIR128(unit) = sal_alloc(mem_sz, "l3_kt_defip_pair128"); 144 if (BCM_KT_DEFIP_PAIR128(unit) == NULL) { 145 return (BCM_E_MEMORY); 146 } 147 148 /* Reset cam control structure. */ 149 sal_memset(BCM_KT_DEFIP_PAIR128(unit), 0, mem_sz); 150 151 BCM_KT_DEFIP_PAIR128_TOTAL(unit) = 152 soc_mem_index_count(unit, L3_DEFIP_PAIR_128m); 153 BCM_KT_DEFIP_PAIR128_URPF_OFFSET(unit) = 154 lpm_ipv6_info->ipv6_128b.sip_start_offset; 155 BCM_KT_DEFIP_PAIR128_IDX_MAX(unit) = lpm_ipv6_info->ipv6_128b.depth - 1; 156 157 mem_sz = lpm_ipv6_info->ipv6_128b.depth * 158 sizeof(_bcm_l3_defip_pair128_entry_t); 159 BCM_KT_DEFIP_PAIR128_ARR(unit) = 160 sal_alloc(mem_sz, "l3_defip_pair128_entry_array"); 161 if (BCM_KT_DEFIP_PAIR128_ARR(unit) == NULL) { 162 BCM_IF_ERROR_RETURN(_bcm_kt_defip_pair128_deinit(unit)); 163 return (BCM_E_MEMORY); 164 } 165 sal_memset(BCM_KT_DEFIP_PAIR128_ARR(unit), 0, mem_sz); 166 167 return (BCM_E_NONE); 168 } 169 170 /* 171 * Function: 172 * _bcm_kt_defip_pair128_deinit 173 * Purpose: 174 * De-initialize sw image for L3_DEFIP_PAIR_128 internal tcam. 175 * Parameters: 176 * unit - (IN)SOC unit number. 177 * Returns: 178 * BCM_E_XXX 179 */ 180 int 181 _bcm_kt_defip_pair128_deinit(int unit) 182 { 183 uint32 ipv6_lpm_128b_enable; 184 185 ipv6_lpm_128b_enable = soc_property_get(unit, spn_IPV6_LPM_128B_ENABLE, 0); 186 if (!ipv6_lpm_128b_enable) { 187 /* We cannot use L3_DEFIP for storing IPv6 LPM 128b entries */ 188 return BCM_E_NONE; 189 } 190 191 if (BCM_KT_DEFIP_PAIR128(unit) == NULL) { 192 return (BCM_E_NONE); 193 } 194 195 /* De-allocate any existing structures. */ 196 if (BCM_KT_DEFIP_PAIR128_ARR(unit) != NULL) { 197 sal_free(BCM_KT_DEFIP_PAIR128_ARR(unit)); 198 BCM_KT_DEFIP_PAIR128_ARR(unit) = NULL; 199 } 200 sal_free(BCM_KT_DEFIP_PAIR128(unit)); 201 BCM_KT_DEFIP_PAIR128(unit) = NULL; 202 203 return (BCM_E_NONE); 204 } 205 206 /* 207 * Function: 208 * _kt_defip_pair128_ip6_mask_set 209 * Purpose: 210 * Set IP6 mask field in memory from ip6 addr type. 211 * Parameters: 212 * unit - (IN) BCM device number. 213 * mem - (IN) Memory id. 214 * entry - (IN) HW entry buffer. 215 * ip6 - (IN) SW ip6 address buffer. 216 * Returns: void 217 */ 218 219 void 220 221 _kt_defip_pair128_ip6_mask_set(int unit, soc_mem_t mem, uint32 *entry, 222 const ip6_addr_t ip6) 223 { 224 uint32 ip6_field[4]; 225 ip6_field[3] = ((ip6[12] << 24)| (ip6[13] << 16) | 226 (ip6[14] << 8) | (ip6[15] << 0)); 227 soc_mem_field_set(unit, mem, entry, IP_ADDR_MASK0_LWRf, &ip6_field[3]); 228 ip6_field[2] = ((ip6[8] << 24) | (ip6[9] << 16) | 229 (ip6[10] << 8) | (ip6[11] << 0)); 230 soc_mem_field_set(unit, mem, entry, IP_ADDR_MASK1_LWRf, &ip6_field[2]); 231 ip6_field[1] = ((ip6[4] << 24) | (ip6[5] << 16) | 232 (ip6[6] << 8) | (ip6[7] << 0)); 233 soc_mem_field_set(unit, mem, entry, IP_ADDR_MASK0_UPRf, &ip6_field[1]); 234 ip6_field[0] = ((ip6[0] << 24) | (ip6[1] << 16) | 235 (ip6[2] << 8) | (ip6[3] << 0)); 236 soc_mem_field_set(unit, mem, entry, IP_ADDR_MASK1_UPRf, ip6_field); 237 } 238 239 /* 240 * Function: 241 * _kt_defip_pair128_ip6_mask_get 242 * Purpose: 243 * Read IP6 mask field from memory field to ip6_addr_t buffer. 244 * Parameters: 245 * unit - (IN) BCM device number. 246 * mem - (IN) Memory id. 247 * entry - (IN) HW entry buffer. 248 * ip6 - (OUT) SW ip6 address buffer. 249 * Returns: void 250 */ 251 void 252 253 _kt_defip_pair128_ip6_mask_get(int unit, soc_mem_t mem, const void *entry, 254 ip6_addr_t ip6) 255 { 256 uint32 ip6_field[4]; 257 soc_mem_field_get(unit, mem, entry, IP_ADDR_MASK0_LWRf, (uint32 *)&ip6_field[3]); 258 ip6[12] = (uint8) (ip6_field[3] >> 24); 259 ip6[13] = (uint8) (ip6_field[3] >> 16 & 0xff); 260 ip6[14] = (uint8) (ip6_field[3] >> 8 & 0xff); 261 ip6[15] = (uint8) (ip6_field[3] & 0xff); 262 soc_mem_field_get(unit, mem, entry, IP_ADDR_MASK1_LWRf, (uint32 *)&ip6_field[2]); 263 ip6[8] = (uint8) (ip6_field[2] >> 24); 264 ip6[9] = (uint8) (ip6_field[2] >> 16 & 0xff); 265 ip6[10] = (uint8) (ip6_field[2] >> 8 & 0xff); 266 ip6[11] = (uint8) (ip6_field[2] & 0xff); 267 soc_mem_field_get(unit, mem, entry, IP_ADDR_MASK0_UPRf, (uint32 *)&ip6_field[1]); 268 ip6[4] = (uint8) (ip6_field[1] >> 24); 269 ip6[5] = (uint8) (ip6_field[1] >> 16 & 0xff); 270 ip6[6] =(uint8) (ip6_field[1] >> 8 & 0xff); 271 ip6[7] =(uint8) (ip6_field[1] & 0xff); 272 soc_mem_field_get(unit, mem, entry, IP_ADDR_MASK1_UPRf, ip6_field); 273 ip6[0] =(uint8) (ip6_field[0] >> 24); 274 ip6[1] =(uint8) (ip6_field[0] >> 16 & 0xff); 275 ip6[2] =(uint8) (ip6_field[0] >> 8 & 0xff); 276 ip6[3] =(uint8) (ip6_field[0] & 0xff); 277 } 278 279 280 /* 281 * Function: 282 * _kt_defip_pair128_ip6_addr_set 283 * Purpose: 284 * Set IP6 address field in memory from ip6 addr type. 285 * Parameters: 286 * unit - (IN) BCM device number. 287 * mem - (IN) Memory id. 288 * entry - (IN) HW entry buffer. 289 * ip6 - (IN) SW ip6 address buffer. 290 * Returns: void 291 */ 292 293 void 294 _kt_defip_pair128_ip6_addr_set(int unit, soc_mem_t mem, uint32 *entry, 295 const ip6_addr_t ip6) 296 { 297 uint32 ip6_field[4]; 298 ip6_field[3] = ((ip6[12] << 24)| (ip6[13] << 16) | 299 (ip6[14] << 8) | (ip6[15] << 0)); 300 soc_mem_field_set(unit, mem, entry, IP_ADDR0_LWRf, &ip6_field[3]); 301 ip6_field[2] = ((ip6[8] << 24) | (ip6[9] << 16) | 302 (ip6[10] << 8) | (ip6[11] << 0)); 303 soc_mem_field_set(unit, mem, entry, IP_ADDR1_LWRf, &ip6_field[2]); 304 ip6_field[1] = ((ip6[4] << 24) | (ip6[5] << 16) | 305 (ip6[6] << 8) | (ip6[7] << 0)); 306 soc_mem_field_set(unit, mem, entry, IP_ADDR0_UPRf, &ip6_field[1]); 307 ip6_field[0] = ((ip6[0] << 24) | (ip6[1] << 16) | 308 (ip6[2] << 8) | (ip6[3] << 0)); 309 soc_mem_field_set(unit, mem, entry, IP_ADDR1_UPRf, ip6_field); 310 } 311 312 /* 313 * Function: 314 * _kt_defip_pair128_ip6_addr_get 315 * Purpose: 316 * Read IP6 address field from memory field to ip6_addr_t buffer. 317 * Parameters: 318 * unit - (IN) BCM device number. 319 * mem - (IN) Memory id. 320 * entry - (IN) HW entry buffer. 321 * ip6 - (OUT) SW ip6 address buffer. 322 * Returns: void 323 */ 324 void 325 326 _kt_defip_pair128_ip6_addr_get(int unit, soc_mem_t mem, const void *entry, 327 ip6_addr_t ip6) 328 { 329 uint32 ip6_field[4]; 330 soc_mem_field_get(unit, mem, entry, IP_ADDR0_LWRf, (uint32 *)&ip6_field[3]); 331 ip6[12] = (uint8) (ip6_field[3] >> 24); 332 ip6[13] = (uint8) (ip6_field[3] >> 16 & 0xff); 333 ip6[14] = (uint8) (ip6_field[3] >> 8 & 0xff); 334 ip6[15] = (uint8) (ip6_field[3] & 0xff); 335 soc_mem_field_get(unit, mem, entry, IP_ADDR1_LWRf, (uint32 *)&ip6_field[2]); 336 ip6[8] = (uint8) (ip6_field[2] >> 24); 337 ip6[9] = (uint8) (ip6_field[2] >> 16 & 0xff); 338 ip6[10] = (uint8) (ip6_field[2] >> 8 & 0xff); 339 ip6[11] = (uint8) (ip6_field[2] & 0xff); 340 soc_mem_field_get(unit, mem, entry, IP_ADDR0_UPRf, (uint32 *)&ip6_field[1]); 341 ip6[4] = (uint8) (ip6_field[1] >> 24); 342 ip6[5] = (uint8) (ip6_field[1] >> 16 & 0xff); 343 ip6[6] =(uint8) (ip6_field[1] >> 8 & 0xff); 344 ip6[7] =(uint8) (ip6_field[1] & 0xff); 345 soc_mem_field_get(unit, mem, entry, IP_ADDR1_UPRf, ip6_field); 346 ip6[0] =(uint8) (ip6_field[0] >> 24); 347 ip6[1] =(uint8) (ip6_field[0] >> 16 & 0xff); 348 ip6[2] =(uint8) (ip6_field[0] >> 8 & 0xff); 349 ip6[3] =(uint8) (ip6_field[0] & 0xff); 350 } 351 352 /* 353 * Function: 354 * _kt_defip_pair128_get_key 355 * Purpose: 356 * Parse route entry key from L3_DEFIP_PAIR_128 table. 357 * Parameters: 358 * unit - (IN)SOC unit number. 359 * entry - (IN)Hw entry buffer. 360 * lpm_cfg - (IN/OUT)Buffer to fill defip information. 361 * Returns: 362 * BCM_E_XXX 363 */ 364 STATIC int 365 _kt_defip_pair128_get_key(int unit, uint32 *hw_entry, 366 _bcm_defip_cfg_t *lpm_cfg) 367 { 368 soc_mem_t mem = L3_DEFIP_PAIR_128m; /* Route table memory. */ 369 bcm_ip6_t mask; /* Subnet mask. */ 370 371 /* Input parameters check. */ 372 if ((lpm_cfg == NULL) || (hw_entry == NULL)) { 373 return (BCM_E_PARAM); 374 } 375 376 /* Extract ip6 address. */ 377 _kt_defip_pair128_ip6_addr_get(unit,mem, hw_entry, lpm_cfg->defip_ip6_addr); 378 379 /* Extract subnet mask. */ 380 _kt_defip_pair128_ip6_mask_get(unit, mem, hw_entry, mask); 381 lpm_cfg->defip_sub_len = bcm_ip6_mask_length(mask); 382 383 /* Extract vrf id & vrf mask. */ 384 if(!soc_mem_field32_get(unit, mem, hw_entry, VRF_ID_MASK0_LWRf)) { 385 lpm_cfg->defip_vrf = BCM_L3_VRF_OVERRIDE; 386 } else { 387 lpm_cfg->defip_vrf = soc_mem_field32_get(unit, mem, hw_entry, VRF_ID_0_LWRf); 388 } 389 return (BCM_E_NONE); 390 } 391 392 /* 393 * Function: 394 * _kt_defip_pair128_parse 395 * Purpose: 396 * Parse route entry from L3_DEFIP_PAIR_128 table to sw structure. 397 * Parameters: 398 * unit - (IN)SOC unit number. 399 * hw_entry - (IN)Hw entry buffer. 400 * lpm_cfg - (IN/OUT)Buffer to fill defip information. 401 * nh_ecmp_idx - (OUT)Next hop ecmp table index. 402 * Returns: 403 * BCM_E_XXX 404 */ 405 STATIC INLINE int 406 _kt_defip_pair128_parse(int unit, uint32 *hw_entry, 407 _bcm_defip_cfg_t *lpm_cfg, int *nh_ecmp_idx) 408 { 409 soc_mem_t mem = L3_DEFIP_PAIR_128m; /* Route table memory. */ 410 411 /* Input parameters check. */ 412 if ((lpm_cfg == NULL) || (hw_entry == NULL)) { 413 return (BCM_E_PARAM); 414 } 415 416 /* Reset entry flags first. */ 417 lpm_cfg->defip_flags = 0; 418 419 /* Check if entry points to ecmp group. */ 420 if (soc_mem_field32_get(unit, mem, hw_entry, ECMPf)) { 421 /* Mark entry as ecmp */ 422 lpm_cfg->defip_ecmp = TRUE; 423 lpm_cfg->defip_flags |= BCM_L3_MULTIPATH; 424 425 /* Get ecmp group id. */ 426 if (nh_ecmp_idx != NULL) { 427 *nh_ecmp_idx = soc_mem_field32_get(unit, mem, hw_entry, ECMP_PTRf); 428 } 429 } else { 430 /* Mark entry as non-ecmp. */ 431 lpm_cfg->defip_ecmp = 0; 432 433 /* Reset ecmp group next hop count. */ 434 lpm_cfg->defip_ecmp_count = 0; 435 436 /* Get next hop index. */ 437 if (nh_ecmp_idx != NULL) { 438 *nh_ecmp_idx = 439 soc_mem_field32_get(unit, mem, hw_entry, NEXT_HOP_INDEXf); 440 } 441 } 442 443 /* Mark entry as IPv6 */ 444 lpm_cfg->defip_flags |= BCM_L3_IP6; 445 446 /* Get entry priority. */ 447 lpm_cfg->defip_prio = soc_mem_field32_get(unit, mem, hw_entry, PRIf); 448 449 /* Get classification group id. */ 450 lpm_cfg->defip_lookup_class = 451 soc_mem_field32_get(unit, mem, hw_entry, CLASS_IDf); 452 453 /* Get hit bit. */ 454 if ((soc_mem_field32_get(unit, mem, hw_entry, HIT0f) && 455 soc_mem_field32_get(unit, mem, hw_entry, HIT1f))) { 456 lpm_cfg->defip_flags |= BCM_L3_HIT; 457 } 458 459 /* Get priority override bit. */ 460 if (soc_mem_field32_get(unit, mem, hw_entry, RPEf)) { 461 lpm_cfg->defip_flags |= BCM_L3_RPE; 462 } 463 464 /* Get destination discard field. */ 465 if(soc_mem_field32_get(unit, mem, hw_entry, DST_DISCARDf)) { 466 lpm_cfg->defip_flags |= BCM_L3_DST_DISCARD; 467 } 468 return (BCM_E_NONE); 469 } 470 471 /* 472 * Function: 473 * _kt_trx_defip_128_get_key 474 * Purpose: 475 * Parse route entry key from L3_DEFIP_128 table. 476 * Parameters: 477 * unit - (IN)SOC unit number. 478 * entry - (IN)Hw entry buffer. 479 * lpm_cfg - (IN/OUT)Buffer to fill defip information. 480 * Returns: 481 * BCM_E_XXX 482 */ 483 STATIC int 484 _kt_trx_defip_128_get_key(int unit, uint32 *hw_entry, 485 _bcm_defip_cfg_t *lpm_cfg) 486 { 487 soc_mem_t mem = L3_DEFIP_128m; /* Route table memory. */ 488 bcm_ip6_t mask; /* Subnet mask. */ 489 490 /* Input parameters check. */ 491 if ((NULL == lpm_cfg) || (NULL == hw_entry)) { 492 return (BCM_E_PARAM); 493 } 494 495 /* Extract ip6 address. */ 496 soc_mem_ip6_addr_get(unit, mem, hw_entry, IP_ADDRf, lpm_cfg->defip_ip6_addr, 497 SOC_MEM_IP6_FULL_ADDR); 498 499 /* Extract subnet mask. */ 500 soc_mem_ip6_addr_get(unit, mem, hw_entry, IP_ADDR_MASKf, mask, 501 SOC_MEM_IP6_FULL_ADDR); 502 lpm_cfg->defip_sub_len = bcm_ip6_mask_length(mask); 503 504 /* Extract vrf id & vrf mask. */ 505 if(!soc_mem_field32_get(unit, mem, hw_entry, VRF_ID_MASKf)) { 506 lpm_cfg->defip_vrf = BCM_L3_VRF_OVERRIDE; 507 } else { 508 lpm_cfg->defip_vrf = soc_mem_field32_get(unit, mem, hw_entry, VRF_IDf); 509 } 510 return (BCM_E_NONE); 511 } 512 513 /* 514 * Function: 515 * _kt_trx_defip_128_parse 516 * Purpose: 517 * Parse route entry from L3_DEFIP_128 table to sw structure. 518 * Parameters: 519 * unit - (IN)SOC unit number. 520 * hw_entry - (IN)Hw entry buffer. 521 * lpm_cfg - (IN/OUT)Buffer to fill defip information. 522 * nh_ecmp_idx - (OUT)Next hop ecmp table index. 523 * Returns: 524 * BCM_E_XXX 525 */ 526 STATIC INLINE int 527 _kt_trx_defip_128_parse(int unit, uint32 *hw_entry, 528 _bcm_defip_cfg_t *lpm_cfg, int *nh_ecmp_idx) 529 { 530 soc_mem_t mem = L3_DEFIP_128m; /* Route table memory. */ 531 532 533 /* Input parameters check. */ 534 if ((NULL == hw_entry) || (NULL == lpm_cfg)) { 535 return (BCM_E_PARAM); 536 } 537 538 /* Reset entry flags first. */ 539 lpm_cfg->defip_flags = 0; 540 541 /* Check if entry points to ecmp group. */ 542 if (soc_mem_field32_get(unit, mem, hw_entry, ECMPf)) { 543 /* Mark entry as ecmp */ 544 lpm_cfg->defip_ecmp = TRUE; 545 lpm_cfg->defip_flags |= BCM_L3_MULTIPATH; 546 547 /* Get ecmp group id. */ 548 if (NULL != nh_ecmp_idx) { 549 *nh_ecmp_idx = soc_mem_field32_get(unit, mem, hw_entry, ECMP_PTRf); 550 } 551 } else { 552 /* Mark entry as non-ecmp. */ 553 lpm_cfg->defip_ecmp = 0; 554 555 /* Reset ecmp group next hop count. */ 556 lpm_cfg->defip_ecmp_count = 0; 557 558 /* Get next hop index. */ 559 if (NULL != nh_ecmp_idx) { 560 *nh_ecmp_idx = 561 soc_mem_field32_get(unit, mem, hw_entry, NEXT_HOP_INDEXf); 562 } 563 } 564 565 /* Mark entry as IPv6 */ 566 lpm_cfg->defip_flags |= BCM_L3_IP6; 567 568 /* Get entry priority. */ 569 lpm_cfg->defip_prio = soc_mem_field32_get(unit, mem, hw_entry, PRIf); 570 571 /* Get classification group id. */ 572 lpm_cfg->defip_lookup_class = 573 soc_mem_field32_get(unit, mem, hw_entry, CLASS_IDf); 574 575 /* Get hit bit. */ 576 if (soc_mem_field32_get(unit, mem, hw_entry, HITf)) { 577 lpm_cfg->defip_flags |= BCM_L3_HIT; 578 } 579 580 /* Get priority override bit. */ 581 if (soc_mem_field32_get(unit, mem, hw_entry, RPEf)) { 582 lpm_cfg->defip_flags |= BCM_L3_RPE; 583 } 584 585 /* Get destination discard field. */ 586 if(soc_mem_field32_get(unit, mem, hw_entry, DST_DISCARDf)) { 587 lpm_cfg->defip_flags |= BCM_L3_DST_DISCARD; 588 } 589 return (BCM_E_NONE); 590 } 591 592 /* 593 * Function: 594 * _kt_defip_pair128_match 595 * Purpose: 596 * Lookup route entry from L3_DEFIP_PAIR_128 table. 597 * Parameters: 598 * unit - (IN)SOC unit number. 599 * lpm_cfg - (IN)Buffer to fill defip information. 600 * hw_entry - (OUT)Matching hw entry. 601 * hw_index - (OUT)HW table index. 602 * Returns: 603 * BCM_E_XXX 604 */ 605 STATIC int 606 _kt_defip_pair128_match(int unit, _bcm_defip_cfg_t *lpm_cfg, 607 uint32 *hw_entry, int *hw_index) 608 { 609 _bcm_defip_cfg_t candidate; /* Match condidate. */ 610 int lkup_plen; /* Vrf weighted lookup prefix. */ 611 int index; /* Table iteration index. */ 612 uint8 hash; /* Entry hash value. */ 613 int rv = BCM_E_NONE; /* Internal operation status. */ 614 615 616 /* Initialization */ 617 sal_memset(&candidate, 0, sizeof(_bcm_defip_cfg_t)); 618 619 /* Calculate vrf weighted prefix length. */ 620 lkup_plen = lpm_cfg->defip_sub_len * 621 ((BCM_L3_VRF_OVERRIDE == lpm_cfg->defip_vrf) ? 2 : 1); 622 623 /* Calculate entry lookup hash. */ 624 BCM_IF_ERROR_RETURN(_kt_defip_pair128_hash(unit, lpm_cfg, &hash)); 625 626 /* coverity[assignment : FALSE] */ 627 for (index = 0; index <= BCM_KT_DEFIP_PAIR128_IDX_MAX(unit); index++) { 628 629 /* Route prefix length comparison. */ 630 if (lkup_plen != BCM_KT_DEFIP_PAIR128_ARR(unit)[index].prefix_len) { 631 continue; 632 } 633 634 /* Route lookup key hash comparison. */ 635 if (hash != BCM_KT_DEFIP_PAIR128_ARR(unit)[index].entry_hash) { 636 continue; 637 } 638 639 /* Hash & prefix length match -> read and compare hw entry itself. */ 640 rv = BCM_XGS3_MEM_READ(unit, L3_DEFIP_PAIR_128m, index, hw_entry); 641 if (BCM_FAILURE(rv)) { 642 break; 643 } 644 645 /* Make sure entry is valid. */ 646 if ((!soc_mem_field32_get(unit, L3_DEFIP_PAIR_128m, hw_entry, VALID0_LWRf)) || 647 (!soc_mem_field32_get(unit, L3_DEFIP_PAIR_128m, hw_entry, VALID1_LWRf)) || 648 (!soc_mem_field32_get(unit, L3_DEFIP_PAIR_128m, hw_entry, VALID0_UPRf)) || 649 (!soc_mem_field32_get(unit, L3_DEFIP_PAIR_128m, hw_entry, VALID1_UPRf)) 650 ) { 651 /* Too bad sw image doesn't match hardware. */ 652 continue; 653 } 654 655 /* Extract entry address vrf */ 656 rv = _kt_defip_pair128_get_key(unit, hw_entry, &candidate); 657 if (BCM_FAILURE(rv)) { 658 break; 659 } 660 661 662 /* Address & Vrf comparison. */ 663 if (lpm_cfg->defip_vrf != candidate.defip_vrf) { 664 continue; 665 } 666 667 /* Subnet mask comparison. */ 668 if (lpm_cfg->defip_sub_len != candidate.defip_sub_len) { 669 continue; 670 } 671 672 673 if (sal_memcmp(lpm_cfg->defip_ip6_addr, candidate.defip_ip6_addr, 674 sizeof(bcm_ip6_t))) { 675 continue; 676 } 677 678 679 /* Matching entry found. */ 680 break; 681 682 } 683 684 BCM_IF_ERROR_RETURN(rv); 685 686 if (index > BCM_KT_DEFIP_PAIR128_IDX_MAX(unit)) { 687 return (BCM_E_NOT_FOUND); 688 } 689 690 *hw_index = index; 691 return (BCM_E_NONE); 692 } 693 694 /* 695 * Function: 696 * _kt_defip_pair128_entry_clear 697 * Purpose: 698 * Clear/Reset a single route entry. 699 * Parameters: 700 * unit - (IN)SOC unit number. 701 * hw_index - (IN)Entry index in the tcam. 702 * Returns: 703 * BCM_E_XXX 704 */ 705 STATIC int 706 _kt_defip_pair128_entry_clear(int unit, int hw_index) 707 { 708 soc_mem_t mem = L3_DEFIP_PAIR_128m; 709 uint32 hw_entry[SOC_MAX_MEM_FIELD_WORDS]; 710 soc_field_t key_field[4], mask_field[4]; 711 int field_count, i; 712 uint64 val64; 713 key_field[0] = KEY0_UPRf; 714 key_field[1] = KEY1_UPRf; 715 key_field[2] = KEY0_LWRf; 716 key_field[3] = KEY1_LWRf; 717 mask_field[0] = MASK0_UPRf; 718 mask_field[1] = MASK1_UPRf; 719 mask_field[2] = MASK0_LWRf; 720 mask_field[3] = MASK1_LWRf; 721 field_count = 4; 722 sal_memset(hw_entry, 0, WORDS2BYTES(SOC_MAX_MEM_FIELD_WORDS)); 723 COMPILER_64_ZERO(val64); 724 for (i = 0; i < field_count; i++) { 725 soc_mem_field64_set(unit, mem, hw_entry, key_field[i], val64); 726 soc_mem_field64_set(unit, mem, hw_entry, mask_field[i], val64); 727 } 728 729 /* Reset hw entry. */ 730 BCM_IF_ERROR_RETURN 731 (BCM_XGS3_MEM_WRITE(unit, L3_DEFIP_PAIR_128m, hw_index, 732 &soc_mem_entry_null(unit, L3_DEFIP_PAIR_128m))); 733 BCM_IF_ERROR_RETURN 734 (BCM_XGS3_MEM_WRITE(unit, L3_DEFIP_PAIR_128m, hw_index, hw_entry)); 735 736 /* Reset sw entry. */ 737 BCM_KT_DEFIP_PAIR128_ENTRY_SET(unit, hw_index, 0, 0); 738 739 /* Reset urpf source lookup entry. */ 740 if (SOC_URPF_STATUS_GET(unit)) { 741 BCM_IF_ERROR_RETURN 742 (BCM_XGS3_MEM_WRITE(unit, L3_DEFIP_PAIR_128m, 743 (hw_index + BCM_KT_DEFIP_PAIR128_URPF_OFFSET(unit)), 744 &soc_mem_entry_null(unit, L3_DEFIP_PAIR_128m))); 745 BCM_IF_ERROR_RETURN 746 (BCM_XGS3_MEM_WRITE(unit, L3_DEFIP_PAIR_128m, 747 (hw_index+ BCM_KT_DEFIP_PAIR128_URPF_OFFSET(unit)), hw_entry)); 748 } 749 return (BCM_E_NONE); 750 } 751 /* 752 * Function: 753 * _kt_defip_pair128_shift 754 * Purpose: 755 * Shift entries in the tcam. 756 * Parameters: 757 * unit - (IN)SOC unit number. 758 * idx_src - (IN)Entry source. 759 * idx_dest - (IN)Entry destination. 760 * Returns: 761 * BCM_E_XXX 762 */ 763 STATIC int 764 _kt_defip_pair128_shift(int unit, int idx_src, int idx_dest) 765 { 766 uint32 hw_entry[SOC_MAX_MEM_FIELD_WORDS]; /* HW entry buffer. */ 767 768 /* Don't copy uninstalled entries. */ 769 if (0 != BCM_KT_DEFIP_PAIR128_ARR(unit)[idx_src].prefix_len) { 770 /* Read entry from source index. */ 771 BCM_IF_ERROR_RETURN 772 (BCM_XGS3_MEM_READ(unit, L3_DEFIP_PAIR_128m, idx_src, hw_entry)); 773 774 /* Write entry to the destination index. */ 775 BCM_IF_ERROR_RETURN 776 (BCM_XGS3_MEM_WRITE(unit, L3_DEFIP_PAIR_128m, idx_dest, hw_entry)); 777 778 /* Shift corresponding URPF/source lookup entries. */ 779 if (SOC_URPF_STATUS_GET(unit)) { 780 /* Read entry from source index + half tcam. */ 781 BCM_IF_ERROR_RETURN 782 (BCM_XGS3_MEM_READ(unit, L3_DEFIP_PAIR_128m, 783 idx_src + BCM_KT_DEFIP_PAIR128_URPF_OFFSET(unit), 784 hw_entry)); 785 786 /* Write entry to the destination index + half tcam. */ 787 BCM_IF_ERROR_RETURN 788 (BCM_XGS3_MEM_WRITE(unit, L3_DEFIP_PAIR_128m, 789 idx_dest + BCM_KT_DEFIP_PAIR128_URPF_OFFSET(unit), 790 hw_entry)); 791 } 792 } 793 /* Copy software portion of the entry. */ 794 sal_memcpy (&BCM_KT_DEFIP_PAIR128_ARR(unit)[idx_dest], 795 &BCM_KT_DEFIP_PAIR128_ARR(unit)[idx_src], 796 sizeof(_bcm_l3_defip_pair128_entry_t)); 797 798 return (BCM_E_NONE); 799 } 800 801 /* 802 * Function: 803 * _kt_defip_pair128_shift_range 804 * Purpose: 805 * Shift entries in the tcam. 806 * Parameters: 807 * unit - (IN)SOC unit number. 808 * idx_start - (IN)Start index 809 * idx_end - (IN)End index 810 * Returns: 811 * BCM_E_XXX 812 */ 813 STATIC int 814 _kt_defip_pair128_shift_range(int unit, int idx_start, int idx_end) 815 { 816 int idx; /* Iteration index. */ 817 int rv = BCM_E_NONE; /* Operaton status. */ 818 819 /* Shift entries down (1 index up) */ 820 if (idx_end > idx_start) { 821 for (idx = idx_end - 1; idx >= idx_start; idx--) { 822 rv = _kt_defip_pair128_shift(unit, idx, idx + 1); 823 if (BCM_FAILURE(rv)) { 824 break; 825 } 826 } 827 /* Delete last entry from hardware & software. */ 828 rv = _kt_defip_pair128_entry_clear(unit, idx_start); 829 } 830 831 /* Shift entries up (1 index down) */ 832 if (idx_end < idx_start) { 833 for (idx = idx_end + 1; idx <= idx_start; idx++) { 834 rv = _kt_defip_pair128_shift(unit, idx, idx - 1); 835 if (BCM_FAILURE(rv)) { 836 break; 837 } 838 } 839 /* Delete last entry from hardware & software. */ 840 rv = _kt_defip_pair128_entry_clear(unit, idx_start); 841 } 842 843 return (rv); 844 } 845 /* 846 * Function: 847 * _kt_defip_pair128_idx_alloc 848 * Purpose: 849 * Shuffle the tcam in order to insert a new entry 850 * based on vrf weighted prefix length. 851 * Parameters: 852 * unit - (IN)SOC unit number. 853 * lpm_cfg - (IN)Route info 854 * hw_index - (OUT)Allocated hw index. 855 * Returns: 856 * BCM_E_XXX 857 */ 858 STATIC int 859 _kt_defip_pair128_idx_alloc(int unit, _bcm_defip_cfg_t *lpm_cfg, int *hw_index, 860 int nh_ecmp_idx) 861 { 862 int lkup_plen; /* Vrf weighted lookup prefix. */ 863 uint8 hash; /* Entry hash value. */ 864 int idx; /* Table iteration index. */ 865 int rv; /* Operation return status. */ 866 int shift_min = 0; /* Minimum entry shift required. */ 867 int range_start = 0; /* First valid location for pfx. */ 868 int range_end = BCM_KT_DEFIP_PAIR128_IDX_MAX(unit); 869 /* Last valid location for pfx. */ 870 int free_idx_before = -1; /* Free index before range_start. */ 871 int free_idx_after = -1; /* Free index after range_end. */ 872 uint32 temp_hw_entry[SOC_MAX_MEM_FIELD_WORDS]; /* HW entry buffer. */ 873 _bcm_defip_cfg_t temp_lpm; 874 int temp_nh_ecmp_idx; 875 876 /* Input parameters check. */ 877 if ((lpm_cfg == NULL) || (hw_index == NULL)) { 878 return (BCM_E_PARAM); 879 } 880 881 /* Calculate vrf weighted prefix length. */ 882 lkup_plen = lpm_cfg->defip_sub_len * 883 ((BCM_L3_VRF_OVERRIDE == lpm_cfg->defip_vrf) ? 2 : 1); 884 885 /* Calculate entry hash. */ 886 BCM_IF_ERROR_RETURN(_kt_defip_pair128_hash(unit, lpm_cfg, &hash)); 887 888 889 /* Make sure at least one slot is available. */ 890 if (BCM_KT_DEFIP_PAIR128_USED_COUNT(unit) == ( range_end + 1)) { 891 /* L3_DEFIP_PAIR_128 table is full */ 892 /* a. Copy entry at index 0 of L3_DEFIP_PAIR_128 893 b. Add the copied entry to L3_DEFIP_128 table 894 c. Delete entry at index 0 from the L3_DEFIP_PAIR_128 table 895 d. Add the new entry to L3_DEFIP_PAIR_128 table 896 */ 897 rv = BCM_XGS3_MEM_READ(unit, L3_DEFIP_PAIR_128m, 0, &temp_hw_entry); 898 BCM_IF_ERROR_RETURN(rv); 899 900 sal_memset(&temp_lpm, 0, sizeof(_bcm_defip_cfg_t)); 901 902 /* Parse entry. */ 903 rv = _kt_defip_pair128_parse(unit, temp_hw_entry, &temp_lpm, &temp_nh_ecmp_idx); 904 BCM_IF_ERROR_RETURN(rv); 905 906 /* Extract entry address vrf */ 907 rv = _kt_defip_pair128_get_key(unit, temp_hw_entry, &temp_lpm); 908 BCM_IF_ERROR_RETURN(rv); 909 910 911 /* Add the copied entry to L3_DEFIP_128 table */ 912 temp_lpm.defip_index = BCM_XGS3_L3_INVALID_INDEX; 913 rv = _bcm_trx_defip_128_add(unit, &temp_lpm, temp_nh_ecmp_idx); 914 BCM_IF_ERROR_RETURN(rv); 915 916 /* Delete entry from hardware & software. */ 917 rv = _kt_defip_pair128_entry_clear(unit, 0); 918 if (BCM_SUCCESS(rv)) { 919 BCM_XGS3_L3_DEFIP_CNT_DEC(unit, TRUE); 920 BCM_KT_DEFIP_PAIR128_USED_COUNT(unit)--; 921 } 922 } 923 924 /* 925 * Find first valid index for the prefix; 926 */ 927 for (idx = 0; idx <= BCM_KT_DEFIP_PAIR128_IDX_MAX(unit); idx++) { 928 /* Remember free entry before installation location. */ 929 if (0 == BCM_KT_DEFIP_PAIR128_ARR(unit)[idx].prefix_len) { 930 free_idx_before = idx; 931 continue; 932 } 933 /* Route prefix length comparison. */ 934 if (lkup_plen < BCM_KT_DEFIP_PAIR128_ARR(unit)[idx].prefix_len) { 935 range_start = idx; 936 continue; 937 } 938 break; 939 } 940 941 /* 942 * Find last valid index for the prefix; 943 */ 944 for (idx = BCM_KT_DEFIP_PAIR128_IDX_MAX(unit); idx >= 0; idx--) { 945 946 /* Remeber free entry after installation location. */ 947 if (0 == BCM_KT_DEFIP_PAIR128_ARR(unit)[idx].prefix_len) { 948 free_idx_after = idx; 949 continue; 950 } 951 /* Route prefix length comparison. */ 952 if (lkup_plen > BCM_KT_DEFIP_PAIR128_ARR(unit)[idx].prefix_len) { 953 range_end = idx; 954 continue; 955 } 956 break; 957 } 958 959 /* Check if entry should be inserted at the end. */ 960 if (range_start == BCM_KT_DEFIP_PAIR128_IDX_MAX(unit)) { 961 /* Shift all entries from free_idx_before till the end 1 up. */ 962 rv = _kt_defip_pair128_shift_range(unit, BCM_KT_DEFIP_PAIR128_IDX_MAX(unit), free_idx_before); 963 964 if (BCM_SUCCESS(rv)) { 965 /* Allocated index is last TCAM entry. */ 966 *hw_index = BCM_KT_DEFIP_PAIR128_IDX_MAX(unit); 967 BCM_KT_DEFIP_PAIR128_ENTRY_SET(unit, *hw_index, lkup_plen, hash); 968 } 969 return (rv); 970 } 971 972 /* Check if entry should be inserted at the beginning. */ 973 if (range_end < 0) { 974 /* Shift all entries from 0 till free_idx_after 1 down. */ 975 rv = _kt_defip_pair128_shift_range(unit, 0, free_idx_after); 976 977 if (BCM_SUCCESS(rv)) { 978 /* Allocated index is first TCAM entry. */ 979 *hw_index = 0; 980 BCM_KT_DEFIP_PAIR128_ENTRY_SET(unit, 0, lkup_plen, hash); 981 } 982 return (rv); 983 } 984 985 /* Find if there is any free index in range. */ 986 for (idx = range_start; idx <= range_end; idx++) { 987 if (0 == BCM_KT_DEFIP_PAIR128_ARR(unit)[idx].prefix_len) { 988 *hw_index = idx; 989 BCM_KT_DEFIP_PAIR128_ENTRY_SET(unit, idx, lkup_plen, hash); 990 return (BCM_E_NONE); 991 } 992 } 993 994 /* Check if entry should be inserted at the end of range. */ 995 if ((free_idx_after > range_end) && (free_idx_after != -1)) { 996 shift_min = free_idx_after - range_end; 997 } 998 999 /* Check if entry should be inserted in the beginning. */ 1000 if ((free_idx_before < range_start) && (free_idx_before != -1)) { 1001 if((shift_min > (range_start - free_idx_before)) || (free_idx_after == -1)) { 1002 shift_min = -1; 1003 } 1004 } 1005 1006 if (shift_min <= 0) { 1007 rv = _kt_defip_pair128_shift_range(unit, range_start, free_idx_before); 1008 if (BCM_SUCCESS(rv)) { 1009 *hw_index= range_start; 1010 BCM_KT_DEFIP_PAIR128_ENTRY_SET(unit, range_start, lkup_plen, hash); 1011 } 1012 } else { 1013 rv = _kt_defip_pair128_shift_range(unit, range_end, free_idx_after); 1014 if (BCM_SUCCESS(rv)) { 1015 *hw_index = range_end; 1016 BCM_KT_DEFIP_PAIR128_ENTRY_SET(unit, range_end, lkup_plen, hash); 1017 } 1018 } 1019 return (rv); 1020 } 1021 /* 1022 * Function: 1023 * _bcm_kt_defip_pair128_get 1024 * Purpose: 1025 * Get an entry from L3_DEFIP_PAIR_128 table. 1026 * Parameters: 1027 * unit - (IN)SOC unit number. 1028 * lpm_cfg - (IN)Buffer to fill defip information. 1029 * nh_ecmp_idx - (IN)Next hop or ecmp group index 1030 * Returns: 1031 * BCM_E_XXX 1032 */ 1033 int 1034 _bcm_kt_defip_pair128_get(int unit, _bcm_defip_cfg_t *lpm_cfg, 1035 int *nh_ecmp_idx) 1036 { 1037 uint32 hw_entry[SOC_MAX_MEM_FIELD_WORDS];/* Hw entry buffer. */ 1038 bcm_ip6_t mask; /* Subnet mask. */ 1039 int clear_hit; /* Clear entry hit bit flag. */ 1040 int hw_index = 0; /* Entry offset in the TCAM. */ 1041 int rv; /* Internal operation status.*/ 1042 soc_kt_lpm_ipv6_info_t *lpm_ipv6_info = soc_kt_lpm_ipv6_info_get(unit); 1043 1044 /* Input parameters check. */ 1045 if (lpm_cfg == NULL) { 1046 return (BCM_E_PARAM); 1047 } 1048 1049 if (lpm_ipv6_info->ipv6_128b.depth == 0) { 1050 /* We cannot use L3_DEFIP for storing IPv6 128b lookup */ 1051 return BCM_E_NOT_FOUND; 1052 } 1053 1054 rv = _bcm_trx_defip_128_get(unit, lpm_cfg, nh_ecmp_idx); 1055 1056 if (rv == BCM_E_NOT_FOUND) { 1057 1058 /* Check if clear hit bit required. */ 1059 clear_hit = lpm_cfg->defip_flags & BCM_L3_HIT_CLEAR; 1060 1061 /* Create mask from prefix length. */ 1062 bcm_ip6_mask_create(mask, lpm_cfg->defip_sub_len); 1063 1064 /* Apply mask on address. */ 1065 bcm_xgs3_l3_mask6_apply(mask, lpm_cfg->defip_ip6_addr); 1066 1067 /* Search for matching entry in the cam. */ 1068 rv = _kt_defip_pair128_match(unit, lpm_cfg, hw_entry, &hw_index); 1069 BCM_IF_ERROR_RETURN(rv); 1070 1071 lpm_cfg->defip_index = hw_index; 1072 1073 /* Parse matched entry. */ 1074 rv = _kt_defip_pair128_parse(unit, hw_entry, lpm_cfg, nh_ecmp_idx); 1075 BCM_IF_ERROR_RETURN(rv); 1076 1077 /* Clear the HIT bit */ 1078 if (clear_hit) { 1079 soc_mem_field32_set(unit, L3_DEFIP_PAIR_128m, hw_entry, HIT0f, 0); 1080 soc_mem_field32_set(unit, L3_DEFIP_PAIR_128m, hw_entry, HIT1f, 0); 1081 1082 rv = BCM_XGS3_MEM_WRITE(unit, L3_DEFIP_PAIR_128m, hw_index, hw_entry); 1083 } 1084 } 1085 1086 return (rv); 1087 } 1088 1089 /* 1090 * Function: 1091 * _bcm_kt_defip_pair128_add 1092 * Purpose: 1093 * Add an entry to internal L3_DEFIP_PAIR_128 table. 1094 * Parameters: 1095 * unit - (IN)SOC unit number. 1096 * lpm_cfg - (IN)Buffer to fill defip information. 1097 * nh_ecmp_idx - (IN)Next hop or ecmp group index. 1098 * Returns: 1099 * BCM_E_XXX 1100 */ 1101 int 1102 _bcm_kt_defip_pair128_add(int unit, _bcm_defip_cfg_t *lpm_cfg, 1103 int nh_ecmp_idx) 1104 { 1105 uint32 hw_entry[SOC_MAX_MEM_FIELD_WORDS]; /* New entry hw buffer. */ 1106 bcm_ip6_t mask; /* Subnet mask. */ 1107 int hw_index = 0; /* Entry offset in the TCAM. */ 1108 int rv; /* Operation return status. */ 1109 soc_mem_t mem = L3_DEFIP_PAIR_128m; /* Route table memory. */ 1110 int lkup_plen; /* Vrf weighted lookup prefix. */ 1111 int range_end; /* Last valid location for pfx. */ 1112 soc_kt_lpm_ipv6_info_t *lpm_ipv6_info = soc_kt_lpm_ipv6_info_get(unit); 1113 1114 /* Input parameters check. */ 1115 if (lpm_cfg == NULL) { 1116 return (BCM_E_PARAM); 1117 } 1118 1119 /* No support for routes matchin AFTER vrf specific. */ 1120 if (BCM_L3_VRF_GLOBAL == lpm_cfg->defip_vrf) { 1121 return (BCM_E_UNAVAIL); 1122 } 1123 1124 if (lpm_ipv6_info->ipv6_128b.depth == 0) { 1125 /* We cannot use L3_DEFIP for storing IPv6 128b lookup */ 1126 return BCM_E_FULL; 1127 } 1128 1129 /* Zero buffers. */ 1130 sal_memset(hw_entry, 0, WORDS2BYTES(SOC_MAX_MEM_FIELD_WORDS)); 1131 1132 /* Create mask from prefix length. */ 1133 bcm_ip6_mask_create(mask, lpm_cfg->defip_sub_len); 1134 1135 /* Apply mask on address. */ 1136 bcm_xgs3_l3_mask6_apply(mask, lpm_cfg->defip_ip6_addr); 1137 1138 /* Allocate a new index for inserted entry. */ 1139 if (BCM_XGS3_L3_INVALID_INDEX == lpm_cfg->defip_index) { 1140 range_end = BCM_KT_DEFIP_PAIR128_IDX_MAX(unit) + 1; 1141 if (BCM_KT_DEFIP_PAIR128_USED_COUNT(unit) == range_end) { 1142 /* If L3_DEFIP_PAIR_128 table is full and weighted prefix length 1143 * of new entry is >= that of 0th entry in L3_DEFIP_PAIR_128 table 1144 * then add the new entry in L3_DEFIP_128 table */ 1145 lkup_plen = lpm_cfg->defip_sub_len * 1146 ((BCM_L3_VRF_OVERRIDE == lpm_cfg->defip_vrf) ? 2 : 1); 1147 if (lkup_plen >= BCM_KT_DEFIP_PAIR128_ARR(unit)[0].prefix_len) { 1148 return _bcm_trx_defip_128_add(unit, lpm_cfg, nh_ecmp_idx); 1149 } 1150 } 1151 rv = _kt_defip_pair128_idx_alloc(unit, lpm_cfg, &hw_index, nh_ecmp_idx); 1152 BCM_IF_ERROR_RETURN(rv); 1153 } else { 1154 hw_index = lpm_cfg->defip_index; 1155 } 1156 1157 /* Set hit bit. */ 1158 if (lpm_cfg->defip_flags & BCM_L3_HIT) { 1159 soc_mem_field32_set(unit, mem, hw_entry, HIT0f, 1); 1160 soc_mem_field32_set(unit, mem, hw_entry, HIT1f, 1); 1161 } 1162 1163 /* Set priority override bit. */ 1164 if (lpm_cfg->defip_flags & BCM_L3_RPE) { 1165 soc_mem_field32_set(unit, mem, hw_entry, RPEf, 1); 1166 } 1167 1168 /* Set classification group id. */ 1169 soc_mem_field32_set(unit, mem, hw_entry, CLASS_IDf, 1170 lpm_cfg->defip_lookup_class); 1171 1172 1173 /* Write priority field. */ 1174 soc_mem_field32_set(unit, mem, hw_entry, PRIf, lpm_cfg->defip_prio); 1175 1176 1177 /* Fill next hop information. */ 1178 if (lpm_cfg->defip_flags & BCM_L3_MULTIPATH) { 1179 soc_mem_field32_set(unit, mem, hw_entry, ECMP_PTRf, nh_ecmp_idx); 1180 soc_mem_field32_set(unit, mem, hw_entry, ECMPf, 1); 1181 } else { 1182 soc_mem_field32_set(unit, mem, hw_entry, NEXT_HOP_INDEXf, nh_ecmp_idx); 1183 } 1184 1185 /* Set destination discard flag. */ 1186 if (lpm_cfg->defip_flags & BCM_L3_DST_DISCARD) { 1187 soc_mem_field32_set(unit, mem, hw_entry, DST_DISCARDf, 1); 1188 } 1189 1190 /* Set mode bits to indicate IP v6 128b pair mode */ 1191 soc_mem_field32_set(unit, mem, hw_entry, MODE0_LWRf, 1); 1192 soc_mem_field32_set(unit, mem, hw_entry, MODE1_LWRf, 1); 1193 soc_mem_field32_set(unit, mem, hw_entry, MODE0_UPRf, 1); 1194 soc_mem_field32_set(unit, mem, hw_entry, MODE1_UPRf, 1); 1195 soc_mem_field32_set(unit, mem, hw_entry, MODE_MASK0_LWRf, 1); 1196 soc_mem_field32_set(unit, mem, hw_entry, MODE_MASK1_LWRf, 1); 1197 soc_mem_field32_set(unit, mem, hw_entry, MODE_MASK0_UPRf, 1); 1198 soc_mem_field32_set(unit, mem, hw_entry, MODE_MASK1_UPRf, 1); 1199 1200 /* Set valid bits. */ 1201 soc_mem_field32_set(unit, mem, hw_entry, VALID0_LWRf, 1); 1202 soc_mem_field32_set(unit, mem, hw_entry, VALID1_LWRf, 1); 1203 soc_mem_field32_set(unit, mem, hw_entry, VALID0_UPRf, 1); 1204 soc_mem_field32_set(unit, mem, hw_entry, VALID1_UPRf, 1); 1205 1206 /* Set destination/source ip address. */ 1207 _kt_defip_pair128_ip6_addr_set(unit, mem, hw_entry, lpm_cfg->defip_ip6_addr); 1208 1209 /* Set ip mask. */ 1210 _kt_defip_pair128_ip6_mask_set(unit, mem, hw_entry, mask); 1211 1212 /* Set vrf id & vrf mask. */ 1213 if (BCM_L3_VRF_OVERRIDE != lpm_cfg->defip_vrf) { 1214 soc_mem_field32_set(unit, mem, hw_entry, VRF_ID_0_LWRf, lpm_cfg->defip_vrf); 1215 soc_mem_field32_set(unit, mem, hw_entry, VRF_ID_1_LWRf, lpm_cfg->defip_vrf); 1216 soc_mem_field32_set(unit, mem, hw_entry, VRF_ID_0_UPRf, lpm_cfg->defip_vrf); 1217 soc_mem_field32_set(unit, mem, hw_entry, VRF_ID_1_UPRf, lpm_cfg->defip_vrf); 1218 soc_mem_field32_set(unit, mem, hw_entry, VRF_ID_MASK0_LWRf, 1219 (1 << soc_mem_field_length(unit, mem, 1220 VRF_ID_MASK0_LWRf)) - 1); 1221 soc_mem_field32_set(unit, mem, hw_entry, VRF_ID_MASK1_LWRf, 1222 (1 << soc_mem_field_length(unit, mem, 1223 VRF_ID_MASK1_LWRf)) - 1); 1224 soc_mem_field32_set(unit, mem, hw_entry, VRF_ID_MASK0_UPRf, 1225 (1 << soc_mem_field_length(unit, mem, 1226 VRF_ID_MASK0_UPRf)) - 1); 1227 soc_mem_field32_set(unit, mem, hw_entry, VRF_ID_MASK1_LWRf, 1228 (1 << soc_mem_field_length(unit, mem, 1229 VRF_ID_MASK1_UPRf)) - 1); 1230 if (SOC_MEM_FIELD_VALID(unit, mem, GLOBAL_ROUTEf)) { 1231 soc_mem_field32_set(unit, mem, hw_entry, GLOBAL_ROUTEf, 0); 1232 } 1233 } else { 1234 soc_mem_field32_set(unit, mem, hw_entry, VRF_ID_0_LWRf, 0); 1235 soc_mem_field32_set(unit, mem, hw_entry, VRF_ID_1_LWRf, 0); 1236 soc_mem_field32_set(unit, mem, hw_entry, VRF_ID_0_UPRf, 0); 1237 soc_mem_field32_set(unit, mem, hw_entry, VRF_ID_1_UPRf, 0); 1238 soc_mem_field32_set(unit, mem, hw_entry, VRF_ID_MASK0_LWRf, 0); 1239 soc_mem_field32_set(unit, mem, hw_entry, VRF_ID_MASK1_LWRf, 0); 1240 soc_mem_field32_set(unit, mem, hw_entry, VRF_ID_MASK0_UPRf, 0); 1241 soc_mem_field32_set(unit, mem, hw_entry, VRF_ID_MASK1_UPRf, 0); 1242 } 1243 1244 /* Write buffer to hw. */ 1245 rv = BCM_XGS3_MEM_WRITE(unit, mem, hw_index, hw_entry); 1246 if (BCM_FAILURE(rv)) { 1247 BCM_KT_DEFIP_PAIR128_ENTRY_SET(unit, hw_index, 0, 0); 1248 return (rv); 1249 } 1250 1251 /* Write source lookup portion of the entry. */ 1252 if (SOC_URPF_STATUS_GET(unit)) { 1253 soc_mem_field32_set(unit, mem, hw_entry, SRC_DISCARDf, 0); 1254 rv = BCM_XGS3_MEM_WRITE(unit, L3_DEFIP_PAIR_128m, 1255 (hw_index + BCM_KT_DEFIP_PAIR128_URPF_OFFSET(unit)), 1256 hw_entry); 1257 if (BCM_FAILURE(rv)) { 1258 _kt_defip_pair128_entry_clear(unit, hw_index); 1259 return (rv); 1260 } 1261 } 1262 1263 /* If new route added increment total number of routes. */ 1264 /* Lack of index indicates a new route. */ 1265 if (BCM_XGS3_L3_INVALID_INDEX == lpm_cfg->defip_index) { 1266 BCM_XGS3_L3_DEFIP_CNT_INC(unit, TRUE); 1267 BCM_KT_DEFIP_PAIR128_USED_COUNT(unit)++; 1268 } 1269 1270 return rv; 1271 } 1272 1273 1274 /* 1275 * Function: 1276 * _bcm_kt_defip_pair128_delete 1277 * Purpose: 1278 * Delete an entry from L3_DEFIP_PAIR_128 table. 1279 * Parameters: 1280 * unit - (IN)SOC unit number. 1281 * lpm_cfg - (IN)Buffer to fill defip information. 1282 * Returns: 1283 * BCM_E_XXX 1284 */ 1285 int 1286 _bcm_kt_defip_pair128_delete(int unit, _bcm_defip_cfg_t *lpm_cfg) 1287 { 1288 uint32 hw_entry[SOC_MAX_MEM_FIELD_WORDS];/* Hw entry buffer. */ 1289 uint32 temp_hw_entry[SOC_MAX_MEM_FIELD_WORDS];/* Hw entry buffer. */ 1290 bcm_ip6_t mask; /* Subnet mask. */ 1291 int hw_index = 0; /* Entry offset in the TCAM. */ 1292 int rv, rv1; /* Internal operation status.*/ 1293 _bcm_defip_cfg_t temp_lpm; 1294 int temp_nh_ecmp_idx, idx; 1295 soc_kt_lpm_ipv6_info_t *lpm_ipv6_info; 1296 1297 /* Input parameters check. */ 1298 if (lpm_cfg == NULL) { 1299 return (BCM_E_PARAM); 1300 } 1301 1302 lpm_ipv6_info = soc_kt_lpm_ipv6_info_get(unit); 1303 1304 if (lpm_ipv6_info->ipv6_128b.depth == 0) { 1305 /* We cannot use L3_DEFIP for storing IPv6 128b lookup */ 1306 return BCM_E_NOT_FOUND; 1307 } 1308 1309 1310 /* First search for matching entry in L3_DEFIP_128 table. 1311 * If found then delete it. If it is not found in L3_DEFIP_128 table 1312 * then search in L3_DEFIP_PAIR_128 table and delete matching entry. */ 1313 1314 /* First try to delete from L3_DEFIP_128 table. If successful then exit. 1315 * If not found in L3_DEFIP_128m then search the L3_DEFIP_PAIR_128 table. 1316 * If it is found in L3_DEFIP_PAIR_128m then delete it. */ 1317 rv = _bcm_trx_defip_128_delete(unit, lpm_cfg); 1318 if (rv == BCM_E_NOT_FOUND) { 1319 /* Create mask from prefix length. */ 1320 bcm_ip6_mask_create(mask, lpm_cfg->defip_sub_len); 1321 1322 /* Apply mask on address. */ 1323 bcm_xgs3_l3_mask6_apply(mask, lpm_cfg->defip_ip6_addr); 1324 /* Search for matching entry in theL3_DEFIP_PAIR_128 cam. */ 1325 rv1 = _kt_defip_pair128_match(unit, lpm_cfg, hw_entry, &hw_index); 1326 if (BCM_FAILURE(rv1)) { 1327 return (rv1); 1328 } 1329 /* Delete entry from hardware & software (L3_DEFIP_PAIR_128m). */ 1330 rv1 = _kt_defip_pair128_entry_clear(unit, hw_index); 1331 if (BCM_SUCCESS(rv1)) { 1332 BCM_XGS3_L3_DEFIP_CNT_DEC(unit, TRUE); 1333 BCM_KT_DEFIP_PAIR128_USED_COUNT(unit)--; 1334 /* Delete valid entry at highest index (or lowest LPM) in 1335 * L3_DEFIP_128m table if available 1336 * and add it to L3_DEFIP_PAIR_128m */ 1337 if (_bcm_trx_defip128_used_count_get(unit) > 0) { 1338 hw_index = _bcm_trx_defip128_idx_max_get(unit); 1339 for (idx = _bcm_trx_defip128_idx_max_get(unit); 1340 idx >=0; idx--) { 1341 if (_bcm_trx_defip128_array_idx_prefix_len_get(unit, idx) 1342 == 0) { 1343 hw_index = idx - 1; 1344 continue; 1345 } 1346 break; 1347 } 1348 rv = BCM_XGS3_MEM_READ(unit, L3_DEFIP_128m, hw_index, &temp_hw_entry); 1349 BCM_IF_ERROR_RETURN(rv); 1350 sal_memset(&temp_lpm, 0, sizeof(_bcm_defip_cfg_t)); 1351 /* Parse entry. */ 1352 rv = _kt_trx_defip_128_parse(unit, temp_hw_entry, &temp_lpm, &temp_nh_ecmp_idx); 1353 BCM_IF_ERROR_RETURN(rv); 1354 1355 /* Extract entry address vrf */ 1356 rv = _kt_trx_defip_128_get_key(unit, temp_hw_entry, &temp_lpm); 1357 BCM_IF_ERROR_RETURN(rv); 1358 1359 /* Add the copied entry to L3_DEFIP_PAIR_128 table */ 1360 temp_lpm.defip_index = BCM_XGS3_L3_INVALID_INDEX; 1361 rv = _bcm_kt_defip_pair128_add(unit, &temp_lpm, temp_nh_ecmp_idx); 1362 BCM_IF_ERROR_RETURN(rv); 1363 1364 /* Delete entry from L3_DEFIP_128 table. */ 1365 temp_lpm.defip_index = hw_index; 1366 rv = _bcm_trx_defip_128_delete(unit, &temp_lpm); 1367 return rv; 1368 } 1369 } 1370 return rv1; 1371 } 1372 return (rv); 1373 } 1374 1375 1376 /* 1377 * Function: 1378 * _bcm_kt_defip_pair128_update_match 1379 * Purpose: 1380 * Update/Delete all entries in defip table matching a certain rule. 1381 * Parameters: 1382 * unit - (IN)SOC unit number. 1383 * trv_data - (IN)Delete pattern + compare,act,notify routines. 1384 * Returns: 1385 * BCM_E_XXX 1386 */ 1387 int 1388 _bcm_kt_defip_pair128_update_match(int unit, _bcm_l3_trvrs_data_t *trv_data) 1389 { 1390 int idx; /* Iteration index. */ 1391 int rv; /* Operation return status. */ 1392 int cmp_result; /* Test routine result. */ 1393 int nh_ecmp_idx; /* Next hop/Ecmp group index. */ 1394 uint32 *hw_entry; /* Hw entry buffer. */ 1395 char *lpm_tbl_ptr; /* Dma table pointer. */ 1396 int defip_pair128_tbl_size; /* Defip table size. */ 1397 _bcm_defip_cfg_t lpm_cfg; /* Buffer to fill route info. */ 1398 soc_mem_t mem = L3_DEFIP_PAIR_128m; /* Route table memory. */ 1399 soc_kt_lpm_ipv6_info_t *lpm_ipv6_info = soc_kt_lpm_ipv6_info_get(unit); 1400 1401 if (lpm_ipv6_info->ipv6_128b.depth == 0) { 1402 /* L3_DEFIP table is not used for storing IPv6 128b lookup */ 1403 return BCM_E_NONE; 1404 } 1405 1406 /* Table DMA the LPM table to software copy */ 1407 BCM_IF_ERROR_RETURN 1408 (bcm_xgs3_l3_tbl_dma(unit, mem, BCM_L3_MEM_ENT_SIZE(unit, mem), 1409 "lpm_tbl", &lpm_tbl_ptr, &defip_pair128_tbl_size)); 1410 1411 if (SOC_URPF_STATUS_GET(unit)) { 1412 defip_pair128_tbl_size >>= 1; 1413 } 1414 1415 for (idx = 0; idx < defip_pair128_tbl_size; idx++) { 1416 /* Calculate entry ofset. */ 1417 hw_entry = soc_mem_table_idx_to_pointer(unit, mem, uint32 *, 1418 lpm_tbl_ptr, idx); 1419 1420 /* Make sure entry is valid. */ 1421 if (!soc_mem_field32_get (unit, mem, hw_entry, VALID0_LWRf)) { 1422 continue; 1423 } 1424 1425 /* Zero destination buffer first. */ 1426 sal_memset(&lpm_cfg, 0, sizeof(_bcm_defip_cfg_t)); 1427 1428 /* Parse the entry. */ 1429 _kt_defip_pair128_parse(unit, hw_entry, &lpm_cfg, &nh_ecmp_idx); 1430 lpm_cfg.defip_index = idx; 1431 1432 /* Fill entry ip address & subnet mask. */ 1433 _kt_defip_pair128_get_key(unit, hw_entry, &lpm_cfg); 1434 1435 /* Execute operation routine if any. */ 1436 if (trv_data->op_cb) { 1437 rv = (*trv_data->op_cb) (unit, (void *)trv_data, 1438 (void *)&lpm_cfg, 1439 (void *)&nh_ecmp_idx, &cmp_result); 1440 if (BCM_FAILURE(rv)) { 1441 soc_cm_sfree(unit, lpm_tbl_ptr); 1442 return rv; 1443 } 1444 } 1445 #ifdef BCM_WARM_BOOT_SUPPORT 1446 if (SOC_WARM_BOOT(unit)) { 1447 rv = _kt_defip_pair128_reinit(unit, idx, &lpm_cfg); 1448 if (BCM_FAILURE(rv)) { 1449 soc_cm_sfree(unit, lpm_tbl_ptr); 1450 return rv; 1451 } 1452 } 1453 #endif /* BCM_WARM_BOOT_SUPPORT */ 1454 } 1455 1456 #ifdef BCM_WARM_BOOT_SUPPORT 1457 if (SOC_WARM_BOOT(unit)) { 1458 SOC_IF_ERROR_RETURN(soc_fb_lpm_reinit_done(unit, 1)); 1459 } 1460 #endif /* BCM_WARM_BOOT_SUPPORT */ 1461 soc_cm_sfree(unit, lpm_tbl_ptr); 1462 return (BCM_E_NONE); 1463 } 1464 1465 int 1466 _bcm_kt_defip_pair128_used_count_get(int unit) 1467 { 1468 return BCM_KT_DEFIP_PAIR128_USED_COUNT(unit); 1469 } 1470 1471 /* 1472 * Function: 1473 * _bcm_kt_l3_info_dump 1474 * Purpose: 1475 * Dump the status of hardware. 1476 * Parameters: 1477 * unit - (IN)SOC unit number 1478 * Returns: 1479 * BCM_E_XXX. 1480 */ 1481 int 1482 _bcm_kt_l3_info_dump(int unit) 1483 { 1484 uint32 ipv6_lpm_128b_enable; 1485 uint32 ipv6_64b_free = 0; 1486 uint32 ipv6_64b_used = 0; 1487 uint32 ipv6_128b_free = 0; 1488 uint32 ipv6_128b_used = 0; 1489 uint32 ipv6_128b_total = 0; 1490 uint32 ipv4_free = 0; 1491 uint32 ipv4_used = 0; 1492 uint32 trx_defip128_idx_max = 0; 1493 uint32 trx_defip128_used_count = 0; 1494 soc_kt_lpm_ipv6_info_t *lpm_ipv6_info; 1495 1496 /* Make sure module was initialized. */ 1497 if (!BCM_XGS3_L3_INITIALIZED(unit)) { 1498 return (BCM_E_INIT); 1499 } 1500 1501 trx_defip128_idx_max = SOC_IS_KATANA(unit) ? 1502 _bcm_trx_defip128_idx_max_get(unit) : 0; 1503 1504 trx_defip128_used_count = SOC_IS_KATANA(unit) ? 1505 _bcm_trx_defip128_used_count_get(unit) : 0; 1506 1507 if (SOC_IS_KATANA(unit)) { 1508 ipv6_lpm_128b_enable = 1509 soc_property_get(unit,spn_IPV6_LPM_128B_ENABLE, 0); 1510 LOG_CLI((BSL_META_U(unit, 1511 "\n*************************************************"))); 1512 LOG_CLI((BSL_META_U(unit, 1513 "\nURPF check \t\t\t\t= %s"), 1514 SOC_URPF_STATUS_GET(unit) ? "ENABLED" : "DISABLED")); 1515 LOG_CLI((BSL_META_U(unit, 1516 "\nconfig ipv6_lpm_128b_enable \t\t= %d"), 1517 ipv6_lpm_128b_enable)); 1518 LOG_CLI((BSL_META_U(unit, 1519 "\n*************************************************"))); 1520 LOG_CLI((BSL_META_U(unit, 1521 "\nMaximum LPM entries types"))); 1522 LOG_CLI((BSL_META_U(unit, 1523 "\n IPv4 * IPv6 64 bit *IPv6 128 bit"))); 1524 if (SOC_URPF_STATUS_GET(unit)) { 1525 if (ipv6_lpm_128b_enable == 0 ) { 1526 LOG_CLI((BSL_META_U(unit, 1527 "\nupto 6144 3072 128"))); 1528 } else { 1529 LOG_CLI((BSL_META_U(unit, 1530 "\nupto 2048 1024 1152"))); 1531 } 1532 } else { 1533 if (ipv6_lpm_128b_enable == 0) { 1534 LOG_CLI((BSL_META_U(unit, 1535 "\nupto 12288 6144 256"))); 1536 } else { 1537 LOG_CLI((BSL_META_U(unit, 1538 "\nupto 4096 2048 2304"))); 1539 } 1540 } 1541 1542 lpm_ipv6_info = soc_kt_lpm_ipv6_info_get(unit); 1543 /* IPv4, IPv6 64b and IPv6 pair128b entries share L3_DEFIPm 1544 * Ipv6 64b and IPv6 pair128b are stored in mutually exclusive entries*/ 1545 if (lpm_ipv6_info->ipv6_128b.depth > 0) { 1546 ipv6_128b_total = lpm_ipv6_info->ipv6_128b.depth + 1547 trx_defip128_idx_max + 1; 1548 ipv6_128b_used = BCM_KT_DEFIP_PAIR128_USED_COUNT(unit) + 1549 trx_defip128_used_count; 1550 ipv6_128b_free = ipv6_128b_total - ipv6_128b_used; 1551 } else { 1552 ipv6_128b_total = trx_defip128_idx_max + 1; 1553 ipv6_128b_used = trx_defip128_used_count; 1554 ipv6_128b_free = ipv6_128b_total - ipv6_128b_used; 1555 } 1556 ipv6_64b_used = BCM_XGS3_L3_DEFIP_IP6_CNT(unit) - ipv6_128b_used; 1557 ipv4_used = BCM_XGS3_L3_DEFIP_IP4_CNT(unit); 1558 ipv6_64b_free = lpm_ipv6_info->ipv6_64b.depth - 1559 ((ipv4_used+1)/2 + ipv6_64b_used); 1560 ipv4_free = ipv6_64b_free * 2; 1561 1562 LOG_CLI((BSL_META_U(unit, 1563 "\n*************************************************"))); 1564 LOG_CLI((BSL_META_U(unit, 1565 "\nIPv4 LPM entries in use \t\t= %5d"), ipv4_used)); 1566 LOG_CLI((BSL_META_U(unit, 1567 "\nIPv4 LPM entries free \t\t\t= %5d"), ipv4_free)); 1568 LOG_CLI((BSL_META_U(unit, 1569 "\nIPv4 LPM entries total \t\t\t= %5d"), 1570 ipv4_free + ipv4_used)); 1571 LOG_CLI((BSL_META_U(unit, 1572 "\n**********"))); 1573 LOG_CLI((BSL_META_U(unit, 1574 "\nIPv6 64 bit LPM entries in use \t\t= %5d"), 1575 ipv6_64b_used)); 1576 LOG_CLI((BSL_META_U(unit, 1577 "\nIPv6 64 bit LPM entries free \t\t= %5d"), 1578 ipv6_64b_free)); 1579 LOG_CLI((BSL_META_U(unit, 1580 "\n64 bit LPM DEFIP entries total \t\t= %5d"), 1581 ipv6_64b_used + ipv6_64b_free)); 1582 LOG_CLI((BSL_META_U(unit, 1583 "\n**********"))); 1584 LOG_CLI((BSL_META_U(unit, 1585 "\nIPv6 128 bit LPM entries in use \t= %5d"), 1586 ipv6_128b_used)); 1587 LOG_CLI((BSL_META_U(unit, 1588 "\nIPv6 128 bit LPM entries free \t\t= %5d"), 1589 ipv6_128b_free)); 1590 LOG_CLI((BSL_META_U(unit, 1591 "\nIPv6 128 bit LPM entries total \t\t= %5d"), 1592 (ipv6_128b_used + ipv6_128b_free))); 1593 LOG_CLI((BSL_META_U(unit, 1594 "\n**********"))); 1595 LOG_CLI((BSL_META_U(unit, 1596 "\nTotal IPv6 LPM entries in use \t\t= %5d"), 1597 BCM_XGS3_L3_DEFIP_IP6_CNT(unit))); 1598 LOG_CLI((BSL_META_U(unit, 1599 "\nTotal IPv6 LPM entries free \t\t= %5d"), 1600 (ipv6_64b_free + ipv6_128b_free))); 1601 LOG_CLI((BSL_META_U(unit, 1602 "\nTotal IPv6 LPM entries \t\t\t= %5d\n"), 1603 BCM_XGS3_L3_DEFIP_IP6_CNT(unit) + 1604 (ipv6_64b_free + ipv6_128b_free))); 1605 } 1606 return (BCM_E_NONE); 1607 } 1608 1609 /* 1610 * Function: 1611 * bcmi_kt_extended_queue_config_destroy 1612 * Purpose: 1613 * Destroy cosq settings done as part of l3 egress. 1614 * Parameters: 1615 * unit - (IN)SOC unit number 1616 * idx - (IN)Egress obj id. 1617 * Returns: 1618 * BCM_E_XXX. 1619 */ 1620 int 1621 bcmi_kt_extended_queue_config_destroy(int unit, bcm_if_t idx) 1622 { 1623 ing_queue_map_entry_t ing_queue_entry; 1624 ing_l3_next_hop_entry_t in_entry; 1625 int old_queue_id = 0; 1626 int mem = ING_L3_NEXT_HOPm; 1627 1628 sal_memset(&in_entry, 0, BCM_XGS3_L3_ENT_SZ(unit, nh)); 1629 /* Read ingress next hop entry. */ 1630 BCM_IF_ERROR_RETURN(BCM_XGS3_MEM_READ(unit, mem, idx, &in_entry)); 1631 1632 old_queue_id = soc_mem_field32_get(unit, mem, &in_entry, 1633 EH_QUEUE_TAGf); 1634 if (old_queue_id > 0) { 1635 /* ING_QUEUE_MAP needs to be reset */ 1636 sal_memset(&ing_queue_entry, 0, sizeof(ing_queue_map_entry_t)); 1637 BCM_IF_ERROR_RETURN(BCM_XGS3_MEM_WRITE(unit, ING_QUEUE_MAPm, 1638 old_queue_id, &ing_queue_entry)); 1639 } 1640 return BCM_E_NONE; 1641 } 1642 1643 #else /* BCM_KT_SUPPORT && INCLUDE_L3 */ 1644 int bcm_kt_l3_not_empty; 1645 #endif /* BCM_KT_SUPPORT && INCLUDE_L3 */ 1646