l3.c (50355B)
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: trident2plus specific L3 function implementations 9 */ 10 #include <shared/bsl.h> 11 #include <soc/defs.h> 12 13 #if defined(INCLUDE_L3) 14 #if defined(BCM_FIREBOLT_SUPPORT) 15 #include <bcm_int/esw/firebolt.h> 16 #endif 17 18 #ifdef BCM_RIOT_SUPPORT 19 #include <assert.h> 20 #include <sal/core/libc.h> 21 #include <shared/util.h> 22 #if defined(BCM_FIREBOLT_SUPPORT) 23 #include <soc/mem.h> 24 #include <soc/l3x.h> 25 #include <bcm/l3.h> 26 #include <bcm/error.h> 27 #include <bcm_int/esw/mbcm.h> 28 #include <bcm_int/esw/l3.h> 29 #include <bcm_int/esw/vlan.h> 30 #include <bcm_int/esw/virtual.h> 31 #if defined(BCM_TRIDENT_SUPPORT) 32 #include <bcm_int/esw/trident.h> 33 #endif /* BCM_TRIDENT_SUPPORT*/ 34 #if defined(BCM_TRIDENT2_SUPPORT) 35 #include <soc/trident2.h> 36 #include <bcm_int/esw/trident2.h> 37 #include <bcm_int/esw/nat.h> 38 #include <bcm_int/esw/qos.h> 39 #endif /* BCM_TRIDENT_SUPPORT*/ 40 #include <bcm_int/esw/trident2plus.h> 41 #ifdef BCM_WARM_BOOT_SUPPORT 42 #include <bcm_int/esw/switch.h> 43 #endif /* BCM_WARM_BOOT_SUPPORT */ 44 #include <bcm_int/common/multicast.h> 45 #include <bcm_int/esw_dispatch.h> 46 #include <bcm_int/esw/failover.h> 47 #endif 48 #endif /* BCM_RIOT_SUPPORT */ 49 50 /* initialize pointer for useful bokkkeeping information */ 51 #define L3_BK_INFO(_unit_) (&_bcm_l3_bk_info[_unit_]) 52 53 #ifdef BCM_RIOT_SUPPORT 54 /* Set ul-ol link params */ 55 #define BCM_L3_NH_NUM_UNDERLAY_BUCKETS 1024 56 ul_nh_link_t *ul_nh_assoc_head 57 [BCM_MAX_NUM_UNITS][BCM_L3_NH_NUM_UNDERLAY_BUCKETS] = {{NULL}}; 58 59 /* 60 * Function: 61 * bcmi_l3_riot_bank_sel 62 * Purpose: 63 * Initialize banks for L3 objects. 64 * The whole l3 table can be divided into 65 * multiple layers and you can set different banks 66 * for different layers. 67 * Parameters: 68 * unit - SOC device unit number 69 * Returns: 70 * BCM_E_NONE Success 71 * BCM_E_XXX ERROR 72 */ 73 int 74 bcmi_l3_riot_bank_sel(int unit) 75 { 76 uint32 bank_sel_reg_val = 0; 77 uint32 num_ol_banks = 0; 78 uint32 l2_tunnel_parse_control = 0; 79 _bcm_l3_bookkeeping_t *l3 = L3_BK_INFO(unit); 80 uint32 ol_bank_bit_value = 0; 81 int iter; 82 int num_nh, num_l3_intf; 83 int max_nh_banks, max_l3_intf_banks; 84 85 if (!(BCMI_RIOT_IS_ENABLED(unit))) { 86 return BCM_E_NONE; 87 } 88 89 /* The interface entries can only be allocated in terms of 2k 90 * banks. if user is allocating in between boundries then we need 91 * to throw error as hardware cannot divide overlay and underlay 92 * entries in between bank. 93 * If SDK does not return error here then user can start using 94 * different entries in same banks for overlay and underlay and may 95 * see unextected results. 96 */ 97 if (l3->l3_intf_overlay_entries % BCMI_L3_INTF_ENT_PER_BANK(unit)) { 98 LOG_ERROR(BSL_LS_BCM_L3, (BSL_META_U(unit, 99 "Please allocate entries in the multiple of %d.\n"), 100 BCMI_L3_INTF_ENT_PER_BANK(unit))); 101 102 return BCM_E_PARAM; 103 } 104 105 if (l3->l3_nh_overlay_entries % BCMI_L3_NH_ENT_PER_BANK(unit)) { 106 LOG_ERROR(BSL_LS_BCM_L3, (BSL_META_U(unit, 107 "Please allocate entries in the multiple of %d.\n"), 108 BCMI_L3_NH_ENT_PER_BANK(unit))); 109 110 return BCM_E_PARAM; 111 } 112 num_nh = soc_mem_index_count(unit, ING_L3_NEXT_HOPm); 113 num_l3_intf = soc_mem_index_count(unit, EGR_L3_INTFm); 114 115 max_nh_banks = num_nh / BCMI_L3_NH_ENT_PER_BANK(unit); 116 max_l3_intf_banks = num_l3_intf / BCMI_L3_INTF_ENT_PER_BANK(unit); 117 118 if (max_nh_banks == 0) { 119 LOG_ERROR(BSL_LS_BCM_L3, (BSL_META_U(unit, 120 "No NH banks in system.\n"))); 121 return BCM_E_RESOURCE; 122 } 123 if (max_l3_intf_banks == 0) { 124 LOG_ERROR(BSL_LS_BCM_L3, (BSL_META_U(unit, 125 "No EGR_L3_INTF banks in system.\n"))); 126 return BCM_E_RESOURCE; 127 } 128 /* 129 * set banks for EGR_L3_INTF 130 * By default ("alloc mode" is 0): 131 * First set of banks are for overlay. 132 * Second set of banks are for underlay. 133 * If "alloc mode" is 1: 134 * First set of banks are for underlay. 135 * Second set of banks are for overlay. 136 */ 137 num_ol_banks = (l3->l3_intf_overlay_entries / 138 BCMI_L3_INTF_ENT_PER_BANK(unit)) + 139 ((l3->l3_intf_overlay_entries % BCMI_L3_INTF_ENT_PER_BANK(unit)) ? 1 : 140 0); 141 142 if (num_ol_banks > max_l3_intf_banks) { 143 LOG_ERROR(BSL_LS_BCM_L3, (BSL_META_U(unit, 144 "ERROR : Overlay l3 interface(%d) > total interfaces(%d).\n"), 145 l3->l3_intf_overlay_entries, 146 max_l3_intf_banks * BCMI_L3_INTF_ENT_PER_BANK(unit))); 147 148 return BCM_E_CONFIG; 149 } 150 151 /* Setup the bits for overlay banks. */ 152 for (iter = 0; iter < num_ol_banks; iter++) { 153 ol_bank_bit_value |= (1 << iter) ; 154 } 155 if (l3->l3_intf_overlay_alloc_mode > 0) { 156 ol_bank_bit_value <<= (max_l3_intf_banks - num_ol_banks); 157 } 158 159 soc_reg_field_set(unit, EGR_L3_INTF_BANK_SELr, &bank_sel_reg_val, 160 BANK_SELf, ol_bank_bit_value); 161 /* set banks in EGR_L3_INTF_BANK_SELr */ 162 SOC_IF_ERROR_RETURN(WRITE_EGR_L3_INTF_BANK_SELr 163 (unit, bank_sel_reg_val)); 164 165 ol_bank_bit_value = 0; 166 bank_sel_reg_val = 0; 167 /* 168 * set banks for ING/EGR/INITIAL_ING_L3_NEXT_HOP. 169 * By default ("alloc mode" is 0): 170 * First set of banks are for overlay. 171 * Second set of banks are for underlay. 172 * If "alloc mode" is 1: 173 * First set of banks are for underlay. 174 * Second set of banks are for overlay. 175 */ 176 num_ol_banks = (l3->l3_nh_overlay_entries / BCMI_L3_NH_ENT_PER_BANK(unit)) + 177 ((l3->l3_nh_overlay_entries % BCMI_L3_NH_ENT_PER_BANK(unit)) ? 1 : 0); 178 if (l3->l3_nh_reserve_for_ecmp) { 179 max_nh_banks -= 180 (BCM_XGS3_L3_ECMP_MAX_GROUPS(unit) / BCMI_L3_ECMP_PER_BANK(unit)) 181 + ((BCM_XGS3_L3_ECMP_MAX_GROUPS(unit) % 182 BCMI_L3_ECMP_PER_BANK(unit)) ? 1 : 0); 183 } 184 if (num_ol_banks > max_nh_banks) { 185 LOG_ERROR(BSL_LS_BCM_L3, (BSL_META_U(unit, 186 "ERROR : Overlay l3 Next hop (%d) > total l3 next hop(%d).\n"), 187 l3->l3_nh_overlay_entries, 188 max_nh_banks * BCMI_L3_NH_ENT_PER_BANK(unit))); 189 190 return BCM_E_CONFIG; 191 } 192 if (l3->l3_nh_reserve_for_ecmp && (l3->l3_nh_overlay_alloc_mode == 0)) { 193 num_ol_banks += 194 (BCM_XGS3_L3_ECMP_MAX_GROUPS(unit) / BCMI_L3_ECMP_PER_BANK(unit)) 195 + ((BCM_XGS3_L3_ECMP_MAX_GROUPS(unit) % 196 BCMI_L3_ECMP_PER_BANK(unit)) ? 1 : 0); 197 } 198 for (iter=0; iter < num_ol_banks; iter++) { 199 ol_bank_bit_value |= (1 << iter) ; 200 } 201 if (l3->l3_nh_overlay_alloc_mode > 0) { 202 if (l3->l3_nh_reserve_for_ecmp) { 203 ol_bank_bit_value <<= (max_nh_banks - num_ol_banks + 204 (BCM_XGS3_L3_ECMP_MAX_GROUPS(unit) / 205 BCMI_L3_ECMP_PER_BANK(unit)) + 206 ((BCM_XGS3_L3_ECMP_MAX_GROUPS(unit) % 207 BCMI_L3_ECMP_PER_BANK(unit)) ? 1 : 0)); 208 } else { 209 ol_bank_bit_value <<= (max_nh_banks - num_ol_banks); 210 } 211 } 212 213 /* set banks in INITIAL_ING_L3_NEXT_HOP_BANK_SELr */ 214 soc_reg_field_set(unit, INITIAL_ING_L3_NEXT_HOP_BANK_SELr, 215 &bank_sel_reg_val, BANK_SELf, ol_bank_bit_value); 216 217 SOC_IF_ERROR_RETURN(WRITE_INITIAL_ING_L3_NEXT_HOP_BANK_SELr 218 (unit, bank_sel_reg_val)); 219 220 /* set banks in ING_L3_NEXT_HOP_BANK_SELr */ 221 soc_reg_field_set(unit, ING_L3_NEXT_HOP_BANK_SELr, 222 &bank_sel_reg_val, BANK_SELf, ol_bank_bit_value); 223 224 SOC_IF_ERROR_RETURN(WRITE_ING_L3_NEXT_HOP_BANK_SELr 225 (unit, bank_sel_reg_val)); 226 227 /* set banks in EGR_L3_NEXT_HOP_BANK_SELr */ 228 soc_reg_field_set(unit, EGR_L3_NEXT_HOP_BANK_SELr, 229 &bank_sel_reg_val, BANK_SELf, ol_bank_bit_value); 230 SOC_IF_ERROR_RETURN(WRITE_EGR_L3_NEXT_HOP_BANK_SELr 231 (unit, bank_sel_reg_val)); 232 233 #ifdef BCM_TRIDENT3_SUPPORT 234 if (SOC_IS_TRIDENT3X(unit) && 235 (soc_property_get(unit, spn_L3_ECMP_LEVELS, 1) == 2) && 236 (l3->l3_ecmp_group_first_lkup_mem_size || 237 l3->l3_ecmp_member_first_lkup_mem_size)) { 238 uint32 rval = 0, rval2 = 0; 239 int ecmp_level_sel_reg_val = (BCMI_L3_ECMP_IS_MULTI_LEVEL(unit) ? 1 : 0); 240 soc_reg_field_set(unit, ECMP_CONFIGr, &rval, ECMP_MODEf, 241 ecmp_level_sel_reg_val); 242 soc_reg_field_set(unit, ECMP_CONFIG_2r, &rval2, ECMP_MODEf, 243 ecmp_level_sel_reg_val); 244 245 SOC_IF_ERROR_RETURN(WRITE_ECMP_CONFIGr(unit, rval)); 246 SOC_IF_ERROR_RETURN(WRITE_ECMP_CONFIG_2r(unit, rval2)); 247 248 if (l3->l3_ecmp_group_first_lkup_mem_size <= BCM_XGS3_L3_ECMP_MAX_GROUPS(unit)) { 249 ol_bank_bit_value = (1 << 250 ((l3->l3_ecmp_group_first_lkup_mem_size / BCMI_L3_ECMP_GROUP_PER_BANK(unit)) + 251 ((l3->l3_ecmp_group_first_lkup_mem_size % BCMI_L3_ECMP_GROUP_PER_BANK(unit)) ? 252 1 : 0))) - 1; 253 soc_reg_field_set(unit, ING_L3_ECMP_GROUP_BANK_SELr, 254 &bank_sel_reg_val, BANK_SELf, ol_bank_bit_value); 255 SOC_IF_ERROR_RETURN(WRITE_ING_L3_ECMP_GROUP_BANK_SELr 256 (unit, bank_sel_reg_val)); 257 soc_reg_field_set(unit, INITIAL_ING_L3_ECMP_GROUP_BANK_SELr, 258 &bank_sel_reg_val, BANK_SELf, ol_bank_bit_value); 259 SOC_IF_ERROR_RETURN(WRITE_INITIAL_ING_L3_ECMP_GROUP_BANK_SELr 260 (unit, bank_sel_reg_val)); 261 } else { 262 LOG_ERROR(BSL_LS_BCM_L3, (BSL_META_U(unit, 263 "ERROR : l3 ecmp group (%d) > total l3 ecmp group(%d).\n"), 264 l3->l3_ecmp_group_first_lkup_mem_size, 265 BCM_XGS3_L3_ECMP_MAX_GROUPS(unit))); 266 267 return BCM_E_CONFIG; 268 } 269 270 if (l3->l3_ecmp_member_first_lkup_mem_size <= (soc_mem_index_count(unit, 271 L3_ECMPm))) { 272 ol_bank_bit_value = (1 << 273 ((l3->l3_ecmp_group_first_lkup_mem_size / BCMI_L3_ECMP_PER_BANK(unit)) + 274 ((l3->l3_ecmp_group_first_lkup_mem_size % BCMI_L3_ECMP_PER_BANK(unit)) ? 275 1 : 0))) - 1; 276 soc_reg_field_set(unit, ING_L3_ECMP_BANK_SELr, 277 &bank_sel_reg_val, BANK_SELf, ol_bank_bit_value); 278 SOC_IF_ERROR_RETURN(WRITE_ING_L3_ECMP_BANK_SELr 279 (unit, bank_sel_reg_val)); 280 soc_reg_field_set(unit, INITIAL_ING_L3_ECMP_BANK_SELr, 281 &bank_sel_reg_val, BANK_SELf, ol_bank_bit_value); 282 SOC_IF_ERROR_RETURN(WRITE_INITIAL_ING_L3_ECMP_BANK_SELr 283 (unit, bank_sel_reg_val)); 284 } else { 285 LOG_ERROR(BSL_LS_BCM_L3, (BSL_META_U(unit, 286 "ERROR : l3 ecmp group (%d) > total l3 ecmp group(%d).\n"), 287 l3->l3_ecmp_group_first_lkup_mem_size, 288 BCM_XGS3_L3_ECMP_MAX(unit))); 289 290 return BCM_E_CONFIG; 291 } 292 } 293 #endif 294 295 /* Enable the control to look into inner l3 header for RioT */ 296 soc_reg_field_set(unit, ING_L2_TUNNEL_PARSE_CONTROLr, 297 &l2_tunnel_parse_control, IFP_L2_TUNNEL_PAYLOAD_FIELD_SELf, 0x1); 298 soc_reg_field_set(unit, ING_L2_TUNNEL_PARSE_CONTROLr, 299 &l2_tunnel_parse_control, PARSE_IPV4_PAYLOADf, 0x1); 300 soc_reg_field_set(unit, ING_L2_TUNNEL_PARSE_CONTROLr, 301 &l2_tunnel_parse_control, PARSE_IPV6_PAYLOADf, 0x1); 302 SOC_IF_ERROR_RETURN(WRITE_ING_L2_TUNNEL_PARSE_CONTROLr 303 (unit, l2_tunnel_parse_control)); 304 305 return BCM_E_NONE; 306 } 307 308 /* 309 * Function: 310 * bcmi_l3_riot_ecmp_level_sel 311 * Purpose: 312 * Initialize banks for L3 objects. 313 * The whole l3 table can be divided into 314 * multiple layers and you can set different banks 315 * for different layers. 316 * Parameters: 317 * unit - SOC device unit number 318 * Returns: 319 * BCM_E_NONE Success 320 * BCM_E_XXX ERROR 321 */ 322 int 323 bcmi_l3_riot_ecmp_level_sel(int unit) 324 { 325 uint32 ecmp_level_sel_reg_val = 0; 326 uint32 rval = 0; 327 #if defined(BCM_TRIDENT3_SUPPORT) 328 uint32 rval2 = 0; 329 uint32 ecmp_bank_sel_reg_val = 0; 330 #endif 331 332 /* 333 * If ecmp level is multi level then set ecmp config register to 1. 334 * else set the ecmp config register to 0. 0 is default case for 335 * legacy single level of ecmp. 336 */ 337 ecmp_level_sel_reg_val = (BCMI_L3_ECMP_IS_MULTI_LEVEL(unit) ? 1 : 0); 338 #if defined(BCM_TRIDENT3_SUPPORT) 339 if (soc_feature(unit, soc_feature_td3_style_riot)) { 340 soc_reg_field_set(unit, ECMP_CONFIGr, &rval, ECMP_MODEf, 341 ecmp_level_sel_reg_val); 342 soc_reg_field_set(unit, ECMP_CONFIG_2r, &rval2, ECMP_MODEf, 343 ecmp_level_sel_reg_val); 344 345 SOC_IF_ERROR_RETURN(WRITE_ECMP_CONFIGr(unit, rval)); 346 SOC_IF_ERROR_RETURN(WRITE_ECMP_CONFIG_2r(unit, rval2)); 347 348 if (ecmp_level_sel_reg_val) { 349 /* Divide ECMP entries into two equal halves for two level resolution */ 350 /* Need to provide option for bank selection later */ 351 /* Maximum number of ECMP group and member banks is 8 in TD3 and 4 352 * in HX5. 353 */ 354 soc_reg_field_set(unit, INITIAL_ING_L3_ECMP_BANK_SELr, 355 &ecmp_bank_sel_reg_val, BANK_SELf, 356 ((1 << (soc_reg_field_length(unit, 357 INITIAL_ING_L3_ECMP_BANK_SELr, BANK_SELf) / 2)) 358 - 1)); 359 SOC_IF_ERROR_RETURN(WRITE_INITIAL_ING_L3_ECMP_BANK_SELr 360 (unit, ecmp_bank_sel_reg_val)); 361 362 soc_reg_field_set(unit, ING_L3_ECMP_BANK_SELr, 363 &ecmp_bank_sel_reg_val, BANK_SELf, 364 ((1 << (soc_reg_field_length(unit, 365 ING_L3_ECMP_BANK_SELr, BANK_SELf) / 2)) 366 - 1)); 367 SOC_IF_ERROR_RETURN(WRITE_ING_L3_ECMP_BANK_SELr 368 (unit, ecmp_bank_sel_reg_val)); 369 370 ecmp_bank_sel_reg_val = 0; 371 372 soc_reg_field_set(unit, INITIAL_ING_L3_ECMP_GROUP_BANK_SELr, 373 &ecmp_bank_sel_reg_val, BANK_SELf, 374 ((1 << (soc_reg_field_length(unit, 375 INITIAL_ING_L3_ECMP_GROUP_BANK_SELr, BANK_SELf) 376 / 2)) - 1)); 377 SOC_IF_ERROR_RETURN(WRITE_INITIAL_ING_L3_ECMP_GROUP_BANK_SELr 378 (unit, ecmp_bank_sel_reg_val)); 379 380 soc_reg_field_set(unit, ING_L3_ECMP_GROUP_BANK_SELr, 381 &ecmp_bank_sel_reg_val, BANK_SELf, 382 ((1 << (soc_reg_field_length(unit, 383 ING_L3_ECMP_GROUP_BANK_SELr, BANK_SELf) / 2)) 384 - 1)); 385 SOC_IF_ERROR_RETURN(WRITE_ING_L3_ECMP_GROUP_BANK_SELr 386 (unit, ecmp_bank_sel_reg_val)); 387 388 } 389 } else 390 #endif 391 { 392 soc_reg_field_set(unit, ECMP_CONFIGr, &rval, ECMP_CONFIGURATIONf, 393 ecmp_level_sel_reg_val); 394 395 SOC_IF_ERROR_RETURN(WRITE_ECMP_CONFIGr(unit, rval)); 396 } 397 return BCM_E_NONE; 398 } 399 400 /* 401 * Function: 402 * bcmi_l3_nh_assoc_ol_ul_link_hash_dump 403 * Purpose: 404 * dumps the whole hash table 405 * Parameters: 406 * IN : Unit 407 * Returns: 408 * void 409 */ 410 void bcmi_l3_nh_assoc_ol_ul_link_hash_dump(int unit) 411 { 412 413 ol_nh_link_t *temp; 414 ul_nh_link_t *hash; 415 int i = 0; 416 417 LOG_ERROR(BSL_LS_SOC_COMMON, (BSL_META_U(unit, 418 "printing nh association hash table\n"))); 419 420 for (; i< BCM_L3_NH_NUM_UNDERLAY_BUCKETS; i++) { 421 hash = ul_nh_assoc_head[unit][i]; 422 while (hash != NULL) { 423 temp = hash->ol_nh_assoc; 424 while (temp != NULL) { 425 LOG_ERROR(BSL_LS_SOC_COMMON, (BSL_META_U(unit, 426 "bkt_idx = %d : ol index = %d : ul index = %d \n"), 427 i, hash->u_nh_idx, temp->o_nh_idx)); 428 temp = temp->next_link; 429 } 430 hash = hash->ul_nh_link; 431 } 432 } 433 } 434 435 /* 436 * Function: 437 * bcmi_nh_assoc_alloc_ol_link 438 * Purpose: 439 * Allocates link memory and sets overlay nh. 440 * Parameters: 441 * ol_nh - overlay nh number 442 * Returns: 443 * pointer to allocated link memory 444 */ 445 446 ol_nh_link_t * 447 bcmi_nh_assoc_alloc_ol_link(int ol_nh) 448 { 449 ol_nh_link_t *ptr ; 450 451 ptr = (ol_nh_link_t *) sal_alloc(sizeof(ol_nh_link_t), "ol_nh_link" ); 452 453 sal_memset(ptr, 0, sizeof(ol_nh_link_t)); 454 ptr->o_nh_idx = ol_nh; 455 return ptr; 456 } 457 458 /* 459 * Function: 460 * bcmi_nh_assoc_alloc_ul_link 461 * Purpose: 462 * Allocates link memory and sets underlay nh. 463 * Parameters: 464 * ul_nh - underlay nh number 465 * Returns: 466 * pointer to allocated link memory 467 */ 468 ul_nh_link_t * 469 bcmi_nh_assoc_alloc_ul_link(int ul_nh) 470 { 471 ul_nh_link_t *ptr; 472 473 ptr = (ul_nh_link_t *) sal_alloc(sizeof(ul_nh_link_t), "ul_nh_link"); 474 sal_memset(ptr, 0, sizeof(ul_nh_link_t)); 475 476 ptr->u_nh_idx = ul_nh; 477 return ptr; 478 } 479 480 481 /* 482 * Function: 483 * bcmi_nh_assoc_bkt_get 484 * Purpose: 485 * Adds a overlay/underlay association. 486 * Parameters: 487 * ol_nh - overlay nh number 488 * ul_nh - underlay nh number 489 * Returns: 490 * BCM_ERROR_T 491 */ 492 int 493 bcmi_nh_assoc_bkt_get(int nh_idx) 494 { 495 496 497 return( _shr_crc16b(0, (uint8 *)(&nh_idx), 498 BYTES2BITS(sizeof(nh_idx))) % 499 BCM_L3_NH_NUM_UNDERLAY_BUCKETS); 500 501 } 502 /* 503 * Function: 504 * bcmi_l3_nh_assoc_ol_ul_link_sw_add 505 * Purpose: 506 * Adds a overlay/underlay association. 507 * Parameters: 508 * ol_nh - overlay nh number 509 * ul_nh - underlay nh number 510 * Returns: 511 * BCM_ERROR_T 512 */ 513 int 514 bcmi_l3_nh_assoc_ol_ul_link_sw_add(int unit, int ol_nh, int ul_nh) 515 { 516 517 ul_nh_link_t *ul_assoc, *prev_assoc, *ul_alloc; 518 ol_nh_link_t *ol_link, *prev_link, *ol_alloc; 519 int bkt_idx = 0; 520 521 if (!(BCMI_RIOT_IS_ENABLED(unit))) { 522 return BCM_E_NONE; 523 } 524 525 bkt_idx = bcmi_nh_assoc_bkt_get(ul_nh); 526 527 prev_assoc = ul_assoc = ul_nh_assoc_head[unit][bkt_idx]; 528 while (ul_assoc && (ul_assoc->u_nh_idx != ul_nh)) { 529 prev_assoc = ul_assoc; 530 ul_assoc = ul_assoc->ul_nh_link; 531 } 532 533 if (ul_assoc) { 534 prev_link = ol_link = ul_assoc->ol_nh_assoc; 535 while (ol_link && (ol_link->o_nh_idx != ol_nh)) { 536 prev_link = ol_link; 537 ol_link = ol_link->next_link; 538 } 539 if (!ol_link) { 540 ol_alloc = bcmi_nh_assoc_alloc_ol_link(ol_nh); 541 if (ol_alloc == NULL) { 542 return BCM_E_MEMORY; 543 } 544 prev_link->next_link = ol_alloc; 545 } 546 } else { 547 548 ul_alloc = bcmi_nh_assoc_alloc_ul_link(ul_nh); 549 if (ul_alloc == NULL) { 550 return BCM_E_MEMORY; 551 } 552 ol_alloc = bcmi_nh_assoc_alloc_ol_link(ol_nh); 553 if (ol_alloc == NULL) { 554 sal_free(ul_alloc); 555 return BCM_E_MEMORY; 556 } 557 558 if (prev_assoc) { 559 prev_assoc->ul_nh_link = ul_alloc; 560 prev_assoc->ul_nh_link->ol_nh_assoc = ol_alloc; 561 } else { 562 ul_nh_assoc_head[unit][bkt_idx] = ul_alloc; 563 ul_nh_assoc_head[unit][bkt_idx]->ol_nh_assoc = ol_alloc; 564 } 565 } 566 /* 567 * increase the ref count of second next hop so that it 568 * not deleted in case someone tries to delete it. 569 */ 570 BCM_XGS3_L3_ENT_REF_CNT_INC 571 (BCM_XGS3_L3_TBL_PTR(unit, next_hop), ul_nh, 572 _BCM_SINGLE_WIDE); 573 574 return BCM_E_NONE; 575 } 576 577 /* 578 * Function: 579 * bcmi_l3_nh_del_nh_nh_assoc 580 * Purpose: 581 * Encode the dstination value based on the gport. 582 * Parameters: 583 * unit - SOC device unit number 584 * nh_idx - next hop index 585 * Returns: 586 * BCM_E_NONE Success 587 * BCM_E_XXX ERROR 588 */ 589 int bcmi_l3_nh_assoc_ol_ul_link_delete(int unit, int nh_idx) 590 { 591 soc_mem_t mem; /* Table location memory. */ 592 egr_l3_next_hop_entry_t egr_entry; /* Egress next hop entry. */ 593 int ent_type, next_ptr_type, next_nh_idx; 594 595 if (!(BCMI_RIOT_IS_ENABLED(unit))) { 596 return BCM_E_NONE; 597 } 598 599 mem = EGR_L3_NEXT_HOPm; 600 sal_memset(&egr_entry, 0, sizeof(egr_l3_next_hop_entry_t)); 601 602 SOC_IF_ERROR_RETURN(BCM_XGS3_MEM_READ(unit, EGR_L3_NEXT_HOPm, 603 nh_idx, &egr_entry)); 604 605 if (soc_feature(unit, soc_feature_mem_access_data_type)) { 606 ent_type = soc_mem_field32_get(unit, mem, &egr_entry, DATA_TYPEf); 607 } else { 608 ent_type = soc_mem_field32_get(unit, mem, &egr_entry, ENTRY_TYPEf); 609 } 610 611 /* chk if the entry is L3MC */ 612 if (ent_type == BCMI_L3_EGR_NH_MCAST_ENTRY_TYPE) { 613 next_ptr_type = soc_mem_field32_get 614 (unit, mem, &egr_entry, L3MC__NEXT_PTR_TYPEf); 615 616 if (next_ptr_type == BCMI_L3_NH_EGR_NEXT_PTR_TYPE_NH) { 617 next_nh_idx = soc_mem_field32_get(unit, mem, &egr_entry, 618 L3MC__NEXT_PTRf); 619 620 BCM_IF_ERROR_RETURN( 621 bcmi_l3_nh_assoc_ol_ul_link_sw_delete(unit, nh_idx, 622 next_nh_idx)); 623 } 624 } 625 626 return BCM_E_NONE; 627 } 628 629 /* 630 * Function: 631 * bcmi_l3_nh_assoc_ol_ul_link_sw_delete 632 * Purpose: 633 * Deletes a overlay/underlay association. 634 * If there is only one underlay nh link, 635 * then remove the overlay link also. 636 * Parameters: 637 * ol_nh - overlay nh number 638 * ul_nh - underlay nh number 639 * Returns: 640 * BCM_ERROR_T 641 */ 642 int 643 bcmi_l3_nh_assoc_ol_ul_link_sw_delete(int unit, int ol_nh, int ul_nh) 644 { 645 ul_nh_link_t *ul_assoc, *prev_assoc; 646 ol_nh_link_t *link_nh, *prev_link; 647 int bkt_idx = 0; 648 649 if (!(BCMI_RIOT_IS_ENABLED(unit))) { 650 return BCM_E_NONE; 651 } 652 653 bkt_idx = bcmi_nh_assoc_bkt_get(ul_nh); 654 655 prev_assoc = ul_assoc = ul_nh_assoc_head[unit][bkt_idx]; 656 657 while (ul_assoc && (ul_assoc->u_nh_idx != ul_nh)) { 658 prev_assoc = ul_assoc; 659 ul_assoc = ul_assoc->ul_nh_link; 660 } 661 662 if (ul_assoc) { 663 prev_link = link_nh = ul_assoc->ol_nh_assoc; 664 while (link_nh && (link_nh->o_nh_idx != ol_nh)) { 665 prev_link = link_nh; 666 link_nh = link_nh->next_link; 667 } 668 669 if (link_nh) { 670 if (link_nh == ul_assoc->ol_nh_assoc) { 671 ul_assoc->ol_nh_assoc = link_nh->next_link; 672 } else { 673 prev_link->next_link = link_nh->next_link; 674 } 675 sal_free(link_nh); 676 } else { 677 /* send an error here */ 678 return BCM_E_NOT_FOUND; 679 } 680 } 681 682 if (ul_assoc && (ul_assoc->ol_nh_assoc == NULL)) { 683 if (ul_assoc == ul_nh_assoc_head[unit][bkt_idx]) { 684 ul_nh_assoc_head[unit][bkt_idx] = ul_assoc->ul_nh_link; 685 } else { 686 prev_assoc->ul_nh_link = ul_assoc->ul_nh_link; 687 } 688 sal_free(ul_assoc); 689 } else if (ul_assoc == NULL) { 690 return BCM_E_NOT_FOUND; 691 } 692 /* 693 * decrease the ref count of second next hop so that it 694 * not deleted in case someone tries to delete it. 695 */ 696 BCM_XGS3_L3_ENT_REF_CNT_DEC 697 (BCM_XGS3_L3_TBL_PTR(unit, next_hop), ul_nh, 698 _BCM_SINGLE_WIDE); 699 700 return BCM_E_NONE; 701 } 702 703 704 /* 705 * Function: 706 * bcmi_l3_nh_assoc_ol_ul_link_replace 707 * Purpose: 708 * Replace overlay/underlay association. 709 * 710 * Parameters: 711 * ol_nh - overlay nh number 712 * ul_nh - underlay nh number 713 * Returns: 714 * BCM_ERROR_T 715 */ 716 int 717 bcmi_l3_nh_assoc_ol_ul_link_replace(int unit, int old_ul, int new_ul) 718 { 719 720 int entry_type, next_ptr_type; 721 egr_l3_next_hop_entry_t egr_nh; 722 ul_nh_link_t *ul_assoc; 723 ol_nh_link_t *ol_link; 724 int bkt_idx = 0; 725 726 if (!(BCMI_RIOT_IS_ENABLED(unit))) { 727 return BCM_E_NONE; 728 } 729 730 bkt_idx = bcmi_nh_assoc_bkt_get(old_ul); 731 732 if (ul_nh_assoc_head[unit][bkt_idx] == NULL) { 733 /* There is nothing to replace */ 734 return BCM_E_NONE; 735 } 736 ul_assoc = ul_nh_assoc_head[unit][bkt_idx]; 737 while (ul_assoc && (ul_assoc->u_nh_idx != old_ul)) { 738 ul_assoc = ul_assoc->ul_nh_link; 739 } 740 /* replace underlay nh index */ 741 if (ul_assoc) { 742 ol_link = ul_assoc->ol_nh_assoc; 743 while (ol_link) { 744 745 SOC_IF_ERROR_RETURN(soc_mem_read(unit, EGR_L3_NEXT_HOPm, MEM_BLOCK_ALL, 746 ol_link->o_nh_idx, &egr_nh)); 747 if (soc_feature(unit, soc_feature_mem_access_data_type)) { 748 entry_type = soc_EGR_L3_NEXT_HOPm_field32_get(unit, 749 &egr_nh, DATA_TYPEf); 750 } else { 751 entry_type = soc_EGR_L3_NEXT_HOPm_field32_get(unit, 752 &egr_nh, ENTRY_TYPEf); 753 } 754 if (entry_type == BCMI_L3_EGR_NH_MCAST_ENTRY_TYPE) { 755 next_ptr_type = soc_EGR_L3_NEXT_HOPm_field32_get(unit, 756 &egr_nh, L3MC__NEXT_PTR_TYPEf); 757 if (next_ptr_type == BCMI_L3_NH_EGR_NEXT_PTR_TYPE_NH) { 758 759 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 760 L3MC__NEXT_PTR_TYPEf, BCMI_L3_NH_EGR_NEXT_PTR_TYPE_NH); 761 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 762 L3MC__NEXT_PTRf, new_ul); 763 764 SOC_IF_ERROR_RETURN(soc_mem_write(unit, EGR_L3_NEXT_HOPm, 765 MEM_BLOCK_ALL, ol_link->o_nh_idx, &egr_nh)); 766 } 767 } 768 /* For all overlay NHs, replace the underlay NH. */ 769 bcmi_l3_nh_assoc_ol_ul_link_sw_delete(unit, ol_link->o_nh_idx, 770 old_ul); 771 bcmi_l3_nh_assoc_ol_ul_link_sw_add(unit, ol_link->o_nh_idx, 772 new_ul); 773 ol_link = ol_link->next_link; 774 } 775 776 } 777 778 return BCM_E_NONE; 779 } 780 781 /* 782 * Function: 783 * bcmi_l3_nh_assoc_ol_ul_link_is_required 784 * Purpose: 785 * check if nh-nh association is needed. 786 * Parameters: 787 * unit - unit number 788 * vp nh index - underlay nh number 789 * Returns: 790 * BCM_ERROR_T 791 */ 792 int 793 bcmi_l3_nh_assoc_ol_ul_link_is_required(int unit, int vp_nh_index) 794 { 795 /* int entry_type = 0; 796 egr_l3_next_hop_entry_t egr_nh; 797 int action_present=0, action_not_present=0, vntag_actions = 0;*/ 798 799 if (!(BCMI_RIOT_IS_ENABLED(unit))) { 800 return BCM_E_NONE; 801 } 802 #if 0 803 /*For TD3, the overlay nh can't be updated easily when underlay nh is changed*/ 804 SOC_IF_ERROR_RETURN(soc_mem_read(unit, EGR_L3_NEXT_HOPm, MEM_BLOCK_ALL, 805 vp_nh_index, &egr_nh)); 806 if (soc_feature(unit, soc_feature_mem_access_data_type)) { 807 entry_type = soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, DATA_TYPEf); 808 } else { 809 entry_type = soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, ENTRY_TYPEf); 810 } 811 /* only TD3 can have no underlay sd_tag. For TD2+, SRC MAC will not be modified */ 812 if (SOC_IS_TRIDENT3X(unit) && (entry_type == BCMI_L3_EGR_NH_SD_TAG_ENTRY_TYPE)) { 813 /* check if sdtag egr nh has some tag actions */ 814 action_present = 815 soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, 816 SD_TAG__SD_TAG_ACTION_IF_PRESENTf); 817 action_not_present = 818 soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, 819 SD_TAG__SD_TAG_ACTION_IF_NOT_PRESENTf); 820 vntag_actions = 821 soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, 822 SD_TAG__VNTAG_ACTIONSf); 823 824 if (vntag_actions || action_present || action_not_present) { 825 /* 826 * this next hop can do some modifications and therefore 827 * we should set nh-nh association for this NH. 828 */ 829 return 1; 830 } else { 831 return 0; 832 } 833 } 834 #endif 835 return 1; 836 } 837 838 /* 839 * Function: 840 * bcmi_l3_nh_assoc_ol_ul_link_reinit 841 * Purpose: 842 * re-initializes overlay/underlay association. 843 * Parameters: 844 * unit - unit number 845 * ol_nh - overlay nh number 846 * ul_nh - underlay nh number 847 * Returns: 848 * BCM_ERROR_T 849 */ 850 int 851 bcmi_l3_nh_assoc_ol_ul_link_reinit(int unit, int ol_nh_idx) 852 { 853 int entry_type, next_ptr_type, ul_nh_idx; 854 egr_l3_next_hop_entry_t egr_nh; 855 856 if (!(BCMI_RIOT_IS_ENABLED(unit))) { 857 return BCM_E_NONE; 858 } 859 860 BCM_IF_ERROR_RETURN 861 (READ_EGR_L3_NEXT_HOPm(unit, MEM_BLOCK_ANY, ol_nh_idx, &egr_nh)); 862 863 if (soc_feature(unit, soc_feature_mem_access_data_type)) { 864 entry_type = soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, DATA_TYPEf); 865 } else { 866 entry_type = soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, ENTRY_TYPEf); 867 } 868 869 if (entry_type == BCMI_L3_EGR_NH_MCAST_ENTRY_TYPE) { 870 next_ptr_type = soc_EGR_L3_NEXT_HOPm_field32_get(unit, 871 &egr_nh, L3MC__NEXT_PTR_TYPEf); 872 if (next_ptr_type == BCMI_L3_NH_EGR_NEXT_PTR_TYPE_NH) { 873 874 ul_nh_idx = soc_EGR_L3_NEXT_HOPm_field32_get(unit, 875 &egr_nh, L3MC__NEXT_PTRf); 876 877 BCM_IF_ERROR_RETURN( 878 bcmi_l3_nh_assoc_ol_ul_link_sw_add(unit, ol_nh_idx, 879 ul_nh_idx)); 880 } 881 } 882 return BCM_E_NONE; 883 } 884 885 /* 886 * Function: 887 * bcmi_nh_destination_set 888 * Purpose: 889 * Encode the dstination value based on the gport. 890 * Parameters: 891 * unit - SOC device unit number 892 * Returns: 893 * BCM_E_NONE Success 894 * BCM_E_XXX ERROR 895 */ 896 897 int bcmi_l3_nh_dest_set(int unit, bcm_l3_egress_t *nh_entry, uint32 *nh_dest) 898 { 899 int gport_type = 0, port = -1, gport = -1; 900 int mc_group = 0; 901 902 if(nh_entry->flags2 & BCM_L3_FLAGS2_MC_GROUP){ 903 if (!_BCM_MULTICAST_IS_L3(nh_entry->mc_group)) { 904 return BCM_E_PARAM; 905 } 906 mc_group = _BCM_MULTICAST_ID_GET(nh_entry->mc_group); 907 *nh_dest = BCMI_L3_NH_DEST_IPMC_GET(mc_group); 908 return BCM_E_NONE; 909 } 910 911 gport = nh_entry->port; 912 gport_type = BCMI_GPORT_TYPE_GET(gport); 913 914 if (BCMI_RIOT_IS_ENABLED(unit)) { 915 916 switch(gport_type) { 917 case BCM_GPORT_VXLAN_PORT: 918 port = BCM_GPORT_VXLAN_PORT_ID_GET(gport); 919 *nh_dest = BCMI_L3_NH_DEST_DVP_GET(port); 920 break; 921 case BCM_GPORT_L2GRE_PORT: 922 port = BCM_GPORT_L2GRE_PORT_ID_GET(gport); 923 *nh_dest = BCMI_L3_NH_DEST_DVP_GET(port); 924 break; 925 case BCM_GPORT_MPLS_PORT: 926 port = BCM_GPORT_MPLS_PORT_ID_GET(gport); 927 *nh_dest = BCMI_L3_NH_DEST_DVP_GET(port); 928 break; 929 case BCM_GPORT_MIM_PORT: 930 port = BCM_GPORT_MIM_PORT_ID_GET(gport); 931 *nh_dest = BCMI_L3_NH_DEST_DVP_GET(port); 932 break; 933 default: 934 if (nh_entry->flags & BCM_L3_TGID) { 935 int tid_is_vp_lag = 0; 936 if (soc_feature(unit, soc_feature_vp_lag)) { 937 (void)_bcm_esw_trunk_id_is_vp_lag(unit, gport, &tid_is_vp_lag); 938 } 939 940 if (tid_is_vp_lag) { 941 int vp_lag_vp; 942 /* Get the VP value representing VP LAG */ 943 BCM_IF_ERROR_RETURN(_bcm_esw_trunk_tid_to_vp_lag_vp(unit, 944 gport, &vp_lag_vp)); 945 946 *nh_dest = BCMI_L3_NH_DEST_DVP_GET(vp_lag_vp); 947 } else { 948 *nh_dest = BCMI_L3_NH_DEST_LAG_GET(nh_entry->port); 949 } 950 } else { 951 *nh_dest = BCMI_L3_NH_DEST_DGLP_GET 952 (BCM_L3_DGLP_GET(nh_entry->module, nh_entry->port)); 953 } 954 } 955 } else { 956 if (nh_entry->flags & BCM_L3_TGID) { 957 *nh_dest = BCMI_L3_NH_DEST_LAG_GET(nh_entry->port); 958 } else { 959 *nh_dest = BCMI_L3_NH_DEST_DGLP_GET 960 (BCM_L3_DGLP_GET(nh_entry->module, nh_entry->port)); 961 } 962 #if defined(BCM_MONTEREY_SUPPORT) 963 if (soc_feature(unit, soc_feature_xflow_macsec) && 964 ((nh_entry->flags2 & BCM_L3_FLAGS2_XFLOW_MACSEC_ENCRYPT) || 965 (nh_entry->flags2 & BCM_L3_FLAGS2_XFLOW_MACSEC_DECRYPT))) { 966 int local_modid; 967 BCM_IF_ERROR_RETURN 968 (bcm_esw_stk_my_modid_get (unit, &local_modid)); 969 *nh_dest = BCMI_L3_NH_DEST_DGLP_GET 970 (BCM_L3_DGLP_GET(local_modid, 66)); 971 } 972 #endif 973 } 974 return BCM_E_NONE; 975 } 976 977 /* 978 * Function: 979 * bcmi_get_gport_from_destination 980 * Purpose: 981 * Encode the dstination value based on the gport. 982 * Parameters: 983 * unit - SOC device unit number 984 * Returns: 985 * BCM_E_NONE Success 986 * BCM_E_XXX ERROR 987 */ 988 int bcmi_get_port_from_destination(int unit, uint32 dest, 989 bcm_l3_egress_t *nh) 990 { 991 int vp; 992 993 if (BCMI_L3_NH_DEST_IS_LAG(dest)) { 994 nh->port = BCMI_L3_NH_PORT_LAG_GET(dest); 995 nh->flags |= BCM_L3_TGID; 996 } else if (BCMI_L3_NH_DEST_IS_DGLP(dest)) { 997 nh->port = BCMI_L3_NH_PORT_DGLP_GET(dest); 998 } else if (BCMI_L3_NH_DEST_IS_DVP(dest)) { 999 vp = BCMI_L3_NH_PORT_DVP_GET(dest); 1000 _bcm_vp_encode_gport(unit, vp, &(nh->port)); 1001 } else if (BCMI_L3_NH_DEST_IS_IPMC(dest)) { 1002 _BCM_MULTICAST_GROUP_SET(nh->mc_group, _BCM_MULTICAST_TYPE_L3, 1003 BCMI_L3_NH_PORT_IPMC_GET(dest)); 1004 nh->flags2 |= BCM_L3_FLAGS2_MC_GROUP; 1005 } else { 1006 nh->port = dest; 1007 } 1008 1009 return BCM_E_NONE; 1010 1011 } 1012 1013 static soc_profile_mem_t *_bcm_td2p_macda_oui_profile[BCM_MAX_NUM_UNITS] = {NULL}; 1014 1015 /* 1016 * Function: 1017 * _bcm_td2p_macda_oui_profile_init 1018 * Purpose: 1019 * Allocate and initialize _bcm_td2p_macda_oui_profile_init 1020 * Parameters: 1021 * unit - (IN)SOC unit number. 1022 * Returns: 1023 * BCM_X_XXX 1024 */ 1025 bcm_error_t 1026 _bcm_td2p_macda_oui_profile_init(int unit) 1027 { 1028 soc_mem_t mem_profile; 1029 int entry_words[1]; 1030 1031 _bcm_td2p_macda_oui_profile_deinit(unit); 1032 1033 /* Create profile for MACDA_OUI_PROFILE table*/ 1034 _bcm_td2p_macda_oui_profile[unit] = sal_alloc(sizeof(soc_profile_mem_t), 1035 "MACDA OUI Profile Mem"); 1036 if (_bcm_td2p_macda_oui_profile[unit] == NULL) { 1037 return BCM_E_MEMORY; 1038 } 1039 soc_profile_mem_t_init(_bcm_td2p_macda_oui_profile[unit]); 1040 mem_profile = EGR_MACDA_OUI_PROFILEm; 1041 entry_words[0] = BYTES2WORDS(sizeof(egr_macda_oui_profile_entry_t)); 1042 SOC_IF_ERROR_RETURN 1043 (soc_profile_mem_create(unit, &mem_profile, entry_words, 1, 1044 _bcm_td2p_macda_oui_profile[unit])); 1045 1046 return BCM_E_NONE; 1047 } 1048 1049 1050 /* 1051 * Function: 1052 * _bcm_td2p_macda_oui_profile_deinit 1053 * Purpose: 1054 * Deallocate _bcm_td2p_macda_oui_profile 1055 * Parameters: 1056 * unit - (IN)SOC unit number. 1057 * Returns: 1058 * BCM_X_XXX 1059 */ 1060 void 1061 _bcm_td2p_macda_oui_profile_deinit(int unit) 1062 { 1063 if (_bcm_td2p_macda_oui_profile[unit]) { 1064 (void)soc_profile_mem_destroy(unit, _bcm_td2p_macda_oui_profile[unit]); 1065 sal_free(_bcm_td2p_macda_oui_profile[unit]); 1066 _bcm_td2p_macda_oui_profile[unit] = NULL; 1067 } 1068 } 1069 1070 /* 1071 * Function: 1072 * _bcm_td2p_l3_macda_oui_profile_entry_del 1073 * Purpose: 1074 * Delete entry from profile table 1075 * Parameters: 1076 * unit - (IN) SOC unit number. 1077 * ipv6 - (IN) IPV4 or IPv6 flag 1078 * l3cfg - (IN) L3 entry info. 1079 * bufentry - (IN) hw buffer 1080 * Returns: 1081 */ 1082 bcm_error_t 1083 _bcm_td2p_l3_macda_oui_profile_entry_del(int unit, _bcm_l3_cfg_t *l3cfg, 1084 int macda_oui_profile_index) 1085 { 1086 /* delete an entry or decrement ref count from EGR_MACDA_OUI_PROFILE table */ 1087 if (macda_oui_profile_index != -1) { 1088 SOC_IF_ERROR_RETURN(soc_profile_mem_delete(unit, _bcm_td2p_macda_oui_profile[unit], 1089 macda_oui_profile_index)); 1090 } 1091 return SOC_E_NONE; 1092 } 1093 1094 /* 1095 * Function: 1096 * _bcm_td2p_l3_macda_oui_profile_entry_parse 1097 * Purpose: 1098 * TD2P helper routine used to parse hw l3 entry to api format 1099 * Parameters: 1100 * unit - (IN) SOC unit number. 1101 * mem - (IN) L3 table memory. 1102 * l3cfg - (IN) L3 entry info. 1103 * l3x_entry - (IN) hw buffer. 1104 * Returns: 1105 */ 1106 bcm_error_t 1107 _bcm_td2p_l3_macda_oui_profile_entry_parse(int unit, soc_mem_t mem, 1108 _bcm_l3_cfg_t *l3cfg, void *l3x_entry) 1109 { 1110 uint32 profile_index; 1111 uint32 mac_field; 1112 int rv = BCM_E_NONE; 1113 int ipv6; /* Entry is IPv6 flag. */ 1114 _bcm_l3_fields_t *fld; /* L3 table common fields. */ 1115 uint32 *buf_p; /* HW buffer address. */ 1116 egr_macda_oui_profile_entry_t macda_oui_profile_entry; 1117 1118 ipv6 = (l3cfg->l3c_flags & BCM_L3_IP6); 1119 buf_p = (uint32 *)l3x_entry; 1120 1121 /* Set table fields */ 1122 BCM_TD2_L3_HOST_TABLE_FLD(unit, mem, ipv6, fld); 1123 soc_mem_mac_address_get(unit, mem, buf_p, fld->macda_lsb, 1124 l3cfg->l3c_mac_addr, 1125 SOC_MEM_MAC_LOWER_ONLY); 1126 /* Read upper 3 bytes of MAC address from profile table */ 1127 profile_index = soc_mem_field32_get(unit, mem, buf_p, 1128 fld->oui_profile_index); 1129 SOC_IF_ERROR_RETURN 1130 (READ_EGR_MACDA_OUI_PROFILEm(unit, MEM_BLOCK_ANY, profile_index, 1131 &macda_oui_profile_entry)); 1132 soc_EGR_MACDA_OUI_PROFILEm_field_get(unit, &macda_oui_profile_entry, 1133 MACDA_OUIf, &mac_field); 1134 l3cfg->l3c_mac_addr[0] = (uint8) (mac_field >> 16 & 0xff); 1135 l3cfg->l3c_mac_addr[1] = (uint8) (mac_field >> 8 & 0xff); 1136 l3cfg->l3c_mac_addr[2] = (uint8) (mac_field & 0xff); 1137 1138 return rv; 1139 } 1140 1141 1142 /* 1143 * Function: 1144 * _bcm_td2p_l3_macda_oui_profile_entry_add 1145 * Purpose: 1146 * TD2P helper routine used to set some fields in hw l3 entry 1147 * Parameters: 1148 * unit - (IN) SOC unit number. 1149 * mem - (IN) L3 table memory. 1150 * l3cfg - (IN) L3 entry info. 1151 * buf_p - (IN) hw buffer. 1152 * Returns: 1153 * BCM_X_XXX 1154 */ 1155 bcm_error_t 1156 _bcm_td2p_l3_macda_oui_profile_entry_add(int unit, soc_mem_t mem, _bcm_l3_cfg_t *l3cfg, 1157 uint32 *buf_p, int *macda_oui_profile_index) 1158 { 1159 int rv = BCM_E_NONE; 1160 int ipv6; /* Entry is IPv6 flag. */ 1161 _bcm_l3_fields_t *fld; /* L3 table common fields. */ 1162 uint32 *bufp; /* HW buffer address. */ 1163 uint32 profile_idx; 1164 uint32 mac_oui; 1165 void *entries[1]; 1166 egr_macda_oui_profile_entry_t macda_oui_profile_entry; 1167 1168 ipv6 = (l3cfg->l3c_flags & BCM_L3_IP6); 1169 /* Set table fields */ 1170 BCM_TD2_L3_HOST_TABLE_FLD(unit, mem, ipv6, fld); 1171 bufp = buf_p; 1172 1173 /* Set MACDA_OUI_PROFILE_VALID to 1 */ 1174 soc_mem_field32_set(unit, mem, bufp, fld->oui_profile_valid, 1); 1175 1176 /* Set the MACDA_LSB field */ 1177 soc_mem_mac_address_set(unit, mem, bufp, fld->macda_lsb, 1178 l3cfg->l3c_mac_addr, 1179 SOC_MEM_MAC_LOWER_ONLY); 1180 /* Setup EGR_MACDA_OUI_PROFILE table with MACDA_OUI */ 1181 mac_oui = ((l3cfg->l3c_mac_addr[0] << 16) | 1182 (l3cfg->l3c_mac_addr[1] << 8) | 1183 (l3cfg->l3c_mac_addr[2] << 0)); 1184 sal_memset(&macda_oui_profile_entry, 0, sizeof(macda_oui_profile_entry)); 1185 soc_EGR_MACDA_OUI_PROFILEm_field_set(unit, &macda_oui_profile_entry, 1186 MACDA_OUIf, &mac_oui); 1187 entries[0] = &macda_oui_profile_entry; 1188 rv = soc_profile_mem_add(unit, _bcm_td2p_macda_oui_profile[unit], 1189 entries, 1, &profile_idx); 1190 1191 *macda_oui_profile_index = profile_idx; 1192 /* Set the MACDA_OUI_PROFILE_INDEX field */ 1193 soc_mem_field32_set(unit, mem, bufp, fld->oui_profile_index, profile_idx); 1194 1195 return rv; 1196 } 1197 /* 1198 * Function: 1199 * _bcm_td2p_l3_macda_oui_profile_entry_replace 1200 * Purpose: 1201 * TD2P helper routine used to replace hw L3 entry 1202 * Parameters: 1203 * unit - (IN) SOC unit number. 1204 * mem - (IN) L3 table memory. 1205 * l3cfg - (IN) L3 entry info. 1206 * buf_p - (IN) hw buffer. 1207 * Returns: 1208 * BCM_X_XXX 1209 */ 1210 bcm_error_t 1211 _bcm_td2p_l3_macda_oui_profile_entry_replace(int unit, soc_mem_t mem, 1212 _bcm_l3_cfg_t *l3cfg, uint32 *bufp) 1213 { 1214 /* For BCM_L3_REPLACE, get profile index for EGR_MACDA_OUI_PROFILE table. 1215 * Delete the profile entry if it's not used by any other host. 1216 */ 1217 int macda_oui_profile_index = -1; 1218 int macda_oui_profile_index_new = -1; 1219 int ref_count = 0; 1220 int rv = BCM_E_NONE; 1221 rv = _bcm_td2p_l3_get_macda_oui_profile_index(unit, mem, l3cfg, 1222 &macda_oui_profile_index, 1223 &ref_count); 1224 if (BCM_FAILURE(rv) && (rv != BCM_E_NOT_FOUND)) { 1225 return rv; 1226 } 1227 if (macda_oui_profile_index == -1) { 1228 /* Host entry was done in regular L3_ENTRY table view, add it to extended view */ 1229 BCM_IF_ERROR_RETURN 1230 (_bcm_td2p_l3_macda_oui_profile_entry_add(unit, mem, l3cfg, bufp, 1231 &macda_oui_profile_index_new)); 1232 } else { 1233 /* Add new entry, ref_count is automatically incremented */ 1234 rv = _bcm_td2p_l3_macda_oui_profile_entry_add(unit, mem, l3cfg, bufp, 1235 &macda_oui_profile_index_new); 1236 if (BCM_SUCCESS(rv)) { 1237 /* Delete old entry from profile table */ 1238 BCM_IF_ERROR_RETURN 1239 (_bcm_td2p_l3_macda_oui_profile_entry_del(unit, l3cfg, 1240 macda_oui_profile_index)); 1241 } else { 1242 return rv; 1243 } 1244 } 1245 return rv; 1246 } 1247 1248 /* 1249 * Function: 1250 * _bcm_td2p_l3_get_macda_oui_profile_index 1251 * Purpose: 1252 * TD2P helper routine used to get profile index for EGR_MACDA_OUI_PROFILE 1253 * Parameters: 1254 * unit - (IN) SOC unit number. 1255 * mem - (IN) L3 Extended table memory. 1256 * l3cfg - (IN) L3 entry info. 1257 * macda_oui_profile_index - (out) EGR_MACDA_OUI profile index. 1258 * Returns: 1259 * BCM_X_XXX 1260 */ 1261 bcm_error_t 1262 _bcm_td2p_l3_get_macda_oui_profile_index(int unit, soc_mem_t mem_ext, _bcm_l3_cfg_t *l3cfg, 1263 int *macda_oui_profile_index, int *ref_count) 1264 { 1265 int ipv6; /* IPv6 entry indicator.*/ 1266 int rv = BCM_E_NONE; /* Operation return status. */ 1267 uint32 *buf_key, *buf_entry; /* Key and entry buffer ptrs*/ 1268 l3_entry_ipv4_unicast_entry_t l3v4_key, l3v4_entry; /* IPv4 */ 1269 l3_entry_ipv4_multicast_entry_t l3v4_ext_key, l3v4_ext_entry; /* IPv4-Embedded */ 1270 l3_entry_ipv6_unicast_entry_t l3v6_key, l3v6_entry; /* IPv6 */ 1271 l3_entry_ipv6_multicast_entry_t l3v6_ext_key, l3v6_ext_entry; /* IPv6-Embedded */ 1272 soc_field_t macda_oui_index, macda_oui_valid; 1273 uint32 macda_oui_profile_valid = 0; 1274 soc_mem_t mem; 1275 1276 /* Get entry type. */ 1277 ipv6 = (l3cfg->l3c_flags & BCM_L3_IP6); 1278 1279 if (ipv6) { 1280 macda_oui_index = IPV6UC_EXT__MACDA_OUI_PROFILE_INDEXf; 1281 macda_oui_valid = IPV6UC_EXT__MACDA_OUI_PROFILE_VALIDf; 1282 mem = BCM_XGS3_L3_MEM(unit, v6); 1283 } else { 1284 macda_oui_index = IPV4UC_EXT__MACDA_OUI_PROFILE_INDEXf; 1285 macda_oui_valid = IPV4UC_EXT__MACDA_OUI_PROFILE_VALIDf; 1286 mem = BCM_XGS3_L3_MEM(unit, v4); 1287 } 1288 1289 /* Assign entry-key buf based on table being used */ 1290 BCM_TD2_L3_HOST_ENTRY_BUF(ipv6, mem_ext, buf_key, 1291 l3v4_key, 1292 l3v4_ext_key, 1293 l3v6_key, 1294 l3v6_ext_key); 1295 1296 /* Assign entry buf based on table being used */ 1297 BCM_TD2_L3_HOST_ENTRY_BUF(ipv6, mem_ext, buf_entry, 1298 l3v4_entry, 1299 l3v4_ext_entry, 1300 l3v6_entry, 1301 l3v6_ext_entry); 1302 /* Prepare lookup key. */ 1303 BCM_IF_ERROR_RETURN 1304 (_bcm_td2_l3_ent_init(unit, mem_ext, l3cfg, buf_key)); 1305 1306 /* Perform lookup hw. to get full entry in ext-view */ 1307 rv = soc_mem_generic_lookup(unit, mem_ext, MEM_BLOCK_ANY, 1308 _BCM_TD2_L3_MEM_BANKS_ALL, 1309 buf_key, buf_entry, &l3cfg->l3c_hw_index); 1310 if (SOC_SUCCESS(rv)) { 1311 /* If entry found, get value of MACDA_OUI_PROFILE_VALIDf */ 1312 macda_oui_profile_valid = soc_mem_field32_get(unit, mem_ext, buf_entry, 1313 macda_oui_valid); 1314 if (macda_oui_profile_valid) { 1315 /* Only if MACDA_OUI_PROFILE_VALIDf is set */ 1316 *macda_oui_profile_index = soc_mem_field32_get(unit, mem_ext, buf_entry, 1317 macda_oui_index); 1318 rv = soc_profile_mem_ref_count_get(unit, 1319 _bcm_td2p_macda_oui_profile[unit], 1320 *macda_oui_profile_index, 1321 ref_count); 1322 } 1323 } else if (rv == SOC_E_NOT_FOUND) { 1324 /* Check if entry was added in regular L3_ENTRY table view */ 1325 1326 /* Assign entry-key buf based on table being used */ 1327 BCM_TD2_L3_HOST_ENTRY_BUF(ipv6, mem, buf_key, 1328 l3v4_key, 1329 l3v4_ext_key, 1330 l3v6_key, 1331 l3v6_ext_key); 1332 1333 /* Assign entry buf based on table being used */ 1334 BCM_TD2_L3_HOST_ENTRY_BUF(ipv6, mem, buf_entry, 1335 l3v4_entry, 1336 l3v4_ext_entry, 1337 l3v6_entry, 1338 l3v6_ext_entry); 1339 /* Prepare lookup key. */ 1340 BCM_IF_ERROR_RETURN(_bcm_td2_l3_ent_init(unit, mem, l3cfg, buf_key)); 1341 1342 /* Perform lookup */ 1343 rv = soc_mem_generic_lookup(unit, mem, MEM_BLOCK_ANY, 1344 _BCM_TD2_L3_MEM_BANKS_ALL, 1345 buf_key, buf_entry, &l3cfg->l3c_hw_index); 1346 } 1347 1348 return rv; 1349 } 1350 1351 /* 1352 * Function: 1353 * bcm_td2p_l3_extended_required_scache_size_get 1354 * Purpose: 1355 * Get required MACDA_OUI_PROFILE scache size for Level 2 Warm Boot in TD2P 1356 * L3_ENTRY extended view 1357 * Parameters: 1358 * unit - StrataSwitch unit number. 1359 * size - (OUT) Required scache size. 1360 */ 1361 void 1362 bcm_td2p_l3_extended_required_scache_size_get(int unit, int *size) 1363 { 1364 /* Sync the ref_count of EGR_MACDA_OUI_PROFILEm */ 1365 *size += SOC_MEM_SIZE(unit, EGR_MACDA_OUI_PROFILEm) * sizeof(uint32); 1366 } 1367 1368 /* 1369 * Function: 1370 * bcm_td2p_l3_extended_view_sync 1371 * Purpose: 1372 * Record persistent info into the scache for the MACDA_OUI_PROFILE 1373 * for L3_ENTRY extended view. 1374 * Parameters: 1375 * unit - StrataSwitch unit # 1376 * scache_ptr - (IN/OUT) Scache pointer 1377 * Returns: 1378 * BCM_E_xxx 1379 */ 1380 bcm_error_t 1381 bcm_td2p_l3_extended_view_sync(int unit, uint8 **scache_ptr) 1382 { 1383 int rv = BCM_E_NONE; 1384 int i; 1385 int ref_count; 1386 1387 if ((scache_ptr == NULL) || (*scache_ptr == NULL)) { 1388 return BCM_E_PARAM; 1389 } 1390 1391 /* Record EGR_MACDA_OUI_PROFILEm ref_count in scache */ 1392 for (i = 0; i < SOC_MEM_SIZE(unit, EGR_MACDA_OUI_PROFILEm); i++) { 1393 rv = soc_profile_mem_ref_count_get(unit, 1394 _bcm_td2p_macda_oui_profile[unit], 1395 i, 1396 &ref_count); 1397 if (!(rv == SOC_E_NONE)) { 1398 return rv; 1399 } 1400 1401 sal_memcpy((*scache_ptr), &ref_count, sizeof(uint32)); 1402 (*scache_ptr) += sizeof(ref_count); 1403 } 1404 1405 return rv; 1406 } 1407 1408 /* 1409 * Function: 1410 * bcm_td2p_l3_extended_view_reinit 1411 * Purpose: 1412 * Warm boot recovery for the MACDA_OUI_PROFILE 1413 * extended view 1414 * Parameters: 1415 * unit - Device Number 1416 * defaul_ver - Warm boot default version 1417 * Returns: 1418 * BCM_E_XXX 1419 */ 1420 bcm_error_t 1421 bcm_td2p_l3_extended_view_reinit(int unit, uint8 **scache_ptr) 1422 { 1423 int rv = BCM_E_NONE; 1424 soc_profile_mem_t *profile_mem; 1425 int i, j, size; 1426 uint32 ref_count; 1427 1428 if ((scache_ptr == NULL) || (*scache_ptr == NULL)) { 1429 return BCM_E_PARAM; 1430 } 1431 1432 /* Update EGR_MACDA_OUI_PROFILE memory profile reference counter */ 1433 profile_mem = _bcm_td2p_macda_oui_profile[unit]; 1434 size = SOC_MEM_SIZE(unit, EGR_MACDA_OUI_PROFILEm); 1435 for (i = 0; i < size; i++) { 1436 sal_memcpy(&ref_count, (*scache_ptr), sizeof(uint32)); 1437 (*scache_ptr) += sizeof(ref_count); 1438 for (j = 0; j < ref_count; j++) { 1439 SOC_IF_ERROR_RETURN( 1440 soc_profile_mem_reference(unit, profile_mem, i, 1)); 1441 } 1442 } 1443 return rv; 1444 } 1445 #endif /* BCM_RIOT_SUPPORT */ 1446 1447 /* 1448 * Function: 1449 * bcm_td2p_l3_tables_init 1450 * Purpose: 1451 * Initialize internal L3 tables and enable L3. 1452 * TD2P has configurable multi domain banks for 1453 * various l3 objects. This routine sets up h/w 1454 * tables for corresponding objects and then calls 1455 * common tables init routine. 1456 * Parameters: 1457 * unit - SOC unit number. 1458 * Returns: 1459 * BCM_E_XXX. 1460 */ 1461 int 1462 bcm_td2p_l3_tables_init(int unit) 1463 { 1464 1465 #ifdef BCM_TRIDENT3_SUPPORT 1466 _bcm_l3_bookkeeping_t *l3 = L3_BK_INFO(unit); 1467 #endif 1468 #ifdef BCM_RIOT_SUPPORT 1469 /* Selects L3 banks based on user inputs */ 1470 BCM_IF_ERROR_RETURN(bcmi_l3_riot_bank_sel(unit)); 1471 #endif 1472 #if defined(BCM_RIOT_SUPPORT) || defined(BCM_MULTI_LEVEL_ECMP_SUPPORT) 1473 if ((!SOC_IS_TRIDENT3X(unit)) 1474 #ifdef BCM_TRIDENT3_SUPPORT 1475 || ((l3->l3_ecmp_group_first_lkup_mem_size == 0) 1476 && (l3->l3_ecmp_member_first_lkup_mem_size == 0)) 1477 #endif 1478 ) { 1479 #if defined(BCM_RIOT_SUPPORT) 1480 /* Non-default ecmp partitions not configured */ 1481 /* selects ecmp level */ 1482 BCM_IF_ERROR_RETURN(bcmi_l3_riot_ecmp_level_sel(unit)); 1483 #endif 1484 } 1485 #endif 1486 BCM_IF_ERROR_RETURN(bcm_xgs3_l3_tables_init(unit)); 1487 1488 return BCM_E_NONE; 1489 } 1490 #endif /* INCLUDE_L3 */