l3.c (42737B)
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: Triumph L3 function implementations 9 */ 10 11 12 #include <soc/defs.h> 13 14 #include <assert.h> 15 16 #include <sal/core/libc.h> 17 #if defined(BCM_TRX_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/tunnel.h> 31 #include <bcm/debug.h> 32 #include <bcm/error.h> 33 #include <bcm/stack.h> 34 35 #include <bcm_int/esw/mbcm.h> 36 #include <bcm_int/esw/firebolt.h> 37 #if defined(BCM_TRX_SUPPORT) 38 #include <bcm_int/esw/trx.h> 39 #endif /* BCM_TRX_SUPPORT */ 40 #if defined(BCM_TRIUMPH_SUPPORT) 41 #include <bcm_int/esw/triumph.h> 42 #endif /* BCM_TRIUMPH_SUPPORT */ 43 #include <bcm_int/esw/l3.h> 44 #include <bcm_int/esw/xgs3.h> 45 #include <bcm_int/esw_dispatch.h> 46 47 48 _bcm_l3_defip_128_table_t *l3_trx_defip_128[BCM_MAX_NUM_UNITS]; 49 50 /* 51 * Function: 52 * _bcm_tr_tnl_type_to_hw_code 53 * Purpose: 54 * Translate tunnel type into value used in hardware 55 * (56624(Triumph) only. 56 * Parameters: 57 * unit - (IN) SOC unit number. 58 * tnl_type - (IN) Tunnel type. 59 * hw_code - (OUT) HW code for tunnel type. 60 * entry_type - (OUT) Entry type. 61 * Returns: 62 * BCM_E_XXX 63 */ 64 int 65 _bcm_trx_tnl_type_to_hw_code(int unit, bcm_tunnel_type_t tnl_type, 66 int *hw_code, int *entry_type) 67 { 68 /* Input parameters check. */ 69 if ((NULL == hw_code) || (NULL == entry_type)) { 70 return (BCM_E_PARAM); 71 } 72 73 switch (tnl_type) { 74 case bcmTunnelTypeNone: 75 *hw_code = 0; 76 *entry_type = BCM_XGS3_TUNNEL_INIT_NONE; 77 break; 78 79 case bcmTunnelTypeIp4In4: 80 case bcmTunnelTypeIp6In4: 81 case bcmTunnelTypeIpAnyIn4: 82 *hw_code = 0; 83 *entry_type = BCM_XGS3_TUNNEL_INIT_V4; 84 break; 85 86 case bcmTunnelTypeIp4In6: 87 case bcmTunnelTypeIp6In6: 88 case bcmTunnelTypeIpAnyIn6: 89 *hw_code = 0; 90 *entry_type = BCM_XGS3_TUNNEL_INIT_V6; 91 #ifdef BCM_TRIDENT3_SUPPORT 92 if (SOC_IS_TRIDENT3X(unit)) { 93 *entry_type = BCM_XGS3_TUNNEL_INIT_V6_TD3; 94 } 95 #endif 96 break; 97 98 case bcmTunnelType6In4Uncheck: 99 *hw_code = 0x1; 100 *entry_type = BCM_XGS3_TUNNEL_INIT_V4; 101 break; 102 103 case bcmTunnelTypeIsatap: 104 *hw_code = 0x2; 105 *entry_type = BCM_XGS3_TUNNEL_INIT_V4; 106 break; 107 108 case bcmTunnelType6In4: 109 *hw_code = 0x3; 110 *entry_type = BCM_XGS3_TUNNEL_INIT_V4; 111 break; 112 113 case bcmTunnelTypeGre4In4: 114 case bcmTunnelTypeGre6In4: 115 case bcmTunnelTypeGreAnyIn4: 116 *hw_code = 0x4; 117 *entry_type = BCM_XGS3_TUNNEL_INIT_V4; 118 break; 119 120 case bcmTunnelTypeGre4In6: 121 case bcmTunnelTypeGre6In6: 122 case bcmTunnelTypeGreAnyIn6: 123 *hw_code = 0x4; 124 *entry_type = BCM_XGS3_TUNNEL_INIT_V6; 125 #ifdef BCM_TRIDENT3_SUPPORT 126 if (SOC_IS_TRIDENT3X(unit)) { 127 *entry_type = BCM_XGS3_TUNNEL_INIT_V6_TD3; 128 } 129 #endif 130 break; 131 132 case bcmTunnelTypePimSmDr1: 133 *hw_code = 0x5; 134 *entry_type = BCM_XGS3_TUNNEL_INIT_V4; 135 break; 136 137 case bcmTunnelTypePimSmDr2: 138 *hw_code = 0x6; 139 *entry_type = BCM_XGS3_TUNNEL_INIT_V4; 140 break; 141 142 case bcmTunnelTypePim6SmDr1: 143 *hw_code = 0x5; 144 *entry_type = BCM_XGS3_TUNNEL_INIT_V6; 145 #ifdef BCM_TRIDENT3_SUPPORT 146 if (SOC_IS_TRIDENT3X(unit)) { 147 *entry_type = BCM_XGS3_TUNNEL_INIT_V6_TD3; 148 } 149 #endif 150 break; 151 152 case bcmTunnelTypePim6SmDr2: 153 *hw_code = 0x6; 154 *entry_type = BCM_XGS3_TUNNEL_INIT_V6; 155 #ifdef BCM_TRIDENT3_SUPPORT 156 if (SOC_IS_TRIDENT3X(unit)) { 157 *entry_type = BCM_XGS3_TUNNEL_INIT_V6_TD3; 158 } 159 #endif 160 break; 161 162 case bcmTunnelTypeL2Gre: 163 *hw_code = 0x7; 164 *entry_type = BCM_XGS3_TUNNEL_INIT_V4; 165 break; 166 167 case bcmTunnelTypeWlanAcToAc: 168 *hw_code = 0x8; 169 *entry_type = BCM_XGS3_TUNNEL_INIT_V4; 170 break; 171 172 case bcmTunnelTypeWlanAcToAc6: 173 *hw_code = 0x8; 174 *entry_type = BCM_XGS3_TUNNEL_INIT_V6; 175 #ifdef BCM_TRIDENT3_SUPPORT 176 if (SOC_IS_TRIDENT3X(unit)) { 177 *entry_type = BCM_XGS3_TUNNEL_INIT_V6_TD3; 178 } 179 #endif 180 break; 181 182 case bcmTunnelTypeWlanWtpToAc: 183 *hw_code = 0x9; 184 *entry_type = BCM_XGS3_TUNNEL_INIT_V4; 185 break; 186 187 case bcmTunnelTypeWlanWtpToAc6: 188 *hw_code = 0x9; 189 *entry_type = BCM_XGS3_TUNNEL_INIT_V6; 190 #ifdef BCM_TRIDENT3_SUPPORT 191 if (SOC_IS_TRIDENT3X(unit)) { 192 *entry_type = BCM_XGS3_TUNNEL_INIT_V6_TD3; 193 } 194 #endif 195 break; 196 197 case bcmTunnelTypeAutoMulticast: 198 *hw_code = 0xA; 199 *entry_type = BCM_XGS3_TUNNEL_INIT_V4; 200 break; 201 202 case bcmTunnelTypeAutoMulticast6: 203 *hw_code = 0xA; 204 *entry_type = BCM_XGS3_TUNNEL_INIT_V6; 205 #ifdef BCM_TRIDENT3_SUPPORT 206 if (SOC_IS_TRIDENT3X(unit)) { 207 *entry_type = BCM_XGS3_TUNNEL_INIT_V6_TD3; 208 } 209 #endif 210 break; 211 #ifdef BCM_MONTEREY_SUPPORT 212 case bcmTunnelTypeRoeIn4: 213 *hw_code = 0xC; 214 *entry_type = BCM_XGS3_TUNNEL_INIT_V4; 215 break; 216 217 case bcmTunnelTypeRoeIn6: 218 *hw_code = 0xC; 219 *entry_type = BCM_XGS3_TUNNEL_INIT_V6; 220 break; 221 #endif 222 default: 223 break; 224 } 225 return (BCM_E_NONE); 226 } 227 228 /* 229 * Function: 230 * _bcm_trx_tnl_hw_code_to_type 231 * Purpose: 232 * Translate hw code for tunnel type into api value 233 * Parameters: 234 * unit - (IN) SOC unit number. 235 * hw_tnl_type - (IN) HW tunnel code. 236 * entry_type - (IN) IPv4/IPv6/MPLS entry. 237 * tunnel_type - (OUT) Tunnel type. 238 * Returns: 239 * BCM_E_XXX 240 */ 241 int 242 _bcm_trx_tnl_hw_code_to_type(int unit, int hw_tnl_type, 243 int entry_type, bcm_tunnel_type_t *tunnel_type) 244 { 245 /* Input parameters check. */ 246 if (NULL == tunnel_type) { 247 return (BCM_E_PARAM); 248 } 249 250 if (BCM_XGS3_TUNNEL_INIT_NONE == entry_type) { 251 *tunnel_type = bcmTunnelTypeNone; 252 return (BCM_E_NONE); 253 } 254 255 switch (hw_tnl_type) { 256 case 0: 257 if (BCM_XGS3_TUNNEL_INIT_V4 == entry_type) { 258 *tunnel_type = bcmTunnelTypeIpAnyIn4; 259 } else { 260 *tunnel_type = bcmTunnelTypeIpAnyIn6; 261 } 262 break; 263 case 0x1: 264 *tunnel_type = bcmTunnelType6In4Uncheck; 265 break; 266 case 0x2: 267 *tunnel_type = bcmTunnelTypeIsatap; 268 break; 269 case 0x3: 270 *tunnel_type = bcmTunnelType6In4; 271 break; 272 case 0x4: 273 *tunnel_type = (BCM_XGS3_TUNNEL_INIT_V4 == entry_type) ? \ 274 bcmTunnelTypeGreAnyIn4 : bcmTunnelTypeGreAnyIn6; 275 break; 276 case 0x5: 277 *tunnel_type = (BCM_XGS3_TUNNEL_INIT_V4 == entry_type) ? \ 278 bcmTunnelTypePimSmDr1 : bcmTunnelTypePim6SmDr1; 279 break; 280 case 0x6: 281 *tunnel_type = (BCM_XGS3_TUNNEL_INIT_V4 == entry_type) ? \ 282 bcmTunnelTypePimSmDr2 : bcmTunnelTypePim6SmDr2; 283 break; 284 case 0x7: 285 *tunnel_type = bcmTunnelTypeL2Gre; 286 break; 287 case 0x8: 288 *tunnel_type = (BCM_XGS3_TUNNEL_INIT_V4 == entry_type) ? \ 289 bcmTunnelTypeWlanAcToAc : bcmTunnelTypeWlanAcToAc6; 290 break; 291 case 0x9: 292 *tunnel_type = (BCM_XGS3_TUNNEL_INIT_V4 == entry_type) ? \ 293 bcmTunnelTypeWlanWtpToAc : bcmTunnelTypeWlanWtpToAc6; 294 break; 295 case 0xA: 296 *tunnel_type = (BCM_XGS3_TUNNEL_INIT_V4 == entry_type) ? \ 297 bcmTunnelTypeAutoMulticast : bcmTunnelTypeAutoMulticast6; 298 break; 299 case 0xB: 300 *tunnel_type = (BCM_XGS3_TUNNEL_INIT_V4 == entry_type) ? \ 301 bcmTunnelTypeVxlan : bcmTunnelTypeVxlan6; 302 break; 303 #ifdef BCM_MONTEREY_SUPPORT 304 case 0xC: 305 *tunnel_type = (BCM_XGS3_TUNNEL_INIT_V4 == entry_type) ? \ 306 bcmTunnelTypeRoeIn4 : bcmTunnelTypeRoeIn6; 307 break; 308 #endif 309 default: 310 return (BCM_E_PARAM); 311 } 312 return (BCM_E_NONE); 313 } 314 315 /* 316 * Function: 317 * _bcm_trx_defip_128_hash 318 * Purpose: 319 * Calculate an entry 8 bit hash. 320 * Parameters: 321 * unit - (IN)SOC unit number. 322 * lpm_cfg - (IN)Buffer to fill defip information. 323 * entry_hash - (OUT)Entry hash 324 * Returns: 325 * BCM_E_XXX 326 */ 327 STATIC int 328 _trx_defip_128_hash(int unit, _bcm_defip_cfg_t *lpm_cfg, uint8 *hash) 329 { 330 uint32 key[BCM_TRX_DEFIP128_HASH_SZ]; 331 332 if (NULL == hash) { 333 return (BCM_E_PARAM); 334 } 335 336 SAL_IP6_ADDR_TO_UINT32(lpm_cfg->defip_ip6_addr, key); 337 key[4] = lpm_cfg->defip_sub_len; 338 key[5] = lpm_cfg->defip_vrf; 339 340 *hash = (_shr_crc16b(0, (void *)key, 341 WORDS2BITS((BCM_TRX_DEFIP128_HASH_SZ))) & 0xff); 342 return (BCM_E_NONE); 343 } 344 345 #ifdef BCM_WARM_BOOT_SUPPORT 346 /* 347 * Function: 348 * _trx_defip_128_reinit 349 * Purpose: 350 * Re-Initialize sw image for L3_DEFIP_128 internal tcam. 351 * during warm boot. 352 * Parameters: 353 * unit - (IN)SOC unit number. 354 * idx - (IN)Entry index 355 * lpm_cfg - (IN)Inserted entry. 356 * Returns: 357 * BCM_E_XXX 358 */ 359 STATIC int 360 _trx_defip_128_reinit(int unit, int idx, _bcm_defip_cfg_t *lpm_cfg) 361 { 362 int lkup_plen; /* Vrf weighted lookup prefix. */ 363 uint8 hash; /* Entry hash value. */ 364 365 /* Calculate vrf weighted prefix length. */ 366 lkup_plen = lpm_cfg->defip_sub_len * 367 ((BCM_L3_VRF_OVERRIDE == lpm_cfg->defip_vrf) ? 2 : 1); 368 369 /* Calculate entry lookup hash. */ 370 BCM_IF_ERROR_RETURN(_trx_defip_128_hash(unit, lpm_cfg, &hash)); 371 372 /* Set software structure info. */ 373 BCM_TRX_DEFIP128_ENTRY_SET(unit, idx, lkup_plen, hash); 374 375 /* Update software usage counter. */ 376 BCM_TRX_DEFIP128_USED_COUNT(unit)++; 377 378 return (BCM_E_NONE); 379 } 380 381 #endif /* BCM_WARM_BOOT_SUPPORT */ 382 383 /* 384 * Function: 385 * _bcm_trx_defip_128_init 386 * Purpose: 387 * Initialize sw image for L3_DEFIP_128 internal tcam. 388 * Parameters: 389 * unit - (IN)SOC unit number. 390 * Returns: 391 * BCM_E_XXX 392 */ 393 int 394 _bcm_trx_defip_128_init(int unit) 395 { 396 int mem_sz; /* Memory allocation size */ 397 int rv; /* Internal operation status. */ 398 399 /* De-allocate any existing structures. */ 400 if (NULL != BCM_TRX_DEFIP128(unit)) { 401 rv = _bcm_trx_defip_128_deinit(unit); 402 BCM_IF_ERROR_RETURN(rv); 403 } 404 405 /* Allocate cam control structure. */ 406 mem_sz = sizeof(_bcm_l3_defip_128_table_t); 407 BCM_TRX_DEFIP128(unit) = sal_alloc(mem_sz, "l3_trx_defip_128"); 408 if (NULL == BCM_TRX_DEFIP128(unit)) { 409 return (BCM_E_MEMORY); 410 } 411 412 /* Reset cam control structure. */ 413 sal_memset(BCM_TRX_DEFIP128(unit), 0, mem_sz); 414 415 BCM_TRX_DEFIP128_TOTAL(unit) = soc_mem_index_count(unit, L3_DEFIP_128m); 416 417 418 if (SOC_URPF_STATUS_GET(unit)) { 419 BCM_TRX_DEFIP128_TOTAL(unit) >>= 1; 420 BCM_TRX_DEFIP128_URPF_OFFSET(unit) = BCM_TRX_DEFIP128_TOTAL(unit); 421 } else { 422 BCM_TRX_DEFIP128_URPF_OFFSET(unit) = 0; 423 } 424 425 BCM_TRX_DEFIP128_IDX_MAX(unit) = BCM_TRX_DEFIP128_TOTAL(unit) - 1; 426 427 mem_sz = BCM_TRX_DEFIP128_TOTAL(unit) * sizeof(_bcm_l3_defip_128_entry_t); 428 429 BCM_TRX_DEFIP128_ARR(unit) = sal_alloc(mem_sz, "l3_defip_128_entry_array"); 430 if (NULL == BCM_TRX_DEFIP128_ARR(unit)) { 431 BCM_IF_ERROR_RETURN(_bcm_trx_defip_128_deinit(unit)); 432 return (BCM_E_MEMORY); 433 } 434 sal_memset(BCM_TRX_DEFIP128_ARR(unit), 0, mem_sz); 435 436 return (BCM_E_NONE); 437 } 438 439 /* 440 * Function: 441 * _bcm_trx_defip_128_deinit 442 * Purpose: 443 * De-initialize sw image for L3_DEFIP_128 internal tcam. 444 * Parameters: 445 * unit - (IN)SOC unit number. 446 * Returns: 447 * BCM_E_XXX 448 */ 449 int 450 _bcm_trx_defip_128_deinit(int unit) 451 { 452 if (NULL == BCM_TRX_DEFIP128(unit)) { 453 return (BCM_E_NONE); 454 } 455 456 457 /* De-allocate any existing structures. */ 458 if (NULL != BCM_TRX_DEFIP128_ARR(unit)) { 459 sal_free(BCM_TRX_DEFIP128_ARR(unit)); 460 BCM_TRX_DEFIP128_ARR(unit) = NULL; 461 } 462 sal_free(BCM_TRX_DEFIP128(unit)); 463 BCM_TRX_DEFIP128(unit) = NULL; 464 465 return (BCM_E_NONE); 466 } 467 468 /* 469 * Function: 470 * _trx_defip_128_get_key 471 * Purpose: 472 * Parse route entry key from L3_DEFIP_128 table. 473 * Parameters: 474 * unit - (IN)SOC unit number. 475 * entry - (IN)Hw entry buffer. 476 * lpm_cfg - (IN/OUT)Buffer to fill defip information. 477 * Returns: 478 * BCM_E_XXX 479 */ 480 STATIC int 481 _trx_defip_128_get_key(int unit, uint32 *hw_entry, 482 _bcm_defip_cfg_t *lpm_cfg) 483 { 484 soc_mem_t mem = L3_DEFIP_128m; /* Route table memory. */ 485 bcm_ip6_t mask; /* Subnet mask. */ 486 487 /* Input parameters check. */ 488 if ((NULL == lpm_cfg) || (NULL == hw_entry)) { 489 return (BCM_E_PARAM); 490 } 491 492 /* Extract ip6 address. */ 493 soc_mem_ip6_addr_get(unit, mem, hw_entry, IP_ADDRf, lpm_cfg->defip_ip6_addr, 494 SOC_MEM_IP6_FULL_ADDR); 495 496 /* Extract subnet mask. */ 497 soc_mem_ip6_addr_get(unit, mem, hw_entry, IP_ADDR_MASKf, mask, 498 SOC_MEM_IP6_FULL_ADDR); 499 lpm_cfg->defip_sub_len = bcm_ip6_mask_length(mask); 500 501 /* Extract vrf id & vrf mask. */ 502 if(!soc_mem_field32_get(unit, mem, hw_entry, VRF_ID_MASKf)) { 503 lpm_cfg->defip_vrf = BCM_L3_VRF_OVERRIDE; 504 } else { 505 lpm_cfg->defip_vrf = soc_mem_field32_get(unit, mem, hw_entry, VRF_IDf); 506 } 507 return (BCM_E_NONE); 508 } 509 510 /* 511 * Function: 512 * _trx_defip_128_parse 513 * Purpose: 514 * Parse route entry from L3_DEFIP_128 table to sw structure. 515 * Parameters: 516 * unit - (IN)SOC unit number. 517 * hw_entry - (IN)Hw entry buffer. 518 * lpm_cfg - (IN/OUT)Buffer to fill defip information. 519 * nh_ecmp_idx - (OUT)Next hop ecmp table index. 520 * Returns: 521 * BCM_E_XXX 522 */ 523 STATIC INLINE int 524 _trx_defip_128_parse(int unit, uint32 *hw_entry, 525 _bcm_defip_cfg_t *lpm_cfg, int *nh_ecmp_idx) 526 { 527 soc_mem_t mem = L3_DEFIP_128m; /* Route table memory. */ 528 529 /* Input parameters check. */ 530 if ((NULL == hw_entry) || (NULL == lpm_cfg)) { 531 return (BCM_E_PARAM); 532 } 533 534 /* Reset entry flags first. */ 535 lpm_cfg->defip_flags = 0; 536 537 /* Check if entry points to ecmp group. */ 538 if (soc_mem_field32_get(unit, mem, hw_entry, ECMPf)) { 539 /* Mark entry as ecmp */ 540 lpm_cfg->defip_ecmp = TRUE; 541 lpm_cfg->defip_flags |= BCM_L3_MULTIPATH; 542 543 /* Get ecmp group id. */ 544 if (NULL != nh_ecmp_idx) { 545 *nh_ecmp_idx = soc_mem_field32_get(unit, mem, hw_entry, ECMP_PTRf); 546 } 547 } else { 548 /* Mark entry as non-ecmp. */ 549 lpm_cfg->defip_ecmp = 0; 550 551 /* Reset ecmp group next hop count. */ 552 lpm_cfg->defip_ecmp_count = 0; 553 554 /* Get next hop index. */ 555 if (NULL != nh_ecmp_idx) { 556 *nh_ecmp_idx = 557 soc_mem_field32_get(unit, mem, hw_entry, NEXT_HOP_INDEXf); 558 } 559 } 560 561 /* Mark entry as IPv6 */ 562 lpm_cfg->defip_flags |= BCM_L3_IP6; 563 564 /* Get entry priority. */ 565 lpm_cfg->defip_prio = soc_mem_field32_get(unit, mem, hw_entry, PRIf); 566 567 /* Get classification group id. */ 568 lpm_cfg->defip_lookup_class = 569 soc_mem_field32_get(unit, mem, hw_entry, CLASS_IDf); 570 571 /* Get hit bit. */ 572 if (soc_mem_field32_get(unit, mem, hw_entry, HITf)) { 573 lpm_cfg->defip_flags |= BCM_L3_HIT; 574 } 575 576 /* Get priority override bit. */ 577 if (soc_mem_field32_get(unit, mem, hw_entry, RPEf)) { 578 lpm_cfg->defip_flags |= BCM_L3_RPE; 579 } 580 581 /* Get destination discard field. */ 582 if(soc_mem_field32_get(unit, mem, hw_entry, DST_DISCARDf)) { 583 lpm_cfg->defip_flags |= BCM_L3_DST_DISCARD; 584 } 585 return (BCM_E_NONE); 586 } 587 588 /* 589 * Function: 590 * _trx_defip_128_match 591 * Purpose: 592 * Lookup route entry from L3_DEFIP_128 table. 593 * Parameters: 594 * unit - (IN)SOC unit number. 595 * lpm_cfg - (IN)Buffer to fill defip information. 596 * hw_entry - (OUT)Matching hw entry. 597 * hw_index - (OUT)HW table index. 598 * Returns: 599 * BCM_E_XXX 600 */ 601 STATIC int 602 _trx_defip_128_match(int unit, _bcm_defip_cfg_t *lpm_cfg, 603 uint32 *hw_entry, int *hw_index) 604 { 605 _bcm_defip_cfg_t candidate; /* Match condidate. */ 606 int lkup_plen; /* Vrf weighted lookup prefix. */ 607 int index; /* Table iteration index. */ 608 uint8 hash; /* Entry hash value. */ 609 int rv = BCM_E_NONE; /* Internal operation status. */ 610 611 612 /* Initialization */ 613 sal_memset(&candidate, 0, sizeof(_bcm_defip_cfg_t)); 614 615 /* Calculate vrf weighted prefix length. */ 616 lkup_plen = lpm_cfg->defip_sub_len * 617 ((BCM_L3_VRF_OVERRIDE == lpm_cfg->defip_vrf) ? 2 : 1); 618 619 /* Calculate entry lookup hash. */ 620 BCM_IF_ERROR_RETURN(_trx_defip_128_hash(unit, lpm_cfg, &hash)); 621 622 /* coverity[assignment : FALSE] */ 623 for (index = 0; index <= BCM_TRX_DEFIP128_IDX_MAX(unit); index++) { 624 625 /* Route prefix length comparison. */ 626 if (lkup_plen != BCM_TRX_DEFIP128_ARR(unit)[index].prefix_len) { 627 continue; 628 } 629 630 /* Route lookup key hash comparison. */ 631 if (hash != BCM_TRX_DEFIP128_ARR(unit)[index].entry_hash) { 632 continue; 633 } 634 635 /* Hash & prefix length match -> read and compare hw entry itself. */ 636 rv = BCM_XGS3_MEM_READ(unit, L3_DEFIP_128m, index, hw_entry); 637 if (BCM_FAILURE(rv)) { 638 break; 639 } 640 641 /* Make sure entry is valid. */ 642 if ((!soc_mem_field32_get(unit, L3_DEFIP_128m, hw_entry, VALID_0f)) || 643 (!soc_mem_field32_get(unit, L3_DEFIP_128m, hw_entry, VALID_1f))) { 644 /* Too bad sw image doesn't match hardware. */ 645 continue; 646 } 647 648 /* Extract entry address vrf */ 649 rv = _trx_defip_128_get_key(unit, hw_entry, &candidate); 650 if (BCM_FAILURE(rv)) { 651 break; 652 } 653 654 655 /* Address & Vrf comparison. */ 656 if (lpm_cfg->defip_vrf != candidate.defip_vrf) { 657 continue; 658 } 659 660 /* Subnet mask comparison. */ 661 if (lpm_cfg->defip_sub_len != candidate.defip_sub_len) { 662 continue; 663 } 664 665 666 if (sal_memcmp(lpm_cfg->defip_ip6_addr, candidate.defip_ip6_addr, 667 sizeof(bcm_ip6_t))) { 668 continue; 669 } 670 671 672 /* Matching entry found. */ 673 break; 674 675 } 676 677 BCM_IF_ERROR_RETURN(rv); 678 679 if (index > BCM_TRX_DEFIP128_IDX_MAX(unit)) { 680 return (BCM_E_NOT_FOUND); 681 } 682 683 #ifdef BCM_TRIDENT_SUPPORT 684 if (SOC_IS_TRIDENT(unit)) { 685 uint32 hit_x, hit_y; 686 BCM_IF_ERROR_RETURN 687 (BCM_XGS3_MEM_READ(unit, L3_DEFIP_128_HIT_ONLY_Ym, index, &hit_y)); 688 hit_x = soc_mem_field32_get(unit, L3_DEFIP_128m, hw_entry, HITf); 689 hit_x |= hit_y; 690 soc_mem_field32_set(unit, L3_DEFIP_128m, hw_entry, HITf, hit_x); 691 } 692 #endif /* BCM_TRIDENT_SUPPORT */ 693 694 *hw_index = index; 695 return (BCM_E_NONE); 696 } 697 698 /* 699 * Function: 700 * _trx_defip_128_entry_clear 701 * Purpose: 702 * Clear/Reset a single route entry. 703 * Parameters: 704 * unit - (IN)SOC unit number. 705 * hw_index - (IN)Entry index in the tcam. 706 * Returns: 707 * BCM_E_XXX 708 */ 709 STATIC int 710 _trx_defip_128_entry_clear(int unit, int hw_index) 711 { 712 713 /* Reset hw entry. */ 714 BCM_IF_ERROR_RETURN 715 (BCM_XGS3_MEM_WRITE(unit, L3_DEFIP_128m, hw_index, 716 soc_mem_entry_null(unit, L3_DEFIP_128m))); 717 718 /* Reset sw entry. */ 719 BCM_TRX_DEFIP128_ENTRY_SET(unit, hw_index, 0, 0); 720 721 /* Reset urpf source lookup entry. */ 722 if (SOC_URPF_STATUS_GET(unit)) { 723 BCM_IF_ERROR_RETURN 724 (BCM_XGS3_MEM_WRITE(unit, L3_DEFIP_128m, 725 (hw_index + BCM_TRX_DEFIP128_URPF_OFFSET(unit)), 726 soc_mem_entry_null(unit, L3_DEFIP_128m))); 727 } 728 return (BCM_E_NONE); 729 } 730 /* 731 * Function: 732 * _trx_defip_128_shift 733 * Purpose: 734 * Shift entries in the tcam. 735 * Parameters: 736 * unit - (IN)SOC unit number. 737 * idx_src - (IN)Entry source. 738 * idx_dest - (IN)Entry destination. 739 * Returns: 740 * BCM_E_XXX 741 */ 742 STATIC int 743 _trx_defip_128_shift(int unit, int idx_src, int idx_dest) 744 { 745 uint32 hw_entry[SOC_MAX_MEM_FIELD_WORDS]; /* HW entry buffer. */ 746 747 /* Don't copy uninstalled entries. */ 748 if (0 != BCM_TRX_DEFIP128_ARR(unit)[idx_src].prefix_len) { 749 /* Read entry from source index. */ 750 BCM_IF_ERROR_RETURN 751 (BCM_XGS3_MEM_READ(unit, L3_DEFIP_128m, idx_src, hw_entry)); 752 753 /* Write entry to the destination index. */ 754 BCM_IF_ERROR_RETURN 755 (BCM_XGS3_MEM_WRITE(unit, L3_DEFIP_128m, idx_dest, hw_entry)); 756 757 /* Shift corresponding URPF/source lookup entries. */ 758 if (SOC_URPF_STATUS_GET(unit)) { 759 /* Read entry from source index + half tcam. */ 760 BCM_IF_ERROR_RETURN 761 (BCM_XGS3_MEM_READ(unit, L3_DEFIP_128m, 762 idx_src + BCM_TRX_DEFIP128_URPF_OFFSET(unit), 763 hw_entry)); 764 765 /* Write entry to the destination index + half tcam. */ 766 BCM_IF_ERROR_RETURN 767 (BCM_XGS3_MEM_WRITE(unit, L3_DEFIP_128m, 768 idx_dest + BCM_TRX_DEFIP128_URPF_OFFSET(unit), 769 hw_entry)); 770 } 771 } 772 /* Copy software portion of the entry. */ 773 sal_memcpy (&BCM_TRX_DEFIP128_ARR(unit)[idx_dest], 774 &BCM_TRX_DEFIP128_ARR(unit)[idx_src], 775 sizeof(_bcm_l3_defip_128_entry_t)); 776 777 return (BCM_E_NONE); 778 } 779 780 /* 781 * Function: 782 * _trx_defip_128_shift_range 783 * Purpose: 784 * Shift entries in the tcam. 785 * Parameters: 786 * unit - (IN)SOC unit number. 787 * idx_start - (IN)Start index 788 * idx_end - (IN)End index 789 * Returns: 790 * BCM_E_XXX 791 */ 792 STATIC int 793 _trx_defip_128_shift_range(int unit, int idx_start, int idx_end) 794 { 795 int idx; /* Iteration index. */ 796 int rv = BCM_E_NONE; /* Operaton status. */ 797 798 /* Shift entries down (1 index up) */ 799 if (idx_end > idx_start) { 800 for (idx = idx_end - 1; idx >= idx_start; idx--) { 801 rv = _trx_defip_128_shift(unit, idx, idx + 1); 802 if (BCM_FAILURE(rv)) { 803 break; 804 } 805 } 806 /* Delete last entry from hardware & software. */ 807 rv = _trx_defip_128_entry_clear(unit, idx_start); 808 } 809 810 /* Shift entries up (1 index down) */ 811 if (idx_end < idx_start) { 812 for (idx = idx_end + 1; idx <= idx_start; idx++) { 813 rv = _trx_defip_128_shift(unit, idx, idx - 1); 814 if (BCM_FAILURE(rv)) { 815 break; 816 } 817 } 818 /* Delete last entry from hardware & software. */ 819 rv = _trx_defip_128_entry_clear(unit, idx_start); 820 } 821 822 return (rv); 823 } 824 /* 825 * Function: 826 * _trx_defip_128_idx_alloc 827 * Purpose: 828 * Shuffle the tcam in order to insert a new entry 829 * based on vrf weighted prefix length. 830 * Parameters: 831 * unit - (IN)SOC unit number. 832 * lpm_cfg - (IN)Route info 833 * hw_index - (OUT)Allocated hw index. 834 * Returns: 835 * BCM_E_XXX 836 */ 837 STATIC int 838 _trx_defip_128_idx_alloc(int unit, _bcm_defip_cfg_t *lpm_cfg, int *hw_index) 839 { 840 int lkup_plen; /* Vrf weighted lookup prefix. */ 841 uint8 hash; /* Entry hash value. */ 842 int idx; /* Table iteration index. */ 843 int rv; /* Operation return status. */ 844 int shift_min = 0; /* Minimum entry shift required. */ 845 int range_start = 0; /* First valid location for pfx. */ 846 int range_end = BCM_TRX_DEFIP128_IDX_MAX(unit); 847 /* Last valid location for pfx. */ 848 int free_idx_before = -1; /* Free index before range_start. */ 849 int free_idx_after = -1; /* Free index after range_end. */ 850 851 /* Input parameters check. */ 852 if ((NULL == lpm_cfg) || (NULL == hw_index)) { 853 return (BCM_E_PARAM); 854 } 855 856 /* Calculate vrf weighted prefix length. */ 857 lkup_plen = lpm_cfg->defip_sub_len * 858 ((BCM_L3_VRF_OVERRIDE == lpm_cfg->defip_vrf) ? 2 : 1); 859 860 /* Calculate entry hash. */ 861 BCM_IF_ERROR_RETURN(_trx_defip_128_hash(unit, lpm_cfg, &hash)); 862 863 /* Make sure at least one slot is available. */ 864 if (BCM_TRX_DEFIP128_USED_COUNT(unit) == BCM_TRX_DEFIP128_TOTAL(unit)) { 865 return (BCM_E_FULL); 866 } 867 868 /* 869 * Find first valid index for the prefix; 870 */ 871 for (idx = 0; idx <= BCM_TRX_DEFIP128_IDX_MAX(unit); idx++) { 872 873 /* Remeber free entry before installation location. */ 874 if (0 == BCM_TRX_DEFIP128_ARR(unit)[idx].prefix_len) { 875 free_idx_before = idx; 876 continue; 877 } 878 /* Route prefix length comparison. */ 879 if (lkup_plen < BCM_TRX_DEFIP128_ARR(unit)[idx].prefix_len) { 880 range_start = idx + 1; 881 continue; 882 } 883 break; 884 } 885 886 /* 887 * Find last valid index for the prefix; 888 */ 889 for (idx = BCM_TRX_DEFIP128_IDX_MAX(unit); idx >= 0; idx--) { 890 891 /* Remeber free entry after installation location. */ 892 if (0 == BCM_TRX_DEFIP128_ARR(unit)[idx].prefix_len) { 893 free_idx_after = idx; 894 continue; 895 } 896 /* Route prefix length comparison. */ 897 if (lkup_plen > BCM_TRX_DEFIP128_ARR(unit)[idx].prefix_len) { 898 range_end = idx; 899 continue; 900 } 901 break; 902 } 903 904 /* Check if entry should be inserted at the end. */ 905 if (range_start > BCM_TRX_DEFIP128_IDX_MAX(unit)) { 906 /* coverity[negative_returns : FALSE] */ 907 /* Shift all entries from free_idx_before till the end 1 up. */ 908 /* coverity[negative_returns] */ 909 rv = _trx_defip_128_shift_range(unit, BCM_TRX_DEFIP128_IDX_MAX(unit), 910 free_idx_before); 911 912 if (BCM_SUCCESS(rv)) { 913 /* Allocated index is last TCAM entry. */ 914 *hw_index = BCM_TRX_DEFIP128_IDX_MAX(unit); 915 BCM_TRX_DEFIP128_ENTRY_SET(unit, *hw_index, lkup_plen, hash); 916 } 917 return (rv); 918 } 919 920 /* Check if entry should be inserted at the beginning. */ 921 if (range_end < 0) { 922 /* Shift all entries from 0 till free_idx_after 1 down. */ 923 rv = _trx_defip_128_shift_range(unit, 0, free_idx_after); 924 925 if (BCM_SUCCESS(rv)) { 926 /* Allocated index is first TCAM entry. */ 927 *hw_index = 0; 928 BCM_TRX_DEFIP128_ENTRY_SET(unit, 0, lkup_plen, hash); 929 } 930 return (rv); 931 } 932 933 /* Find if there is any free index in range. */ 934 for (idx = range_start; idx <= range_end; idx++) { 935 if (0 == BCM_TRX_DEFIP128_ARR(unit)[idx].prefix_len) { 936 *hw_index = idx; 937 BCM_TRX_DEFIP128_ENTRY_SET(unit, idx, lkup_plen, hash); 938 return (BCM_E_NONE); 939 } 940 } 941 942 /* Check if entry should be inserted at the end of range. */ 943 if ((free_idx_after > range_end) && (free_idx_after != -1)) { 944 shift_min = free_idx_after - range_end; 945 } 946 947 /* Check if entry should be inserted in the beginning. */ 948 if ((free_idx_before < range_start) && (free_idx_before != -1)) { 949 if(shift_min > (range_start - free_idx_before)) { 950 shift_min = -1; 951 } 952 /* coverity[negative_returns : FALSE] */ 953 } 954 955 /* coverity[negative_returns] */ 956 if (shift_min <= 0) { 957 rv = _trx_defip_128_shift_range(unit, range_start, free_idx_before); 958 /* coverity[negative_returns : FALSE] */ 959 if (BCM_SUCCESS(rv)) { 960 *hw_index= range_start; 961 /* coverity[negative_returns : FALSE] */ 962 BCM_TRX_DEFIP128_ENTRY_SET(unit, range_start, lkup_plen, hash); 963 /* coverity[negative_returns] */ 964 /* coverity[negative_returns] */ 965 } 966 } else { 967 /* coverity[negative_returns] */ 968 /* coverity[negative_returns] */ 969 rv = _trx_defip_128_shift_range(unit, range_end, free_idx_after); 970 if (BCM_SUCCESS(rv)) { 971 *hw_index = range_end; 972 BCM_TRX_DEFIP128_ENTRY_SET(unit, range_end, lkup_plen, hash); 973 } 974 } 975 return (rv); 976 } 977 /* 978 * Function: 979 * _bcm_trx_defip_128_get 980 * Purpose: 981 * Get an entry from L3_DEFIP_128 table. 982 * Parameters: 983 * unit - (IN)SOC unit number. 984 * lpm_cfg - (IN)Buffer to fill defip information. 985 * nh_ecmp_idx - (IN)Next hop or ecmp group index 986 * Returns: 987 * BCM_E_XXX 988 */ 989 int 990 _bcm_trx_defip_128_get(int unit, _bcm_defip_cfg_t *lpm_cfg, 991 int *nh_ecmp_idx) 992 { 993 uint32 hw_entry[SOC_MAX_MEM_FIELD_WORDS];/* Hw entry buffer. */ 994 bcm_ip6_t mask; /* Subnet mask. */ 995 int clear_hit; /* Clear entry hit bit flag. */ 996 int hw_index = 0; /* Entry offset in the TCAM. */ 997 int rv; /* Internal operation status.*/ 998 999 /* Input parameters check. */ 1000 if (NULL == lpm_cfg) { 1001 return (BCM_E_PARAM); 1002 } 1003 1004 /* Check if clear hit bit required. */ 1005 clear_hit = lpm_cfg->defip_flags & BCM_L3_HIT_CLEAR; 1006 1007 /* Create mask from prefix length. */ 1008 bcm_ip6_mask_create(mask, lpm_cfg->defip_sub_len); 1009 1010 /* Apply mask on address. */ 1011 bcm_xgs3_l3_mask6_apply(mask, lpm_cfg->defip_ip6_addr); 1012 1013 1014 /* Search for matching entry in the cam. */ 1015 rv = _trx_defip_128_match(unit, lpm_cfg, hw_entry, &hw_index); 1016 BCM_IF_ERROR_RETURN(rv); 1017 1018 lpm_cfg->defip_index = hw_index; 1019 1020 /* Parse matched entry. */ 1021 rv = _trx_defip_128_parse(unit, hw_entry, lpm_cfg, nh_ecmp_idx); 1022 BCM_IF_ERROR_RETURN(rv); 1023 1024 /* Clear the HIT bit */ 1025 if (clear_hit) { 1026 soc_mem_field32_set(unit, L3_DEFIP_128m, hw_entry, HITf, 0); 1027 1028 rv = BCM_XGS3_MEM_WRITE(unit, L3_DEFIP_128m, hw_index, hw_entry); 1029 } 1030 1031 return (rv); 1032 } 1033 1034 /* 1035 * Function: 1036 * _bcm_trx_defip_128_add 1037 * Purpose: 1038 * Add an entry to internal L3_DEFIP_128 table. 1039 * Parameters: 1040 * unit - (IN)SOC unit number. 1041 * lpm_cfg - (IN)Buffer to fill defip information. 1042 * nh_ecmp_idx - (IN)Next hop or ecmp group index. 1043 * Returns: 1044 * BCM_E_XXX 1045 */ 1046 int 1047 _bcm_trx_defip_128_add(int unit, _bcm_defip_cfg_t *lpm_cfg, 1048 int nh_ecmp_idx) 1049 { 1050 uint32 hw_entry[SOC_MAX_MEM_FIELD_WORDS]; /* New entry hw buffer. */ 1051 bcm_ip6_t mask; /* Subnet mask. */ 1052 int hw_index = 0; /* Entry offset in the TCAM. */ 1053 int rv; /* Operation return status. */ 1054 soc_mem_t mem = L3_DEFIP_128m; /* Route table memory. */ 1055 1056 /* Input parameters check. */ 1057 if (NULL == lpm_cfg) { 1058 return (BCM_E_PARAM); 1059 } 1060 1061 /* No support for routes matchin AFTER vrf specific. */ 1062 if (BCM_L3_VRF_GLOBAL == lpm_cfg->defip_vrf) { 1063 return (BCM_E_UNAVAIL); 1064 } 1065 1066 /* Zero buffers. */ 1067 sal_memset(hw_entry, 0, WORDS2BYTES(SOC_MAX_MEM_FIELD_WORDS)); 1068 1069 /* Create mask from prefix length. */ 1070 bcm_ip6_mask_create(mask, lpm_cfg->defip_sub_len); 1071 1072 /* Apply mask on address. */ 1073 bcm_xgs3_l3_mask6_apply(mask, lpm_cfg->defip_ip6_addr); 1074 1075 /* Allocate a new index for inserted entry. */ 1076 if (BCM_XGS3_L3_INVALID_INDEX == lpm_cfg->defip_index) { 1077 rv = _trx_defip_128_idx_alloc(unit, lpm_cfg, &hw_index); 1078 BCM_IF_ERROR_RETURN(rv); 1079 } else { 1080 hw_index = lpm_cfg->defip_index; 1081 } 1082 1083 /* Set hit bit. */ 1084 if (lpm_cfg->defip_flags & BCM_L3_HIT) { 1085 soc_mem_field32_set(unit, mem, hw_entry, HITf, 1); 1086 } 1087 1088 /* Set priority override bit. */ 1089 if (lpm_cfg->defip_flags & BCM_L3_RPE) { 1090 soc_mem_field32_set(unit, mem, hw_entry, RPEf, 1); 1091 } 1092 1093 /* Set classification group id. */ 1094 soc_mem_field32_set(unit, mem, hw_entry, CLASS_IDf, 1095 lpm_cfg->defip_lookup_class); 1096 1097 1098 /* Write priority field. */ 1099 soc_mem_field32_set(unit, mem, hw_entry, PRIf, lpm_cfg->defip_prio); 1100 1101 1102 /* Fill next hop information. */ 1103 if (lpm_cfg->defip_flags & BCM_L3_MULTIPATH) { 1104 soc_mem_field32_set(unit, mem, hw_entry, ECMP_PTRf, nh_ecmp_idx); 1105 soc_mem_field32_set(unit, mem, hw_entry, ECMPf, 1); 1106 } else { 1107 soc_mem_field32_set(unit, mem, hw_entry, NEXT_HOP_INDEXf, nh_ecmp_idx); 1108 } 1109 1110 /* Set destination discard flag. */ 1111 if (lpm_cfg->defip_flags & BCM_L3_DST_DISCARD) { 1112 soc_mem_field32_set(unit, mem, hw_entry, DST_DISCARDf, 1); 1113 } 1114 1115 /* Set valid bits. */ 1116 soc_mem_field32_set(unit, mem, hw_entry, VALID_0f, 1); 1117 soc_mem_field32_set(unit, mem, hw_entry, VALID_1f, 1); 1118 1119 1120 /* Set destination/source ip address. */ 1121 soc_mem_ip6_addr_set(unit, mem, hw_entry, IP_ADDRf, lpm_cfg->defip_ip6_addr, 1122 SOC_MEM_IP6_FULL_ADDR); 1123 1124 /* Set ip mask. */ 1125 soc_mem_ip6_addr_set(unit, mem, hw_entry, IP_ADDR_MASKf, mask, 1126 SOC_MEM_IP6_FULL_ADDR); 1127 1128 /* Set vrf id & vrf mask. */ 1129 if (BCM_L3_VRF_OVERRIDE != lpm_cfg->defip_vrf) { 1130 soc_mem_field32_set(unit, mem, hw_entry, VRF_IDf, lpm_cfg->defip_vrf); 1131 soc_mem_field32_set(unit, mem, hw_entry, VRF_ID_MASKf, 1132 (1 << soc_mem_field_length(unit, mem, 1133 VRF_ID_MASKf)) - 1); 1134 if (SOC_MEM_FIELD_VALID(unit, mem, GLOBAL_ROUTEf)) { 1135 soc_mem_field32_set(unit, mem, hw_entry, GLOBAL_ROUTEf, 0); 1136 } 1137 } else { 1138 soc_mem_field32_set(unit, mem, hw_entry, VRF_IDf, 0); 1139 soc_mem_field32_set(unit, mem, hw_entry, VRF_ID_MASKf, 0); 1140 } 1141 1142 /* Write buffer to hw. */ 1143 rv = BCM_XGS3_MEM_WRITE(unit, mem, hw_index, hw_entry); 1144 if (BCM_FAILURE(rv)) { 1145 BCM_TRX_DEFIP128_ENTRY_SET(unit, hw_index, 0, 0); 1146 return (rv); 1147 } 1148 1149 /* Write source lookup portion of the entry. */ 1150 if (SOC_URPF_STATUS_GET(unit)) { 1151 soc_mem_field32_set(unit, mem, hw_entry, SRC_DISCARDf, 0); 1152 rv = BCM_XGS3_MEM_WRITE(unit, L3_DEFIP_128m, 1153 (hw_index + BCM_TRX_DEFIP128_URPF_OFFSET(unit)), 1154 hw_entry); 1155 if (BCM_FAILURE(rv)) { 1156 _trx_defip_128_entry_clear(unit, hw_index); 1157 return (rv); 1158 } 1159 } 1160 1161 /* If new route added increment total number of routes. */ 1162 /* Lack of index indicates a new route. */ 1163 if (BCM_XGS3_L3_INVALID_INDEX == lpm_cfg->defip_index) { 1164 BCM_XGS3_L3_DEFIP_CNT_INC(unit, TRUE); 1165 BCM_TRX_DEFIP128_USED_COUNT(unit)++; 1166 } 1167 1168 return rv; 1169 } 1170 1171 1172 /* 1173 * Function: 1174 * _bcm_trx_defip_128_delete 1175 * Purpose: 1176 * Delete an entry from L3_DEFIP_128 table. 1177 * Parameters: 1178 * unit - (IN)SOC unit number. 1179 * lpm_cfg - (IN)Buffer to fill defip information. 1180 * Returns: 1181 * BCM_E_XXX 1182 */ 1183 int 1184 _bcm_trx_defip_128_delete(int unit, _bcm_defip_cfg_t *lpm_cfg) 1185 { 1186 uint32 hw_entry[SOC_MAX_MEM_FIELD_WORDS];/* Hw entry buffer. */ 1187 bcm_ip6_t mask; /* Subnet mask. */ 1188 int hw_index; /* Entry offset in the TCAM. */ 1189 int rv; /* Internal operation status.*/ 1190 /* Input parameters check. */ 1191 if (NULL == lpm_cfg) { 1192 return (BCM_E_PARAM); 1193 } 1194 1195 /* Create mask from prefix length. */ 1196 bcm_ip6_mask_create(mask, lpm_cfg->defip_sub_len); 1197 1198 /* Apply mask on address. */ 1199 bcm_xgs3_l3_mask6_apply(mask, lpm_cfg->defip_ip6_addr); 1200 1201 /* Search for matching entry in the cam. */ 1202 rv = _trx_defip_128_match(unit, lpm_cfg, hw_entry, &hw_index); 1203 if (BCM_FAILURE(rv)) { 1204 return (rv); 1205 } 1206 /* Delete entry from hardware & software. */ 1207 rv = _trx_defip_128_entry_clear(unit, hw_index); 1208 if (BCM_SUCCESS(rv)) { 1209 BCM_XGS3_L3_DEFIP_CNT_DEC(unit, TRUE); 1210 BCM_TRX_DEFIP128_USED_COUNT(unit)--; 1211 } 1212 1213 return (rv); 1214 } 1215 1216 1217 /* 1218 * Function: 1219 * _bcm_trx_defip_128_update_match 1220 * Purpose: 1221 * Update/Delete all entries in defip table matching a certain rule. 1222 * Parameters: 1223 * unit - (IN)SOC unit number. 1224 * trv_data - (IN)Delete pattern + compare,act,notify routines. 1225 * Returns: 1226 * BCM_E_XXX 1227 */ 1228 int 1229 _bcm_trx_defip_128_update_match(int unit, _bcm_l3_trvrs_data_t *trv_data) 1230 { 1231 int idx; /* Iteration index. */ 1232 int rv; /* Operation return status. */ 1233 int cmp_result; /* Test routine result. */ 1234 int nh_ecmp_idx; /* Next hop/Ecmp group index. */ 1235 uint32 *hw_entry; /* Hw entry buffer. */ 1236 char *lpm_tbl_ptr; /* Dma table pointer. */ 1237 int defip_table_size; /* Defip table size. */ 1238 _bcm_defip_cfg_t lpm_cfg; /* Buffer to fill route info. */ 1239 soc_mem_t mem = L3_DEFIP_128m; /* Route table memory. */ 1240 1241 /* Table DMA the LPM table to software copy */ 1242 BCM_IF_ERROR_RETURN 1243 (bcm_xgs3_l3_tbl_dma(unit, mem, BCM_L3_MEM_ENT_SIZE(unit, mem), 1244 "lpm_tbl", &lpm_tbl_ptr, &defip_table_size)); 1245 1246 if (SOC_URPF_STATUS_GET(unit)) { 1247 defip_table_size >>= 1; 1248 } 1249 1250 for (idx = 0; idx < defip_table_size; idx++) { 1251 /* Calculate entry ofset. */ 1252 hw_entry = soc_mem_table_idx_to_pointer(unit, mem, uint32 *, 1253 lpm_tbl_ptr, idx); 1254 1255 /* Make sure entry is valid. */ 1256 if (!soc_mem_field32_get (unit, mem, hw_entry, VALID_0f)) { 1257 continue; 1258 } 1259 1260 #ifdef BCM_TRIDENT_SUPPORT 1261 if (SOC_IS_TRIDENT(unit)) { 1262 uint32 hit_x, hit_y; 1263 BCM_IF_ERROR_RETURN 1264 (BCM_XGS3_MEM_READ(unit, L3_DEFIP_128_HIT_ONLY_Ym, idx, 1265 &hit_y)); 1266 hit_x = soc_mem_field32_get(unit, L3_DEFIP_128m, hw_entry, HITf); 1267 hit_x |= hit_y; 1268 soc_mem_field32_set(unit, L3_DEFIP_128m, hw_entry, HITf, hit_x); 1269 } 1270 #endif /* BCM_TRIDENT_SUPPORT */ 1271 1272 /* Zero destination buffer first. */ 1273 sal_memset(&lpm_cfg, 0, sizeof(_bcm_defip_cfg_t)); 1274 1275 /* Parse the entry. */ 1276 _trx_defip_128_parse(unit, hw_entry, &lpm_cfg, &nh_ecmp_idx); 1277 lpm_cfg.defip_index = idx; 1278 1279 /* Fill entry ip address & subnet mask. */ 1280 _trx_defip_128_get_key(unit, hw_entry, &lpm_cfg); 1281 1282 /* Execute operation routine if any. */ 1283 if (trv_data->op_cb) { 1284 rv = (*trv_data->op_cb) (unit, (void *)trv_data, 1285 (void *)&lpm_cfg, 1286 (void *)&nh_ecmp_idx, &cmp_result); 1287 if (BCM_FAILURE(rv)) { 1288 soc_cm_sfree(unit, lpm_tbl_ptr); 1289 return rv; 1290 } 1291 } 1292 #ifdef BCM_WARM_BOOT_SUPPORT 1293 if (SOC_WARM_BOOT(unit)) { 1294 rv = _trx_defip_128_reinit(unit, idx, &lpm_cfg); 1295 if (BCM_FAILURE(rv)) { 1296 soc_cm_sfree(unit, lpm_tbl_ptr); 1297 return rv; 1298 } 1299 } 1300 #endif /* BCM_WARM_BOOT_SUPPORT */ 1301 } 1302 1303 #ifdef BCM_WARM_BOOT_SUPPORT 1304 if (SOC_WARM_BOOT(unit)) { 1305 SOC_IF_ERROR_RETURN(soc_fb_lpm_reinit_done(unit, 1)); 1306 } 1307 #endif /* BCM_WARM_BOOT_SUPPORT */ 1308 soc_cm_sfree(unit, lpm_tbl_ptr); 1309 return (BCM_E_NONE); 1310 } 1311 1312 /* 1313 * Function: 1314 * _bcm_trx_l3_defip_mem_get 1315 * Purpose: 1316 * Resolve route table memory for a given route entry. 1317 * Parameters: 1318 * unit - (IN)SOC unit number. 1319 * flags - (IN)IPv6/IPv4 route. 1320 * plen - (IN)Prefix length. 1321 * mem - (OUT)Route table memory. 1322 * Returns: 1323 * BCM_E_XXX 1324 */ 1325 int 1326 _bcm_trx_l3_defip_mem_get(int unit, uint32 flags, int plen, soc_mem_t *mem) 1327 { 1328 /* Input parameters check. */ 1329 if (NULL == mem) { 1330 return (BCM_E_PARAM); 1331 } 1332 1333 #if defined(BCM_TRIUMPH_SUPPORT) 1334 if (SOC_IS_TR_VL(unit)) { 1335 BCM_IF_ERROR_RETURN 1336 (_bcm_tr_l3_defip_mem_get(unit, flags, plen, mem)); 1337 } 1338 #endif /* BCM_TRIUMPH_SUPPORT */ 1339 #if defined(BCM_SCORPION_SUPPORT) 1340 if (SOC_IS_SCORPION(unit)) { 1341 if ((flags & BCM_L3_IP6) && (plen > 64)) { 1342 *mem = L3_DEFIP_128m; 1343 } else { 1344 *mem = L3_DEFIPm; 1345 } 1346 } 1347 #endif /* BCM_SCORPION_SUPPORT */ 1348 return (BCM_E_NONE); 1349 } 1350 1351 #if defined(BCM_TRIUMPH_SUPPORT) 1352 /* 1353 * Function: 1354 * _bcm_trx_l3_defip_verify_internal_mem_usage 1355 * Purpose: 1356 * Verify if entries are present within INT-DEFIP table 1357 * Parameters: 1358 * unit - (IN)SOC unit number. 1359 * Returns: 1360 * BCM_E_XXX 1361 */ 1362 1363 int 1364 _bcm_trx_l3_defip_verify_internal_mem_usage(int unit) 1365 { 1366 if (soc_feature(unit, soc_feature_esm_support)) { 1367 if (SOC_MEM_IS_VALID(unit, L3_DEFIP_128m)) { 1368 if (soc_mem_index_count(unit, L3_DEFIP_128m)) { 1369 if (BCM_TRX_DEFIP128(unit) != NULL) { 1370 if (BCM_TRX_DEFIP128_USED_COUNT(unit)) { 1371 return BCM_E_DISABLED; 1372 } 1373 } 1374 } 1375 } 1376 } 1377 return BCM_E_NONE; 1378 } 1379 #endif 1380 1381 1382 int 1383 _bcm_trx_defip128_used_count_get(int unit) 1384 { 1385 return BCM_TRX_DEFIP128_USED_COUNT(unit); 1386 } 1387 1388 int 1389 _bcm_trx_defip128_idx_max_get(int unit) 1390 { 1391 return BCM_TRX_DEFIP128_IDX_MAX(unit); 1392 } 1393 1394 int 1395 _bcm_trx_defip128_array_idx_prefix_len_get(int unit, int arr_idx) 1396 { 1397 return BCM_TRX_DEFIP128_ARR(unit)[arr_idx].prefix_len; 1398 } 1399 1400 #else /* BCM_TRX_SUPPORT && INCLUDE_L3 */ 1401 int bcm_trx_l3_not_empty; 1402 #endif /* BCM_TRX_SUPPORT && INCLUDE_L3 */