l3.c (198690B)
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: Trident3 L3 functions implementation 9 */ 10 11 12 #include <shared/bsl.h> 13 14 #include <soc/defs.h> 15 #if defined(INCLUDE_L3) && defined(BCM_TRIDENT3_SUPPORT) 16 17 #include <soc/drv.h> 18 #include <soc/scache.h> 19 #include <bcm/vlan.h> 20 #include <bcm/error.h> 21 22 #include <bcm/l3.h> 23 #include <soc/l3x.h> 24 #include <soc/lpm.h> 25 #ifdef ALPM_ENABLE 26 #include <soc/alpm.h> 27 #include <soc/esw/alpm_int.h> 28 #endif 29 #include <bcm/tunnel.h> 30 #include <bcm/debug.h> 31 #include <bcm/error.h> 32 #include <bcm/stack.h> 33 #include <soc/mem.h> 34 #include <soc/format.h> 35 #include <soc/trident2.h> 36 #include <soc/tomahawk.h> 37 #include <soc/apache.h> 38 #include <soc/esw/flow_db.h> 39 #ifdef SOC_L3_ECMP_PROTECTED_ACCESS_SUPPORT 40 #include <soc/esw/ecmp.h> 41 #endif /* SOC_L3_ECMP_PROTECTED_ACCESS_SUPPORT */ 42 #include <bcm_int/esw/flow.h> 43 #include <bcm_int/esw/tomahawk.h> 44 #include <bcm_int/esw/trident2.h> 45 #include <bcm_int/esw/trident3.h> 46 #include <bcm_int/esw/firebolt.h> 47 #include <bcm_int/esw/triumph.h> 48 #include <bcm_int/esw/triumph2.h> 49 #include <bcm_int/esw/triumph3.h> 50 #include <bcm_int/esw/stack.h> 51 #include <bcm_int/esw/flex_ctr.h> 52 #include <bcm_int/esw_dispatch.h> 53 #include <bcm_int/esw/flex_ctr.h> 54 #include <bcm_int/esw/virtual.h> 55 #include <bcm_int/esw/trident2plus.h> 56 #include <bcm_int/esw/xgs5.h> 57 #include <bcm_int/esw/trx.h> 58 #include <bcm_int/esw/qos.h> 59 #include <bcm_int/common/multicast.h> 60 #include <soc/trident3.h> 61 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 62 #include <bcm_int/esw/trident2plus.h> 63 #endif /* BCM_TRIDENT2PLUS_SUPPORT */ 64 #ifdef BCM_HELIX5_SUPPORT 65 #include <soc/helix5.h> 66 #endif 67 68 #define _BCM_TD3_L3_MEM_BANKS_ALL (-1) 69 #define _BCM_TD3_HOST_ENTRY_NOT_FOUND (-1) 70 71 /* needed for software state of the vc_and_swap label */ 72 extern _bcm_tr_mpls_bookkeeping_t _bcm_tr_mpls_bk_info[BCM_MAX_NUM_UNITS]; 73 #define MPLS_INFO(_unit_) (&_bcm_tr_mpls_bk_info[_unit_]) 74 #define VC_AND_SWAP_TABLE_RESV_INDEX 0 75 76 77 static soc_profile_mem_t *_bcm_td3_macda_oui_profile[BCM_MAX_NUM_UNITS]; 78 static soc_profile_mem_t *_bcm_td3_vntag_etag_profile[BCM_MAX_NUM_UNITS]; 79 #define L3_EXT_VIEW_INVALID_VNTAG_ETAG_PROFILE 0 80 81 #ifdef BCM_WARM_BOOT_SUPPORT 82 /* bitmap of egress L3 intf, set indicates the intf is used by IPMC next hop */ 83 int *td3_l3_intf_next_hop_ipmc = NULL; 84 #endif 85 86 87 #ifdef SOC_L3_ECMP_PROTECTED_ACCESS_SUPPORT 88 #if 0 89 int 90 bcm_td3x_l3_ecmp_free_idx_get(int unit, 91 soc_esw_ecmp_bank_lkup_level_t level, 92 int count, 93 int *free_idx) 94 { 95 int bix = 0; 96 int rv = BCM_E_NONE; 97 uint32 bank_bmp = 0; 98 99 rv = soc_esw_ecmp_protected_banks_get(unit, 100 level, 101 &bank_bmp); 102 103 BCM_IF_ERROR_RETURN(rv); 104 105 for (bix = 0; bix < BCMI_L3_ECMP_MAX_BANKS(unit); bix++) { 106 if ((1 << bix) & bank_bmp) { 107 rv = soc_esw_ecmp_protected_idx_free_get(unit, 108 bix, 109 count, 110 free_idx); 111 if (rv == BCM_E_NONE) { 112 break; 113 } 114 } 115 } 116 117 return rv; 118 } 119 #endif 120 121 122 123 STATIC int 124 _bcmi_td3x_l3_ecmp_free_idx_attempt(int unit, 125 uint32 bank_bmp[], 126 int count, 127 int *free_idx) 128 { 129 int bix; 130 int rv = BCM_E_NONE; 131 132 for (bix = 0; bix < BCMI_L3_ECMP_MAX_BANKS(unit); bix++) { 133 if (SHR_BITGET(bank_bmp, bix)) { 134 rv = soc_esw_ecmp_protected_idx_free_get(unit, 135 bix, 136 count, 137 free_idx); 138 if (rv == BCM_E_NONE) { 139 break; 140 } 141 } 142 } 143 144 return rv; 145 } 146 147 int 148 bcm_td3x_l3_ecmp_free_idx_get(int unit, 149 soc_esw_ecmp_bank_lkup_level_t level, 150 int count, 151 int *free_idx) 152 { 153 int rv; 154 int bix; 155 int free_count = 0; 156 uint32 bank_bmp[1] = {0}; 157 158 /* Get banks mapped to the lkup level */ 159 rv = soc_esw_ecmp_protected_banks_get(unit, 160 level, 161 bank_bmp); 162 163 BCM_IF_ERROR_RETURN(rv); 164 165 /* Attempt to find a free idx that can fit the current group */ 166 rv = _bcmi_td3x_l3_ecmp_free_idx_attempt(unit, bank_bmp, count, free_idx); 167 168 if (rv == BCM_E_FULL) { 169 170 /* Compress ECMP member tables to make room for new group */ 171 for (bix = 0; bix < BCMI_L3_ECMP_MAX_BANKS(unit); bix++) { 172 if (SHR_BITGET(bank_bmp, bix)) { 173 rv = soc_esw_ecmp_bank_free_count_get(unit, 174 bix, 175 &free_count); 176 BCM_IF_ERROR_RETURN(rv); 177 178 if (free_count < count) { 179 continue; 180 } 181 182 rv = soc_esw_ecmp_protected_bank_defragment(unit, 183 bix, 184 -1, 185 &free_count); 186 BCM_IF_ERROR_RETURN(rv); 187 188 /* If the defragmented bank can fit the new group, break */ 189 if (free_count >= count) { 190 break; 191 } 192 } 193 } 194 195 if (free_count < count) { 196 return BCM_E_FULL; 197 } 198 199 bank_bmp[0] = 0; 200 rv = soc_esw_ecmp_protected_banks_get(unit, 201 level, 202 bank_bmp); 203 BCM_IF_ERROR_RETURN(rv); 204 205 /* Check if the free idx can be found now */ 206 rv = _bcmi_td3x_l3_ecmp_free_idx_attempt(unit, bank_bmp, count, free_idx); 207 } 208 209 return rv; 210 } 211 #endif /* SOC_L3_ECMP_PROTECTED_ACCESS_SUPPORT */ 212 213 214 /* 215 * Function: 216 * bcmi_td3_l3_nh_dest_set 217 * Purpose: 218 * Encode the destination value based on the gport. 219 * Parameters: 220 * unit - SOC device unit number 221 * Returns: 222 * BCM_E_NONE Success 223 * BCM_E_XXX ERROR 224 */ 225 226 int bcmi_td3_l3_nh_dest_set(int unit, bcm_l3_egress_t *nh_entry, uint32 *nh_dest) 227 { 228 int gport_type = 0, port = -1, gport = -1; 229 uint32 dest_type = SOC_MEM_FIF_DEST_DVP; 230 uint32 shift_val = 0; 231 int mc_group = 0; 232 233 if(nh_entry->flags2 & BCM_L3_FLAGS2_MC_GROUP){ 234 if (!_BCM_MULTICAST_IS_L3(nh_entry->mc_group)) { 235 return BCM_E_PARAM; 236 } 237 dest_type = SOC_MEM_FIF_DEST_IPMC; 238 mc_group = _BCM_MULTICAST_ID_GET(nh_entry->mc_group); 239 *nh_dest = _soc_mem_dest_value_construct(unit, dest_type, mc_group); 240 return BCM_E_NONE; 241 } 242 243 gport = nh_entry->port; 244 gport_type = BCMI_GPORT_TYPE_GET(gport); 245 246 switch(gport_type) { 247 case BCM_GPORT_VXLAN_PORT: 248 port = BCM_GPORT_VXLAN_PORT_ID_GET(gport); 249 break; 250 case BCM_GPORT_L2GRE_PORT: 251 port = BCM_GPORT_L2GRE_PORT_ID_GET(gport); 252 break; 253 case BCM_GPORT_MPLS_PORT: 254 port = BCM_GPORT_MPLS_PORT_ID_GET(gport); 255 break; 256 case BCM_GPORT_MIM_PORT: 257 port = BCM_GPORT_MIM_PORT_ID_GET(gport); 258 break; 259 case BCM_GPORT_FLOW_PORT: 260 port = BCM_GPORT_FLOW_PORT_ID_GET(gport); 261 break; 262 default: 263 if (nh_entry->flags & BCM_L3_TGID) { 264 int tid_is_vp_lag = 0; 265 if (soc_feature(unit, soc_feature_vp_lag)) { 266 (void)_bcm_esw_trunk_id_is_vp_lag(unit, gport, &tid_is_vp_lag); 267 } 268 269 if (tid_is_vp_lag) { 270 /* Get the VP value representing VP LAG */ 271 BCM_IF_ERROR_RETURN(_bcm_esw_trunk_tid_to_vp_lag_vp(unit, 272 gport, &port)); 273 274 } else { 275 dest_type = SOC_MEM_FIF_DEST_LAG; 276 port = gport; 277 } 278 } else { 279 dest_type = SOC_MEM_FIF_DEST_DGPP; 280 shift_val = SOC_MEM_FIF_DGPP_MOD_ID_SHIFT_BITS; 281 port = gport; 282 } 283 } 284 285 *nh_dest = _soc_mem_dest_value_construct(unit, dest_type, 286 nh_entry->module << shift_val | port); 287 288 return BCM_E_NONE; 289 } 290 291 /* 292 * Function: 293 * _bcm_td3_mpls_get_vc_and_swap_flex_table_index 294 * Purpose: 295 * Obtain Index into VC_AND_SWAP_TABLE 296 * A software hash is not maintained, so duplicates may be created. 297 * Parameters: 298 * IN : Unit 299 * IN : num_vc 300 * IN : mpls port entry 301 * IN : next hop entry 302 * IN : action 303 * OUT : vc_swap_index 304 * Returns: 305 * BCM_E_XXX 306 */ 307 STATIC int 308 _bcm_td3_mpls_get_vc_and_swap_flex_table_index (int unit, int *vc_swap_index) 309 { 310 int num_vc; 311 int imin; 312 int free_idx = 0, offset = 0; 313 314 imin = soc_mem_index_min(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm); 315 num_vc = soc_mem_index_count(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm); 316 317 /* we are dividng the table in half to manage counted and 318 * non-counted entries. 319 */ 320 num_vc /= 2; 321 322 /* Try getting index from 2nd half of MPLS_VC_AND_SWAP table */ 323 for (free_idx = imin; free_idx < num_vc + imin; free_idx++) { 324 if (!(_BCM_MPLS_VC_NON_COUNT_USED_GET(unit, free_idx) || 325 (soc_feature(unit, soc_feature_vc_and_swap_table_overlaid) && 326 _bcm_vp_used_get(unit, free_idx, _bcmVpTypeFlow)))) { 327 break; 328 } 329 } 330 331 if (free_idx == (num_vc + imin)) { 332 333 /* Get index from 1st half of MPLS_VC_AND_SWAP table */ 334 for (free_idx = imin; free_idx < num_vc + imin; free_idx++) { 335 if (!_BCM_MPLS_VC_COUNT_USED_GET(unit, free_idx - imin)) { 336 break; 337 } 338 } 339 if (free_idx == num_vc + imin) { 340 return BCM_E_RESOURCE; 341 } 342 _BCM_MPLS_VC_COUNT_USED_SET(unit, free_idx - imin); 343 offset = imin; 344 } else { 345 _BCM_MPLS_VC_NON_COUNT_USED_SET(unit, free_idx - imin); 346 offset = num_vc + imin; 347 } 348 349 *vc_swap_index = free_idx + offset; 350 351 /* Increase refcount on table idx */ 352 _bcm_tr_mpls_vc_and_swap_ref_count_adjust(unit, *vc_swap_index , 1); 353 354 return BCM_E_NONE; 355 } 356 357 #ifdef BCM_RIOT_SUPPORT 358 359 /* 360 * Function: 361 * _bcm_td3_vc_and_swap_table_dst_port_set 362 * Purpose: 363 * Set dgpp in vc and swap table for IFA 364 * Parameters: 365 * unit - (IN) SOC unit number. 366 * module - (IN) module id. 367 * port - (IN) port num. 368 * vc_swap_index - (IN) vc and swap table index 369 * Returns: 370 * BCM_X_XXX 371 */ 372 int 373 _bcm_td3_vc_and_swap_table_dst_port_set(int unit, bcm_module_t module, 374 bcm_port_t port, int vc_swap_index) 375 { 376 int idx = 0; 377 int rv = BCM_E_NONE; 378 uint32 view_id = 0; 379 uint32 flow_handle = 0; 380 uint32 flow_option = 0; 381 uint32 flex_data_array[128]; 382 uint32 flex_data_count; 383 uint32 process_vntag_p = 0; 384 uint32 process_vntag_dst_vif = 0; 385 uint32 vntag_p = 0; 386 uint32 vntag_dst_vif = 0; 387 egr_mpls_vc_and_swap_label_table_entry_t vc_entry; 388 389 SOC_IF_ERROR_RETURN( 390 soc_flow_db_flow_handle_get(unit, "IFA", &flow_handle)); 391 SOC_IF_ERROR_RETURN( 392 soc_flow_db_flow_option_id_get( 393 unit, flow_handle, "V6_DGPP_ASSIGN", &flow_option)); 394 395 SOC_IF_ERROR_RETURN(soc_flow_db_ffo_to_mem_view_id_get(unit, 396 flow_handle, flow_option, SOC_FLOW_DB_FUNC_EGRESS_LABEL_ID, &view_id)); 397 398 SOC_IF_ERROR_RETURN(soc_mem_read(unit, view_id, 399 MEM_BLOCK_ANY, vc_swap_index, &vc_entry)); 400 401 SOC_IF_ERROR_RETURN(soc_flow_db_mem_view_entry_init( 402 unit, view_id, (uint32*)&vc_entry)); 403 404 SOC_IF_ERROR_RETURN(soc_flow_db_mem_view_field_list_get( 405 unit, view_id, SOC_FLOW_DB_FIELD_TYPE_POLICY_DATA, 406 128, flex_data_array, &flex_data_count)); 407 408 for (idx = 0; idx < flex_data_count; idx++) { 409 switch (flex_data_array[idx]) { 410 case VNTAG_Pf: 411 process_vntag_p = 1; 412 break; 413 414 case VNTAG_DST_VIFf: 415 process_vntag_dst_vif = 1; 416 break; 417 418 default: 419 break; 420 } 421 } 422 423 if (process_vntag_p) { 424 vntag_p = (module >> BCMI_TD3_L3_NH_IFA_DST_PORT_SHIFT) & 0x1; 425 soc_mem_field32_set(unit, view_id, &vc_entry, VNTAG_Pf, vntag_p); 426 } 427 428 if (process_vntag_dst_vif) { 429 vntag_dst_vif = (port & BCMI_TD3_L3_NH_IFA_DST_PORT_MASK) | 430 ((module & BCMI_TD3_L3_NH_IFA_DST_PORT_MASK) << 431 BCMI_TD3_L3_NH_IFA_DST_PORT_SHIFT); 432 soc_mem_field32_set(unit, view_id, &vc_entry, VNTAG_DST_VIFf, vntag_dst_vif); 433 } 434 435 SOC_IF_ERROR_RETURN(soc_mem_write( 436 unit, view_id, MEM_BLOCK_ALL, vc_swap_index, &vc_entry)); 437 438 return rv; 439 } 440 441 /* 442 * Function: 443 * _bcm_td3_l3_flex_nh_add 444 * Purpose: 445 * Set L3 multicast / unicast next hop flex entry. 446 * Parameters: 447 * unit - (IN) SOC unit number. 448 * nh_index - (IN) Next hop index. 449 * l3_egress - (IN) L3 egress structure. 450 * ipmc - (IN) multicast 451 * Returns: 452 * BCM_X_XXX 453 */ 454 int 455 _bcm_td3_l3_flex_nh_add(int unit, int nh_index, 456 bcm_l3_egress_t *l3_egress, uint32 *egr_nh, 457 int ipmc) 458 { 459 int rv = BCM_E_NONE; 460 int i; 461 int macda_index = -1; 462 #ifdef BCM_RIOT_SUPPORT 463 uint32 vp; 464 #endif 465 uint32 view_id; 466 uint32 flex_data_array[128]; 467 uint32 flex_data_count; 468 uint32 opaque_array[_BCM_FLOW_LOGICAL_FIELD_MAX]; 469 uint32 opaque_count; 470 bcm_flow_logical_field_t* user_fields; 471 472 uint32 action_set = 0; 473 uint32 action_set_field = 0; 474 uint8 process_l2_edit_controls = 0; 475 uint8 process_switching_controls = 0; 476 uint8 process_profiled_assignment_dst_mac = 0; 477 uint8 process_higig_controls = 0; 478 uint8 process_higig_change_dest = 0; 479 uint8 process_ttl_a = 0; 480 uint8 process_intf = 0; 481 uint8 process_outer_mac_addr = 0; 482 uint8 process_inner_mac_addr = 0; 483 uint8 process_vxlt = 0; 484 uint8 process_class_id = 0; 485 uint8 process_next_ptr = 0; 486 487 /* 488 int flag_set; 489 uint32 flag_array[] = { 490 BCM_L3_MULTICAST_L2_DEST_PRESERVE, 491 BCM_L3_MULTICAST_L2_SRC_PRESERVE, 492 BCM_L3_MULTICAST_L2_VLAN_PRESERVE, 493 BCM_L3_MULTICAST_TTL_PRESERVE, 494 BCM_L3_MULTICAST_DEST_PRESERVE, 495 BCM_L3_MULTICAST_SRC_PRESERVE, 496 BCM_L3_MULTICAST_VLAN_PRESERVE, 497 BCM_L3_MULTICAST_L3_DROP, 498 BCM_L3_MULTICAST_L2_DROP 499 }; 500 soc_field_t field_array[] = { 501 L3MC__L2_MC_DA_DISABLEf, 502 L3MC__L2_MC_SA_DISABLEf, 503 L3MC__L2_MC_VLAN_DISABLEf, 504 L3MC__L3_MC_TTL_DISABLEf, 505 L3MC__L3_MC_DA_DISABLEf, 506 L3MC__L3_MC_SA_DISABLEf, 507 L3MC__L3_MC_VLAN_DISABLEf, 508 L3MC__L3_DROPf, 509 L3MC__L2_DROPf 510 }; 511 */ 512 513 /* Get view id corresponding to the specified flow. */ 514 rv = soc_flow_db_ffo_to_mem_view_id_get(unit, 515 l3_egress->flow_handle, 516 l3_egress->flow_option_handle, 517 SOC_FLOW_DB_FUNC_EGRESS_OBJ_ID, 518 &view_id); 519 BCM_IF_ERROR_RETURN(rv); 520 521 /* Configure the egress next hop entry */ 522 SOC_IF_ERROR_RETURN(soc_mem_read(unit, view_id, 523 MEM_BLOCK_ANY, nh_index, egr_nh)); 524 525 /* Initialize control field list for this view id. */ 526 rv = soc_flow_db_mem_view_entry_init(unit, view_id, egr_nh); 527 528 BCM_IF_ERROR_RETURN(rv); 529 530 /* Get logical field list for this view id. */ 531 rv = soc_flow_db_mem_view_field_list_get(unit, 532 view_id, 533 SOC_FLOW_DB_FIELD_TYPE_LOGICAL_POLICY_DATA, 534 _BCM_FLOW_LOGICAL_FIELD_MAX, 535 opaque_array, 536 &opaque_count); 537 BCM_IF_ERROR_RETURN(rv); 538 539 user_fields = l3_egress->logical_fields; 540 541 for (i=0; i<opaque_count; i++) { 542 if (user_fields[i].id == opaque_array[i]) { 543 soc_mem_field32_set(unit, view_id, egr_nh, user_fields[i].id, 544 user_fields[i].value); 545 } 546 } 547 548 /* Get PDD field list corresponding to the view id. */ 549 rv = soc_flow_db_mem_view_field_list_get(unit, 550 view_id, 551 SOC_FLOW_DB_FIELD_TYPE_POLICY_DATA, 552 128, 553 flex_data_array, 554 &flex_data_count); 555 BCM_IF_ERROR_RETURN(rv); 556 557 for (i=0; i<flex_data_count; i++) { 558 switch (flex_data_array[i]) { 559 case L2_EDIT_CONTROLS_ACTION_SETf: 560 process_l2_edit_controls = 1; 561 break; 562 case HIGIG_CONTROLS_ACTION_SETf: 563 process_higig_controls = 1; 564 break; 565 case HIGIG_CHANGE_DEST_ACTION_SETf: 566 process_higig_change_dest = 1; 567 break; 568 case SWITCHING_CTRLS_ACTION_SETf: 569 process_switching_controls = 1; 570 break; 571 case TTL_A_ACTION_SETf: 572 process_ttl_a = 1; 573 break; 574 case CLASS_ID_ACTION_SETf: 575 process_class_id = 1; 576 break; 577 case INTF_ACTION_SETf: 578 process_intf = 1; 579 break; 580 case DIRECT_ASSIGNMENT_6_ACTION_SETf: 581 process_outer_mac_addr = 1; 582 break; 583 case DIRECT_ASSIGNMENT_4_ACTION_SETf: 584 process_inner_mac_addr = 1; 585 break; 586 case PROFILED_ASSIGNMENT_DST_MAC_ADDRESS_ACTION_SETf: 587 process_profiled_assignment_dst_mac = 1; 588 break; 589 case VXLT_CLASS_IDf: 590 process_vxlt = 1; 591 break; 592 case NEXT_PTR_ACTION_SETf: 593 process_next_ptr = 1; 594 break; 595 default: 596 break; 597 } 598 } 599 600 if (process_vxlt) { 601 soc_mem_field32_set(unit, view_id, egr_nh, 602 VXLT_CLASS_IDf, l3_egress->intf_class); 603 } 604 605 if (process_higig_controls) { 606 action_set = 0; 607 soc_format_field32_set(unit, HIGIG_CONTROLS_ACTION_SETfmt, 608 &action_set, HG_HDR_SELf, 1); 609 610 soc_mem_field32_set(unit, view_id, egr_nh, 611 HIGIG_CONTROLS_ACTION_SETf, action_set); 612 } 613 614 /* Set interface id. */ 615 if (process_intf) { 616 617 action_set = 0; 618 soc_format_field32_set(unit, INTF_ACTION_SETfmt, 619 &action_set, INTF_TYPEf, 0); 620 /* INTF_NUMf */ 621 soc_format_field32_set(unit, INTF_ACTION_SETfmt, 622 &action_set, INTF_PTRf, l3_egress->intf); 623 soc_mem_field32_set(unit, view_id, egr_nh, 624 INTF_ACTION_SETf, action_set); 625 } 626 if (process_outer_mac_addr) { 627 /* L3UC__MAC_ADDRESSf */ 628 soc_mem_mac_addr_set(unit, view_id, egr_nh, 629 DIRECT_ASSIGNMENT_6_ACTION_SETf, 630 l3_egress->mac_addr); 631 } else if (process_inner_mac_addr) { 632 soc_mem_mac_addr_set(unit, view_id, egr_nh, 633 DIRECT_ASSIGNMENT_4_ACTION_SETf, 634 l3_egress->mac_addr); 635 } 636 #if 0 637 for (i = 0; i < COUNTOF(flag_array); i++) { 638 if (l3_egress->multicast_flags & flag_array[i]) { 639 flag_set = 1; 640 } else { 641 flag_set = 0; 642 } 643 if (soc_mem_field_valid(unit, EGR_L3_NEXT_HOPm, field_array[i])) { 644 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, egr_nh, 645 field_array[i], flag_set); 646 } else { 647 if (flag_set) { 648 return BCM_E_PARAM; 649 } 650 } 651 } 652 #endif 653 654 if (process_l2_edit_controls) { 655 action_set = 0; 656 if (ipmc) { 657 action_set_field = _SHR_IS_FLAG_SET(l3_egress->multicast_flags, 658 BCM_L3_MULTICAST_L2_VLAN_PRESERVE); 659 soc_format_field32_set(unit, L2_EDIT_CONTROLS_ACTION_SETfmt, 660 &action_set, VLAN_DISABLEf, /* L3MC__L2_MC_VLAN_DISABLEf */ 661 action_set_field); 662 action_set_field = _SHR_IS_FLAG_SET(l3_egress->multicast_flags, 663 BCM_L3_MULTICAST_L2_DEST_PRESERVE); 664 soc_format_field32_set(unit, L2_EDIT_CONTROLS_ACTION_SETfmt, 665 &action_set, MACDA_DISABLEf, /* L3MC__L2_MC_DA_DISABLEf */ 666 action_set_field); 667 action_set_field = _SHR_IS_FLAG_SET(l3_egress->multicast_flags, 668 BCM_L3_MULTICAST_L2_SRC_PRESERVE); 669 soc_format_field32_set(unit, L2_EDIT_CONTROLS_ACTION_SETfmt, 670 &action_set, MACSA_DISABLEf, /* L3MC__L2_MC_SA_DISABLEf */ 671 action_set_field); 672 } 673 else { 674 action_set_field = _SHR_IS_FLAG_SET(l3_egress->flags, BCM_L3_KEEP_VLAN); 675 soc_format_field32_set(unit, L2_EDIT_CONTROLS_ACTION_SETfmt, 676 &action_set, VLAN_DISABLEf, /* L3__L3_UC_VLAN_DISABLEf */ 677 action_set_field); 678 action_set_field = _SHR_IS_FLAG_SET(l3_egress->flags, BCM_L3_KEEP_DSTMAC); 679 soc_format_field32_set(unit, L2_EDIT_CONTROLS_ACTION_SETfmt, 680 &action_set, MACDA_DISABLEf, /* L3__L3_UC_DA_DISABLEf */ 681 action_set_field); 682 683 action_set_field = _SHR_IS_FLAG_SET(l3_egress->flags, BCM_L3_KEEP_SRCMAC); 684 soc_format_field32_set(unit, L2_EDIT_CONTROLS_ACTION_SETfmt, 685 &action_set, MACSA_DISABLEf, /* L3__L3_UC_SA_DISABLEf */ 686 action_set_field); 687 } 688 689 soc_mem_field32_set(unit, view_id, egr_nh, 690 L2_EDIT_CONTROLS_ACTION_SETf, action_set); 691 } 692 if (process_ttl_a) { 693 if (ipmc) { 694 soc_mem_field32_set(unit, view_id, egr_nh, 695 TTL_A_ACTION_SETf, /* L3MC__L3_MC_TTL_DISABLEf */ 696 _SHR_IS_FLAG_SET(l3_egress->multicast_flags, BCM_L3_MULTICAST_TTL_PRESERVE)); 697 } 698 else { 699 soc_mem_field32_set(unit, view_id, egr_nh, 700 TTL_A_ACTION_SETf, /* L3__L3_UC_TTL_DISABLEf */ 701 _SHR_IS_FLAG_SET(l3_egress->flags, BCM_L3_KEEP_TTL)); 702 } 703 } 704 705 if (process_class_id) { 706 soc_mem_field32_set(unit, view_id, egr_nh, 707 CLASS_ID_ACTION_SETf, /* L3__CLASS_IDf */ 708 l3_egress->intf_class); 709 } 710 711 if (process_next_ptr && (l3_egress->flags2 & BCM_L3_FLAGS2_IFA_DST_PORT)) { 712 int vc_swap_index = 0; 713 if (l3_egress->port > (1 << BCMI_TD3_L3_NH_IFA_DST_PORT_SHIFT)) { 714 return BCM_E_PARAM; 715 } 716 BCM_IF_ERROR_RETURN( 717 _bcm_td3_mpls_get_vc_and_swap_flex_table_index(unit, &vc_swap_index)); 718 BCM_IF_ERROR_RETURN( 719 _bcm_td3_vc_and_swap_table_dst_port_set( 720 unit, l3_egress->module, l3_egress->port, vc_swap_index)); 721 722 action_set = 0; 723 soc_format_field32_set(unit, NEXT_PTR_ACTION_SETfmt, 724 &action_set, NEXT_PTR_TYPEf, 725 BCMI_TD3_L3_NH_EGR_NEXT_PTR_TYPE_DVP_AND_VC_SWAP); 726 soc_format_field32_set(unit, NEXT_PTR_ACTION_SETfmt, 727 &action_set, NEXT_PTRf, vc_swap_index); 728 soc_mem_field32_set(unit, view_id, egr_nh, 729 NEXT_PTR_ACTION_SETf, action_set); 730 } 731 732 if (soc_feature(unit, soc_feature_virtual_port_routing)) { 733 if (l3_egress->encap_id > 0 && 734 l3_egress->encap_id < BCM_XGS3_EGRESS_IDX_MIN(unit)) { 735 /* encap_id contains the virtual port value if it's greater than 0 and 736 * less than the starting value of egress object ID. 737 */ 738 if (process_next_ptr) { 739 action_set = 0; 740 soc_format_field32_set(unit, NEXT_PTR_ACTION_SETfmt, 741 &action_set, NEXT_PTR_TYPEf, 742 BCMI_L3_NH_EGR_NEXT_PTR_TYPE_DVP); 743 /* L3__DVPf */ 744 soc_format_field32_set(unit, NEXT_PTR_ACTION_SETfmt, 745 &action_set, NEXT_PTRf, 746 l3_egress->encap_id); 747 soc_mem_field32_set(unit, view_id, egr_nh, 748 NEXT_PTR_ACTION_SETf, action_set); 749 } 750 /* no support for _bcmVpTypeNiv, _bcmVpTypeExtender in flexflow */ 751 } else if (l3_egress->encap_id >= BCM_XGS3_EGRESS_IDX_MIN(unit)) { 752 return BCM_E_PARAM; 753 } 754 } 755 756 /* for SD-Tag & L3MC views */ 757 if (process_switching_controls) { 758 if (ipmc) { 759 action_set = 0; 760 action_set_field = _SHR_IS_FLAG_SET(l3_egress->multicast_flags, BCM_L3_MULTICAST_L3_DROP); 761 soc_format_field32_set(unit, SWITCHING_CTRLS_ACTION_SETfmt, 762 &action_set, L3_DROPf, /* L3MC__L3_DROPf */ 763 action_set_field); 764 action_set_field = _SHR_IS_FLAG_SET(l3_egress->multicast_flags, BCM_L3_MULTICAST_L2_DROP); 765 soc_format_field32_set(unit, SWITCHING_CTRLS_ACTION_SETfmt, 766 &action_set, L2_DROPf, /* L3MC__L2_DROPf */ 767 action_set_field); 768 769 } 770 else { 771 action_set_field = _SHR_IS_FLAG_SET(l3_egress->multicast_flags, BCM_L3_MULTICAST_L3_DROP); 772 soc_format_field32_set(unit, SWITCHING_CTRLS_ACTION_SETfmt, 773 &action_set, BC_DROPf, /* SD_TAG__BC_DROPf */ 774 action_set_field); 775 776 action_set_field = _SHR_IS_FLAG_SET(l3_egress->multicast_flags, BCM_L3_MULTICAST_L2_DROP); 777 soc_format_field32_set(unit, SWITCHING_CTRLS_ACTION_SETfmt, 778 &action_set, UUC_DROPf, /* SD_TAG__UUC_DROPf */ 779 action_set_field); 780 781 action_set_field = _SHR_IS_FLAG_SET(l3_egress->multicast_flags, BCM_L3_MULTICAST_L2_DROP); 782 soc_format_field32_set(unit, SWITCHING_CTRLS_ACTION_SETfmt, 783 &action_set, UMC_DROPf, /* SD_TAG__UMC_DROPf */ 784 action_set_field); 785 786 } 787 soc_mem_field32_set(unit, view_id, egr_nh, 788 SWITCHING_CTRLS_ACTION_SETf, action_set); 789 } 790 791 /* Write IPUC entry in caller _bcm_fb_nh_add, otherwise continue for IPMC */ 792 if (ipmc == 0) { 793 return (BCM_E_NONE); 794 } 795 796 #ifdef BCM_RIOT_SUPPORT 797 /* 798 * TD2Plus has multi layer routing. 799 * The multicast packet can be routed in the overlay 800 * layer and then underlay encapsulation is performed. 801 * To achieve this, there will be overlay egr nexthop association 802 * with undelray egress next hop. 803 * the overlay egr nexthop will point to underlay next hop. 804 */ 805 if (process_next_ptr && 806 BCMI_RIOT_IS_ENABLED(unit) && 807 _bcm_vp_vfi_type_vp_get(unit, l3_egress->port, (int *)&vp)) { 808 /* This is a overlay NH case */ 809 ing_dvp_table_entry_t dvp; 810 int vp_nh_index; 811 /* Get the vp */ 812 SOC_IF_ERROR_RETURN 813 (READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp, &dvp)); 814 815 /* read vp to get next hop */ 816 vp_nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, 817 NEXT_HOP_INDEXf); 818 819 /* 820 * check if nh-nh association is needed. 821 * else set up nh-dvp association 822 * NH-NH association will be done for all the 823 * nhs other than SDTAG which does not modify any packets field. 824 * e.g. on access ports, it may be needed to change a vlan/tpid, 825 * in that case, we may have to set nh-nh association else we may 826 * setup vlan/tpid from DVP. 827 */ 828 if (bcmi_l3_nh_assoc_ol_ul_link_is_required(unit, vp_nh_index)) { 829 action_set = 0; 830 action_set_field = BCMI_L3_NH_EGR_NEXT_PTR_TYPE_NH; 831 soc_format_field32_set(unit, NEXT_PTR_ACTION_SETfmt, 832 &action_set, NEXT_PTR_TYPEf, /* L3MC__NEXT_PTR_TYPEf */ 833 action_set_field); 834 action_set_field = (uint32)vp_nh_index; 835 soc_format_field32_set(unit, NEXT_PTR_ACTION_SETfmt, 836 &action_set, NEXT_PTRf, 837 action_set_field); /* L3MC__NEXT_PTRf */ 838 /* Set up the association of NHs in sw */ 839 BCM_IF_ERROR_RETURN( 840 bcmi_l3_nh_assoc_ol_ul_link_sw_add(unit, nh_index, 841 vp_nh_index)); 842 } else { 843 action_set = 0; 844 action_set_field = BCMI_L3_NH_EGR_NEXT_PTR_TYPE_DVP; 845 soc_format_field32_set(unit, NEXT_PTR_ACTION_SETfmt, 846 &action_set, NEXT_PTR_TYPEf, /* L3MC__NEXT_PTR_TYPEf */ 847 action_set_field); 848 soc_format_field32_set(unit, NEXT_PTR_ACTION_SETfmt, 849 &action_set, NEXT_PTRf, 850 vp); /* L3MC__NEXT_PTRf */ 851 } 852 soc_mem_field32_set(unit, view_id, egr_nh, 853 NEXT_PTR_ACTION_SETf, action_set); 854 } 855 #endif 856 857 /* 858 * TD2Plus has a overlaid mac_address. 859 * This mac_address field may be overlaid by some other fields 860 * used for CoE/HG feature. Meanwhile a mac_da_profile_index 861 * is present for the actual mac_address. 862 * This index points to EGR_MAC_DA_PROFILE, which is managed in 863 * Profile mechanism. 864 */ 865 #ifdef BCM_HGPROXY_COE_SUPPORT 866 if (process_higig_change_dest && 867 _bcm_xgs5_subport_coe_mod_port_local(unit, l3_egress->module, 868 l3_egress->port)) { 869 870 action_set = 0; 871 action_set_field = l3_egress->module; 872 soc_format_field32_set(unit, HIGIG_CHANGE_DEST_ACTION_SETfmt, 873 &action_set, HG_MC_DST_MODIDf, /* L3MC__HG_MC_DST_MODIDf */ 874 action_set_field); 875 action_set_field = l3_egress->port; 876 soc_format_field32_set(unit, HIGIG_CHANGE_DEST_ACTION_SETfmt, 877 &action_set, HG_MC_DST_PORT_NUMf, /* L3MC__HG_MC_DST_PORT_NUMf */ 878 action_set_field); 879 soc_mem_field32_set(unit, view_id, egr_nh, 880 HIGIG_CHANGE_DEST_ACTION_SETf, action_set); 881 882 } 883 #endif 884 if (process_profiled_assignment_dst_mac) { 885 egr_mac_da_profile_entry_t macda; 886 void *entries[1] = { NULL }; 887 888 sal_memset(&macda, 0, sizeof(egr_mac_da_profile_entry_t)); 889 soc_mem_mac_addr_set(unit, EGR_MAC_DA_PROFILEm, 890 &macda, MAC_ADDRESSf, l3_egress->mac_addr); 891 entries[0] = &macda; 892 rv = _bcm_mac_da_profile_entry_add(unit, entries, 1, 893 (uint32 *)&macda_index); 894 if (BCM_FAILURE(rv)) { 895 goto cleanup; 896 } 897 /* L3MC__MAC_DA_PROFILE_INDEXf */ 898 soc_mem_field32_set(unit, view_id, egr_nh, 899 EGR_MAC_ADDRESS_PROFILEf, macda_index); 900 } 901 else { 902 if (!BCM_MAC_IS_ZERO(l3_egress->mac_addr)) { 903 if (!soc_feature(unit, soc_feature_ipmc_use_configured_dest_mac)) { 904 return BCM_E_CONFIG; 905 } 906 } 907 } 908 909 rv = soc_mem_write(unit, view_id, 910 MEM_BLOCK_ALL, nh_index, egr_nh); 911 if (BCM_FAILURE(rv)) { 912 goto cleanup; 913 } 914 return BCM_E_NONE; 915 916 cleanup: 917 if (macda_index != -1) { 918 (void) _bcm_mac_da_profile_entry_delete(unit, macda_index); 919 } 920 return rv; 921 } 922 /* 923 * Function: 924 * __bcm_td3_l3_flex_nh_entry_parse 925 * Purpose: 926 * Parse the Flex NextHop table entry info. 927 * Parameters: 928 * unit - (IN) SOC unit number. 929 * egr_entry_ptr - (IN) Egress next hop table entry. 930 * index - (IN) Next hop index. 931 * nh_entry - (OUT) Next hop entry info. 932 * Returns: 933 * BCM_E_XXX 934 */ 935 int 936 _bcm_td3_l3_flex_nh_entry_parse(int unit, uint32 *egr_entry_ptr, 937 uint32 index, bcm_l3_egress_t *nh_entry) 938 { 939 940 int rv = BCM_E_NONE; 941 uint32 view_id; 942 uint32 flex_data_array[128]; 943 uint32 flex_data_count; 944 int ipmc=0; 945 int nh_index_out; 946 int i; 947 _bcm_l3_intf_cfg_t intf_info; 948 int ret_val; 949 uint32 next_ptr_type; 950 uint32 next_ptr; 951 952 bcm_flow_logical_field_t* user_fields; 953 uint32 opaque_array[_BCM_FLOW_LOGICAL_FIELD_MAX]; 954 uint32 opaque_count; 955 uint32 action_set = 0; 956 uint32 action_set_field = 0; 957 soc_flow_db_ffo_t ffo[SOC_FLOW_DB_MAX_VIEW_FFO_TPL]; 958 uint32 num_ffo = 0; 959 960 uint8 process_l2_edit_controls = 0; 961 uint8 process_switching_controls = 0; 962 uint8 process_profiled_assignment_dst_mac = 0; 963 uint8 process_ttl_a = 0; 964 uint8 process_next_ptr = 0; 965 uint8 process_intf = 0; 966 uint8 process_mac_addr = 0; 967 uint8 process_class_id = 0; 968 uint8 process_vxlt = 0; 969 uint8 process_inner_mac_addr = 0; 970 uint32 data_type; 971 uint32 intf_type = 0; 972 973 /* Input parameters check */ 974 if (NULL == nh_entry) { 975 return (BCM_E_PARAM); 976 } 977 978 if (NULL == egr_entry_ptr) { 979 return (BCM_E_PARAM); 980 } 981 982 /* Get view id corresponding to the specified flow. */ 983 if (nh_entry->flow_handle != 0) { 984 BCM_IF_ERROR_RETURN( 985 soc_flow_db_ffo_to_mem_view_id_get(unit, 986 nh_entry->flow_handle, 987 nh_entry->flow_option_handle, 988 SOC_FLOW_DB_FUNC_EGRESS_OBJ_ID, 989 &view_id)); 990 } 991 else { 992 data_type = soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, 993 egr_entry_ptr, DATA_TYPEf); 994 995 BCM_IF_ERROR_RETURN( 996 soc_flow_db_mem_to_view_id_get(unit, 997 EGR_L3_NEXT_HOPm, 998 SOC_FLOW_DB_KEY_TYPE_INVALID, 999 data_type, 1000 0, 1001 NULL, 1002 &view_id)); 1003 1004 /* Get the flow handle, function id, option id */ 1005 BCM_IF_ERROR_RETURN( 1006 soc_flow_db_mem_view_to_ffo_get(unit, 1007 view_id, 1008 SOC_FLOW_DB_MAX_VIEW_FFO_TPL, 1009 ffo, 1010 &num_ffo)); 1011 nh_entry->flow_handle = ffo[0].flow_handle; 1012 nh_entry->flow_option_handle = ffo[0].option_id; 1013 } 1014 1015 /* Get logical field list for this view id. */ 1016 rv = soc_flow_db_mem_view_field_list_get(unit, 1017 view_id, 1018 SOC_FLOW_DB_FIELD_TYPE_LOGICAL_POLICY_DATA, 1019 _BCM_FLOW_LOGICAL_FIELD_MAX, 1020 opaque_array, 1021 &opaque_count); 1022 BCM_IF_ERROR_RETURN(rv); 1023 1024 user_fields = nh_entry->logical_fields; 1025 1026 for (i=0; i<opaque_count; i++) { 1027 user_fields[i].id = opaque_array[i]; 1028 user_fields[i].value = soc_mem_field32_get(unit, view_id, egr_entry_ptr, opaque_array[i]); 1029 } 1030 1031 /* Get PDD field list corresponding to the view id. */ 1032 rv = soc_flow_db_mem_view_field_list_get(unit, 1033 view_id, 1034 SOC_FLOW_DB_FIELD_TYPE_POLICY_DATA, 1035 128, 1036 flex_data_array, 1037 &flex_data_count); 1038 BCM_IF_ERROR_RETURN(rv); 1039 1040 for (i=0; i<flex_data_count; i++) { 1041 switch (flex_data_array[i]) { 1042 case L2_EDIT_CONTROLS_ACTION_SETf: 1043 process_l2_edit_controls = 1; 1044 break; 1045 case SWITCHING_CTRLS_ACTION_SETf: 1046 process_switching_controls = 1; 1047 break; 1048 case TTL_A_ACTION_SETf: 1049 process_ttl_a = 1; 1050 break; 1051 case HIGIG_CONTROLS_ACTION_SETf: 1052 break; 1053 case CLASS_ID_ACTION_SETf: 1054 process_class_id = 1; 1055 break; 1056 case INTF_ACTION_SETf: 1057 process_intf = 1; 1058 break; 1059 case DIRECT_ASSIGNMENT_6_ACTION_SETf: 1060 process_mac_addr = 1; 1061 break; 1062 case PROFILED_ASSIGNMENT_DST_MAC_ADDRESS_ACTION_SETf: 1063 process_profiled_assignment_dst_mac = 1; 1064 break; 1065 case VXLT_CLASS_IDf: 1066 process_vxlt = 1; 1067 break; 1068 case NEXT_PTR_ACTION_SETf: 1069 process_next_ptr = 1; 1070 break; 1071 case DIRECT_ASSIGNMENT_4_ACTION_SETf: 1072 process_inner_mac_addr = 1; 1073 break; 1074 default: 1075 /* Unrecongnized acion set or new ones */ 1076 break; 1077 } 1078 } 1079 1080 if (process_vxlt) { 1081 nh_entry->intf_class = soc_mem_field32_get(unit, view_id, egr_entry_ptr, 1082 VXLT_CLASS_IDf); 1083 } 1084 1085 if (process_l2_edit_controls) { 1086 action_set = soc_mem_field32_get(unit, view_id, egr_entry_ptr, 1087 L2_EDIT_CONTROLS_ACTION_SETf); 1088 1089 if (soc_format_field32_get(unit, L2_EDIT_CONTROLS_ACTION_SETfmt, 1090 &action_set, L3_UC_VLAN_DISABLEf)) { 1091 /* L3__L3_UC_VLAN_DISABLEf */ 1092 nh_entry->flags |= BCM_L3_KEEP_VLAN; 1093 } 1094 1095 if (soc_format_field32_get(unit, L2_EDIT_CONTROLS_ACTION_SETfmt, 1096 &action_set, L3_UC_DA_DISABLEf)) { 1097 /* L3__L3_UC_DA_DISABLEf */ 1098 nh_entry->flags |= BCM_L3_KEEP_DSTMAC; 1099 } 1100 1101 if (soc_format_field32_get(unit, L2_EDIT_CONTROLS_ACTION_SETfmt, 1102 &action_set, L3_UC_SA_DISABLEf)) { 1103 /* L3__L3_UC_SA_DISABLEf */ 1104 nh_entry->flags |= BCM_L3_KEEP_SRCMAC; 1105 } 1106 if (soc_format_field32_get(unit, L2_EDIT_CONTROLS_ACTION_SETfmt, 1107 &action_set, MACDA_DISABLEf)) { 1108 /* L3MC__L2_MC_DA_DISABLEf */ 1109 nh_entry->flags |= BCM_L3_MULTICAST_L2_DEST_PRESERVE; 1110 } 1111 if (soc_format_field32_get(unit, L2_EDIT_CONTROLS_ACTION_SETfmt, 1112 &action_set, MACSA_DISABLEf)) { 1113 /* L3MC__L2_MC_SA_DISABLEf */ 1114 nh_entry->flags |= BCM_L3_MULTICAST_L2_SRC_PRESERVE; 1115 } 1116 if (soc_format_field32_get(unit, L2_EDIT_CONTROLS_ACTION_SETfmt, 1117 &action_set, VLAN_DISABLEf)) { 1118 /* L3MC__L2_MC_VLAN_DISABLEf */ 1119 nh_entry->flags |= BCM_L3_MULTICAST_L2_VLAN_PRESERVE; 1120 } 1121 } 1122 1123 if (process_intf) { 1124 action_set = soc_mem_field32_get(unit, view_id, egr_entry_ptr, 1125 INTF_ACTION_SETf); 1126 1127 action_set_field = soc_format_field32_get(unit, INTF_ACTION_SETfmt, 1128 &action_set, INTF_PTRf); /* INTF_NUMf */ 1129 nh_entry->intf = action_set_field; 1130 intf_type = soc_format_field32_get(unit, INTF_ACTION_SETfmt, 1131 &action_set, INTF_TYPEf); 1132 1133 /* determine if this is an IPMC entry from the l3 interface */ 1134 #ifdef BCM_WARM_BOOT_SUPPORT 1135 if (SOC_WARM_BOOT(unit)) { 1136 if((td3_l3_intf_next_hop_ipmc != NULL) && 1137 SHR_BITSET(td3_l3_intf_next_hop_ipmc, nh_entry->intf )){ 1138 ipmc = 1; 1139 } 1140 } else 1141 #endif 1142 { 1143 _bcm_th_ipmc_l3_intf_next_hop_get(unit, nh_entry->intf, 1144 &nh_index_out); 1145 if (nh_index_out == -2) { 1146 ipmc = 1; 1147 } 1148 } 1149 1150 } 1151 if (nh_entry->intf == BCM_XGS3_L3_L2CPU_INTF_IDX(unit)) { 1152 nh_entry->flags |= BCM_L3_L2TOCPU; 1153 } 1154 if (process_intf && intf_type == 0) { 1155 /* Now get the vlan */ 1156 sal_memset(&intf_info, 0x0, sizeof(intf_info)); 1157 intf_info.l3i_index = nh_entry->intf; 1158 1159 if (BCM_XGS3_L3_HWCALL_CHECK(unit, if_get)) { 1160 BCM_XGS3_L3_MODULE_LOCK(unit); 1161 ret_val = BCM_XGS3_L3_HWCALL_EXEC(unit, if_get) (unit, 1162 &intf_info); 1163 BCM_XGS3_L3_MODULE_UNLOCK(unit); 1164 BCM_IF_ERROR_RETURN(ret_val); 1165 nh_entry->vlan = intf_info.l3i_vid; 1166 } 1167 } 1168 1169 if (process_profiled_assignment_dst_mac) { 1170 int macda_idx; 1171 egr_mac_da_profile_entry_t macda; 1172 1173 macda_idx = soc_mem_field32_get(unit, view_id, egr_entry_ptr, 1174 EGR_MAC_ADDRESS_PROFILEf); 1175 1176 /* Read entry from MAC-DA-PROFILEm */ 1177 BCM_IF_ERROR_RETURN (soc_mem_read(unit, EGR_MAC_DA_PROFILEm, 1178 MEM_BLOCK_ANY, macda_idx, &macda)); 1179 1180 /* Obtain Mac-Address */ 1181 soc_mem_mac_addr_get(unit, EGR_MAC_DA_PROFILEm, 1182 &macda, MAC_ADDRESSf, nh_entry->mac_addr); 1183 1184 } 1185 else if (process_mac_addr) { 1186 /* L3MC__MAC_ADDRESSf */ 1187 soc_mem_mac_addr_get(unit, view_id, egr_entry_ptr, 1188 DIRECT_ASSIGNMENT_6_ACTION_SETf, 1189 nh_entry->mac_addr); 1190 } 1191 else if (process_inner_mac_addr) { 1192 soc_mem_mac_addr_set(unit, view_id, egr_entry_ptr, 1193 DIRECT_ASSIGNMENT_4_ACTION_SETf, 1194 nh_entry->mac_addr); 1195 } 1196 1197 if (process_ttl_a) { 1198 if (soc_mem_field32_get(unit, view_id, egr_entry_ptr, 1199 TTL_A_ACTION_SETf)) { 1200 if (ipmc) { 1201 /* L3MC__L3_MC_TTL_DISABLEf */ 1202 nh_entry->flags |= BCM_L3_MULTICAST_TTL_PRESERVE; 1203 } 1204 else { 1205 /* L3__L3_UC_TTL_DISABLEf */ 1206 nh_entry->flags |= BCM_L3_KEEP_TTL; 1207 } 1208 } 1209 } 1210 1211 if (process_switching_controls) { 1212 action_set = soc_mem_field32_get(unit, view_id, egr_entry_ptr, 1213 SWITCHING_CTRLS_ACTION_SETf); 1214 1215 if (soc_format_field32_get(unit, SWITCHING_CTRLS_ACTION_SETfmt, 1216 &action_set, L3_DROPf)) { 1217 /* L3MC__L3_DROPf */ 1218 nh_entry->flags |= BCM_L3_MULTICAST_L3_DROP; 1219 } 1220 if (soc_format_field32_get(unit, SWITCHING_CTRLS_ACTION_SETfmt, 1221 &action_set, L2_DROPf)) { 1222 /* L3MC__L2_DROPf */ 1223 nh_entry->flags |= BCM_L3_MULTICAST_L2_DROP; 1224 } 1225 } 1226 1227 if (process_next_ptr) { 1228 action_set = soc_mem_field32_get(unit, view_id, egr_entry_ptr, 1229 NEXT_PTR_ACTION_SETf); 1230 1231 /* L3MC__NEXT_PTR_TYPEf */ 1232 action_set_field = 1233 soc_format_field32_get(unit, NEXT_PTR_ACTION_SETfmt, 1234 &action_set, NEXT_PTR_TYPEf); 1235 1236 next_ptr_type = action_set_field; 1237 action_set_field = 1238 soc_format_field32_get(unit, NEXT_PTR_ACTION_SETfmt, 1239 &action_set, NEXT_PTRf); 1240 1241 next_ptr = action_set_field; 1242 if (next_ptr_type == BCMI_L3_NH_EGR_NEXT_PTR_TYPE_DVP) { 1243 nh_entry->encap_id = next_ptr; 1244 } 1245 else if (next_ptr_type == 1246 BCMI_TD3_L3_NH_EGR_NEXT_PTR_TYPE_VC_SWAP) { 1247 int vc_swap_idx = next_ptr; 1248 1249 if (vc_swap_idx > 0) { /* 0th entry is the default */ 1250 /* Read entry from EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm */ 1251 1252 BCM_IF_ERROR_RETURN ( 1253 _bcm_td3_mpls_gre_label_get (unit, vc_swap_idx, nh_entry)); 1254 } 1255 else { 1256 nh_entry->mpls_label = BCM_MPLS_LABEL_INVALID; 1257 } 1258 } 1259 } 1260 1261 if (process_class_id) { /* L3__CLASS_IDf */ 1262 nh_entry->intf_class = 1263 soc_mem_field32_get(unit, view_id, egr_entry_ptr, 1264 CLASS_ID_ACTION_SETf); 1265 } 1266 1267 if (ipmc) { 1268 nh_entry->flags |= BCM_L3_IPMC; 1269 } 1270 1271 return (BCM_E_NONE); 1272 } 1273 1274 /* 1275 * Function: 1276 * bcmi_td3_get_port_from_destination 1277 * Purpose: 1278 * Decodes the destination value based on programmed field. 1279 * Parameters: 1280 * unit - SOC device unit number 1281 * Returns: 1282 * BCM_E_NONE Success 1283 * BCM_E_XXX ERROR 1284 */ 1285 int bcmi_td3_get_port_from_destination(int unit, uint32 dest, 1286 bcm_l3_egress_t *nh) 1287 { 1288 int vp; 1289 uint32 dt, dval; 1290 1291 _soc_mem_dest_value_resolve(unit, dest, &dt, &dval); 1292 1293 switch(dt) { 1294 case SOC_MEM_FIF_DEST_LAG: 1295 nh->port = dval; 1296 nh->flags |= BCM_L3_TGID; 1297 break; 1298 case SOC_MEM_FIF_DEST_DGPP: 1299 nh->port = dval; 1300 break; 1301 case SOC_MEM_FIF_DEST_DVP: 1302 vp = dval; 1303 _bcm_vp_encode_gport(unit, vp, &(nh->port)); 1304 break; 1305 case SOC_MEM_FIF_DEST_IPMC: 1306 _BCM_MULTICAST_GROUP_SET(nh->mc_group, 1307 _BCM_MULTICAST_TYPE_L3, dval); 1308 nh->flags2 |= BCM_L3_FLAGS2_MC_GROUP; 1309 break; 1310 default: 1311 nh->port = dest; 1312 } 1313 1314 return BCM_E_NONE; 1315 1316 } 1317 1318 #endif /* BCM_RIOT_SUPPORT */ 1319 1320 /* 1321 * Function: 1322 * _bcm_td3_l3_flex_intf_opri_ocfi_set 1323 * Purpose: 1324 * Set L3 Interface OVLAN QoS parameters 1325 * Parameters: 1326 * unit - (IN)SOC unit number. 1327 * view_id - (IN) memory view 1328 * l3_if_entry_p - (IN) Pointer to buffer 1329 * vid - (IN) Intf_info 1330 * Returns: 1331 * BCM_E_XXX. 1332 */ 1333 STATIC int 1334 _bcm_td3_l3_flex_intf_opri_ocfi_set(int unit, uint32 view_id, uint32 *l3_if_entry_p, _bcm_l3_intf_cfg_t *intf_info) 1335 { 1336 int hw_map_idx=0; 1337 1338 uint32 action_set = 0; 1339 1340 /* Input parameters check */ 1341 if (NULL == intf_info) { 1342 return (BCM_E_PARAM); 1343 } 1344 1345 if (intf_info->vlan_qos.flags & BCM_L3_INTF_QOS_OUTER_VLAN_PRI_COPY) { 1346 /* OPRI_OCFI_SELf */ 1347 soc_format_field32_set(unit, OTAG_ACTION_SETfmt, 1348 &action_set, PCP_DE_SELf, 0x0); 1349 1350 } else if (intf_info->vlan_qos.flags & BCM_L3_INTF_QOS_OUTER_VLAN_PRI_SET) { 1351 /* OPRI_OCFI_SELf */ 1352 soc_format_field32_set(unit, OTAG_ACTION_SETfmt, 1353 &action_set, PCP_DE_SELf, 0x1); 1354 /* OPRIf */ 1355 soc_format_field32_set(unit, OTAG_ACTION_SETfmt, 1356 &action_set, PCPf, intf_info->vlan_qos.pri); 1357 /* OCFIf */ 1358 soc_format_field32_set(unit, OTAG_ACTION_SETfmt, 1359 &action_set, DEf, intf_info->vlan_qos.cfi); 1360 1361 } else if (intf_info->vlan_qos.flags & BCM_L3_INTF_QOS_OUTER_VLAN_PRI_REMARK) { 1362 /* OPRI_OCFI_SELf */ 1363 soc_format_field32_set(unit, OTAG_ACTION_SETfmt, 1364 &action_set, PCP_DE_SELf, 0x2); 1365 1366 BCM_IF_ERROR_RETURN 1367 (_bcm_tr2_qos_id2idx(unit, intf_info->vlan_qos.qos_map_id, 1368 &hw_map_idx)); 1369 /* OPRI_OCFI_MAPPING_PROFILEf */ 1370 soc_format_field32_set(unit, OTAG_ACTION_SETfmt, 1371 &action_set, PCP_DE_MAPPING_PTRf, 1372 hw_map_idx); 1373 } 1374 1375 soc_mem_field32_set(unit, view_id, l3_if_entry_p, 1376 OTAG_ACTION_SETf, action_set); 1377 1378 return BCM_E_NONE; 1379 } 1380 /* 1381 * Function: 1382 * _bcm_td3_l3_flex_intf_ipri_icfi_set 1383 * Purpose: 1384 * Set L3 Interface IVLAN QoS parameters 1385 * Parameters: 1386 * unit - (IN)SOC unit number. 1387 * view_id - (IN) memory view 1388 * l3_if_entry_p - (IN) Pointer to buffer 1389 * vid - (IN) Intf_info 1390 * Returns: 1391 * BCM_E_XXX. 1392 */ 1393 STATIC int 1394 _bcm_td3_l3_flex_intf_ipri_icfi_set(int unit, uint32 view_id, uint32 *l3_if_entry_p, _bcm_l3_intf_cfg_t *intf_info) 1395 { 1396 int hw_map_idx=0; 1397 uint32 action_set = 0; 1398 1399 /* Input parameters check */ 1400 if (NULL == intf_info) { 1401 return (BCM_E_PARAM); 1402 } 1403 1404 if (intf_info->inner_vlan_qos.flags & BCM_L3_INTF_QOS_INNER_VLAN_PRI_COPY) { 1405 /* IPRI_OCFI_SELf */ 1406 soc_format_field32_set(unit, ITAG_ACTION_SETfmt, &action_set, 1407 PCP_DE_SELf, 0x0); 1408 1409 } else if (intf_info->inner_vlan_qos.flags & BCM_L3_INTF_QOS_INNER_VLAN_PRI_SET) { 1410 /* IPRI_OCFI_SELf */ 1411 soc_format_field32_set(unit, ITAG_ACTION_SETfmt, &action_set, 1412 PCP_DE_SELf, 0x1); 1413 /* IPRIf */ 1414 soc_format_field32_set(unit, ITAG_ACTION_SETfmt, 1415 &action_set, PCPf, intf_info->vlan_qos.pri); 1416 /* ICFIf */ 1417 soc_format_field32_set(unit, ITAG_ACTION_SETfmt, &action_set, 1418 DEf, intf_info->vlan_qos.cfi); 1419 1420 } else if (intf_info->inner_vlan_qos.flags & BCM_L3_INTF_QOS_INNER_VLAN_PRI_REMARK) { 1421 /* IPRI_OCFI_SELf */ 1422 soc_format_field32_set(unit, ITAG_ACTION_SETfmt, &action_set, 1423 PCP_DE_SELf, 0x2); 1424 1425 BCM_IF_ERROR_RETURN 1426 (_bcm_tr2_qos_id2idx(unit, intf_info->vlan_qos.qos_map_id, 1427 &hw_map_idx)); 1428 /* IPRI_ICFI_MAPPING_PROFILEf */ 1429 soc_format_field32_set(unit, ITAG_ACTION_SETfmt, &action_set, 1430 PCP_DE_MAPPING_PTRf, hw_map_idx); 1431 1432 } 1433 1434 soc_mem_field32_set(unit, view_id, l3_if_entry_p, 1435 ITAG_ACTION_SETf, action_set); 1436 1437 return BCM_E_NONE; 1438 } 1439 /* 1440 * Function: 1441 * _bcm_td3_l3_flex_intf_dscp_set 1442 * Purpose: 1443 * Set L3 Interface DSCP parameters 1444 * Parameters: 1445 * unit - (IN)SOC unit number. 1446 * view_id - (IN) memory view 1447 * l3_if_entry_p - (IN) Pointer to buffer 1448 * vid - (IN) Intf_info 1449 * Returns: 1450 * BCM_E_XXX. 1451 */ 1452 STATIC int 1453 _bcm_td3_l3_flex_intf_dscp_set(int unit, uint32 view_id, uint32 *l3_if_entry_p, _bcm_l3_intf_cfg_t *intf_info) 1454 { 1455 int hw_map_idx=0; 1456 uint32 action_set = 0; 1457 1458 /* Input parameters check */ 1459 if (NULL == intf_info) { 1460 return (BCM_E_PARAM); 1461 } 1462 1463 if (intf_info->dscp_qos.flags & BCM_L3_INTF_QOS_DSCP_COPY) { 1464 /* DSCP_SELf */ 1465 soc_format_field32_set(unit, QOS_A_ACTION_SETfmt, 1466 &action_set, QOS_ACTION_SELf, 0x0); 1467 } else if (intf_info->dscp_qos.flags & BCM_L3_INTF_QOS_DSCP_SET) { 1468 /* DSCP_SELf */ 1469 soc_format_field32_set(unit, QOS_A_ACTION_SETfmt, &action_set, 1470 QOS_ACTION_SELf, 0x1); 1471 /* DSCPf */ 1472 soc_format_field32_set(unit, QOS_A_ACTION_SETfmt, 1473 &action_set, QOS_VALUE_OR_MAPPING_PTR_OR_ZONE_IDf, 1474 intf_info->dscp_qos.dscp); 1475 } else if (intf_info->dscp_qos.flags & BCM_L3_INTF_QOS_DSCP_REMARK) { 1476 /* DSCP_SELf */ 1477 soc_format_field32_set(unit, QOS_A_ACTION_SETfmt, 1478 &action_set, QOS_ACTION_SELf, 0x2); 1479 BCM_IF_ERROR_RETURN 1480 (_bcm_tr2_qos_id2idx(unit, intf_info->dscp_qos.qos_map_id, 1481 &hw_map_idx)); 1482 /* DSCP_MAPPING_PTRf */ 1483 soc_format_field32_set(unit, QOS_A_ACTION_SETfmt, &action_set, 1484 QOS_VALUE_OR_MAPPING_PTR_OR_ZONE_IDf, 1485 hw_map_idx); 1486 } 1487 1488 soc_mem_field32_set(unit, view_id, l3_if_entry_p, 1489 QOS_A_ACTION_SETf, action_set); 1490 1491 return BCM_E_NONE; 1492 } 1493 1494 /* 1495 * Function: 1496 * _bcm_td3_l3_flex_intf_add 1497 * Purpose: 1498 * Add an entry to L3 interface table. 1499 * Parameters: 1500 * unit - (IN)SOC unit number. 1501 * intf_info - (IN)Interface information. 1502 * l3_if_entry_p - (IN) Write buffer address. 1503 * Returns: 1504 * BCM_E_XXX 1505 */ 1506 int 1507 _bcm_td3_l3_flex_intf_add(int unit, _bcm_l3_intf_cfg_t *intf_info, uint32 *l3_if_entry_p) 1508 { 1509 int rv = BCM_E_NONE; 1510 int i; 1511 uint32 view_id; 1512 uint32 flex_data_array[128]; 1513 uint32 flex_data_count; 1514 uint32 opaque_array[_BCM_FLOW_LOGICAL_FIELD_MAX]; 1515 uint32 opaque_count; 1516 bcm_flow_logical_field_t* user_fields; 1517 1518 uint32 action_set = 0; 1519 uint8 process_fwd_domain = 0; 1520 uint8 process_otag = 0; 1521 uint8 process_itag = 0; 1522 uint8 process_dscp = 0; 1523 uint8 process_tag_action_profile = 0; 1524 uint8 process_tunnel_ptr = 0; 1525 uint8 process_class_id = 0; 1526 uint8 process_vxlt = 0; 1527 uint8 process_outer_sa = 0; 1528 uint8 process_inner_sa = 0; 1529 uint8 process_ttl_b = 0; 1530 uint8 process_ttl_a = 0; 1531 uint8 process_svp = 0; 1532 bcm_vlan_action_set_t action; 1533 uint32 profile_idx; 1534 uint8 process_outer_sa_profile = 0; 1535 1536 /* Input parameters check */ 1537 if (NULL == intf_info) { 1538 return (BCM_E_PARAM); 1539 } 1540 1541 if (NULL == l3_if_entry_p) { 1542 return (BCM_E_PARAM); 1543 } 1544 1545 /* Get memory fields information. 1546 fld = (_bcm_l3_intf_fields_t *)BCM_XGS3_L3_MEM_FIELDS(unit, intf); 1547 */ 1548 1549 /* Get view id corresponding to the specified flow. */ 1550 rv = soc_flow_db_ffo_to_mem_view_id_get(unit, 1551 intf_info->flow_handle, 1552 intf_info->flow_option_handle, 1553 SOC_FLOW_DB_FUNC_EGRESS_INTF_ID, 1554 &view_id); 1555 BCM_IF_ERROR_RETURN(rv); 1556 1557 /* Initialize control field list for this view id. */ 1558 rv = soc_flow_db_mem_view_entry_init(unit, view_id, l3_if_entry_p); 1559 1560 BCM_IF_ERROR_RETURN(rv); 1561 1562 /* Get logical field list for this view id. */ 1563 rv = soc_flow_db_mem_view_field_list_get(unit, 1564 view_id, 1565 SOC_FLOW_DB_FIELD_TYPE_LOGICAL_POLICY_DATA, 1566 _BCM_FLOW_LOGICAL_FIELD_MAX, 1567 opaque_array, 1568 &opaque_count); 1569 BCM_IF_ERROR_RETURN(rv); 1570 1571 user_fields = intf_info->logical_fields; 1572 1573 for (i=0; i<opaque_count; i++) { 1574 if (user_fields[i].id == opaque_array[i]) { 1575 soc_mem_field32_set(unit, view_id, l3_if_entry_p, user_fields[i].id, 1576 user_fields[i].value); 1577 } 1578 } 1579 1580 /* Get PDD field list corresponding to the view id. */ 1581 rv = soc_flow_db_mem_view_field_list_get(unit, 1582 view_id, 1583 SOC_FLOW_DB_FIELD_TYPE_POLICY_DATA, 1584 128, 1585 flex_data_array, 1586 &flex_data_count); 1587 BCM_IF_ERROR_RETURN(rv); 1588 1589 for (i=0; i<flex_data_count; i++) { 1590 switch (flex_data_array[i]) { 1591 case FWD_DOMAIN_ACTION_SETf: 1592 process_fwd_domain = 1; 1593 break; 1594 case OTAG_ACTION_SETf: 1595 process_otag = 1; 1596 break; 1597 case ITAG_ACTION_SETf: 1598 process_itag = 1; 1599 break; 1600 case QOS_A_ACTION_SETf: 1601 process_dscp = 1; 1602 break; 1603 case TAG_ACTION_PROFILE_ACTION_SETf: 1604 process_tag_action_profile = 1; 1605 break; 1606 case TUNNEL_PTR_ACTION_SETf: 1607 process_tunnel_ptr = 1; 1608 break; 1609 case CLASS_ID_ACTION_SETf: 1610 process_class_id = 1; 1611 break; 1612 case VXLT_CLASS_IDf: 1613 process_vxlt = 1; 1614 break; 1615 case DIRECT_ASSIGNMENT_7_ACTION_SETf: 1616 process_outer_sa = 1; 1617 break; 1618 case DIRECT_ASSIGNMENT_5_ACTION_SETf: 1619 process_inner_sa = 1; 1620 break; 1621 case TTL_B_ACTION_SETf: 1622 process_ttl_b = 1; 1623 break; 1624 case TTL_A_ACTION_SETf: 1625 process_ttl_a = 1; 1626 break; 1627 case SVP_ACTION_SETf: 1628 process_svp = 1; 1629 break; 1630 case PROFILED_ASSIGNMENT_SRC_MAC_ADDRESS_ACTION_SETf: 1631 process_outer_sa_profile = 1; 1632 break; 1633 default: 1634 /* Unrecongnized acion set */ 1635 break; 1636 } 1637 } 1638 1639 if (process_vxlt) { 1640 soc_mem_field32_set(unit, view_id, l3_if_entry_p, 1641 VXLT_CLASS_IDf, intf_info->l3i_class); 1642 } 1643 1644 /* Set mac address. */ 1645 if (process_outer_sa) { 1646 /* fld->mac_addr */ 1647 soc_mem_mac_addr_set(unit, view_id, l3_if_entry_p, 1648 DIRECT_ASSIGNMENT_7_ACTION_SETf, 1649 intf_info->l3i_mac_addr); 1650 } else if (process_inner_sa) { 1651 soc_mem_mac_addr_set(unit, view_id, l3_if_entry_p, 1652 DIRECT_ASSIGNMENT_5_ACTION_SETf, 1653 intf_info->l3i_mac_addr); 1654 } else if (process_outer_sa_profile) { 1655 egr_mac_da_profile_entry_t mac_addr; 1656 uint32 mac_idx ; 1657 void *entries[1]; 1658 1659 sal_memset(&mac_addr, 0, sizeof(egr_mac_da_profile_entry_t)); 1660 soc_mem_mac_addr_set(unit, EGR_MAC_DA_PROFILEm, 1661 &mac_addr, MAC_ADDRESSf, intf_info->l3i_mac_addr); 1662 entries[0] = &mac_addr; 1663 BCM_IF_ERROR_RETURN(_bcm_mac_da_profile_entry_add(unit, 1664 entries, 1, &mac_idx)); 1665 soc_mem_field32_set(unit, view_id, l3_if_entry_p, 1666 PROFILED_ASSIGNMENT_SRC_MAC_ADDRESS_ACTION_SETf, mac_idx); 1667 } 1668 #ifdef BCM_RIOT_SUPPORT 1669 if (BCMI_L3_INTF_OVERLAY_VALID(unit)) { 1670 int svp = intf_info->l3i_source_vp; 1671 if (BCM_GPORT_IS_VXLAN_PORT(svp)) { 1672 svp = BCM_GPORT_VXLAN_PORT_ID_GET(svp); 1673 } else if (BCM_GPORT_IS_L2GRE_PORT(svp)) { 1674 svp = BCM_GPORT_L2GRE_PORT_ID_GET(svp); 1675 } else if (BCM_GPORT_IS_FLOW_PORT(svp)) { 1676 svp = BCM_GPORT_FLOW_PORT_ID_GET(svp); 1677 } else if (BCM_GPORT_IS_MIM_PORT(svp)) { 1678 svp = BCM_GPORT_MIM_PORT_ID_GET(svp); 1679 } else if (BCM_GPORT_IS_MPLS_PORT(svp)) { 1680 svp = BCM_GPORT_MPLS_PORT_ID_GET(svp); 1681 } 1682 1683 if (process_svp) { 1684 soc_mem_field32_set(unit, view_id, l3_if_entry_p, 1685 SVP_ACTION_SETf, svp); /* SVPf */ 1686 } 1687 1688 if (process_fwd_domain) { 1689 action_set = 0; 1690 1691 /* VLAN_VFI_OVERLAY_TYPEf */ 1692 soc_format_field32_set(unit, FWD_DOMAIN_ACTION_SETfmt, 1693 &action_set, FORWARDING_DOMAIN_TYPEf, 1694 BCMI_RIOT_VPN_VFI_IS_SET(unit, intf_info->l3i_vid) ? 0x2 : 0x1 ); 1695 1696 if (BCMI_RIOT_VPN_VFI_IS_SET(unit, intf_info->l3i_vid)) { 1697 int vfi_idx = 0; 1698 _BCM_VPN_GET(vfi_idx, _BCM_VPN_TYPE_VFI, intf_info->l3i_vid); 1699 /* VFIf */ 1700 soc_format_field32_set(unit, FWD_DOMAIN_ACTION_SETfmt, 1701 &action_set, FORWARDING_DOMAINf, vfi_idx); 1702 } else { 1703 /* fld->vlan_id */ 1704 soc_format_field32_set(unit, FWD_DOMAIN_ACTION_SETfmt, 1705 &action_set, FORWARDING_DOMAINf, intf_info->l3i_vid); 1706 } 1707 soc_mem_field32_set(unit, view_id, l3_if_entry_p, 1708 FWD_DOMAIN_ACTION_SETf, action_set); 1709 } 1710 } else 1711 #endif 1712 { 1713 /* Set vlan id. */ 1714 if (process_fwd_domain) { 1715 action_set = 0; 1716 /* fld->vlan_id */ 1717 soc_format_field32_set(unit, FWD_DOMAIN_ACTION_SETfmt, 1718 &action_set, FORWARDING_DOMAINf, intf_info->l3i_vid); 1719 soc_format_field32_set(unit, FWD_DOMAIN_ACTION_SETfmt, 1720 &action_set, FORWARDING_DOMAIN_TYPEf, 0x1 ); 1721 1722 soc_mem_field32_set(unit, view_id, l3_if_entry_p, 1723 FWD_DOMAIN_ACTION_SETf, action_set); 1724 } 1725 } 1726 /* Set Time To Live. */ 1727 if (process_ttl_b) { 1728 action_set = 0; 1729 /* fld->ttl */ 1730 soc_format_field32_set(unit, TTL_B_ACTION_SETfmt, 1731 &action_set, TTL_THRESHOLDf, intf_info->l3i_ttl); 1732 1733 soc_mem_field32_set(unit, view_id, l3_if_entry_p, 1734 TTL_B_ACTION_SETf, action_set); 1735 } else if (process_ttl_a) { 1736 1737 soc_mem_field32_set(unit, view_id, l3_if_entry_p, 1738 TTL_A_ACTION_SETf, intf_info->l3i_ttl? 1: 0); 1739 } 1740 1741 /* Set tunnel index. */ 1742 if (process_tunnel_ptr) { 1743 action_set = 0; 1744 /* fld->tnl_id */ 1745 soc_format_field32_set(unit, TUNNEL_PTR_ACTION_SETfmt, 1746 &action_set, TUNNEL_INDEXf, intf_info->l3i_tunnel_idx); 1747 1748 soc_mem_field32_set(unit, view_id, l3_if_entry_p, 1749 TUNNEL_PTR_ACTION_SETf, action_set); 1750 } 1751 1752 /* Set L2 bridging only flag. */ 1753 if (intf_info->l3i_flags & BCM_L3_L2ONLY) { 1754 /* fld->l2_switch not supported in flex view */ 1755 return BCM_E_PARAM; 1756 } 1757 1758 if (process_class_id) { 1759 /* fld->class_id */ 1760 soc_mem_field32_set(unit, view_id, l3_if_entry_p, 1761 CLASS_ID_ACTION_SETf, intf_info->l3i_class); 1762 } 1763 1764 if (process_itag && intf_info->l3i_inner_vlan) { 1765 1766 if (!process_tag_action_profile) { 1767 return BCM_E_INTERNAL; 1768 } 1769 action_set = 0; 1770 /* IVIDf, IVID_VALIDf */ 1771 soc_format_field32_set(unit, ITAG_ACTION_SETfmt, 1772 &action_set, VIDf, intf_info->l3i_inner_vlan); 1773 1774 soc_mem_field32_set(unit, view_id, l3_if_entry_p, 1775 ITAG_ACTION_SETf, action_set); 1776 } 1777 1778 /* QoS */ 1779 if (process_otag) { 1780 BCM_IF_ERROR_RETURN 1781 (_bcm_td3_l3_flex_intf_opri_ocfi_set(unit, view_id, l3_if_entry_p, 1782 intf_info)); 1783 if (intf_info->l3i_vid) { /* XXX need to check not VFI */ 1784 action_set = soc_mem_field32_get(unit, view_id, l3_if_entry_p, 1785 OTAG_ACTION_SETf); 1786 soc_format_field32_set(unit, OTAG_ACTION_SETfmt, 1787 &action_set, VIDf, intf_info->l3i_vid); 1788 soc_mem_field32_set(unit, view_id, l3_if_entry_p, 1789 OTAG_ACTION_SETf, action_set); 1790 } 1791 } 1792 if (process_itag) { 1793 BCM_IF_ERROR_RETURN 1794 (_bcm_td3_l3_flex_intf_ipri_icfi_set(unit, view_id, l3_if_entry_p, 1795 intf_info)); 1796 } 1797 if (process_dscp) { 1798 BCM_IF_ERROR_RETURN 1799 (_bcm_td3_l3_flex_intf_dscp_set(unit, view_id, l3_if_entry_p, 1800 intf_info)); 1801 } 1802 1803 bcm_vlan_action_set_t_init(&action); 1804 1805 /* Program Inner VLAN handling actions */ 1806 if (process_tag_action_profile) { 1807 if (intf_info->l3i_intf_flags & BCM_L3_INTF_INNER_VLAN_DO_NOT_MODIFY) { 1808 /* IVID_PRESENT_ACTIONf */ 1809 action.dt_inner = bcmVlanActionNone; 1810 /* IVID_ABSENT_ACTIONf */ 1811 action.ot_inner = bcmVlanActionNone; 1812 } else { 1813 if (intf_info->l3i_intf_flags & BCM_L3_INTF_INNER_VLAN_ADD) { 1814 if (intf_info->l3i_intf_flags & 1815 BCM_L3_INTF_INNER_VLAN_REPLACE) { 1816 1817 /*IVID_PRESENT_ACTIONf*/ 1818 action.dt_inner = bcmVlanActionReplace; 1819 1820 } else if (intf_info->l3i_intf_flags & 1821 1822 BCM_L3_INTF_INNER_VLAN_DELETE) { 1823 1824 /* IVID_PRESENT_ACTIONf */ 1825 action.dt_inner = bcmVlanActionDelete; 1826 } else { 1827 action.dt_inner = bcmVlanActionNone; 1828 } 1829 /* IVID_ABSENT_ACTIONf */ 1830 action.ot_inner = bcmVlanActionAdd; 1831 } else { 1832 if (intf_info->l3i_intf_flags & BCM_L3_INTF_INNER_VLAN_REPLACE) { 1833 1834 action.dt_inner = bcmVlanActionReplace; 1835 action.ot_inner = bcmVlanActionNone; 1836 } else { 1837 if (intf_info->l3i_intf_flags & BCM_L3_INTF_INNER_VLAN_DELETE) { 1838 1839 action.dt_inner = bcmVlanActionDelete; 1840 action.ot_inner = bcmVlanActionNone; 1841 } 1842 } 1843 } 1844 } 1845 if (intf_info->l3i_vid) { /* XXX need to check not VFI */ 1846 action.ut_outer = bcmVlanActionAdd; 1847 action.ut_outer_pkt_prio = bcmVlanActionAdd; 1848 action.ut_outer_cfi = bcmVlanActionAdd; 1849 } 1850 1851 BCM_IF_ERROR_RETURN 1852 (_bcm_trx_egr_vlan_action_profile_entry_add(unit, &action, &profile_idx)); 1853 1854 action_set = 0; 1855 soc_format_field32_set(unit, TAG_ACTION_PROFILE_ACTION_SETfmt, 1856 &action_set, TAG_ACTION_PROFILE_PTRf, profile_idx); 1857 1858 soc_mem_field32_set(unit, view_id, l3_if_entry_p, 1859 TAG_ACTION_PROFILE_ACTION_SETf, action_set); 1860 1861 } 1862 1863 return (BCM_E_NONE); 1864 1865 } 1866 1867 /* 1868 * Function: 1869 * _bcm_td3_l3_intf_flex_opri_ocfi_get 1870 * Purpose: 1871 * Get L3 Interface OVLAN QoS parameters for flex views 1872 * Parameters: 1873 * unit - (IN)SOC unit number. 1874 * view_id - (IN) memory view 1875 * l3_if_entry_p - entry buffer 1876 * vid - (IN) Intf_info 1877 * Returns: 1878 * BCM_E_XXX. 1879 */ 1880 STATIC int 1881 _bcm_td3_l3_intf_flex_opri_ocfi_get(int unit, uint32 view_id, uint32 *l3_if_entry_p, _bcm_l3_intf_cfg_t *intf_info) 1882 { 1883 uint32 action_set; 1884 1885 /* Input parameters check */ 1886 if (NULL == intf_info) { 1887 return (BCM_E_PARAM); 1888 } 1889 1890 action_set = soc_mem_field32_get(unit, view_id, l3_if_entry_p, 1891 OTAG_ACTION_SETf); 1892 1893 if (soc_format_field32_get(unit, OTAG_ACTION_SETfmt, 1894 &action_set, PCP_DE_SELf) == 0x0) { /* OPRI_OCFI_SELf */ 1895 intf_info->vlan_qos.flags |= BCM_L3_INTF_QOS_OUTER_VLAN_PRI_COPY; 1896 } else if (soc_format_field32_get(unit, OTAG_ACTION_SETfmt, 1897 &action_set, PCP_DE_SELf) == 0x1) { /* OPRI_OCFI_SELf */ 1898 intf_info->vlan_qos.flags |= BCM_L3_INTF_QOS_OUTER_VLAN_PRI_SET; 1899 /* OPRIf */ 1900 intf_info->vlan_qos.pri = 1901 soc_format_field32_get(unit, OTAG_ACTION_SETfmt, &action_set, PCPf); 1902 /* OCFIf */ 1903 intf_info->vlan_qos.cfi = 1904 soc_format_field32_get(unit, OTAG_ACTION_SETfmt, &action_set, DEf); 1905 } else if (soc_format_field32_get(unit, OTAG_ACTION_SETfmt, 1906 &action_set, PCP_DE_SELf) == 0x2) { /* OPRI_OCFI_SELf */ 1907 intf_info->vlan_qos.flags |= BCM_L3_INTF_QOS_OUTER_VLAN_PRI_REMARK; 1908 BCM_IF_ERROR_RETURN 1909 (_bcm_tr2_qos_idx2id(unit, 1910 soc_format_field32_get(unit, OTAG_ACTION_SETfmt, 1911 &action_set, PCP_DE_MAPPING_PTRf), 0x2, 1912 &intf_info->vlan_qos.qos_map_id)); 1913 } 1914 1915 return BCM_E_NONE; 1916 } 1917 /* 1918 * Function: 1919 * _bcm_td3_l3_intf_flex_ipri_icfi_get 1920 * Purpose: 1921 * Get L3 Interface IVLAN QoS parameters for flex views 1922 * Parameters: 1923 * unit - (IN)SOC unit number. 1924 * view_id - (IN) memory view 1925 * l3_if_entry_p - entry buffer 1926 * vid - (IN) Intf_info 1927 * Returns: 1928 * BCM_E_XXX. 1929 */ 1930 STATIC int 1931 _bcm_td3_l3_intf_flex_ipri_icfi_get(int unit, uint32 view_id, uint32 *l3_if_entry_p, _bcm_l3_intf_cfg_t *intf_info) 1932 { 1933 uint32 action_set; 1934 1935 /* Input parameters check */ 1936 if (NULL == intf_info) { 1937 return (BCM_E_PARAM); 1938 } 1939 1940 action_set = soc_mem_field32_get(unit, view_id, l3_if_entry_p, 1941 ITAG_ACTION_SETf); 1942 1943 if (soc_format_field32_get(unit, ITAG_ACTION_SETfmt, 1944 &action_set, PCP_DE_SELf) == 0x0) { /* IPRI_ICFI_SELf */ 1945 intf_info->inner_vlan_qos.flags |= BCM_L3_INTF_QOS_INNER_VLAN_PRI_COPY; 1946 } else if (soc_format_field32_get(unit, ITAG_ACTION_SETfmt, 1947 &action_set, PCP_DE_SELf) == 0x1) { /* IPRI_ICFI_SELf */ 1948 intf_info->inner_vlan_qos.flags |= BCM_L3_INTF_QOS_INNER_VLAN_PRI_SET; 1949 /* OPRIf */ 1950 intf_info->inner_vlan_qos.pri = 1951 soc_format_field32_get(unit, ITAG_ACTION_SETfmt, &action_set, PCPf); 1952 /* OCFIf */ 1953 intf_info->inner_vlan_qos.cfi = 1954 soc_format_field32_get(unit, ITAG_ACTION_SETfmt, &action_set, DEf); 1955 } else if (soc_format_field32_get(unit, ITAG_ACTION_SETfmt, 1956 &action_set, PCP_DE_SELf) == 0x2) { /* IPRI_ICFI_SELf */ 1957 intf_info->inner_vlan_qos.flags |= BCM_L3_INTF_QOS_INNER_VLAN_PRI_REMARK; 1958 BCM_IF_ERROR_RETURN 1959 (_bcm_tr2_qos_idx2id(unit, 1960 soc_format_field32_get(unit, ITAG_ACTION_SETfmt, 1961 &action_set, PCP_DE_MAPPING_PTRf), 0x2, 1962 &intf_info->inner_vlan_qos.qos_map_id)); 1963 } 1964 return BCM_E_NONE; 1965 } 1966 /* 1967 * Function: 1968 * _bcm_td3_l3_intf_flex_dscp_get 1969 * Purpose: 1970 * Get L3 Interface DSCP parameters for flex views 1971 * Parameters: 1972 * unit - (IN)SOC unit number. 1973 * view_id - (IN) memory view 1974 * l3_if_entry_p - entry buffer 1975 * vid - (IN) Intf_info 1976 * Returns: 1977 * BCM_E_XXX. 1978 */ 1979 STATIC int 1980 _bcm_td3_l3_intf_flex_dscp_get(int unit, uint32 view_id, uint32 *l3_if_entry_p, _bcm_l3_intf_cfg_t *intf_info) 1981 { 1982 uint32 action_set; 1983 1984 /* Input parameters check */ 1985 if (NULL == intf_info) { 1986 return (BCM_E_PARAM); 1987 } 1988 1989 action_set = soc_mem_field32_get(unit, view_id, l3_if_entry_p, 1990 QOS_A_ACTION_SETf); 1991 1992 if (soc_format_field32_get(unit, QOS_A_ACTION_SETfmt, 1993 &action_set, PCP_DE_SELf) == 0x0) { /* DSCP_SELf */ 1994 intf_info->dscp_qos.flags |= BCM_L3_INTF_QOS_DSCP_COPY; 1995 } else if (soc_format_field32_get(unit, QOS_A_ACTION_SETfmt, 1996 &action_set, PCP_DE_SELf) == 0x1) { /* DSCP_SELf */ 1997 intf_info->dscp_qos.flags |= BCM_L3_INTF_QOS_DSCP_SET; 1998 /* DSCPf */ 1999 intf_info->dscp_qos.dscp = 2000 soc_format_field32_get(unit, QOS_A_ACTION_SETfmt, &action_set, 2001 QOS_VALUE_OR_MAPPING_PTR_OR_ZONE_IDf); 2002 } else if (soc_format_field32_get(unit, QOS_A_ACTION_SETfmt, 2003 &action_set, PCP_DE_SELf) == 0x2) { /* DSCP_SELf */ 2004 intf_info->dscp_qos.flags |= BCM_L3_INTF_QOS_DSCP_REMARK; 2005 BCM_IF_ERROR_RETURN 2006 (_bcm_tr2_qos_idx2id(unit, 2007 soc_format_field32_get(unit, QOS_A_ACTION_SETfmt, &action_set, 2008 QOS_VALUE_OR_MAPPING_PTR_OR_ZONE_IDf), 0x4, 2009 &intf_info->dscp_qos.qos_map_id)); 2010 } 2011 2012 return BCM_E_NONE; 2013 } 2014 /* 2015 * Function: 2016 * _bcm_td3_l3_flex_intf_get 2017 * Purpose: 2018 * Get an flex view entry from L3 interface table. 2019 * Parameters: 2020 * unit - (IN)SOC unit number. 2021 * intf_info - (IN/OUT)Pointer to memory for interface information. 2022 * l3_if_entry - Buffer to read interface info. 2023 * Returns: 2024 * BCM_E_XXX 2025 */ 2026 int 2027 _bcm_td3_l3_flex_intf_get(int unit, _bcm_l3_intf_cfg_t *intf_info, uint32 *l3_if_entry_p) 2028 { 2029 int rv = BCM_E_NONE; 2030 int i; 2031 uint32 view_id; 2032 uint32 flex_data_array[128]; 2033 uint32 flex_data_count; 2034 soc_flow_db_ffo_t ffo[SOC_FLOW_DB_MAX_VIEW_FFO_TPL]; 2035 uint32 num_ffo = 0; 2036 uint32 opaque_array[_BCM_FLOW_LOGICAL_FIELD_MAX]; 2037 uint32 opaque_count; 2038 bcm_flow_logical_field_t* user_fields; 2039 2040 uint32 action_set = 0; 2041 uint8 process_fwd_domain = 0; 2042 uint8 process_otag = 0; 2043 uint8 process_itag = 0; 2044 uint8 process_dscp = 0; 2045 uint8 process_tag_action_profile = 0; 2046 uint8 process_tunnel_ptr = 0; 2047 uint8 process_class_id = 0; 2048 uint8 process_outer_sa = 0; 2049 uint8 process_inner_sa = 0; 2050 uint8 process_vxlt = 0; 2051 uint8 process_ttl_b = 0; 2052 uint8 process_ttl_a = 0; 2053 uint8 process_svp = 0; 2054 uint8 data_type; 2055 soc_mem_t mem; 2056 uint8 process_outer_sa_profile = 0; 2057 2058 /* Input parameters check */ 2059 if (NULL == intf_info) { 2060 return (BCM_E_PARAM); 2061 } 2062 2063 if (NULL == l3_if_entry_p) { 2064 return (BCM_E_PARAM); 2065 } 2066 2067 mem = BCM_XGS3_L3_MEM(unit, intf); 2068 2069 /* Get view id corresponding to the specified flow. */ 2070 if (intf_info->flow_handle != 0) { 2071 BCM_IF_ERROR_RETURN( 2072 soc_flow_db_ffo_to_mem_view_id_get(unit, 2073 intf_info->flow_handle, 2074 intf_info->flow_option_handle, 2075 SOC_FLOW_DB_FUNC_EGRESS_INTF_ID, 2076 &view_id)); 2077 } 2078 else { 2079 soc_flow_db_ctrl_field_t field_list; 2080 int num_fields = 0; 2081 2082 data_type = soc_mem_field32_get(unit, mem, l3_if_entry_p, DATA_TYPEf); 2083 2084 if(soc_mem_field_valid(unit, mem, FLOW_SELECT_CTRL_IDf)) { 2085 field_list.field_id = FLOW_SELECT_CTRL_IDf; 2086 field_list.value = soc_mem_field32_get(unit, mem, 2087 l3_if_entry_p, FLOW_SELECT_CTRL_IDf); 2088 num_fields = 1; 2089 } 2090 2091 /* coverity[callee_ptr_arith : FALSE] */ 2092 BCM_IF_ERROR_RETURN( 2093 soc_flow_db_mem_to_view_id_get(unit, 2094 mem, 2095 SOC_FLOW_DB_KEY_TYPE_INVALID, 2096 data_type, 2097 num_fields, 2098 &field_list, 2099 &view_id)); 2100 2101 /* Get the flow handle, function id, option id */ 2102 BCM_IF_ERROR_RETURN( 2103 soc_flow_db_mem_view_to_ffo_get(unit, 2104 view_id, 2105 SOC_FLOW_DB_MAX_VIEW_FFO_TPL, 2106 ffo, 2107 &num_ffo)); 2108 2109 intf_info->flow_handle = ffo[0].flow_handle; 2110 intf_info->flow_option_handle = ffo[0].option_id; 2111 } 2112 2113 /* Get logical field list for this view id. */ 2114 rv = soc_flow_db_mem_view_field_list_get(unit, 2115 view_id, 2116 SOC_FLOW_DB_FIELD_TYPE_LOGICAL_POLICY_DATA, 2117 _BCM_FLOW_LOGICAL_FIELD_MAX, 2118 opaque_array, 2119 &opaque_count); 2120 BCM_IF_ERROR_RETURN(rv); 2121 2122 user_fields = intf_info->logical_fields; 2123 2124 for (i=0; i<opaque_count; i++) { 2125 user_fields[i].id = opaque_array[i]; 2126 user_fields[i].value = soc_mem_field32_get(unit, view_id, l3_if_entry_p, opaque_array[i]); 2127 } 2128 2129 /* Get PDD field list corresponding to the view id. */ 2130 rv = soc_flow_db_mem_view_field_list_get(unit, 2131 view_id, 2132 SOC_FLOW_DB_FIELD_TYPE_POLICY_DATA, 2133 128, 2134 flex_data_array, 2135 &flex_data_count); 2136 BCM_IF_ERROR_RETURN(rv); 2137 2138 for (i=0; i<flex_data_count; i++) { 2139 switch (flex_data_array[i]) { 2140 case FWD_DOMAIN_ACTION_SETf: 2141 process_fwd_domain = 1; 2142 break; 2143 case OTAG_ACTION_SETf: 2144 process_otag = 1; 2145 break; 2146 case ITAG_ACTION_SETf: 2147 process_itag = 1; 2148 break; 2149 case QOS_A_ACTION_SETf: 2150 process_dscp = 1; 2151 break; 2152 case TAG_ACTION_PROFILE_ACTION_SETf: 2153 process_tag_action_profile = 1; 2154 break; 2155 case TUNNEL_PTR_ACTION_SETf: 2156 process_tunnel_ptr = 1; 2157 break; 2158 case CLASS_ID_ACTION_SETf: 2159 process_class_id = 1; 2160 break; 2161 case VXLT_CLASS_IDf: 2162 process_vxlt = 1; 2163 break; 2164 case DIRECT_ASSIGNMENT_7_ACTION_SETf: 2165 process_outer_sa = 1; 2166 break; 2167 case DIRECT_ASSIGNMENT_5_ACTION_SETf: 2168 process_inner_sa = 1; 2169 break; 2170 case TTL_B_ACTION_SETf: 2171 process_ttl_b = 1; 2172 break; 2173 case TTL_A_ACTION_SETf: 2174 process_ttl_a = 1; 2175 break; 2176 case SVP_ACTION_SETf: 2177 process_svp = 1; 2178 break; 2179 case PROFILED_ASSIGNMENT_SRC_MAC_ADDRESS_ACTION_SETf: 2180 process_outer_sa_profile = 1; 2181 break; 2182 default: 2183 break; 2184 } 2185 } 2186 2187 if (process_vxlt) { 2188 intf_info->l3i_class = 2189 soc_mem_field32_get(unit, view_id, l3_if_entry_p, 2190 VXLT_CLASS_IDf); 2191 } 2192 2193 /* Get mac address. */ 2194 if (process_outer_sa) { 2195 soc_mem_mac_addr_get(unit, view_id, l3_if_entry_p, 2196 DIRECT_ASSIGNMENT_7_ACTION_SETf, intf_info->l3i_mac_addr); 2197 } else if (process_inner_sa) { 2198 soc_mem_mac_addr_get(unit, view_id, l3_if_entry_p, 2199 DIRECT_ASSIGNMENT_5_ACTION_SETf, intf_info->l3i_mac_addr); 2200 } else if (process_outer_sa_profile) { 2201 egr_mac_da_profile_entry_t mac_addr; 2202 uint32 mac_idx ; 2203 2204 mac_idx = soc_mem_field32_get(unit, view_id, l3_if_entry_p, 2205 PROFILED_ASSIGNMENT_SRC_MAC_ADDRESS_ACTION_SETf); 2206 BCM_IF_ERROR_RETURN (soc_mem_read(unit, EGR_MAC_DA_PROFILEm, 2207 MEM_BLOCK_ANY, mac_idx, &mac_addr)); 2208 soc_mem_mac_addr_get(unit, EGR_MAC_DA_PROFILEm, &mac_addr, 2209 MAC_ADDRESSf, intf_info->l3i_mac_addr); 2210 } 2211 2212 if (soc_feature(unit, soc_feature_riot)) { 2213 2214 if (process_svp) { 2215 intf_info->l3i_source_vp = 2216 soc_mem_field32_get(unit, view_id, l3_if_entry_p, SVP_ACTION_SETf); 2217 } 2218 2219 if (process_fwd_domain) { 2220 action_set = 0; 2221 2222 action_set = soc_mem_field32_get(unit, view_id, l3_if_entry_p, 2223 FWD_DOMAIN_ACTION_SETf); 2224 2225 /* VLAN_VFI_OVERLAY_TYPEf */ 2226 if (soc_format_field32_get(unit, FWD_DOMAIN_ACTION_SETfmt, 2227 &action_set, FORWARDING_DOMAIN_TYPEf) == 0x2) { 2228 2229 /* VFIf */ 2230 _BCM_VPN_SET(intf_info->l3i_vid, _BCM_VPN_TYPE_VFI, 2231 soc_format_field32_get(unit, FWD_DOMAIN_ACTION_SETfmt, 2232 &action_set, FORWARDING_DOMAINf)); 2233 } else { 2234 2235 /* fld->vlan_id */ 2236 intf_info->l3i_vid = 2237 soc_format_field32_get(unit, FWD_DOMAIN_ACTION_SETfmt, 2238 &action_set, FORWARDING_DOMAINf); 2239 } 2240 2241 } 2242 2243 } else 2244 { 2245 /* Get vlan id. */ 2246 if (process_fwd_domain) { 2247 action_set = soc_mem_field32_get(unit, view_id, l3_if_entry_p, 2248 FWD_DOMAIN_ACTION_SETf); 2249 /* fld->vlan_id */ 2250 intf_info->l3i_vid = 2251 soc_format_field32_get(unit, FWD_DOMAIN_ACTION_SETfmt, 2252 &action_set, FORWARDING_DOMAINf); 2253 } 2254 } 2255 /* Get Time To Live. */ 2256 if (process_ttl_b) { 2257 action_set = soc_mem_field32_get(unit, view_id, l3_if_entry_p, 2258 TTL_B_ACTION_SETf); 2259 /* fld->ttl */ 2260 intf_info->l3i_ttl = 2261 soc_format_field32_get(unit, TTL_B_ACTION_SETfmt, 2262 &action_set, TTL_B_ACTION_SETf); 2263 } else if (process_ttl_a) { 2264 intf_info->l3i_ttl = soc_mem_field32_get(unit, view_id, l3_if_entry_p, 2265 TTL_A_ACTION_SETf); 2266 } 2267 2268 /* Get tunnel index. */ 2269 if (process_tunnel_ptr) { 2270 action_set = soc_mem_field32_get(unit, view_id, l3_if_entry_p, 2271 TUNNEL_PTR_ACTION_SETf); 2272 /* fld->tnl_id */ 2273 intf_info->l3i_tunnel_idx = 2274 soc_format_field32_get(unit, TUNNEL_PTR_ACTION_SETfmt, 2275 &action_set, TUNNEL_INDEXf); 2276 } 2277 2278 /* Set L2 bridging only flag. */ 2279 /* not available in flex views */ 2280 /* 2281 if (soc_mem_field32_get(unit, mem, l3_if_entry_p, fld->l2_switch)) { 2282 intf_info->l3i_flags |= BCM_L3_L2ONLY; 2283 } 2284 */ 2285 2286 /* QoS */ 2287 if (process_otag) { 2288 BCM_IF_ERROR_RETURN 2289 (_bcm_td3_l3_intf_flex_opri_ocfi_get(unit, view_id, 2290 l3_if_entry_p, intf_info)); 2291 } 2292 if (process_itag) { 2293 BCM_IF_ERROR_RETURN 2294 (_bcm_td3_l3_intf_flex_ipri_icfi_get(unit, view_id, 2295 l3_if_entry_p, intf_info)); 2296 } 2297 if (process_dscp) { 2298 BCM_IF_ERROR_RETURN 2299 (_bcm_td3_l3_intf_flex_dscp_get(unit, view_id, 2300 l3_if_entry_p, intf_info)); 2301 } 2302 2303 if (process_itag) { 2304 action_set = soc_mem_field32_get(unit, view_id, l3_if_entry_p, 2305 ITAG_ACTION_SETf); 2306 2307 /* IVIDf, IVID_VALIDf */ 2308 intf_info->l3i_inner_vlan = 2309 soc_format_field32_get(unit, ITAG_ACTION_SETfmt, 2310 &action_set, VIDf); 2311 } 2312 2313 /*Program Inner VLAN handling actions */ 2314 if (process_tag_action_profile) { 2315 uint32 profile_idx; 2316 bcm_vlan_action_set_t action; 2317 2318 action_set = soc_mem_field32_get(unit, view_id, l3_if_entry_p, 2319 TAG_ACTION_PROFILE_ACTION_SETf); 2320 2321 profile_idx = soc_format_field32_get(unit, TAG_ACTION_PROFILE_ACTION_SETfmt, 2322 &action_set, TAG_ACTION_PROFILE_PTRf); 2323 2324 _bcm_trx_egr_vlan_action_profile_entry_get(unit, &action, profile_idx); 2325 2326 /* IVID_PRESENT_ACTIONf */ 2327 switch (action.dt_inner) { 2328 case bcmVlanActionNone: 2329 intf_info->l3i_intf_flags |= BCM_L3_INTF_INNER_VLAN_DO_NOT_MODIFY; 2330 break; 2331 case bcmVlanActionReplace: 2332 intf_info->l3i_intf_flags |= BCM_L3_INTF_INNER_VLAN_REPLACE; 2333 break; 2334 case bcmVlanActionDelete: 2335 intf_info->l3i_intf_flags |= BCM_L3_INTF_INNER_VLAN_DELETE; 2336 break; 2337 default : 2338 intf_info->l3i_intf_flags |= BCM_L3_INTF_INNER_VLAN_DO_NOT_MODIFY; 2339 } 2340 2341 /* IVID_ABSENT_ACTIONf */ 2342 if (action.ot_inner == bcmVlanActionAdd) { 2343 intf_info->l3i_intf_flags |= BCM_L3_INTF_INNER_VLAN_ADD; 2344 intf_info->l3i_intf_flags &= ~(BCM_L3_INTF_INNER_VLAN_DO_NOT_MODIFY); 2345 } 2346 /* IVIDf */ 2347 intf_info->l3i_inner_vlan = 2348 soc_format_field32_get(unit, ITAG_ACTION_SETfmt, 2349 &action_set, VIDf); 2350 } 2351 2352 if (process_class_id) { 2353 /* fld->class_id */ 2354 intf_info->l3i_class = 2355 soc_mem_field32_get(unit, view_id, l3_if_entry_p, CLASS_ID_ACTION_SETf); 2356 } 2357 2358 return (BCM_E_NONE); 2359 } 2360 /* 2361 * Function: 2362 * _bcm_td3_l3_flex_intf_profile_delete 2363 * Purpose: 2364 * Delete mac profile in an L3 interface entry. 2365 * Parameters: 2366 * unit - (IN)SOC unit number. 2367 * ifindex - (IN)Interface index. 2368 * Returns: 2369 * BCM_E_XXX 2370 */ 2371 int 2372 _bcm_td3_l3_flex_intf_profile_delete(int unit, int ifindex) 2373 { 2374 uint32 l3_if_entry[SOC_MAX_MEM_WORDS]; 2375 soc_mem_t mem; 2376 uint32 view_id; 2377 uint32 data_type = 0; 2378 soc_flow_db_ctrl_field_t field_list; 2379 int num_fields = 0; 2380 int rv = BCM_E_NONE; 2381 2382 mem = BCM_XGS3_L3_MEM(unit, intf); 2383 sal_memset(&l3_if_entry, 0, sizeof(l3_if_entry)); 2384 2385 BCM_IF_ERROR_RETURN 2386 (BCM_XGS3_MEM_READ(unit, mem, ifindex, &l3_if_entry)); 2387 2388 if (SOC_MEM_FIELD_VALID(unit, mem, DATA_TYPEf)) { 2389 data_type = soc_mem_field32_get(unit, mem, &l3_if_entry, DATA_TYPEf); 2390 } 2391 if(soc_mem_field_valid(unit, mem, FLOW_SELECT_CTRL_IDf)) { 2392 field_list.field_id = FLOW_SELECT_CTRL_IDf; 2393 field_list.value = soc_mem_field32_get(unit, mem, 2394 &l3_if_entry, FLOW_SELECT_CTRL_IDf); 2395 num_fields = 1; 2396 } 2397 /* coverity[callee_ptr_arith : FALSE] */ 2398 rv = soc_flow_db_mem_to_view_id_get(unit, 2399 mem, 2400 SOC_FLOW_DB_KEY_TYPE_INVALID, 2401 data_type, 2402 num_fields, 2403 &field_list, 2404 &view_id); 2405 2406 if ((rv == BCM_E_NONE) && soc_mem_field_valid(unit, view_id, 2407 PROFILED_ASSIGNMENT_SRC_MAC_ADDRESS_ACTION_SETf)) { 2408 2409 egr_mac_da_profile_entry_t mac_addr; 2410 uint32 mac_idx ; 2411 bcm_mac_t mac_sa; 2412 2413 mac_idx = soc_mem_field32_get(unit, view_id, &l3_if_entry, 2414 PROFILED_ASSIGNMENT_SRC_MAC_ADDRESS_ACTION_SETf); 2415 BCM_IF_ERROR_RETURN (soc_mem_read(unit, EGR_MAC_DA_PROFILEm, 2416 MEM_BLOCK_ANY, mac_idx, &mac_addr)); 2417 soc_mem_mac_addr_get(unit, EGR_MAC_DA_PROFILEm, &mac_addr, 2418 MAC_ADDRESSf, mac_sa); 2419 if (mac_sa[0] | mac_sa[1] | mac_sa[2] | mac_sa[3] | mac_sa[4] | 2420 mac_sa[5]) { 2421 BCM_IF_ERROR_RETURN(_bcm_mac_da_profile_entry_delete(unit, 2422 mac_idx)); 2423 } 2424 } 2425 2426 return (BCM_E_NONE); 2427 } 2428 2429 /* 2430 * Function: 2431 * _bcm_td3_l3_flex_ent_init 2432 * Purpose: 2433 * TD2 helper routine used to init l3 host entry buffer 2434 * Parameters: 2435 * unit - (IN) SOC unit number. 2436 * mem - (IN) L3 table memory. 2437 * l3cfg - (IN/OUT) l3 entry lookup key & search result. 2438 * l3x_entry - (IN) hw buffer. 2439 * Returns: 2440 * void 2441 */ 2442 STATIC int 2443 _bcm_td3_l3_flex_ent_init(int unit, soc_mem_t view_id, 2444 _bcm_l3_cfg_t *l3cfg, uint32 *buf_p) 2445 { 2446 int ipv6; /* Entry is IPv6 flag. */ 2447 int ipmc; /* Entry is IPMC flag. */ 2448 uint32 opaque_array[_BCM_FLOW_LOGICAL_FIELD_MAX]; 2449 uint32 opaque_count; 2450 bcm_flow_logical_field_t* user_fields; 2451 int rv; 2452 int i; 2453 int j; 2454 2455 /* Get entry type. */ 2456 ipv6 = (l3cfg->l3c_flags & BCM_L3_IP6); 2457 /* Check if IPMC entry */ 2458 ipmc = (l3cfg->l3c_flags & BCM_L3_IPMC); 2459 2460 /* Get logical KEY field list for this view id. */ 2461 rv = soc_flow_db_mem_view_field_list_get(unit, 2462 view_id, 2463 SOC_FLOW_DB_FIELD_TYPE_LOGICAL_KEY, 2464 _BCM_FLOW_LOGICAL_FIELD_MAX, 2465 opaque_array, 2466 &opaque_count); 2467 BCM_IF_ERROR_RETURN(rv); 2468 2469 user_fields = l3cfg->l3c_logical_fields; 2470 2471 for (i=0; i<opaque_count; i++) { 2472 for (j = 0; j < l3cfg->l3c_num_of_fields; j++) { 2473 if (user_fields[j].id == opaque_array[i]) { 2474 soc_mem_field32_set(unit, view_id, buf_p, user_fields[j].id, 2475 user_fields[j].value); 2476 break; 2477 } 2478 } 2479 } 2480 2481 soc_mem_field32_set(unit, view_id, buf_p, VRFf, 2482 l3cfg->l3c_vrf); 2483 2484 if (SOC_MEM_FIELD_VALID(unit, view_id, L3_IIFf)) { 2485 soc_mem_field32_set(unit, view_id, buf_p, L3_IIFf, 2486 l3cfg->l3c_ing_intf); 2487 } 2488 if (ipv6) { /* ipv6 entry */ 2489 if (SOC_MEM_FIELD_VALID(unit, view_id, IP_ADDR_LWR_64f)) { 2490 soc_mem_ip6_addr_set(unit, view_id, buf_p, IP_ADDR_LWR_64f, 2491 l3cfg->l3c_ip6, SOC_MEM_IP6_LOWER_ONLY); 2492 } 2493 if (SOC_MEM_FIELD_VALID(unit, view_id, IP_ADDR_UPR_64f)) { 2494 soc_mem_ip6_addr_set(unit, view_id, buf_p, IP_ADDR_UPR_64f, 2495 l3cfg->l3c_ip6, SOC_MEM_IP6_UPPER_ONLY); 2496 } 2497 if (SOC_MEM_FIELD_VALID(unit, view_id, IPV6__DIPf)) { 2498 soc_mem_ip6_addr_set(unit, view_id, buf_p, IPV6__DIPf, 2499 l3cfg->l3c_ip6, SOC_MEM_IP6_FULL_ADDR); 2500 } else if (SOC_MEM_FIELD_VALID(unit, view_id, IPV6__SIPf)) { 2501 soc_mem_ip6_addr_set(unit, view_id, buf_p, IPV6__SIPf, 2502 l3cfg->l3c_ip6, SOC_MEM_IP6_FULL_ADDR); 2503 } 2504 if (ipmc) { 2505 if (SOC_MEM_FIELD_VALID(unit, view_id, IPV6__DIP_V6f)) { 2506 soc_mem_ip6_addr_set(unit, view_id, buf_p, IPV6__DIP_V6f, 2507 l3cfg->l3c_ip6, SOC_MEM_IP6_FULL_ADDR); 2508 } 2509 if (SOC_MEM_FIELD_VALID(unit, view_id, IPV6__SIPf)) { 2510 soc_mem_ip6_addr_set(unit, view_id, buf_p, IPV6__SIPf, 2511 l3cfg->l3c_sip6, SOC_MEM_IP6_FULL_ADDR); 2512 } 2513 } 2514 } else { /* ipv4 entry */ 2515 if (SOC_MEM_FIELD_VALID(unit, view_id, IP_ADDRf)) { 2516 soc_mem_field32_set(unit, view_id, buf_p, IP_ADDRf, 2517 l3cfg->l3c_ip_addr); 2518 } else if (SOC_MEM_FIELD_VALID(unit, view_id, IPV4__DIPf)) { 2519 soc_mem_field32_set(unit, view_id, buf_p, IPV4__DIPf, 2520 l3cfg->l3c_ip_addr); 2521 } else if (SOC_MEM_FIELD_VALID(unit, view_id, IPV4__SIPf)) { 2522 soc_mem_field32_set(unit, view_id, buf_p, IPV4__SIPf, 2523 l3cfg->l3c_ip_addr); 2524 } 2525 if (ipmc) { 2526 if (SOC_MEM_FIELD_VALID(unit, view_id, IPV4__SIPf)) { 2527 soc_mem_field32_set(unit, view_id, buf_p, IPV4__SIPf, 2528 l3cfg->l3c_src_ip_addr); 2529 } 2530 } 2531 } 2532 return BCM_E_NONE; 2533 } 2534 /* 2535 * Function: 2536 * _bcm_td3_flex_get_extended_profile_index 2537 * Purpose: 2538 * TD3 helper routine used to get profile index for EGR_MACDA_OUI_PROFILE 2539 * and EGR_VNTAG_ETAG_PROFILE 2540 * Parameters: 2541 * unit - (IN) SOC unit number. 2542 * mem - (IN) L3 Extended table memory. 2543 * l3cfg - (IN) L3 entry info. 2544 * macda_oui_profile_index - (out) EGR_MACDA_OUI profile index. 2545 * vntag_etag_profile_index - (out) EGR_VNTAG_ETAG profile index. 2546 * Returns: 2547 * BCM_X_XXX 2548 */ 2549 bcm_error_t _bcm_td3_flex_get_extended_profile_index(int unit, soc_mem_t view_id, 2550 _bcm_l3_cfg_t *l3cfg, 2551 int *macda_oui_profile_index, 2552 int *vntag_etag_profile_index, 2553 int *ref_count) { 2554 2555 int rv = BCM_E_NONE; /* Operation return status. */ 2556 uint32 buf_key[SOC_MAX_MEM_WORDS]; /* Key buffer ptr */ 2557 uint32 buf_entry[SOC_MAX_MEM_WORDS]; /* Entry buffer ptr */ 2558 uint32 action_set; 2559 #if 0 2560 l3_entry_ipv4_unicast_entry_t l3v4_key, l3v4_entry; /* IPv4 */ 2561 l3_entry_ipv4_multicast_entry_t l3v4_ext_key, l3v4_ext_entry; /* IPv4-Embedded */ 2562 l3_entry_ipv6_unicast_entry_t l3v6_key, l3v6_entry; /* IPv6 */ 2563 l3_entry_ipv6_multicast_entry_t l3v6_ext_key, l3v6_ext_entry; /* IPv6-Embedded */ 2564 #endif 2565 2566 if (!SOC_MEM_FIELD_VALID(unit, view_id, EXTENDED_VIEW_MACDA_ACTION_SETf)) { 2567 return BCM_E_NOT_FOUND; 2568 } 2569 2570 sal_memset(buf_key, 0, SOC_MAX_MEM_WORDS * sizeof(uint32)); 2571 2572 /* Initialize control field list for this view id. */ 2573 rv = soc_flow_db_mem_view_entry_init(unit, view_id, buf_key); 2574 2575 BCM_IF_ERROR_RETURN(rv); 2576 2577 /* Prepare lookup key. */ 2578 BCM_IF_ERROR_RETURN 2579 (_bcm_td3_l3_flex_ent_init(unit, view_id, l3cfg, buf_key)); 2580 2581 /* Perform lookup hw. */ 2582 rv = soc_mem_generic_lookup(unit, view_id, MEM_BLOCK_ANY, 2583 _BCM_TD3_L3_MEM_BANKS_ALL, 2584 buf_key, buf_entry, &l3cfg->l3c_hw_index); 2585 if (BCM_SUCCESS(rv)) { 2586 2587 action_set = soc_mem_field32_get(unit, view_id, buf_entry, 2588 EXTENDED_VIEW_MACDA_ACTION_SETf); 2589 2590 *macda_oui_profile_index = soc_format_field32_get(unit, 2591 EXTENDED_VIEW_MACDA_ACTION_SETfmt, 2592 &action_set, MACDA_OUI_PROFILEf); 2593 2594 *vntag_etag_profile_index = soc_format_field32_get(unit, 2595 EXTENDED_VIEW_MACDA_ACTION_SETfmt, 2596 &action_set, VNTAG_ETAG_PROFILE_IDf); 2597 2598 rv = soc_profile_mem_ref_count_get(unit, 2599 _bcm_td3_macda_oui_profile[unit], 2600 *macda_oui_profile_index, 2601 ref_count); 2602 } 2603 2604 return rv; 2605 } 2606 /* 2607 * Function: 2608 * _bcm_td3_l3_flex_vp_entry_add 2609 * Purpose: 2610 * TD3 helper routine used to parse hw flex l3 entry to api format 2611 * Parameters: 2612 * unit - (IN) SOC unit number. 2613 * mem - (IN) L3 table memory. 2614 * l3cfg - (IN) L3 entry info. 2615 * buf_p - (IN) hw buffer. 2616 * Returns: 2617 * BCM_X_XXX 2618 */ 2619 bcm_error_t 2620 _bcm_td3_l3_flex_vp_entry_add(int unit, soc_mem_t view_id, _bcm_l3_cfg_t *l3cfg, 2621 uint32 *buf_p, int *macda_oui_profile_index, 2622 int *vntag_etag_profile_index) 2623 { 2624 2625 int rv = BCM_E_NONE; 2626 int rv1 = BCM_E_NONE; 2627 uint32 *bufp; /* HW buffer address. */ 2628 uint32 profile_idx; 2629 uint32 mac_field; 2630 uint32 vntag_actions; 2631 void *entries[1]; 2632 uint32 action_set = 0; 2633 2634 egr_macda_oui_profile_entry_t macda_oui_profile_entry; 2635 egr_vntag_etag_profile_entry_t vntag_etag_profile_entry; 2636 2637 /* Set table fields */ 2638 bufp = buf_p; 2639 2640 if (soc_feature(unit, soc_feature_virtual_port_routing) && 2641 (l3cfg->l3c_encap_id > 0 && 2642 l3cfg->l3c_encap_id < BCM_XGS3_EGRESS_IDX_MIN(unit))) { 2643 int virtual_interface_id; 2644 uint32 hg_vntag_modify = 1; 2645 if (_bcm_vp_used_get(unit, l3cfg->l3c_encap_id, 2646 _bcmVpTypeNiv)) { /* NIV */ 2647 bcm_niv_port_t niv_port; 2648 bcm_niv_egress_t niv_egress; 2649 int count; 2650 BCM_GPORT_NIV_PORT_ID_SET(niv_port.niv_port_id, 2651 l3cfg->l3c_encap_id); 2652 BCM_IF_ERROR_RETURN(bcm_esw_niv_port_get(unit, &niv_port)); 2653 if (niv_port.flags & BCM_NIV_PORT_MATCH_NONE) { 2654 BCM_IF_ERROR_RETURN(bcm_esw_niv_egress_get(unit, 2655 niv_port.niv_port_id, 1, 2656 &niv_egress, &count)); 2657 if (count == 0) { 2658 return BCM_E_CONFIG; 2659 } 2660 if (niv_egress.flags & BCM_NIV_EGRESS_MULTICAST) { 2661 return BCM_E_PARAM; 2662 } 2663 virtual_interface_id = niv_egress.virtual_interface_id; 2664 } else { 2665 if (niv_port.flags & BCM_NIV_PORT_MULTICAST) { 2666 return BCM_E_PARAM; 2667 } 2668 virtual_interface_id = niv_port.virtual_interface_id; 2669 } 2670 /* fld->dst_vif */ 2671 soc_format_field32_set(unit, EXTENDED_VIEW_MACDA_ACTION_SETfmt, 2672 &action_set, DST_VIFf, 2673 virtual_interface_id); 2674 2675 sal_memset(&vntag_etag_profile_entry, 0, sizeof(vntag_etag_profile_entry)); 2676 vntag_actions = 1; 2677 soc_EGR_VNTAG_ETAG_PROFILEm_field_set(unit, &vntag_etag_profile_entry, 2678 VNTAG_ACTIONSf, &vntag_actions); 2679 if (l3cfg->l3c_flags2 & BCM_L3_FLAGS2_NIV_ENCAP_LOCAL) { 2680 soc_EGR_VNTAG_ETAG_PROFILEm_field_set(unit, &vntag_etag_profile_entry, 2681 HG_VNTAG_MODIFY_ENABLEf, &hg_vntag_modify); 2682 } 2683 entries[0] = &vntag_etag_profile_entry; 2684 BCM_IF_ERROR_RETURN(soc_profile_mem_add(unit, _bcm_td3_vntag_etag_profile[unit], 2685 entries, 1, &profile_idx)); 2686 *vntag_etag_profile_index = profile_idx; 2687 soc_format_field32_set(unit, EXTENDED_VIEW_MACDA_ACTION_SETfmt, 2688 &action_set, VNTAG_ETAG_PROFILE_IDf, 2689 profile_idx); 2690 soc_format_field32_set(unit, EXTENDED_VIEW_MACDA_ACTION_SETfmt, 2691 &action_set, MACDA_OUI_PROFILE_VALIDf, 1); 2692 } else if (_bcm_vp_used_get(unit, l3cfg->l3c_encap_id, 2693 _bcmVpTypeExtender)) { /* PE */ 2694 bcm_extender_port_t ep; 2695 int etag_dot1p_mapping_ptr = 0; 2696 BCM_GPORT_EXTENDER_PORT_ID_SET(ep.extender_port_id, 2697 l3cfg->l3c_encap_id); 2698 BCM_IF_ERROR_RETURN(bcm_esw_extender_port_get(unit, &ep)); 2699 if (ep.flags & BCM_EXTENDER_PORT_MULTICAST) { 2700 return BCM_E_PARAM; 2701 } 2702 sal_memset(&vntag_etag_profile_entry, 0, sizeof(vntag_etag_profile_entry)); 2703 vntag_actions = 2; 2704 soc_EGR_VNTAG_ETAG_PROFILEm_field_set(unit, &vntag_etag_profile_entry, 2705 VNTAG_ACTIONSf, &vntag_actions); 2706 if (l3cfg->l3c_flags2 & BCM_L3_FLAGS2_NIV_ENCAP_LOCAL) { 2707 soc_EGR_VNTAG_ETAG_PROFILEm_field_set(unit, &vntag_etag_profile_entry, 2708 HG_VNTAG_MODIFY_ENABLEf, &hg_vntag_modify); 2709 } 2710 bcm_td2_qos_egr_etag_id2profile(unit, ep.qos_map_id, 2711 &etag_dot1p_mapping_ptr); 2712 soc_EGR_VNTAG_ETAG_PROFILEm_field_set(unit, &vntag_etag_profile_entry, 2713 ETAG_DOT1P_MAPPING_PTRf, 2714 (uint32 *)&etag_dot1p_mapping_ptr); 2715 2716 entries[0] = &vntag_etag_profile_entry; 2717 BCM_IF_ERROR_RETURN(soc_profile_mem_add(unit, _bcm_td3_vntag_etag_profile[unit], 2718 entries, 1, &profile_idx)); 2719 *vntag_etag_profile_index = profile_idx; 2720 soc_format_field32_set(unit, EXTENDED_VIEW_MACDA_ACTION_SETfmt, 2721 &action_set, VNTAG_ETAG_PROFILE_IDf, 2722 profile_idx); 2723 virtual_interface_id = ep.extended_port_vid; 2724 soc_format_field32_set(unit, EXTENDED_VIEW_MACDA_ACTION_SETfmt, 2725 &action_set, DST_VIFf, 2726 virtual_interface_id); 2727 soc_format_field32_set(unit, EXTENDED_VIEW_MACDA_ACTION_SETfmt, 2728 &action_set, MACDA_OUI_PROFILE_VALIDf, 1); 2729 } else { 2730 return BCM_E_PARAM; 2731 } 2732 } else { 2733 soc_format_field32_set(unit, EXTENDED_VIEW_MACDA_ACTION_SETfmt, 2734 &action_set, MACDA_OUI_PROFILE_VALIDf, 0); 2735 } 2736 mac_field = ((l3cfg->l3c_mac_addr[3] << 16) | 2737 (l3cfg->l3c_mac_addr[4] << 8) | 2738 (l3cfg->l3c_mac_addr[5] << 0)); 2739 soc_format_field32_set(unit, EXTENDED_VIEW_MACDA_ACTION_SETfmt, 2740 &action_set, MACDA_23_0f, mac_field); 2741 mac_field = ((l3cfg->l3c_mac_addr[0] << 16) | 2742 (l3cfg->l3c_mac_addr[1] << 8) | 2743 (l3cfg->l3c_mac_addr[2] << 0)); 2744 sal_memset(&macda_oui_profile_entry, 0, sizeof(macda_oui_profile_entry)); 2745 soc_EGR_MACDA_OUI_PROFILEm_field_set(unit, &macda_oui_profile_entry, 2746 MACDA_OUIf, &mac_field); 2747 entries[0] = &macda_oui_profile_entry; 2748 rv = soc_profile_mem_add(unit, _bcm_td3_macda_oui_profile[unit], 2749 entries, 1, &profile_idx); 2750 if (BCM_FAILURE(rv)) { 2751 /* delete previously added entry or decrement ref count 2752 * from EGR_VNTAG_ETAG_PROFILE table 2753 */ 2754 soc_mem_lock(unit, EGR_VNTAG_ETAG_PROFILEm); 2755 /* profile 0 is reserved for NON NIV/PE entries */ 2756 if (*vntag_etag_profile_index != 0) { 2757 rv1 = soc_profile_mem_delete(unit, _bcm_td3_vntag_etag_profile[unit], 2758 *vntag_etag_profile_index); 2759 } 2760 if (BCM_FAILURE(rv1)) { 2761 soc_mem_unlock(unit, EGR_VNTAG_ETAG_PROFILEm); 2762 return rv1; 2763 } 2764 soc_mem_unlock(unit, EGR_VNTAG_ETAG_PROFILEm); 2765 return rv; 2766 } 2767 2768 *macda_oui_profile_index = profile_idx; 2769 soc_format_field32_set(unit, EXTENDED_VIEW_MACDA_ACTION_SETfmt, 2770 &action_set, MACDA_OUI_PROFILEf, profile_idx); 2771 2772 soc_mem_field32_set(unit, view_id, bufp, 2773 EXTENDED_VIEW_MACDA_ACTION_SETf, 2774 action_set); 2775 return rv; 2776 } 2777 /* 2778 * Function: 2779 * _bcm_td3_l3_flex_vp_entry_del 2780 * Purpose: 2781 * Delete entry from profile table 2782 * Parameters: 2783 * unit - (IN) SOC unit number. 2784 * ipv6 - (IN) IPV4 or IPv6 flag 2785 * l3cfg - (IN) L3 entry info. 2786 * bufentry - (IN) hw buffer 2787 * Returns: 2788 */ 2789 bcm_error_t 2790 _bcm_td3_l3_flex_vp_entry_del(int unit, _bcm_l3_cfg_t *l3cfg, 2791 int macda_oui_profile_index ,int vntag_etag_profile_index) 2792 { 2793 2794 int rv = BCM_E_NONE; 2795 2796 if (BCM_L3_BK_FLAG_GET(unit, BCM_L3_BK_ENABLE_MACDA_OUI_PROFILE)) { 2797 2798 /* delete an entry or decrement ref count from EGR_MACDA_OUI_PROFILE table */ 2799 soc_mem_lock(unit, EGR_MACDA_OUI_PROFILEm); 2800 if (macda_oui_profile_index != -1) { 2801 rv = soc_profile_mem_delete(unit, _bcm_td3_macda_oui_profile[unit], 2802 macda_oui_profile_index); 2803 } 2804 if (BCM_FAILURE(rv)) { 2805 soc_mem_unlock(unit, EGR_MACDA_OUI_PROFILEm); 2806 return rv; 2807 } 2808 soc_mem_unlock(unit, EGR_MACDA_OUI_PROFILEm); 2809 2810 /* delete an entry or decrement ref count from EGR_VNTAG_ETAG_PROFILE table */ 2811 soc_mem_lock(unit, EGR_VNTAG_ETAG_PROFILEm); 2812 /* profile 0 is reserved for NON NIV/PE entries */ 2813 if (vntag_etag_profile_index != 0) { 2814 rv = soc_profile_mem_delete(unit, _bcm_td3_vntag_etag_profile[unit], 2815 vntag_etag_profile_index); 2816 } 2817 if (BCM_FAILURE(rv)) { 2818 soc_mem_unlock(unit, EGR_VNTAG_ETAG_PROFILEm); 2819 return rv; 2820 } 2821 soc_mem_unlock(unit, EGR_VNTAG_ETAG_PROFILEm); 2822 2823 } 2824 2825 return rv; 2826 } 2827 /* 2828 * Function: 2829 * _bcm_td3_l3_flex_vp_ent_parse 2830 * Purpose: 2831 * TD3 helper routine used to parse hw flex l3 entry to api format 2832 * Parameters: 2833 * unit - (IN) SOC unit number. 2834 * mem - (IN) L3 table memory. 2835 * l3cfg - (IN) L3 entry info. 2836 * l3x_entry - (IN) hw buffer. 2837 * Returns: 2838 */ 2839 bcm_error_t 2840 _bcm_td3_l3_flex_vp_ent_parse(int unit, soc_mem_t view_id, _bcm_l3_cfg_t *l3cfg, void *l3x_entry) 2841 { 2842 2843 uint32 profile_index; 2844 uint32 dst_vif; 2845 uint32 mac_field; 2846 bcm_gport_t vp_gport; 2847 uint32 vntag_actions; 2848 int rv = BCM_E_NONE; 2849 uint32 glp; /* Global port. */ 2850 uint32 *buf_p; /* HW buffer address. */ 2851 egr_macda_oui_profile_entry_t macda_oui_profile_entry; 2852 egr_vntag_etag_profile_entry_t vntag_etag_profile_entry; 2853 int is_trunk = -1; 2854 uint32 HG_VNTAG_MODIFY_ENABLE_FLAG = 0; 2855 uint32 action_set; 2856 2857 buf_p = (uint32 *)l3x_entry; 2858 2859 action_set = soc_mem_field32_get(unit, view_id, buf_p, 2860 DESTINATION_ACTION_SETf); 2861 /* fld->glp */ 2862 glp = soc_format_field32_get(unit, DESTINATION_FORMATfmt, 2863 &action_set, DGPPf); 2864 2865 _bcm_th_glp_resolve_embedded_nh(unit, glp, &l3cfg->l3c_modid, 2866 &l3cfg->l3c_port_tgid, &is_trunk); 2867 if (is_trunk == 1) { 2868 l3cfg->l3c_flags |= BCM_L3_TGID; 2869 } 2870 2871 action_set = soc_mem_field32_get(unit, view_id, buf_p, 2872 EXTENDED_VIEW_MACDA_ACTION_SETf); 2873 2874 /* Set table fields */ 2875 /* fld->macda_low */ 2876 mac_field = soc_format_field32_get(unit, 2877 EXTENDED_VIEW_MACDA_ACTION_SETfmt, 2878 &action_set, MACDA_23_0f); 2879 2880 l3cfg->l3c_mac_addr[3] = (uint8) (mac_field >> 16 & 0xff); 2881 l3cfg->l3c_mac_addr[4] = (uint8) (mac_field >> 8 & 0xff); 2882 l3cfg->l3c_mac_addr[5] = (uint8) (mac_field & 0xff); 2883 /* Read upper 3 bytes of MAC address from profile table */ 2884 /* fld->oui_profile_id */ 2885 profile_index = soc_format_field32_get(unit, 2886 EXTENDED_VIEW_MACDA_ACTION_SETfmt, 2887 &action_set, MACDA_OUI_PROFILEf); 2888 2889 SOC_IF_ERROR_RETURN 2890 (READ_EGR_MACDA_OUI_PROFILEm(unit, MEM_BLOCK_ANY, profile_index, 2891 &macda_oui_profile_entry)); 2892 soc_EGR_MACDA_OUI_PROFILEm_field_get(unit, &macda_oui_profile_entry, 2893 MACDA_OUIf, &mac_field); 2894 l3cfg->l3c_mac_addr[0] = (uint8) (mac_field >> 16 & 0xff); 2895 l3cfg->l3c_mac_addr[1] = (uint8) (mac_field >> 8 & 0xff); 2896 l3cfg->l3c_mac_addr[2] = (uint8) (mac_field & 0xff); 2897 2898 /* fld->dst_vif */ 2899 dst_vif = soc_format_field32_get(unit, 2900 EXTENDED_VIEW_MACDA_ACTION_SETfmt, 2901 &action_set, DST_VIFf); 2902 /* fld->vntag_etag_profile_id */ 2903 profile_index = soc_format_field32_get(unit, 2904 EXTENDED_VIEW_MACDA_ACTION_SETfmt, 2905 &action_set, VNTAG_ETAG_PROFILE_IDf); 2906 2907 if (profile_index != L3_EXT_VIEW_INVALID_VNTAG_ETAG_PROFILE) { 2908 SOC_IF_ERROR_RETURN 2909 (READ_EGR_VNTAG_ETAG_PROFILEm(unit, MEM_BLOCK_ANY, profile_index, 2910 &vntag_etag_profile_entry)); 2911 soc_EGR_VNTAG_ETAG_PROFILEm_field_get(unit, &vntag_etag_profile_entry, 2912 HG_VNTAG_MODIFY_ENABLEf, 2913 &HG_VNTAG_MODIFY_ENABLE_FLAG); 2914 l3cfg->l3c_flags2 = HG_VNTAG_MODIFY_ENABLE_FLAG; 2915 soc_EGR_VNTAG_ETAG_PROFILEm_field_get(unit, &vntag_etag_profile_entry, 2916 VNTAG_ACTIONSf, &vntag_actions); 2917 switch (vntag_actions) { 2918 case VNTAG_ACTIONS_NIV: /* NIV encap */ 2919 if (_bcm_niv_gport_get(unit, is_trunk, l3cfg->l3c_modid, 2920 l3cfg->l3c_port_tgid, dst_vif, 2921 &vp_gport) == BCM_E_NONE) { 2922 l3cfg->l3c_port_tgid = vp_gport; 2923 } 2924 break; 2925 case VNTAG_ACTIONS_ETAG: /* PE encap */ 2926 if (_bcm_extender_gport_get(unit, is_trunk, l3cfg->l3c_modid, 2927 l3cfg->l3c_port_tgid, dst_vif, 2928 &vp_gport) == BCM_E_NONE) { 2929 l3cfg->l3c_port_tgid = vp_gport; 2930 } 2931 break; 2932 default: 2933 break; 2934 } 2935 } 2936 2937 return rv; 2938 } 2939 2940 /* 2941 * Function: 2942 * _bcm_td3_l3_flex_entry_add 2943 * Purpose: 2944 * Add and entry to flex view in TD3 L3 host table. 2945 * Parameters: 2946 * unit - (IN) SOC unit number. 2947 * l3cfg - (IN) L3 entry info. 2948 * nh_idx - (IN) Next hop index. 2949 * Returns: 2950 * BCM_E_XXX 2951 */ 2952 int 2953 _bcm_td3_l3_flex_entry_add(int unit, _bcm_l3_cfg_t *l3cfg, int nh_idx) 2954 { 2955 int ipv6; 2956 uint32 bufp[SOC_MAX_MEM_WORDS]; /* Hardware buffer ptr */ 2957 int rv = BCM_E_NONE; /* Operation status. */ 2958 int embedded_nh = FALSE; 2959 uint32 glp = 0, port_id = 0, modid = 0; 2960 _bcm_l3_intf_cfg_t l3_intf; 2961 #if 0 2962 l3_entry_ipv4_unicast_entry_t l3v4_entry; /* IPv4 */ 2963 l3_entry_ipv4_multicast_entry_t l3v4_ext_entry; /* IPv4-Embedded */ 2964 l3_entry_ipv6_unicast_entry_t l3v6_entry; /* IPv6 */ 2965 l3_entry_ipv6_multicast_entry_t l3v6_ext_entry; /* IPv6-Embedded */ 2966 #endif 2967 uint32 port_addr_max = 0, modid_max = 0; 2968 int macda_oui_profile_index = -1; 2969 int macda_oui_profile_index1 = -1; 2970 int vntag_etag_profile_index = 0; 2971 int vntag_etag_profile_index1 = 0; 2972 int ref_count = 0; 2973 #ifdef BCM_RIOT_SUPPORT 2974 int dvp = -1; 2975 #endif 2976 soc_flow_db_mem_view_info_t mem_view_info; 2977 int i; 2978 uint32 view_id; 2979 uint32 field_array[128]; 2980 uint32 field_count; 2981 uint32 opaque_array[_BCM_FLOW_LOGICAL_FIELD_MAX]; 2982 uint32 opaque_count; 2983 bcm_flow_logical_field_t* user_fields; 2984 2985 uint32 action_set = 0; 2986 uint32 mac_action_set[2]; 2987 2988 uint8 process_destination = 0; 2989 uint8 process_class_id = 0; 2990 uint8 process_qos = 0; 2991 uint8 process_fwd_attributes = 0; 2992 uint8 process_fwd_2_attributes = 0; 2993 uint8 process_qtag = 0; 2994 uint8 process_macda = 0; 2995 uint8 process_l3_if = 0; 2996 uint8 process_source = 0; 2997 2998 /* Marking the l3c_hw_index INVALID 2999 * when l3 host entry flag is not BCM_L3_REPLACE 3000 */ 3001 if (!(l3cfg->l3c_flags & BCM_L3_REPLACE)) { 3002 l3cfg->l3c_hw_index = BCM_XGS3_L3_INVALID_INDEX; 3003 } 3004 /* Get view id corresponding to the specified flow. */ 3005 rv = soc_flow_db_ffo_to_mem_view_id_get(unit, 3006 l3cfg->l3c_flow_handle, 3007 l3cfg->l3c_flow_option_handle, 3008 SOC_FLOW_DB_FUNC_L3_HOST_ID, 3009 &view_id); 3010 BCM_IF_ERROR_RETURN(rv); 3011 3012 rv = soc_flow_db_mem_view_info_get(unit, 3013 view_id, 3014 &mem_view_info); 3015 3016 BCM_IF_ERROR_RETURN(rv); 3017 3018 /* Get entry type. */ 3019 ipv6 = (l3cfg->l3c_flags & BCM_L3_IP6); 3020 3021 #if 0 3022 /* Assign entry buf based on table being used */ 3023 BCM_TD3_L3_HOST_ENTRY_BUF(ipv6, mem, bufp, 3024 l3v4_entry, 3025 l3v4_ext_entry, 3026 l3v6_entry, 3027 l3v6_ext_entry); 3028 #endif 3029 3030 /* Initialize control field list for this view id. */ 3031 sal_memset(bufp, 0, sizeof(bufp)); 3032 rv = soc_flow_db_mem_view_entry_init(unit, view_id, bufp); 3033 3034 BCM_IF_ERROR_RETURN(rv); 3035 3036 /* Prepare host entry for addition. */ 3037 rv = _bcm_td3_l3_flex_ent_init(unit, view_id, l3cfg, bufp); 3038 3039 BCM_IF_ERROR_RETURN(rv); 3040 3041 /* Get logical PDD field list for this view id. */ 3042 rv = soc_flow_db_mem_view_field_list_get(unit, 3043 view_id, 3044 SOC_FLOW_DB_FIELD_TYPE_LOGICAL_POLICY_DATA, 3045 _BCM_FLOW_LOGICAL_FIELD_MAX, 3046 opaque_array, 3047 &opaque_count); 3048 BCM_IF_ERROR_RETURN(rv); 3049 3050 user_fields = l3cfg->l3c_logical_fields; 3051 3052 for (i=0; i<opaque_count; i++) { 3053 if (user_fields[i].id == opaque_array[i]) { 3054 soc_mem_field32_set(unit, view_id, bufp, user_fields[i].id, 3055 user_fields[i].value); 3056 } 3057 } 3058 3059 /* Get PDD field list corresponding to the view id. */ 3060 rv = soc_flow_db_mem_view_field_list_get(unit, 3061 view_id, 3062 SOC_FLOW_DB_FIELD_TYPE_POLICY_DATA, 3063 128, 3064 field_array, 3065 &field_count); 3066 BCM_IF_ERROR_RETURN(rv); 3067 3068 for (i=0; i<field_count; i++) { 3069 switch (field_array[i]) { 3070 case DESTINATION_ACTION_SETf: 3071 process_destination = 1; 3072 break; 3073 case CLASS_ID_ACTION_SETf: 3074 process_class_id = 1; 3075 break; 3076 case QOS_ACTION_SETf: 3077 process_qos = 1; 3078 break; 3079 case FWD_ATTRIBUTES_ACTION_SETf: 3080 process_fwd_attributes = 1; 3081 break; 3082 case FORWARDING_2_MISC_ATTRIBUTES_ACTION_SETf: 3083 process_fwd_2_attributes = 1; 3084 break; 3085 case QTAG_ACTION_SETf: 3086 process_qtag = 1; 3087 break; 3088 case EXTENDED_VIEW_MACDA_ACTION_SETf: 3089 process_macda = 1; 3090 break; 3091 case EXTENDED_VIEW_L3_OIF_ACTION_SETf: 3092 process_l3_if = 1; 3093 break; 3094 case SOURCE_ACTION_SETf: 3095 process_source = 1; 3096 break; 3097 default: 3098 break; 3099 } 3100 } 3101 3102 #ifdef BCM_RIOT_SUPPORT 3103 if ((BCMI_RIOT_IS_ENABLED(unit)) 3104 && (_bcm_vp_is_vfi_type(unit, l3cfg->l3c_port_tgid))) { 3105 _bcm_vp_vfi_type_vp_get(unit, l3cfg->l3c_port_tgid, &dvp); 3106 } else 3107 #endif 3108 { 3109 port_addr_max = SOC_PORT_ADDR_MAX(unit) + 1; 3110 modid_max = SOC_MODID_MAX(unit) + 1; 3111 if (l3cfg->l3c_flags & BCM_L3_TGID) { 3112 glp = (BCM_TGID_PORT_TRUNK_MASK(unit) & l3cfg->l3c_port_tgid); 3113 glp |= (port_addr_max * modid_max); 3114 } else { 3115 port_id = (SOC_PORT_ADDR_MAX(unit) & l3cfg->l3c_port_tgid); 3116 modid = (SOC_MODID_MAX(unit) & l3cfg->l3c_modid) * port_addr_max; 3117 glp = modid | port_id; 3118 } 3119 } 3120 3121 /* Set hit bit. */ 3122 if (SOC_MEM_FIELD_VALID(unit, view_id, HITf)) { 3123 if (l3cfg->l3c_flags & BCM_L3_HIT) { 3124 soc_mem_field32_set(unit, view_id, bufp, HITf, 1); 3125 } 3126 } 3127 /* Set priority. */ 3128 action_set = 0; 3129 if (SOC_MEM_FIELD_VALID(unit, view_id, QOS_ACTION_SETf)) { 3130 soc_format_field32_set(unit, QOS_ACTION_SETfmt, 3131 &action_set, PRIf, l3cfg->l3c_prio); 3132 } 3133 /* Set priority override bit. */ 3134 if (l3cfg->l3c_flags & BCM_L3_RPE) { 3135 if (!process_qos) { 3136 return BCM_E_PARAM; 3137 } 3138 soc_format_field32_set(unit, QOS_ACTION_SETfmt, 3139 &action_set, RPEf, 1); 3140 } 3141 3142 if (process_qos) { 3143 soc_mem_field32_set(unit, view_id, bufp, 3144 QOS_ACTION_SETf, action_set); 3145 } 3146 3147 /* Set destination discard bit. */ 3148 action_set = 0; 3149 if (l3cfg->l3c_flags & BCM_L3_DST_DISCARD) { 3150 if (!process_fwd_attributes) { 3151 return BCM_E_PARAM; 3152 } 3153 soc_format_field32_set(unit, FWD_ATTRIBUTES_ACTION_SETfmt, 3154 &action_set, DST_DISCARDf, 1); 3155 } 3156 3157 if (process_fwd_attributes) { 3158 soc_mem_field32_set(unit, view_id, bufp, 3159 FWD_ATTRIBUTES_ACTION_SETf, action_set); 3160 } 3161 3162 /* Set local addr bit. */ 3163 action_set = 0; 3164 if (l3cfg->l3c_flags & BCM_L3_HOST_LOCAL) { 3165 if (!process_fwd_2_attributes) { 3166 return BCM_E_PARAM; 3167 } 3168 soc_format_field32_set(unit, FORWARDING_2_MISC_ATTRIBUTES_ACTION_SETfmt, 3169 &action_set, LOCAL_ADDRESSf, 1); 3170 } 3171 3172 if (process_fwd_2_attributes) { 3173 soc_mem_field32_set(unit, view_id, bufp, 3174 FORWARDING_2_MISC_ATTRIBUTES_ACTION_SETf, action_set); 3175 } 3176 3177 /* Set classification group id. */ 3178 if (process_class_id) { 3179 soc_mem_field32_set(unit, view_id, bufp, CLASS_ID_ACTION_SETf, 3180 l3cfg->l3c_lookup_class); 3181 } 3182 3183 if (!process_destination) { 3184 return BCM_E_INTERNAL; 3185 } 3186 3187 /* Check if embedded NH table is being used */ 3188 embedded_nh = BCM_TD2_L3_USE_EMBEDDED_NEXT_HOP(unit, l3cfg->l3c_intf, nh_idx); 3189 3190 if (l3cfg->l3c_flags & BCM_L3_IPMC) { 3191 if (process_source) { 3192 action_set = 0; 3193 3194 if (dvp != -1) { 3195 soc_format_field32_set(unit, DESTINATION_FORMATfmt, 3196 &action_set, DEST_TYPE0f, BCMI_TD3_DEST_TYPE0_DVP ); 3197 soc_format_field32_set(unit, DESTINATION_FORMATfmt, 3198 &action_set, DVPf, dvp); 3199 } else { 3200 if (l3cfg->l3c_flags & BCM_L3_TGID) { 3201 soc_format_field32_set(unit, DESTINATION_FORMATfmt, 3202 &action_set, DEST_TYPE2f, BCMI_TD3_DEST_TYPE2_LAG); 3203 } else { 3204 soc_format_field32_set(unit, DESTINATION_FORMATfmt, 3205 &action_set, DEST_TYPE0f, BCMI_TD3_DEST_TYPE0_DGPP); 3206 } 3207 soc_format_field32_set(unit, DESTINATION_FORMATfmt, 3208 &action_set, DGPPf, glp); 3209 } 3210 soc_mem_field32_set(unit, view_id, bufp, SOURCE_ACTION_SETf, 3211 action_set); 3212 } 3213 3214 action_set = 0; 3215 soc_format_field32_set(unit, DESTINATION_FORMATfmt, 3216 &action_set, DEST_TYPE1f, BCMI_TD3_DEST_TYPE1_IPMC); 3217 soc_format_field32_set(unit, DESTINATION_FORMATfmt, 3218 &action_set, IPMC_GROUPf, l3cfg->l3c_ipmc_ptr); 3219 soc_mem_field32_set(unit, view_id, bufp, 3220 DESTINATION_ACTION_SETf, action_set); 3221 } else if (embedded_nh) { 3222 if (!process_l3_if || !process_macda) { 3223 return BCM_E_PARAM; 3224 } 3225 sal_memset(&l3_intf, 0, sizeof(_bcm_l3_intf_cfg_t)); 3226 BCM_XGS3_L3_INTF_IDX_SET(l3_intf, l3cfg->l3c_intf); 3227 3228 BCM_XGS3_L3_MODULE_LOCK(unit); 3229 rv = BCM_XGS3_L3_HWCALL_EXEC(unit, if_get) (unit, &l3_intf); 3230 BCM_XGS3_L3_MODULE_UNLOCK(unit); 3231 3232 soc_mem_field32_set(unit, view_id, bufp, 3233 EXTENDED_VIEW_L3_OIF_ACTION_SETf, 3234 l3cfg->l3c_intf); 3235 action_set = 0; 3236 if (dvp != -1) { 3237 soc_format_field32_set(unit, DESTINATION_FORMATfmt, 3238 &action_set, DEST_TYPE0f, BCMI_TD3_DEST_TYPE0_DVP); 3239 soc_format_field32_set(unit, DESTINATION_FORMATfmt, 3240 &action_set, DVPf, dvp); 3241 } else { 3242 if (l3cfg->l3c_flags & BCM_L3_TGID) { 3243 soc_format_field32_set(unit, DESTINATION_FORMATfmt, 3244 &action_set, DEST_TYPE2f, BCMI_TD3_DEST_TYPE2_LAG); 3245 } else { 3246 soc_format_field32_set(unit, DESTINATION_FORMATfmt, 3247 &action_set, DEST_TYPE0f, BCMI_TD3_DEST_TYPE0_DGPP); 3248 } 3249 soc_format_field32_set(unit, DESTINATION_FORMATfmt, 3250 &action_set, DGPPf, glp); 3251 } 3252 soc_mem_field32_set(unit, view_id, bufp, 3253 DESTINATION_ACTION_SETf, action_set); 3254 3255 mac_action_set[0] = 0; 3256 mac_action_set[1] = 0; 3257 if (BCM_L3_BK_FLAG_GET(unit, BCM_L3_BK_ENABLE_MACDA_OUI_PROFILE)) { 3258 if (l3cfg->l3c_flags & BCM_L3_REPLACE) { 3259 /* For BCM_L3_REPLACE, get profile index for EGR_MACDA_OUI_PROFILE 3260 * and EGR_VNTAG_ETAG_PROFILE table. Delete the profile entry if 3261 * it's not used by any other host. 3262 */ 3263 rv = _bcm_td3_flex_get_extended_profile_index(unit, view_id, l3cfg, 3264 &macda_oui_profile_index, 3265 &vntag_etag_profile_index, 3266 &ref_count); 3267 if (BCM_FAILURE(rv) && (rv!=BCM_E_NOT_FOUND)) { 3268 return rv; 3269 } 3270 if (macda_oui_profile_index == -1) { 3271 /* Host entry was done in regular L3_ENTRY table view */ 3272 BCM_IF_ERROR_RETURN 3273 (_bcm_td3_l3_flex_vp_entry_add(unit, view_id, l3cfg, bufp, 3274 &macda_oui_profile_index1, 3275 &vntag_etag_profile_index1)); 3276 } else { 3277 if (ref_count > 1) { 3278 rv = _bcm_td3_l3_flex_vp_entry_add(unit, view_id, l3cfg, bufp, 3279 &macda_oui_profile_index1, 3280 &vntag_etag_profile_index1); 3281 if (BCM_SUCCESS(rv)) { 3282 BCM_IF_ERROR_RETURN 3283 (_bcm_td3_l3_flex_vp_entry_del(unit, l3cfg, 3284 macda_oui_profile_index, 3285 vntag_etag_profile_index)); 3286 } else { 3287 return rv; 3288 } 3289 } else { 3290 BCM_IF_ERROR_RETURN 3291 (_bcm_td3_l3_flex_vp_entry_del(unit, l3cfg, 3292 macda_oui_profile_index, 3293 vntag_etag_profile_index)); 3294 BCM_IF_ERROR_RETURN 3295 (_bcm_td3_l3_flex_vp_entry_add(unit, view_id, l3cfg, bufp, 3296 &macda_oui_profile_index1, 3297 &vntag_etag_profile_index1)); 3298 3299 } 3300 } 3301 3302 } else { 3303 BCM_IF_ERROR_RETURN 3304 (_bcm_td3_l3_flex_vp_entry_add(unit, view_id, l3cfg, bufp, 3305 &macda_oui_profile_index1, 3306 &vntag_etag_profile_index1)); 3307 3308 } 3309 3310 } else 3311 { 3312 uint32 mac_field[2]; 3313 /* fld->mac_addr */ 3314 SAL_MAC_ADDR_TO_UINT32(l3cfg->l3c_mac_addr, mac_field); 3315 3316 soc_format_field_set(unit, EXTENDED_VIEW_MACDA_ACTION_SETfmt, 3317 mac_action_set, 3318 MAC_ADDRf, mac_field); 3319 soc_format_field32_set(unit, EXTENDED_VIEW_MACDA_ACTION_SETfmt, 3320 mac_action_set, 3321 MACDA_OUI_PROFILE_VALIDf, 0); 3322 } 3323 soc_mem_field_set(unit, view_id, bufp, 3324 EXTENDED_VIEW_MACDA_ACTION_SETf, mac_action_set); 3325 3326 action_set = 0; 3327 if (process_qtag) { 3328 soc_format_field32_set(unit, QTAG_ACTION_SETfmt, &action_set, 3329 EH_TAG_TYPEf, l3cfg->l3c_eh_q_tag_type); 3330 soc_format_field32_set(unit, QTAG_ACTION_SETfmt, &action_set, 3331 EH_QUEUE_TAGf, l3cfg->l3c_eh_q_tag); 3332 soc_mem_field32_set(unit, view_id, bufp, 3333 QTAG_ACTION_SETf, action_set); 3334 } 3335 3336 /* Set copy_to_cpu bit. */ 3337 if (l3cfg->l3c_flags & BCM_L3_COPY_TO_CPU) { 3338 if (!process_fwd_attributes) { 3339 return BCM_E_PARAM; 3340 } 3341 soc_format_field32_set(unit, FWD_ATTRIBUTES_ACTION_SETfmt, 3342 &action_set, COPY_TO_CPUf, 1); 3343 soc_mem_field32_set(unit, view_id, bufp, 3344 FWD_ATTRIBUTES_ACTION_SETf, action_set); 3345 } 3346 } else { 3347 /* Set next hop index. */ 3348 action_set = 0; 3349 if (l3cfg->l3c_flags & BCM_L3_MULTIPATH) { 3350 soc_format_field32_set(unit, DESTINATION_FORMATfmt, 3351 &action_set, DEST_TYPE1f, BCMI_TD3_DEST_TYPE1_ECMP); 3352 soc_format_field32_set(unit, DESTINATION_FORMATfmt, 3353 &action_set, ECMP_GROUPf, nh_idx); 3354 } else { 3355 soc_format_field32_set(unit, DESTINATION_FORMATfmt, 3356 &action_set, DEST_TYPE0f, BCMI_TD3_DEST_TYPE0_NH); 3357 soc_format_field32_set(unit, DESTINATION_FORMATfmt, 3358 &action_set, NEXT_HOP_INDEXf, nh_idx); 3359 } 3360 soc_mem_field32_set(unit, view_id, bufp, 3361 DESTINATION_ACTION_SETf, action_set); 3362 } 3363 3364 /* Insert in table */ 3365 rv = soc_mem_insert(unit, view_id, MEM_BLOCK_ANY, bufp); 3366 3367 /* Handle host entry 'replace' actions */ 3368 if ((BCM_E_EXISTS == rv) && (l3cfg->l3c_flags & BCM_L3_REPLACE)) { 3369 rv = BCM_E_NONE; 3370 } 3371 3372 3373 if (BCM_L3_BK_FLAG_GET(unit, BCM_L3_BK_ENABLE_MACDA_OUI_PROFILE)) { 3374 if (BCM_FAILURE(rv)) { 3375 /* if host add is not successful, then corresponding entries in the 3376 * profile table need to be removed for extended view hosts. 3377 */ 3378 BCM_IF_ERROR_RETURN 3379 (_bcm_td3_l3_flex_vp_entry_del(unit, l3cfg, 3380 macda_oui_profile_index1, 3381 vntag_etag_profile_index1)); 3382 } 3383 } 3384 3385 /* Write status check. */ 3386 if ((rv >= 0) && (BCM_XGS3_L3_INVALID_INDEX == l3cfg->l3c_hw_index)) { 3387 (ipv6) ? BCM_XGS3_L3_IP6_CNT(unit)++ : BCM_XGS3_L3_IP4_CNT(unit)++; 3388 } 3389 3390 return rv; 3391 } 3392 /* 3393 * Function: 3394 * _bcm_td3_l3_flex_ent_parse 3395 * Purpose: 3396 * TD3 helper routine used to parse hw flex l3 entry to api format. 3397 * Parameters: 3398 * unit - (IN) SOC unit number. 3399 * mem - (IN) L3 table memory. 3400 * l3cfg - (IN/OUT) l3 entry key & parse result. 3401 * nh_idx - (IN/OUT) Next hop index. 3402 * l3x_entry - (IN) hw buffer. 3403 * Returns: 3404 * void 3405 */ 3406 int 3407 _bcm_td3_l3_flex_ent_parse(int unit, soc_mem_t mem, _bcm_l3_cfg_t *l3cfg, 3408 int *nh_idx, void *l3x_entry) 3409 { 3410 int ipv6; /* Entry is IPv6 flag. */ 3411 uint32 hit = 0; /* composite hit = hit_x|hit_y */ 3412 uint32 *buf_p; /* HW buffer address. */ 3413 uint32 glp; /* Global port. */ 3414 int embedded_nh = FALSE; 3415 l3_entry_hit_only_x_entry_t hit_x; 3416 int idx, idx_max, idx_offset, hit_idx_shift; 3417 soc_field_t hitf[] = { HIT_0f, HIT_1f, HIT_2f, HIT_3f}; 3418 3419 int i; 3420 int rv; 3421 uint32 view_id; 3422 uint32 field_array[128]; 3423 uint32 field_count; 3424 uint32 action_set; 3425 uint32 dst_type; 3426 uint8 data_type; 3427 3428 uint8 process_destination = 0; 3429 uint8 process_class_id = 0; 3430 uint8 process_qos = 0; 3431 uint8 process_fwd_attributes = 0; 3432 uint8 process_fwd_2_attributes = 0; 3433 uint8 process_qtag = 0; 3434 uint8 process_macda = 0; 3435 uint8 process_l3_if = 0; 3436 uint8 process_source = 0; 3437 soc_flow_db_ffo_t ffo[SOC_FLOW_DB_MAX_VIEW_FFO_TPL]; 3438 uint32 num_ffo = 0; 3439 uint32 data_ids[BCM_FLOW_MAX_NOF_LOGICAL_FIELDS]; 3440 uint32 key_ids[BCM_FLOW_MAX_NOF_LOGICAL_FIELDS]; 3441 uint32 key_cnt = 0; 3442 uint32 data_cnt = 0; 3443 3444 ipv6 = (l3cfg->l3c_flags & BCM_L3_IP6); 3445 buf_p = (uint32 *)l3x_entry; 3446 3447 /* Reset entry flags */ 3448 l3cfg->l3c_flags = (ipv6) ? BCM_L3_IP6 : 0; 3449 3450 /* Read hit bits */ 3451 idx_max = 1; 3452 idx_offset = (l3cfg->l3c_hw_index & 0x3); 3453 hit_idx_shift = 2; 3454 if (mem == L3_ENTRY_IPV4_MULTICASTm || 3455 mem == L3_ENTRY_IPV6_UNICASTm || 3456 (mem == L3_ENTRY_DOUBLEm)) { 3457 idx_max = 2; 3458 hit_idx_shift = 1; 3459 idx_offset = (l3cfg->l3c_hw_index & 0x1) << 1; 3460 } else if ((mem == L3_ENTRY_IPV6_MULTICASTm) || 3461 (mem == L3_ENTRY_QUADm)) { 3462 idx_max = 4; 3463 hit_idx_shift = 0; 3464 idx_offset = 0; 3465 } 3466 3467 if (soc_feature(unit, soc_feature_multi_pipe_mapped_ports)) { 3468 /* Get info from L3 and next hop table */ 3469 BCM_IF_ERROR_RETURN( 3470 BCM_XGS3_MEM_READ(unit, L3_ENTRY_HIT_ONLYm, 3471 (l3cfg->l3c_hw_index >> hit_idx_shift), &hit_x)); 3472 3473 hit = 0; 3474 for (idx = idx_offset; idx < (idx_offset + idx_max); idx++) { 3475 hit |= soc_mem_field32_get(unit, L3_ENTRY_HIT_ONLYm, 3476 &hit_x, hitf[idx]); 3477 } 3478 } 3479 3480 /* Get view id corresponding to the specified flow. */ 3481 if (l3cfg->l3c_flow_handle != 0) { 3482 BCM_IF_ERROR_RETURN(soc_flow_db_ffo_to_mem_view_id_get(unit, 3483 l3cfg->l3c_flow_handle, 3484 l3cfg->l3c_flow_option_handle, 3485 SOC_FLOW_DB_FUNC_L3_HOST_ID, 3486 &view_id)); 3487 } 3488 else { 3489 data_type = soc_mem_field32_get(unit, mem, buf_p, DATA_TYPEf); 3490 3491 BCM_IF_ERROR_RETURN(soc_flow_db_mem_to_view_id_get(unit, 3492 mem, 3493 SOC_FLOW_DB_KEY_TYPE_INVALID, 3494 data_type, 3495 0, 3496 NULL, 3497 &view_id)); 3498 /* get the flow handle, function id, option id */ 3499 BCM_IF_ERROR_RETURN( 3500 soc_flow_db_mem_view_to_ffo_get(unit, 3501 view_id, 3502 SOC_FLOW_DB_MAX_VIEW_FFO_TPL, 3503 ffo, 3504 &num_ffo)); 3505 l3cfg->l3c_flow_handle = ffo[0].flow_handle; 3506 l3cfg->l3c_flow_option_handle = ffo[0].option_id; 3507 } 3508 3509 /* Get PDD field list corresponding to the view id. */ 3510 rv = soc_flow_db_mem_view_field_list_get(unit, 3511 view_id, 3512 SOC_FLOW_DB_FIELD_TYPE_POLICY_DATA, 3513 128, 3514 field_array, 3515 &field_count); 3516 BCM_IF_ERROR_RETURN(rv); 3517 3518 if (SOC_MEM_FIELD_VALID(unit, view_id, HITf)) { 3519 soc_mem_field32_set(unit, view_id, buf_p, HITf, hit); 3520 } 3521 3522 for (i=0; i<field_count; i++) { 3523 switch (field_array[i]) { 3524 case DESTINATION_ACTION_SETf: 3525 process_destination = 1; 3526 break; 3527 case CLASS_ID_ACTION_SETf: 3528 process_class_id = 1; 3529 break; 3530 case QOS_ACTION_SETf: 3531 process_qos = 1; 3532 break; 3533 case FWD_ATTRIBUTES_ACTION_SETf: 3534 process_fwd_attributes = 1; 3535 break; 3536 case FORWARDING_2_MISC_ATTRIBUTES_ACTION_SETf: 3537 process_fwd_2_attributes = 1; 3538 break; 3539 case QTAG_ACTION_SETf: 3540 process_qtag = 1; 3541 break; 3542 case EXTENDED_VIEW_MACDA_ACTION_SETf: 3543 process_macda = 1; 3544 break; 3545 case EXTENDED_VIEW_L3_OIF_ACTION_SETf: 3546 process_l3_if = 1; 3547 break; 3548 case SOURCE_ACTION_SETf: 3549 process_source = 1; 3550 break; 3551 default: 3552 break; 3553 } 3554 } 3555 3556 if (!process_destination) { 3557 return BCM_E_INTERNAL; 3558 } 3559 3560 embedded_nh = process_macda && process_l3_if; 3561 3562 if (hit) { 3563 l3cfg->l3c_flags |= BCM_L3_HIT; 3564 } 3565 3566 /* Get priority override flag, and priority. */ 3567 if (process_qos) { 3568 /* fld->rpe */ 3569 action_set = soc_mem_field32_get(unit, view_id, buf_p, 3570 QOS_ACTION_SETf); 3571 if (soc_format_field32_get(unit, QOS_ACTION_SETfmt, 3572 &action_set, RPEf)) { 3573 l3cfg->l3c_flags |= BCM_L3_RPE; 3574 } 3575 /* fld->priority */ 3576 l3cfg->l3c_prio = soc_format_field32_get(unit, QOS_ACTION_SETfmt, 3577 &action_set, PRIf); 3578 } 3579 3580 /* Get destination discard flag. */ 3581 if (process_fwd_attributes) { 3582 /* fld->dst_discard*/ 3583 action_set = soc_mem_field32_get(unit, view_id, buf_p, 3584 FWD_ATTRIBUTES_ACTION_SETf); 3585 if (soc_format_field32_get(unit, FWD_ATTRIBUTES_ACTION_SETfmt, 3586 &action_set, DST_DISCARDf)) { 3587 l3cfg->l3c_flags |= BCM_L3_DST_DISCARD; 3588 } 3589 } 3590 3591 /* Get local addr bit. */ 3592 if (process_fwd_2_attributes) { 3593 /* fld->local_addr */ 3594 action_set = soc_mem_field32_get(unit, view_id, buf_p, 3595 FORWARDING_2_MISC_ATTRIBUTES_ACTION_SETf); 3596 if (soc_format_field32_get(unit, 3597 FORWARDING_2_MISC_ATTRIBUTES_ACTION_SETfmt, 3598 &action_set, LOCAL_ADDRESSf)) { 3599 l3cfg->l3c_flags |= BCM_L3_HOST_LOCAL; 3600 } 3601 } 3602 3603 /* Get classification group id. */ 3604 if (process_class_id) { 3605 /* fld->class_id */ 3606 l3cfg->l3c_lookup_class = 3607 soc_mem_field32_get(unit, view_id, buf_p, 3608 CLASS_ID_ACTION_SETf); 3609 } 3610 3611 /* Get virtual router id. */ 3612 /* fld->vrf */ 3613 l3cfg->l3c_vrf = soc_mem_field32_get(unit, view_id, buf_p, VRFf); 3614 3615 if (embedded_nh) { 3616 uint32 port_addr_max = 0, modid_max = 0; 3617 #ifdef BCM_RIOT_SUPPORT 3618 int dvp = -1; 3619 #endif 3620 3621 l3cfg->l3c_flags |= BCM_L3_DEREFERENCED_NEXTHOP; 3622 if (nh_idx) { 3623 *nh_idx = BCM_XGS3_L3_INVALID_INDEX; /* Embedded NH */ 3624 } 3625 /* fld->l3_intf */ 3626 l3cfg->l3c_intf = soc_mem_field32_get(unit, view_id, buf_p, 3627 EXTENDED_VIEW_L3_OIF_ACTION_SETf); 3628 if (BCM_L3_BK_FLAG_GET(unit, BCM_L3_BK_ENABLE_MACDA_OUI_PROFILE)) { 3629 BCM_IF_ERROR_RETURN 3630 (_bcm_td3_l3_flex_vp_ent_parse(unit, view_id, l3cfg, buf_p)); 3631 } else { 3632 uint32 mac_action_set[2]; 3633 uint32 mac_field[2]; 3634 uint32 dtype0; 3635 3636 soc_mem_field_get(unit, view_id, buf_p, 3637 EXTENDED_VIEW_MACDA_ACTION_SETf, mac_action_set); 3638 3639 /* fld->mac_addr */ 3640 soc_mem_field_get(unit, mem, buf_p, MAC_ADDRf, mac_field); 3641 3642 soc_format_field_get(unit, EXTENDED_VIEW_MACDA_ACTION_SETfmt, 3643 mac_action_set, 3644 MAC_ADDRf, mac_field); 3645 3646 SAL_MAC_ADDR_FROM_UINT32(l3cfg->l3c_mac_addr, mac_field); 3647 3648 action_set = soc_mem_field32_get(unit, view_id, buf_p, 3649 DESTINATION_ACTION_SETf); 3650 3651 dtype0 = soc_format_field32_get(unit, DESTINATION_FORMATfmt, 3652 &action_set, DEST_TYPE0f); 3653 3654 /* fld->dest */ 3655 glp = soc_format_field32_get(unit, DESTINATION_FORMATfmt, 3656 &action_set, DGPPf); 3657 3658 port_addr_max = SOC_PORT_ADDR_MAX(unit) + 1; 3659 modid_max = SOC_MODID_MAX(unit) + 1; 3660 3661 #ifdef BCM_RIOT_SUPPORT 3662 if (BCMI_RIOT_IS_ENABLED(unit)) { 3663 if (dtype0 == BCMI_TD3_DEST_TYPE0_DVP) { 3664 dvp = glp; /*glp already holds the DEST value from earlier call */ 3665 _bcm_vp_encode_gport(unit, dvp, &(l3cfg->l3c_port_tgid)); 3666 l3cfg->l3c_modid = 0; 3667 } 3668 } 3669 if (dvp == -1) 3670 #endif 3671 { 3672 if (glp & (port_addr_max * modid_max)) { 3673 l3cfg->l3c_flags |= BCM_L3_TGID; 3674 l3cfg->l3c_port_tgid = glp & BCM_TGID_PORT_TRUNK_MASK(unit); 3675 l3cfg->l3c_modid = 0; 3676 } else { 3677 l3cfg->l3c_port_tgid = glp & SOC_PORT_ADDR_MAX(unit); 3678 l3cfg->l3c_modid = (glp / port_addr_max) & SOC_MODID_MAX(unit); 3679 } 3680 } 3681 } 3682 if (process_qtag) { 3683 action_set = soc_mem_field32_get(unit, view_id, buf_p, 3684 QTAG_ACTION_SETf); 3685 /* fld->eh_tag_type */ 3686 l3cfg->l3c_eh_q_tag_type = 3687 soc_format_field32_get(unit, QTAG_ACTION_SETfmt, 3688 &action_set, EH_TAG_TYPEf); 3689 /* fld->eh_queue_tag */ 3690 l3cfg->l3c_eh_q_tag = 3691 soc_format_field32_get(unit, QTAG_ACTION_SETfmt, 3692 &action_set, EH_QUEUE_TAGf); 3693 } 3694 /* Get copy_to_cpu bit. */ 3695 /* fld->copy_to_cpu */ 3696 if (process_fwd_attributes) { 3697 action_set = soc_mem_field32_get(unit, view_id, buf_p, 3698 FWD_ATTRIBUTES_ACTION_SETf); 3699 if (soc_format_field32_get(unit, FWD_ATTRIBUTES_ACTION_SETfmt, 3700 &action_set, COPY_TO_CPUf)) { 3701 l3cfg->l3c_flags |= BCM_L3_COPY_TO_CPU; 3702 } 3703 } 3704 } else { 3705 uint32 dtype0, dtype1; 3706 /* Get next hop info. */ 3707 if (nh_idx) { 3708 3709 action_set = soc_mem_field32_get(unit, view_id, buf_p, 3710 DESTINATION_ACTION_SETf); 3711 3712 dtype0 = soc_format_field32_get(unit, DESTINATION_FORMATfmt, 3713 &action_set, DEST_TYPE0f); 3714 3715 /* fld->dest */ 3716 if (dtype0 == BCMI_TD3_DEST_TYPE0_NH) { 3717 *nh_idx = soc_format_field32_get(unit, DESTINATION_FORMATfmt, 3718 &action_set, NEXT_HOP_INDEXf); 3719 } 3720 } 3721 dtype1 = soc_format_field32_get(unit, DESTINATION_FORMATfmt, 3722 &action_set, DEST_TYPE1f); 3723 3724 if (dtype1 == BCMI_TD3_DEST_TYPE1_ECMP) { 3725 /* Mark entry as ecmp */ 3726 l3cfg->l3c_ecmp = TRUE; 3727 l3cfg->l3c_flags |= BCM_L3_MULTIPATH; 3728 } else if (dtype1 == BCMI_TD3_DEST_TYPE1_IPMC){ 3729 /* Mark the flag IPMC */ 3730 l3cfg->l3c_flags |= BCM_L3_IPMC; 3731 l3cfg->l3c_ipmc_ptr = soc_format_field32_get(unit, 3732 DESTINATION_FORMATfmt, 3733 &action_set, IPMC_GROUPf); 3734 } else { 3735 l3cfg->l3c_ecmp = FALSE; 3736 l3cfg->l3c_flags &= ~BCM_L3_MULTIPATH; 3737 l3cfg->l3c_flags &= ~BCM_L3_IPMC; 3738 l3cfg->l3c_ipmc_ptr = FALSE; 3739 } 3740 } 3741 3742 if (process_source) { 3743 action_set = soc_mem_field32_get(unit, view_id, buf_p, 3744 SOURCE_ACTION_SETf); 3745 dst_type = soc_format_field32_get(unit, DESTINATION_FORMATfmt, 3746 &action_set,DEST_TYPE0f); 3747 glp = soc_format_field32_get(unit, DESTINATION_FORMATfmt, 3748 &action_set, DGPPf); 3749 3750 if (dst_type) { 3751 if (dst_type == BCMI_TD3_DEST_TYPE0_DGPP) { 3752 l3cfg->l3c_port_tgid = glp & SOC_PORT_ADDR_MAX(unit); 3753 l3cfg->l3c_modid = (glp / (SOC_PORT_ADDR_MAX(unit) + 1)) & 3754 SOC_MODID_MAX(unit); 3755 } 3756 } else { 3757 dst_type = soc_format_field32_get(unit, DESTINATION_FORMATfmt, 3758 &action_set,DEST_TYPE1f); 3759 if (!dst_type) { 3760 dst_type = soc_format_field32_get(unit, DESTINATION_FORMATfmt, 3761 &action_set,DEST_TYPE2f); 3762 if (dst_type == BCMI_TD3_DEST_TYPE2_LAG) { 3763 l3cfg->l3c_flags |= BCM_L3_TGID; 3764 l3cfg->l3c_port_tgid = glp & BCM_TGID_PORT_TRUNK_MASK(unit); 3765 l3cfg->l3c_modid = 0; 3766 } 3767 } 3768 } 3769 } 3770 l3cfg->l3c_num_of_fields = 0; 3771 BCM_IF_ERROR_RETURN( 3772 soc_flow_db_mem_view_field_list_get(unit, 3773 view_id, 3774 SOC_FLOW_DB_FIELD_TYPE_LOGICAL_KEY, 3775 BCM_FLOW_MAX_NOF_LOGICAL_FIELDS, 3776 key_ids, 3777 &key_cnt)); 3778 3779 if (key_cnt) { 3780 for (i = 0; 3781 (i < key_cnt) ; i++) { 3782 l3cfg->l3c_logical_fields[i].id = key_ids[i]; 3783 l3cfg->l3c_logical_fields[i].value = 3784 soc_mem_field32_get(unit, view_id, buf_p, 3785 key_ids[i]); 3786 3787 } 3788 l3cfg->l3c_num_of_fields = key_cnt; 3789 } 3790 BCM_IF_ERROR_RETURN( 3791 soc_flow_db_mem_view_field_list_get(unit, 3792 view_id, 3793 SOC_FLOW_DB_FIELD_TYPE_LOGICAL_POLICY_DATA, 3794 BCM_FLOW_MAX_NOF_LOGICAL_FIELDS, data_ids, &data_cnt)); 3795 if (data_cnt) { 3796 /* Entry traverse */ 3797 for ( ; 3798 ((i < data_cnt) && 3799 ( i < SOC_FLOW_DB_FIELD_TYPE_LOGICAL_POLICY_DATA)); 3800 i++) { 3801 l3cfg->l3c_logical_fields[i].id = data_ids[i]; 3802 l3cfg->l3c_logical_fields[i].value = 3803 soc_mem_field32_get(unit, view_id, buf_p, 3804 data_ids[i]); 3805 } 3806 l3cfg->l3c_num_of_fields += data_cnt; 3807 } 3808 3809 if (process_source) { 3810 action_set = soc_mem_field32_get(unit, view_id, buf_p, 3811 SOURCE_ACTION_SETf); 3812 dst_type = soc_format_field32_get(unit, DESTINATION_FORMATfmt, 3813 &action_set,DEST_TYPE0f); 3814 glp = soc_format_field32_get(unit, DESTINATION_FORMATfmt, 3815 &action_set, DGPPf); 3816 3817 if (dst_type) { 3818 if (dst_type == BCMI_TD3_DEST_TYPE0_DGPP) { 3819 l3cfg->l3c_port_tgid = glp & SOC_PORT_ADDR_MAX(unit); 3820 l3cfg->l3c_modid = (glp / (SOC_PORT_ADDR_MAX(unit) + 1)) & 3821 SOC_MODID_MAX(unit); 3822 } 3823 } else { 3824 dst_type = soc_format_field32_get(unit, DESTINATION_FORMATfmt, 3825 &action_set,DEST_TYPE1f); 3826 if (!dst_type) { 3827 dst_type = soc_format_field32_get(unit, DESTINATION_FORMATfmt, 3828 &action_set,DEST_TYPE2f); 3829 if (dst_type == BCMI_TD3_DEST_TYPE2_LAG) { 3830 l3cfg->l3c_flags |= BCM_L3_TGID; 3831 l3cfg->l3c_port_tgid = glp & BCM_TGID_PORT_TRUNK_MASK(unit); 3832 l3cfg->l3c_modid = 0; 3833 } 3834 } 3835 } 3836 } 3837 return BCM_E_NONE; 3838 } 3839 /* 3840 * Function: 3841 * _bcm_td3_l3_flex_entry_del 3842 * Purpose: 3843 * Delete an flex entry from TD3 L3 host table. 3844 * Parameters: 3845 * unit - (IN) SOC unit number. 3846 * l3cfg - (IN/OUT) L3 entry lookup key & search result. 3847 * nh_index - (IN/OUT) Next hop index. 3848 * Returns: 3849 * BCM_E_XXX 3850 */ 3851 int 3852 _bcm_td3_l3_flex_entry_del(int unit, _bcm_l3_cfg_t *l3cfg) 3853 { 3854 int ipv6; /* IPv6 entry indicator. */ 3855 soc_mem_t view_id; /* L3 table memory view. */ 3856 soc_flow_db_mem_view_info_t mem_view_info; 3857 int rv = BCM_E_NONE; /* Operation status. */ 3858 uint32 buf_entry[SOC_MAX_MEM_WORDS]; /* Entry buffer ptrs */ 3859 #if 0 3860 l3_entry_ipv4_unicast_entry_t l3v4_entry; /* IPv4 */ 3861 l3_entry_ipv4_multicast_entry_t l3v4_ext_entry; /* IPv4-Embedded */ 3862 l3_entry_ipv6_unicast_entry_t l3v6_entry; /* IPv6 */ 3863 l3_entry_ipv6_multicast_entry_t l3v6_ext_entry; /* IPv6-Embedded */ 3864 #endif 3865 int macda_oui_profile_index = -1; 3866 int vntag_etag_profile_index = 0; 3867 int ref_count = 0; 3868 3869 /* Get entry type. */ 3870 ipv6 = (l3cfg->l3c_flags & BCM_L3_IP6); 3871 3872 /* Get view id corresponding to the specified flow. */ 3873 rv = soc_flow_db_ffo_to_mem_view_id_get(unit, 3874 l3cfg->l3c_flow_handle, 3875 l3cfg->l3c_flow_option_handle, 3876 SOC_FLOW_DB_FUNC_L3_HOST_ID, 3877 (uint32 *) &view_id); 3878 BCM_IF_ERROR_RETURN(rv); 3879 3880 rv = soc_flow_db_mem_view_info_get(unit, 3881 view_id, 3882 &mem_view_info); 3883 3884 BCM_IF_ERROR_RETURN(rv); 3885 3886 sal_memset(buf_entry, 0, SOC_MAX_MEM_WORDS * sizeof(uint32)); 3887 3888 /* Initialize control field list for this view id. */ 3889 rv = soc_flow_db_mem_view_entry_init(unit, view_id, buf_entry); 3890 3891 BCM_IF_ERROR_RETURN(rv); 3892 3893 /* Prepare lookup key. */ 3894 BCM_IF_ERROR_RETURN(_bcm_td3_l3_flex_ent_init(unit, view_id, l3cfg, buf_entry)); 3895 3896 rv = soc_mem_delete(unit, view_id, MEM_BLOCK_ANY, (void*) buf_entry); 3897 3898 if (rv >= 0) { 3899 (ipv6) ? BCM_XGS3_L3_IP6_CNT(unit)-- : BCM_XGS3_L3_IP4_CNT(unit)--; 3900 } 3901 3902 if ((BCM_E_NOT_FOUND == rv) && 3903 (soc_feature(unit, soc_feature_l3_extended_host_entry))) { 3904 /* Delete from the extended tables only if the extended host entry 3905 * feature is supported and if the entry was not found in the 3906 * regular host entry */ 3907 3908 if (BCM_L3_BK_FLAG_GET(unit, BCM_L3_BK_ENABLE_MACDA_OUI_PROFILE)) { 3909 BCM_IF_ERROR_RETURN 3910 (_bcm_td3_flex_get_extended_profile_index(unit, view_id, l3cfg, 3911 &macda_oui_profile_index, 3912 &vntag_etag_profile_index, 3913 &ref_count)); 3914 } 3915 3916 BCM_IF_ERROR_RETURN 3917 (_bcm_td3_l3_flex_vp_entry_del(unit, l3cfg, 3918 macda_oui_profile_index, 3919 vntag_etag_profile_index)); 3920 } 3921 3922 return rv; 3923 } 3924 3925 int 3926 _bcm_td3_l3_flex_entry_flags_cmp(int unit, int req_flags, int ent_flags, int *idx) 3927 { 3928 /* If protocol doesn't match skip the entry. */ 3929 if (req_flags & BCM_L3_IP6) { 3930 if (!(ent_flags & BCM_L3_IP6)) { 3931 return (BCM_L3_CMP_NOT_EQUAL); 3932 } 3933 } else if (ent_flags & BCM_L3_IP6) { 3934 #ifdef BCM_FIREBOLT_SUPPORT 3935 BCM_XGS3_INC_IF_FIREBOLT(unit, (*idx)); 3936 #endif /* BCM_FIREBOLT_SUPPORT */ 3937 return (BCM_L3_CMP_NOT_EQUAL); 3938 } 3939 3940 /* Check ipmc flag. 3941 Do not exit on mismatch for L3 host IPMC */ 3942 if ((!(req_flags & BCM_L3_IPMC)) && (ent_flags & BCM_L3_IPMC)) { 3943 #ifdef BCM_FIREBOLT_SUPPORT 3944 if (req_flags & BCM_L3_IP6) { 3945 BCM_XGS3_INC_IF_FIREBOLT(unit, (*idx)); 3946 } 3947 #endif /* BCM_FIREBOLT_SUPPORT */ 3948 } 3949 return (BCM_L3_CMP_EQUAL); 3950 } 3951 3952 /* 3953 * Function: 3954 * _bcm_td3_l3_clear_hit 3955 * Purpose: 3956 * Clear hit bit on flex l3 entry 3957 * Parameters: 3958 * unit - (IN)SOC unit number. 3959 * mem - (IN)L3 table memory. 3960 * l3cfg - (IN)l3 entry info. 3961 * l3x_entry - (IN)l3 entry filled hw buffer. 3962 * Returns: 3963 * BCM_E_XXX 3964 */ 3965 STATIC int 3966 _bcm_td3_l3_clear_hit(int unit, soc_mem_t mem, _bcm_l3_cfg_t *l3cfg, 3967 void *l3x_entry, int l3_entry_idx) 3968 { 3969 int ipv6; /* Entry is IPv6 flag. */ 3970 int mcast; /* Entry is multicast flag. */ 3971 uint32 *buf_p; /* HW buffer address. */ 3972 soc_field_t hitf[] = { HIT_0f, HIT_1f, HIT_2f, HIT_3f }; 3973 int idx; 3974 3975 /* Input parameters check */ 3976 if ((NULL == l3cfg) || (NULL == l3x_entry)) { 3977 return (BCM_E_PARAM); 3978 } 3979 3980 /* Get entry type. */ 3981 ipv6 = (l3cfg->l3c_flags & BCM_L3_IP6); 3982 mcast = (l3cfg->l3c_flags & BCM_L3_IPMC); 3983 3984 /* Init memory pointers. */ 3985 buf_p = (uint32 *)l3x_entry; 3986 3987 /* If entry was not hit there is nothing to clear */ 3988 if (!(l3cfg->l3c_flags & BCM_L3_HIT)) { 3989 return (BCM_E_NONE); 3990 } 3991 3992 /* Reset hit bit. */ 3993 soc_mem_field32_set(unit, mem, buf_p, HITf, 0); 3994 3995 if (ipv6 && mcast) { 3996 /* IPV6 multicast entry hit reset. */ 3997 for (idx = 0; idx < 4; idx++) { 3998 soc_mem_field32_set(unit, mem, buf_p, hitf[idx], 0); 3999 } 4000 } else if (ipv6 || mcast) { 4001 /* Reset IPV6 unicast and IPV4 multicast hit bits. */ 4002 for (idx = 0; idx < 2; idx++) { 4003 soc_mem_field32_set(unit, mem, buf_p, hitf[idx], 0); 4004 } 4005 } 4006 4007 /* Write entry back to hw. */ 4008 return BCM_XGS3_MEM_WRITE(unit, mem, l3_entry_idx, buf_p); 4009 } 4010 /* 4011 * Function: 4012 * _bcm_td3_l3_flex_entry_get 4013 * Purpose: 4014 * Get an flex entry from TD3 L3 host table. 4015 * Parameters: 4016 * unit - (IN) SOC unit number. 4017 * l3cfg - (IN/OUT) L3 entry lookup key & search result. 4018 * nh_index - (IN/OUT) Next hop index. 4019 * embd - (OUT) If TRUE, entry was found as embedded NH. 4020 * Returns: 4021 * BCM_E_XXX 4022 */ 4023 int 4024 _bcm_td3_l3_flex_entry_get(int unit, _bcm_l3_cfg_t *l3cfg, int *nh_idx, int *embd) 4025 { 4026 int clear_hit; /* Clear hit bit. */ 4027 int rv = BCM_E_NONE; /* Operation return status. */ 4028 uint32 buf_key[SOC_MAX_MEM_WORDS]; /* Key buffer ptr*/ 4029 uint32 buf_entry[SOC_MAX_MEM_WORDS]; /* Entry buffer ptr*/ 4030 uint32 view_id; 4031 soc_flow_db_mem_view_info_t mem_view_info; 4032 4033 /* Indexed NH entry */ 4034 *embd = _BCM_TD3_HOST_ENTRY_NOT_FOUND; 4035 4036 /* Preserve clear_hit value. */ 4037 clear_hit = l3cfg->l3c_flags & BCM_L3_HIT_CLEAR; 4038 4039 /* Get view id corresponding to the specified flow. */ 4040 rv = soc_flow_db_ffo_to_mem_view_id_get(unit, 4041 l3cfg->l3c_flow_handle, 4042 l3cfg->l3c_flow_option_handle, 4043 SOC_FLOW_DB_FUNC_L3_HOST_ID, 4044 &view_id); 4045 BCM_IF_ERROR_RETURN(rv); 4046 4047 /* Get mem id corresponding to the view_id . */ 4048 rv = soc_flow_db_mem_view_info_get(unit, 4049 view_id, 4050 &mem_view_info); 4051 4052 BCM_IF_ERROR_RETURN(rv); 4053 4054 sal_memset(buf_key, 0, SOC_MAX_MEM_WORDS * sizeof(uint32)); 4055 4056 /* Initialize control field list for this view id. */ 4057 rv = soc_flow_db_mem_view_entry_init(unit, view_id, buf_key); 4058 4059 BCM_IF_ERROR_RETURN(rv); 4060 4061 /* Prepare lookup key. */ 4062 BCM_IF_ERROR_RETURN(_bcm_td3_l3_flex_ent_init(unit, view_id, l3cfg, buf_key)); 4063 4064 /* Perform lookup */ 4065 rv = soc_mem_generic_lookup(unit, view_id, MEM_BLOCK_ANY, 4066 _BCM_TD3_L3_MEM_BANKS_ALL, 4067 buf_key, buf_entry, &l3cfg->l3c_hw_index); 4068 if (BCM_SUCCESS(rv)) { 4069 /* Indexed NH entry */ 4070 *embd = FALSE; 4071 /* Extract entry info. */ 4072 BCM_IF_ERROR_RETURN(_bcm_td3_l3_flex_ent_parse(unit, 4073 mem_view_info.mem, l3cfg, 4074 nh_idx, buf_entry)); 4075 /* Clear the HIT bit */ 4076 if (clear_hit) { 4077 BCM_IF_ERROR_RETURN(_bcm_td3_l3_clear_hit(unit, view_id, 4078 l3cfg, buf_entry, l3cfg->l3c_hw_index)); 4079 } 4080 } 4081 4082 return rv; 4083 } 4084 4085 /* 4086 * Function: 4087 * _bcm_td3_mpls_vc_and_swap_flex_table_reset 4088 * Purpose: 4089 * Reset VC_AND_SWAP_TABLE entry 4090 * Parameters: 4091 * IN : Unit 4092 * IN : vc_swap_index 4093 * Returns: 4094 * BCM_E_XXX 4095 */ 4096 STATIC int 4097 _bcm_td3_mpls_vc_and_swap_flex_table_index_reset (int unit, int vc_swap_index) 4098 { 4099 egr_mpls_vc_and_swap_label_table_entry_t vc_entry; 4100 int rv = BCM_E_NONE; 4101 _bcm_tr_mpls_bookkeeping_t *mpls_info = MPLS_INFO(unit); 4102 int num_vc; 4103 4104 /* Entry 0 is reserved with _bcm_tr_mpls_default_entry_setup during init */ 4105 if (vc_swap_index == VC_AND_SWAP_TABLE_RESV_INDEX) { 4106 LOG_INFO(BSL_LS_BCM_L3, 4107 (BSL_META_U(unit,"Not resetting reserved index: %d in " 4108 "VC AND SWAP TABLE\n"), 0)); 4109 return BCM_E_NONE; 4110 } 4111 if ( mpls_info->vc_swap_ref_count[vc_swap_index] != 0 ) { 4112 return BCM_E_NONE; 4113 } 4114 4115 num_vc = soc_mem_index_count(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm); 4116 num_vc /= 2; 4117 4118 if (vc_swap_index >= num_vc) { 4119 _BCM_MPLS_VC_NON_COUNT_USED_CLR(unit, vc_swap_index - num_vc); 4120 } else { 4121 _BCM_MPLS_VC_COUNT_USED_CLR(unit, vc_swap_index); 4122 } 4123 4124 sal_memset(&vc_entry, 0, 4125 sizeof(egr_mpls_vc_and_swap_label_table_entry_t)); 4126 4127 rv = soc_mem_write(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 4128 MEM_BLOCK_ALL, vc_swap_index, 4129 &vc_entry); 4130 4131 4132 4133 return rv; 4134 } 4135 /* 4136 * Function: 4137 * _bcm_td3_mpls_vc_and_swap_table_flex_entry_set 4138 * Purpose: 4139 * Set VC_AND_SWAP_TABLE entry 4140 * Parameters: 4141 * IN : Unit 4142 * IN : egress object 4143 * IN : View ID for memory 4144 * IN : label action 4145 * IN : vc_swap entry 4146 * IN : hw_map_idx: qos map table 4147 * IN : vc_swap_index 4148 * Returns: 4149 * BCM_E_XXX 4150 */ 4151 STATIC int 4152 _bcm_td3_mpls_vc_and_swap_table_flex_entry_set (int unit, 4153 bcm_l3_egress_t *egr_obj, 4154 soc_mem_t view_id, 4155 int label_action, 4156 egr_mpls_vc_and_swap_label_table_entry_t *vc_entry, 4157 int hw_map_idx, int vc_swap_index) 4158 { 4159 int rv; 4160 bcm_mpls_label_t mpls_label = BCM_MPLS_LABEL_INVALID; 4161 uint8 mpls_ttl = 0; 4162 uint32 mpls_flags = 0; 4163 uint8 mpls_exp = 0; 4164 uint8 mpls_pkt_pri = 0; 4165 uint8 mpls_pkt_cfi = 0; 4166 4167 uint32 flex_data_array[128]; 4168 uint32 flex_data_count; 4169 uint32 opaque_array[_BCM_FLOW_LOGICAL_FIELD_MAX]; 4170 uint32 opaque_count; 4171 bcm_flow_logical_field_t* user_fields; 4172 uint32 mpls_hdr; 4173 4174 int i; 4175 uint32 action_set = 0; 4176 uint8 process_mpls_entry = 0; 4177 uint8 process_label = 0; 4178 4179 if (egr_obj == NULL) { 4180 return BCM_E_PARAM; 4181 } 4182 4183 mpls_label = egr_obj->mpls_label; 4184 mpls_ttl = egr_obj->mpls_ttl; 4185 mpls_flags = egr_obj->mpls_flags; 4186 mpls_pkt_pri = egr_obj->mpls_pkt_pri; 4187 mpls_pkt_cfi = egr_obj->mpls_pkt_cfi; 4188 mpls_exp = egr_obj->mpls_exp; 4189 4190 if ((mpls_exp > 7) || (mpls_pkt_pri > 7) || 4191 (mpls_pkt_cfi > 1)) { 4192 return BCM_E_PARAM; 4193 } 4194 4195 sal_memset(vc_entry, 0, 4196 sizeof(egr_mpls_vc_and_swap_label_table_entry_t)); 4197 4198 /* Initialize control field list for this view id. */ 4199 rv = soc_flow_db_mem_view_entry_init(unit, view_id, (uint32 *) vc_entry); 4200 4201 BCM_IF_ERROR_RETURN(rv); 4202 4203 /* Get logical field list for this view id. */ 4204 rv = soc_flow_db_mem_view_field_list_get(unit, 4205 view_id, 4206 SOC_FLOW_DB_FIELD_TYPE_LOGICAL_POLICY_DATA, 4207 _BCM_FLOW_LOGICAL_FIELD_MAX, 4208 opaque_array, 4209 &opaque_count); 4210 BCM_IF_ERROR_RETURN(rv); 4211 4212 user_fields = egr_obj->logical_fields; 4213 4214 for (i=0; i<opaque_count; i++) { 4215 if (user_fields[i].id == opaque_array[i]) { 4216 soc_mem_field32_set(unit, view_id, vc_entry, user_fields[i].id, 4217 user_fields[i].value); 4218 } 4219 } 4220 4221 /* Get PDD field list corresponding to the view id. */ 4222 rv = soc_flow_db_mem_view_field_list_get(unit, 4223 view_id, 4224 SOC_FLOW_DB_FIELD_TYPE_POLICY_DATA, 4225 128, 4226 flex_data_array, 4227 &flex_data_count); 4228 BCM_IF_ERROR_RETURN(rv); 4229 4230 for (i=0; i<flex_data_count; i++) { 4231 switch (flex_data_array[i]) { 4232 case MPLS_ENTRY_0_ACTION_SETf: 4233 process_mpls_entry = 1; 4234 break; 4235 case SD_TAG_ACTION_SETf: 4236 break; 4237 case DIRECT_ASSIGNMENT_21_ACTION_SETf: 4238 process_label = 1; 4239 break; 4240 default: 4241 break; 4242 } 4243 } 4244 4245 if (process_mpls_entry) { 4246 action_set = 0; 4247 if (_BCM_MPLS_EGRESS_LABEL_PRESERVE(unit, mpls_flags)) { 4248 /* set label select to 1 to get label from metadata */ 4249 soc_format_field32_set(unit, MPLS_ENTRY_ACTION_SETfmt, 4250 &action_set, LABEL_SELECTf, 4251 1); 4252 /* CANCUN has fixed the container 1 for swap to self */ 4253 soc_format_field32_set(unit, MPLS_ENTRY_ACTION_SETfmt, 4254 &action_set, CONTAINER_IDf, 4255 1); 4256 soc_format_field32_set(unit, MPLS_ENTRY_ACTION_SETfmt, 4257 &action_set, MPLS_PUSH_ACTIONf, 4258 _BCM_MPLS_ACTION_PUSH); 4259 MPLS_INFO(unit)->egr_vc_swap_lbl_action[vc_swap_index] = 4260 _BCM_MPLS_ACTION_PRESERVED; 4261 } else { 4262 if (BCM_XGS3_L3_MPLS_LBL_VALID(mpls_label)) { 4263 soc_format_field32_set(unit, MPLS_ENTRY_ACTION_SETfmt, 4264 &action_set, MPLS_LABELf, 4265 mpls_label); 4266 MPLS_INFO(unit)->egr_vc_swap_lbl_action[vc_swap_index] = 4267 label_action; 4268 if (label_action == _BCM_MPLS_ACTION_SWAP) { 4269 /*VC SWAP HW Tbl supports Label actions NOOP,PUSH in TD3. 4270 *Record software defined label actions in software 4271 *state to reuse existing code for L3MPLS*/ 4272 label_action = _BCM_MPLS_ACTION_PUSH; 4273 } 4274 soc_format_field32_set(unit, MPLS_ENTRY_ACTION_SETfmt, 4275 &action_set, MPLS_PUSH_ACTIONf, 4276 _BCM_MPLS_ACTION_PUSH); 4277 } else { 4278 soc_format_field32_set(unit, MPLS_ENTRY_ACTION_SETfmt, 4279 &action_set, MPLS_PUSH_ACTIONf, 4280 _BCM_MPLS_ACTION_NOOP); 4281 } 4282 } 4283 4284 if (mpls_flags & BCM_MPLS_EGRESS_LABEL_TTL_SET) { 4285 soc_format_field32_set(unit, MPLS_ENTRY_ACTION_SETfmt, 4286 &action_set, MPLS_TTLf, 4287 mpls_ttl); 4288 } else { 4289 soc_format_field32_set(unit, MPLS_ENTRY_ACTION_SETfmt, 4290 &action_set, MPLS_TTLf, 4291 0x0); 4292 } 4293 4294 if ((mpls_flags & BCM_MPLS_EGRESS_LABEL_EXP_SET) || 4295 (mpls_flags & BCM_MPLS_EGRESS_LABEL_PRI_SET)) { 4296 4297 if ((mpls_flags & BCM_MPLS_EGRESS_LABEL_EXP_REMARK) || 4298 (mpls_flags & BCM_MPLS_EGRESS_LABEL_EXP_COPY) || 4299 (mpls_flags & BCM_MPLS_EGRESS_LABEL_PRI_REMARK)) { 4300 return BCM_E_PARAM; 4301 } 4302 /* Use the specified EXP, PRI and CFI */ 4303 soc_format_field32_set(unit, MPLS_ENTRY_ACTION_SETfmt, 4304 &action_set, MPLS_EXP_SELECTf, 4305 0x0); /* USE_FIXED */ 4306 soc_format_field32_set(unit, MPLS_ENTRY_ACTION_SETfmt, 4307 &action_set, MPLS_EXPf, 4308 mpls_exp); 4309 soc_format_field32_set(unit, MPLS_ENTRY_ACTION_SETfmt, 4310 &action_set, NEW_PRIf, 4311 mpls_pkt_pri); 4312 soc_format_field32_set(unit, MPLS_ENTRY_ACTION_SETfmt, 4313 &action_set, NEW_CFIf, 4314 mpls_pkt_cfi); 4315 } else if (mpls_flags & BCM_MPLS_EGRESS_LABEL_EXP_REMARK) { 4316 if (mpls_flags & BCM_MPLS_EGRESS_LABEL_PRI_SET) { 4317 return BCM_E_PARAM; 4318 } 4319 /* Use EXP-map for EXP, PRI and CFI */ 4320 soc_format_field32_set(unit, MPLS_ENTRY_ACTION_SETfmt, 4321 &action_set, MPLS_EXP_SELECTf, 4322 0x1); /* USE_MAPPING */ 4323 soc_format_field32_set(unit, MPLS_ENTRY_ACTION_SETfmt, 4324 &action_set, MPLS_EXP_MAPPING_PTRf, 4325 hw_map_idx); 4326 } else if ((label_action != _BCM_MPLS_ACTION_SWAP) && 4327 (mpls_flags & BCM_MPLS_EGRESS_LABEL_EXP_COPY) ) { 4328 /* not support for MPLSoGRE flow */ 4329 return BCM_E_PARAM; 4330 } else if ((label_action == _BCM_MPLS_ACTION_SWAP) && 4331 (mpls_flags & BCM_MPLS_EGRESS_LABEL_EXP_COPY) ) { 4332 /* not support for MPLSoGRE flow */ 4333 return BCM_E_PARAM; 4334 } 4335 soc_mem_field32_set(unit, view_id, vc_entry, 4336 MPLS_ENTRY_0_ACTION_SETf, action_set); 4337 } 4338 if (process_label) { 4339 mpls_hdr = mpls_label<<12 | mpls_exp<<9 | 1<<8 | mpls_ttl; 4340 soc_mem_field32_set(unit, view_id, vc_entry, 4341 DIRECT_ASSIGNMENT_21_ACTION_SETf, mpls_hdr); 4342 } 4343 return BCM_E_NONE; 4344 } 4345 /* 4346 * Function: 4347 * _bcm_td3_mpls_gre_label_add 4348 * Purpose: 4349 * Updates MPLSoGRE within VC_AND_SWAP_TABLE for a given EGR_NH Index 4350 * Parameters: 4351 * IN : Unit 4352 * IN : egr object 4353 * IN : nh_index, available when BCM_L3_REPLACE 4354 * IN : mpls_flags 4355 * Returns: 4356 * BCM_E_XXX 4357 */ 4358 int 4359 _bcm_td3_mpls_gre_label_add (int unit, bcm_l3_egress_t *egr, int nh_index, uint32 flags) 4360 { 4361 int rv=BCM_E_NONE; 4362 egr_mpls_vc_and_swap_label_table_entry_t vc_entry; 4363 int vc_swap_index=-1; 4364 uint32 view_id; 4365 egr_l3_next_hop_entry_t egr_nh; 4366 uint32 nh_entry_type; 4367 uint32 nh_view_id; 4368 int hw_map_idx, num_mpls_map; 4369 uint32 action_set; 4370 4371 if (egr == NULL) { 4372 return BCM_E_PARAM; 4373 } 4374 4375 rv = soc_flow_db_ffo_to_mem_view_id_get(unit, 4376 egr->flow_handle, 4377 egr->flow_label_option_handle, 4378 SOC_FLOW_DB_FUNC_EGRESS_LABEL_ID, 4379 &view_id); 4380 BCM_IF_ERROR_RETURN(rv); 4381 4382 sal_memset(&vc_entry, 0, 4383 sizeof(egr_mpls_vc_and_swap_label_table_entry_t)); 4384 4385 /* Retrieve EGR L3 NHOP Entry from given index */ 4386 BCM_IF_ERROR_RETURN (soc_mem_read(unit, EGR_L3_NEXT_HOPm, MEM_BLOCK_ANY, 4387 nh_index, &egr_nh)); 4388 4389 nh_entry_type = 4390 soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_nh, DATA_TYPEf); 4391 4392 rv = soc_flow_db_mem_to_view_id_get(unit, 4393 EGR_L3_NEXT_HOPm, 4394 SOC_FLOW_DB_KEY_TYPE_INVALID, 4395 nh_entry_type, 4396 0, 4397 NULL, 4398 &nh_view_id); 4399 4400 /* Be sure that the existing entry is already setup to 4401 * egress into an MPLS tunnel. If not, return BCM_E_PARAM. 4402 */ 4403 4404 if (!BCMI_L3_NH_FLEX_VIEW(nh_entry_type)) { 4405 return BCM_E_PARAM; 4406 } 4407 4408 if ((egr->mpls_label != BCM_MPLS_LABEL_INVALID) && 4409 (flags & BCM_L3_REPLACE)) { 4410 4411 action_set = soc_mem_field32_get(unit, nh_view_id, &egr_nh, 4412 NEXT_PTR_ACTION_SETf); 4413 4414 if (soc_format_field32_get(unit, NEXT_PTR_ACTION_SETfmt, 4415 &action_set, NEXT_PTR_TYPEf) != 4416 BCMI_TD3_L3_NH_EGR_NEXT_PTR_TYPE_VC_SWAP) { 4417 /* this entry doesn't have a vc_swap index */ 4418 return BCM_E_PARAM; 4419 } 4420 /* Retrieve VC_AND_SWAP_INDEX */ 4421 vc_swap_index = soc_format_field32_get(unit, NEXT_PTR_ACTION_SETfmt, 4422 &action_set, NEXT_PTRf); 4423 4424 if (vc_swap_index == 0) { 4425 4426 BCM_IF_ERROR_RETURN( 4427 _bcm_td3_mpls_get_vc_and_swap_flex_table_index(unit, 4428 &vc_swap_index)); 4429 } else { 4430 /* Retrieve VC_AND_SWAP_TABLE entry */ 4431 BCM_IF_ERROR_RETURN( 4432 soc_mem_read(unit, view_id, 4433 MEM_BLOCK_ALL, vc_swap_index, &vc_entry)); 4434 } 4435 } else if ((egr->mpls_label == BCM_MPLS_LABEL_INVALID) && 4436 (flags & BCM_L3_REPLACE)) { 4437 rv = _bcm_td3_mpls_gre_label_delete (unit, nh_index, nh_view_id); 4438 return rv; 4439 } else { 4440 4441 BCM_IF_ERROR_RETURN( 4442 _bcm_td3_mpls_get_vc_and_swap_flex_table_index(unit, 4443 &vc_swap_index)); 4444 } 4445 /* Retrieve hardware index for mapping pointer */ 4446 if ((egr->mpls_flags & BCM_MPLS_EGRESS_LABEL_EXP_SET) || 4447 (egr->mpls_flags & BCM_MPLS_EGRESS_LABEL_PRI_SET)) { 4448 /* Mapping pointer not used */ 4449 hw_map_idx = -1; 4450 } else { 4451 num_mpls_map = soc_mem_index_count(unit, EGR_MPLS_EXP_MAPPING_1m) / 64; 4452 rv = _egr_qos_id2hw_idx(unit,egr->mpls_qos_map_id,&hw_map_idx); 4453 if ((rv != BCM_E_NONE) || hw_map_idx < 0 || hw_map_idx >= num_mpls_map) { 4454 if (egr->mpls_flags & BCM_MPLS_EGRESS_LABEL_EXP_REMARK) { 4455 rv = BCM_E_PARAM; 4456 goto cleanup; 4457 } else { 4458 hw_map_idx = 0; /* use default */ 4459 } 4460 } 4461 } 4462 4463 /* Program the MPLS_VC_AND_SWAP table entry */ 4464 rv = _bcm_td3_mpls_vc_and_swap_table_flex_entry_set(unit, egr, view_id, 4465 _BCM_MPLS_ACTION_PUSH, &vc_entry, 4466 hw_map_idx, vc_swap_index); 4467 if (rv < 0){ 4468 goto cleanup; 4469 } 4470 4471 rv = soc_mem_write(unit, view_id, 4472 MEM_BLOCK_ALL, vc_swap_index, 4473 &vc_entry); 4474 if (rv < 0){ 4475 goto cleanup; 4476 } 4477 /* 4478 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 4479 &egr_nh, nh_entry_type_field, 4480 entry_type); 4481 */ 4482 4483 action_set = 0; 4484 soc_format_field32_set(unit, NEXT_PTR_ACTION_SETfmt, 4485 &action_set, NEXT_PTR_TYPEf, 4486 BCMI_TD3_L3_NH_EGR_NEXT_PTR_TYPE_VC_SWAP); 4487 /* VC_AND_SWAP_INDEXf */ 4488 soc_format_field32_set(unit, NEXT_PTR_ACTION_SETfmt, 4489 &action_set, NEXT_PTRf, 4490 vc_swap_index); 4491 soc_mem_field32_set(unit, nh_view_id, &egr_nh, 4492 NEXT_PTR_ACTION_SETf, action_set); 4493 4494 /* Enable HG.L3_bit 4495 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 4496 &egr_nh, MPLS__HG_L3_OVERRIDEf, 0x1); 4497 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 4498 &egr_nh, MPLS__HG_MODIFY_ENABLEf, 0x1); 4499 */ 4500 4501 rv = soc_mem_write(unit, nh_view_id, 4502 MEM_BLOCK_ALL, nh_index, &egr_nh); 4503 4504 if (rv < 0) { 4505 goto cleanup; 4506 } 4507 #ifdef BCM_WARM_BOOT_SUPPORT 4508 SOC_CONTROL_LOCK(unit); 4509 SOC_CONTROL(unit)->scache_dirty = 1; 4510 SOC_CONTROL_UNLOCK(unit); 4511 #endif 4512 4513 return rv; 4514 4515 cleanup: 4516 if (vc_swap_index != -1) { 4517 _bcm_tr_mpls_vc_and_swap_ref_count_adjust (unit, vc_swap_index, -1); 4518 /* Free VC_AND_SWAP_LABEL entry */ 4519 (void)_bcm_td3_mpls_vc_and_swap_flex_table_index_reset (unit, vc_swap_index); 4520 } 4521 return rv; 4522 } 4523 /* 4524 * Function: 4525 * _bcm_td3_mpls_gre_label_get 4526 * Purpose: 4527 * Retrieves the Inner_LABEL within VC_AND_SWAP_TABLE for a specific EGR_NH Index 4528 * Parameters: 4529 * IN : Unit 4530 * IN : mpls_label 4531 * IN : nh_index 4532 * Returns: 4533 * BCM_E_XXX 4534 */ 4535 4536 int 4537 _bcm_td3_mpls_gre_label_get (int unit, int vc_swap_index, bcm_l3_egress_t *egr) 4538 { 4539 int rv=BCM_E_NONE; 4540 egr_mpls_vc_and_swap_label_table_entry_t vc_entry; 4541 uint32 label_action; 4542 uint32 action_set; 4543 uint32 opaque_array[_BCM_FLOW_LOGICAL_FIELD_MAX]; 4544 uint32 opaque_count; 4545 int8 data_type; 4546 uint32 view_id; 4547 bcm_flow_logical_field_t* user_fields; 4548 soc_flow_db_ffo_t ffo[SOC_FLOW_DB_MAX_VIEW_FFO_TPL]; 4549 uint32 num_ffo = 0; 4550 uint32 mpls_hdr; 4551 int i; 4552 4553 if (vc_swap_index != -1) { 4554 /* Retrieve VC_AND_SWAP_TABLE entry */ 4555 BCM_IF_ERROR_RETURN( 4556 soc_mem_read(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 4557 MEM_BLOCK_ALL, vc_swap_index, &vc_entry)); 4558 4559 data_type = soc_mem_field32_get(unit, 4560 EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, &vc_entry, DATA_TYPEf); 4561 4562 if (data_type == 0) { /* fixed view */ 4563 egr->mpls_label = BCM_MPLS_LABEL_INVALID; 4564 return rv; 4565 } 4566 4567 BCM_IF_ERROR_RETURN( 4568 soc_flow_db_mem_to_view_id_get(unit, 4569 EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 4570 SOC_FLOW_DB_KEY_TYPE_INVALID, 4571 data_type, 4572 0, 4573 NULL, 4574 &view_id)); 4575 4576 BCM_IF_ERROR_RETURN( 4577 soc_flow_db_mem_view_to_ffo_get(unit, 4578 view_id, 4579 SOC_FLOW_DB_MAX_VIEW_FFO_TPL, 4580 ffo, 4581 &num_ffo)); 4582 4583 egr->flow_label_option_handle = ffo[0].option_id; 4584 4585 /* Get logical field list for this view id. */ 4586 BCM_IF_ERROR_RETURN( 4587 soc_flow_db_mem_view_field_list_get(unit, 4588 view_id, 4589 SOC_FLOW_DB_FIELD_TYPE_LOGICAL_POLICY_DATA, 4590 _BCM_FLOW_LOGICAL_FIELD_MAX, 4591 opaque_array, 4592 &opaque_count)); 4593 4594 user_fields = egr->logical_fields; 4595 4596 for (i=0; i<opaque_count; i++) { 4597 user_fields[i].id = opaque_array[i]; 4598 user_fields[i].value = soc_mem_field32_get(unit, view_id, &vc_entry, user_fields[i].id); 4599 } 4600 4601 if (SOC_MEM_FIELD_VALID(unit, view_id, MPLS_ENTRY_0_ACTION_SETf)) { 4602 egr->mpls_label = BCM_MPLS_LABEL_INVALID; 4603 4604 action_set = soc_mem_field32_get(unit, view_id, &vc_entry, 4605 MPLS_ENTRY_0_ACTION_SETf); 4606 4607 label_action = soc_format_field32_get(unit, 4608 MPLS_ENTRY_ACTION_SETfmt, 4609 &action_set, MPLS_PUSH_ACTIONf); 4610 4611 if (label_action == _BCM_MPLS_ACTION_PUSH) { /* PUSH */ 4612 egr->flags2 |= BCM_L3_MPLS_GRE_LABEL; 4613 egr->mpls_label = 4614 soc_format_field32_get(unit, MPLS_ENTRY_ACTION_SETfmt, 4615 &action_set, MPLS_LABELf); 4616 egr->mpls_ttl = 4617 soc_format_field32_get(unit, MPLS_ENTRY_ACTION_SETfmt, 4618 &action_set, MPLS_TTLf); 4619 if (egr->mpls_ttl) { 4620 egr->mpls_flags |= BCM_MPLS_EGRESS_LABEL_TTL_SET; 4621 } 4622 4623 } else { 4624 egr->mpls_label = BCM_MPLS_LABEL_INVALID; 4625 } 4626 } 4627 if (SOC_MEM_FIELD_VALID(unit, view_id, DIRECT_ASSIGNMENT_21_ACTION_SETf)) { 4628 mpls_hdr = soc_mem_field32_get(unit, view_id, &vc_entry, 4629 DIRECT_ASSIGNMENT_21_ACTION_SETf); 4630 egr->mpls_label = mpls_hdr & 0xfffff; 4631 egr->mpls_exp = (mpls_hdr >> 20) & 0xf; 4632 egr->mpls_ttl = (mpls_hdr >> 24) & 0xff; 4633 } 4634 } else { 4635 egr->mpls_label = BCM_MPLS_LABEL_INVALID; 4636 } 4637 egr->flags2 |= BCM_L3_MPLS_GRE_LABEL; 4638 4639 return rv; 4640 } 4641 /* 4642 * Function: 4643 * _bcm_td3_mpls_gre_label_delete 4644 * Purpose: 4645 * Deletes Inner_LABEL within VC_AND_SWAP_TABLE for a specific EGR_NH Index 4646 * Parameters: 4647 * IN : Unit 4648 * IN : nh_index 4649 * IN : view_id 4650 * Returns: 4651 * BCM_E_XXX 4652 */ 4653 int 4654 _bcm_td3_mpls_gre_label_delete (int unit, int index, soc_mem_t view_id) 4655 { 4656 int rv=BCM_E_NONE; 4657 int vc_swap_index=-1; 4658 egr_l3_next_hop_entry_t egr_nh; 4659 uint8 entry_type; 4660 /*int macda_index=-1;*/ 4661 uint32 action_set; 4662 4663 BCM_IF_ERROR_RETURN (soc_mem_read(unit, EGR_L3_NEXT_HOPm, MEM_BLOCK_ANY, 4664 index, &egr_nh)); 4665 4666 /* Retrieve and Verify ENTRY_TYPE */ 4667 entry_type = 4668 soc_mem_field32_get(unit, view_id, &egr_nh, DATA_TYPEf); 4669 4670 if (!BCMI_L3_NH_FLEX_VIEW(entry_type)) { 4671 return BCM_E_PARAM; 4672 } 4673 4674 /* Don't change the Entry_Type to Normal since this is a flex view */ 4675 4676 /* Delete MAC_DA_PROFILE_INDEX 4677 if (soc_feature(unit, soc_feature_mpls_enhanced)) { 4678 macda_index = 4679 soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, 4680 MPLS__MAC_DA_PROFILE_INDEXf); 4681 } 4682 4683 if (macda_index != -1) { 4684 _bcm_mac_da_profile_entry_delete(unit, macda_index); 4685 } 4686 */ 4687 4688 /* Retrieve VC_AND_SWAP_INDEX */ 4689 action_set = soc_mem_field32_get(unit, view_id, &egr_nh, 4690 NEXT_PTR_ACTION_SETf); 4691 4692 if (soc_format_field32_get(unit, NEXT_PTR_ACTION_SETfmt, 4693 &action_set, NEXT_PTR_TYPEf) != 4694 BCMI_TD3_L3_NH_EGR_NEXT_PTR_TYPE_VC_SWAP) { 4695 /* this entry doesn't have a vc_swap index */ 4696 return BCM_E_PARAM; 4697 } 4698 /* Retrieve VC_AND_SWAP_INDEX */ 4699 vc_swap_index = soc_format_field32_get(unit, NEXT_PTR_ACTION_SETfmt, 4700 &action_set, NEXT_PTRf); 4701 4702 /* Decrease refcount on table idx */ 4703 _bcm_tr_mpls_vc_and_swap_ref_count_adjust (unit, vc_swap_index, -1); 4704 4705 BCM_IF_ERROR_RETURN 4706 (_bcm_td3_mpls_vc_and_swap_flex_table_index_reset (unit, vc_swap_index)); 4707 4708 vc_swap_index = 0; 4709 soc_format_field32_set(unit, NEXT_PTR_ACTION_SETfmt, 4710 &action_set, NEXT_PTRf, 4711 vc_swap_index); 4712 4713 soc_mem_field32_set(unit, view_id, &egr_nh, 4714 NEXT_PTR_ACTION_SETf, action_set); 4715 4716 rv = soc_mem_write(unit, view_id, 4717 MEM_BLOCK_ALL, index, &egr_nh); 4718 4719 #ifdef BCM_WARM_BOOT_SUPPORT 4720 SOC_CONTROL_LOCK(unit); 4721 SOC_CONTROL(unit)->scache_dirty = 1; 4722 SOC_CONTROL_UNLOCK(unit); 4723 #endif 4724 4725 return rv; 4726 } 4727 4728 /* 4729 * Function: 4730 * bcm_td3_ipmc_egr_nh_mac_da_profile_entry_delete 4731 * Purpose: 4732 * Release the MACDA Profile pointed to by this Egress NH entry. 4733 * Parameters: 4734 * unit - SOC device unit number 4735 * nh_idx - next hop index 4736 * Returns: 4737 * BCM_E_NONE Success 4738 * BCM_E_XXX ERROR 4739 */ 4740 int 4741 bcm_td3_ipmc_egr_nh_mac_da_profile_entry_delete(int unit, int nh_idx) 4742 { 4743 soc_mem_t mem = EGR_L3_NEXT_HOPm; 4744 egr_l3_next_hop_entry_t egr_nh; /* Egress next hop entry. */ 4745 int ent_type; /* Entry type */ 4746 4747 if (!soc_mem_field_valid(unit, EGR_L3_NEXT_HOPm, L3MC__USE_MAC_DA_PROFILEf)) { 4748 return BCM_E_NONE; 4749 } 4750 sal_memset(&egr_nh, 0, sizeof(egr_l3_next_hop_entry_t)); 4751 4752 SOC_IF_ERROR_RETURN(BCM_XGS3_MEM_READ(unit, mem, nh_idx, &egr_nh)); 4753 4754 if (soc_feature(unit, soc_feature_mem_access_data_type)) { 4755 ent_type = soc_mem_field32_get(unit, mem, &egr_nh, DATA_TYPEf); 4756 } else { 4757 ent_type = soc_mem_field32_get(unit, mem, &egr_nh, ENTRY_TYPEf); 4758 } 4759 4760 /* check if IPMC entry */ 4761 if ((ent_type == 7) && soc_mem_field32_get(unit, mem, &egr_nh, 4762 L3MC__USE_MAC_DA_PROFILEf)) { 4763 uint32 macda_index; 4764 macda_index = soc_mem_field32_get(unit, mem, &egr_nh, 4765 L3MC__MAC_DA_PROFILE_INDEXf); 4766 BCM_IF_ERROR_RETURN( 4767 _bcm_mac_da_profile_entry_delete(unit, macda_index)); 4768 } 4769 return BCM_E_NONE; 4770 } 4771 4772 int 4773 bcm_td3_l3_conflict_get(int unit, bcm_l3_key_t *ipkey, bcm_l3_key_t *cf_array, 4774 int cf_max, int *cf_count) 4775 { 4776 _bcm_l3_cfg_t l3cfg; 4777 uint32 *bufp; /* Hardware buffer ptr */ 4778 soc_mem_t mem; /* L3 table memory type. */ 4779 int nh_idx, index, rv = BCM_E_NONE; /* Operation status. */ 4780 _bcm_l3_fields_t *fld; /* L3 table common fields. */ 4781 l3_entry_ipv4_unicast_entry_t l3v4_entry; 4782 l3_entry_ipv4_multicast_entry_t l3v4_ext_entry; 4783 l3_entry_ipv6_unicast_entry_t l3v6_entry; 4784 l3_entry_ipv6_multicast_entry_t l3v6_ext_entry; 4785 uint8 i, bidx, num_ent; 4786 uint32 l3_entry[SOC_MAX_MEM_WORDS]; 4787 uint32 ipmc, ipv6, embedded_nh; 4788 uint32 bucket; 4789 int num_banks, bank_id; 4790 4791 /* Make sure module was initialized. */ 4792 if (!BCM_XGS3_L3_INITIALIZED(unit)) { 4793 return (BCM_E_INIT); 4794 } 4795 4796 /* Input parameters check. */ 4797 if ((NULL == ipkey) || (NULL == cf_count) || 4798 (NULL == cf_array) || (cf_max <= 0)) { 4799 return (BCM_E_PARAM); 4800 } 4801 4802 embedded_nh = ipkey->l3k_flags & BCM_L3_DEREFERENCED_NEXTHOP; 4803 nh_idx = (embedded_nh) ? BCM_XGS3_L3_INVALID_INDEX : 0; 4804 4805 /* Translate lookup key to l3cfg format. */ 4806 BCM_IF_ERROR_RETURN(_bcm_td2_ip_key_to_l3cfg(unit, ipkey, &l3cfg)); 4807 4808 /* Get entry type. */ 4809 ipv6 = (l3cfg.l3c_flags & BCM_L3_IP6); 4810 ipmc = (l3cfg.l3c_flags & BCM_L3_IPMC); 4811 4812 /* Get table memory. */ 4813 BCM_TD3_L3_HOST_TABLE_MEM(unit, l3cfg.l3c_intf, ipv6, mem, nh_idx); 4814 mem = (ipmc) ? (ipv6 ? L3_ENTRY_QUADm : L3_ENTRY_DOUBLEm) : mem; 4815 BCM_TD3_L3_HOST_TABLE_FLD(unit, mem, ipv6, fld); 4816 BCM_TD3_L3_HOST_ENTRY_BUF(ipv6, mem, bufp, 4817 l3v4_entry, 4818 l3v4_ext_entry, 4819 l3v6_entry, 4820 l3v6_ext_entry); 4821 4822 /* Prepare host entry for addition. */ 4823 if (ipmc) { 4824 /* Zero entry buffer. */ 4825 sal_memcpy(bufp, soc_mem_entry_null(unit, mem), 4826 soc_mem_entry_words(unit,mem) * 4); 4827 BCM_IF_ERROR_RETURN(_bcm_td2_l3_ipmc_ent_init(unit, bufp, &l3cfg)); 4828 } else { 4829 BCM_IF_ERROR_RETURN(_bcm_td2_l3_ent_init(unit, mem, &l3cfg, bufp)); 4830 } 4831 4832 *cf_count = 0; 4833 4834 /* Get entries of each banks */ 4835 switch (mem) { 4836 case L3_ENTRY_SINGLEm: 4837 case L3_ENTRY_DOUBLEm: 4838 case L3_ENTRY_QUADm: 4839 num_ent = 4; 4840 break; 4841 4842 /* coverity[dead_error_begin] */ 4843 default: 4844 return BCM_E_PARAM; 4845 } 4846 #ifdef BCM_HELIX5_SUPPORT 4847 if (SOC_IS_HELIX5(unit)) { 4848 /* Get number of L3 banks */ 4849 SOC_IF_ERROR_RETURN 4850 (soc_helix5_hash_bank_count_get(unit, mem, &num_banks)); 4851 /* bank 9 and 8 are dedicated L3 banks in HX5 */ 4852 bank_id = 9; 4853 } else 4854 #endif /* BCM_HELIX5_SUPPORT */ 4855 { 4856 /* Get number of L3 banks */ 4857 SOC_IF_ERROR_RETURN 4858 (soc_trident3_hash_bank_count_get(unit, mem, &num_banks)); 4859 bank_id = 11; 4860 } 4861 /* bank 11 to 10 are dedicated L3 banks, 9 to 5 are dedicated, depends on 4862 * mode how many shared banks are assigned to l3 4863 */ 4864 for (bidx = bank_id; bidx >= (bank_id - num_banks + 1); bidx--) { 4865 /* Calculate hash index */ 4866 #ifdef BCM_HELIX5_SUPPORT 4867 if (SOC_IS_HELIX5(unit)) { 4868 rv = soc_hx5_hash_bucket_get(unit, mem, bidx, bufp, &bucket); 4869 } else 4870 #endif /* BCM_HELIX5_SUPPORT */ 4871 { 4872 rv = soc_td3_hash_bucket_get(unit, mem, bidx, bufp, &bucket); 4873 } 4874 if (SOC_FAILURE(rv)) { 4875 return rv; 4876 } 4877 #ifdef BCM_HELIX5_SUPPORT 4878 if (SOC_IS_HELIX5(unit)) { 4879 index = soc_hx5_hash_index_get(unit, mem, bidx, bucket); 4880 } else 4881 #endif /* BCM_HELIX5_SUPPORT */ 4882 { 4883 index = soc_td3_hash_index_get(unit, mem, bidx, bucket); 4884 } 4885 4886 /* Get conflicting IPs from all HW entries in current bank */ 4887 for (i = 0; (i < num_ent) && (*cf_count < cf_max);) { 4888 rv = soc_mem_read(unit, mem, COPYNO_ALL, index + i, l3_entry); 4889 if (SOC_FAILURE(rv)) { 4890 return BCM_E_MEMORY; 4891 } 4892 if (soc_mem_field32_get(unit, mem, &l3_entry, fld->valid)) { 4893 switch(soc_mem_field32_get(unit, mem, &l3_entry, fld->key_type)) { 4894 case TD3_L3_HASH_DATA_TYPE_V4UC: 4895 l3cfg.l3c_flags = 0; 4896 break; 4897 case TD3_L3_HASH_DATA_TYPE_V4UC_EXT: 4898 l3cfg.l3c_flags = BCM_L3_DEREFERENCED_NEXTHOP; 4899 break; 4900 case TD3_L3_HASH_DATA_TYPE_V4MC: 4901 l3cfg.l3c_flags = BCM_L3_IPMC; 4902 break; 4903 case TD3_L3_HASH_DATA_TYPE_V6UC: 4904 l3cfg.l3c_flags = BCM_L3_IP6; 4905 break; 4906 case TD3_L3_HASH_DATA_TYPE_V6UC_EXT: 4907 l3cfg.l3c_flags = BCM_L3_IP6 | BCM_L3_DEREFERENCED_NEXTHOP; 4908 break; 4909 case TD3_L3_HASH_DATA_TYPE_V6MC: 4910 l3cfg.l3c_flags = BCM_L3_IP6 | BCM_L3_IPMC; 4911 break; 4912 case TD3_L3_HASH_DATA_TYPE_V4L2MC: 4913 case TD3_L3_HASH_DATA_TYPE_V4L2VPMC: 4914 l3cfg.l3c_flags = BCM_L3_IPMC | BCM_L3_L2ONLY; 4915 break; 4916 case TD3_L3_HASH_DATA_TYPE_V6L2MC: 4917 case TD3_L3_HASH_KEY_TYPE_V6L2VPMC: 4918 l3cfg.l3c_flags = BCM_L3_IP6 | BCM_L3_IPMC | BCM_L3_L2ONLY; 4919 default: 4920 break; 4921 } 4922 /* Get host ip address. */ 4923 rv = _bcm_td2_l3_get_by_idx(unit, NULL, index + i, &l3cfg, &nh_idx); 4924 if (BCM_FAILURE(rv)) { 4925 continue; 4926 } 4927 4928 BCM_IF_ERROR_RETURN 4929 (_bcm_td2_l3cfg_to_ipkey(unit, cf_array + (*cf_count), &l3cfg)); 4930 if ((++(*cf_count)) >= cf_max) { 4931 break; 4932 } 4933 } 4934 /* increment based upon existing entry */ 4935 i += (mem == L3_ENTRY_QUADm) ? 2 : 1; 4936 } 4937 4938 /* Stop loop if conflicting IPs got from HW is no less than cf_max. */ 4939 if ((*cf_count) >= cf_max) { 4940 break; 4941 } 4942 } 4943 return BCM_E_NONE; 4944 } 4945 4946 4947 #ifdef SOC_L3_ECMP_PROTECTED_ACCESS_SUPPORT 4948 /* 4949 * Function: 4950 * bcm_td3x_l3_ecmp_protected_grp_get 4951 * Purpose: 4952 * Get ecmp group next hop members by index. 4953 * Parameters: 4954 * unit - (IN)SOC unit number. 4955 * ecmp_grp - (IN)Ecmp group id to read. 4956 * ecmp_group_size - (IN)Maximum number of entries to read. 4957 * nh_list - (OUT)Next hop index list. 4958 * Returns: 4959 * BCM_E_XXX 4960 */ 4961 int 4962 bcm_td3x_l3_ecmp_protected_grp_get(int unit, 4963 int ecmp_grp, 4964 int ecmp_group_size, 4965 int *nh_list) 4966 { 4967 int rv = BCM_E_UNAVAIL; 4968 int i = 0; 4969 uint32 alloc_sz = 0; 4970 soc_esw_ecmp_group_info_t grp_info = {0}; 4971 soc_esw_ecmp_member_info_t *mem_array = NULL; 4972 4973 /* Input parameters sanity check. */ 4974 if ((NULL == nh_list) || (ecmp_group_size < 1)) { 4975 return (BCM_E_PARAM); 4976 } 4977 4978 /* Zero all next hop indexes first. */ 4979 sal_memset(nh_list, 0, ecmp_group_size * sizeof(int)); 4980 4981 alloc_sz = (ecmp_group_size * sizeof(soc_esw_ecmp_member_info_t)); 4982 mem_array = sal_alloc(alloc_sz, "NH array"); 4983 if (NULL == mem_array) { 4984 return BCM_E_MEMORY; 4985 } 4986 4987 sal_memset(mem_array, 0, alloc_sz); 4988 4989 SOC_ESW_ECMP_LOCK(unit); 4990 4991 /* Calculate Base_ptr table index. */ 4992 grp_info.ecmp_grp = ecmp_grp; 4993 rv = soc_esw_ecmp_protected_grp_get(unit, &grp_info, mem_array); 4994 if (rv != BCM_E_NONE) { 4995 goto exit; 4996 } 4997 4998 for (i = 0; i < ecmp_group_size; i++) { 4999 nh_list[i] = mem_array[i].nh; 5000 } 5001 5002 exit: 5003 if (mem_array != NULL) { 5004 sal_free(mem_array); 5005 } 5006 SOC_ESW_ECMP_UNLOCK(unit); 5007 5008 return rv; 5009 } 5010 5011 /* 5012 * Function: 5013 * bcm_td3x_l3_ecmp_protected_grp_add 5014 * Purpose: 5015 * Add ecmp group next hop members, or reset ecmp group entry. 5016 * NOTE: Function always writes all the entries in ecmp group. 5017 * If there is not enough nh indexes - next hops written 5018 * in cycle. 5019 * Parameters: 5020 * unit - (IN)SOC unit number. 5021 * ecmp_grp - (IN)ecmp group id to write. 5022 * buf - (IN)Next hop indexes or NULL for entry reset. 5023 * info - (IN)ECMP additional info 5024 * Returns: 5025 * BCM_E_XXX 5026 */ 5027 int 5028 bcm_td3x_l3_ecmp_protected_grp_add(int unit, 5029 int ecmp_grp, 5030 void *buf, 5031 void *info) 5032 { 5033 uint32 l3_ecmp_grp_buf[SOC_MAX_MEM_FIELD_WORDS]; 5034 uint32 reg_val, value, alloc_sz; 5035 int max_grp_size = 0; /* Maximum ecmp group size.*/ 5036 int old_max_paths = 0; 5037 int ecmp_idx; /* Ecmp table entry index. */ 5038 int idx; /* Iteration index. */ 5039 int *nh_list; /* Ecmp group nh indexes. */ 5040 int rv = BCM_E_NONE; /* Operation return value. */ 5041 int entry_type; 5042 int intf_count = 0; 5043 int grp_exists = 0; 5044 uint8 grp_added = 0; 5045 soc_esw_ecmp_bank_lkup_level_t level; 5046 _bcm_l3_tbl_op_t data; 5047 soc_mem_t grp_mem = L3_ECMP_COUNTm; 5048 int ecmp_table_incr = 0; 5049 _bcm_l3_ecmp_group_info_t *ecmp_info = info; 5050 _bcm_l3_ecmp_group_buffer_t *ecmp_buffer = buf; 5051 ing_l3_next_hop_entry_t ing_nh; 5052 initial_l3_ecmp_group_entry_t initial_l3_ecmp_group_entry; 5053 int l3_ecmp_oif_flds[8] = { 5054 L3_OIF_0f, 5055 L3_OIF_1f, 5056 L3_OIF_2f, 5057 L3_OIF_3f, 5058 L3_OIF_4f, 5059 L3_OIF_5f, 5060 L3_OIF_6f, 5061 L3_OIF_7f}; 5062 int l3_ecmp_oif_type_flds[8] ={ 5063 L3_OIF_0_TYPEf, 5064 L3_OIF_1_TYPEf, 5065 L3_OIF_2_TYPEf, 5066 L3_OIF_3_TYPEf, 5067 L3_OIF_4_TYPEf, 5068 L3_OIF_5_TYPEf, 5069 L3_OIF_6_TYPEf, 5070 L3_OIF_7_TYPEf }; 5071 5072 soc_esw_ecmp_group_info_t grp_info = {0}; 5073 soc_esw_ecmp_member_info_t *mem_array = NULL; 5074 5075 /* Input parameters check. */ 5076 if (NULL == ecmp_buffer || NULL == ecmp_info || 5077 NULL == ecmp_buffer->group_buffer) { 5078 return (BCM_E_PARAM); 5079 } 5080 5081 /* Cast input buffer. */ 5082 nh_list = ecmp_buffer->group_buffer; 5083 max_grp_size = ecmp_info->max_paths; 5084 5085 alloc_sz = (max_grp_size * sizeof(soc_esw_ecmp_member_info_t)); 5086 mem_array = sal_alloc(alloc_sz, "NH array"); 5087 if (NULL == mem_array) { 5088 return BCM_E_MEMORY; 5089 } 5090 sal_memset(mem_array, 0, alloc_sz); 5091 5092 SOC_ESW_ECMP_LOCK(unit); 5093 for (idx = 0; idx < max_grp_size; idx++) { 5094 mem_array[idx].nh = nh_list[idx]; 5095 } 5096 5097 if (BCM_XGS3_L3_ENT_REF_CNT(BCM_XGS3_L3_TBL_PTR(unit, 5098 ecmp_grp), ecmp_grp)) { 5099 /* Group already exists, get base ptr from group table */ 5100 rv = _bcm_xgs3_l3_ecmp_grp_info_get(unit, ecmp_grp, NULL, &ecmp_idx); 5101 _BCM_TD3X_L3_ERR_EXIT(rv); 5102 5103 rv = _bcm_xgs3_ecmp_max_grp_size_get(unit, ecmp_grp, 5104 &old_max_paths); 5105 _BCM_TD3X_L3_ERR_EXIT(rv); 5106 5107 grp_exists = 1; 5108 } else { 5109 /* Get index to the first slot in the ECMP table 5110 * that can accomodate max_grp_size */ 5111 data.width = ecmp_info->max_paths; 5112 data.tbl_ptr = BCM_XGS3_L3_TBL_PTR(unit, ecmp); 5113 data.oper_flags = _BCM_L3_SHR_TABLE_TRAVERSE_CONTROL; 5114 /* 5115 * we can look into the ecmp_grp index to know if this 5116 * is overlay entry or underlay entry. 5117 */ 5118 if (BCMI_L3_ECMP_IS_MULTI_LEVEL(unit)) { 5119 if (ecmp_grp < BCMI_L3_ECMP_OVERLAY_ENTRIES(unit)) { 5120 5121 data.oper_flags |= _BCM_L3_SHR_OVERLAY_OBJECT; 5122 } 5123 } 5124 data.entry_index = -1; 5125 if (ecmp_info->ecmp_flags & BCM_L3_ECMP_OVERLAY) { 5126 level = socEswEcmpBankLkupLevelOverlay; 5127 } else { 5128 level = socEswEcmpBankLkupLevelUnderlay; 5129 } 5130 rv = bcm_td3x_l3_ecmp_free_idx_get(unit, 5131 level, 5132 ecmp_info->max_paths, 5133 &ecmp_idx); 5134 _BCM_TD3X_L3_ERR_EXIT(rv); 5135 5136 data.entry_index = ecmp_idx; 5137 BCM_XGS3_L3_ENT_REF_CNT_INC(data.tbl_ptr, ecmp_idx, max_grp_size); 5138 ecmp_table_incr = 1; 5139 } 5140 5141 soc_esw_ecmp_group_info_t_init(&grp_info); 5142 grp_info.ecmp_grp = ecmp_grp; 5143 grp_info.ecmp_member_base = ecmp_idx; 5144 grp_info.max_paths = max_grp_size; 5145 grp_info.flags = ecmp_info->ecmp_flags; 5146 rv = soc_esw_ecmp_protected_grp_add(unit, &grp_info, mem_array); 5147 _BCM_TD3X_L3_ERR_EXIT(rv); 5148 5149 grp_added = 1; 5150 if (ecmp_idx != grp_info.ecmp_member_base) { 5151 if (grp_exists == 1) { 5152 BCM_XGS3_L3_ENT_REF_CNT_DEC(BCM_XGS3_L3_TBL_PTR(unit, ecmp), 5153 ecmp_idx, old_max_paths); 5154 } 5155 ecmp_idx = grp_info.ecmp_member_base; 5156 BCM_XGS3_L3_ENT_REF_CNT_INC(BCM_XGS3_L3_TBL_PTR(unit, ecmp), 5157 ecmp_idx, max_grp_size); 5158 } 5159 5160 if (BCM_SUCCESS(rv)) { 5161 /* mode 0 = 512 ecmp groups */ 5162 if (!BCM_XGS3_L3_MAX_ECMP_MODE(unit)) { 5163 /* Set Max Group Size. */ 5164 sal_memset(l3_ecmp_grp_buf, 0, 5165 SOC_MAX_MEM_FIELD_WORDS * sizeof(uint32)); 5166 rv = _bcm_xgs3_l3_ecmp_grp_info_set(unit, (ecmp_grp + 1), 5167 l3_ecmp_grp_buf, 5168 NULL, 0, 5169 max_grp_size, -1, 0, 5170 ecmp_info->ecmp_flags); 5171 _BCM_TD3X_L3_ERR_EXIT(rv); 5172 5173 rv = soc_mem_write(unit, grp_mem, MEM_BLOCK_ALL, 5174 (ecmp_grp + 1), l3_ecmp_grp_buf); 5175 _BCM_TD3X_L3_ERR_EXIT(rv); 5176 } 5177 5178 sal_memset(l3_ecmp_grp_buf, 5179 0, 5180 SOC_MAX_MEM_FIELD_WORDS * sizeof(uint32)); 5181 5182 sal_memset (&initial_l3_ecmp_group_entry, 5183 0, 5184 sizeof(initial_l3_ecmp_group_entry_t)); 5185 5186 for (idx = 0; idx < max_grp_size; idx++) { 5187 if (!nh_list[idx]) { 5188 break; 5189 } 5190 if (soc_feature(unit, soc_feature_urpf)) { 5191 /* Check if URPF is enabled on device */ 5192 rv = READ_L3_DEFIP_RPF_CONTROLr(unit, ®_val); 5193 _BCM_TD3X_L3_ERR_EXIT(rv); 5194 5195 if (reg_val) { 5196 if (idx < 8) { 5197 rv = soc_mem_read(unit, ING_L3_NEXT_HOPm, MEM_BLOCK_ANY, 5198 nh_list[idx], &ing_nh); 5199 _BCM_TD3X_L3_ERR_EXIT(rv); 5200 5201 entry_type = 5202 soc_ING_L3_NEXT_HOPm_field32_get(unit, 5203 &ing_nh, ENTRY_TYPEf); 5204 5205 if (entry_type == 0x0) { 5206 if (SOC_MEM_FIELD_VALID(unit, ING_L3_NEXT_HOPm, 5207 L3_OIFf)) { 5208 value = soc_ING_L3_NEXT_HOPm_field32_get( 5209 unit, &ing_nh, L3_OIFf); 5210 } else { 5211 value = soc_ING_L3_NEXT_HOPm_field32_get( 5212 unit, &ing_nh, VLAN_IDf); 5213 } 5214 soc_mem_field32_set(unit, L3_ECMP_COUNTm, l3_ecmp_grp_buf, 5215 l3_ecmp_oif_type_flds[idx], entry_type); 5216 soc_mem_field32_set(unit, L3_ECMP_COUNTm, l3_ecmp_grp_buf, 5217 l3_ecmp_oif_flds[idx], value); 5218 } else if (entry_type == 0x1) { 5219 value = soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, L3_OIFf); 5220 soc_mem_field32_set(unit, L3_ECMP_COUNTm, l3_ecmp_grp_buf, 5221 l3_ecmp_oif_type_flds[idx], entry_type); 5222 soc_mem_field32_set(unit, L3_ECMP_COUNTm, l3_ecmp_grp_buf, 5223 l3_ecmp_oif_flds[idx], value); 5224 } 5225 soc_mem_field32_set(unit, L3_ECMP_COUNTm, l3_ecmp_grp_buf, URPF_COUNTf, idx); 5226 } else { 5227 /* Inorder to avoid TRAP_TO_CPU, urpf_mode on L3_IIF/PORT must be set 5228 to STRICT_MODE / LOOSE_MODE */ 5229 soc_mem_field32_set(unit, L3_ECMP_COUNTm, l3_ecmp_grp_buf, ECMP_GT8f , 1); 5230 } 5231 } 5232 } 5233 } 5234 intf_count = idx; 5235 rv = _bcm_xgs3_l3_ecmp_grp_info_set(unit, ecmp_grp, 5236 l3_ecmp_grp_buf, 5237 &initial_l3_ecmp_group_entry, TRUE, 5238 intf_count, 5239 ecmp_idx, 5240 ecmp_info->alternate_cnt, 5241 ecmp_info->ecmp_flags); 5242 _BCM_TD3X_L3_ERR_EXIT(rv); 5243 5244 rv = soc_mem_write(unit, INITIAL_L3_ECMP_GROUPm, MEM_BLOCK_ALL, 5245 ecmp_grp, &initial_l3_ecmp_group_entry); 5246 _BCM_TD3X_L3_ERR_EXIT(rv); 5247 5248 /* Preserve the fields related to resilient hashing */ 5249 if (soc_feature(unit, soc_feature_ecmp_resilient_hash)) { 5250 ecmp_count_entry_t old_ecmp_count_entry; 5251 int enhanced_hashing_enable; 5252 int rh_flow_set_base; 5253 int rh_flow_set_size; 5254 5255 rv = READ_L3_ECMP_COUNTm(unit, MEM_BLOCK_ANY, 5256 ecmp_grp, &old_ecmp_count_entry); 5257 _BCM_TD3X_L3_ERR_EXIT(rv); 5258 5259 enhanced_hashing_enable = soc_mem_field32_get(unit, L3_ECMP_COUNTm, 5260 &old_ecmp_count_entry, LB_MODEf); 5261 rh_flow_set_base = soc_mem_field32_get(unit, L3_ECMP_COUNTm, 5262 &old_ecmp_count_entry, RH_FLOW_SET_BASEf); 5263 rh_flow_set_size = soc_mem_field32_get(unit, L3_ECMP_COUNTm, 5264 &old_ecmp_count_entry, RH_FLOW_SET_SIZEf); 5265 soc_mem_field32_set(unit, L3_ECMP_COUNTm, l3_ecmp_grp_buf, 5266 LB_MODEf, enhanced_hashing_enable); 5267 soc_mem_field32_set(unit, L3_ECMP_COUNTm, l3_ecmp_grp_buf, 5268 RH_FLOW_SET_BASEf, rh_flow_set_base); 5269 soc_mem_field32_set(unit, L3_ECMP_COUNTm, l3_ecmp_grp_buf, 5270 RH_FLOW_SET_SIZEf, rh_flow_set_size); 5271 } 5272 5273 rv = soc_mem_write(unit, grp_mem, MEM_BLOCK_ALL, 5274 ecmp_grp, l3_ecmp_grp_buf); 5275 _BCM_TD3X_L3_ERR_EXIT(rv); 5276 5277 /* mode 1 = max possible ecmp groups */ 5278 if (BCM_XGS3_L3_MAX_ECMP_MODE(unit)) { 5279 /* Save the max possible paths for this ECMP group in s/w */ 5280 BCM_XGS3_L3_MAX_PATHS_PERGROUP_PTR(unit)[ecmp_grp] = ecmp_info->max_paths; 5281 } 5282 } 5283 5284 _BCM_TD3X_L3_ERR_EXIT(rv); 5285 5286 exit: 5287 if (mem_array != NULL) { 5288 sal_free(mem_array); 5289 } 5290 if (rv != BCM_E_NONE) { 5291 if (ecmp_table_incr == 1) { 5292 BCM_XGS3_L3_ENT_REF_CNT_DEC(BCM_XGS3_L3_TBL_PTR(unit, ecmp), 5293 ecmp_idx, max_grp_size); 5294 } 5295 5296 if (grp_added == 1) { 5297 soc_esw_ecmp_protected_grp_delete(unit, &grp_info); 5298 } 5299 } 5300 SOC_ESW_ECMP_UNLOCK(unit); 5301 return rv; 5302 } 5303 5304 5305 /* 5306 * Function: 5307 * bcm_td3x_l3_ecmp_protected_grp_del 5308 * Purpose: 5309 * Reset ecmp group next hop members 5310 * Parameters: 5311 * unit - (IN)SOC unit number. 5312 * ecmp_grp - (IN)ecmp group id to write. 5313 * info - (IN)ECMP additional info 5314 * Returns: 5315 * BCM_E_XXX 5316 */ 5317 int 5318 bcm_td3x_l3_ecmp_protected_grp_del(int unit, 5319 int ecmp_grp, 5320 void *info) 5321 { 5322 uint32 hw_buf[SOC_MAX_MEM_FIELD_WORDS]; /* Buffer to write hw entry.*/ 5323 int ecmp_idx = 0; /* Ecmp table entry index. */ 5324 int rv = BCM_E_UNAVAIL; /* Operation return value. */ 5325 int max_ent_count = 0; /* Number of entries to read.*/ 5326 _bcm_l3_tbl_op_t data; 5327 soc_mem_t mem = L3_ECMP_COUNTm; 5328 _bcm_l3_ecmp_group_info_t *ecmp_info = info; 5329 soc_esw_ecmp_group_info_t grp_info = {0}; 5330 5331 data.tbl_ptr = BCM_XGS3_L3_TBL_PTR(unit, ecmp); 5332 5333 if (NULL == info) { 5334 return BCM_E_INTERNAL; 5335 } 5336 /* Initialize ecmp entry. */ 5337 sal_memset (hw_buf, 0, SOC_MAX_MEM_FIELD_WORDS * sizeof(uint32)); 5338 5339 SOC_ESW_ECMP_LOCK(unit); 5340 5341 rv = _bcm_xgs3_l3_ecmp_grp_info_get(unit, ecmp_grp, &max_ent_count, &ecmp_idx); 5342 _BCM_TD3X_L3_ERR_EXIT(rv); 5343 5344 grp_info.ecmp_grp = ecmp_grp; 5345 rv = soc_esw_ecmp_protected_grp_delete(unit, &grp_info); 5346 5347 /* Decrement ref count for the entries in ecmp table 5348 * Ref count for ecmp_group table is decremented in common table del func. */ 5349 BCM_XGS3_L3_ENT_REF_CNT_DEC(data.tbl_ptr, ecmp_idx, 5350 ecmp_info->max_paths); 5351 5352 if (SOC_MEM_IS_VALID(unit, mem)) { 5353 /* Set group base pointer. */ 5354 ecmp_idx = ecmp_grp; 5355 5356 if (SOC_MEM_IS_VALID(unit, INITIAL_L3_ECMP_GROUPm)) { 5357 rv = soc_mem_write(unit, INITIAL_L3_ECMP_GROUPm, MEM_BLOCK_ALL, 5358 ecmp_idx, hw_buf); 5359 5360 _BCM_TD3X_L3_ERR_EXIT(rv); 5361 } 5362 5363 if (!BCM_XGS3_L3_MAX_ECMP_MODE(unit)) { 5364 rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, 5365 (ecmp_idx + 1), hw_buf); 5366 _BCM_TD3X_L3_ERR_EXIT(rv); 5367 } 5368 5369 /* Preserve the fields related to resilient hashing */ 5370 if (soc_feature(unit, soc_feature_ecmp_resilient_hash)) { 5371 ecmp_count_entry_t old_ecmp_count_entry; 5372 int enhanced_hashing_enable; 5373 int rh_flow_set_base; 5374 int rh_flow_set_size; 5375 5376 rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, 5377 ecmp_grp, &old_ecmp_count_entry); 5378 _BCM_TD3X_L3_ERR_EXIT(rv); 5379 5380 enhanced_hashing_enable = soc_mem_field32_get(unit, mem, 5381 &old_ecmp_count_entry, LB_MODEf); 5382 rh_flow_set_base = soc_mem_field32_get(unit, mem, 5383 &old_ecmp_count_entry, RH_FLOW_SET_BASEf); 5384 rh_flow_set_size = soc_mem_field32_get(unit, mem, 5385 &old_ecmp_count_entry, RH_FLOW_SET_SIZEf); 5386 soc_mem_field32_set(unit, mem, hw_buf, 5387 LB_MODEf, enhanced_hashing_enable); 5388 soc_mem_field32_set(unit, mem, hw_buf, 5389 RH_FLOW_SET_BASEf, rh_flow_set_base); 5390 soc_mem_field32_set(unit, mem, hw_buf, 5391 RH_FLOW_SET_SIZEf, rh_flow_set_size); 5392 } 5393 5394 rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, 5395 ecmp_idx, hw_buf); 5396 _BCM_TD3X_L3_ERR_EXIT(rv); 5397 } 5398 5399 if (BCM_XGS3_L3_MAX_ECMP_MODE(unit) && 5400 BCM_XGS3_L3_MAX_PATHS_PERGROUP_PTR(unit)) { 5401 /* Reset max paths of the deleted group */ 5402 BCM_XGS3_L3_MAX_PATHS_PERGROUP_PTR(unit)[ecmp_grp] = 0; 5403 } 5404 5405 exit: 5406 SOC_ESW_ECMP_UNLOCK(unit); 5407 return rv; 5408 } 5409 #endif /* SOC_L3_ECMP_PROTECTED_ACCESS_SUPPORT */ 5410 5411 #ifdef BCM_WARM_BOOT_SUPPORT 5412 #define BCM_WB_VERSION_1_1 SOC_SCACHE_VERSION(1,1) 5413 #define BCM_WB_VERSION_1_5 SOC_SCACHE_VERSION(1,5) 5414 5415 /* 5416 * Function: 5417 * _bcm_td3_l3_repl_l3_intf_recover 5418 * Purpose: 5419 * Recover L3 interface bitmap from scache. 5420 * Parameters: 5421 * unit - (IN) SOC unit number. 5422 * Returns: 5423 * BCM_E_XXX 5424 */ 5425 int 5426 _bcm_td3_l3_repl_l3_intf_recover(int unit){ 5427 soc_scache_handle_t scache_handle; 5428 uint8 *ipmc_scache_ptr; 5429 uint16 recovered_ver; 5430 uint32 temp_size = 0; 5431 int num_l3_intf; 5432 int rv = BCM_E_UNAVAIL; 5433 5434 num_l3_intf = soc_mem_index_count(unit, EGR_L3_INTFm); 5435 td3_l3_intf_next_hop_ipmc = sal_alloc(SHR_BITALLOCSIZE(num_l3_intf), 5436 "TD3 l3 interface bitmap"); 5437 if (NULL == td3_l3_intf_next_hop_ipmc) { 5438 return BCM_E_MEMORY; 5439 } 5440 sal_memset(td3_l3_intf_next_hop_ipmc, 0, SHR_BITALLOCSIZE(num_l3_intf)); 5441 5442 #ifdef BCM_TRIDENT2_SUPPORT 5443 if (soc_feature(unit, soc_feature_pim_bidir)) { 5444 BCM_IF_ERROR_RETURN 5445 (bcm_td2_ipmc_pim_bidir_scache_size_get(unit, &temp_size)); 5446 } 5447 #endif /* BCM_TRIDENT2_SUPPORT */ 5448 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_IPMC, 0); 5449 rv = _bcm_esw_scache_ptr_get(unit, scache_handle, FALSE, 5450 0, &ipmc_scache_ptr, 5451 BCM_WB_VERSION_1_5, &recovered_ver); 5452 if (BCM_SUCCESS(rv)) { 5453 ipmc_scache_ptr += temp_size; 5454 if (recovered_ver >= BCM_WB_VERSION_1_1) { 5455 if (soc_feature(unit, soc_feature_repl_l3_intf_use_next_hop)) { 5456 sal_memcpy(td3_l3_intf_next_hop_ipmc, ipmc_scache_ptr, 5457 SHR_BITALLOCSIZE(num_l3_intf)); 5458 } 5459 } 5460 } 5461 5462 return rv; 5463 } 5464 #endif /* BCM_WARM_BOOT_SUPPORT */ 5465 5466 #endif /*(INCLUDE_L3) && (BCM_TRIDENT3_SUPPORT) */