l3.c (56999B)
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: Trident 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_TRIDENT_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 #include <bcm_int/esw/trx.h> 38 #include <bcm_int/esw/trident.h> 39 #if defined(BCM_TRIUMPH2_SUPPORT) 40 #include <bcm_int/esw/triumph2.h> 41 #endif /* BCM_TRIUMPH2_SUPPORT */ 42 #if defined(BCM_TOMAHAWK_SUPPORT) 43 #include <bcm_int/esw/tomahawk.h> 44 #endif /* BCM_TOMAHAWK_SUPPORT */ 45 #if defined(BCM_TRIDENT3_SUPPORT) 46 #include <bcm_int/esw/trident3.h> 47 #endif /* BCM_TOMAHAWK_SUPPORT */ 48 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 49 #include <bcm_int/esw/trident2plus.h> 50 #endif /* BCM_TRIDENT2PLUS_SUPPORT */ 51 #include <bcm_int/esw/l3.h> 52 #include <bcm_int/esw/xgs3.h> 53 54 #include <bcm_int/esw_dispatch.h> 55 56 extern int ecmp_mode_hierarchical; 57 extern int ecmp_mode_single; 58 59 /* 60 * Function: 61 * _bcm_td_l3_ecmp_grp_get 62 * Purpose: 63 * Get ecmp group next hop members by index. 64 * Parameters: 65 * unit - (IN)SOC unit number. 66 * ecmp_grp - (IN)Ecmp group id to read. 67 * ecmp_count - (IN)Maximum number of entries to read. 68 * nh_idx - (OUT)Next hop indexes. 69 * Returns: 70 * BCM_E_XXX 71 */ 72 int 73 _bcm_td_l3_ecmp_grp_get (int unit, int ecmp_grp, int ecmp_group_size, int *nh_idx) 74 { 75 int idx; /* Iteration index. */ 76 int max_ent_count=0; /* Number of entries to read.*/ 77 uint32 hw_buf[SOC_MAX_MEM_FIELD_WORDS]; /* Buffer to read hw entry. */ 78 int one_entry_grp = TRUE; /* Single next hop entry group. */ 79 int rv = BCM_E_UNAVAIL; /* Operation return status. */ 80 int ecmp_idx = 0; 81 char *l3_ecmp_tbl_ptr; /* Dma L3 ECMP table pointer. */ 82 uint32 *ecmp_entry_ptr = NULL; /* ECMP entry pointer.*/ 83 uint32 dest_type = SOC_MEM_FIF_DEST_INVALID; 84 85 /* Input parameters sanity check. */ 86 if ((NULL == nh_idx) || (ecmp_group_size < 1)) { 87 return (BCM_E_PARAM); 88 } 89 90 91 /* Zero all next hop indexes first. */ 92 sal_memset(nh_idx, 0, ecmp_group_size * sizeof(int)); 93 sal_memset(hw_buf, 0, SOC_MAX_MEM_FIELD_WORDS * sizeof(uint32)); 94 95 /* Calculate Base_ptr table index. */ 96 if (SOC_MEM_IS_VALID(unit, L3_ECMP_COUNTm)) { 97 BCM_IF_ERROR_RETURN( 98 _bcm_xgs3_l3_ecmp_grp_info_get(unit, ecmp_grp, 99 &max_ent_count, &ecmp_idx)); 100 101 } 102 103 if (max_ent_count > L3_ECMP_MEM_DMA_THRESHOLD) { 104 rv = bcm_xgs3_l3_tbl_range_dma(unit, L3_ECMPm, sizeof(ecmp_entry_t), 105 "l3_ecmp_tbl", ecmp_idx, 106 ecmp_idx + max_ent_count - 1, 107 &l3_ecmp_tbl_ptr); 108 BCM_IF_ERROR_RETURN(rv); 109 } 110 111 /* Read all the indexes from hw. */ 112 for (idx = 0; idx < max_ent_count; idx++) { 113 114 /* Read next hop index. */ 115 if (max_ent_count > L3_ECMP_MEM_DMA_THRESHOLD) { 116 ecmp_entry_ptr = 117 soc_mem_table_idx_to_pointer(unit, L3_ECMPm, uint32 *, 118 l3_ecmp_tbl_ptr, idx); 119 } else { 120 rv = soc_mem_read(unit, L3_ECMPm, MEM_BLOCK_ANY, 121 (ecmp_idx + idx), hw_buf); 122 if (rv < 0) { 123 break; 124 } 125 ecmp_entry_ptr = hw_buf; 126 } 127 if (SOC_IS_TRIDENT3X(unit)) { 128 nh_idx[idx] = soc_mem_field32_dest_get(unit, L3_ECMPm, ecmp_entry_ptr, 129 DESTINATIONf, &dest_type); 130 } else { 131 nh_idx[idx] = soc_mem_field32_get(unit, L3_ECMPm, 132 ecmp_entry_ptr, NEXT_HOP_INDEXf); 133 } 134 #ifdef BCM_TOMAHAWK_SUPPORT 135 /* Calculate the multipath intf index if ecmp member is a group id */ 136 if (soc_feature(unit, soc_feature_hierarchical_ecmp)) { 137 /* Read ecmp flag and check if NH index is a group id */ 138 if (SOC_IS_TRIDENT3X(unit)) { 139 if (dest_type == SOC_MEM_FIF_DEST_ECMP) { 140 nh_idx[idx] += BCM_XGS3_MPATH_EGRESS_IDX_MIN(unit); 141 } 142 } else if (soc_feature(unit, soc_feature_l3_ecmp_hier_tbl)) { 143 if (BCM_XGS3_L3_TBL(unit, ecmp_info).ecmp_mode == 144 ecmp_mode_hierarchical) { 145 if ((nh_idx[idx]) && 146 (ecmp_idx < (BCM_XGS3_L3_ECMP_TBL_SIZE(unit) / 2))) { 147 nh_idx[idx] += BCM_XGS3_MPATH_EGRESS_IDX_MIN(unit); 148 } 149 } 150 } else if (soc_mem_field32_get(unit, L3_ECMPm, 151 ecmp_entry_ptr, ECMP_FLAGf)) { 152 nh_idx[idx] += BCM_XGS3_MPATH_EGRESS_IDX_MIN(unit); 153 } 154 } 155 #endif /* BCM_TOMAHAWK_SUPPORT */ 156 157 #ifdef BCM_MULTI_LEVEL_ECMP_SUPPORT 158 /* Calculate the multipath intf index if ecmp member is a group id */ 159 if (soc_feature(unit, soc_feature_multi_level_ecmp)) { 160 /* Read ecmp flag and check if NH index is a group id */ 161 #ifdef BCM_TRIDENT3_SUPPORT 162 if (SOC_IS_TRIDENT3X(unit)) { 163 if (dest_type == SOC_MEM_FIF_DEST_ECMP) { 164 nh_idx[idx] += BCM_XGS3_MPATH_EGRESS_IDX_MIN(unit); 165 } 166 } else 167 #endif 168 if (soc_mem_field32_get(unit, L3_ECMPm, 169 ecmp_entry_ptr, ECMPf)) { 170 nh_idx[idx] += BCM_XGS3_MPATH_EGRESS_IDX_MIN(unit); 171 } 172 } 173 #endif /* BCM_MULTI_LEVEL_ECMP_SUPPORT */ 174 175 176 /* Check if group contains . */ 177 if (idx && (nh_idx[idx] != nh_idx[0])) { 178 one_entry_grp = FALSE; 179 } 180 181 if (0 == soc_feature(unit, soc_feature_l3_dynamic_ecmp_group)) { 182 /* Next hops popuplated in cycle,stop once you read first entry again */ 183 if (idx && (FALSE == one_entry_grp) && (nh_idx[idx] == nh_idx[0])) { 184 nh_idx[idx] = 0; 185 break; 186 } 187 } else { 188 one_entry_grp = FALSE; 189 } 190 } 191 /* Reset rest of the group if only 1 next hop is present. */ 192 if (one_entry_grp) { 193 sal_memset(nh_idx + 1, 0, (ecmp_group_size - 1) * sizeof(int)); 194 } 195 if (max_ent_count > L3_ECMP_MEM_DMA_THRESHOLD) { 196 soc_cm_sfree(unit, l3_ecmp_tbl_ptr); 197 } 198 return rv; 199 } 200 201 202 /* 203 * Function: 204 * _bcm_td_l3_ecmp_grp_add 205 * Purpose: 206 * Add ecmp group next hop members, or reset ecmp group entry. 207 * NOTE: Function always writes all the entries in ecmp group. 208 * If there is not enough nh indexes - next hops written 209 * in cycle. 210 * Parameters: 211 * unit - (IN)SOC unit number. 212 * ecmp_grp - (IN)ecmp group id to write. 213 * buf - (IN)Next hop indexes or NULL for entry reset. 214 * info - (IN)ECMP additional info 215 * Returns: 216 * BCM_E_XXX 217 */ 218 int 219 _bcm_td_l3_ecmp_grp_add (int unit, int ecmp_grp, void *buf, void *info) 220 { 221 uint32 l3_ecmp[SOC_MAX_MEM_FIELD_WORDS]; 222 uint32 initial_l3_ecmp[SOC_MAX_MEM_FIELD_WORDS]; 223 uint32 l3_ecmp_count[SOC_MAX_MEM_FIELD_WORDS]; 224 uint32 hw_buf[SOC_MAX_MEM_FIELD_WORDS]; 225 initial_l3_ecmp_group_entry_t initial_l3_ecmp_group_entry; 226 int max_grp_size = 0; /* Maximum ecmp group size.*/ 227 int ecmpf = 0; 228 int ecmp_idx; /* Ecmp table entry index. */ 229 int *nh_idx; /* Ecmp group nh indexes. */ 230 int nh_cycle_idx; 231 int idx = 0; /* Iteration index. */ 232 int rv = BCM_E_NONE; /* Operation return value. */ 233 int entry_type; 234 int max_subgrp_cnt, subgrp_cnt, intf_count = 0; 235 int l3_ecmp_oif_flds[8] = { L3_OIF_0f, 236 L3_OIF_1f, 237 L3_OIF_2f, 238 L3_OIF_3f, 239 L3_OIF_4f, 240 L3_OIF_5f, 241 L3_OIF_6f, 242 L3_OIF_7f }; 243 int l3_ecmp_oif_type_flds[8] = { L3_OIF_0_TYPEf, 244 L3_OIF_1_TYPEf, 245 L3_OIF_2_TYPEf, 246 L3_OIF_3_TYPEf, 247 L3_OIF_4_TYPEf, 248 L3_OIF_5_TYPEf, 249 L3_OIF_6_TYPEf, 250 L3_OIF_7_TYPEf }; 251 ing_l3_next_hop_entry_t ing_nh; 252 uint32 reg_val, value; 253 _bcm_l3_tbl_op_t data; 254 soc_mem_t grp_mem = L3_ECMP_COUNTm; 255 256 #ifdef BCM_TOMAHAWK_SUPPORT 257 soc_field_t _initial_l3_ecmp_flag = ECMP_FLAGf; 258 int defragment_direction = 0; 259 #endif 260 int ecmp_table_incr = 0; 261 _bcm_l3_ecmp_group_info_t *ecmp_info = info; 262 _bcm_l3_ecmp_group_buffer_t *ecmp_buffer = buf; 263 #if defined(BCM_TOMAHAWK2_SUPPORT) || defined(BCM_TRIDENT3_SUPPORT) 264 int dgm_zero_hit = 0; 265 #endif /* BCM_TOMAHAWK2_SUPPORT */ 266 267 char *l3_ecmp_tbl_ptr; /* Dma L3 ECMP table pointer. */ 268 uint32 *ecmp_entry_ptr = NULL; /* ECMP entry pointer.*/ 269 char *initial_l3_ecmp_tbl_ptr = NULL; /* Dma INITIAL L3 ECMP table pointer. */ 270 uint32 *initial_ecmp_entry_ptr = NULL; /* INITIAL ECMP entry pointer.*/ 271 void *ecmp_null_entry = NULL, *initial_ecmp_null_entry = NULL; 272 273 /* Input parameters check. */ 274 if (NULL == ecmp_buffer || NULL == ecmp_info || 275 NULL == ecmp_buffer->group_buffer) { 276 return (BCM_E_PARAM); 277 } 278 279 #ifdef BCM_TRIDENT3_SUPPORT 280 if (SOC_IS_TRIDENT3X(unit)) { 281 _initial_l3_ecmp_flag = ECMPf; 282 } 283 #endif 284 285 #ifdef BCM_TOMAHAWK3_SUPPORT 286 if ((soc_feature(unit, soc_feature_l3_ecmp_hier_tbl)) && 287 (ecmp_info->ecmp_flags & BCM_L3_ECMP_OVERLAY)) { 288 grp_mem = ECMP_GROUP_HIERARCHICALm; 289 } 290 #endif 291 /* Cast input buffer. */ 292 nh_idx = ecmp_buffer->group_buffer; 293 max_grp_size = ecmp_info->max_paths; 294 295 if (BCM_XGS3_L3_ENT_REF_CNT(BCM_XGS3_L3_TBL_PTR(unit, 296 ecmp_grp), ecmp_grp) 297 #ifdef BCM_TOMAHAWK3_SUPPORT 298 || ((soc_feature(unit, soc_feature_l3_ecmp_hier_tbl)) && 299 (ecmp_info->ecmp_flags & BCM_L3_ECMP_OVERLAY) && 300 BCM_XGS3_L3_ENT_REF_CNT(BCM_XGS3_L3_TBL_PTR(unit, 301 hecmp_grp), ecmp_grp)) 302 #endif 303 ) { 304 /* Group already exists, get base ptr from group table */ 305 BCM_IF_ERROR_RETURN( 306 _bcm_xgs3_l3_ecmp_grp_info_get(unit, ecmp_grp, NULL, &ecmp_idx)); 307 } else { 308 /* Get index to the first slot in the ECMP table 309 * that can accomodate max_grp_size */ 310 data.width = ecmp_info->max_paths; 311 data.tbl_ptr = BCM_XGS3_L3_TBL_PTR(unit, ecmp); 312 data.oper_flags = _BCM_L3_SHR_TABLE_TRAVERSE_CONTROL; 313 #if defined(BCM_RIOT_SUPPORT) || defined(BCM_MULTI_LEVEL_ECMP_SUPPORT) 314 /* 315 * we can look into the ecmp_grp index to know if this 316 * is overlay entry or underlay entry. 317 */ 318 if (BCMI_L3_ECMP_IS_MULTI_LEVEL(unit)) { 319 if (ecmp_grp < BCMI_L3_ECMP_OVERLAY_ENTRIES(unit)) { 320 321 data.oper_flags |= _BCM_L3_SHR_OVERLAY_OBJECT; 322 } 323 } 324 #endif 325 data.entry_index = -1; 326 rv = _bcm_xgs3_tbl_free_idx_get(unit, &data); 327 if (rv == BCM_E_FULL) { 328 /* Defragment ECMP table */ 329 #ifdef BCM_TOMAHAWK_SUPPORT 330 /* Pass ECMP level so the defragmentation can happen in the 331 right part of the ECMP table */ 332 if (soc_feature(unit, soc_feature_hierarchical_ecmp) && 333 (BCM_XGS3_L3_TBL(unit, ecmp_info).ecmp_mode == 334 ecmp_mode_hierarchical)) { 335 if (data.tbl_ptr->idx_min > 0) { 336 /* De-fragment Level 2 or Underlay ECMP table */ 337 BCM_IF_ERROR_RETURN(bcm_tr2_l3_ecmp_defragment_no_lock(unit, 2)); 338 /* Further De-fragment if possible */ 339 defragment_direction = 0; 340 } else if ((data.tbl_ptr->idx_min == 0) && 341 (data.tbl_ptr->idx_max < 342 soc_mem_index_max(unit,L3_ECMPm))) { 343 /* De-fragment Level 1 or Overlay ECMP table */ 344 BCM_IF_ERROR_RETURN(bcm_tr2_l3_ecmp_defragment_no_lock(unit, 1)); 345 /* Further De-fragment if possible */ 346 defragment_direction = 1; 347 } else { 348 /* 349 * The current entry can go in anywhere in the ECMP table. 350 * De-fragment the entire ECMP table 351 */ 352 BCM_IF_ERROR_RETURN(bcm_tr2_l3_ecmp_defragment_no_lock(unit, 2)); 353 BCM_IF_ERROR_RETURN(bcm_tr2_l3_ecmp_defragment_no_lock(unit, 1)); 354 /* Further De-fragment if possible */ 355 defragment_direction = 0; 356 } 357 } else 358 #endif /* BCM_TOMAHAWK_SUPPORT */ 359 #if defined(BCM_RIOT_SUPPORT) || defined(BCM_MULTI_LEVEL_ECMP_SUPPORT) 360 if (BCMI_L3_ECMP_IS_MULTI_LEVEL(unit)) { 361 if (data.oper_flags & _BCM_L3_SHR_OVERLAY_OBJECT) { 362 BCM_IF_ERROR_RETURN( 363 bcm_tr2_l3_ecmp_defragment_no_lock(unit, 2)); 364 } else { 365 BCM_IF_ERROR_RETURN( 366 bcm_tr2_l3_ecmp_defragment_no_lock(unit, 1)); 367 } 368 } else 369 #endif 370 { 371 BCM_IF_ERROR_RETURN(bcm_tr2_l3_ecmp_defragment_no_lock(unit, 0)); 372 } 373 /* Attempt to get free index again */ 374 rv = _bcm_xgs3_tbl_free_idx_get(unit, &data); 375 #ifdef BCM_TOMAHAWK_SUPPORT 376 if (soc_feature(unit, soc_feature_hierarchical_ecmp) && 377 (BCM_XGS3_L3_TBL(unit, ecmp_info).ecmp_mode == 378 ecmp_mode_hierarchical) && (rv == BCM_E_FULL)) { 379 /* 380 * Move the ECMP tables (which have flags 0) 381 * across two layers 382 */ 383 BCM_IF_ERROR_RETURN( 384 _bcm_th_l3_ecmp_across_layers_move(unit, max_grp_size, 385 defragment_direction)); 386 if (defragment_direction) { 387 /* L1 -> L2: further de-fragment on L1 */ 388 BCM_IF_ERROR_RETURN( 389 bcm_tr2_l3_ecmp_defragment_no_lock(unit, 1)); 390 } else { 391 /* L2 -> L1: further de-fragment on L2*/ 392 BCM_IF_ERROR_RETURN( 393 bcm_tr2_l3_ecmp_defragment_no_lock(unit, 2)); 394 } 395 396 BCM_IF_ERROR_RETURN(_bcm_xgs3_tbl_free_idx_get(unit, &data)); 397 } else 398 #endif 399 if (BCM_FAILURE(rv)) { 400 return rv; 401 } 402 } else if (BCM_FAILURE(rv)) { 403 return rv; 404 } 405 406 ecmp_idx = data.entry_index; 407 BCM_XGS3_L3_ENT_REF_CNT_INC(data.tbl_ptr, ecmp_idx, max_grp_size); 408 ecmp_table_incr = 1; 409 410 } 411 412 sal_memset (hw_buf, 0, SOC_MAX_MEM_FIELD_WORDS * sizeof(uint32)); 413 sal_memset (&initial_l3_ecmp_group_entry, 0, 414 sizeof(initial_l3_ecmp_group_entry_t)); 415 416 if (max_grp_size > L3_ECMP_MEM_DMA_THRESHOLD) { 417 rv = bcm_xgs3_l3_tbl_range_dma(unit, L3_ECMPm, sizeof(ecmp_entry_t), 418 "l3_ecmp_tbl", ecmp_idx, 419 ecmp_idx + max_grp_size - 1, 420 &l3_ecmp_tbl_ptr); 421 BCM_IF_ERROR_RETURN(rv); 422 if (!soc_feature(unit, soc_feature_post_ifp_single_stage_ecmp)) { 423 rv = bcm_xgs3_l3_tbl_range_dma(unit, INITIAL_L3_ECMPm, 424 sizeof(initial_l3_ecmp_entry_t), 425 "initial_l3_ecmp_tbl", ecmp_idx, 426 ecmp_idx + max_grp_size - 1, 427 &initial_l3_ecmp_tbl_ptr); 428 if (BCM_FAILURE(rv)) { 429 soc_cm_sfree(unit, l3_ecmp_tbl_ptr); 430 return rv; 431 } 432 initial_ecmp_null_entry = soc_mem_entry_null(unit, INITIAL_L3_ECMPm); 433 } 434 435 ecmp_null_entry = soc_mem_entry_null(unit, L3_ECMPm); 436 } 437 438 /* Write all the indexes to hw. */ 439 for (idx = 0, nh_cycle_idx = 0; idx < max_grp_size; idx++, nh_cycle_idx++) { 440 /* Set next hop index. */ 441 if (max_grp_size > L3_ECMP_MEM_DMA_THRESHOLD) { 442 ecmp_entry_ptr = 443 soc_mem_table_idx_to_pointer(unit, L3_ECMPm, uint32 *, 444 l3_ecmp_tbl_ptr, idx); 445 if (!soc_feature(unit, soc_feature_post_ifp_single_stage_ecmp)) { 446 initial_ecmp_entry_ptr = 447 soc_mem_table_idx_to_pointer(unit, INITIAL_L3_ECMPm, uint32 *, 448 initial_l3_ecmp_tbl_ptr, idx); 449 sal_memcpy(initial_ecmp_entry_ptr, initial_ecmp_null_entry, 450 sizeof(initial_l3_ecmp_entry_t)); 451 } 452 sal_memcpy(ecmp_entry_ptr, ecmp_null_entry, sizeof(ecmp_entry_t)); 453 } else { 454 sal_memset (l3_ecmp, 0, SOC_MAX_MEM_FIELD_WORDS * sizeof(uint32)); 455 if (!soc_feature(unit, soc_feature_post_ifp_single_stage_ecmp)) { 456 sal_memset (initial_l3_ecmp, 0, 457 SOC_MAX_MEM_FIELD_WORDS * sizeof(uint32)); 458 initial_ecmp_entry_ptr = initial_l3_ecmp; 459 } 460 ecmp_entry_ptr = l3_ecmp; 461 } 462 463 /* If this is the last nhop then program black-hole. */ 464 #ifdef BCM_TOMAHAWK_SUPPORT 465 if (!(soc_feature(unit, soc_feature_ecmp_resilient_hash_optimized) && 466 (ecmp_info->ecmp_flags & BCM_L3_ECMP_RH_OPT))) 467 #endif /* BCM_TOMAHAWK_SUPPORT */ 468 { 469 if (!nh_idx[nh_cycle_idx]) { 470 if (!idx) { 471 nh_cycle_idx = 0; 472 } else { 473 #if defined(BCM_TOMAHAWK2_SUPPORT) || defined(BCM_TRIDENT3_SUPPORT) 474 if (soc_feature(unit, soc_feature_dgm) && 475 (ecmp_info->ecmp_flags & BCM_L3_ECMP_DGM_OPT)) { 476 /* primay entry exists or one more entry zeroed */ 477 if (idx > ecmp_info->alternate_cnt || dgm_zero_hit) { 478 if (dgm_zero_hit) { 479 /* decrease idx to get real count */ 480 idx--; 481 } 482 break; 483 } else { 484 /* If there is no primary entry, zero one more entry */ 485 dgm_zero_hit = 1; 486 } 487 } else 488 #endif /* BCM_TOMAHAWK2_SUPPORT */ 489 { 490 break; 491 } 492 } 493 } 494 } 495 ecmpf = 0; 496 #ifdef BCM_TOMAHAWK_SUPPORT 497 /* Set ecmp flag if member is an ecmp group */ 498 if (soc_feature(unit, soc_feature_hierarchical_ecmp)) { 499 if (BCM_XGS3_L3_MPATH_EGRESS_IDX_VALID(unit, 500 nh_idx[nh_cycle_idx])) { 501 ecmpf = 1; 502 nh_idx[nh_cycle_idx] -= BCM_XGS3_MPATH_EGRESS_IDX_MIN(unit); 503 if (!soc_feature(unit, soc_feature_post_ifp_single_stage_ecmp)) { 504 soc_mem_field32_set(unit, L3_ECMPm, ecmp_entry_ptr, 505 ECMP_FLAGf, 1); 506 soc_mem_field32_set(unit, INITIAL_L3_ECMPm, 507 initial_ecmp_entry_ptr, _initial_l3_ecmp_flag, 1); 508 } 509 } 510 } 511 #endif /* BCM_TOMAHAWK_SUPPORT */ 512 513 #ifdef BCM_MULTI_LEVEL_ECMP_SUPPORT 514 /* Set ecmp flag if member is an ecmp group */ 515 if (soc_feature(unit, soc_feature_multi_level_ecmp)) { 516 if (BCM_XGS3_L3_MPATH_EGRESS_IDX_VALID(unit, 517 nh_idx[nh_cycle_idx])) { 518 nh_idx[nh_cycle_idx] -= BCM_XGS3_MPATH_EGRESS_IDX_MIN(unit); 519 #ifdef BCM_TRIDENT3_SUPPORT 520 if (SOC_IS_TRIDENT3X(unit)) { 521 soc_mem_field32_set(unit, L3_ECMPm, ecmp_entry_ptr, ECMP_FLAGf, 1); 522 ecmpf = 1; 523 soc_mem_field32_set(unit, INITIAL_L3_ECMPm, 524 initial_ecmp_entry_ptr, ECMPf, 1); 525 } else 526 #endif 527 { 528 soc_mem_field32_set(unit, L3_ECMPm, ecmp_entry_ptr, ECMPf, 1); 529 if (!soc_feature(unit, soc_feature_post_ifp_single_stage_ecmp)) { 530 soc_mem_field32_set(unit, INITIAL_L3_ECMPm, 531 initial_ecmp_entry_ptr, ECMPf, 1); 532 } 533 } 534 } 535 } 536 #endif /* BCM_MULTI_LEVEL_ECMP_SUPPORT */ 537 538 539 if (SOC_IS_TRIDENT3X(unit)) { 540 soc_mem_field32_dest_set(unit, L3_ECMPm, ecmp_entry_ptr, DESTINATIONf, 541 ecmpf ? SOC_MEM_FIF_DEST_ECMP : SOC_MEM_FIF_DEST_NEXTHOP, 542 nh_idx[nh_cycle_idx]); 543 soc_mem_field32_dest_set(unit, INITIAL_L3_ECMPm, initial_ecmp_entry_ptr, DESTINATIONf, 544 ecmpf ? SOC_MEM_FIF_DEST_ECMP : SOC_MEM_FIF_DEST_NEXTHOP, 545 nh_idx[nh_cycle_idx]); 546 } else { 547 548 soc_mem_field32_set(unit, L3_ECMPm, ecmp_entry_ptr, 549 NEXT_HOP_INDEXf, nh_idx[nh_cycle_idx]); 550 if (!soc_feature(unit, soc_feature_post_ifp_single_stage_ecmp)) { 551 soc_mem_field32_set(unit, INITIAL_L3_ECMPm, initial_ecmp_entry_ptr, 552 NEXT_HOP_INDEXf, nh_idx[nh_cycle_idx]); 553 } 554 } 555 556 /* Write buffer to hw L3_ECMPm table. */ 557 if (max_grp_size <= L3_ECMP_MEM_DMA_THRESHOLD) { 558 rv = soc_mem_write(unit, L3_ECMPm, MEM_BLOCK_ALL, 559 (ecmp_idx + idx), ecmp_entry_ptr); 560 561 if (BCM_FAILURE(rv)) { 562 break; 563 } 564 565 if (!soc_feature(unit, soc_feature_post_ifp_single_stage_ecmp)) { 566 /* Write buffer to hw INITIAL_L3_ECMPm table. */ 567 rv = soc_mem_write(unit, INITIAL_L3_ECMPm, MEM_BLOCK_ALL, 568 (ecmp_idx + idx), initial_ecmp_entry_ptr); 569 570 if (BCM_FAILURE(rv)) { 571 break; 572 } 573 } 574 } 575 576 if (soc_feature(unit, soc_feature_urpf)) { 577 /* Check if URPF is enabled on device */ 578 rv = READ_L3_DEFIP_RPF_CONTROLr(unit, ®_val); 579 if (BCM_FAILURE(rv)) { 580 if (max_grp_size > L3_ECMP_MEM_DMA_THRESHOLD) { 581 soc_cm_sfree(unit, l3_ecmp_tbl_ptr); 582 soc_cm_sfree(unit, initial_l3_ecmp_tbl_ptr); 583 } 584 return rv; 585 } 586 587 if (reg_val) { 588 if (idx < 8) { 589 rv = soc_mem_read(unit, ING_L3_NEXT_HOPm, MEM_BLOCK_ANY, 590 nh_idx[idx], &ing_nh); 591 if (BCM_FAILURE(rv)) { 592 if (max_grp_size > L3_ECMP_MEM_DMA_THRESHOLD) { 593 soc_cm_sfree(unit, l3_ecmp_tbl_ptr); 594 soc_cm_sfree(unit, initial_l3_ecmp_tbl_ptr); 595 } 596 return rv; 597 } 598 599 entry_type = 600 soc_ING_L3_NEXT_HOPm_field32_get(unit, 601 &ing_nh, ENTRY_TYPEf); 602 603 if (entry_type == 0x0) { 604 if (SOC_MEM_FIELD_VALID(unit, ING_L3_NEXT_HOPm, 605 L3_OIFf)) { 606 value = soc_ING_L3_NEXT_HOPm_field32_get( 607 unit, &ing_nh, L3_OIFf); 608 } else { 609 value = soc_ING_L3_NEXT_HOPm_field32_get( 610 unit, &ing_nh, VLAN_IDf); 611 } 612 soc_mem_field32_set(unit, L3_ECMP_COUNTm, hw_buf, 613 l3_ecmp_oif_type_flds[idx], entry_type); 614 soc_mem_field32_set(unit, L3_ECMP_COUNTm, hw_buf, 615 l3_ecmp_oif_flds[idx], value); 616 } else if (entry_type == 0x1) { 617 value = soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, L3_OIFf); 618 soc_mem_field32_set(unit, L3_ECMP_COUNTm, hw_buf, 619 l3_ecmp_oif_type_flds[idx], entry_type); 620 soc_mem_field32_set(unit, L3_ECMP_COUNTm, hw_buf, 621 l3_ecmp_oif_flds[idx], value); 622 } 623 soc_mem_field32_set(unit, L3_ECMP_COUNTm, hw_buf, URPF_COUNTf, idx); 624 }else { 625 /* Inorder to avoid TRAP_TO_CPU, urpf_mode on L3_IIF/PORT must be set 626 to STRICT_MODE / LOOSE_MODE */ 627 soc_mem_field32_set(unit, L3_ECMP_COUNTm, hw_buf, ECMP_GT8f , 1); 628 } 629 } 630 } 631 } 632 intf_count = idx; 633 if (max_grp_size > L3_ECMP_MEM_DMA_THRESHOLD) { 634 rv = soc_mem_write_range(unit, L3_ECMPm, MEM_BLOCK_ALL, ecmp_idx, 635 ecmp_idx + max_grp_size - 1, l3_ecmp_tbl_ptr); 636 if (BCM_SUCCESS(rv)) { 637 if (!soc_feature(unit, soc_feature_post_ifp_single_stage_ecmp)) { 638 rv = soc_mem_write_range(unit, INITIAL_L3_ECMPm, MEM_BLOCK_ALL, 639 ecmp_idx, ecmp_idx + max_grp_size - 1, 640 initial_l3_ecmp_tbl_ptr); 641 soc_cm_sfree(unit, initial_l3_ecmp_tbl_ptr); 642 } 643 } 644 soc_cm_sfree(unit, l3_ecmp_tbl_ptr); 645 } 646 647 if (BCM_SUCCESS(rv)) { 648 /* mode 0 = 512 ecmp groups */ 649 if (!BCM_XGS3_L3_MAX_ECMP_MODE(unit)) { 650 /* Set Max Group Size. */ 651 sal_memset (l3_ecmp_count, 0, 652 SOC_MAX_MEM_FIELD_WORDS * sizeof(uint32)); 653 if (soc_feature(unit, soc_feature_l3_ecmp_1k_groups) || 654 SOC_IS_MONTEREY(unit)) { 655 rv = _bcm_xgs3_l3_ecmp_grp_info_set(unit, (ecmp_grp + 1), 656 l3_ecmp_count, 657 NULL, 0, 658 max_grp_size, -1, 0, 659 ecmp_info->ecmp_flags); 660 if (BCM_FAILURE(rv)) { 661 if (ecmp_table_incr == 1) { 662 BCM_XGS3_L3_ENT_REF_CNT_DEC(BCM_XGS3_L3_TBL_PTR(unit, ecmp), 663 ecmp_idx, max_grp_size); 664 } 665 return rv; 666 } 667 } else { 668 if (soc_feature(unit, soc_feature_ecmp_1k_paths_4_subgroups) && 669 (max_grp_size >= 256)) { 670 max_subgrp_cnt = ((max_grp_size + 3) / 4); 671 soc_mem_field32_set(unit, L3_ECMP_COUNTm, 672 l3_ecmp_count, COUNT_0f, (max_subgrp_cnt - 1)); 673 soc_mem_field32_set(unit, L3_ECMP_COUNTm, 674 l3_ecmp_count, COUNT_1f, (max_subgrp_cnt - 1)); 675 soc_mem_field32_set(unit, L3_ECMP_COUNTm, 676 l3_ecmp_count, COUNT_2f, (max_subgrp_cnt - 1)); 677 soc_mem_field32_set(unit, L3_ECMP_COUNTm, 678 l3_ecmp_count, COUNT_3f, 679 ((max_grp_size - (3 * max_subgrp_cnt) - 1))); 680 681 soc_mem_field32_set(unit, L3_ECMP_COUNTm, 682 l3_ecmp_count, BASE_PTR_0f, ecmp_idx); 683 soc_mem_field32_set(unit, L3_ECMP_COUNTm, 684 l3_ecmp_count, BASE_PTR_1f, 685 (ecmp_idx + max_subgrp_cnt)); 686 soc_mem_field32_set(unit, L3_ECMP_COUNTm, 687 l3_ecmp_count, BASE_PTR_2f, 688 (ecmp_idx + (2 * max_subgrp_cnt))); 689 soc_mem_field32_set(unit, L3_ECMP_COUNTm, 690 l3_ecmp_count, BASE_PTR_3f, 691 (ecmp_idx + (3 * max_subgrp_cnt))); 692 } else { 693 soc_mem_field32_set(unit, L3_ECMP_COUNTm, 694 l3_ecmp_count, COUNT_0f, max_grp_size-1); 695 soc_mem_field32_set(unit, L3_ECMP_COUNTm, 696 l3_ecmp_count, COUNT_1f, max_grp_size-1); 697 soc_mem_field32_set(unit, L3_ECMP_COUNTm, 698 l3_ecmp_count, COUNT_2f, max_grp_size-1); 699 soc_mem_field32_set(unit, L3_ECMP_COUNTm, 700 l3_ecmp_count, COUNT_3f, max_grp_size-1); 701 } 702 } 703 rv = soc_mem_write(unit, grp_mem, MEM_BLOCK_ALL, 704 (ecmp_grp+1), l3_ecmp_count); 705 706 if (BCM_FAILURE(rv)) { 707 if (ecmp_table_incr == 1) { 708 BCM_XGS3_L3_ENT_REF_CNT_DEC(BCM_XGS3_L3_TBL_PTR(unit, ecmp), 709 ecmp_idx, max_grp_size); 710 } 711 return rv; 712 } 713 } 714 if (soc_feature(unit, soc_feature_l3_ecmp_1k_groups) || 715 SOC_IS_MONTEREY(unit)) { 716 rv = _bcm_xgs3_l3_ecmp_grp_info_set(unit, ecmp_grp, hw_buf, 717 &initial_l3_ecmp_group_entry, !soc_feature(unit, soc_feature_post_ifp_single_stage_ecmp), 718 idx, ecmp_idx, ecmp_info->alternate_cnt, 719 ecmp_info->ecmp_flags); 720 if (BCM_FAILURE(rv)) { 721 if (ecmp_table_incr == 1) { 722 BCM_XGS3_L3_ENT_REF_CNT_DEC(BCM_XGS3_L3_TBL_PTR(unit, ecmp), 723 ecmp_idx, max_grp_size); 724 } 725 return rv; 726 } 727 } else { 728 if (!idx) { 729 soc_mem_field32_set(unit, L3_ECMP_COUNTm, hw_buf, COUNT_0f, idx ); 730 soc_mem_field32_set(unit, L3_ECMP_COUNTm, hw_buf, COUNT_1f, idx ); 731 soc_mem_field32_set(unit, L3_ECMP_COUNTm, hw_buf, COUNT_2f, idx ); 732 soc_mem_field32_set(unit, L3_ECMP_COUNTm, hw_buf, COUNT_3f, idx ); 733 734 if (!soc_feature(unit, soc_feature_post_ifp_single_stage_ecmp)) { 735 soc_mem_field32_set(unit, INITIAL_L3_ECMP_GROUPm, 736 &initial_l3_ecmp_group_entry, COUNT_0f, idx); 737 soc_mem_field32_set(unit, INITIAL_L3_ECMP_GROUPm, 738 &initial_l3_ecmp_group_entry, COUNT_1f, idx); 739 soc_mem_field32_set(unit, INITIAL_L3_ECMP_GROUPm, 740 &initial_l3_ecmp_group_entry, COUNT_2f, idx); 741 soc_mem_field32_set(unit, INITIAL_L3_ECMP_GROUPm, 742 &initial_l3_ecmp_group_entry, COUNT_3f, idx); 743 } 744 } else { 745 if (soc_feature(unit, soc_feature_ecmp_1k_paths_4_subgroups) && 746 (intf_count >= 256)) { 747 subgrp_cnt = ((intf_count + 3) / 4); 748 soc_mem_field32_set(unit, L3_ECMP_COUNTm, 749 hw_buf, COUNT_0f, (subgrp_cnt - 1)); 750 soc_mem_field32_set(unit, L3_ECMP_COUNTm, 751 hw_buf, COUNT_1f, (subgrp_cnt - 1)); 752 soc_mem_field32_set(unit, L3_ECMP_COUNTm, 753 hw_buf, COUNT_2f, (subgrp_cnt - 1)); 754 soc_mem_field32_set(unit, L3_ECMP_COUNTm, 755 hw_buf, COUNT_3f, 756 (intf_count - (3 * subgrp_cnt) - 1)); 757 758 if (!soc_feature(unit, soc_feature_post_ifp_single_stage_ecmp)) { 759 soc_mem_field32_set(unit, INITIAL_L3_ECMP_GROUPm, 760 &initial_l3_ecmp_group_entry, COUNT_0f, 761 (subgrp_cnt - 1)); 762 soc_mem_field32_set(unit, INITIAL_L3_ECMP_GROUPm, 763 &initial_l3_ecmp_group_entry, COUNT_1f, 764 (subgrp_cnt - 1)); 765 soc_mem_field32_set(unit, INITIAL_L3_ECMP_GROUPm, 766 &initial_l3_ecmp_group_entry, COUNT_2f, 767 (subgrp_cnt - 1)); 768 soc_mem_field32_set(unit, INITIAL_L3_ECMP_GROUPm, 769 &initial_l3_ecmp_group_entry, COUNT_3f, 770 (intf_count - (3 * subgrp_cnt) - 1)); 771 } 772 } else { 773 774 soc_mem_field32_set(unit, L3_ECMP_COUNTm, hw_buf, COUNT_0f, idx - 1); 775 soc_mem_field32_set(unit, L3_ECMP_COUNTm, hw_buf, COUNT_1f, idx - 1); 776 soc_mem_field32_set(unit, L3_ECMP_COUNTm, hw_buf, COUNT_2f, idx - 1); 777 soc_mem_field32_set(unit, L3_ECMP_COUNTm, hw_buf, COUNT_3f, idx - 1); 778 779 if (!soc_feature(unit, soc_feature_post_ifp_single_stage_ecmp)) { 780 soc_mem_field32_set(unit, INITIAL_L3_ECMP_GROUPm, 781 &initial_l3_ecmp_group_entry, COUNT_0f, idx - 1); 782 soc_mem_field32_set(unit, INITIAL_L3_ECMP_GROUPm, 783 &initial_l3_ecmp_group_entry, COUNT_1f, idx - 1); 784 soc_mem_field32_set(unit, INITIAL_L3_ECMP_GROUPm, 785 &initial_l3_ecmp_group_entry, COUNT_2f, idx - 1); 786 soc_mem_field32_set(unit, INITIAL_L3_ECMP_GROUPm, 787 &initial_l3_ecmp_group_entry, COUNT_3f, idx - 1); 788 } 789 } 790 } 791 792 if (soc_feature(unit, soc_feature_ecmp_1k_paths_4_subgroups) && 793 (intf_count >= 256)) { 794 subgrp_cnt = ((intf_count + 3) / 4); 795 soc_mem_field32_set(unit, L3_ECMP_COUNTm, hw_buf, 796 BASE_PTR_0f, ecmp_idx); 797 soc_mem_field32_set(unit, L3_ECMP_COUNTm, hw_buf, 798 BASE_PTR_1f, (ecmp_idx + subgrp_cnt)); 799 soc_mem_field32_set(unit, L3_ECMP_COUNTm, hw_buf, 800 BASE_PTR_2f, (ecmp_idx + (2 * subgrp_cnt))); 801 soc_mem_field32_set(unit, L3_ECMP_COUNTm, hw_buf, 802 BASE_PTR_3f, (ecmp_idx + (3 * subgrp_cnt))); 803 804 if (!soc_feature(unit, soc_feature_post_ifp_single_stage_ecmp)) { 805 soc_mem_field32_set(unit, INITIAL_L3_ECMP_GROUPm, &initial_l3_ecmp_group_entry, 806 BASE_PTR_0f, ecmp_idx); 807 soc_mem_field32_set(unit, INITIAL_L3_ECMP_GROUPm, &initial_l3_ecmp_group_entry, 808 BASE_PTR_1f, (ecmp_idx + subgrp_cnt)); 809 soc_mem_field32_set(unit, INITIAL_L3_ECMP_GROUPm, &initial_l3_ecmp_group_entry, 810 BASE_PTR_2f, (ecmp_idx + (2 * subgrp_cnt))); 811 soc_mem_field32_set(unit, INITIAL_L3_ECMP_GROUPm, &initial_l3_ecmp_group_entry, 812 BASE_PTR_3f, (ecmp_idx + (3 * subgrp_cnt))); 813 } 814 } else { 815 /* Set group base pointer. */ 816 if (SOC_MEM_FIELD_VALID(unit, L3_ECMP_COUNTm, BASE_PTR_0f)) { 817 soc_mem_field32_set(unit, L3_ECMP_COUNTm, hw_buf, 818 BASE_PTR_0f, ecmp_idx); 819 } 820 if (SOC_MEM_FIELD_VALID(unit, L3_ECMP_COUNTm, BASE_PTR_1f)) { 821 soc_mem_field32_set(unit, L3_ECMP_COUNTm, hw_buf, 822 BASE_PTR_1f, ecmp_idx); 823 } 824 if (SOC_MEM_FIELD_VALID(unit, L3_ECMP_COUNTm, BASE_PTR_2f)) { 825 soc_mem_field32_set(unit, L3_ECMP_COUNTm, hw_buf, 826 BASE_PTR_2f, ecmp_idx); 827 } 828 if (SOC_MEM_FIELD_VALID(unit, L3_ECMP_COUNTm, BASE_PTR_3f)) { 829 soc_mem_field32_set(unit, L3_ECMP_COUNTm, hw_buf, 830 BASE_PTR_3f, ecmp_idx); 831 } 832 833 if (SOC_MEM_FIELD_VALID(unit, INITIAL_L3_ECMP_GROUPm, BASE_PTR_0f)) { 834 soc_mem_field32_set(unit, INITIAL_L3_ECMP_GROUPm, 835 &initial_l3_ecmp_group_entry, BASE_PTR_0f, ecmp_idx); 836 } 837 if (SOC_MEM_FIELD_VALID(unit, INITIAL_L3_ECMP_GROUPm, BASE_PTR_1f)) { 838 soc_mem_field32_set(unit, INITIAL_L3_ECMP_GROUPm, 839 &initial_l3_ecmp_group_entry, BASE_PTR_1f, ecmp_idx); 840 } 841 if (SOC_MEM_FIELD_VALID(unit, INITIAL_L3_ECMP_GROUPm, BASE_PTR_2f)) { 842 soc_mem_field32_set(unit, INITIAL_L3_ECMP_GROUPm, 843 &initial_l3_ecmp_group_entry, BASE_PTR_2f, ecmp_idx); 844 } 845 if (SOC_MEM_FIELD_VALID(unit, INITIAL_L3_ECMP_GROUPm, BASE_PTR_3f)) { 846 soc_mem_field32_set(unit, INITIAL_L3_ECMP_GROUPm, 847 &initial_l3_ecmp_group_entry, BASE_PTR_3f, ecmp_idx); 848 } 849 } 850 } 851 852 if (!soc_feature(unit, soc_feature_post_ifp_single_stage_ecmp)) { 853 rv = soc_mem_write(unit, INITIAL_L3_ECMP_GROUPm, MEM_BLOCK_ALL, 854 ecmp_grp, &initial_l3_ecmp_group_entry); 855 if (BCM_FAILURE(rv) && (ecmp_table_incr == 1)) { 856 BCM_XGS3_L3_ENT_REF_CNT_DEC 857 (BCM_XGS3_L3_TBL_PTR(unit, ecmp), ecmp_idx, max_grp_size); 858 return rv; 859 } 860 } 861 862 #ifdef BCM_TRIDENT2_SUPPORT 863 /* Preserve the fields related to resilient hashing */ 864 if (soc_feature(unit, soc_feature_ecmp_resilient_hash)) { 865 ecmp_count_entry_t old_ecmp_count_entry; 866 int enhanced_hashing_enable; 867 int rh_flow_set_base; 868 int rh_flow_set_size; 869 870 SOC_IF_ERROR_RETURN(READ_L3_ECMP_COUNTm(unit, MEM_BLOCK_ANY, 871 ecmp_grp, &old_ecmp_count_entry)); 872 if (soc_feature(unit, soc_feature_td3_style_dlb_rh)){ 873 enhanced_hashing_enable = soc_mem_field32_get(unit, L3_ECMP_COUNTm, 874 &old_ecmp_count_entry, LB_MODEf); 875 } else { 876 enhanced_hashing_enable = soc_mem_field32_get(unit, L3_ECMP_COUNTm, 877 &old_ecmp_count_entry, ENHANCED_HASHING_ENABLEf); 878 } 879 rh_flow_set_base = soc_mem_field32_get(unit, L3_ECMP_COUNTm, 880 &old_ecmp_count_entry, RH_FLOW_SET_BASEf); 881 rh_flow_set_size = soc_mem_field32_get(unit, L3_ECMP_COUNTm, 882 &old_ecmp_count_entry, RH_FLOW_SET_SIZEf); 883 if (soc_feature(unit, soc_feature_td3_style_dlb_rh)){ 884 soc_mem_field32_set(unit, L3_ECMP_COUNTm, hw_buf, 885 LB_MODEf, enhanced_hashing_enable); 886 } else { 887 soc_mem_field32_set(unit, L3_ECMP_COUNTm, hw_buf, 888 ENHANCED_HASHING_ENABLEf, enhanced_hashing_enable); 889 } 890 soc_mem_field32_set(unit, L3_ECMP_COUNTm, hw_buf, 891 RH_FLOW_SET_BASEf, rh_flow_set_base); 892 soc_mem_field32_set(unit, L3_ECMP_COUNTm, hw_buf, 893 RH_FLOW_SET_SIZEf, rh_flow_set_size); 894 } 895 #endif /* BCM_TRIDENT2_SUPPORT */ 896 897 #ifdef BCM_TOMAHAWK_SUPPORT 898 /* Write Load Balancing Mode fields */ 899 if (soc_feature(unit, soc_feature_ecmp_resilient_hash_optimized) 900 && !(ecmp_info->ecmp_flags & BCM_L3_ECMP_WEIGHTED)) { 901 ecmp_count_entry_t old_ecmp_count_entry; 902 int lb_mode; 903 SOC_IF_ERROR_RETURN(soc_mem_read(unit, grp_mem, MEM_BLOCK_ANY, 904 ecmp_grp, &old_ecmp_count_entry)); 905 lb_mode = soc_mem_field32_get(unit, grp_mem, 906 &old_ecmp_count_entry, LB_MODEf); 907 soc_mem_field32_set(unit, grp_mem, hw_buf, 908 LB_MODEf, lb_mode); 909 } 910 #endif /* BCM_TOMAHAWK_SUPPORT */ 911 912 rv = soc_mem_write(unit, grp_mem, MEM_BLOCK_ALL, 913 ecmp_grp, hw_buf); 914 915 /* mode 1 = max possible ecmp groups */ 916 if (BCM_XGS3_L3_MAX_ECMP_MODE(unit)) { 917 /* Save the max possible paths for this ECMP group in s/w */ 918 BCM_XGS3_L3_MAX_PATHS_PERGROUP_PTR(unit)[ecmp_grp] = ecmp_info->max_paths; 919 } 920 } 921 922 if (BCM_FAILURE(rv)) { 923 if (ecmp_table_incr == 1) { 924 BCM_XGS3_L3_ENT_REF_CNT_DEC(BCM_XGS3_L3_TBL_PTR(unit, ecmp), 925 ecmp_idx, max_grp_size); 926 } 927 } 928 return rv; 929 } 930 931 932 /* 933 * Function: 934 * _bcm_td_l3_ecmp_grp_del 935 * Purpose: 936 * Reset ecmp group next hop members 937 * Parameters: 938 * unit - (IN)SOC unit number. 939 * ecmp_grp - (IN)ecmp group id to write. 940 * info - (IN)ECMP additional info 941 * Returns: 942 * BCM_E_XXX 943 */ 944 int 945 _bcm_td_l3_ecmp_grp_del (int unit, int ecmp_grp, void *info) 946 { 947 uint32 hw_buf[SOC_MAX_MEM_FIELD_WORDS]; /* Buffer to write hw entry.*/ 948 int ecmp_idx = 0; /* Ecmp table entry index. */ 949 int idx; /* Iteration index. */ 950 int rv = BCM_E_UNAVAIL; /* Operation return value. */ 951 _bcm_l3_tbl_op_t data; 952 soc_mem_t mem = L3_ECMP_COUNTm; 953 954 data.tbl_ptr = BCM_XGS3_L3_TBL_PTR(unit, ecmp); 955 956 if (NULL == info) { 957 return BCM_E_INTERNAL; 958 } 959 /* Initialize ecmp entry. */ 960 sal_memset (hw_buf, 0, SOC_MAX_MEM_FIELD_WORDS * sizeof(uint32)); 961 962 /* Calculate table index. */ 963 #ifdef BCM_TOMAHAWK3_SUPPORT 964 if ((soc_feature(unit, soc_feature_l3_ecmp_hier_tbl)) && 965 (BCM_XGS3_L3_TBL(unit, ecmp_info).ecmp_mode == 966 ecmp_mode_hierarchical) && 967 (ecmp_grp < (BCM_XGS3_L3_ECMP_MAX_GROUPS(unit) / 2))) { 968 mem = ECMP_GROUP_HIERARCHICALm; 969 } 970 #endif 971 972 BCM_IF_ERROR_RETURN( 973 _bcm_xgs3_l3_ecmp_grp_info_get(unit, ecmp_grp, NULL, &ecmp_idx)); 974 975 /* Write all the indexes to hw. */ 976 for (idx = 0; idx < ((_bcm_l3_ecmp_group_info_t*)info)->max_paths; idx++) { 977 /* Write buffer to hw. */ 978 rv = soc_mem_write(unit, L3_ECMPm, MEM_BLOCK_ALL, 979 (ecmp_idx + idx), hw_buf); 980 if (BCM_FAILURE(rv)) { 981 return rv; 982 } 983 /* Write buffer to hw INITIAL_L3_ECMPm table. */ 984 if (!soc_feature(unit, soc_feature_post_ifp_single_stage_ecmp)) { 985 rv = soc_mem_write(unit, INITIAL_L3_ECMPm, MEM_BLOCK_ALL, 986 (ecmp_idx + idx), hw_buf); 987 988 if (BCM_FAILURE(rv)) { 989 return rv; 990 } 991 } 992 } 993 994 /* Decrement ref count for the entries in ecmp table 995 * Ref count for ecmp_group table is decremented in common table del func. */ 996 BCM_XGS3_L3_ENT_REF_CNT_DEC(data.tbl_ptr, ecmp_idx, 997 ((_bcm_l3_ecmp_group_info_t*)info)->max_paths); 998 999 if (SOC_MEM_IS_VALID(unit, mem)) { 1000 /* Set group base pointer. */ 1001 ecmp_idx = ecmp_grp; 1002 1003 if (SOC_MEM_IS_VALID(unit, INITIAL_L3_ECMP_GROUPm)) { 1004 rv = soc_mem_write(unit, INITIAL_L3_ECMP_GROUPm, MEM_BLOCK_ALL, 1005 ecmp_idx, hw_buf); 1006 BCM_IF_ERROR_RETURN(rv); 1007 } 1008 1009 if (!BCM_XGS3_L3_MAX_ECMP_MODE(unit)) { 1010 rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, 1011 (ecmp_idx+1), hw_buf); 1012 BCM_IF_ERROR_RETURN(rv); 1013 } 1014 1015 #ifdef BCM_TRIDENT2_SUPPORT 1016 /* Preserve the fields related to resilient hashing */ 1017 if (soc_feature(unit, soc_feature_ecmp_resilient_hash)) { 1018 ecmp_count_entry_t old_ecmp_count_entry; 1019 int enhanced_hashing_enable; 1020 int rh_flow_set_base; 1021 int rh_flow_set_size; 1022 1023 SOC_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ANY, 1024 ecmp_grp, &old_ecmp_count_entry)); 1025 if (soc_feature(unit, soc_feature_td3_style_dlb_rh)){ 1026 enhanced_hashing_enable = soc_mem_field32_get(unit, mem, 1027 &old_ecmp_count_entry, LB_MODEf); 1028 } else { 1029 enhanced_hashing_enable = soc_mem_field32_get(unit, mem, 1030 &old_ecmp_count_entry, ENHANCED_HASHING_ENABLEf); 1031 } 1032 rh_flow_set_base = soc_mem_field32_get(unit, mem, 1033 &old_ecmp_count_entry, RH_FLOW_SET_BASEf); 1034 rh_flow_set_size = soc_mem_field32_get(unit, mem, 1035 &old_ecmp_count_entry, RH_FLOW_SET_SIZEf); 1036 if (soc_feature(unit, soc_feature_td3_style_dlb_rh)){ 1037 soc_mem_field32_set(unit, mem, hw_buf, 1038 LB_MODEf, enhanced_hashing_enable); 1039 } else { 1040 soc_mem_field32_set(unit, mem, hw_buf, 1041 ENHANCED_HASHING_ENABLEf, enhanced_hashing_enable); 1042 } 1043 soc_mem_field32_set(unit, mem, hw_buf, 1044 RH_FLOW_SET_BASEf, rh_flow_set_base); 1045 soc_mem_field32_set(unit, mem, hw_buf, 1046 RH_FLOW_SET_SIZEf, rh_flow_set_size); 1047 } 1048 #endif /* BCM_TRIDENT2_SUPPORT */ 1049 1050 #ifdef BCM_TOMAHAWK_SUPPORT 1051 /* LB field set */ 1052 if (soc_feature(unit, soc_feature_ecmp_resilient_hash_optimized)) { 1053 ecmp_count_entry_t old_ecmp_count_entry; 1054 int lb_mode; 1055 1056 SOC_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ANY, 1057 ecmp_grp, &old_ecmp_count_entry)); 1058 lb_mode = soc_mem_field32_get(unit, mem, 1059 &old_ecmp_count_entry, LB_MODEf); 1060 soc_mem_field32_set(unit, mem, hw_buf, 1061 LB_MODEf, lb_mode); 1062 } 1063 #endif /* BCM_TOMAHAWK_SUPPORT */ 1064 1065 rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, 1066 ecmp_idx, hw_buf); 1067 BCM_IF_ERROR_RETURN(rv); 1068 } 1069 1070 if (BCM_XGS3_L3_MAX_ECMP_MODE(unit) && 1071 BCM_XGS3_L3_MAX_PATHS_PERGROUP_PTR(unit)) { 1072 /* Reset max paths of the deleted group */ 1073 BCM_XGS3_L3_MAX_PATHS_PERGROUP_PTR(unit)[ecmp_grp] = 0; 1074 } 1075 1076 return rv; 1077 } 1078 1079 /* 1080 * Function: 1081 * _bcm_td_l3_intf_qos_set 1082 * Purpose: 1083 * Set L3 Interface QoS parameters 1084 * Parameters: 1085 * unit - (IN)SOC unit number. 1086 * l3_if_entry_p - (IN) Pointer to buffer 1087 * vid - (IN) Intf_info 1088 * Returns: 1089 * BCM_E_XXX. 1090 */ 1091 int 1092 _bcm_td_l3_intf_qos_set(int unit, uint32 *l3_if_entry_p, _bcm_l3_intf_cfg_t *intf_info) 1093 { 1094 int hw_map_idx=0; 1095 1096 /* Input parameters check */ 1097 if (NULL == intf_info) { 1098 return (BCM_E_PARAM); 1099 } 1100 1101 if (intf_info->vlan_qos.flags & BCM_L3_INTF_QOS_OUTER_VLAN_PRI_COPY) { 1102 if (SOC_MEM_FIELD_VALID(unit, EGR_L3_INTFm, OPRI_OCFI_SELf)) { 1103 soc_mem_field32_set(unit, EGR_L3_INTFm, l3_if_entry_p, OPRI_OCFI_SELf, 0x0); 1104 } 1105 } else if (intf_info->vlan_qos.flags & BCM_L3_INTF_QOS_OUTER_VLAN_PRI_SET) { 1106 if (SOC_MEM_FIELD_VALID(unit, EGR_L3_INTFm, OPRI_OCFI_SELf)) { 1107 soc_mem_field32_set(unit, EGR_L3_INTFm, l3_if_entry_p, OPRI_OCFI_SELf, 0x1); 1108 soc_mem_field32_set(unit, EGR_L3_INTFm, l3_if_entry_p, OPRIf, 1109 intf_info->vlan_qos.pri); 1110 soc_mem_field32_set(unit, EGR_L3_INTFm, l3_if_entry_p, OCFIf, 1111 intf_info->vlan_qos.cfi); 1112 } 1113 } else if (intf_info->vlan_qos.flags & BCM_L3_INTF_QOS_OUTER_VLAN_PRI_REMARK) { 1114 1115 if (SOC_MEM_FIELD_VALID(unit, EGR_L3_INTFm, OPRI_OCFI_SELf)) { 1116 soc_mem_field32_set(unit, EGR_L3_INTFm, l3_if_entry_p, OPRI_OCFI_SELf, 0x2); 1117 } 1118 if (SOC_MEM_FIELD_VALID(unit, EGR_L3_INTFm, OPRI_OCFI_MAPPING_PROFILEf)) { 1119 BCM_IF_ERROR_RETURN 1120 (_bcm_tr2_qos_id2idx(unit, intf_info->vlan_qos.qos_map_id, &hw_map_idx)); 1121 soc_mem_field32_set(unit, EGR_L3_INTFm, l3_if_entry_p, 1122 OPRI_OCFI_MAPPING_PROFILEf, hw_map_idx); 1123 } 1124 } 1125 1126 if (intf_info->inner_vlan_qos.flags & BCM_L3_INTF_QOS_INNER_VLAN_PRI_COPY) { 1127 if (SOC_MEM_FIELD_VALID(unit, EGR_L3_INTFm, IPRI_ICFI_SELf)) { 1128 soc_mem_field32_set(unit, EGR_L3_INTFm, l3_if_entry_p, IPRI_ICFI_SELf, 0x0); 1129 } 1130 } else if (intf_info->inner_vlan_qos.flags & BCM_L3_INTF_QOS_INNER_VLAN_PRI_SET) { 1131 if (SOC_MEM_FIELD_VALID(unit, EGR_L3_INTFm, IPRI_ICFI_SELf)) { 1132 soc_mem_field32_set(unit, EGR_L3_INTFm, l3_if_entry_p, IPRI_ICFI_SELf, 0x1); 1133 soc_mem_field32_set(unit, EGR_L3_INTFm, l3_if_entry_p, IPRIf, 1134 intf_info->inner_vlan_qos.pri); 1135 soc_mem_field32_set(unit, EGR_L3_INTFm, l3_if_entry_p, ICFIf, 1136 intf_info->inner_vlan_qos.cfi); 1137 } 1138 } else if (intf_info->inner_vlan_qos.flags & BCM_L3_INTF_QOS_INNER_VLAN_PRI_REMARK) { 1139 if (SOC_MEM_FIELD_VALID(unit, EGR_L3_INTFm, IPRI_ICFI_SELf)) { 1140 soc_mem_field32_set(unit, EGR_L3_INTFm, l3_if_entry_p, IPRI_ICFI_SELf, 0x2); 1141 } 1142 if (SOC_MEM_FIELD_VALID(unit, EGR_L3_INTFm, IPRI_ICFI_MAPPING_PROFILEf)) { 1143 BCM_IF_ERROR_RETURN 1144 (_bcm_tr2_qos_id2idx(unit, intf_info->inner_vlan_qos.qos_map_id, &hw_map_idx)); 1145 soc_mem_field32_set(unit, EGR_L3_INTFm, l3_if_entry_p, 1146 IPRI_ICFI_MAPPING_PROFILEf, hw_map_idx); 1147 } 1148 } 1149 1150 if (intf_info->dscp_qos.flags & BCM_L3_INTF_QOS_DSCP_COPY) { 1151 if (SOC_MEM_FIELD_VALID(unit, EGR_L3_INTFm, DSCP_SELf)) { 1152 soc_mem_field32_set(unit, EGR_L3_INTFm, l3_if_entry_p, DSCP_SELf, 0x0); 1153 } 1154 } else if (intf_info->dscp_qos.flags & BCM_L3_INTF_QOS_DSCP_SET) { 1155 if (SOC_MEM_FIELD_VALID(unit, EGR_L3_INTFm, DSCP_SELf)) { 1156 soc_mem_field32_set(unit, EGR_L3_INTFm, l3_if_entry_p, DSCP_SELf, 0x1); 1157 soc_mem_field32_set(unit, EGR_L3_INTFm, l3_if_entry_p, DSCPf, 1158 intf_info->dscp_qos.dscp); 1159 } 1160 } else if (intf_info->dscp_qos.flags & BCM_L3_INTF_QOS_DSCP_REMARK) { 1161 if (SOC_MEM_FIELD_VALID(unit, EGR_L3_INTFm, DSCP_SELf)) { 1162 soc_mem_field32_set(unit, EGR_L3_INTFm, l3_if_entry_p, DSCP_SELf, 0x2); 1163 } 1164 if (SOC_MEM_FIELD_VALID(unit, EGR_L3_INTFm, DSCP_MAPPING_PTRf)) { 1165 BCM_IF_ERROR_RETURN 1166 (_bcm_tr2_qos_id2idx(unit, intf_info->dscp_qos.qos_map_id, &hw_map_idx)); 1167 soc_mem_field32_set(unit, EGR_L3_INTFm, l3_if_entry_p, 1168 DSCP_MAPPING_PTRf, hw_map_idx); 1169 } 1170 } 1171 return BCM_E_NONE; 1172 } 1173 1174 /* 1175 * Function: 1176 * _bcm_td_l3_intf_qos_get 1177 * Purpose: 1178 * Get L3 Interface QoS parameters 1179 * Parameters: 1180 * unit - (IN)SOC unit number. 1181 * l3_if_entry_p - entry buffer 1182 * vid - (IN) Intf_info 1183 * Returns: 1184 * BCM_E_XXX. 1185 */ 1186 int 1187 _bcm_td_l3_intf_qos_get(int unit, uint32 *l3_if_entry_p, _bcm_l3_intf_cfg_t *intf_info) 1188 { 1189 1190 /* Input parameters check */ 1191 if (NULL == intf_info) { 1192 return (BCM_E_PARAM); 1193 } 1194 1195 if (SOC_MEM_FIELD_VALID(unit, EGR_L3_INTFm, OPRI_OCFI_SELf)) { 1196 if (soc_mem_field32_get(unit, EGR_L3_INTFm, 1197 l3_if_entry_p, OPRI_OCFI_SELf) == 0x0) { 1198 intf_info->vlan_qos.flags |= BCM_L3_INTF_QOS_OUTER_VLAN_PRI_COPY; 1199 } else if (soc_mem_field32_get(unit, EGR_L3_INTFm, 1200 l3_if_entry_p, OPRI_OCFI_SELf) == 0x1) { 1201 intf_info->vlan_qos.flags |= BCM_L3_INTF_QOS_OUTER_VLAN_PRI_SET; 1202 intf_info->vlan_qos.pri = 1203 soc_mem_field32_get(unit, EGR_L3_INTFm, l3_if_entry_p, OPRIf); 1204 intf_info->vlan_qos.cfi = 1205 soc_mem_field32_get(unit, EGR_L3_INTFm, l3_if_entry_p, OCFIf); 1206 } else if (soc_mem_field32_get(unit, EGR_L3_INTFm, 1207 l3_if_entry_p, OPRI_OCFI_SELf) == 0x2) { 1208 intf_info->vlan_qos.flags |= BCM_L3_INTF_QOS_OUTER_VLAN_PRI_REMARK; 1209 BCM_IF_ERROR_RETURN 1210 (_bcm_tr2_qos_idx2id(unit, 1211 soc_mem_field32_get(unit, EGR_L3_INTFm, l3_if_entry_p, 1212 OPRI_OCFI_MAPPING_PROFILEf), 0x2, 1213 &intf_info->vlan_qos.qos_map_id)); 1214 } 1215 } 1216 1217 if (SOC_MEM_FIELD_VALID(unit, EGR_L3_INTFm, IPRI_ICFI_SELf)) { 1218 if (soc_mem_field32_get(unit, EGR_L3_INTFm, 1219 l3_if_entry_p, IPRI_ICFI_SELf) == 0x0) { 1220 intf_info->inner_vlan_qos.flags |= BCM_L3_INTF_QOS_INNER_VLAN_PRI_COPY; 1221 } else if (soc_mem_field32_get(unit, EGR_L3_INTFm, 1222 l3_if_entry_p, IPRI_ICFI_SELf) == 0x1) { 1223 intf_info->inner_vlan_qos.flags |= BCM_L3_INTF_QOS_INNER_VLAN_PRI_SET; 1224 intf_info->inner_vlan_qos.pri = 1225 soc_mem_field32_get(unit, EGR_L3_INTFm, l3_if_entry_p, IPRIf); 1226 intf_info->inner_vlan_qos.cfi = 1227 soc_mem_field32_get(unit, EGR_L3_INTFm, l3_if_entry_p, ICFIf); 1228 } else if (soc_mem_field32_get(unit, EGR_L3_INTFm, 1229 l3_if_entry_p, IPRI_ICFI_SELf) == 0x2) { 1230 intf_info->inner_vlan_qos.flags |= BCM_L3_INTF_QOS_INNER_VLAN_PRI_REMARK; 1231 BCM_IF_ERROR_RETURN 1232 (_bcm_tr2_qos_idx2id(unit, 1233 soc_mem_field32_get(unit, EGR_L3_INTFm, l3_if_entry_p, 1234 IPRI_ICFI_MAPPING_PROFILEf), 0x2, 1235 &intf_info->inner_vlan_qos.qos_map_id)); 1236 } 1237 } 1238 1239 1240 if (SOC_MEM_FIELD_VALID(unit, EGR_L3_INTFm, DSCP_SELf)) { 1241 if (soc_mem_field32_get(unit, EGR_L3_INTFm, 1242 l3_if_entry_p, DSCP_SELf) == 0x0) { 1243 intf_info->dscp_qos.flags |= BCM_L3_INTF_QOS_DSCP_COPY; 1244 } else if (soc_mem_field32_get(unit, EGR_L3_INTFm, 1245 l3_if_entry_p, DSCP_SELf) == 0x1) { 1246 intf_info->dscp_qos.flags |= BCM_L3_INTF_QOS_DSCP_SET; 1247 intf_info->dscp_qos.dscp = 1248 soc_mem_field32_get(unit, EGR_L3_INTFm, l3_if_entry_p, DSCPf); 1249 } else if (soc_mem_field32_get(unit, EGR_L3_INTFm, 1250 l3_if_entry_p, DSCP_SELf) == 0x2) { 1251 intf_info->dscp_qos.flags |= BCM_L3_INTF_QOS_DSCP_REMARK; 1252 BCM_IF_ERROR_RETURN 1253 (_bcm_tr2_qos_idx2id(unit, 1254 soc_mem_field32_get(unit, EGR_L3_INTFm, l3_if_entry_p, 1255 DSCP_MAPPING_PTRf), 0x4, 1256 &intf_info->dscp_qos.qos_map_id)); 1257 } 1258 } 1259 return BCM_E_NONE; 1260 } 1261 1262 /* 1263 * Function: 1264 * _bcm_td_l3_routed_int_pri_init 1265 * Purpose: 1266 * Set L3 Routed Internal Priority 1267 * Parameters: 1268 * unit - (IN)SOC unit number. 1269 * Returns: 1270 * BCM_E_XXX. 1271 */ 1272 1273 int 1274 _bcm_td_l3_routed_int_pri_init (int unit) 1275 { 1276 int rv=BCM_E_NONE; 1277 int idx; /* Iteration index. */ 1278 int max_ent_count=0; /* Number of entries to read.*/ 1279 ing_routed_int_pri_mapping_entry_t int_pri_entry; 1280 1281 1282 if(soc_mem_is_valid(unit, ING_ROUTED_INT_PRI_MAPPINGm)) { 1283 max_ent_count = soc_mem_index_count(unit, ING_ROUTED_INT_PRI_MAPPINGm); 1284 1285 for(idx=0; idx<max_ent_count; idx++) { 1286 1287 sal_memset(&int_pri_entry, 0, sizeof(ing_routed_int_pri_mapping_entry_t)); 1288 1289 soc_mem_field32_set(unit, ING_ROUTED_INT_PRI_MAPPINGm, &int_pri_entry, 1290 NEW_INT_PRIf, idx); 1291 1292 rv = soc_mem_write(unit, ING_ROUTED_INT_PRI_MAPPINGm, 1293 MEM_BLOCK_ALL, idx, &int_pri_entry); 1294 1295 if (rv < 0) { 1296 return rv; 1297 } 1298 } 1299 } 1300 return rv; 1301 } 1302 1303 #else /* BCM_TRIDENT_SUPPORT && INCLUDE_L3 */ 1304 int bcm_esw_trident_l3_not_empty; 1305 #endif /* BCM_TRIDENT_SUPPORT && INCLUDE_L3 */ 1306