mpls.c (1109296B)
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: mpls.c 8 * Purpose: Manages MPLS functions 9 */ 10 #include <soc/defs.h> 11 #include <sal/core/libc.h> 12 #include <shared/bsl.h> 13 #if defined(BCM_TRIUMPH_SUPPORT) && defined(BCM_MPLS_SUPPORT) && \ 14 defined(INCLUDE_L3) 15 16 #include <soc/drv.h> 17 #include <soc/scache.h> 18 #include <soc/hash.h> 19 #include <soc/util.h> 20 #include <soc/triumph.h> 21 #include <soc/format.h> 22 #include <bcm/error.h> 23 #include <bcm/mpls.h> 24 25 26 #include <bcm_int/esw/mbcm.h> 27 #include <bcm_int/esw/l3.h> 28 #include <bcm_int/esw/firebolt.h> 29 #include <bcm_int/esw/triumph.h> 30 #include <bcm_int/esw/trx.h> 31 #include <bcm_int/esw/xgs3.h> 32 #include <bcm_int/esw/mpls.h> 33 #include <bcm_int/esw/stack.h> 34 #include <bcm_int/common/multicast.h> 35 #include <bcm_int/esw/virtual.h> 36 #include <bcm_int/esw/port.h> 37 #if defined(BCM_TOMAHAWK_SUPPORT) 38 #include <bcm_int/esw/ecn.h> 39 #endif 40 #include <bcm_int/esw/vlan.h> 41 #ifdef BCM_TRIUMPH2_SUPPORT 42 #include <bcm_int/esw/triumph2.h> 43 #endif 44 #if defined(BCM_TRIUMPH3_SUPPORT) 45 #include <bcm_int/esw/triumph3.h> 46 #endif /* BCM_TRIUMPH3_SUPPORT*/ 47 #ifdef BCM_KATANA2_SUPPORT 48 #include <bcm_int/esw/katana2.h> 49 #include <soc/katana2.h> 50 #endif 51 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 52 #include <bcm_int/esw/trident2plus.h> 53 #endif 54 #if defined(BCM_TRIDENT2PLUS_SUPPORT) || defined(BCM_TOMAHAWK_SUPPORT) 55 #include <bcm_int/esw/xgs5.h> 56 #endif 57 #if defined(BCM_SABER2_SUPPORT) 58 #include <soc/saber2.h> 59 #endif /* BCM_SABER2_SUPPORT */ 60 #if defined(BCM_TRIDENT3_SUPPORT) 61 #include <bcm_int/esw/trident3.h> 62 #endif 63 64 #include <bcm_int/esw_dispatch.h> 65 #include <bcm_int/api_xlate_port.h> 66 #include <bcm_int/esw/failover.h> 67 68 #if defined(BCM_TOMAHAWK3_SUPPORT) 69 #include <bcm_int/esw/tomahawk3.h> 70 #endif 71 extern uint32 nh_entry_type_field[SOC_MAX_NUM_DEVICES]; 72 extern void _bcm_vp_vfi_set(int unit, int vp, int vfi); 73 #ifdef BCM_WARM_BOOT_SUPPORT 74 #include <bcm_int/esw/switch.h> 75 76 #define BCM_WB_VERSION_1_13 SOC_SCACHE_VERSION(1,13) 77 #define BCM_WB_VERSION_1_12 SOC_SCACHE_VERSION(1,12) 78 #define BCM_WB_VERSION_1_11 SOC_SCACHE_VERSION(1,11) 79 #define BCM_WB_VERSION_1_10 SOC_SCACHE_VERSION(1,10) 80 #define BCM_WB_VERSION_1_9 SOC_SCACHE_VERSION(1,9) 81 #define BCM_WB_VERSION_1_8 SOC_SCACHE_VERSION(1,8) 82 #define BCM_WB_VERSION_1_7 SOC_SCACHE_VERSION(1,7) 83 #define BCM_WB_VERSION_1_6 SOC_SCACHE_VERSION(1,6) 84 #define BCM_WB_VERSION_1_5 SOC_SCACHE_VERSION(1,5) 85 #define BCM_WB_VERSION_1_4 SOC_SCACHE_VERSION(1,4) 86 #define BCM_WB_VERSION_1_3 SOC_SCACHE_VERSION(1,3) 87 #define BCM_WB_VERSION_1_2 SOC_SCACHE_VERSION(1,2) 88 #define BCM_WB_VERSION_1_1 SOC_SCACHE_VERSION(1,1) 89 #define BCM_WB_VERSION_1_0 SOC_SCACHE_VERSION(1,0) 90 #define BCM_WB_DEFAULT_VERSION BCM_WB_VERSION_1_13 91 #endif /* BCM_WARM_BOOT_SUPPORT */ 92 93 #define MPLS_VPWS_VP_NUM 3 94 95 #if defined(BCM_KATANA_SUPPORT) 96 #include <bcm_int/esw/katana.h> 97 #endif 98 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) 99 #include <bcm_int/esw/policer.h> 100 #include <bcm_int/esw/flex_ctr.h> 101 #endif 102 #if defined(BCM_TRIDENT3_SUPPORT) 103 #include <bcm_int/esw/trident3.h> 104 #include <soc/esw/cancun.h> 105 #include <soc/esw/cancun_enums.h> 106 #endif 107 108 #ifdef BCM_SPECIAL_LABEL_SUPPORT 109 char *label_type_array[5] = { "special_label_type_NONE", 110 "Special_label_type_GAL", 111 "Special_label_type_RAL", 112 "Special_label_type_SPECIAL", 113 "Special_label_type_ELI"}; 114 #endif 115 116 #if (defined(BCM_TOMAHAWK2_SUPPORT) || defined(BCM_TRIDENT3_SUPPORT)) 117 #define ECN_MAP_ID_INVALID 0xffffffff 118 #endif 119 120 121 _bcm_tr_mpls_bookkeeping_t _bcm_tr_mpls_bk_info[BCM_MAX_NUM_UNITS] = {{ 0 }}; 122 STATIC _bcm_mpls_egr_nhopList_t *_bcm_tr_mpls_nhop_headPtr[BCM_MAX_NUM_UNITS][_BCM_TR_MPLS_HASH_ELEMENTS]; 123 bcm_tr_mpls_vc_swap_table_hash_t *bcmi_vc_swap_label_hash[SOC_MAX_NUM_DEVICES]; 124 125 #define MPLS_INFO(_unit_) (&_bcm_tr_mpls_bk_info[_unit_]) 126 #define L3_INFO(_unit_) (&_bcm_l3_bk_info[_unit_]) 127 128 /* for _bcm_tr_mpls_get_vc_and_swap_table_index() function */ 129 #define ENTRIES_PER_CHUNK 0x400 130 #define CHUNK_NUM(_ix) (((_ix) - imin)/ENTRIES_PER_CHUNK) 131 132 #define SOC_VC_SWAP_LABLE_FIELD(m, f) soc_field_info_t * m##f 133 #define SOC_VC_SWAP_LABLE_FIELD_ASSIGN(m_u, s, m, f) \ 134 (s)->m##f = soc_mem_fieldinfo_get(m_u, m, f) 135 136 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_APACHE_SUPPORT) 137 #define _BCM_QOS_MAP_TYPE_MASK 0x3ff 138 #define _BCM_QOS_MAP_SHIFT 10 139 #define _BCM_QOS_MAP_TYPE_ING_QUEUE_OFFSET_MAP_TABLE 5 140 #define _BCM_QOS_MAP_ING_QUEUE_OFFSET_MAX 7 141 #define EH_TAG_TYPE_NONE 0 142 #define EH_TAG_TYPE_EXPLICT_QUEUE 1 143 #define EH_TAG_TYPE_ING_QUEUE_MAP 2 144 145 #endif 146 147 #ifdef BCM_APACHE_SUPPORT 148 #define _BCM_MPLS_FWD_LABEL1_PHB_FROM_TOS 0 149 #define _BCM_MPLS_FWD_LABEL2_PHB_FROM_TOS 1 150 #define _BCM_MPLS_FWD_LABEL3_PHB_FROM_TOS 2 151 #endif 152 153 typedef struct soc_emvasltm_field_cache_s { 154 SOC_VC_SWAP_LABLE_FIELD(EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, MPLS_LABELf); 155 SOC_VC_SWAP_LABLE_FIELD(EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, MPLS_LABEL_ACTIONf); 156 SOC_VC_SWAP_LABLE_FIELD(EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, MPLS_TTLf); 157 SOC_VC_SWAP_LABLE_FIELD(EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, CW_INSERT_FLAGf); 158 SOC_VC_SWAP_LABLE_FIELD(EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, MPLS_EXPf); 159 SOC_VC_SWAP_LABLE_FIELD(EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, NEW_PRIf); 160 SOC_VC_SWAP_LABLE_FIELD(EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, NEW_CFIf); 161 SOC_VC_SWAP_LABLE_FIELD(EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, SD_TAG_VIDf); 162 SOC_VC_SWAP_LABLE_FIELD(EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, SD_TAG_ACTION_IF_PRESENTf); 163 SOC_VC_SWAP_LABLE_FIELD(EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, SD_TAG_ACTION_IF_NOT_PRESENTf); 164 SOC_VC_SWAP_LABLE_FIELD(EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, MPLS_EXP_SELECTf); 165 SOC_VC_SWAP_LABLE_FIELD(EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, MPLS_EXP_MAPPING_PTRf); 166 } soc_emvasltm_field_cache_t; 167 168 STATIC soc_emvasltm_field_cache_t soc_emvasltm_field_cache[SOC_MAX_NUM_DEVICES]; 169 170 static soc_field_t _tnl_push_action_f[] = 171 { MPLS_PUSH_ACTION_0f, MPLS_PUSH_ACTION_1f, 172 MPLS_PUSH_ACTION_2f, MPLS_PUSH_ACTION_3f, 173 MPLS_PUSH_ACTION_4f, MPLS_PUSH_ACTION_5f, 174 MPLS_PUSH_ACTION_6f, MPLS_PUSH_ACTION_7f }; 175 176 #define SOC_MEM_VC_SWAP_F32_GET(m_unit, m_mem, m_entry_data, m_field) \ 177 soc_meminfo_fieldinfo_field32_get((&SOC_MEM_INFO(m_unit, m_mem)), (m_entry_data), \ 178 (soc_emvasltm_field_cache[(m_unit)].m_mem##m_field)) 179 180 #define SOC_MEM_VC_SWAP_F32_SET(m_unit, m_mem, m_entry_data, m_field, m_val) \ 181 soc_meminfo_fieldinfo_field32_set((&SOC_MEM_INFO(m_unit, m_mem)), (m_entry_data), \ 182 (soc_emvasltm_field_cache[(m_unit)].m_mem##m_field), (m_val)) 183 184 185 #define SOC_MEM_VC_SWAP_FIELD_VALID(m_unit, m_mem, m_field) \ 186 ((soc_emvasltm_field_cache[(m_unit)].m_mem##m_field) != NULL) 187 188 #define VC_AND_SWAP_TABLE_RESV_INDEX 0 189 190 #define _BCM_MPLS_MEPID_IN_VALID_RANGE(mep_id) (mep_id > 0 && mep_id < 8192) 191 192 STATIC int _bcm_tr_mpls_add_vp_nh(int unit, bcm_if_t egr_if, int nh_index); 193 STATIC int _bcm_tr_mpls_add_egrNhop ( int unit, bcm_if_t egress_if); 194 STATIC void _bcm_tr_mpls_cleanup_egrNhop (int unit); 195 STATIC int _bcm_tr_mpls_l2_nh_info_delete(int unit, int nh_index); 196 STATIC void _bcm_tr_mpls_vpws_vp_map_clear (int unit, bcm_vpn_t vpn); 197 STATIC void _bcm_tr_mpls_egr_tunnel_ref_count_adjust (int unit, int index, int step); 198 #ifdef BCM_KATANA_SUPPORT 199 STATIC void _bcm_tr_mpls_ing_queue_map_ref_count_adjust (int unit, int index, int step); 200 #endif /* BCM_KATANA_SUPPORT */ 201 STATIC void bcmi_tr_mpls_vc_swap_hash_cleanup(int unit); 202 STATIC int _bcm_tr_mpls_port_get(int unit, bcm_vpn_t vpn, int vp, bcm_mpls_port_t *mpls_port); 203 #if defined(BCM_TRIUMPH3_SUPPORT) 204 STATIC int _bcm_tr_mpls_vc_and_swap_hash_nhop_add (int unit, int vc_swap_index, 205 int nh_index); 206 #endif 207 208 STATIC int bcmi_egr_mpls_exp_pri_mapping_num_exp_map_get(int unit); 209 STATIC int 210 bcmi_td3_soc_mem_fields32_modify(int unit, soc_mem_t mem, int index, 211 soc_field_t field, uint32 value); 212 213 #if defined(BCM_TRIDENT3_SUPPORT) 214 STATIC int 215 bcmi_egr_dvp_attribute_nwgroup_get(int unit, int vp, int *nw_group); 216 #endif /* BCM_TRIDENT3_SUPPORT */ 217 218 #if defined(BCM_TRIDENT3_SUPPORT) 219 #define EXP_MAP_DSCP_INVALID 0xff 220 #endif 221 222 STATIC int 223 bcmi_cmh_svp_attributes_set(int unit, int entry_type, int svp, int set_flag, 224 int mpls_flags) 225 { 226 int rv = BCM_E_NONE; 227 uint32 svp_attrs_0_prof_idx = 0; 228 uint32 svp_attrs_1_prof_idx = 0; 229 uint32 flow_sel_ctrl_id_0 = 0; 230 source_vp_2_entry_t svpattrs_0; 231 svp_attrs_1_entry_t svpattrs_1; 232 233 /*VPWS or VPLS SVP ATTRIBUTES*/ 234 if ((entry_type == 1) || (entry_type == 2)) { 235 if((set_flag == TRUE) && (mpls_flags & BCM_MPLS_PORT_EGRESS_TUNNEL)) { 236 svp_attrs_0_prof_idx = 2; 237 flow_sel_ctrl_id_0 = 1; 238 239 if(mpls_flags & BCM_MPLS_PORT_CONTROL_WORD || 240 mpls_flags & BCM_MPLS_PORT_SEQUENCED) { 241 svp_attrs_1_prof_idx = 2; 242 } else { 243 svp_attrs_1_prof_idx = 1; 244 } 245 } 246 } 247 248 /*Write SVP_ATTR_0,SVP_ATTRS_1 tables*/ 249 BCM_IF_ERROR_RETURN(READ_SVP_ATTRS_1m(unit, MEM_BLOCK_ALL, 250 svp,&svpattrs_1)); 251 soc_SVP_ATTRS_1m_field_set(unit, &svpattrs_1, 252 CTRL_PROFILE_IDXf, &svp_attrs_1_prof_idx); 253 rv = WRITE_SVP_ATTRS_1m(unit, MEM_BLOCK_ALL, svp, &svpattrs_1); 254 if( rv != BCM_E_NONE) { 255 return rv; 256 } 257 258 BCM_IF_ERROR_RETURN(READ_SOURCE_VP_2m(unit, MEM_BLOCK_ALL, 259 svp,&svpattrs_0)); 260 soc_SOURCE_VP_2m_field_set(unit, &svpattrs_0, 261 CTRL_PROFILE_IDXf, &svp_attrs_0_prof_idx); 262 soc_SOURCE_VP_2m_field_set(unit, &svpattrs_0, 263 PKT_FLOW_SELECT_CTRL_ID_0f, &flow_sel_ctrl_id_0); 264 rv = WRITE_SOURCE_VP_2m(unit, MEM_BLOCK_ALL, svp, &svpattrs_0); 265 if( rv != BCM_E_NONE) { 266 return rv; 267 } 268 269 return rv; 270 } 271 272 #if defined(BCM_TRIDENT3_SUPPORT) 273 STATIC int 274 bcmi_cmh_vfi_profile_set(int unit, uint32 *vfi_profile_idx) 275 { 276 int rv = BCM_E_NONE; 277 uint32 pkt_flow_sel_ctrl_id_2 = 4; 278 uint32 en_ifilter = 1; 279 vfi_profile_entry_t vfi_profile; 280 void *entries[1]; 281 282 sal_memset(&vfi_profile, 0, sizeof(vfi_profile_entry_t)); 283 soc_VFI_PROFILEm_field_set(unit, &vfi_profile, 284 PKT_FLOW_SELECT_CTRL_ID_2f, &pkt_flow_sel_ctrl_id_2); 285 soc_VFI_PROFILEm_field_set(unit, &vfi_profile, 286 EN_IFILTERf, &en_ifilter); 287 entries[0] = &vfi_profile; 288 rv = _bcm_vfi_profile_entry_add(unit, entries, 1, vfi_profile_idx); 289 290 return rv; 291 } 292 #endif 293 294 STATIC int 295 bcmi_egr_mpls_exp_pri_mapping_num_exp_map_get(int unit) 296 { 297 int num_exp_map = 0; 298 299 #if defined(BCM_TRIDENT3_SUPPORT) 300 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 301 num_exp_map = soc_mem_index_count(unit, 302 EGR_MPLS_PRI_MAPPINGm) / 64; 303 } else 304 #endif 305 { 306 num_exp_map = soc_mem_index_count(unit, 307 EGR_MPLS_EXP_PRI_MAPPINGm) / 8; 308 } 309 310 return num_exp_map; 311 } 312 313 STATIC int 314 bcmi_td3_soc_mem_fields32_modify(int unit, soc_mem_t mem, int index, 315 soc_field_t field, uint32 value) 316 { 317 uint32 buf[SOC_MAX_MEM_WORDS]; /* Buffer to read memory entry. */ 318 int rv; /* Operation return status. */ 319 uint32 ret_val = 0,dest_type = 0; 320 int value_changed = 0; /* Flag of value changed comparing 321 between input and current reading*/ 322 323 /* Check that memory is a valid one for this unit. */ 324 if (!SOC_MEM_IS_VALID(unit, mem)) { 325 return (SOC_E_UNAVAIL); 326 } 327 328 /* Check entry index range. */ 329 if ((index > soc_mem_index_max(unit, mem)) || 330 (index < soc_mem_index_min(unit, mem))) { 331 return (SOC_E_PARAM); 332 } 333 334 /* Make sure value fits into memory field. */ 335 SOC_IF_ERROR_RETURN 336 (soc_mem_field32_fit(unit, mem, field, value)); 337 338 /* Lock the memory. */ 339 soc_mem_lock(unit, mem); 340 rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, index, buf); 341 if (SOC_FAILURE(rv)) { 342 soc_mem_unlock(unit, mem); 343 return (rv); 344 } 345 346 /* Set updated values in the buffer. */ 347 if (field == DESTINATIONf) { 348 ret_val = soc_mem_field32_dest_get(unit, mem, buf, 349 DESTINATIONf, &dest_type); 350 351 if ((dest_type == SOC_MEM_FIF_DEST_DVP) && 352 (value != ret_val)) { 353 soc_mem_field32_dest_set(unit, mem, buf, 354 DESTINATIONf, SOC_MEM_FIF_DEST_DVP, value); 355 value_changed = 1; 356 } 357 } else { 358 if(value != soc_mem_field32_get(unit, mem, buf, field)) { 359 value_changed = 1; 360 soc_mem_field32_set(unit, mem, buf, field, value); 361 } 362 } 363 364 /* Write buffer back to memory. */ 365 if(value_changed) { 366 rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, index, buf); 367 } 368 369 soc_mem_unlock(unit, mem); 370 return (rv); 371 } 372 373 #if defined(BCM_TRIDENT3_SUPPORT) 374 STATIC int 375 bcmi_egr_dvp_attribute_nwgroup_get(int unit, int vp, int *nw_group) 376 { 377 int rv=BCM_E_UNAVAIL; 378 egr_dvp_attribute_entry_t egr_dvp_attribute; 379 380 rv = soc_mem_read(unit, EGR_DVP_ATTRIBUTEm, 381 MEM_BLOCK_ALL, vp, &egr_dvp_attribute); 382 if (BCM_SUCCESS(rv)) { 383 if (soc_mem_field32_get(unit, EGR_DVP_ATTRIBUTEm, 384 &egr_dvp_attribute, COMMON__DVP_NETWORK_GROUPf)) { 385 *nw_group = soc_mem_field32_get(unit, EGR_DVP_ATTRIBUTEm, 386 &egr_dvp_attribute, COMMON__DVP_NETWORK_GROUPf); 387 } 388 } 389 return rv; 390 } 391 #endif /* BCM_TRIDENT3_SUPPORT */ 392 393 int _bcm_tr_get_ing_mpls_index_size(int unit) 394 { 395 int num_ing_exp_map; 396 397 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 398 num_ing_exp_map = 32; 399 } else { 400 num_ing_exp_map = soc_mem_index_count(unit, ING_MPLS_EXP_MAPPINGm) / 8; 401 } 402 403 return num_ing_exp_map; 404 } 405 406 /* 407 * Function: 408 * bcm_mpls_enable 409 * Purpose: 410 * Enable/disable MPLS function. 411 * Parameters: 412 * unit - SOC unit number. 413 * enable - TRUE: enable MPLS support; FALSE: disable MPLS support. 414 * Returns: 415 * BCM_E_XXX. 416 */ 417 STATIC int 418 bcm_tr_mpls_enable(int unit, int enable) 419 { 420 int port, rv = BCM_E_NONE; 421 bcm_pbmp_t port_pbmp; 422 423 BCM_PBMP_CLEAR(port_pbmp); 424 BCM_PBMP_ASSIGN(port_pbmp, PBMP_PORT_ALL(unit)); 425 #ifdef BCM_KATANA2_SUPPORT 426 if (SOC_IS_KATANA2(unit) && soc_feature(unit, soc_feature_flex_port)) { 427 BCM_IF_ERROR_RETURN(_bcm_kt2_flexio_pbmp_update(unit, &port_pbmp)); 428 } 429 if (soc_feature(unit, soc_feature_linkphy_coe) || 430 soc_feature(unit, soc_feature_subtag_coe)) { 431 _bcm_kt2_subport_pbmp_update(unit, &port_pbmp); 432 } 433 #endif 434 435 PBMP_ITER(port_pbmp, port) { 436 /* No mpls lookup on stacking ports. */ 437 if (IS_ST_PORT(unit, port)) { 438 continue; 439 } 440 BCM_IF_ERROR_RETURN 441 (bcm_esw_port_control_set(unit, port, bcmPortControlMpls, 442 (enable) ? 1 : 0)); 443 } 444 return rv; 445 } 446 447 /* 448 * Function: 449 * _bcm_tr_mpls_free_resource 450 * Purpose: 451 * Free all allocated tables and memory 452 * Parameters: 453 * unit - SOC unit number 454 * Returns: 455 * Nothing 456 */ 457 STATIC void 458 _bcm_tr_mpls_free_resource(int unit, _bcm_tr_mpls_bookkeeping_t *mpls_info) 459 { 460 if (!mpls_info) { 461 return; 462 } 463 464 if (mpls_info->vrf_bitmap) { 465 sal_free(mpls_info->vrf_bitmap); 466 mpls_info->vrf_bitmap = NULL; 467 } 468 469 if (mpls_info->vpws_bitmap) { 470 sal_free(mpls_info->vpws_bitmap); 471 mpls_info->vpws_bitmap = NULL; 472 } 473 474 if (mpls_info->vpws_vp_map) { 475 sal_free(mpls_info->vpws_vp_map); 476 mpls_info->vpws_vp_map = NULL; 477 } 478 479 if (mpls_info->trunk_vp_map) { 480 sal_free(mpls_info->trunk_vp_map); 481 mpls_info->trunk_vp_map = NULL; 482 } 483 484 if (mpls_info->vc_c_bitmap) { 485 sal_free(mpls_info->vc_c_bitmap); 486 mpls_info->vc_c_bitmap = NULL; 487 } 488 489 if (mpls_info->vc_nc_bitmap) { 490 sal_free(mpls_info->vc_nc_bitmap); 491 mpls_info->vc_nc_bitmap = NULL; 492 } 493 494 if (mpls_info->pw_term_bitmap) { 495 sal_free(mpls_info->pw_term_bitmap); 496 mpls_info->pw_term_bitmap = NULL; 497 } 498 499 if (mpls_info->pw_init_bitmap) { 500 sal_free(mpls_info->pw_init_bitmap); 501 mpls_info->pw_init_bitmap = NULL; 502 } 503 504 if (mpls_info->match_key) { 505 sal_free(mpls_info->match_key); 506 mpls_info->match_key = NULL; 507 } 508 509 if (mpls_info->tnl_bitmap) { 510 sal_free(mpls_info->tnl_bitmap); 511 mpls_info->tnl_bitmap = NULL; 512 } 513 514 if (mpls_info->ip_tnl_bitmap) { 515 sal_free(mpls_info->ip_tnl_bitmap); 516 mpls_info->ip_tnl_bitmap = NULL; 517 } 518 519 if (mpls_info->egr_mpls_bitmap) { 520 sal_free(mpls_info->egr_mpls_bitmap); 521 mpls_info->egr_mpls_bitmap = NULL; 522 } 523 if (mpls_info->egr_mpls_hw_idx) { 524 sal_free(mpls_info->egr_mpls_hw_idx); 525 mpls_info->egr_mpls_hw_idx = NULL; 526 } 527 528 if (mpls_info->ing_exp_map_bitmap) { 529 sal_free(mpls_info->ing_exp_map_bitmap); 530 mpls_info->ing_exp_map_bitmap = NULL; 531 } 532 533 if (mpls_info->egr_l2_exp_map_bitmap) { 534 sal_free(mpls_info->egr_l2_exp_map_bitmap); 535 mpls_info->egr_l2_exp_map_bitmap = NULL; 536 } 537 #ifdef BCM_APACHE_SUPPORT 538 if (soc_feature(unit, soc_feature_mpls_exp_to_phb_cng_map)) { 539 if (mpls_info->ing_exp_to_phb_cng_map_bitmap) { 540 sal_free(mpls_info->ing_exp_to_phb_cng_map_bitmap); 541 mpls_info->ing_exp_to_phb_cng_map_bitmap = NULL; 542 } 543 544 if (mpls_info->egr_exp_to_phb_cng_map_bitmap) { 545 sal_free(mpls_info->egr_exp_to_phb_cng_map_bitmap); 546 mpls_info->egr_exp_to_phb_cng_map_bitmap = NULL; 547 } 548 } 549 #endif 550 if (mpls_info->vc_swap_ref_count) { 551 sal_free(mpls_info->vc_swap_ref_count); 552 mpls_info->vc_swap_ref_count = NULL; 553 } 554 555 if (mpls_info->egr_tunnel_ref_count) { 556 sal_free(mpls_info->egr_tunnel_ref_count); 557 mpls_info->egr_tunnel_ref_count = NULL; 558 } 559 560 if (mpls_info->ing_qmap_ref_count) { 561 sal_free(mpls_info->ing_qmap_ref_count); 562 mpls_info->ing_qmap_ref_count = NULL; 563 } 564 565 if (mpls_info->svp_profile_set_bitmap) { 566 sal_free(mpls_info->svp_profile_set_bitmap); 567 mpls_info->svp_profile_set_bitmap = NULL; 568 } 569 570 if (mpls_info->network_vp_bitmap) { 571 sal_free(mpls_info->network_vp_bitmap); 572 mpls_info->network_vp_bitmap = NULL; 573 } 574 575 if (mpls_info->failover_vp) { 576 sal_free(mpls_info->failover_vp); 577 mpls_info->failover_vp = NULL; 578 } 579 580 (void) _bcm_tr_mpls_cleanup_egrNhop(unit); 581 if (!soc_feature(unit, soc_feature_th3_style_simple_mpls)) { 582 bcmi_tr_mpls_vc_swap_hash_cleanup(unit); 583 } 584 #if defined(BCM_APACHE_SUPPORT) || defined(BCM_TOMAHAWK2_SUPPORT) \ 585 || defined(BCM_TRIDENT3_SUPPORT) || defined(BCM_TOMAHAWK3_SUPPORT) 586 if (soc_feature(unit, soc_feature_egr_ip_tnl_mpls_double_wide) || 587 (soc_feature(unit, soc_feature_th3_style_simple_mpls))) { 588 bcmi_egr_ip_tunnel_mpls_sw_cleanup(unit); 589 } 590 #endif 591 592 #ifdef BCM_TRIDENT3_SUPPORT 593 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 594 if (mpls_info->egr_vc_swap_lbl_action) { 595 sal_free(mpls_info->egr_vc_swap_lbl_action); 596 mpls_info->egr_vc_swap_lbl_action = NULL; 597 } 598 } 599 #endif 600 601 #if defined(BCM_SPECIAL_LABEL_SUPPORT) 602 if (soc_feature(unit, soc_feature_mpls_special_label)) { 603 (void) bcmi_mpls_special_label_deinit(unit); 604 } 605 #endif 606 607 } 608 609 /* 610 * Function: 611 * bcm_tr_mpls_check_init 612 * Purpose: 613 * Check if MPLS is initialized 614 * Parameters: 615 * unit - Device Number 616 * Returns: 617 * BCM_E_XXX 618 */ 619 620 STATIC int 621 _bcm_tr_mpls_check_init (int unit) 622 { 623 if ((unit < 0) || (unit >= BCM_MAX_NUM_UNITS)) { 624 return BCM_E_UNIT; 625 } 626 627 if (!_bcm_tr_mpls_bk_info[unit].initialized) { 628 return BCM_E_INIT; 629 } else { 630 return BCM_E_NONE; 631 } 632 } 633 634 /* 635 * Function: 636 * bcm_tr_mpls_lock 637 * Purpose: 638 * Take the MPLS software module Lock Sempahore 639 * Parameters: 640 * unit - Device Number 641 * Returns: 642 * BCM_E_XXX 643 */ 644 645 int 646 bcm_tr_mpls_lock (int unit) 647 { 648 int rv; 649 650 rv = _bcm_tr_mpls_check_init (unit); 651 652 if ( rv == BCM_E_NONE ) { 653 sal_mutex_take(MPLS_INFO((unit))->mpls_mutex, sal_mutex_FOREVER); 654 } 655 return rv; 656 } 657 658 659 /* 660 * Function: 661 * bcm_tr_mpls_unlock 662 * Purpose: 663 * Release the MPLS software module Lock Semaphore 664 * Parameters: 665 * unit - Device Number 666 * Returns: 667 * BCM_E_XXX 668 */ 669 670 void 671 bcm_tr_mpls_unlock(int unit) 672 { 673 int rv; 674 675 rv = _bcm_tr_mpls_check_init (unit); 676 677 if ( rv == BCM_E_NONE ) { 678 sal_mutex_give(MPLS_INFO((unit))->mpls_mutex); 679 } 680 } 681 682 /* 683 * Function: 684 * bcm_tr_mpls_stat_clear 685 * Purpose: 686 * Clear L2 MPLS PW Stats 687 * Parameters: 688 * unit - (IN) SOC unit # 689 * Returns: 690 * BCM_E_XXX 691 */ 692 693 STATIC int 694 _bcm_tr_mpls_stat_clear(int unit) 695 { 696 int num_pw_term, num_pw_init; 697 int index, rv=BCM_E_NONE; 698 ing_pw_term_counters_entry_t cent; 699 ing_pw_term_seq_num_entry_t snent; 700 egr_pw_init_counters_entry_t pw_init_entry; 701 egr_pw_init_counters_x_entry_t pw_init_entry_x; 702 egr_pw_init_counters_y_entry_t pw_init_entry_y; 703 704 if (SOC_HW_RESET(unit)) { 705 return BCM_E_NONE; 706 } 707 num_pw_term = 0; 708 if (SOC_MEM_IS_VALID(unit, ING_PW_TERM_COUNTERSm)) { 709 num_pw_term = soc_mem_index_count(unit, ING_PW_TERM_COUNTERSm); 710 /* Clear the ING Counters */ 711 sal_memset(¢, 0, sizeof(ing_pw_term_counters_entry_t)); 712 for (index=0; index<num_pw_term; index++) { 713 rv = WRITE_ING_PW_TERM_COUNTERSm(unit, MEM_BLOCK_ANY, index, ¢); 714 if (rv < 0) { 715 return rv; 716 } 717 } 718 } 719 720 if (SOC_MEM_IS_VALID(unit, ING_PW_TERM_SEQ_NUMm)) { 721 num_pw_term = soc_mem_index_count(unit, ING_PW_TERM_SEQ_NUMm); 722 /* Clear the ING Counters */ 723 sal_memset(&snent, 0, sizeof(ing_pw_term_seq_num_entry_t)); 724 for (index = 0; index < num_pw_term; index++) { 725 rv = WRITE_ING_PW_TERM_SEQ_NUMm(unit, MEM_BLOCK_ANY, index, &snent); 726 if (rv < 0) { 727 return rv; 728 } 729 } 730 } 731 732 num_pw_init = 0; 733 #if defined(BCM_TRIDENT3_SUPPORT) 734 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 735 egr_sequence_number_table_entry_t td3_pw_init_entry; 736 num_pw_init = soc_mem_index_count(unit, EGR_SEQUENCE_NUMBER_TABLEm); 737 /* Clear the EGR Counters */ 738 sal_memset(&td3_pw_init_entry, 0, sizeof(egr_sequence_number_table_entry_t)); 739 for (index = 0; index < num_pw_init; index++) { 740 rv = WRITE_EGR_SEQUENCE_NUMBER_TABLEm(unit, MEM_BLOCK_ANY, index, 741 &td3_pw_init_entry); 742 if (rv < 0) { 743 return rv; 744 } 745 } 746 } else 747 #endif 748 { 749 if (SOC_MEM_IS_VALID(unit, EGR_PW_INIT_COUNTERSm)) { 750 num_pw_init = soc_mem_index_count(unit, EGR_PW_INIT_COUNTERSm); 751 /* Clear the EGR Counters */ 752 sal_memset(&pw_init_entry, 0, sizeof(egr_pw_init_counters_entry_t)); 753 for (index = 0; index < num_pw_init; index++) { 754 rv = WRITE_EGR_PW_INIT_COUNTERSm(unit, MEM_BLOCK_ANY, index, 755 &pw_init_entry); 756 if (rv < 0) { 757 return rv; 758 } 759 } 760 if (SOC_MEM_IS_VALID(unit, EGR_PW_INIT_COUNTERS_Xm)) { 761 num_pw_init = soc_mem_index_count(unit, EGR_PW_INIT_COUNTERS_Xm); 762 sal_memset(&pw_init_entry_x, 0, sizeof(egr_pw_init_counters_x_entry_t)); 763 for (index = 0; index < num_pw_init; index++) { 764 rv = WRITE_EGR_PW_INIT_COUNTERS_Xm(unit, MEM_BLOCK_ANY, index, 765 &pw_init_entry_x); 766 if (rv < 0) { 767 return rv; 768 } 769 } 770 } 771 if (SOC_MEM_IS_VALID(unit, EGR_PW_INIT_COUNTERS_Ym)) { 772 num_pw_init = soc_mem_index_count(unit, EGR_PW_INIT_COUNTERS_Ym); 773 sal_memset(&pw_init_entry_y, 0, sizeof(egr_pw_init_counters_y_entry_t)); 774 for (index = 0; index < num_pw_init; index++) { 775 rv = WRITE_EGR_PW_INIT_COUNTERS_Ym(unit, MEM_BLOCK_ANY, index, 776 &pw_init_entry_y); 777 if (rv < 0) { 778 return rv; 779 } 780 } 781 } 782 } 783 } 784 return rv; 785 } 786 787 788 /* 789 * Purpose: 790 * Entry-0 VC-AND-SWAP Entry is reserved for default 791 * Parameters: 792 * unit - (IN) StrataSwitch #. 793 * Returns: 794 * BCM_E_XXX 795 */ 796 STATIC int 797 _bcm_tr_mpls_default_entry_setup(int unit) 798 { 799 egr_mpls_vc_and_swap_label_table_entry_t vc_entry; 800 int rv = BCM_E_NONE; 801 uint32 vc_swap_index = VC_AND_SWAP_TABLE_RESV_INDEX; 802 803 sal_memset(&vc_entry, 0, 804 sizeof(egr_mpls_vc_and_swap_label_table_entry_t)); 805 806 _BCM_MPLS_VC_COUNT_USED_SET(unit, vc_swap_index); 807 808 #if defined(BCM_SWAP_TO_SELF_SUPPORT) 809 if (soc_feature(unit, soc_feature_mpls_swap_label_preserve)) { 810 811 soc_mem_field32_set(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 812 &vc_entry, MPLS_LABEL_ACTIONf, 813 _BCM_MPLS_ACTION_NOOP); 814 815 } else 816 #endif 817 { 818 soc_mem_field32_set(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 819 &vc_entry, MPLS_LABEL_ACTIONf, 820 _BCM_MPLS_ACTION_RESERVED); 821 } 822 823 rv = soc_mem_write(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 824 MEM_BLOCK_ALL, vc_swap_index, 825 &vc_entry); 826 827 return rv; 828 } 829 830 /* 831 * Function: 832 * bcm_tr_mpls_vrf_used_get 833 */ 834 835 int 836 bcm_tr_mpls_vrf_used_get(int unit, int vrf) 837 { 838 return _BCM_MPLS_VRF_USED_GET(unit, vrf); 839 } 840 841 /* 842 * Function: 843 * bcm_tr_mpls_pw_used_clear 844 */ 845 846 void 847 bcm_tr_mpls_pw_used_clear(int unit, int pw_cnt) 848 { 849 _BCM_MPLS_PW_TERM_USED_CLR(unit, pw_cnt); 850 } 851 852 /* 853 * Function: 854 * bcm_tr_mpls_pw_used_get 855 */ 856 int 857 bcm_tr_mpls_pw_used_get(int unit, int pw_cnt) 858 { 859 return _BCM_MPLS_PW_TERM_USED_GET(unit, pw_cnt); 860 } 861 862 /* 863 * Function: 864 * bcm_tr_mpls_pw_used_set 865 */ 866 void 867 bcm_tr_mpls_pw_used_set(int unit, int pw_cnt) 868 { 869 _BCM_MPLS_PW_TERM_USED_SET(unit, pw_cnt); 870 } 871 /* 872 * Function: 873 * bcm_tr_mpls_port_independent_range 874 * Purpose: 875 * Check if the incoming Label is within the Port Independent Range 876 * Parameters: 877 * label - Label 878 * Returns: 879 * BCM_E_XXX 880 */ 881 882 int 883 bcm_tr_mpls_port_independent_range (int unit, bcm_mpls_label_t label, bcm_gport_t port ) 884 { 885 uint32 reg_val; /* Register value */ 886 uint32 label_1_low=0, label_1_high=0; 887 uint32 label_2_low=0, label_2_high=0; 888 889 890 if (SOC_REG_IS_VALID(unit, GLOBAL_MPLS_RANGE_1_LOWERr)) { 891 BCM_IF_ERROR_RETURN(READ_GLOBAL_MPLS_RANGE_1_LOWERr(unit, ®_val)); 892 label_1_low = 893 soc_reg_field_get(unit, GLOBAL_MPLS_RANGE_1_LOWERr, reg_val, LABELf); 894 } 895 896 if (SOC_REG_IS_VALID(unit, GLOBAL_MPLS_RANGE_1_UPPERr)) { 897 BCM_IF_ERROR_RETURN(READ_GLOBAL_MPLS_RANGE_1_UPPERr(unit, ®_val)); 898 label_1_high = 899 soc_reg_field_get(unit, GLOBAL_MPLS_RANGE_1_UPPERr, reg_val, LABELf); 900 } 901 902 if (SOC_REG_IS_VALID(unit, GLOBAL_MPLS_RANGE_2_LOWERr)) { 903 BCM_IF_ERROR_RETURN(READ_GLOBAL_MPLS_RANGE_2_LOWERr(unit, ®_val)); 904 label_2_low = 905 soc_reg_field_get(unit, GLOBAL_MPLS_RANGE_2_LOWERr, reg_val, LABELf); 906 } 907 908 if (SOC_REG_IS_VALID(unit, GLOBAL_MPLS_RANGE_2_UPPERr)) { 909 BCM_IF_ERROR_RETURN(READ_GLOBAL_MPLS_RANGE_2_UPPERr(unit, ®_val)); 910 label_2_high = 911 soc_reg_field_get(unit, GLOBAL_MPLS_RANGE_2_UPPERr, reg_val, LABELf); 912 } 913 914 if ( (( label >= label_1_low) && ( label <= label_1_high)) || 915 (( label >= label_2_low) && ( label <= label_2_high)) ){ 916 if (port == BCM_GPORT_INVALID) { 917 return BCM_E_NONE; 918 } else { 919 return BCM_E_CONFIG; 920 } 921 } else { 922 if (port == BCM_GPORT_INVALID) { 923 return BCM_E_CONFIG; 924 } else { 925 return BCM_E_NONE; 926 } 927 } 928 } 929 930 931 932 #ifdef BCM_WARM_BOOT_SUPPORT 933 934 int 935 _bcm_tr_mpls_scache_size_get(int unit, int *size) 936 { 937 int num_vp = 0, num_vc = 0; 938 int num_vrf, num_ip_tnl, num_mpls_map; 939 int num_ing_exp_map, num_egr_l2_exp_map, num_pw_term, num_pw_init; 940 #ifdef BCM_APACHE_SUPPORT 941 int num_ing_mpls_exp_map1 = 0, num_egr_mpls_exp_map3 = 0; 942 #endif 943 int num_nh, alloc_sz = 0; 944 soc_mem_t mem; 945 946 num_vrf = SOC_CONTROL(unit)->max_vrf_id + 1; 947 if (SOC_MEM_IS_VALID(unit, SOURCE_VPm)) { 948 num_vp = soc_mem_index_count(unit, SOURCE_VPm); 949 } 950 if (SOC_MEM_IS_VALID(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm)) { 951 num_vc = soc_mem_index_count(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm); 952 } 953 #if defined(BCM_TRIDENT3_SUPPORT) 954 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 955 mem = EGR_IP_TUNNEL_MPLS_DOUBLE_WIDEm; 956 } else 957 #endif 958 { 959 mem = EGR_IP_TUNNEL_MPLSm; 960 } 961 num_ip_tnl = soc_mem_index_count(unit, mem); 962 /* EGR_MPLS_EXP_MAPPING_1 profiles indexed by ((int_pri << 2) + cng) */ 963 num_mpls_map = soc_mem_index_count(unit, EGR_MPLS_EXP_MAPPING_1m) / 64; 964 num_ing_exp_map = _bcm_tr_get_ing_mpls_index_size(unit); 965 #ifdef BCM_APACHE_SUPPORT 966 if (soc_feature(unit, soc_feature_mpls_exp_to_phb_cng_map)) { 967 num_ing_mpls_exp_map1 = soc_mem_index_count(unit, 968 ING_MPLS_EXP_MAPPING_1m) / 16; 969 num_egr_mpls_exp_map3 = soc_mem_index_count(unit, 970 EGR_MPLS_EXP_MAPPING_3m) / 8; 971 } 972 #endif 973 974 num_egr_l2_exp_map = bcmi_egr_mpls_exp_pri_mapping_num_exp_map_get(unit); 975 num_pw_term = 0; 976 if (SOC_MEM_IS_VALID(unit, ING_PW_TERM_COUNTERSm)) { 977 num_pw_term = soc_mem_index_count(unit, ING_PW_TERM_COUNTERSm); 978 } 979 num_pw_init = 0; 980 #if defined(BCM_TRIDENT3_SUPPORT) 981 if(soc_feature(unit, soc_feature_td3_style_mpls)) { 982 mem = EGR_SEQUENCE_NUMBER_TABLEm; 983 } else 984 #endif 985 { 986 mem = EGR_PW_INIT_COUNTERSm; 987 } 988 if (SOC_MEM_IS_VALID(unit, mem)) { 989 num_pw_init = soc_mem_index_count(unit, mem); 990 } 991 num_nh = soc_mem_index_count(unit, EGR_L3_NEXT_HOPm); 992 993 alloc_sz = 0; 994 alloc_sz += SOC_WB_SCACHE_CONTROL_SIZE; /* For version number */ 995 alloc_sz += SHR_BITALLOCSIZE(num_vrf); 996 alloc_sz += SHR_BITALLOCSIZE(num_vp / 2); 997 alloc_sz += SHR_BITALLOCSIZE(num_vc) * 2; 998 alloc_sz += SHR_BITALLOCSIZE(num_pw_term); 999 alloc_sz += SHR_BITALLOCSIZE(num_pw_init); 1000 alloc_sz += SHR_BITALLOCSIZE(num_mpls_map); 1001 alloc_sz += SHR_BITALLOCSIZE(num_ing_exp_map); 1002 alloc_sz += SHR_BITALLOCSIZE(num_egr_l2_exp_map); 1003 alloc_sz += SHR_BITALLOCSIZE(num_ip_tnl * 1004 _BCM_MPLS_NUM_MPLS_ENTRIES_PER_INDEX(unit)); 1005 alloc_sz += SHR_BITALLOCSIZE(num_ip_tnl); 1006 1007 alloc_sz += sizeof(uint32) * (num_nh + 1); 1008 #ifdef BCM_APACHE_SUPPORT 1009 if (soc_feature(unit, soc_feature_mpls_exp_to_phb_cng_map)) { 1010 alloc_sz += SHR_BITALLOCSIZE(num_ing_mpls_exp_map1); 1011 alloc_sz += SHR_BITALLOCSIZE(num_egr_mpls_exp_map3); 1012 } 1013 #endif 1014 if (size != NULL) { 1015 *size = alloc_sz; 1016 } 1017 1018 return BCM_E_NONE; 1019 } 1020 1021 /* 1022 * Function: 1023 * _bcm_tr_mpls_unsynchronized_reinit 1024 * Purpose: 1025 * - Recover MPLS related state from h/w. 1026 * - For MPLS module, the case where limited scache is 1027 * available is the same as unsynchronized init. 1028 * - In Cold Boot sequence, just returns to calling func. 1029 * Parameters: 1030 * unit : (IN) Device Unit Number 1031 * Returns: 1032 * BCM_E_XXX 1033 */ 1034 STATIC int 1035 _bcm_tr_mpls_unsynchronized_reinit(int unit) 1036 { 1037 int rv = BCM_E_NONE; 1038 if (!SOC_WARM_BOOT(unit)) { 1039 return rv; 1040 } 1041 1042 return rv; 1043 } 1044 1045 /* 1046 * Function: 1047 * _bcm_tr_mpls_limited_reinit 1048 * Purpose: 1049 * This is called when only limited scache space 1050 * is available. Please see comments for func 1051 * '_bcm_tr_mpls_ingexpbitmap_sync' in relation to this. 1052 * Parameters: 1053 * unit : (IN) Device Unit Number 1054 * Returns: 1055 * BCM_E_XXX 1056 */ 1057 STATIC int 1058 _bcm_tr_mpls_limited_reinit(int unit) 1059 { 1060 int rv = BCM_E_NONE; 1061 int stable_size; 1062 uint8 *mpls_state; 1063 int num_ing_exp_map; 1064 soc_scache_handle_t scache_handle; 1065 _bcm_tr_mpls_bookkeeping_t *mpls_info = MPLS_INFO(unit); 1066 1067 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_MPLS, 0); 1068 1069 if (SOC_WARM_BOOT(unit)) { 1070 /* Warm Boot */ 1071 SOC_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size)); 1072 1073 if (stable_size > sizeof(int32)) { 1074 rv = _bcm_esw_scache_ptr_get(unit, scache_handle, 1075 FALSE, sizeof(int32), &mpls_state, 1076 BCM_WB_DEFAULT_VERSION, NULL); 1077 1078 if (BCM_FAILURE(rv) && (rv != BCM_E_NOT_FOUND)) { 1079 return rv; 1080 } 1081 1082 if (NULL == mpls_state) { 1083 return BCM_E_MEMORY; 1084 } 1085 num_ing_exp_map = _bcm_tr_get_ing_mpls_index_size(unit); 1086 SHR_BITCOPY_RANGE(mpls_info->ing_exp_map_bitmap, 0, 1087 (SHR_BITDCL *)mpls_state, 0, num_ing_exp_map); 1088 } 1089 } else { 1090 /* Cold Boot */ 1091 rv = _bcm_esw_scache_ptr_get(unit, scache_handle, TRUE, 1092 sizeof(int32), &mpls_state, 1093 BCM_WB_DEFAULT_VERSION, NULL); 1094 if (BCM_FAILURE(rv) && (rv != BCM_E_NOT_FOUND)) { 1095 return rv; 1096 } 1097 } 1098 1099 return BCM_E_NONE; 1100 } 1101 1102 #ifdef BCM_TRIUMPH2_SUPPORT 1103 /* 1104 * Function: 1105 * _bcm_tr_mpls_flex_stat_recover 1106 * Purpose: 1107 * - Recover flex stats for given VP 1108 * Parameters: 1109 * unit : (IN) Device Unit Number 1110 * vp : (IN) Index into SOURCE_VPm table 1111 * Returns: 1112 * BCM_E_XXX 1113 */ 1114 int 1115 _bcm_tr_mpls_flex_stat_recover(int unit, int vp) 1116 { 1117 int fs_index; 1118 bcm_gport_t gport; 1119 source_vp_entry_t svp_entry; 1120 1121 SOC_IF_ERROR_RETURN(soc_mem_read(unit, SOURCE_VPm, 1122 MEM_BLOCK_ANY, vp, &svp_entry)); 1123 1124 if (soc_mem_field_valid(unit, SOURCE_VPm, VINTF_CTR_IDXf)) { 1125 fs_index = soc_SOURCE_VPm_field32_get(unit, &svp_entry, 1126 VINTF_CTR_IDXf); 1127 if (fs_index) { 1128 BCM_GPORT_MPLS_PORT_ID_SET(gport, vp); 1129 _bcm_esw_flex_stat_reinit_add(unit, 1130 _bcmFlexStatTypeGport, fs_index, gport); 1131 } 1132 } 1133 1134 return BCM_E_NONE; 1135 } 1136 1137 /* 1138 * Function: 1139 * _bcm_tr_mpls_flex_stat_recover 1140 * Purpose: 1141 * - Recover flex stats for given VP 1142 * Parameters: 1143 * unit : (IN) Device Unit Number 1144 * ment : (IN) Pointer to MPLS_ENTRYm table entry 1145 * Returns: 1146 * BCM_E_XXX 1147 */ 1148 void 1149 _bcm_tr_mpls_label_flex_stat_recover(int unit, mpls_entry_entry_t *ment) 1150 { 1151 int fs_index; 1152 _bcm_flex_stat_handle_t mpls_fsh; 1153 mpls_entry_entry_t fs_ment; 1154 uint32 key[2]; 1155 1156 fs_index = soc_MPLS_ENTRYm_field32_get(unit, ment, 1157 VINTF_CTR_IDXf); 1158 1159 if ((0 != soc_MPLS_ENTRYm_field32_get(unit, ment, 1160 USE_VINTF_CTR_IDXf)) && 1161 (0 != fs_index)) { 1162 sal_memset(&fs_ment, 0, sizeof(fs_ment)); 1163 /* Construct key-only entry, copy to FS handle */ 1164 soc_MPLS_ENTRYm_field32_set(unit, &fs_ment, VALIDf, 1165 soc_MPLS_ENTRYm_field32_get(unit, ment, VALIDf)); 1166 soc_mem_field_get(unit, MPLS_ENTRYm, (uint32 *) ment, 1167 KEYf, (uint32 *) key); 1168 soc_mem_field_set(unit, MPLS_ENTRYm, (uint32 *) &fs_ment, 1169 KEYf, (uint32 *) key); 1170 /* Technically, we should copy the KEY_TYPE field here, 1171 * but the rest of the MPLS code appears to abuse the fact that 1172 * the key type value is 0, so it was handled when we 1173 * cleared the entry above. 1174 */ 1175 1176 _BCM_FLEX_STAT_HANDLE_CLEAR(mpls_fsh); 1177 _BCM_FLEX_STAT_HANDLE_COPY(mpls_fsh, fs_ment); 1178 1179 _bcm_esw_flex_stat_ext_reinit_add(unit, 1180 _bcmFlexStatTypeMplsLabel, 1181 fs_index, mpls_fsh); 1182 } 1183 } 1184 1185 int 1186 _bcm_tr_mpls_source_vp_recover(int unit) 1187 { 1188 source_vp_entry_t svp; 1189 int rv = BCM_E_NONE; 1190 int value = 0, vp; 1191 int dscp_map_chunk = 0, ing_pri_cng_chunk = 0; 1192 int vp_count = 0; 1193 soc_mem_t port_tbl; 1194 1195 #if defined(BCM_TOMAHAWK3_SUPPORT) 1196 if (SOC_IS_TOMAHAWK3(unit)) { 1197 return BCM_E_NONE; 1198 } 1199 #endif 1200 #if defined(BCM_TRIDENT3_SUPPORT) 1201 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 1202 ing_pri_cng_chunk = 64; 1203 dscp_map_chunk = 64; 1204 } else 1205 #endif 1206 { 1207 ing_pri_cng_chunk = 16; 1208 dscp_map_chunk = 64; 1209 } 1210 1211 vp_count = soc_mem_index_count(unit, SOURCE_VPm); 1212 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 1213 port_tbl = LPORT_TABm; 1214 } else { 1215 port_tbl = PORT_TABm; 1216 } 1217 1218 for (vp = 0; vp < vp_count; vp++) { 1219 if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeMpls)) { 1220 continue; 1221 } 1222 1223 if (_BCM_MPLS_SVP_PROFILE_SET_USED_GET(unit, vp)) { 1224 /* Read PORT Table */ 1225 if (!soc_mem_field_valid(unit, SOURCE_VPm, TRUST_DSCP_PTRf) || 1226 !soc_mem_field_valid(unit, port_tbl, TRUST_DOT1P_PTRf) || 1227 !soc_mem_field_valid(unit, SOURCE_VPm, TRUST_DOT1P_PTRf)) { 1228 return BCM_E_NONE; 1229 } 1230 1231 rv = READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp, &svp); 1232 if (rv < 0) { 1233 return rv; 1234 } 1235 if (soc_feature(unit, soc_feature_dscp_map_per_port)) { 1236 if (soc_mem_field_valid(unit, SOURCE_VPm, TRUST_DSCP_PTRf)) { 1237 value = soc_SOURCE_VPm_field32_get(unit, 1238 &svp, 1239 TRUST_DSCP_PTRf); 1240 rv = _bcm_dscp_table_entry_reference(unit, 1241 (value * dscp_map_chunk), 1242 dscp_map_chunk); 1243 if (rv != BCM_E_NONE) { 1244 return rv; 1245 } else { 1246 rv = BCM_E_NONE; 1247 } 1248 } 1249 } 1250 if (soc_feature(unit, soc_feature_color_prio_map_profile)) { 1251 if (soc_mem_field_valid(unit, SOURCE_VPm, TRUST_DOT1P_PTRf)) { 1252 value = soc_SOURCE_VPm_field32_get(unit, 1253 &svp, 1254 TRUST_DOT1P_PTRf); 1255 rv = _bcm_ing_pri_cng_map_entry_reference( 1256 unit, 1257 (value * ing_pri_cng_chunk), 1258 ing_pri_cng_chunk); 1259 if (rv != BCM_E_NONE) { 1260 return rv; 1261 } else { 1262 rv = BCM_E_NONE; 1263 } 1264 } 1265 } 1266 } 1267 } 1268 return rv; 1269 } 1270 #endif /* BCM_TRIUMPH2_SUPPORT */ 1271 1272 /* 1273 * Function: 1274 * _bcm_tr_mpls_source_vp_tpid_recover 1275 * Purpose: 1276 * - Recover SVP TPIDs 1277 * Parameters: 1278 * unit : (IN) Device Unit Number 1279 * vp : (IN) Index into SOURCE_VPm table 1280 * Returns: 1281 * BCM_E_XXX 1282 */ 1283 int 1284 _bcm_tr_mpls_source_vp_tpid_recover(int unit, int vp) 1285 { 1286 int index, tpid_enable; 1287 source_vp_entry_t svp_entry; 1288 1289 SOC_IF_ERROR_RETURN(soc_mem_read(unit, SOURCE_VPm, 1290 MEM_BLOCK_ANY, vp, &svp_entry)); 1291 if (soc_SOURCE_VPm_field32_get(unit, &svp_entry, SD_TAG_MODEf) == 1) { 1292 #if defined(BCM_TRIDENT3_SUPPORT) 1293 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 1294 uint32 svp_attrs_1[SOC_MAX_MEM_WORDS]; 1295 1296 BCM_IF_ERROR_RETURN(READ_SVP_ATTRS_1m(unit, 1297 MEM_BLOCK_ANY, vp, svp_attrs_1)); 1298 soc_SVP_ATTRS_1m_field_get(unit, 1299 &svp_attrs_1, TPID_ENABLEf, (uint32 *)&tpid_enable); 1300 } else 1301 #endif 1302 { 1303 tpid_enable = soc_SOURCE_VPm_field32_get(unit, &svp_entry, 1304 TPID_ENABLEf); 1305 } 1306 for (index = 0; index < 4; index++) { 1307 if (tpid_enable & (1 << index)) { 1308 BCM_IF_ERROR_RETURN(_bcm_fb2_outer_tpid_tab_ref_count_add( 1309 unit, index, 1)); 1310 break; 1311 } 1312 } 1313 } 1314 1315 return BCM_E_NONE; 1316 } 1317 1318 int 1319 _bcm_tr_mpls_associated_data_recover(int unit) 1320 { 1321 int macda_idx; 1322 int i, idx_min, idx_max; 1323 egr_l3_next_hop_entry_t nh_entry; 1324 1325 idx_min = soc_mem_index_min(unit, EGR_L3_NEXT_HOPm); 1326 idx_max = soc_mem_index_max(unit, EGR_L3_NEXT_HOPm); 1327 1328 for (i = idx_min; i <= idx_max; i++) { 1329 SOC_IF_ERROR_RETURN(soc_mem_read(unit, EGR_L3_NEXT_HOPm, 1330 MEM_BLOCK_ANY, i, &nh_entry)); 1331 if (soc_EGR_L3_NEXT_HOPm_field32_get(unit, &nh_entry, nh_entry_type_field[unit]) != 1) { 1332 continue; /* MPLS entries only */ 1333 } 1334 1335 /* Get Index to MAC-DA-PROFILEm */ 1336 if (soc_feature(unit, soc_feature_mpls_enhanced)) { 1337 macda_idx = soc_EGR_L3_NEXT_HOPm_field32_get 1338 (unit, &nh_entry, MPLS__MAC_DA_PROFILE_INDEXf); 1339 } else { 1340 macda_idx = soc_EGR_L3_NEXT_HOPm_field32_get 1341 (unit, &nh_entry, MAC_DA_PROFILE_INDEXf); 1342 } 1343 1344 _bcm_common_profile_mem_ref_cnt_update(unit, EGR_MAC_DA_PROFILEm, 1345 macda_idx, 1); 1346 } 1347 1348 return BCM_E_NONE; 1349 } 1350 1351 /* 1352 * Function: 1353 * bcmi_tr_mpls_vc_swap_hash_dump 1354 * Purpose: 1355 * dumps the whole hash table 1356 * Parameters: 1357 * IN : Unit 1358 * Returns: 1359 * void 1360 */ 1361 void bcmi_tr_mpls_vc_swap_hash_dump(int unit) 1362 { 1363 1364 bcm_tr_mpls_vc_swap_table_hash_entry_t *temp; 1365 bcm_tr_mpls_vc_swap_table_hash_t *hash; 1366 int i, count = 0; 1367 1368 1369 LOG_ERROR(BSL_LS_SOC_COMMON, (BSL_META_U(unit, 1370 "printing VC and SWAP hash table\n"))); 1371 1372 if (bcmi_vc_swap_label_hash[unit] != NULL) { 1373 for (i=0; i< BCM_TR_MPLS_VC_SWAP_HASH_BUCKETS ; i++) { 1374 hash = &(bcmi_vc_swap_label_hash[unit][i]); 1375 temp = hash->head_link; 1376 if (temp != NULL) { 1377 while (temp != NULL) { 1378 LOG_ERROR(BSL_LS_SOC_COMMON, (BSL_META_U(unit, 1379 "hash index = %d : table index = %d \n"), 1380 i, temp->index)); 1381 temp = temp->link; 1382 count++; 1383 } 1384 } 1385 } 1386 LOG_ERROR(BSL_LS_SOC_COMMON, (BSL_META_U(unit,"\ntotal counts = %d\n"), 1387 count)); 1388 } 1389 } 1390 1391 /* 1392 * Function: 1393 * bcmi_tr_mpls_egr_vc_and_swap_table_hash_recover 1394 * Purpose: 1395 * - Recover MPLS VC Label table sw state. 1396 * Parameters: 1397 * unit : (IN) Device Unit Number 1398 * Returns: 1399 * BCM_E_XXX 1400 */ 1401 STATIC int 1402 bcmi_tr_mpls_egr_vc_and_swap_table_hash_recover(int unit) 1403 { 1404 int idx, hash_idx, vc_swap_index, table_idx; 1405 int imin, num_vc; 1406 egr_mpls_vc_and_swap_label_table_entry_t vc_entry; 1407 _bcm_tr_mpls_bookkeeping_t *mpls_info = MPLS_INFO(unit); 1408 int action = 0; 1409 1410 imin = soc_mem_index_min(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm); 1411 num_vc = soc_mem_index_count(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm); 1412 num_vc /= 2; 1413 /* we are diving the table in half to manage counted and non-counted entries. */ 1414 for (idx = imin; idx < num_vc + imin; idx++) { 1415 if ((!_BCM_MPLS_VC_COUNT_USED_GET(unit, idx - imin)) && 1416 (!_BCM_MPLS_VC_NON_COUNT_USED_GET(unit, idx - imin))) { 1417 continue; 1418 } 1419 1420 table_idx = idx; 1421 if (_BCM_MPLS_VC_NON_COUNT_USED_GET(unit, idx - imin)) { 1422 table_idx += num_vc; 1423 } 1424 1425 if (mpls_info->vc_swap_ref_count[table_idx - imin] <= 0) { 1426 continue; 1427 } 1428 1429 BCM_IF_ERROR_RETURN(soc_mem_read(unit, 1430 EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 1431 MEM_BLOCK_ALL, table_idx, &vc_entry)); 1432 1433 #if defined(BCM_TRIDENT3_SUPPORT) 1434 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 1435 action = MPLS_INFO(unit)->egr_vc_swap_lbl_action[table_idx]; 1436 } else 1437 #endif 1438 { 1439 action = 0; 1440 } 1441 BCM_IF_ERROR_RETURN(bcmi_tr_mpls_vc_swap_hash_index_get(unit, 1442 NULL , action, NULL, NULL, &vc_entry, &hash_idx)); 1443 1444 BCM_IF_ERROR_RETURN(bcmi_tr_mpls_vc_swap_hash_insert(unit, 1445 &(bcmi_vc_swap_label_hash[unit][hash_idx]), 1446 table_idx, NULL, NULL, NULL, NULL, 0, &vc_swap_index, FALSE)); 1447 } 1448 return BCM_E_NONE; 1449 } 1450 #if defined(BCM_TRIUMPH3_SUPPORT) 1451 STATIC int 1452 _bcm_tr_mpls_egr_vc_and_swap_table_hash_nhop_recover(int unit) 1453 { 1454 egr_l3_next_hop_entry_t egr_nh; 1455 int nh_count, idx, entry_type, vc_swap_idx, vc_count; 1456 int rv = BCM_E_NONE; 1457 soc_field_t vc_swap_idxf; 1458 1459 if (soc_feature(unit, soc_feature_mpls_enhanced)) { 1460 vc_swap_idxf = MPLS__VC_AND_SWAP_INDEXf ; 1461 } else { 1462 vc_swap_idxf = VC_AND_SWAP_INDEXf; 1463 } 1464 1465 sal_memset(&egr_nh, 0, sizeof(egr_l3_next_hop_entry_t)); 1466 nh_count = soc_mem_index_count(unit, EGR_L3_NEXT_HOPm); 1467 vc_count = soc_mem_index_count(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm); 1468 1469 for (idx = 0; idx < nh_count; idx++) { 1470 BCM_IF_ERROR_RETURN ( 1471 soc_mem_read(unit, EGR_L3_NEXT_HOPm, 1472 MEM_BLOCK_ANY, idx, &egr_nh)); 1473 entry_type = soc_EGR_L3_NEXT_HOPm_field32_get(unit, 1474 &egr_nh, ENTRY_TYPEf); 1475 if (entry_type == 0x1) { 1476 vc_swap_idx = soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, 1477 vc_swap_idxf); 1478 if ((vc_swap_idx) && (vc_swap_idx < vc_count)) { 1479 (void)_bcm_tr_mpls_vc_and_swap_hash_nhop_add (unit, 1480 vc_swap_idx, 1481 idx); 1482 } 1483 } 1484 } 1485 return rv; 1486 } 1487 #endif 1488 /* 1489 * Function: 1490 * _bcm_tr_mpls_vc_refcount_recover 1491 * Purpose: 1492 * - Recover MPLS VC Label Reference Count from HW 1493 * Parameters: 1494 * unit : (IN) Device Unit Number 1495 * Returns: 1496 * BCM_E_XXX 1497 */ 1498 1499 STATIC int 1500 _bcm_tr_mpls_vc_refcount_recover (int unit) 1501 { 1502 _bcm_tr_mpls_bookkeeping_t *mpls_info = MPLS_INFO(unit); 1503 egr_l3_next_hop_entry_t egr_nh; 1504 int nh_count, idx, entry_type, vc_swap_idx, vc_count; 1505 int rv=BCM_E_NONE; 1506 soc_field_t vc_swap_idxf; 1507 1508 if (soc_feature(unit, soc_feature_mpls_enhanced)) { 1509 vc_swap_idxf = MPLS__VC_AND_SWAP_INDEXf ; 1510 } else { 1511 vc_swap_idxf = VC_AND_SWAP_INDEXf; 1512 } 1513 1514 sal_memset(&egr_nh, 0, sizeof(egr_l3_next_hop_entry_t)); 1515 nh_count = soc_mem_index_count(unit, EGR_L3_NEXT_HOPm); 1516 vc_count = soc_mem_index_count(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm); 1517 1518 for (idx=0; idx<nh_count; idx++) { 1519 BCM_IF_ERROR_RETURN (soc_mem_read(unit, EGR_L3_NEXT_HOPm, 1520 MEM_BLOCK_ANY, idx, &egr_nh)); 1521 entry_type = soc_EGR_L3_NEXT_HOPm_field32_get(unit, 1522 &egr_nh, nh_entry_type_field[unit]); 1523 if (entry_type == 0x1) { 1524 vc_swap_idx = soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, 1525 vc_swap_idxf); 1526 if ((vc_swap_idx) && (vc_swap_idx < vc_count)) { 1527 mpls_info->vc_swap_ref_count[vc_swap_idx]++; 1528 } 1529 } 1530 } 1531 return rv; 1532 } 1533 1534 1535 /* 1536 * Function: 1537 * _bcm_tr_mpls_egr_tunnel_refcount_recover 1538 * Purpose: 1539 * - Recover MPLS Egress Tunnel-Label Reference Count from HW 1540 * Parameters: 1541 * unit : (IN) Device Unit Number 1542 * Returns: 1543 * BCM_E_XXX 1544 */ 1545 1546 STATIC int 1547 _bcm_tr_mpls_egr_tunnel_refcount_recover (int unit) 1548 { 1549 egr_ip_tunnel_mpls_entry_t tnl_entry; 1550 egr_l3_intf_entry_t if_entry; 1551 int intf_count, idx; 1552 int mpls_index, tnl_index; 1553 int offset, push_action; 1554 int rv=BCM_E_NONE; 1555 1556 sal_memset(&if_entry, 0, sizeof(egr_l3_intf_entry_t)); 1557 intf_count = soc_mem_index_count(unit, EGR_L3_INTFm); 1558 1559 for (idx=0; idx<intf_count; idx++) { 1560 BCM_IF_ERROR_RETURN (soc_mem_read(unit, EGR_L3_INTFm, 1561 MEM_BLOCK_ANY, idx, &if_entry)); 1562 mpls_index = soc_EGR_L3_INTFm_field32_get(unit, &if_entry, 1563 MPLS_TUNNEL_INDEXf); 1564 tnl_index = mpls_index / _BCM_MPLS_NUM_MPLS_ENTRIES_PER_INDEX(unit); 1565 #if defined(BCM_TRIDENT3_SUPPORT) 1566 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 1567 egr_ip_tunnel_mpls_double_wide_entry_t tnl_entry_dbl; 1568 rv = READ_EGR_IP_TUNNEL_MPLS_DOUBLE_WIDEm(unit, MEM_BLOCK_ANY, 1569 tnl_index, &tnl_entry_dbl); 1570 if (rv < 0) { 1571 return rv; 1572 } 1573 if (soc_mem_field32_get(unit, EGR_IP_TUNNEL_MPLS_DOUBLE_WIDEm, 1574 &tnl_entry_dbl, DATA_TYPEf) == 0x14) { 1575 /* Increment Ref count */ 1576 _bcm_tr_mpls_egr_tunnel_ref_count_adjust (unit, 1577 mpls_index, 1); 1578 } 1579 } else 1580 #endif 1581 { 1582 rv = READ_EGR_IP_TUNNEL_MPLSm(unit, MEM_BLOCK_ANY, 1583 tnl_index, &tnl_entry); 1584 if (rv < 0) { 1585 return rv; 1586 } 1587 if (soc_mem_field32_get(unit, EGR_IP_TUNNEL_MPLSm, &tnl_entry, 1588 ENTRY_TYPEf) == 0x3) { 1589 /* Increment Ref count */ 1590 _bcm_tr_mpls_egr_tunnel_ref_count_adjust (unit, 1591 mpls_index, 1); 1592 1593 offset = mpls_index & _BCM_MPLS_EGR_L3_INTF_MPLS_INDEX_OFFSET_MASK(unit); 1594 push_action = soc_mem_field32_get(unit, EGR_IP_TUNNEL_MPLSm, &tnl_entry, 1595 _tnl_push_action_f[offset]); 1596 if (push_action == 2) { 1597 _bcm_tr_mpls_egr_tunnel_ref_count_adjust (unit, 1598 mpls_index+1, 1); 1599 } 1600 } 1601 } 1602 } 1603 return rv; 1604 } 1605 1606 /* 1607 * Function: 1608 * _bcm_tr_mpls_match_key_recover 1609 * Purpose: 1610 * - Recover MPLS match key from h/w tables 1611 * Parameters: 1612 * unit : (IN) Device Unit Number 1613 * Returns: 1614 * BCM_E_XXX 1615 */ 1616 int 1617 _bcm_tr_mpls_match_key_recover(int unit) 1618 { 1619 int i, vp, port_type; 1620 int index_min, index_max; 1621 mpls_entry_entry_t mpls_entry; 1622 source_trunk_map_table_entry_t trunk_entry; 1623 _bcm_tr_mpls_bookkeeping_t *mpls_info = MPLS_INFO(unit); 1624 uint32 vent[SOC_MAX_MEM_WORDS]; 1625 soc_mem_t mem; 1626 #if defined(BCM_TOMAHAWK3_SUPPORT) 1627 if (SOC_IS_TOMAHAWK3(unit)) { 1628 /* Recover misc associated data */ 1629 BCM_IF_ERROR_RETURN(_bcm_tr_mpls_associated_data_recover(unit)); 1630 return BCM_E_NONE; 1631 } 1632 #endif 1633 sal_memset(vent, 0, sizeof(uint32) * SOC_MAX_MEM_WORDS); 1634 #if defined(BCM_TRIDENT3_SUPPORT) 1635 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 1636 mem = VLAN_XLATE_1_DOUBLEm; 1637 } else 1638 #endif 1639 { 1640 mem = VLAN_XLATEm; 1641 } 1642 1643 /* Recover match keys from VLAN_XLATEm table */ 1644 index_min = soc_mem_index_min(unit, mem); 1645 index_max = soc_mem_index_max(unit, mem); 1646 for (i = index_min; i <= index_max; i++) { 1647 SOC_IF_ERROR_RETURN(soc_mem_read(unit, 1648 mem, MEM_BLOCK_ANY, i, vent)); 1649 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 1650 if ((soc_mem_field32_get(unit, mem, vent, BASE_VALID_0f) == 0) || 1651 (soc_mem_field32_get(unit, mem, vent, BASE_VALID_1f) == 0)) { 1652 continue; 1653 } 1654 } else { 1655 if (soc_mem_field32_get(unit, mem, vent, VALIDf) == 0) { 1656 continue; 1657 } 1658 } 1659 1660 if ((soc_mem_field32_get(unit, mem, vent, MPLS_ACTIONf) & 0x1) != 0x1) { 1661 continue; 1662 } 1663 1664 vp = soc_mem_field32_get(unit, mem, vent, SOURCE_VPf); 1665 1666 /* Proceed only if this VP belongs to MPLS */ 1667 if (_bcm_vp_used_get(unit, vp, _bcmVpTypeMpls)) { 1668 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 1669 _bcm_vp_info_t vp_info; 1670 BCM_IF_ERROR_RETURN(_bcm_vp_info_get(unit, vp, &vp_info)); 1671 1672 if (vp_info.flags & _BCM_VP_INFO_SHARED_PORT) { 1673 mpls_info->match_key[vp].flags = _BCM_MPLS_PORT_MATCH_TYPE_SHARE; 1674 bcm_tr_mpls_port_match_count_adjust(unit, vp, 1); 1675 continue; 1676 } 1677 #endif 1678 if (soc_mem_field32_get(unit, mem, vent, KEY_TYPEf) == 1679 TR_VLXLT_HASH_KEY_TYPE_OVID) { 1680 1681 mpls_info->match_key[vp].flags = _BCM_MPLS_PORT_MATCH_TYPE_VLAN; 1682 mpls_info->match_key[vp].match_vlan = 1683 soc_mem_field32_get(unit, mem, vent, OVIDf); 1684 if (soc_mem_field32_get(unit, mem, vent, GLPf) != 1685 SOC_VLAN_XLATE_GLP_WILDCARD(unit)) { 1686 if (soc_mem_field32_get(unit, mem, vent, Tf) == 0x1) { 1687 mpls_info->match_key[vp].trunk_id = 1688 soc_mem_field32_get(unit, mem, vent, TGIDf); 1689 } else { 1690 mpls_info->match_key[vp].port = 1691 soc_mem_field32_get(unit, mem, vent, PORT_NUMf); 1692 mpls_info->match_key[vp].modid = 1693 soc_mem_field32_get(unit, mem, vent, MODULE_IDf); 1694 } 1695 } 1696 bcm_tr_mpls_port_match_count_adjust(unit, vp, 1); 1697 } else if (soc_mem_field32_get(unit, mem, vent, KEY_TYPEf) == 1698 TR_VLXLT_HASH_KEY_TYPE_IVID) { 1699 1700 mpls_info->match_key[vp].flags = _BCM_MPLS_PORT_MATCH_TYPE_INNER_VLAN; 1701 mpls_info->match_key[vp].match_inner_vlan = 1702 soc_mem_field32_get(unit, mem, vent, IVIDf); 1703 if (soc_mem_field32_get(unit, mem, vent, Tf) == 0x1) { 1704 mpls_info->match_key[vp].trunk_id = 1705 soc_mem_field32_get(unit, mem, vent, TGIDf); 1706 } else { 1707 mpls_info->match_key[vp].port = 1708 soc_mem_field32_get(unit, mem, vent, PORT_NUMf); 1709 mpls_info->match_key[vp].modid = 1710 soc_mem_field32_get(unit, mem, vent, MODULE_IDf); 1711 } 1712 bcm_tr_mpls_port_match_count_adjust(unit, vp, 1); 1713 } else if (soc_mem_field32_get(unit, mem, vent, KEY_TYPEf) == 1714 TR_VLXLT_HASH_KEY_TYPE_IVID_OVID) { 1715 1716 mpls_info->match_key[vp].flags = 1717 _BCM_MPLS_PORT_MATCH_TYPE_VLAN_STACKED; 1718 mpls_info->match_key[vp].match_vlan = 1719 soc_mem_field32_get(unit, mem, vent, OVIDf); 1720 mpls_info->match_key[vp].match_inner_vlan = 1721 soc_mem_field32_get(unit, mem, vent, IVIDf); 1722 if (soc_mem_field32_get(unit, mem, vent, Tf) == 0x1) { 1723 mpls_info->match_key[vp].trunk_id = 1724 soc_mem_field32_get(unit, mem, vent, TGIDf); 1725 } else { 1726 mpls_info->match_key[vp].port = 1727 soc_mem_field32_get(unit, mem, vent, PORT_NUMf); 1728 mpls_info->match_key[vp].modid = 1729 soc_mem_field32_get(unit, mem, vent, MODULE_IDf); 1730 } 1731 bcm_tr_mpls_port_match_count_adjust(unit, vp, 1); 1732 } 1733 #ifdef BCM_KATANA2_SUPPORT 1734 else if ((soc_mem_field32_get(unit, mem, vent, KEY_TYPEf) == 1735 KT2_PT_XLT_KEY_TYPE_LLVID) && soc_feature(unit, soc_feature_lltag)) { 1736 1737 mpls_info->match_key[vp].flags = 1738 _BCM_MPLS_PORT_MATCH_TYPE_PORT_SUBPORT_PKT_VID; 1739 mpls_info->match_key[vp].match_subport_pkt_vid = 1740 soc_mem_field32_get(unit, mem, vent, 1741 LLTAG__LLVIDf); 1742 1743 if (soc_mem_field32_get(unit, mem, vent, Tf) == 0x1) { 1744 mpls_info->match_key[vp].trunk_id = 1745 soc_mem_field32_get(unit, mem, vent, TGIDf); 1746 } else { 1747 mpls_info->match_key[vp].port = 1748 soc_mem_field32_get(unit, mem, vent, PORT_NUMf); 1749 mpls_info->match_key[vp].modid = 1750 soc_mem_field32_get(unit, mem, vent, MODULE_IDf); 1751 } 1752 bcm_tr_mpls_port_match_count_adjust(unit, vp, 1); 1753 } else if (soc_mem_field32_get(unit, mem, vent, KEY_TYPEf) == 1754 KT2_PT_XLT_KEY_TYPE_LLVID_IVID && soc_feature(unit, soc_feature_lltag)) { 1755 1756 mpls_info->match_key[vp].flags = 1757 _BCM_MPLS_PORT_MATCH_TYPE_PORT_SUBPORT_PKT_VID_INNER_VLAN; 1758 mpls_info->match_key[vp].match_subport_pkt_vid = 1759 soc_mem_field32_get(unit, mem, vent, 1760 LLTAG__LLVIDf); 1761 mpls_info->match_key[vp].match_inner_vlan = 1762 soc_mem_field32_get(unit, mem, vent, LLTAG__IVIDf); 1763 if (soc_mem_field32_get(unit, mem, vent, Tf) == 0x1) { 1764 mpls_info->match_key[vp].trunk_id = 1765 soc_mem_field32_get(unit, mem, vent, TGIDf); 1766 } else { 1767 mpls_info->match_key[vp].port = 1768 soc_mem_field32_get(unit, mem, vent, PORT_NUMf); 1769 mpls_info->match_key[vp].modid = 1770 soc_mem_field32_get(unit, mem, vent, MODULE_IDf); 1771 } 1772 bcm_tr_mpls_port_match_count_adjust(unit, vp, 1); 1773 } else if (soc_mem_field32_get(unit, mem, vent, KEY_TYPEf) == 1774 KT2_PT_XLT_KEY_TYPE_LLVID_OVID && soc_feature(unit, soc_feature_lltag)) { 1775 1776 mpls_info->match_key[vp].flags = 1777 _BCM_MPLS_PORT_MATCH_TYPE_PORT_SUBPORT_PKT_VID_OUTER_VLAN; 1778 mpls_info->match_key[vp].match_subport_pkt_vid = 1779 soc_mem_field32_get(unit, mem, vent, 1780 LLTAG__LLVIDf); 1781 mpls_info->match_key[vp].match_vlan = 1782 soc_mem_field32_get(unit, mem, vent, LLTAG__OVIDf); 1783 if (soc_mem_field32_get(unit, mem, vent, Tf) == 0x1) { 1784 mpls_info->match_key[vp].trunk_id = 1785 soc_mem_field32_get(unit, mem, vent, TGIDf); 1786 } else { 1787 mpls_info->match_key[vp].port = 1788 soc_mem_field32_get(unit, mem, vent, PORT_NUMf); 1789 mpls_info->match_key[vp].modid = 1790 soc_mem_field32_get(unit, mem, vent, MODULE_IDf); 1791 } 1792 bcm_tr_mpls_port_match_count_adjust(unit, vp, 1); 1793 } 1794 #endif /* BCM_KATANA2_SUPPORT */ 1795 1796 #ifdef BCM_TRIUMPH2_SUPPORT /* Recover flex stats */ 1797 if (soc_feature(unit, soc_feature_gport_service_counters)) { 1798 BCM_IF_ERROR_RETURN(_bcm_tr_mpls_flex_stat_recover(unit, vp)); 1799 } 1800 #endif /* BCM_TRIUMPH2_SUPPORT */ 1801 1802 /* Recover TPID ref count */ 1803 BCM_IF_ERROR_RETURN(_bcm_tr_mpls_source_vp_tpid_recover(unit, vp)); 1804 } 1805 } 1806 1807 /* Recover misc associated data */ 1808 BCM_IF_ERROR_RETURN(_bcm_tr_mpls_associated_data_recover(unit)); 1809 1810 /* Recover match keys from SOURCE_TRUNK_MAP_TABLEm table */ 1811 index_min = soc_mem_index_min(unit, SOURCE_TRUNK_MAP_TABLEm); 1812 index_max = soc_mem_index_max(unit, SOURCE_TRUNK_MAP_TABLEm); 1813 for (i = index_min; i <= index_max; i++) { 1814 SOC_IF_ERROR_RETURN(soc_mem_read(unit, SOURCE_TRUNK_MAP_TABLEm, 1815 MEM_BLOCK_ANY, i, &trunk_entry)); 1816 1817 vp = soc_SOURCE_TRUNK_MAP_TABLEm_field32_get(unit, 1818 &trunk_entry, SOURCE_VPf); 1819 1820 /* Proceed only if this VP belongs to MPLS */ 1821 if (_bcm_vp_used_get(unit, vp, _bcmVpTypeMpls)) { 1822 1823 port_type = soc_SOURCE_TRUNK_MAP_TABLEm_field32_get(unit, 1824 &trunk_entry, PORT_TYPEf); 1825 if (0 == port_type) { /* Normal port */ 1826 mpls_info->match_key[vp].flags = _BCM_MPLS_PORT_MATCH_TYPE_PORT; 1827 mpls_info->match_key[vp].index = i; 1828 } else if(1 == port_type) { /* Trunk port */ 1829 mpls_info->match_key[vp].flags =_BCM_MPLS_PORT_MATCH_TYPE_TRUNK; 1830 mpls_info->match_key[vp].trunk_id = 1831 soc_SOURCE_TRUNK_MAP_TABLEm_field32_get(unit, &trunk_entry, 1832 TGIDf); 1833 mpls_info->trunk_vp_map[mpls_info->match_key[vp].trunk_id] = vp; 1834 } 1835 1836 #ifdef BCM_TRIUMPH2_SUPPORT /* Recover flex stats */ 1837 if (soc_feature(unit, soc_feature_gport_service_counters)) { 1838 BCM_IF_ERROR_RETURN(_bcm_tr_mpls_flex_stat_recover(unit, vp)); 1839 } 1840 #endif /* BCM_TRIUMPH2_SUPPORT */ 1841 1842 /* Recover TPID ref count */ 1843 BCM_IF_ERROR_RETURN(_bcm_tr_mpls_source_vp_tpid_recover(unit, vp)); 1844 } 1845 } 1846 1847 /* Recover match keys from MPLS_ENTRYm table */ 1848 index_min = soc_mem_index_min(unit, MPLS_ENTRYm); 1849 index_max = soc_mem_index_max(unit, MPLS_ENTRYm); 1850 for (i = index_min; i <= index_max; i++) { 1851 SOC_IF_ERROR_RETURN(soc_mem_read(unit, MPLS_ENTRYm, 1852 MEM_BLOCK_ANY, i, &mpls_entry)); 1853 1854 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 1855 if ((soc_MPLS_ENTRYm_field32_get(unit, &mpls_entry, BASE_VALID_0f) == 0) || 1856 (soc_MPLS_ENTRYm_field32_get(unit, &mpls_entry, BASE_VALID_1f) == 0)) { 1857 continue; 1858 } 1859 } else { 1860 if (soc_MPLS_ENTRYm_field32_get(unit, &mpls_entry, VALIDf) == 0) { 1861 continue; 1862 } 1863 } 1864 if ((soc_MPLS_ENTRYm_field32_get(unit, 1865 &mpls_entry, MPLS_ACTION_IF_BOSf) != 0x1) || 1866 (soc_MPLS_ENTRYm_field32_get(unit, 1867 &mpls_entry, MPLS_ACTION_IF_NOT_BOSf) != 0x0)) { 1868 #if defined(BCM_SABER2_SUPPORT) 1869 /* SB2: IF not BOS field is set for VCCV type 4. 1870 * It needs to be recovered. 1871 */ 1872 if (!(SOC_IS_SABER2(unit) && 1873 (soc_MPLS_ENTRYm_field32_get(unit, 1874 &mpls_entry, MPLS_ACTION_IF_NOT_BOSf) == 0x5))) 1875 #endif 1876 { 1877 continue; 1878 } 1879 } 1880 1881 vp = soc_MPLS_ENTRYm_field32_get(unit, &mpls_entry, SOURCE_VPf); 1882 1883 /* Proceed only if this VP belongs to MPLS */ 1884 if (_bcm_vp_used_get(unit, vp, _bcmVpTypeMpls)) { 1885 bcm_module_t modid; 1886 bcm_port_t local_port; 1887 bcm_trunk_t trunk_id; 1888 int local_id; 1889 bcm_gport_t mpls_port_id; 1890 bcm_trunk_t mpls_tid = 0; 1891 bcm_port_t mpls_local_port = 0; 1892 int mpls_local_modid = 0; 1893 int rv; 1894 1895 BCM_GPORT_MPLS_PORT_ID_SET(mpls_port_id,vp); 1896 rv = _bcm_esw_gport_resolve(unit, mpls_port_id, &modid, 1897 &local_port, &trunk_id, 1898 &local_id); 1899 if (rv != BCM_E_NONE) { 1900 continue; 1901 } 1902 1903 if (soc_MPLS_ENTRYm_field32_get(unit, &mpls_entry, Tf) == 0x1) { 1904 mpls_tid = soc_MPLS_ENTRYm_field32_get(unit, &mpls_entry, TGIDf); 1905 if (mpls_tid == trunk_id) { 1906 mpls_info->match_key[vp].trunk_id = mpls_tid; 1907 } else { 1908 mpls_info->match_key[vp].fo_trunk_id = mpls_tid; 1909 } 1910 mpls_info->match_key[vp].flags = _BCM_MPLS_PORT_MATCH_TYPE_LABEL_PORT; 1911 } else { 1912 mpls_local_port = 1913 soc_MPLS_ENTRYm_field32_get(unit, &mpls_entry, PORT_NUMf); 1914 mpls_local_modid = 1915 soc_MPLS_ENTRYm_field32_get(unit, &mpls_entry, MODULE_IDf); 1916 1917 if ((mpls_local_port == 0) && (mpls_local_modid == 0)) { 1918 mpls_info->match_key[vp].flags = _BCM_MPLS_PORT_MATCH_TYPE_LABEL; 1919 mpls_info->match_key[vp].port = mpls_local_port; 1920 mpls_info->match_key[vp].modid = mpls_local_modid; 1921 } else { 1922 mpls_info->match_key[vp].flags = _BCM_MPLS_PORT_MATCH_TYPE_LABEL_PORT; 1923 if (mpls_local_port == local_port && mpls_local_modid == modid) { 1924 mpls_info->match_key[vp].port = mpls_local_port; 1925 mpls_info->match_key[vp].modid = mpls_local_modid; 1926 } else { 1927 mpls_info->match_key[vp].fo_port = mpls_local_port; 1928 mpls_info->match_key[vp].fo_modid = mpls_local_modid; 1929 } 1930 } 1931 } 1932 mpls_info->match_key[vp].match_label = 1933 soc_MPLS_ENTRYm_field32_get(unit, &mpls_entry, MPLS_LABELf); 1934 1935 #ifdef BCM_TRIUMPH2_SUPPORT /* Recover flex stats */ 1936 if (soc_feature(unit, soc_feature_gport_service_counters)) { 1937 BCM_IF_ERROR_RETURN 1938 (_bcm_tr_mpls_flex_stat_recover(unit, vp)); 1939 _bcm_tr_mpls_label_flex_stat_recover(unit, &mpls_entry); 1940 } 1941 #endif /* BCM_TRIUMPH2_SUPPORT */ 1942 1943 /* Recover TPID ref count */ 1944 BCM_IF_ERROR_RETURN(_bcm_tr_mpls_source_vp_tpid_recover(unit, vp)); 1945 } 1946 } 1947 1948 #ifdef BCM_TRIDENT2PLUS_SUPPORT 1949 index_min = soc_mem_index_min(unit, SOURCE_VPm); 1950 index_max = soc_mem_index_max(unit, SOURCE_VPm); 1951 for (i = index_min; i <= index_max; i++) { 1952 if (_bcm_vp_used_get(unit, i, _bcmVpTypeMpls)) { 1953 _bcm_vp_info_t vp_info; 1954 BCM_IF_ERROR_RETURN(_bcm_vp_info_get(unit, i, &vp_info)); 1955 1956 if (vp_info.flags & _BCM_VP_INFO_SHARED_PORT) { 1957 mpls_info->match_key[i].flags = _BCM_MPLS_PORT_MATCH_TYPE_SHARE; 1958 } 1959 } 1960 } 1961 #endif /* BCM_TRIDENT2PLUS_SUPPORT */ 1962 1963 #ifdef BCM_TRIUMPH2_SUPPORT /* Recover flex stats */ 1964 if (soc_feature(unit, soc_feature_gport_service_counters)) { 1965 index_min = soc_mem_index_min(unit, SOURCE_VPm); 1966 index_max = soc_mem_index_max(unit, SOURCE_VPm); 1967 for (i = index_min; i <= index_max; i++) { 1968 if ((!_bcm_vp_used_get(unit, i, _bcmVpTypeMpls)) || 1969 (mpls_info->match_key[i].flags != 0)){ 1970 continue; 1971 } 1972 1973 BCM_IF_ERROR_RETURN(_bcm_tr_mpls_flex_stat_recover(unit, i)); 1974 } 1975 } 1976 #endif /* BCM_TRIUMPH2_SUPPORT */ 1977 1978 return BCM_E_NONE; 1979 } 1980 1981 /* 1982 * Function: 1983 * _bcm_tr_mpls_vpws_vp_map_recover 1984 * Purpose: 1985 * Reconstruct the VPWS VP to VPN mapping info 1986 * from h/w by traversing the source VP table. 1987 * NOTE: This is possible oly for sdk versions 1988 * where the VPWS VPS are vp and vp+1. 1989 * Parameters: 1990 * unit : (IN) Device Unit Number 1991 * Returns: 1992 * BCM_E_XXX 1993 */ 1994 STATIC int 1995 _bcm_tr_mpls_vpws_vp_map_recover(int unit) 1996 { 1997 int i, idx_min, idx_max; 1998 source_vp_entry_t svp_entry; 1999 _bcm_tr_mpls_bookkeeping_t *mpls_info = MPLS_INFO(unit); 2000 2001 idx_min = soc_mem_index_min(unit, SOURCE_VPm); 2002 idx_max = soc_mem_index_max(unit, SOURCE_VPm); 2003 2004 for (i = idx_min; i <=idx_max; i++) { 2005 SOC_IF_ERROR_RETURN(soc_mem_read(unit, 2006 SOURCE_VPm, MEM_BLOCK_ANY, i, &svp_entry)); 2007 if (soc_SOURCE_VPm_field32_get(unit, &svp_entry, ENTRY_TYPEf) != 2) { 2008 continue; /* Looking for VPWS VPs only */ 2009 } 2010 mpls_info->vpws_vp_map[(i>>1)].vp1 = i; 2011 mpls_info->vpws_vp_map[(i>>1)].vp2 = (i+1); 2012 i++; /* Skip past the immediate next VP as it belongs to this VPWS */ 2013 } 2014 return BCM_E_NONE; 2015 } 2016 2017 /* 2018 * Function: 2019 * _bcm_tr_mpls_extended_reinit 2020 * Purpose: 2021 * - Called when persistent memory adequate for 2022 * MPLS state recover is available. 2023 * - In Cold Boot sequence, scache space is allocated 2024 * in persistent memory. 2025 * - In Warm Boot sequence, state stored in persistent 2026 * memory is retrieved to reconstrunct MPLS 2027 * book keeping structure. 2028 * Parameters: 2029 * unit : (IN) Device Unit Number 2030 * Returns: 2031 * BCM_E_XXX 2032 */ 2033 STATIC int 2034 _bcm_tr_mpls_extended_reinit(int unit) 2035 { 2036 int i, rv = BCM_E_NONE; 2037 int stable_size, alloc_sz; 2038 int num_pw_term, num_pw_init; 2039 int num_ip_tnl, num_mpls_map, num_nh; 2040 int num_vrf, num_vp = 0, num_vc = 0; 2041 int num_ing_exp_map, num_egr_l2_exp_map; 2042 #ifdef BCM_APACHE_SUPPORT 2043 int num_ing_exp_to_phb_cng_map = 0, num_egr_exp_to_phb_cng_map = 0; 2044 #endif 2045 int vpws_vp_map_size; 2046 int idx_min, idx_max; 2047 uint8 *mpls_state, *mpls_state_marker; 2048 uint16 recovered_ver; 2049 soc_scache_handle_t scache_handle; 2050 uint8* egr_nh_tbl_buf = NULL; 2051 _bcm_tr_mpls_bookkeeping_t *mpls_info = MPLS_INFO(unit); 2052 uint32 nh_if, primary_nh_if, bitmask; 2053 int additional_scache_sz = 0; 2054 int vp3_recovery_reqd = 0; 2055 uint32 recovered_sz = 0; 2056 int alloc_ver1_3_sz = 0; 2057 int old_num_vp = 0; 2058 #if defined(BCM_SABER2_SUPPORT) 2059 uint32 source_vp_sb2_5626x = 0; 2060 #endif /* BCM_SABER2_SUPPORT */ 2061 soc_mem_t mem; 2062 2063 num_mpls_map = soc_mem_index_count(unit, 2064 EGR_MPLS_EXP_MAPPING_1m) / 64; 2065 2066 if (SOC_WARM_BOOT(unit)) { 2067 /* Warm Boot */ 2068 alloc_sz = 0; 2069 alloc_ver1_3_sz = 0; 2070 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_MPLS, 0); 2071 BCM_IF_ERROR_RETURN(_bcm_tr_mpls_scache_size_get(unit, &alloc_sz)); 2072 if (BCM_WB_DEFAULT_VERSION >= BCM_WB_VERSION_1_1) { 2073 /* Although the sync and recover is changed to individual fields, 2074 * we are still allocating full structure to start with. 2075 * At this point, we do not know from which version we are 2076 * coming from so if we are coming from a version which had 2077 * more space then we will reduce alloc space here. 2078 * We will anyways reduce the space when we will recover 2079 * each field based on versions below. 2080 */ 2081 if (SOC_MEM_IS_VALID(unit, SOURCE_VPm)) { 2082 alloc_sz += sizeof(_bcm_mpls_vpws_vp_map_info_t) * 2083 (soc_mem_index_count(unit, SOURCE_VPm)/2); 2084 } 2085 } 2086 2087 if (BCM_WB_DEFAULT_VERSION >= BCM_WB_VERSION_1_2) { 2088 alloc_sz += SHR_BITALLOCSIZE(num_mpls_map); 2089 } 2090 2091 if (BCM_WB_DEFAULT_VERSION >= BCM_WB_VERSION_1_3) { 2092 alloc_sz += (num_mpls_map * sizeof(uint32) - 2093 SHR_BITALLOCSIZE(num_mpls_map)); 2094 } 2095 alloc_ver1_3_sz = alloc_sz; 2096 2097 SOC_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size)); 2098 SOC_IF_ERROR_RETURN(soc_scache_ptr_get(unit, scache_handle, 2099 &mpls_state, &recovered_sz)); 2100 recovered_sz -= SOC_WB_SCACHE_CONTROL_SIZE; 2101 vp3_recovery_reqd = (recovered_sz == alloc_ver1_3_sz) ? 1 : 0; 2102 2103 if (stable_size > alloc_sz) { 2104 rv = _bcm_esw_scache_ptr_get(unit, 2105 scache_handle, FALSE, 2106 alloc_sz, &mpls_state, 2107 BCM_WB_DEFAULT_VERSION, &recovered_ver); 2108 2109 if (BCM_FAILURE(rv) && (rv != BCM_E_NOT_FOUND)) { 2110 return rv; 2111 } 2112 2113 if (NULL == mpls_state) { 2114 return BCM_E_MEMORY; 2115 } 2116 2117 /* Maximum virtual port supported on saber2 5626x devices are 4K 2118 * This fix is related to scaling down of vpn from 8K to 4K 2119 */ 2120 #if defined(BCM_SABER2_SUPPORT) 2121 if (soc_sb2_5626x_devtype(unit)) { 2122 sal_memcpy(&source_vp_sb2_5626x, mpls_state, 2123 sizeof(source_vp_sb2_5626x)); 2124 if (source_vp_sb2_5626x == 0xFED5ABC7) { 2125 mpls_state += sizeof(source_vp_sb2_5626x); 2126 } else { 2127 old_num_vp = 1; 2128 } 2129 } 2130 #endif /* BCM_SABER2_SUPPORT */ 2131 num_vrf = SOC_CONTROL(unit)->max_vrf_id + 1; 2132 if (!SOC_IS_TOMAHAWK3(unit)) { 2133 num_vp = soc_mem_index_count(unit, SOURCE_VPm); 2134 num_vc = soc_mem_index_count(unit, 2135 EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm); 2136 } 2137 #if defined(BCM_TRIDENT3_SUPPORT) 2138 if(soc_feature(unit, soc_feature_td3_style_mpls)) { 2139 num_ip_tnl = soc_mem_index_count(unit, 2140 EGR_IP_TUNNEL_MPLS_DOUBLE_WIDEm); 2141 } else 2142 #endif 2143 { 2144 num_ip_tnl = soc_mem_index_count(unit, EGR_IP_TUNNEL_MPLSm); 2145 } 2146 2147 /*EGR_MPLS_EXP_MAPPING_1 profiles indexed by ((int_pri <<2) + cng)*/ 2148 num_ing_exp_map = _bcm_tr_get_ing_mpls_index_size(unit); 2149 num_egr_l2_exp_map = bcmi_egr_mpls_exp_pri_mapping_num_exp_map_get(unit); 2150 #ifdef BCM_APACHE_SUPPORT 2151 if (soc_feature(unit, soc_feature_mpls_exp_to_phb_cng_map)) { 2152 num_ing_exp_to_phb_cng_map = soc_mem_index_count(unit, 2153 ING_MPLS_EXP_MAPPING_1m) / 16; 2154 num_egr_exp_to_phb_cng_map = soc_mem_index_count(unit, 2155 EGR_MPLS_EXP_MAPPING_3m) / 8; 2156 } 2157 #endif 2158 num_pw_term = 0; 2159 if (SOC_MEM_IS_VALID(unit, ING_PW_TERM_COUNTERSm)) { 2160 num_pw_term = soc_mem_index_count(unit, ING_PW_TERM_COUNTERSm); 2161 } 2162 num_pw_init = 0; 2163 #if defined(BCM_TRIDENT3_SUPPORT) 2164 if(soc_feature(unit, soc_feature_td3_style_mpls)) { 2165 mem = EGR_SEQUENCE_NUMBER_TABLEm; 2166 } else 2167 #endif 2168 { 2169 mem = EGR_PW_INIT_COUNTERSm; 2170 } 2171 if (SOC_MEM_IS_VALID(unit, mem)) { 2172 num_pw_init = soc_mem_index_count(unit, mem); 2173 } 2174 num_nh = soc_mem_index_count(unit, EGR_L3_NEXT_HOPm); 2175 SHR_BITCOPY_RANGE(mpls_info->vrf_bitmap, 0, 2176 (SHR_BITDCL *)mpls_state, 0, num_vrf); 2177 mpls_state += SHR_BITALLOCSIZE(num_vrf); 2178 SHR_BITCOPY_RANGE(mpls_info->vpws_bitmap, 0, 2179 (SHR_BITDCL *)mpls_state, 0, (num_vp/2)); 2180 if (old_num_vp) { 2181 mpls_state += SHR_BITALLOCSIZE(num_vp); 2182 } else { 2183 mpls_state += SHR_BITALLOCSIZE(num_vp/2); 2184 } 2185 SHR_BITCOPY_RANGE(mpls_info->vc_c_bitmap, 0, 2186 (SHR_BITDCL *)mpls_state, 0, num_vc); 2187 mpls_state += SHR_BITALLOCSIZE(num_vc); 2188 SHR_BITCOPY_RANGE(mpls_info->vc_nc_bitmap, 0, 2189 (SHR_BITDCL *)mpls_state, 0, num_vc); 2190 mpls_state += SHR_BITALLOCSIZE(num_vc); 2191 if (num_pw_term) { 2192 SHR_BITCOPY_RANGE(mpls_info->pw_term_bitmap, 0, 2193 (SHR_BITDCL *)mpls_state, 0, num_pw_term); 2194 mpls_state += SHR_BITALLOCSIZE(num_pw_term); 2195 } 2196 2197 if (num_pw_init) { 2198 SHR_BITCOPY_RANGE(mpls_info->pw_init_bitmap, 0, 2199 (SHR_BITDCL *)mpls_state, 0, num_pw_init); 2200 mpls_state += SHR_BITALLOCSIZE(num_pw_init); 2201 } 2202 SHR_BITCOPY_RANGE(mpls_info->egr_mpls_bitmap, 0, 2203 (SHR_BITDCL *)mpls_state, 0, num_mpls_map); 2204 mpls_state += SHR_BITALLOCSIZE(num_mpls_map); 2205 SHR_BITCOPY_RANGE(mpls_info->ing_exp_map_bitmap, 0, 2206 (SHR_BITDCL *)mpls_state, 0, num_ing_exp_map); 2207 mpls_state += SHR_BITALLOCSIZE(num_ing_exp_map); 2208 SHR_BITCOPY_RANGE(mpls_info->egr_l2_exp_map_bitmap, 0, 2209 (SHR_BITDCL *)mpls_state, 0, num_egr_l2_exp_map); 2210 mpls_state += SHR_BITALLOCSIZE(num_egr_l2_exp_map); 2211 2212 SHR_BITCOPY_RANGE(mpls_info->tnl_bitmap, 0, 2213 (SHR_BITDCL *)mpls_state, 0, (num_ip_tnl * 2214 _BCM_MPLS_NUM_MPLS_ENTRIES_PER_INDEX(unit))); 2215 mpls_state += SHR_BITALLOCSIZE(num_ip_tnl * 2216 _BCM_MPLS_NUM_MPLS_ENTRIES_PER_INDEX(unit)); 2217 SHR_BITCOPY_RANGE(mpls_info->ip_tnl_bitmap, 0, 2218 (SHR_BITDCL *)mpls_state, 0, num_ip_tnl); 2219 mpls_state += SHR_BITALLOCSIZE(num_ip_tnl); 2220 mpls_state_marker = mpls_state; 2221 2222 /* Reconstruct match_index by reading tables */ 2223 rv = _bcm_esw_mpls_match_key_recover(unit); 2224 if (BCM_FAILURE(rv)) { 2225 return rv; 2226 } 2227 2228 if (!soc_feature(unit, soc_feature_th3_style_simple_mpls)) { 2229 /* Reconstruct VC RefCount */ 2230 rv = _bcm_tr_mpls_vc_refcount_recover(unit); 2231 if (BCM_FAILURE(rv)) { 2232 return rv; 2233 } 2234 } 2235 2236 /* Reconstruct Egress MPLS Tunnel-Label RefCount */ 2237 rv = _bcm_tr_mpls_egr_tunnel_refcount_recover(unit); 2238 if (BCM_FAILURE(rv)) { 2239 return rv; 2240 } 2241 2242 #if defined(BCM_TRIDENT3_SUPPORT) 2243 /*Recover VCSWAP Label Actions in TD3 first, for hash recover depend on it*/ 2244 if (recovered_ver >= BCM_WB_VERSION_1_12) { 2245 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 2246 int num_sl = soc_mem_index_count(unit, SPECIAL_LABEL_CONTROLm); 2247 int lbl_action_offset = sizeof(uint32) * num_nh + sizeof(int) + 2248 (num_vp/2) * 3 * sizeof(int) + 2249 num_mpls_map * sizeof(uint32) + 2250 2 * SHR_BITALLOCSIZE(num_vp) + 2251 num_vp * sizeof(uint32) + 2252 num_sl * 2 *sizeof(int); 2253 sal_memcpy(mpls_info->egr_vc_swap_lbl_action, mpls_state + lbl_action_offset, 2254 num_vc * sizeof(int)); 2255 } 2256 } 2257 #endif 2258 if (!soc_feature(unit, soc_feature_th3_style_simple_mpls)) { 2259 /* Reconstruct hash for egr VC and swap table */ 2260 rv = bcmi_tr_mpls_egr_vc_and_swap_table_hash_recover(unit); 2261 if (BCM_FAILURE(rv)) { 2262 return rv; 2263 } 2264 } 2265 #if defined(BCM_TRIUMPH3_SUPPORT) 2266 /* Reconstruct intf hash for egr VC and swap table */ 2267 if (soc_feature(unit, soc_feature_vc_and_swap_table_overlaid)) { 2268 rv = _bcm_tr_mpls_egr_vc_and_swap_table_hash_nhop_recover(unit); 2269 if (BCM_FAILURE(rv)) { 2270 return rv; 2271 } 2272 } 2273 #endif 2274 #if defined(BCM_APACHE_SUPPORT) || defined(BCM_TOMAHAWK2_SUPPORT) \ 2275 || defined(BCM_TRIDENT3_SUPPORT) || defined(BCM_TOMAHAWK3_SUPPORT) 2276 if (soc_feature(unit, soc_feature_egr_ip_tnl_mpls_double_wide) || 2277 (soc_feature(unit, soc_feature_th3_style_simple_mpls))) { 2278 rv = bcmi_xgs5_mpls_tunnel_initiator_reinit(unit); 2279 if (BCM_FAILURE(rv)) { 2280 return rv; 2281 } 2282 } 2283 #endif 2284 /* reconstruct the hash and linked lists */ 2285 idx_min = soc_mem_index_min(unit, EGR_L3_NEXT_HOPm); 2286 idx_max = soc_mem_index_max(unit, EGR_L3_NEXT_HOPm); 2287 egr_nh_tbl_buf = soc_cm_salloc(unit, SOC_MEM_TABLE_BYTES(unit, 2288 EGR_L3_NEXT_HOPm), 2289 "egr_l3_next_hop"); 2290 if (egr_nh_tbl_buf == NULL) { 2291 return BCM_E_MEMORY; 2292 } 2293 2294 rv = soc_mem_read_range(unit, EGR_L3_NEXT_HOPm, MEM_BLOCK_ANY, 2295 idx_min, idx_max, egr_nh_tbl_buf); 2296 if (SOC_FAILURE(rv)) { 2297 goto cleanup; 2298 } 2299 2300 primary_nh_if = 0; 2301 bitmask = 1 << ((8 * sizeof(uint32)) - 1); 2302 sal_memcpy(&nh_if, mpls_state, sizeof(uint32)); 2303 while (nh_if != 0xdeadbeef) { 2304 if (nh_if & bitmask) { 2305 primary_nh_if = (nh_if & ~bitmask); 2306 } 2307 if (primary_nh_if != (nh_if & ~bitmask)) { 2308 BCM_IF_ERROR_RETURN(_bcm_tr_mpls_add_egrNhop(unit, primary_nh_if)); 2309 BCM_IF_ERROR_RETURN(_bcm_tr_mpls_add_vp_nh(unit, primary_nh_if, nh_if)); 2310 BCM_XGS3_L3_ENT_REF_CNT_INC(BCM_XGS3_L3_TBL_PTR(unit, next_hop), 2311 (primary_nh_if) ? (primary_nh_if - BCM_XGS3_EGRESS_IDX_MIN(unit)) : 0, 2312 _BCM_SINGLE_WIDE); 2313 } 2314 mpls_state += sizeof(uint32); 2315 sal_memcpy(&nh_if, mpls_state, sizeof(uint32)); 2316 } 2317 mpls_state = mpls_state_marker + (sizeof(uint32) * num_nh); 2318 2319 /* Reconstruct VPWS VP map from the scache */ 2320 if (recovered_ver >= BCM_WB_VERSION_1_1) { 2321 mpls_state += sizeof(int); 2322 for (i=0; i<(num_vp/2); i++) { 2323 if(recovered_ver <= BCM_WB_VERSION_1_3) { 2324 sal_memcpy(&mpls_info->vpws_vp_map[i].vp1, mpls_state, 2325 sizeof(int)); 2326 mpls_state += sizeof(int); 2327 sal_memcpy(&mpls_info->vpws_vp_map[i].vp2, mpls_state, 2328 sizeof(int)); 2329 mpls_state += sizeof(int); 2330 if(vp3_recovery_reqd) { 2331 sal_memcpy(&mpls_info->vpws_vp_map[i].vp3, 2332 mpls_state, sizeof(int)); 2333 mpls_state += sizeof(int); 2334 } 2335 } else { /* if recovered_ver > BCM_WB_VERSION_1_3 */ 2336 sal_memcpy(&mpls_info->vpws_vp_map[i].vp1, mpls_state, 2337 sizeof(int)); 2338 mpls_state += sizeof(int); 2339 sal_memcpy(&mpls_info->vpws_vp_map[i].vp2, mpls_state, 2340 sizeof(int)); 2341 mpls_state += sizeof(int); 2342 sal_memcpy(&mpls_info->vpws_vp_map[i].vp3, mpls_state, 2343 sizeof(int)); 2344 mpls_state += sizeof(int); 2345 2346 if ((recovered_ver >= BCM_WB_VERSION_1_8) && 2347 soc_feature(unit, soc_feature_hierarchical_protection)) { 2348 2349 sal_memcpy(&mpls_info->vpws_vp_map[i].vp_b_1, mpls_state, 2350 sizeof(int)); 2351 mpls_state += sizeof(int); 2352 sal_memcpy(&mpls_info->vpws_vp_map[i].vp_b_2, mpls_state, 2353 sizeof(int)); 2354 mpls_state += sizeof(int); 2355 sal_memcpy(&mpls_info->vpws_vp_map[i].vp_b_3, mpls_state, 2356 sizeof(int)); 2357 mpls_state += sizeof(int); 2358 } else if (recovered_ver == BCM_WB_VERSION_1_8) { 2359 /* As part of version 8, we allocated space common 2360 * for all devices without any soc checks because 2361 * whole structure was synced. as part of 1.9 2362 * version, the structure is broken to sync/alloc 2363 * each field separately. 2364 */ 2365 mpls_state += (3 * sizeof(int)); 2366 } 2367 } 2368 } 2369 if (old_num_vp) { 2370 if(recovered_ver <= BCM_WB_VERSION_1_3) { 2371 mpls_state += ((sizeof(int) + sizeof(int)) * 2372 (num_vp - (num_vp/2))); 2373 if(vp3_recovery_reqd) { 2374 mpls_state += (sizeof(int) * 2375 (num_vp - (num_vp/2))); 2376 } 2377 } else { 2378 mpls_state += ((sizeof(int) * 3) * 2379 (num_vp - (num_vp/2))); 2380 if (recovered_ver >= BCM_WB_VERSION_1_8) { 2381 mpls_state += ((sizeof(int) * 3) * 2382 (num_vp - (num_vp/2))); 2383 } 2384 } 2385 } 2386 } else { /* Reconstruct VPWS VP map from h/w */ 2387 rv = _bcm_tr_mpls_vpws_vp_map_recover(unit); 2388 if (BCM_FAILURE(rv)) { 2389 goto cleanup; 2390 } 2391 if (old_num_vp) { 2392 vpws_vp_map_size = sizeof(_bcm_mpls_vpws_vp_map_info_t) * 2393 num_vp; 2394 } else { 2395 vpws_vp_map_size = sizeof(_bcm_mpls_vpws_vp_map_info_t) * 2396 (soc_mem_index_count(unit, SOURCE_VPm)/2); 2397 } 2398 rv = soc_scache_realloc(unit, scache_handle, vpws_vp_map_size); 2399 if (SOC_FAILURE(rv)) { 2400 goto cleanup; 2401 } 2402 } 2403 2404 /* Recover the MPLS map entry */ 2405 if (recovered_ver >= BCM_WB_VERSION_1_3) { 2406 sal_memcpy(mpls_info->egr_mpls_hw_idx, mpls_state, 2407 (num_mpls_map * sizeof(uint32))); 2408 mpls_state += (num_mpls_map * sizeof(uint32)); 2409 2410 for (i = 0; i < num_mpls_map; i++) { 2411 if (_BCM_EGR_MPLS_MAP_USED_GET(unit, i)) { 2412 rv = _bcm_egr_mpls_combo_map_entry_reference(unit, 2413 ((mpls_info->egr_mpls_hw_idx[i]) * 64), 64); 2414 if (BCM_FAILURE(rv)) { 2415 goto cleanup; 2416 } 2417 } 2418 } 2419 } else if (recovered_ver >= BCM_WB_VERSION_1_2) { 2420 /* Can not get correct data from VERSION_1_2 */ 2421 additional_scache_sz = num_mpls_map * sizeof(uint32) - 2422 SHR_BITALLOCSIZE(num_mpls_map); 2423 } else { 2424 additional_scache_sz = num_mpls_map * sizeof(uint32); 2425 } 2426 2427 if ( (recovered_ver >= BCM_WB_VERSION_1_1) && 2428 (recovered_ver <= BCM_WB_VERSION_1_3) ){ 2429 if (!vp3_recovery_reqd) { 2430 if (old_num_vp) { 2431 additional_scache_sz += sizeof(int) * num_vp; 2432 } else { 2433 additional_scache_sz += sizeof(int) * (num_vp/2); 2434 } 2435 } 2436 } 2437 if (!(soc_feature(unit, soc_feature_hierarchical_protection))) { 2438 2439 /* if 2 level protection is not enabled then we 2440 * will have to allocate space only for version 1.8 as we 2441 * sync the whole structure there. from 1.9 we changed 2442 * sync of whole strcuture to indivisual fields. 2443 * going from 1.8 to 1.9 we will have to remove the space also. 2444 */ 2445 if (recovered_ver == BCM_WB_VERSION_1_8) { 2446 if (old_num_vp) { 2447 additional_scache_sz -= (3 *sizeof(int)) * num_vp; 2448 } else { 2449 additional_scache_sz -= (3 *sizeof(int)) * (num_vp/2); 2450 } 2451 } 2452 } else { 2453 /* Adding state for 3 more backup VPs */ 2454 if (recovered_ver < BCM_WB_VERSION_1_8) { 2455 if (old_num_vp) { 2456 additional_scache_sz += (3 *sizeof(int)) * num_vp; 2457 } else { 2458 additional_scache_sz += (3 *sizeof(int)) * (num_vp/2); 2459 } 2460 } 2461 } 2462 2463 /* Recover the MPLS svp profile set bitmap */ 2464 if (recovered_ver >= BCM_WB_VERSION_1_5) { 2465 SHR_BITCOPY_RANGE(mpls_info->svp_profile_set_bitmap, 0, 2466 (SHR_BITDCL *)mpls_state, 0, num_vp); 2467 if (old_num_vp) { 2468 mpls_state += SHR_BITALLOCSIZE((num_vp * 2)); 2469 } else { 2470 mpls_state += SHR_BITALLOCSIZE(num_vp); 2471 } 2472 #ifdef BCM_TRIUMPH2_SUPPORT 2473 rv = _bcm_tr_mpls_source_vp_recover(unit); 2474 if (BCM_FAILURE(rv)) { 2475 goto cleanup; 2476 } 2477 #endif 2478 } else { 2479 if (old_num_vp) { 2480 additional_scache_sz += SHR_BITALLOCSIZE((num_vp * 2)); 2481 } else { 2482 additional_scache_sz += SHR_BITALLOCSIZE(num_vp); 2483 } 2484 } 2485 2486 /* Recover the network VP bitmap */ 2487 if (recovered_ver >= BCM_WB_VERSION_1_6) { 2488 SHR_BITCOPY_RANGE(mpls_info->network_vp_bitmap, 0, 2489 (SHR_BITDCL *)mpls_state, 0, num_vp); 2490 if (old_num_vp) { 2491 mpls_state += SHR_BITALLOCSIZE((num_vp * 2)); 2492 } else { 2493 mpls_state += SHR_BITALLOCSIZE(num_vp); 2494 } 2495 } else { 2496 if (old_num_vp) { 2497 additional_scache_sz += SHR_BITALLOCSIZE((num_vp * 2)); 2498 } else { 2499 additional_scache_sz += SHR_BITALLOCSIZE(num_vp); 2500 } 2501 } 2502 #ifdef BCM_APACHE_SUPPORT 2503 if (soc_feature(unit, soc_feature_mpls_exp_to_phb_cng_map)) { 2504 /* Recover MPLS EXP to PHB and CNG maps */ 2505 if (recovered_ver >= BCM_WB_VERSION_1_7) { 2506 SHR_BITCOPY_RANGE(mpls_info->ing_exp_to_phb_cng_map_bitmap, 0, 2507 (SHR_BITDCL *)mpls_state, 0, 2508 num_ing_exp_to_phb_cng_map); 2509 mpls_state += SHR_BITALLOCSIZE(num_ing_exp_to_phb_cng_map); 2510 SHR_BITCOPY_RANGE(mpls_info->egr_exp_to_phb_cng_map_bitmap, 0, 2511 (SHR_BITDCL *)mpls_state, 0, 2512 num_egr_exp_to_phb_cng_map); 2513 mpls_state += SHR_BITALLOCSIZE(num_egr_exp_to_phb_cng_map); 2514 } else { 2515 additional_scache_sz += 2516 (SHR_BITALLOCSIZE(num_ing_exp_to_phb_cng_map) + 2517 SHR_BITALLOCSIZE(num_egr_exp_to_phb_cng_map)); 2518 } 2519 } 2520 #endif 2521 2522 #ifdef BCM_TRIUMPH2_SUPPORT 2523 if (soc_feature(unit, soc_feature_mpls_failover)) { 2524 /* Recover failover vp */ 2525 if (recovered_ver >= BCM_WB_VERSION_1_10) { 2526 sal_memcpy(mpls_info->failover_vp, (SHR_BITDCL *)mpls_state, 2527 num_vp * sizeof(uint32)); 2528 mpls_state += num_vp * sizeof(uint32); 2529 } else { 2530 additional_scache_sz += num_vp * sizeof(uint32); 2531 } 2532 } 2533 #endif 2534 #ifdef BCM_SPECIAL_LABEL_SUPPORT 2535 if (soc_feature(unit, soc_feature_mpls_special_label)) { 2536 int num_entry = 0; 2537 bcmi_mpls_special_label_control_t *ptr; 2538 num_entry = 2539 soc_mem_index_count(unit, SPECIAL_LABEL_CONTROLm); 2540 2541 /* Recover MPLS MPLS special label identifier state */ 2542 if (recovered_ver >= BCM_WB_VERSION_1_11) { 2543 2544 ptr = bcmi_special_label_precedence_state[unit]; 2545 for (i = 0; i < num_entry; i++) { 2546 sal_memcpy((&(ptr[i].ref_count)), mpls_state, 2547 sizeof(int)); 2548 mpls_state += sizeof(int); 2549 sal_memcpy((&(ptr[i].cancun_added)), mpls_state, 2550 sizeof(int)); 2551 mpls_state += sizeof(int); 2552 } 2553 } else { 2554 /* Ask for space for new two variables */ 2555 additional_scache_sz += (num_entry * 2 * sizeof(int)); 2556 } 2557 } 2558 #endif 2559 #if defined(BCM_TRIDENT3_SUPPORT) || defined(BCM_TOMAHAWK3_SUPPORT) 2560 /*Recover VCSWAP Label Actions in TD3*/ 2561 if (recovered_ver >= BCM_WB_VERSION_1_12) { 2562 #ifdef BCM_TRIDENT3_SUPPORT 2563 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 2564 sal_memcpy(mpls_info->egr_vc_swap_lbl_action, mpls_state, 2565 num_vc * sizeof(int)); 2566 mpls_state += num_vc * sizeof(int); 2567 } 2568 #endif 2569 } else { 2570 additional_scache_sz += (num_vc * sizeof(int)); 2571 } 2572 #endif 2573 #ifdef BCM_SPECIAL_LABEL_SUPPORT 2574 if (soc_feature(unit, soc_feature_mpls_special_label)) { 2575 /* Recover MPLS special label egress state */ 2576 if (recovered_ver >= BCM_WB_VERSION_1_13) { 2577 bcmi_mpls_special_label_egress_t *ptr; 2578 2579 ptr = (&(bcmi_special_label_egress_state[unit])); 2580 sal_memcpy((&(ptr->special_label_ref_count)), mpls_state, 2581 sizeof(int)); 2582 2583 mpls_state += sizeof(int); 2584 sal_memcpy((&(ptr->entropy_label_ref_count)), mpls_state, 2585 sizeof(int)); 2586 mpls_state += sizeof(int); 2587 } else { 2588 /* Ask for space for new two variables */ 2589 additional_scache_sz += (2 * sizeof(int)); 2590 } 2591 } 2592 #endif 2593 2594 if (additional_scache_sz != 0) { 2595 rv = soc_scache_realloc(unit, scache_handle, additional_scache_sz); 2596 if (SOC_FAILURE(rv)) { 2597 goto cleanup; 2598 } 2599 } 2600 } 2601 /* Egress Mpls Tunnel related flex stat reloaded after Mpls 2602 * SW structures are populated since the flow require Mpls 2603 * book-keeping information. 2604 */ 2605 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 2606 if (soc_feature(unit,soc_feature_advanced_flex_counter)) { 2607 _bcm_esw_stat_flex_check_egress_mpls_tunnel_table(unit); 2608 } 2609 #endif 2610 } else { 2611 /* Cold Boot */ 2612 alloc_sz = 0; 2613 BCM_IF_ERROR_RETURN(_bcm_tr_mpls_scache_size_get(unit, &alloc_sz)); 2614 2615 if (SOC_MEM_IS_VALID(unit, SOURCE_VPm)) { 2616 if (BCM_WB_DEFAULT_VERSION >= BCM_WB_VERSION_1_5) { 2617 alloc_sz += 2618 SHR_BITALLOCSIZE(soc_mem_index_count(unit, SOURCE_VPm)); 2619 } 2620 2621 /* For network_vp_bitmap */ 2622 if (BCM_WB_DEFAULT_VERSION >= BCM_WB_VERSION_1_6) { 2623 alloc_sz += 2624 SHR_BITALLOCSIZE(soc_mem_index_count(unit, SOURCE_VPm)); 2625 } 2626 2627 /* Allocate MPLS scache for the VPWS VP map */ 2628 if (BCM_WB_DEFAULT_VERSION >= BCM_WB_VERSION_1_1) { 2629 alloc_sz += (MPLS_VPWS_VP_NUM * sizeof(int)) * 2630 (soc_mem_index_count(unit, SOURCE_VPm)/2); 2631 2632 if ((BCM_WB_DEFAULT_VERSION >= BCM_WB_VERSION_1_8) && 2633 (soc_feature(unit, soc_feature_hierarchical_protection))) { 2634 alloc_sz += (MPLS_VPWS_VP_NUM * sizeof(int)) * 2635 (soc_mem_index_count(unit, SOURCE_VPm)/2); 2636 } 2637 } 2638 2639 #ifdef BCM_TRIUMPH2_SUPPORT 2640 if (soc_feature(unit, soc_feature_mpls_failover)) { 2641 num_vp = soc_mem_index_count(unit, SOURCE_VPm); 2642 alloc_sz += num_vp * sizeof(uint32); 2643 } 2644 #endif 2645 } 2646 2647 /* Allocate scache for the MPLS map entry */ 2648 if (BCM_WB_DEFAULT_VERSION >= BCM_WB_VERSION_1_2) { 2649 alloc_sz += SHR_BITALLOCSIZE(num_mpls_map); 2650 } 2651 2652 if (BCM_WB_DEFAULT_VERSION >= BCM_WB_VERSION_1_3) { 2653 alloc_sz += (num_mpls_map * sizeof(uint32) - 2654 SHR_BITALLOCSIZE(num_mpls_map)); 2655 } 2656 2657 #ifdef BCM_APACHE_SUPPORT 2658 /* For MPLS EXP to PHB and CNG maps */ 2659 if (soc_feature(unit, soc_feature_mpls_exp_to_phb_cng_map)) { 2660 if (BCM_WB_DEFAULT_VERSION >= BCM_WB_VERSION_1_7) { 2661 alloc_sz += SHR_BITALLOCSIZE(soc_mem_index_count(unit, 2662 ING_MPLS_EXP_MAPPING_1m) / 16); 2663 alloc_sz += SHR_BITALLOCSIZE(soc_mem_index_count(unit, 2664 EGR_MPLS_EXP_MAPPING_3m) / 8); 2665 } 2666 } 2667 #endif 2668 /* Maximum virtual port supported on saber2 5626x devices are 4K 2669 * This fix is related to scaling down of vpn from 8K to 4K 2670 */ 2671 #if defined(BCM_SABER2_SUPPORT) 2672 if (soc_sb2_5626x_devtype(unit)) { 2673 alloc_sz += sizeof(source_vp_sb2_5626x); 2674 } 2675 #endif /* BCM_SABER2_SUPPORT */ 2676 2677 #ifdef BCM_SPECIAL_LABEL_SUPPORT 2678 if (soc_feature(unit, soc_feature_mpls_special_label)) { 2679 int num_entry = 0; 2680 2681 if (BCM_WB_DEFAULT_VERSION >= BCM_WB_VERSION_1_11) { 2682 num_entry = 2683 soc_mem_index_count(unit, SPECIAL_LABEL_CONTROLm); 2684 /* Ask for space for new two variables */ 2685 alloc_sz += (num_entry * 2 * sizeof(int)); 2686 } 2687 } 2688 #endif 2689 /* 2690 * Alloc space for TD3 VCSWAP Label action 2691 * in coldboot 2692 */ 2693 if (BCM_WB_DEFAULT_VERSION >= BCM_WB_VERSION_1_12) { 2694 if(soc_feature(unit, soc_feature_td3_style_mpls)) { 2695 alloc_sz += soc_mem_index_count(unit, 2696 EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm) * sizeof(int); 2697 } 2698 } 2699 #ifdef BCM_SPECIAL_LABEL_SUPPORT 2700 if (soc_feature(unit, soc_feature_mpls_special_label)) { 2701 2702 if (BCM_WB_DEFAULT_VERSION >= BCM_WB_VERSION_1_13) { 2703 /* Ask for space for new two variables */ 2704 alloc_sz += (2 * sizeof(int)); 2705 } 2706 } 2707 #endif 2708 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_MPLS, 0); 2709 2710 rv = _bcm_esw_scache_ptr_get(unit, scache_handle, TRUE, 2711 alloc_sz, &mpls_state, 2712 BCM_WB_DEFAULT_VERSION, NULL); 2713 2714 if (BCM_FAILURE(rv) && (rv != BCM_E_NOT_FOUND)) { 2715 return rv; 2716 } 2717 2718 } 2719 2720 cleanup: 2721 if (egr_nh_tbl_buf) { 2722 soc_cm_sfree(unit, egr_nh_tbl_buf); 2723 } 2724 2725 return rv; 2726 } 2727 2728 /* 2729 * Function: 2730 * _bcm_tr_mpls_nexthop_ref_inc 2731 * Purpose: 2732 * Recover the nexthop refcount for mpls entry from hw. 2733 * Parameters: 2734 * unit : (IN) Device Unit Number 2735 * Returns: 2736 * BCM_E_XXX 2737 */ 2738 STATIC int 2739 _bcm_tr_mpls_nexthop_ref_inc( 2740 int unit, 2741 bcm_mpls_tunnel_switch_t *info, 2742 void *user_data) 2743 { 2744 int rv = BCM_E_NONE; 2745 int nexthop = 0, nh_idx = 0; 2746 uint32 mpath_flag = 0; 2747 2748 COMPILER_REFERENCE(user_data); 2749 if (info == NULL) { 2750 return BCM_E_PARAM; 2751 } 2752 2753 nexthop = info->egress_if; 2754 if (nexthop) { 2755 /* figure out hw index from egress object */ 2756 rv = bcm_xgs3_get_nh_from_egress_object(unit, 2757 nexthop, &mpath_flag, 1, &nh_idx); 2758 if (BCM_FAILURE(rv)) { 2759 return rv; 2760 } 2761 } 2762 2763 #ifdef BCM_TRIDENT3_SUPPORT 2764 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 2765 if ((info->action_if_bos == BCM_MPLS_SWITCH_ACTION_PHP) || 2766 (info->action_if_not_bos == BCM_MPLS_SWITCH_ACTION_PHP)) { 2767 if (BCM_XGS3_L3_EGRESS_IDX_VALID(unit, info->egress_if)) { 2768 rv = bcm_xgs3_get_nh_from_egress_object(unit, 2769 info->egress_if, &mpath_flag, 1, &nh_idx); 2770 if (BCM_FAILURE(rv)) { 2771 return rv; 2772 } 2773 } 2774 } 2775 } 2776 #endif 2777 return BCM_E_NONE; 2778 } 2779 2780 /* 2781 * Function: 2782 * _bcm_tr_mpls_reinit 2783 * Purpose: 2784 * Top level Warm Boot init for MPLS 2785 * Parameters: 2786 * unit : (IN) Device Unit Number 2787 * Returns: 2788 * BCM_E_XXX 2789 */ 2790 STATIC int 2791 _bcm_tr_mpls_reinit(int unit) 2792 { 2793 int rv = BCM_E_NONE; 2794 int stable_size = 0; 2795 2796 if (SOC_WARM_BOOT(unit)) { 2797 (void)_bcm_esw_mpls_tunnel_switch_traverse_no_lock(unit, 2798 _bcm_tr_mpls_nexthop_ref_inc, NULL); 2799 } 2800 SOC_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size)); 2801 2802 if (stable_size == 0) { 2803 rv = _bcm_tr_mpls_unsynchronized_reinit(unit); 2804 } else if (SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit)) { 2805 rv = _bcm_tr_mpls_limited_reinit(unit); 2806 } else { 2807 rv = _bcm_tr_mpls_extended_reinit(unit); 2808 } 2809 return rv; 2810 } 2811 2812 /* 2813 * Function: 2814 * _bcm_tr_mpls_ingexpbitmap_sync 2815 * Purpose: 2816 * This is called only in the Cold Boot sequence when 2817 * limited scache is available. The 'ing_exp_map_bitmap' field of MPLS bk 2818 * structure is needed by the QoS module during Warm Boot with limited and 2819 * extended scache support. When extended scache support is available, 2820 * this field is retreived by the '_bcm_tr_mpls_extended_reinit' sequence. 2821 * Parameters: 2822 * unit : (IN) Device Unit Number 2823 * Returns: 2824 * BCM_E_XXX 2825 */ 2826 STATIC int 2827 _bcm_tr_mpls_ingexpbitmap_sync(int unit) 2828 { 2829 int rv = BCM_E_NONE; 2830 uint8 *mpls_state; 2831 int num_ing_exp_map; 2832 soc_scache_handle_t scache_handle; 2833 _bcm_tr_mpls_bookkeeping_t *mpls_info = MPLS_INFO(unit); 2834 2835 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_MPLS, 0); 2836 2837 rv = _bcm_esw_scache_ptr_get(unit, scache_handle, FALSE, 2838 sizeof(int32), &mpls_state, 2839 BCM_WB_DEFAULT_VERSION, NULL); 2840 2841 if (BCM_FAILURE(rv) && (rv != BCM_E_INTERNAL)) { 2842 return rv; 2843 } 2844 2845 num_ing_exp_map = _bcm_tr_get_ing_mpls_index_size(unit); 2846 2847 BCM_IF_ERROR_RETURN(bcm_tr_mpls_lock(unit)); 2848 SHR_BITCOPY_RANGE((SHR_BITDCL *)mpls_state, 0, 2849 mpls_info->ing_exp_map_bitmap, 0, num_ing_exp_map); 2850 bcm_tr_mpls_unlock(unit); 2851 return rv; 2852 } 2853 2854 /* 2855 * Function: 2856 * bcm_tr_mpls_sync 2857 * Purpose: 2858 * Store the s/w maintained MPLS book keeping structure 2859 * onto persistent memory. 2860 * Parameters: 2861 * unit : (IN) Device Unit Number 2862 * Returns: 2863 * BCM_E_XXX 2864 */ 2865 int 2866 bcm_tr_mpls_sync(int unit) 2867 { 2868 int num_vp = 0, num_vc = 0; 2869 int num_vrf, num_ip_tnl, num_mpls_map; 2870 int num_ing_exp_map, num_egr_l2_exp_map, num_pw_term, num_pw_init; 2871 #ifdef BCM_APACHE_SUPPORT 2872 int num_ing_exp_to_phb_cng_map = 0; 2873 int num_egr_exp_to_phb_cng_map = 0; 2874 #endif 2875 int num_nh, alloc_sz = 0; 2876 int i, vp_count, rv = BCM_E_NONE; 2877 uint8 *mpls_state, *mpls_state_marker; 2878 soc_scache_handle_t scache_handle; 2879 _bcm_tr_mpls_bookkeeping_t *mpls_info = MPLS_INFO(unit); 2880 _bcm_mpls_egr_nhopList_t *nhop_ptr; 2881 _bcm_mpls_vp_nh_list_t *vp_ptr; 2882 uint32 primary_nh_if, bitmask; 2883 #if defined(BCM_SABER2_SUPPORT) 2884 uint32 source_vp_sb2_5626x = 0xFED5ABC7; 2885 #endif /* BCM_SABER2_SUPPORT */ 2886 soc_mem_t mem; 2887 2888 if (SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit)) { 2889 return _bcm_tr_mpls_ingexpbitmap_sync(unit); 2890 } 2891 2892 num_mpls_map = soc_mem_index_count(unit, EGR_MPLS_EXP_MAPPING_1m) / 64; 2893 2894 BCM_IF_ERROR_RETURN(_bcm_tr_mpls_scache_size_get(unit, &alloc_sz)); 2895 if (SOC_MEM_IS_VALID(unit, SOURCE_VPm)) { 2896 if (BCM_WB_DEFAULT_VERSION >= BCM_WB_VERSION_1_1) { 2897 alloc_sz += (3 * sizeof(int)) * 2898 (soc_mem_index_count(unit, SOURCE_VPm)/2); 2899 2900 if ((BCM_WB_DEFAULT_VERSION >= BCM_WB_VERSION_1_8) && 2901 (soc_feature(unit, soc_feature_hierarchical_protection))) { 2902 2903 alloc_sz += (3 * sizeof(int)) * 2904 (soc_mem_index_count(unit, SOURCE_VPm)/2); 2905 } 2906 2907 } 2908 2909 if (BCM_WB_DEFAULT_VERSION >= BCM_WB_VERSION_1_5) { 2910 alloc_sz += SHR_BITALLOCSIZE(soc_mem_index_count(unit, SOURCE_VPm)); 2911 } 2912 2913 /* 2914 * For network_vp_bitmap 2915 */ 2916 if (BCM_WB_DEFAULT_VERSION >= BCM_WB_VERSION_1_6) { 2917 alloc_sz += SHR_BITALLOCSIZE(soc_mem_index_count(unit, SOURCE_VPm)); 2918 } 2919 2920 /* 2921 * For failover_vp 2922 */ 2923 #ifdef BCM_TRIUMPH2_SUPPORT 2924 if (soc_feature(unit, soc_feature_mpls_failover)) { 2925 if (BCM_WB_DEFAULT_VERSION >= BCM_WB_VERSION_1_10) { 2926 alloc_sz += 2927 sizeof(uint32) * soc_mem_index_count(unit, SOURCE_VPm); 2928 } 2929 } 2930 #endif /* BCM_TRIUMPH2_SUPPORT */ 2931 } 2932 2933 if (BCM_WB_DEFAULT_VERSION >= BCM_WB_VERSION_1_2) { 2934 alloc_sz += SHR_BITALLOCSIZE(num_mpls_map); 2935 } 2936 2937 if (BCM_WB_DEFAULT_VERSION >= BCM_WB_VERSION_1_3) { 2938 alloc_sz += (num_mpls_map * sizeof(uint32) - 2939 SHR_BITALLOCSIZE(num_mpls_map)); 2940 } 2941 2942 /* Maximum virtual port supported on saber2 5626x devices are 4K 2943 * This fix is related to scaling down of vpn from 8K to 4K 2944 */ 2945 #if defined(BCM_SABER2_SUPPORT) 2946 if (soc_sb2_5626x_devtype(unit)) { 2947 alloc_sz += sizeof(source_vp_sb2_5626x); 2948 } 2949 #endif /* BCM_SABER2_SUPPORT */ 2950 2951 2952 #ifdef BCM_SPECIAL_LABEL_SUPPORT 2953 if (soc_feature(unit, soc_feature_mpls_special_label)) { 2954 int num_entry = 0; 2955 /* Recover MPLS EXP to PHB and CNG maps */ 2956 if (BCM_WB_DEFAULT_VERSION >= BCM_WB_VERSION_1_11) { 2957 num_entry = 2958 soc_mem_index_count(unit, SPECIAL_LABEL_CONTROLm); 2959 alloc_sz += sizeof(bcmi_mpls_special_label_control_t) * num_entry; 2960 } 2961 } 2962 #endif /* BCM_SPECIAL_LABEL_SUPPORT */ 2963 2964 /* 2965 * Alloc sync space for TD3 VCSWAP Label action 2966 */ 2967 if (BCM_WB_DEFAULT_VERSION >= BCM_WB_VERSION_1_12) { 2968 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 2969 alloc_sz += soc_mem_index_count(unit, 2970 EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm) * sizeof(int); 2971 } 2972 } 2973 #ifdef BCM_SPECIAL_LABEL_SUPPORT 2974 if (soc_feature(unit, soc_feature_mpls_special_label)) { 2975 2976 if (BCM_WB_DEFAULT_VERSION >= BCM_WB_VERSION_1_13) { 2977 /* Ask for space for new two variables */ 2978 alloc_sz += (2 * sizeof(int)); 2979 } 2980 } 2981 #endif 2982 2983 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_MPLS, 0); 2984 rv = _bcm_esw_scache_ptr_get(unit, scache_handle, FALSE, 2985 alloc_sz, &mpls_state, 2986 BCM_WB_DEFAULT_VERSION, NULL); 2987 if (BCM_FAILURE(rv) && (rv != BCM_E_INTERNAL)) { 2988 return rv; 2989 } 2990 2991 /* Maximum virtual port supported on saber2 5626x devices are 4K 2992 * This fix is related to scaling down of vpn from 8K to 4K 2993 */ 2994 #if defined(BCM_SABER2_SUPPORT) 2995 if (soc_sb2_5626x_devtype(unit)) { 2996 sal_memcpy(mpls_state, &source_vp_sb2_5626x, sizeof(source_vp_sb2_5626x)); 2997 mpls_state += sizeof(source_vp_sb2_5626x); 2998 } 2999 #endif /* BCM_SABER2_SUPPORT */ 3000 num_vrf = SOC_CONTROL(unit)->max_vrf_id + 1; 3001 if (SOC_MEM_IS_VALID(unit, SOURCE_VPm)) { 3002 num_vp = soc_mem_index_count(unit, SOURCE_VPm); 3003 } 3004 if (SOC_MEM_IS_VALID(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm)) { 3005 num_vc = soc_mem_index_count(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm); 3006 } 3007 3008 #if defined(BCM_TRIDENT3_SUPPORT) 3009 if(soc_feature(unit, soc_feature_td3_style_mpls)) { 3010 num_ip_tnl = soc_mem_index_count(unit, 3011 EGR_IP_TUNNEL_MPLS_DOUBLE_WIDEm); 3012 } else 3013 #endif 3014 { 3015 num_ip_tnl = soc_mem_index_count(unit, EGR_IP_TUNNEL_MPLSm); 3016 } 3017 3018 /* EGR_MPLS_EXP_MAPPING_1 profiles indexed by ((int_pri << 2) + cng) */ 3019 num_ing_exp_map = _bcm_tr_get_ing_mpls_index_size(unit); 3020 num_egr_l2_exp_map = bcmi_egr_mpls_exp_pri_mapping_num_exp_map_get(unit); 3021 #ifdef BCM_APACHE_SUPPORT 3022 if (soc_feature(unit, soc_feature_mpls_exp_to_phb_cng_map)) { 3023 num_ing_exp_to_phb_cng_map = soc_mem_index_count(unit, 3024 ING_MPLS_EXP_MAPPING_1m) / 16; 3025 num_egr_exp_to_phb_cng_map = soc_mem_index_count(unit, 3026 EGR_MPLS_EXP_MAPPING_3m) / 8; 3027 } 3028 #endif 3029 num_pw_term = 0; 3030 if (SOC_MEM_IS_VALID(unit, ING_PW_TERM_COUNTERSm)) { 3031 num_pw_term = soc_mem_index_count(unit, ING_PW_TERM_COUNTERSm); 3032 } 3033 num_pw_init = 0; 3034 #if defined(BCM_TRIDENT3_SUPPORT) 3035 if(soc_feature(unit, soc_feature_td3_style_mpls)) { 3036 mem = EGR_SEQUENCE_NUMBER_TABLEm; 3037 } else 3038 #endif 3039 { 3040 mem = EGR_PW_INIT_COUNTERSm; 3041 } 3042 if (SOC_MEM_IS_VALID(unit, mem)) { 3043 num_pw_init = soc_mem_index_count(unit, mem); 3044 } 3045 num_nh = soc_mem_index_count(unit, EGR_L3_NEXT_HOPm); 3046 3047 BCM_IF_ERROR_RETURN(bcm_tr_mpls_lock(unit)); 3048 3049 rv = BCM_E_NONE; 3050 SHR_BITCOPY_RANGE((SHR_BITDCL *)mpls_state, 0, 3051 mpls_info->vrf_bitmap, 0, num_vrf); 3052 mpls_state += SHR_BITALLOCSIZE(num_vrf); 3053 SHR_BITCOPY_RANGE((SHR_BITDCL *)mpls_state, 0, 3054 mpls_info->vpws_bitmap, 0, (num_vp/2)); 3055 mpls_state += SHR_BITALLOCSIZE(num_vp/2); 3056 SHR_BITCOPY_RANGE((SHR_BITDCL *)mpls_state, 0, 3057 mpls_info->vc_c_bitmap, 0, num_vc); 3058 mpls_state += SHR_BITALLOCSIZE(num_vc); 3059 SHR_BITCOPY_RANGE((SHR_BITDCL *)mpls_state, 0, 3060 mpls_info->vc_nc_bitmap, 0, num_vc); 3061 mpls_state += SHR_BITALLOCSIZE(num_vc); 3062 if (num_pw_term) { 3063 SHR_BITCOPY_RANGE((SHR_BITDCL *)mpls_state, 0, 3064 mpls_info->pw_term_bitmap, 0, num_pw_term); 3065 mpls_state += SHR_BITALLOCSIZE(num_pw_term); 3066 } 3067 if (num_pw_init) { 3068 SHR_BITCOPY_RANGE((SHR_BITDCL *)mpls_state, 0, 3069 mpls_info->pw_init_bitmap, 0, num_pw_init); 3070 mpls_state += SHR_BITALLOCSIZE(num_pw_init); 3071 } 3072 3073 SHR_BITCOPY_RANGE((SHR_BITDCL *)mpls_state, 0, 3074 mpls_info->egr_mpls_bitmap, 0, num_mpls_map); 3075 mpls_state += SHR_BITALLOCSIZE(num_mpls_map); 3076 SHR_BITCOPY_RANGE((SHR_BITDCL *)mpls_state, 0, 3077 mpls_info->ing_exp_map_bitmap, 0, num_ing_exp_map); 3078 mpls_state += SHR_BITALLOCSIZE(num_ing_exp_map); 3079 SHR_BITCOPY_RANGE((SHR_BITDCL *)mpls_state, 0, 3080 mpls_info->egr_l2_exp_map_bitmap, 0, num_egr_l2_exp_map); 3081 mpls_state += SHR_BITALLOCSIZE(num_egr_l2_exp_map); 3082 SHR_BITCOPY_RANGE((SHR_BITDCL *)mpls_state, 0, 3083 mpls_info->tnl_bitmap, 0, 3084 (num_ip_tnl * _BCM_MPLS_NUM_MPLS_ENTRIES_PER_INDEX(unit))); 3085 mpls_state += SHR_BITALLOCSIZE(num_ip_tnl * 3086 _BCM_MPLS_NUM_MPLS_ENTRIES_PER_INDEX(unit)); 3087 SHR_BITCOPY_RANGE((SHR_BITDCL *)mpls_state, 0, 3088 mpls_info->ip_tnl_bitmap, 0, num_ip_tnl); 3089 mpls_state += SHR_BITALLOCSIZE(num_ip_tnl); 3090 mpls_state_marker = mpls_state; 3091 3092 bitmask = 1 << ((8 * sizeof(uint32)) - 1); 3093 for (i = 0; i < _BCM_TR_MPLS_HASH_ELEMENTS; i++) { 3094 if (_bcm_tr_mpls_nhop_headPtr[unit][i] != NULL) { 3095 for (nhop_ptr = _bcm_tr_mpls_nhop_headPtr[unit][i]; 3096 nhop_ptr != NULL; 3097 nhop_ptr = nhop_ptr->link) { 3098 primary_nh_if = nhop_ptr->egr_if; 3099 primary_nh_if |= bitmask; 3100 sal_memcpy(mpls_state, &primary_nh_if, sizeof(uint32)); 3101 mpls_state += sizeof(uint32); 3102 for (vp_ptr = nhop_ptr->vp_head_ptr; 3103 vp_ptr != NULL; 3104 vp_ptr = vp_ptr->link) { 3105 sal_memcpy(mpls_state, &(vp_ptr->vp_nh_idx), sizeof(uint32)); 3106 mpls_state += sizeof(uint32); 3107 } /* for each vp on nh */ 3108 } /* for each nh */ 3109 } 3110 } 3111 vp_count = 0xdeadbeef; 3112 sal_memcpy(mpls_state, &vp_count, sizeof(uint32)); 3113 mpls_state = mpls_state_marker + (sizeof(uint32) * num_nh); 3114 3115 /* Sync the MPLS scache for the VPWS VP map */ 3116 if (BCM_WB_DEFAULT_VERSION >= BCM_WB_VERSION_1_1) { 3117 mpls_state += sizeof(int); 3118 /* Copy VPWS map table to scache */ 3119 for (i=0; i<(num_vp/2); i++) { 3120 sal_memcpy(mpls_state, &mpls_info->vpws_vp_map[i].vp1, 3121 sizeof(int)); 3122 mpls_state += sizeof(int); 3123 sal_memcpy(mpls_state, &mpls_info->vpws_vp_map[i].vp2, 3124 sizeof(int)); 3125 mpls_state += sizeof(int); 3126 sal_memcpy(mpls_state, &mpls_info->vpws_vp_map[i].vp3, 3127 sizeof(int)); 3128 mpls_state += sizeof(int); 3129 3130 if ((BCM_WB_DEFAULT_VERSION >= BCM_WB_VERSION_1_8) && 3131 (soc_feature(unit, soc_feature_hierarchical_protection))) { 3132 sal_memcpy(mpls_state, &mpls_info->vpws_vp_map[i].vp_b_1, 3133 sizeof(int)); 3134 mpls_state += sizeof(int); 3135 sal_memcpy(mpls_state, &mpls_info->vpws_vp_map[i].vp_b_2, 3136 sizeof(int)); 3137 mpls_state += sizeof(int); 3138 sal_memcpy(mpls_state, &mpls_info->vpws_vp_map[i].vp_b_3, 3139 sizeof(int)); 3140 mpls_state += sizeof(int); 3141 } 3142 } 3143 } 3144 3145 /* Sync the scache for the MPLS map */ 3146 if (BCM_WB_DEFAULT_VERSION >= BCM_WB_VERSION_1_2) { 3147 sal_memcpy(mpls_state, mpls_info->egr_mpls_hw_idx, 3148 (num_mpls_map * sizeof(uint32))); 3149 mpls_state += (num_mpls_map * sizeof(uint32)); 3150 } 3151 3152 /* Sync the scache for the MPLS svp profile set */ 3153 if (BCM_WB_DEFAULT_VERSION >= BCM_WB_VERSION_1_5) { 3154 SHR_BITCOPY_RANGE((SHR_BITDCL *)mpls_state, 0, 3155 mpls_info->svp_profile_set_bitmap, 0, num_vp); 3156 mpls_state += SHR_BITALLOCSIZE(num_vp); 3157 } 3158 3159 /* Sync the scache for the MPLS network VP bitmap */ 3160 if (BCM_WB_DEFAULT_VERSION >= BCM_WB_VERSION_1_6) { 3161 SHR_BITCOPY_RANGE((SHR_BITDCL *)mpls_state, 0, 3162 mpls_info->network_vp_bitmap, 0, num_vp); 3163 mpls_state += SHR_BITALLOCSIZE(num_vp); 3164 } 3165 #ifdef BCM_APACHE_SUPPORT 3166 if (soc_feature(unit, soc_feature_mpls_exp_to_phb_cng_map)) { 3167 /* Sync the scache for the MPLS EXP to PHB and CNG maps */ 3168 3169 SHR_BITCOPY_RANGE((SHR_BITDCL *)mpls_state, 0, 3170 mpls_info->ing_exp_to_phb_cng_map_bitmap, 0, 3171 num_ing_exp_to_phb_cng_map); 3172 mpls_state += SHR_BITALLOCSIZE(num_ing_exp_to_phb_cng_map); 3173 SHR_BITCOPY_RANGE((SHR_BITDCL *)mpls_state, 0, 3174 mpls_info->egr_exp_to_phb_cng_map_bitmap, 0, 3175 num_egr_exp_to_phb_cng_map); 3176 mpls_state += SHR_BITALLOCSIZE(num_egr_exp_to_phb_cng_map); 3177 } 3178 #endif 3179 3180 #ifdef BCM_TRIUMPH2_SUPPORT 3181 if (soc_feature(unit, soc_feature_mpls_failover)) { 3182 if (BCM_WB_DEFAULT_VERSION >= BCM_WB_VERSION_1_10) { 3183 sal_memcpy(mpls_state, mpls_info->failover_vp, 3184 (num_vp * sizeof(uint32))); 3185 mpls_state += sizeof(uint32) * soc_mem_index_count(unit, SOURCE_VPm); 3186 } 3187 } 3188 #endif /* BCM_TRIUMPH2_SUPPORT */ 3189 #ifdef BCM_SPECIAL_LABEL_SUPPORT 3190 if (soc_feature(unit, soc_feature_mpls_special_label)) { 3191 int num_entry = 0; 3192 bcmi_mpls_special_label_control_t *ptr; 3193 /* Recover MPLS EXP to PHB and CNG maps */ 3194 if (BCM_WB_DEFAULT_VERSION >= BCM_WB_VERSION_1_11) { 3195 3196 ptr = bcmi_special_label_precedence_state[unit]; 3197 num_entry = 3198 soc_mem_index_count(unit, SPECIAL_LABEL_CONTROLm); 3199 for (i = 0; i < num_entry; i++) { 3200 sal_memcpy(mpls_state, (&(ptr[i].ref_count)), 3201 sizeof(int)); 3202 mpls_state += sizeof(int); 3203 sal_memcpy(mpls_state, (&(ptr[i].cancun_added)), 3204 sizeof(int)); 3205 mpls_state += sizeof(int); 3206 } 3207 } 3208 } 3209 #endif 3210 3211 #if defined(BCM_TRIDENT3_SUPPORT) 3212 /* Sync VCSWAP Label action into scache*/ 3213 if (BCM_WB_DEFAULT_VERSION >= BCM_WB_VERSION_1_12) { 3214 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 3215 sal_memcpy(mpls_state, mpls_info->egr_vc_swap_lbl_action, 3216 num_vc * sizeof(int)); 3217 mpls_state += num_vc * sizeof(int); 3218 } 3219 } 3220 #endif 3221 #ifdef BCM_SPECIAL_LABEL_SUPPORT 3222 if (soc_feature(unit, soc_feature_mpls_special_label)) { 3223 if (BCM_WB_DEFAULT_VERSION >= BCM_WB_VERSION_1_13) { 3224 bcmi_mpls_special_label_egress_t *ptr; 3225 3226 ptr = (&(bcmi_special_label_egress_state[unit])); 3227 sal_memcpy(mpls_state, (&(ptr->special_label_ref_count)), 3228 sizeof(int)); 3229 mpls_state += sizeof(int); 3230 sal_memcpy(mpls_state, (&(ptr->entropy_label_ref_count)), 3231 sizeof(int)); 3232 mpls_state += sizeof(int); 3233 3234 } 3235 } 3236 #endif 3237 3238 bcm_tr_mpls_unlock(unit); 3239 3240 return rv; 3241 } 3242 3243 #endif 3244 3245 int 3246 _egr_qos_id2hw_idx (int unit,int qos_id,int *hw_inx) 3247 { 3248 int rv = BCM_E_NOT_FOUND; 3249 int table_num; 3250 3251 if (SOC_IS_TRIUMPH(unit) || SOC_IS_VALKYRIE(unit)) { 3252 rv = _bcm_tr_qos_id2idx(unit, qos_id, hw_inx); 3253 } else { 3254 #ifdef BCM_TRIUMPH2_SUPPORT 3255 rv = _bcm_tr2_qos_id2idx(unit, qos_id, hw_inx); 3256 #endif /* BCM_TRIUMPH2_SUPPORT */ 3257 } 3258 3259 if (rv == BCM_E_NOT_FOUND) { 3260 /* created from API bcm_mpls_exp_map_create() */ 3261 if ((qos_id & (~_BCM_TR_MPLS_EXP_MAP_TABLE_NUM_MASK)) == 3262 _BCM_TR_MPLS_EXP_MAP_TABLE_TYPE_EGRESS) { 3263 table_num = qos_id & _BCM_TR_MPLS_EXP_MAP_TABLE_NUM_MASK; 3264 if (!_BCM_EGR_MPLS_MAP_USED_GET(unit, table_num)) { 3265 return BCM_E_PARAM; 3266 } 3267 *hw_inx = MPLS_INFO(unit)->egr_mpls_hw_idx[table_num]; 3268 rv = BCM_E_NONE; 3269 } else if ((qos_id & (~_BCM_TR_MPLS_EXP_MAP_TABLE_NUM_MASK)) == 3270 _BCM_TR_MPLS_EXP_MAP_TABLE_TYPE_EGRESS_L2) { 3271 table_num = qos_id & _BCM_TR_MPLS_EXP_MAP_TABLE_NUM_MASK; 3272 if (!_BCM_MPLS_EGR_EXP_MAP_USED_GET(unit, table_num)) { 3273 return BCM_E_PARAM; 3274 } 3275 *hw_inx = table_num; 3276 rv = BCM_E_NONE; 3277 } else { 3278 rv = BCM_E_NOT_FOUND; 3279 } 3280 } 3281 if (rv == BCM_E_NOT_FOUND) { 3282 rv = BCM_E_PARAM; 3283 } 3284 return rv; 3285 } 3286 3287 #if !defined(_BCM_QOS_MAP_TYPE_EGR_MPLS_MAPS) 3288 #define _BCM_QOS_MAP_TYPE_EGR_MPLS_MAPS 2 3289 #endif 3290 3291 int 3292 _egr_qos_hw_idx2id (int unit, int hw_idx, int *map_id) 3293 { 3294 int rv = BCM_E_NOT_FOUND; 3295 int num_exp_map = soc_mem_index_count(unit, EGR_MPLS_EXP_MAPPING_1m) / 64; 3296 int id; 3297 3298 if (SOC_IS_TRIUMPH(unit) || SOC_IS_VALKYRIE(unit)) { 3299 rv = _bcm_tr_qos_idx2id(unit, hw_idx, _BCM_QOS_MAP_TYPE_EGR_MPLS_MAPS, map_id); 3300 } else { 3301 #ifdef BCM_TRIUMPH2_SUPPORT 3302 rv = _bcm_tr2_qos_idx2id(unit, hw_idx, _BCM_QOS_MAP_TYPE_EGR_MPLS_MAPS, map_id); 3303 #endif /* BCM_TRIUMPH2_SUPPORT */ 3304 } 3305 3306 3307 if (rv == BCM_E_NOT_FOUND) { 3308 /* created from API bcm_mpls_exp_map_create() */ 3309 3310 for (id = 0; id < num_exp_map; id++) { 3311 if (_BCM_EGR_MPLS_MAP_USED_GET(unit, id)) { 3312 if (MPLS_INFO(unit)->egr_mpls_hw_idx[id] == (uint32)hw_idx) { 3313 *map_id = id | _BCM_TR_MPLS_EXP_MAP_TABLE_TYPE_EGRESS; 3314 rv = BCM_E_NONE; 3315 break; 3316 } 3317 } 3318 } 3319 } 3320 3321 if (rv == BCM_E_NOT_FOUND) { 3322 for (id = 0; id < num_exp_map; id++) { 3323 if (_BCM_MPLS_EGR_EXP_MAP_USED_GET(unit, id)) { 3324 if (id == hw_idx) { 3325 *map_id = id | _BCM_TR_MPLS_EXP_MAP_TABLE_TYPE_EGRESS_L2; 3326 rv = BCM_E_NONE; 3327 break; 3328 } 3329 } 3330 } 3331 } 3332 if (rv == BCM_E_NOT_FOUND) { 3333 if (hw_idx == 0) { 3334 *map_id = 0; 3335 return BCM_E_NONE; 3336 } 3337 rv = BCM_E_PARAM; 3338 } 3339 return rv; 3340 } 3341 #ifdef BCM_APACHE_SUPPORT 3342 STATIC int bcm_apache_mpls_effective_phb_select_init(int unit) 3343 { 3344 int num_ing_phb_select_entries, num_egr_phb_select_entries, index; 3345 effective_phb_select_entry_t ing_phb_select_entry; 3346 egr_effective_phb_select_entry_t egr_phb_select_entry; 3347 3348 num_ing_phb_select_entries = soc_mem_index_count(unit, 3349 EFFECTIVE_PHB_SELECTm); 3350 num_egr_phb_select_entries = soc_mem_index_count(unit, 3351 EGR_EFFECTIVE_PHB_SELECTm); 3352 3353 /*Use PHB for INNER label in Ingress pipeline(Decapsulation) */ 3354 for (index = 0; index < num_ing_phb_select_entries; index++) { 3355 BCM_IF_ERROR_RETURN(READ_EFFECTIVE_PHB_SELECTm(unit, MEM_BLOCK_ANY, 3356 index, 3357 &ing_phb_select_entry)); 3358 if((index & 1) == 0) { 3359 soc_EFFECTIVE_PHB_SELECTm_field32_set(unit, &ing_phb_select_entry, 3360 EFFECTIVE_PHB3_SELECTf, 3361 _BCM_MPLS_FWD_LABEL3_PHB_FROM_TOS); 3362 } else { 3363 soc_EFFECTIVE_PHB_SELECTm_field32_set(unit, &ing_phb_select_entry, 3364 EFFECTIVE_PHB3_SELECTf, 3365 _BCM_MPLS_FWD_LABEL2_PHB_FROM_TOS); 3366 } 3367 if((index & 2) == 0) { 3368 soc_EFFECTIVE_PHB_SELECTm_field32_set(unit, &ing_phb_select_entry, 3369 EFFECTIVE_PHB2_SELECTf, 3370 _BCM_MPLS_FWD_LABEL2_PHB_FROM_TOS); 3371 } else { 3372 soc_EFFECTIVE_PHB_SELECTm_field32_set(unit, &ing_phb_select_entry, 3373 EFFECTIVE_PHB2_SELECTf, 3374 _BCM_MPLS_FWD_LABEL1_PHB_FROM_TOS); 3375 } 3376 /*Use PHB of label 1 both for pipe and uniform tunnels*/ 3377 soc_EFFECTIVE_PHB_SELECTm_field32_set(unit, &ing_phb_select_entry, 3378 EFFECTIVE_PHB1_SELECTf, 3379 _BCM_MPLS_FWD_LABEL1_PHB_FROM_TOS); 3380 3381 BCM_IF_ERROR_RETURN(WRITE_EFFECTIVE_PHB_SELECTm(unit, MEM_BLOCK_ALL, 3382 index, 3383 &ing_phb_select_entry)); 3384 } 3385 3386 /*Use PHB from INNER label in the Egress pipeline (Encapsulation)*/ 3387 for (index = 0; index < num_egr_phb_select_entries; index++) { 3388 BCM_IF_ERROR_RETURN(READ_EGR_EFFECTIVE_PHB_SELECTm(unit, MEM_BLOCK_ANY, 3389 index, 3390 &egr_phb_select_entry)); 3391 /*Use PHB of label 3 both for pipe and uniform tunnels*/ 3392 soc_EGR_EFFECTIVE_PHB_SELECTm_field32_set(unit, &egr_phb_select_entry, 3393 EFFECTIVE_PHB3_SELECTf, 3394 _BCM_MPLS_FWD_LABEL3_PHB_FROM_TOS); 3395 3396 if(((index & 0xc) >> 2) == 2) { 3397 soc_EGR_EFFECTIVE_PHB_SELECTm_field32_set(unit, &egr_phb_select_entry, 3398 EFFECTIVE_PHB2_SELECTf, 3399 _BCM_MPLS_FWD_LABEL2_PHB_FROM_TOS); 3400 } else { 3401 soc_EGR_EFFECTIVE_PHB_SELECTm_field32_set(unit, &egr_phb_select_entry, 3402 EFFECTIVE_PHB2_SELECTf, 3403 _BCM_MPLS_FWD_LABEL3_PHB_FROM_TOS); 3404 } 3405 if(((index & 0x30) >> 4) == 2) { 3406 soc_EGR_EFFECTIVE_PHB_SELECTm_field32_set(unit, &egr_phb_select_entry, 3407 EFFECTIVE_PHB1_SELECTf, 3408 _BCM_MPLS_FWD_LABEL1_PHB_FROM_TOS); 3409 } else { 3410 soc_EGR_EFFECTIVE_PHB_SELECTm_field32_set(unit, &egr_phb_select_entry, 3411 EFFECTIVE_PHB1_SELECTf, 3412 _BCM_MPLS_FWD_LABEL2_PHB_FROM_TOS); 3413 } 3414 BCM_IF_ERROR_RETURN(WRITE_EGR_EFFECTIVE_PHB_SELECTm(unit, MEM_BLOCK_ALL, 3415 index, 3416 &egr_phb_select_entry)); 3417 } 3418 return BCM_E_NONE; 3419 } 3420 #endif 3421 3422 #if defined(BCM_TRIDENT2_SUPPORT) 3423 /* 3424 * Function: 3425 * _bcm_tr_l3_ingress_interface_dma_init 3426 * Purpose: 3427 * Perform L3_IIF Table Initialization using DMA Operation 3428 * Parameters: 3429 * unit : (IN) Device Unit Number 3430 * start_idx : (IN) Start index for Read/Write 3431 * end_idx : (IN) End index for Read/Write 3432 * Returns: 3433 * BCM_E_XXX 3434 * 3435 * Note: 3436 * Function to perform DMA Read / Write of L3_IIF during initialization 3437 * and perform all init related operations without read / writes to H/W 3438 */ 3439 int _bcm_tr_l3_ingress_interface_dma_init(int unit, 3440 int start_idx, 3441 int end_idx) 3442 { 3443 uint32 *l3iif_buf = NULL; 3444 iif_entry_t *hw_entry = NULL; 3445 iif_entry_t write_entry; 3446 _bcm_l3_ingress_intf_t iif; 3447 int idx, size, count; 3448 int rv = BCM_E_INTERNAL; 3449 3450 /* Determine size of buffer to be allocated. 3451 * Ideally buffer allocation should be done in chunks in case chunk size 3452 * is defined. 3453 */ 3454 count = (end_idx - start_idx +1); 3455 size = count * soc_mem_entry_words(unit, L3_IIFm) * 4; 3456 3457 l3iif_buf = soc_cm_salloc(unit, size, "l3_iif_buffer"); 3458 if (l3iif_buf == NULL) { 3459 return BCM_E_MEMORY; 3460 } 3461 3462 sal_memset((void *)l3iif_buf, 0, size); 3463 /* Read L3_IIF Table */ 3464 rv = soc_mem_read_range(unit, L3_IIFm, MEM_BLOCK_ANY, 3465 start_idx, end_idx, l3iif_buf); 3466 if (SOC_FAILURE(rv)) { 3467 LOG_ERROR(BSL_LS_BCM_MPLS, 3468 (BSL_META_U(unit, 3469 "Mpls Init: DMA Read Failed for L3_IIF\n"))); 3470 soc_cm_sfree(unit, l3iif_buf); 3471 return rv; 3472 } 3473 3474 /* Iterate over each entry to get and set the S/W structure */ 3475 for (idx = 0; idx < count; idx++) { 3476 sal_memset(&iif, 0, sizeof(_bcm_l3_ingress_intf_t)); 3477 iif.intf_id = idx + start_idx; 3478 iif.vrf = 0; 3479 sal_memcpy(&write_entry, soc_mem_entry_null(unit, L3_IIFm), 3480 sizeof(iif_entry_t)); 3481 3482 /* Read entry from buffer and pass it to interface function in order 3483 * to avoid a PIO read */ 3484 hw_entry = soc_mem_table_idx_to_pointer(unit, L3_IIFm, iif_entry_t *, 3485 l3iif_buf, idx); 3486 3487 /* Populate iif structure to using a _get API , No PIO Reads performed*/ 3488 rv = _bcm_tr_l3_ingress_interface_get(unit, hw_entry, &iif); 3489 if (BCM_FAILURE(rv)) { 3490 LOG_ERROR(BSL_LS_BCM_MPLS, 3491 (BSL_META_U(unit, 3492 "Mpls Init: Ingress interface get failed for index=(%d)\n"), 3493 idx)); 3494 soc_cm_sfree(unit, l3iif_buf); 3495 return rv; 3496 } 3497 3498 /* Get the new entry to be written to hw , pass the hw_entry as an argument 3499 * to the function to avoid PIO read & write. 3500 * Profile function is also updated to not read from H/W but use the hw_entry 3501 * provided 3502 */ 3503 rv = _bcm_tr_l3_ingress_interface_set(unit, &iif, hw_entry, 3504 &write_entry); 3505 if (BCM_FAILURE(rv)) { 3506 LOG_ERROR(BSL_LS_BCM_MPLS, 3507 (BSL_META_U(unit, 3508 "Mpls Init: Ingress interface set failed for index=(%d)\n"), 3509 idx)); 3510 soc_cm_sfree(unit, l3iif_buf); 3511 return rv; 3512 } 3513 3514 /* Update the entry copy in the DMAed buffer with the new contents 3515 * of write_entry modified by interface_set. 3516 */ 3517 sal_memcpy(hw_entry, &write_entry, soc_mem_entry_words(unit, L3_IIFm) * 4); 3518 } 3519 3520 /* Write to H/W */ 3521 rv = soc_mem_write_range(unit, L3_IIFm, MEM_BLOCK_ALL, 3522 start_idx, end_idx, l3iif_buf); 3523 soc_cm_sfree(unit, l3iif_buf); 3524 return rv; 3525 } 3526 #endif 3527 3528 /* 3529 * Function: 3530 * bcm_mpls_init 3531 * Purpose: 3532 * Initialize the MPLS software module 3533 * Parameters: 3534 * unit - Device Number 3535 * Returns: 3536 * BCM_E_XXX 3537 */ 3538 int 3539 bcm_tr_mpls_init(int unit) 3540 { 3541 _bcm_tr_mpls_bookkeeping_t *mpls_info = MPLS_INFO(unit); 3542 bcm_tr_mpls_vc_swap_table_hash_t *vc_swap_hash; 3543 int rv=0, i, num_vp = 0, num_vpws = 0, num_vc = 0, num_vrf, num_iif, num_trunk = 0; 3544 int num_pw_term, num_pw_init, num_ip_tnl, num_mpls_map, num_ing_exp_map, num_egr_l2_exp_map, pkt_cfi, pkt_pri; 3545 #ifdef BCM_APACHE_SUPPORT 3546 int num_egr_mpls_exp_to_phb_cng_map = 0; 3547 int num_ing_mpls_exp_to_phb_cng_map = 0; 3548 #endif 3549 soc_mem_t mem; 3550 soc_field_t pri_field; 3551 uint32 pri_map[SOC_MAX_MEM_FIELD_WORDS]; 3552 vfi_entry_t vfi_entry; 3553 int num_vfi = 0; 3554 3555 _bcm_l3_ingress_intf_t iif; 3556 uint32 label; 3557 #ifdef BCM_KATANA_SUPPORT 3558 int num_ing_qmap = 0; 3559 #endif /* BCM_KATANA_SUPPORT */ 3560 3561 if (!L3_INFO(unit)->l3_initialized) { 3562 LOG_ERROR(BSL_LS_BCM_MPLS, 3563 (BSL_META_U(unit, 3564 "L3 module must be initialized prior to MPLS_init\n"))); 3565 return BCM_E_CONFIG; 3566 } 3567 3568 /* cache the EGR_MPLS_VC_AND_SWAP_LABEL_TABLE field info for fast performance in the 3569 * table serarch function. 3570 */ 3571 if (!soc_feature(unit, soc_feature_th3_style_simple_mpls)) { 3572 SOC_VC_SWAP_LABLE_FIELD_ASSIGN(unit, &soc_emvasltm_field_cache[unit], 3573 EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, MPLS_LABELf); 3574 SOC_VC_SWAP_LABLE_FIELD_ASSIGN(unit, &soc_emvasltm_field_cache[unit], 3575 EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, MPLS_LABEL_ACTIONf); 3576 SOC_VC_SWAP_LABLE_FIELD_ASSIGN(unit, &soc_emvasltm_field_cache[unit], 3577 EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, MPLS_TTLf); 3578 SOC_VC_SWAP_LABLE_FIELD_ASSIGN(unit, &soc_emvasltm_field_cache[unit], 3579 EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, CW_INSERT_FLAGf); 3580 SOC_VC_SWAP_LABLE_FIELD_ASSIGN(unit, &soc_emvasltm_field_cache[unit], 3581 EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, MPLS_EXPf); 3582 SOC_VC_SWAP_LABLE_FIELD_ASSIGN(unit, &soc_emvasltm_field_cache[unit], 3583 EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, NEW_PRIf); 3584 SOC_VC_SWAP_LABLE_FIELD_ASSIGN(unit, &soc_emvasltm_field_cache[unit], 3585 EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, NEW_CFIf); 3586 SOC_VC_SWAP_LABLE_FIELD_ASSIGN(unit, &soc_emvasltm_field_cache[unit], 3587 EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, SD_TAG_VIDf); 3588 SOC_VC_SWAP_LABLE_FIELD_ASSIGN(unit, &soc_emvasltm_field_cache[unit], 3589 EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, SD_TAG_ACTION_IF_PRESENTf); 3590 SOC_VC_SWAP_LABLE_FIELD_ASSIGN(unit, &soc_emvasltm_field_cache[unit], 3591 EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, SD_TAG_ACTION_IF_NOT_PRESENTf); 3592 SOC_VC_SWAP_LABLE_FIELD_ASSIGN(unit, &soc_emvasltm_field_cache[unit], 3593 EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, MPLS_EXP_SELECTf); 3594 SOC_VC_SWAP_LABLE_FIELD_ASSIGN(unit, &soc_emvasltm_field_cache[unit], 3595 EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, MPLS_EXP_MAPPING_PTRf); 3596 } 3597 3598 /* 3599 * Include flex stat hooks when implemented 3600 */ 3601 if (SOC_MEM_IS_VALID(unit, VFIm)) { 3602 num_vfi = soc_mem_index_count(unit, VFIm); 3603 } 3604 3605 num_vrf = SOC_CONTROL(unit)->max_vrf_id + 1; 3606 num_iif = soc_mem_index_count(unit, L3_IIFm); 3607 if (SOC_MEM_IS_VALID(unit, SOURCE_VPm)) { 3608 num_vp = soc_mem_index_count(unit, SOURCE_VPm); 3609 num_vpws = num_vp / 2; 3610 } 3611 if (SOC_MEM_IS_VALID(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm)) { 3612 num_vc = soc_mem_index_count(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm); 3613 } 3614 #if defined(BCM_TRIDENT3_SUPPORT) 3615 if(soc_feature(unit, soc_feature_td3_style_mpls)) { 3616 num_ip_tnl = soc_mem_index_count(unit, 3617 EGR_IP_TUNNEL_MPLS_DOUBLE_WIDEm); 3618 } else 3619 #endif 3620 { 3621 num_ip_tnl = soc_mem_index_count(unit, EGR_IP_TUNNEL_MPLSm); 3622 } 3623 if (SOC_MEM_IS_VALID(unit, TRUNK_GROUPm)) { 3624 num_trunk = soc_mem_index_count(unit, TRUNK_GROUPm); 3625 } 3626 #ifdef BCM_KATANA_SUPPORT 3627 if (soc_feature(unit, soc_feature_extended_queueing)) { 3628 num_ing_qmap = soc_mem_index_count(unit, ING_QUEUE_MAPm); 3629 } 3630 #endif /* BCM_KATANA_SUPPORT */ 3631 /* EGR_MPLS_EXP_MAPPING_1 profiles indexed by ((int_pri << 2) + cng) */ 3632 num_mpls_map = soc_mem_index_count(unit, EGR_MPLS_EXP_MAPPING_1m) / 64; 3633 num_ing_exp_map = _bcm_tr_get_ing_mpls_index_size(unit); 3634 #ifdef BCM_APACHE_SUPPORT 3635 if (soc_feature(unit, soc_feature_mpls_exp_to_phb_cng_map)) { 3636 num_egr_mpls_exp_to_phb_cng_map = soc_mem_index_count(unit, 3637 EGR_MPLS_EXP_MAPPING_3m) / 8; 3638 num_ing_mpls_exp_to_phb_cng_map = soc_mem_index_count(unit, 3639 ING_MPLS_EXP_MAPPING_1m) / 16; 3640 } 3641 #endif 3642 3643 num_egr_l2_exp_map = bcmi_egr_mpls_exp_pri_mapping_num_exp_map_get(unit); 3644 num_pw_term = 0; 3645 if (SOC_MEM_IS_VALID(unit, ING_PW_TERM_COUNTERSm)) { 3646 num_pw_term = soc_mem_index_count(unit, ING_PW_TERM_COUNTERSm); 3647 } else if (SOC_MEM_IS_VALID(unit, ING_PW_TERM_SEQ_NUMm)) { 3648 num_pw_term = soc_mem_index_count(unit, ING_PW_TERM_SEQ_NUMm); 3649 } 3650 num_pw_init = 0; 3651 #if defined(BCM_TRIDENT3_SUPPORT) 3652 if(soc_feature(unit, soc_feature_td3_style_mpls)) { 3653 mem = EGR_SEQUENCE_NUMBER_TABLEm; 3654 } else 3655 #endif 3656 { 3657 mem = EGR_PW_INIT_COUNTERSm; 3658 } 3659 if (SOC_MEM_IS_VALID(unit, mem)) { 3660 num_pw_init = soc_mem_index_count(unit, mem); 3661 } 3662 3663 /* 3664 * allocate resources 3665 */ 3666 if (mpls_info->initialized) { 3667 /* coverity[stack_use_overflow : FALSE] */ 3668 rv = bcm_tr_mpls_cleanup(unit); 3669 BCM_IF_ERROR_RETURN(rv); 3670 } 3671 3672 mpls_info->vrf_bitmap = 3673 sal_alloc(SHR_BITALLOCSIZE(num_vrf), "vrf_bitmap"); 3674 if (mpls_info->vrf_bitmap == NULL) { 3675 _bcm_tr_mpls_free_resource(unit, mpls_info); 3676 return BCM_E_MEMORY; 3677 } 3678 3679 if (num_vpws) { 3680 mpls_info->vpws_bitmap = 3681 sal_alloc(SHR_BITALLOCSIZE(num_vpws), "vpws_bitmap"); 3682 if (mpls_info->vpws_bitmap == NULL) { 3683 _bcm_tr_mpls_free_resource(unit, mpls_info); 3684 return BCM_E_MEMORY; 3685 } 3686 3687 mpls_info->vpws_vp_map = 3688 sal_alloc(sizeof(_bcm_mpls_vpws_vp_map_info_t) * (num_vpws), "vpws_vp_map"); 3689 if (mpls_info->vpws_vp_map == NULL) { 3690 _bcm_tr_mpls_free_resource(unit, mpls_info); 3691 return BCM_E_MEMORY; 3692 } 3693 } else { 3694 mpls_info->vpws_bitmap = NULL; 3695 mpls_info->vpws_vp_map = NULL; 3696 } 3697 3698 if (num_trunk) { 3699 mpls_info->trunk_vp_map = 3700 sal_alloc(sizeof(int) * (num_trunk), "trunk_vp_map"); 3701 if (mpls_info->trunk_vp_map == NULL) { 3702 _bcm_tr_mpls_free_resource(unit, mpls_info); 3703 return BCM_E_MEMORY; 3704 } 3705 } else { 3706 mpls_info->trunk_vp_map = NULL; 3707 } 3708 3709 if (num_vp) { 3710 mpls_info->match_key = 3711 sal_alloc(sizeof(_bcm_tr_mpls_match_port_info_t) * num_vp, "match_key"); 3712 if (mpls_info->match_key == NULL) { 3713 _bcm_tr_mpls_free_resource(unit, mpls_info); 3714 return BCM_E_MEMORY; 3715 } 3716 } else { 3717 mpls_info->match_key = NULL; 3718 } 3719 3720 3721 if (num_vc) { 3722 mpls_info->vc_c_bitmap = 3723 sal_alloc(SHR_BITALLOCSIZE(num_vc), "vc_c_bitmap"); 3724 if (mpls_info->vc_c_bitmap == NULL) { 3725 _bcm_tr_mpls_free_resource(unit, mpls_info); 3726 return BCM_E_MEMORY; 3727 } 3728 3729 mpls_info->vc_nc_bitmap = 3730 sal_alloc(SHR_BITALLOCSIZE(num_vc), "vc_nc_bitmap"); 3731 if (mpls_info->vc_nc_bitmap == NULL) { 3732 _bcm_tr_mpls_free_resource(unit, mpls_info); 3733 return BCM_E_MEMORY; 3734 } 3735 } else { 3736 mpls_info->vc_c_bitmap = NULL; 3737 mpls_info->vc_nc_bitmap = NULL; 3738 } 3739 3740 if (num_pw_term) { 3741 mpls_info->pw_term_bitmap = 3742 sal_alloc(SHR_BITALLOCSIZE(num_pw_term), "pw_term_bitmap"); 3743 if (mpls_info->pw_term_bitmap == NULL) { 3744 _bcm_tr_mpls_free_resource(unit, mpls_info); 3745 return BCM_E_MEMORY; 3746 } 3747 } 3748 3749 if(num_pw_init) { 3750 mpls_info->pw_init_bitmap = 3751 sal_alloc(SHR_BITALLOCSIZE(num_pw_init), "pw_init_bitmap"); 3752 if (mpls_info->pw_init_bitmap == NULL) { 3753 _bcm_tr_mpls_free_resource(unit, mpls_info); 3754 return BCM_E_MEMORY; 3755 } 3756 } 3757 3758 mpls_info->egr_mpls_bitmap = 3759 sal_alloc(SHR_BITALLOCSIZE(num_mpls_map), "egr_mpls_bitmap"); 3760 if (mpls_info->egr_mpls_bitmap == NULL) { 3761 _bcm_tr_mpls_free_resource(unit, mpls_info); 3762 return BCM_E_MEMORY; 3763 } 3764 mpls_info->egr_mpls_hw_idx = 3765 sal_alloc(sizeof(uint32) * num_mpls_map, "egr_mpls_hw_idx"); 3766 if (mpls_info->egr_mpls_hw_idx == NULL) { 3767 _bcm_tr_mpls_free_resource(unit, mpls_info); 3768 return BCM_E_MEMORY; 3769 } 3770 3771 mpls_info->ing_exp_map_bitmap = 3772 sal_alloc(SHR_BITALLOCSIZE(num_ing_exp_map), "ing_exp_map_bitmap"); 3773 if (mpls_info->ing_exp_map_bitmap == NULL) { 3774 _bcm_tr_mpls_free_resource(unit, mpls_info); 3775 return BCM_E_MEMORY; 3776 } 3777 3778 mpls_info->egr_l2_exp_map_bitmap = 3779 sal_alloc(SHR_BITALLOCSIZE(num_egr_l2_exp_map), "egr_l2_exp_map_bitmap"); 3780 if (mpls_info->egr_l2_exp_map_bitmap == NULL) { 3781 _bcm_tr_mpls_free_resource(unit, mpls_info); 3782 return BCM_E_MEMORY; 3783 } 3784 #ifdef BCM_APACHE_SUPPORT 3785 if (soc_feature(unit, soc_feature_mpls_exp_to_phb_cng_map)) { 3786 mpls_info->ing_exp_to_phb_cng_map_bitmap = 3787 sal_alloc(SHR_BITALLOCSIZE(num_ing_mpls_exp_to_phb_cng_map), 3788 "ing_exp_to_phb_cng_map_bitmap"); 3789 if (mpls_info->ing_exp_to_phb_cng_map_bitmap == NULL) { 3790 _bcm_tr_mpls_free_resource(unit, mpls_info); 3791 return BCM_E_MEMORY; 3792 } 3793 3794 mpls_info->egr_exp_to_phb_cng_map_bitmap = 3795 sal_alloc(SHR_BITALLOCSIZE(num_egr_mpls_exp_to_phb_cng_map), 3796 "egr_exp_to_phb_cng_map_bitmap"); 3797 if (mpls_info->egr_exp_to_phb_cng_map_bitmap == NULL) { 3798 _bcm_tr_mpls_free_resource(unit, mpls_info); 3799 return BCM_E_MEMORY; 3800 } 3801 } 3802 #endif 3803 /* 4 MPLS entries for each EGR_IP_TUNNEL_MPLS entry */ 3804 mpls_info->tnl_bitmap = 3805 sal_alloc(SHR_BITALLOCSIZE(num_ip_tnl * 3806 _BCM_MPLS_NUM_MPLS_ENTRIES_PER_INDEX(unit)), 3807 "tnl_bitmap"); 3808 if (mpls_info->tnl_bitmap == NULL) { 3809 _bcm_tr_mpls_free_resource(unit, mpls_info); 3810 return BCM_E_MEMORY; 3811 } 3812 3813 mpls_info->ip_tnl_bitmap = 3814 sal_alloc(SHR_BITALLOCSIZE(num_ip_tnl), "ip_tnl_bitmap"); 3815 if (mpls_info->ip_tnl_bitmap == NULL) { 3816 _bcm_tr_mpls_free_resource(unit, mpls_info); 3817 return BCM_E_MEMORY; 3818 } 3819 3820 if (!soc_feature(unit, soc_feature_th3_style_simple_mpls) 3821 && (NULL == mpls_info->vc_swap_ref_count)) { 3822 mpls_info->vc_swap_ref_count = sal_alloc(sizeof(uint16) * 3823 num_vc, "vc_swap_refcount"); 3824 if (mpls_info->vc_swap_ref_count == NULL) { 3825 _bcm_tr_mpls_free_resource(unit, mpls_info); 3826 return BCM_E_MEMORY; 3827 } 3828 sal_memset(mpls_info->vc_swap_ref_count, 0, 3829 sizeof(uint16) * num_vc); 3830 } 3831 3832 if (NULL == mpls_info->egr_tunnel_ref_count) { 3833 mpls_info->egr_tunnel_ref_count = sal_alloc(sizeof(uint16) * 3834 (num_ip_tnl * _BCM_MPLS_NUM_MPLS_ENTRIES_PER_INDEX(unit)), 3835 "egr_tunnel_ref_count"); 3836 if (mpls_info->egr_tunnel_ref_count == NULL) { 3837 _bcm_tr_mpls_free_resource(unit, mpls_info); 3838 return BCM_E_MEMORY; 3839 } 3840 sal_memset(mpls_info->egr_tunnel_ref_count, 0, 3841 sizeof(uint16) * (num_ip_tnl * 3842 _BCM_MPLS_NUM_MPLS_ENTRIES_PER_INDEX(unit))); 3843 } 3844 3845 if (SOC_MEM_IS_VALID(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm)) { 3846 if (NULL == bcmi_vc_swap_label_hash[unit]) { 3847 bcmi_vc_swap_label_hash[unit] = sal_alloc( 3848 BCM_TR_MPLS_VC_SWAP_HASH_BUCKETS * 3849 sizeof (bcm_tr_mpls_vc_swap_table_hash_t), "vc_swap_hash"); 3850 3851 if (bcmi_vc_swap_label_hash[unit] == NULL) { 3852 _bcm_tr_mpls_free_resource(unit, mpls_info); 3853 return SOC_E_MEMORY; 3854 } 3855 3856 for (i = 0; i < BCM_TR_MPLS_VC_SWAP_HASH_BUCKETS; i++) { 3857 vc_swap_hash = &(bcmi_vc_swap_label_hash[unit][i]); 3858 vc_swap_hash->head_link = NULL; 3859 } 3860 } 3861 3862 mpls_info->svp_profile_set_bitmap = 3863 sal_alloc(SHR_BITALLOCSIZE(num_vp), "svp_profile_set_bitmap"); 3864 if (mpls_info->svp_profile_set_bitmap == NULL) { 3865 _bcm_tr_mpls_free_resource(unit, mpls_info); 3866 return BCM_E_MEMORY; 3867 } 3868 3869 mpls_info->network_vp_bitmap = 3870 sal_alloc(SHR_BITALLOCSIZE(num_vp), "network_vp_bitmap"); 3871 if (mpls_info->network_vp_bitmap == NULL) { 3872 _bcm_tr_mpls_free_resource(unit, mpls_info); 3873 return BCM_E_MEMORY; 3874 } 3875 } 3876 3877 #ifdef BCM_KATANA_SUPPORT 3878 if (soc_feature(unit, soc_feature_extended_queueing)) { 3879 if (NULL == mpls_info->ing_qmap_ref_count) { 3880 mpls_info->ing_qmap_ref_count = sal_alloc(sizeof(uint16) * 3881 num_ing_qmap, "ing_qmap_ref_count"); 3882 if (mpls_info->ing_qmap_ref_count == NULL) { 3883 _bcm_tr_mpls_free_resource(unit, mpls_info); 3884 return BCM_E_MEMORY; 3885 } 3886 sal_memset(mpls_info->ing_qmap_ref_count, 0, 3887 sizeof(uint16) * num_ing_qmap); 3888 } 3889 } 3890 #endif /* BCM_KATANA_SUPPORT */ 3891 #ifdef BCM_TRIUMPH2_SUPPORT 3892 if (soc_feature(unit, soc_feature_mpls_failover)) { 3893 mpls_info->failover_vp = 3894 sal_alloc(num_vp * sizeof(uint32), "failover vp"); 3895 if (mpls_info->failover_vp == NULL) { 3896 _bcm_tr_mpls_free_resource(unit, mpls_info); 3897 return BCM_E_MEMORY; 3898 } 3899 } 3900 #endif /* BCM_TRIUMPH2_SUPPORT */ 3901 3902 3903 #if defined(BCM_TRIDENT3_SUPPORT) 3904 /*To store label actions of vc swap index*/ 3905 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 3906 mpls_info->egr_vc_swap_lbl_action = 3907 sal_alloc((num_vc * sizeof(int)), "egr_vc_swap_lbl_action"); 3908 if (mpls_info->egr_vc_swap_lbl_action == NULL) { 3909 _bcm_tr_mpls_free_resource(unit, mpls_info); 3910 return BCM_E_MEMORY; 3911 } 3912 } 3913 #endif 3914 3915 sal_memset(mpls_info->vrf_bitmap, 0, SHR_BITALLOCSIZE(num_vrf)); 3916 sal_memset(mpls_info->vpws_bitmap, 0, SHR_BITALLOCSIZE(num_vpws)); 3917 sal_memset(mpls_info->vc_c_bitmap, 0, SHR_BITALLOCSIZE(num_vc)); 3918 sal_memset(mpls_info->vc_nc_bitmap, 0, SHR_BITALLOCSIZE(num_vc)); 3919 if (num_pw_term) { 3920 sal_memset(mpls_info->pw_term_bitmap, 0, SHR_BITALLOCSIZE(num_pw_term)); 3921 } 3922 sal_memset(mpls_info->pw_init_bitmap, 0, SHR_BITALLOCSIZE(num_pw_init)); 3923 sal_memset(mpls_info->egr_mpls_bitmap, 0, SHR_BITALLOCSIZE(num_mpls_map)); 3924 sal_memset(mpls_info->egr_mpls_hw_idx, 0, (sizeof(uint32) * num_mpls_map)); 3925 sal_memset(mpls_info->ing_exp_map_bitmap, 0, SHR_BITALLOCSIZE(num_ing_exp_map)); 3926 sal_memset(mpls_info->egr_l2_exp_map_bitmap, 0, SHR_BITALLOCSIZE(num_egr_l2_exp_map)); 3927 #ifdef BCM_APACHE_SUPPORT 3928 if (soc_feature(unit, soc_feature_mpls_exp_to_phb_cng_map)) { 3929 sal_memset(mpls_info->ing_exp_to_phb_cng_map_bitmap, 0, 3930 SHR_BITALLOCSIZE(num_ing_mpls_exp_to_phb_cng_map)); 3931 sal_memset(mpls_info->egr_exp_to_phb_cng_map_bitmap, 0, 3932 SHR_BITALLOCSIZE(num_egr_mpls_exp_to_phb_cng_map)); 3933 } 3934 #endif 3935 sal_memset(mpls_info->match_key, 0, sizeof(_bcm_tr_mpls_match_port_info_t) * num_vp); 3936 sal_memset(mpls_info->tnl_bitmap, 0, 3937 SHR_BITALLOCSIZE(num_ip_tnl * 3938 _BCM_MPLS_NUM_MPLS_ENTRIES_PER_INDEX(unit))); 3939 sal_memset(mpls_info->ip_tnl_bitmap, 0, SHR_BITALLOCSIZE(num_ip_tnl)); 3940 sal_memset(mpls_info->svp_profile_set_bitmap, 0, SHR_BITALLOCSIZE(num_vp)); 3941 #if defined(BCM_TRIDENT3_SUPPORT) 3942 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 3943 sal_memset(mpls_info->egr_vc_swap_lbl_action, 0, 3944 (num_vc * sizeof(int))); 3945 } 3946 #endif 3947 #ifdef BCM_TRIUMPH2_SUPPORT 3948 if (soc_feature(unit, soc_feature_mpls_failover)) { 3949 sal_memset(mpls_info->failover_vp, 0, num_vp * sizeof(uint32)); 3950 } 3951 #endif /* BCM_TRIUMPH2_SUPPORT */ 3952 3953 if (!SOC_WARM_BOOT(unit)) { 3954 /* 3955 * Initialize the VFI table by setting L3MC_INDEX to 0 and 3956 * PFM to 3. The PFM==3 (invalid) indicates that the VFI entry is not used. 3957 * This can be used to recover SW state during warm reboot. 3958 */ 3959 3960 #ifdef BCM_TRIUMPH2_SUPPORT 3961 if (soc_feature(unit, soc_feature_mpls_enhanced) 3962 && SOC_MEM_IS_VALID(unit, VFIm)) { 3963 /* Initialize VFIm entries need to have: 3964 * { BC_INDEX == 0, UUC_INDEX == 0, UMC_INDEX == 0 } 3965 * Just same to clear it. 3966 */ 3967 rv = soc_mem_clear(unit, VFIm, MEM_BLOCK_ANY, TRUE); 3968 if (rv < 0) { 3969 _bcm_tr_mpls_free_resource(unit, mpls_info); 3970 return rv; 3971 } 3972 } else 3973 #endif /* BCM_TRIUMPH2_SUPPORT */ 3974 { 3975 if (soc_mem_field_valid(unit, VFIm, PFMf)) { 3976 sal_memset(&vfi_entry, 0, sizeof(vfi_entry_t)); 3977 3978 soc_VFIm_field32_set(unit, &vfi_entry, L3MC_INDEXf, 0); 3979 soc_VFIm_field32_set(unit, &vfi_entry, PFMf, 3); 3980 for (i = 0; i < num_vfi; i++) { 3981 rv = WRITE_VFIm(unit, MEM_BLOCK_ALL, i, &vfi_entry); 3982 if (rv < 0) { 3983 _bcm_tr_mpls_free_resource(unit, mpls_info); 3984 return rv; 3985 } 3986 } 3987 } 3988 } 3989 3990 /* 3991 * Initialize L3_IIF entries starting from 3992 * _BCM_TR_MPLS_L3_IIF_BASE for each valid IIF value. 3993 */ 3994 #if defined(BCM_TRIDENT2_SUPPORT) 3995 if (soc_feature(unit, soc_feature_l3_iif_profile) && 3996 !soc_feature(unit, soc_feature_l3_iif_under_4k)) { 3997 rv = _bcm_tr_l3_ingress_interface_dma_init(unit, 3998 _BCM_TR_MPLS_L3_IIF_BASE+1, 3999 soc_mem_index_max(unit, L3_IIFm)); 4000 4001 if (BCM_FAILURE(rv)) { 4002 _bcm_tr_mpls_free_resource(unit, mpls_info); 4003 return rv; 4004 } 4005 } else 4006 #endif /* BCM_TRIDENT2_SUPPORT */ 4007 { 4008 sal_memset(&iif, 0, sizeof(_bcm_l3_ingress_intf_t)); 4009 for (i = _BCM_TR_MPLS_L3_IIF_BASE+1; i < num_iif; i++) { 4010 iif.intf_id = i; 4011 iif.vrf = 0; 4012 4013 rv = _bcm_tr_l3_ingress_interface_set(unit, &iif, 4014 NULL, NULL); 4015 if (BCM_FAILURE(rv)) { 4016 _bcm_tr_mpls_free_resource(unit, mpls_info); 4017 return rv; 4018 } 4019 } 4020 } 4021 4022 /* 4023 * Reserve one mapping instance in ING_PRI_CNG_MAP for 4024 * identity mapping of packet pri/cfi to internal pri/color. 4025 */ 4026 sal_memset(pri_map, 0, (SOC_MAX_MEM_FIELD_WORDS) * 4); 4027 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 4028 mem = PHB_MAPPING_TBL_1m; 4029 pri_field = INT_PRIf; 4030 } else { 4031 mem = ING_PRI_CNG_MAPm; 4032 pri_field = PRIf; 4033 } 4034 4035 for (pkt_cfi = 0; pkt_cfi <= 1; pkt_cfi++) { 4036 for (pkt_pri = 0; pkt_pri <= 7; pkt_pri++) { 4037 /* ING_PRI_CNG_MAP table is indexed with 4038 * port[0:4] incoming priority[2:0] incoming CFI[0] 4039 */ 4040 i = (_BCM_TR_MPLS_PRI_CNG_MAP_IDENTITY << 4) | (pkt_pri << 1) | pkt_cfi; 4041 soc_mem_field32_set(unit, mem, pri_map, pri_field, 4042 pkt_pri); 4043 soc_mem_field32_set(unit, mem, pri_map, CNGf, 4044 pkt_cfi); 4045 rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, i, pri_map); 4046 if (rv < 0) { 4047 _bcm_tr_mpls_free_resource(unit, mpls_info); 4048 return rv; 4049 } 4050 } 4051 } 4052 4053 /* Clear L2 PW Counters */ 4054 rv = _bcm_tr_mpls_stat_clear(unit); 4055 if (rv < 0) { 4056 return rv; 4057 } 4058 4059 /* Initialize the entire label space "Port Independent" 4060 * Use Switch Controls to re-configure the Label Space 4061 * for Port-Dependant and Port-Independant 4062 */ 4063 4064 label = 0; 4065 rv = soc_reg_field32_modify(unit, GLOBAL_MPLS_RANGE_1_LOWERr, 4066 REG_PORT_ANY, LABELf, label); 4067 if (rv < 0) { 4068 _bcm_tr_mpls_free_resource(unit, mpls_info); 4069 return rv; 4070 } 4071 rv = soc_reg_field32_modify(unit, GLOBAL_MPLS_RANGE_2_LOWERr, 4072 REG_PORT_ANY, LABELf, label); 4073 if (rv < 0) { 4074 _bcm_tr_mpls_free_resource(unit, mpls_info); 4075 return rv; 4076 } 4077 4078 label = (1 << 20) - 1; 4079 rv = soc_reg_field32_modify(unit, GLOBAL_MPLS_RANGE_1_UPPERr, 4080 REG_PORT_ANY, LABELf, label); 4081 if (rv < 0) { 4082 _bcm_tr_mpls_free_resource(unit, mpls_info); 4083 return rv; 4084 } 4085 rv = soc_reg_field32_modify(unit, GLOBAL_MPLS_RANGE_2_UPPERr, 4086 REG_PORT_ANY, LABELf, label); 4087 if (rv < 0) { 4088 _bcm_tr_mpls_free_resource(unit, mpls_info); 4089 return rv; 4090 } 4091 4092 /* Enable MPLS */ 4093 rv = bcm_tr_mpls_enable(unit, TRUE); 4094 if (rv < 0) { 4095 _bcm_tr_mpls_free_resource(unit, mpls_info); 4096 return rv; 4097 } 4098 #ifdef BCM_APACHE_SUPPORT 4099 if (soc_feature(unit, soc_feature_mpls_exp_to_phb_cng_map)) { 4100 rv = bcm_apache_mpls_effective_phb_select_init(unit); 4101 if (rv < 0) { 4102 _bcm_tr_mpls_free_resource(unit, mpls_info); 4103 return rv; 4104 } 4105 } 4106 #endif 4107 } /* !WARM_BOOT */ 4108 4109 /* Init Software State */ 4110 for (i=0; i < num_vp; i++) { 4111 mpls_info->match_key[i].modid = -1; 4112 mpls_info->match_key[i].trunk_id = -1; 4113 mpls_info->match_key[i].fo_modid = -1; 4114 mpls_info->match_key[i].fo_trunk_id = -1; 4115 mpls_info->match_key[i].match_count = 0; 4116 mpls_info->match_key[i].index = 0; 4117 } 4118 4119 for (i=0; i < num_vpws; i++) { 4120 mpls_info->vpws_vp_map[i].vp1 = -1; 4121 mpls_info->vpws_vp_map[i].vp2 = -1; 4122 mpls_info->vpws_vp_map[i].vp3 = -1; 4123 #ifdef BCM_MULTI_LEVEL_FAILOVER_SUPPORT 4124 if ((soc_feature(unit, soc_feature_hierarchical_protection))) { 4125 mpls_info->vpws_vp_map[i].vp_b_1 = -1; 4126 mpls_info->vpws_vp_map[i].vp_b_2 = -1; 4127 mpls_info->vpws_vp_map[i].vp_b_3 = -1; 4128 } 4129 #endif 4130 } 4131 for (i = 0; i < num_trunk; i++) { 4132 mpls_info->trunk_vp_map[i] = -1; 4133 } 4134 if (SOC_MEM_IS_VALID(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm)) { 4135 /* Reserve Default-VC_AND_SWAP_LABEL_TABLE entry */ 4136 rv = _bcm_tr_mpls_default_entry_setup(unit); 4137 if (rv < 0) { 4138 _bcm_tr_mpls_free_resource(unit, mpls_info); 4139 return rv; 4140 } 4141 } 4142 4143 /* Create MPLS protection mutex. */ 4144 MPLS_INFO((unit))->mpls_mutex = sal_mutex_create("mpls_mutex"); 4145 if (!MPLS_INFO((unit))->mpls_mutex) { 4146 _bcm_tr_mpls_free_resource(unit, mpls_info); 4147 return rv; 4148 } 4149 4150 for(i=0; i < _BCM_TR_MPLS_HASH_ELEMENTS; ++i) { 4151 _bcm_tr_mpls_nhop_headPtr[unit][i] = NULL; 4152 } 4153 4154 #if defined(BCM_APACHE_SUPPORT) || defined(BCM_TOMAHAWK2_SUPPORT) \ 4155 || defined(BCM_TRIDENT3_SUPPORT) || defined(BCM_TOMAHAWK3_SUPPORT) 4156 if (soc_feature(unit, soc_feature_egr_ip_tnl_mpls_double_wide) || 4157 (soc_feature(unit, soc_feature_th3_style_simple_mpls))) { 4158 rv = bcmi_egr_ip_tunnel_mpls_sw_init(unit); 4159 if (rv != BCM_E_NONE) { 4160 _bcm_tr_mpls_free_resource(unit, mpls_info); 4161 } 4162 } 4163 #endif 4164 4165 #if defined(BCM_SPECIAL_LABEL_SUPPORT) 4166 if (soc_feature(unit, soc_feature_mpls_special_label)) { 4167 rv = bcmi_mpls_special_label_init(unit); 4168 if (rv != BCM_E_NONE) { 4169 _bcm_tr_mpls_free_resource(unit, mpls_info); 4170 } 4171 } 4172 #endif 4173 4174 4175 #if defined(BCM_TRIDENT3_SUPPORT) 4176 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 4177 if (!SOC_WARM_BOOT(unit)) { 4178 rv = soc_reg_field32_modify(unit, RTAG7_HASH_CONTROLr, 4179 REG_PORT_ANY, USE_MPLS_STACK_FOR_HASHINGf, 0); 4180 4181 if (rv != BCM_E_NONE) { 4182 _bcm_tr_mpls_free_resource(unit, mpls_info); 4183 } 4184 } 4185 } 4186 #endif 4187 4188 #ifdef BCM_WARM_BOOT_SUPPORT 4189 rv = _bcm_tr_mpls_reinit(unit); 4190 if (rv != BCM_E_NONE) { 4191 _bcm_tr_mpls_free_resource(unit, mpls_info); 4192 } 4193 #endif /* BCM_WARM_BOOT_SUPPORT */ 4194 4195 /* Mark the state as initialized */ 4196 mpls_info->initialized = TRUE; 4197 4198 return rv; 4199 } 4200 4201 #ifdef BCM_APACHE_SUPPORT 4202 /* 4203 * Function: 4204 * bcm_tr_mpls_exp_to_phb_cng_map_destroy_all 4205 * Purpose: 4206 * Destroy all existing MPLS EXP to PBH and CNG map instances. 4207 * Parameters: 4208 * unit - (IN) SOC unit # 4209 * Returns: 4210 * BCM_E_XXX 4211 */ 4212 STATIC int 4213 bcm_tr_mpls_exp_to_phb_cng_map_destroy_all(int unit) 4214 { 4215 int i, num_exp_map; 4216 4217 /* ING_MPLS_EXP_MAPPING_1 profiles indexed by EXP */ 4218 num_exp_map = soc_mem_index_count(unit, ING_MPLS_EXP_MAPPING_1m) / 16; 4219 for (i = 0; i < num_exp_map; i++) { 4220 if (_BCM_MPLS_ING_EXP_TO_PHB_CNG_MAP_USED_GET(unit, i)) { 4221 _BCM_MPLS_ING_EXP_TO_PHB_CNG_MAP_USED_CLR(unit, i); 4222 } 4223 } 4224 4225 /* EGR_MPLS_EXP_MAPPING_3m profiles indexed by EXP */ 4226 num_exp_map = soc_mem_index_count(unit, EGR_MPLS_EXP_MAPPING_3m) / 8; 4227 for (i = 0; i < num_exp_map; i++) { 4228 if (_BCM_MPLS_EGR_EXP_TO_PHB_CNG_MAP_USED_GET(unit, i)) { 4229 _BCM_MPLS_EGR_EXP_TO_PHB_CNG_MAP_USED_CLR(unit, i); 4230 } 4231 } 4232 4233 return BCM_E_NONE; 4234 } 4235 #endif 4236 /* 4237 * Function: 4238 * _bcm_tr_mpls_hw_clear 4239 * Purpose: 4240 * Perform hw tables clean up for mpls module. 4241 * Parameters: 4242 * unit - Device Number 4243 * Returns: 4244 * BCM_E_XXX 4245 */ 4246 STATIC int 4247 _bcm_tr_mpls_hw_clear(int unit) 4248 { 4249 int rv=BCM_E_NONE, rv_error = BCM_E_NONE; 4250 4251 rv = bcm_tr_mpls_enable(unit, FALSE); 4252 if (BCM_FAILURE(rv)) { 4253 rv_error = rv; 4254 } 4255 4256 /* Clear L2 PW Counters */ 4257 rv = _bcm_tr_mpls_stat_clear(unit); 4258 if (rv<0) { 4259 rv_error = rv; 4260 } 4261 4262 if (!soc_feature(unit, soc_feature_th3_style_simple_mpls)) { 4263 /* Destroy all VPNs */ 4264 rv = bcm_tr_mpls_vpn_id_destroy_all(unit); 4265 if (BCM_FAILURE(rv) && (BCM_E_NONE == rv_error)) { 4266 rv_error = rv; 4267 } 4268 } 4269 4270 /* Delete all L2 tunnel entries */ 4271 rv = bcm_esw_l2_tunnel_delete_all(unit); 4272 if (BCM_FAILURE(rv) && (BCM_E_NONE == rv_error)) { 4273 rv_error = rv; 4274 } 4275 4276 /* Clear all MPLS tunnel initiators */ 4277 rv = bcm_esw_mpls_tunnel_initiator_clear_all(unit); 4278 if (BCM_FAILURE(rv) && (BCM_E_NONE == rv_error)) { 4279 rv_error = rv; 4280 } 4281 4282 /* Delete all MPLS switch entries */ 4283 rv = _bcm_esw_mpls_tunnel_switch_delete_all(unit); 4284 if (BCM_FAILURE(rv) && (BCM_E_NONE == rv_error)) { 4285 rv_error = rv; 4286 } 4287 4288 /* Destroy all EXP maps */ 4289 rv = bcm_tr_mpls_exp_map_destroy_all(unit); 4290 if (BCM_FAILURE(rv) && (BCM_E_NONE == rv_error)) { 4291 rv_error = rv; 4292 } 4293 4294 #ifdef BCM_APACHE_SUPPORT 4295 if (soc_feature(unit, soc_feature_mpls_exp_to_phb_cng_map)) { 4296 rv = bcm_tr_mpls_exp_to_phb_cng_map_destroy_all(unit); 4297 if (BCM_FAILURE(rv) && (BCM_E_NONE == rv_error)) { 4298 rv_error = rv; 4299 } 4300 } 4301 #endif 4302 return rv_error; 4303 } 4304 4305 /* 4306 * Function: 4307 * bcm_mpls_cleanup 4308 * Purpose: 4309 * Detach the MPLS software module 4310 * Parameters: 4311 * unit - Device Number 4312 * Returns: 4313 * BCM_E_XXX 4314 */ 4315 int 4316 bcm_tr_mpls_cleanup(int unit) 4317 { 4318 _bcm_tr_mpls_bookkeeping_t *mpls_info = MPLS_INFO(unit); 4319 int rv=BCM_E_NONE; 4320 4321 if (FALSE == mpls_info->initialized) { 4322 return (BCM_E_NONE); 4323 } 4324 4325 rv = bcm_tr_mpls_lock (unit); 4326 if (BCM_FAILURE(rv)) { 4327 return rv; 4328 } 4329 4330 if (0 == SOC_HW_ACCESS_DISABLE(unit)) { 4331 rv = _bcm_tr_mpls_hw_clear(unit); 4332 } 4333 4334 /* Free software resources */ 4335 (void) _bcm_tr_mpls_free_resource(unit, mpls_info); 4336 4337 bcm_tr_mpls_unlock (unit); 4338 4339 /* Destroy MPLS protection mutex. */ 4340 sal_mutex_destroy(MPLS_INFO((unit))->mpls_mutex ); 4341 4342 /* Mark the state as uninitialized */ 4343 mpls_info->initialized = FALSE; 4344 4345 return rv; 4346 } 4347 4348 /* 4349 * Function: 4350 * _bcm_tr_vpws_vpn_alloc 4351 * Purpose: 4352 * Internal function for allocating a VPWS Vpn_id 4353 * Parameters: 4354 * unit - (IN) Device number. 4355 * vpn_id - (OUT) VPWS Vpn_id 4356 * Returns: 4357 * BCM_X_XXX 4358 */ 4359 4360 int 4361 _bcm_tr_vpws_vpn_alloc(int unit, bcm_vpn_t *vpn_id) 4362 { 4363 int i, num_vpws; 4364 4365 num_vpws = soc_mem_index_count(unit, SOURCE_VPm) / 2; 4366 4367 for (i = 0; i < num_vpws; i++) { 4368 if (!_BCM_MPLS_VPWS_USED_GET(unit, i)) { 4369 break; 4370 } 4371 } 4372 if (i == num_vpws) { 4373 return BCM_E_RESOURCE; 4374 } 4375 4376 *vpn_id = i; 4377 _BCM_MPLS_VPWS_USED_SET(unit, *vpn_id); 4378 4379 return BCM_E_NONE; 4380 } 4381 4382 4383 /* 4384 * Function: 4385 * bcm_mpls_vpn_id_create 4386 * Purpose: 4387 * Create a VPN instance 4388 * Parameters: 4389 * unit - (IN) Device Number 4390 * info - (IN/OUT) VPN configuration info 4391 * Returns: 4392 * BCM_E_XXX 4393 * Note: 4394 * No hardware action 4395 */ 4396 int 4397 bcm_tr_mpls_vpn_id_create(int unit, bcm_mpls_vpn_config_t *info) 4398 { 4399 int rv = BCM_E_PARAM; 4400 bcm_vpn_t vpn_id; 4401 int proto_pkt_inx; 4402 int num_vpws; 4403 #if defined(BCM_TRIDENT3_SUPPORT) 4404 uint32 vfi_profile_idx=0; 4405 #endif 4406 4407 if (info->flags & BCM_MPLS_VPN_REPLACE) { 4408 if (!(info->flags & BCM_MPLS_VPN_WITH_ID)) { 4409 return BCM_E_PARAM; 4410 } 4411 } 4412 4413 if (info->flags & BCM_MPLS_VPN_VPWS) { 4414 if (info->flags & BCM_MPLS_VPN_WITH_ID) { 4415 if (!_BCM_MPLS_VPN_IS_VPWS(info->vpn)) { 4416 return BCM_E_PARAM; 4417 } 4418 _BCM_MPLS_VPN_GET(vpn_id, _BCM_MPLS_VPN_TYPE_VPWS, info->vpn); 4419 num_vpws = soc_mem_index_count(unit, SOURCE_VPm) / 2; 4420 if (vpn_id >= num_vpws) { 4421 return BCM_E_PARAM; 4422 } else if (_BCM_MPLS_VPWS_USED_GET(unit, vpn_id)) { 4423 /* Already used */ 4424 return BCM_E_EXISTS; 4425 } 4426 _BCM_MPLS_VPWS_USED_SET(unit, vpn_id); 4427 rv = BCM_E_NONE; 4428 } else { 4429 /* Get vpn_id */ 4430 rv = _bcm_tr_vpws_vpn_alloc(unit, &vpn_id); 4431 if (BCM_SUCCESS(rv)) { 4432 _BCM_MPLS_VPN_SET(info->vpn, _BCM_MPLS_VPN_TYPE_VPWS, vpn_id); 4433 } 4434 } 4435 } else if (info->flags & BCM_MPLS_VPN_VPLS) { 4436 vfi_entry_t vfi_entry; 4437 int vfi_index, mc_group=0, mc_group_type, num_vfi; 4438 bcm_vpn_t vpls_vpn_min=0; 4439 4440 bcm_vlan_mcast_flood_t mode; 4441 #if defined(BCM_TRIUMPH2_SUPPORT) 4442 int bc_group=0, umc_group=0, uuc_group=0; 4443 int bc_group_type, umc_group_type, uuc_group_type; 4444 #endif /* BCM_TRIUMPH2_SUPPORT */ 4445 4446 num_vfi = soc_mem_index_count(unit, VFIm); 4447 #ifdef BCM_TRIUMPH2_SUPPORT 4448 if (soc_feature(unit, soc_feature_mpls_enhanced)) { 4449 /* Check that the groups are valid. */ 4450 bc_group_type = _BCM_MULTICAST_TYPE_GET(info->broadcast_group); 4451 bc_group = _BCM_MULTICAST_ID_GET(info->broadcast_group); 4452 umc_group_type = _BCM_MULTICAST_TYPE_GET(info->unknown_multicast_group); 4453 umc_group = _BCM_MULTICAST_ID_GET(info->unknown_multicast_group); 4454 uuc_group_type = _BCM_MULTICAST_TYPE_GET(info->unknown_unicast_group); 4455 uuc_group = _BCM_MULTICAST_ID_GET(info->unknown_unicast_group); 4456 4457 if ((bc_group_type != _BCM_MULTICAST_TYPE_VPLS) || 4458 (umc_group_type != _BCM_MULTICAST_TYPE_VPLS) || 4459 (uuc_group_type != _BCM_MULTICAST_TYPE_VPLS) || 4460 (bc_group >= soc_mem_index_count(unit, L3_IPMCm)) || 4461 (umc_group >= soc_mem_index_count(unit, L3_IPMCm)) || 4462 (uuc_group >= soc_mem_index_count(unit, L3_IPMCm))) { 4463 return BCM_E_PARAM; 4464 } 4465 } else 4466 #endif 4467 { 4468 /* Check that the broadcast group is valid. Also check that 4469 * broadcast, unknown_unicast, and unknown_multicast groups 4470 * are the same (this device only supports on multicast group 4471 * for all 3 types of multicast traffic. 4472 */ 4473 4474 mc_group_type = _BCM_MULTICAST_TYPE_GET(info->broadcast_group); 4475 mc_group = _BCM_MULTICAST_ID_GET(info->broadcast_group); 4476 4477 if ((mc_group_type != _BCM_MULTICAST_TYPE_VPLS) || 4478 (mc_group >= soc_mem_index_count(unit, L3_IPMCm)) || 4479 (info->broadcast_group != info->unknown_unicast_group) || 4480 (info->broadcast_group != info->unknown_multicast_group)) { 4481 return BCM_E_PARAM; 4482 } 4483 } 4484 4485 /* validate parameter protocol_pkt */ 4486 if (SOC_MEM_FIELD_VALID(unit, VFIm, PROTOCOL_PKT_INDEXf)) { 4487 rv = _bcm_xgs3_protocol_packet_actions_validate(unit, 4488 &info->protocol_pkt); 4489 if (BCM_FAILURE(rv) && (rv != BCM_E_UNAVAIL)) { 4490 return rv; 4491 } 4492 } 4493 4494 /* Allocate a VFI */ 4495 /* Lock the VFI table while allocating and writing to allow 4496 * proper operation with the service counters */ 4497 soc_mem_lock(unit, VFIm); 4498 if (info->flags & BCM_MPLS_VPN_WITH_ID) { 4499 _BCM_MPLS_VPN_SET(vpls_vpn_min, _BCM_MPLS_VPN_TYPE_VPLS, 0); 4500 if ( info->vpn < vpls_vpn_min || info->vpn > (vpls_vpn_min+num_vfi-1) ) { 4501 soc_mem_unlock(unit, VFIm); 4502 return BCM_E_PARAM; 4503 } 4504 4505 _BCM_MPLS_VPN_GET(vfi_index, _BCM_MPLS_VPN_TYPE_VPLS, info->vpn); 4506 4507 if (_bcm_vfi_used_get(unit, vfi_index, _bcmVfiTypeMpls)) { 4508 if (!(info->flags & BCM_MPLS_VPN_REPLACE)) { 4509 soc_mem_unlock(unit, VFIm); 4510 return BCM_E_EXISTS; 4511 } 4512 } else { 4513 rv = _bcm_vfi_alloc_with_id(unit, VFIm, _bcmVfiTypeMpls, vfi_index); 4514 if (rv < 0) { 4515 soc_mem_unlock(unit, VFIm); 4516 return rv; 4517 } 4518 } 4519 } else { 4520 rv = _bcm_vfi_alloc(unit, VFIm, _bcmVfiTypeMpls, &vfi_index); 4521 if (rv < 0) { 4522 soc_mem_unlock(unit, VFIm); 4523 return rv; 4524 } 4525 4526 } 4527 4528 /* Get the default flood mode */ 4529 BCM_IF_ERROR_RETURN(_bcm_esw_vlan_flood_default_get(unit, &mode)); 4530 switch (mode) { 4531 case BCM_VLAN_MCAST_FLOOD_ALL: 4532 mode = 0; 4533 break; 4534 case BCM_VLAN_MCAST_FLOOD_NONE: 4535 mode = 2; 4536 break; 4537 default: 4538 mode = 1; 4539 break; 4540 } 4541 4542 /* Commit the entry to HW */ 4543 BCM_IF_ERROR_RETURN(READ_VFIm(unit, MEM_BLOCK_ALL, vfi_index, &vfi_entry)); 4544 if (info->flags & BCM_MPLS_VPN_REPLACE) { 4545 rv = READ_VFIm(unit, MEM_BLOCK_ALL, vfi_index, &vfi_entry); 4546 if (BCM_FAILURE(rv)) { 4547 soc_mem_unlock(unit, VFIm); 4548 return rv; 4549 } 4550 } 4551 #ifdef BCM_TRIUMPH2_SUPPORT 4552 if (soc_feature(unit, soc_feature_mpls_enhanced)) { 4553 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 4554 soc_mem_field32_dest_set(unit, VFIm, &vfi_entry, 4555 UMC_DESTINATIONf, SOC_MEM_FIF_DEST_IPMC, umc_group); 4556 soc_mem_field32_dest_set(unit, VFIm, &vfi_entry, 4557 UUC_DESTINATIONf, SOC_MEM_FIF_DEST_IPMC, uuc_group); 4558 soc_mem_field32_dest_set(unit, VFIm, &vfi_entry, 4559 BC_DESTINATIONf, SOC_MEM_FIF_DEST_IPMC, bc_group); 4560 4561 #if defined(BCM_TRIDENT3_SUPPORT) 4562 /*VFI_PROFILE setting as per CMH rules*/ 4563 bcmi_cmh_vfi_profile_set(unit, &vfi_profile_idx); 4564 if(vfi_profile_idx != 0) { 4565 soc_VFIm_field32_set(unit, &vfi_entry, 4566 VFI_PROFILE_PTRf, vfi_profile_idx); 4567 } 4568 #endif 4569 } else { 4570 soc_VFIm_field32_set(unit, &vfi_entry, UMC_INDEXf, umc_group); 4571 soc_VFIm_field32_set(unit, &vfi_entry, UUC_INDEXf, uuc_group); 4572 soc_VFIm_field32_set(unit, &vfi_entry, BC_INDEXf, bc_group); 4573 } 4574 } else 4575 #endif 4576 { 4577 soc_VFIm_field32_set(unit, &vfi_entry, L3MC_INDEXf, mc_group); 4578 soc_VFIm_field32_set(unit, &vfi_entry, PFMf, mode); 4579 } 4580 4581 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) || \ 4582 defined(BCM_APACHE_SUPPORT) 4583 if (SOC_IS_KATANAX(unit) || SOC_IS_TRIUMPH3(unit) || SOC_IS_APACHE(unit)) { 4584 rv = _bcm_esw_add_policer_to_table(unit, info->policer_id, VFIm, 4585 0, &vfi_entry); 4586 if (rv < 0) { 4587 soc_mem_unlock(unit, VFIm); 4588 return rv; 4589 } 4590 } 4591 #endif /* BCM_KATANA_SUPPORT or BCM_TRIUMPH3_SUPPORT or BCM_APACHE_SUPPORT */ 4592 4593 if (SOC_MEM_FIELD_VALID (unit,VFIm, PROTOCOL_PKT_INDEXf)) { 4594 if (info->flags & BCM_MPLS_VPN_REPLACE) { 4595 proto_pkt_inx = soc_VFIm_field32_get(unit, &vfi_entry, 4596 PROTOCOL_PKT_INDEXf); 4597 } else { 4598 proto_pkt_inx = -1; 4599 } 4600 rv = _bcm_xgs3_protocol_pkt_ctrl_set(unit,proto_pkt_inx, 4601 &info->protocol_pkt, 4602 &proto_pkt_inx); 4603 if (BCM_SUCCESS(rv)) { 4604 soc_VFIm_field32_set(unit, &vfi_entry, PROTOCOL_PKT_INDEXf, 4605 proto_pkt_inx); 4606 } else if (rv != BCM_E_UNAVAIL) { 4607 soc_mem_unlock(unit, VFIm); 4608 return rv; 4609 } 4610 } 4611 rv = WRITE_VFIm(unit, MEM_BLOCK_ALL, vfi_index, &vfi_entry); 4612 if (rv < 0) { 4613 (void) _bcm_vfi_free(unit, _bcmVfiTypeMpls, vfi_index); 4614 soc_mem_unlock(unit, VFIm); 4615 return rv; 4616 } 4617 soc_mem_unlock(unit, VFIm); 4618 4619 /* Set the returned VPN id */ 4620 _BCM_MPLS_VPN_SET(info->vpn, _BCM_MPLS_VPN_TYPE_VPLS, vfi_index); 4621 4622 } else if (info->flags & BCM_MPLS_VPN_L3) { 4623 int vrf; 4624 uint16 vrf_vpn_min; 4625 4626 /* 4627 * The caller manages VRF space. An MPLS L3 VPN identifier 4628 * is simply the VRF value passed in by the caller (info->lookup_id) 4629 * added to a base offset. The VPN ID returned here can 4630 * be used in the bcm_mpls_tunnel_switch_* APIs. 4631 */ 4632 if (info->flags & BCM_MPLS_VPN_WITH_ID) { 4633 _BCM_MPLS_VPN_SET(vrf_vpn_min, _BCM_MPLS_VPN_TYPE_L3, 0); 4634 4635 if ( info->vpn < vrf_vpn_min || info->vpn > (vrf_vpn_min +SOC_VRF_MAX(unit)) ) { 4636 return BCM_E_PARAM; 4637 } 4638 4639 _BCM_MPLS_VPN_GET(vrf, _BCM_MPLS_VPN_TYPE_L3, info->vpn); 4640 } else { 4641 vrf = info->lookup_id; 4642 } 4643 4644 if ((vrf < 0) || (vrf > SOC_VRF_MAX(unit))) { 4645 return BCM_E_PARAM; 4646 } 4647 if (_BCM_MPLS_VRF_USED_GET(unit, vrf)) { 4648 if (info->flags & BCM_MPLS_VPN_REPLACE) { 4649 return BCM_E_CONFIG; 4650 } 4651 return BCM_E_EXISTS; 4652 } 4653 _BCM_MPLS_VRF_USED_SET(unit, vrf); 4654 _BCM_MPLS_VPN_SET(info->vpn, _BCM_MPLS_VPN_TYPE_L3, vrf); 4655 rv = BCM_E_NONE; 4656 } 4657 4658 #ifdef BCM_WARM_BOOT_SUPPORT 4659 SOC_CONTROL_LOCK(unit); 4660 SOC_CONTROL(unit)->scache_dirty = 1; 4661 SOC_CONTROL_UNLOCK(unit); 4662 #endif 4663 4664 return rv; 4665 } 4666 4667 /* 4668 * Function: 4669 * bcm_tr_mpls_vpn_id_get 4670 * Purpose: 4671 * Get VPN instance 4672 * Parameters: 4673 * unit - (IN) Device Number 4674 * vpn - (IN) VPN instance ID 4675 * info - (OUT) VPN configuration info 4676 * Returns: 4677 * BCM_E_XXX 4678 * Note: 4679 * No hardware action 4680 */ 4681 4682 int 4683 bcm_tr_mpls_vpn_id_get(int unit, 4684 bcm_vpn_t vpn, 4685 bcm_mpls_vpn_config_t *info) 4686 { 4687 int proto_pkt_inx; 4688 int rv; 4689 4690 if (soc_feature(unit, soc_feature_th3_style_simple_mpls)) { 4691 if ((_BCM_MPLS_VPN_IS_VPWS(vpn)) || (_BCM_MPLS_VPN_IS_VPLS(vpn))) { 4692 return BCM_E_PARAM; 4693 } 4694 } 4695 4696 if (_BCM_MPLS_VPN_IS_VPWS(vpn)) { 4697 bcm_vpn_t vpws_vpn_id; 4698 int num_vpws; 4699 4700 num_vpws = soc_mem_index_count(unit, SOURCE_VPm) / 2; 4701 4702 /* 4703 * validate the vpn id, must be in the range 0 to 4704 * (number of SOURCE_VP entries / 2) 4705 */ 4706 _BCM_MPLS_VPN_GET(vpws_vpn_id, _BCM_MPLS_VPN_TYPE_VPWS, vpn); 4707 4708 if (vpws_vpn_id >= num_vpws) { 4709 return BCM_E_PARAM; 4710 } 4711 4712 if (!_BCM_MPLS_VPWS_USED_GET(unit, vpws_vpn_id)) { 4713 return BCM_E_NOT_FOUND; 4714 } 4715 4716 /* Set the VPN id value returned to caller */ 4717 _BCM_MPLS_VPN_SET(info->vpn, _BCM_MPLS_VPN_TYPE_VPWS, vpws_vpn_id); 4718 info->flags |= BCM_MPLS_VPN_VPWS; 4719 4720 } else if (_BCM_MPLS_VPN_IS_VPLS(vpn)) { 4721 int vfi_index, num_vfi; 4722 bcm_vpn_t vpls_vpn_min=0; 4723 vfi_entry_t vfi_entry; 4724 4725 num_vfi = soc_mem_index_count(unit, VFIm); 4726 4727 _BCM_MPLS_VPN_SET(vpls_vpn_min, _BCM_MPLS_VPN_TYPE_VPLS, 0); 4728 if ( vpn < vpls_vpn_min || vpn > (vpls_vpn_min+num_vfi-1) ) { 4729 return BCM_E_PARAM; 4730 } 4731 4732 _BCM_MPLS_VPN_GET(vfi_index, _BCM_MPLS_VPN_TYPE_VPLS, vpn); 4733 4734 if (!_bcm_vfi_used_get(unit, vfi_index, _bcmVfiTypeMpls)) { 4735 return BCM_E_NOT_FOUND; 4736 } 4737 4738 BCM_IF_ERROR_RETURN 4739 (READ_VFIm(unit, MEM_BLOCK_ALL, vfi_index, &vfi_entry)); 4740 #ifdef BCM_TRIUMPH2_SUPPORT 4741 if (soc_feature(unit, soc_feature_mpls_enhanced)) { 4742 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 4743 uint32 dt, dv; 4744 4745 dv = soc_mem_field32_dest_get(unit, VFIm, 4746 &vfi_entry, BC_DESTINATIONf, &dt); 4747 if (dt == SOC_MEM_FIF_DEST_IPMC) { 4748 _BCM_MULTICAST_GROUP_SET(info->broadcast_group, 4749 _BCM_MULTICAST_TYPE_VPLS, dv); 4750 } else { 4751 return BCM_E_INTERNAL; 4752 } 4753 4754 dv = soc_mem_field32_dest_get(unit, VFIm, 4755 &vfi_entry, UUC_DESTINATIONf, &dt); 4756 if (dt == SOC_MEM_FIF_DEST_IPMC) { 4757 _BCM_MULTICAST_GROUP_SET(info->unknown_unicast_group, 4758 _BCM_MULTICAST_TYPE_VPLS, dv); 4759 } else { 4760 return BCM_E_INTERNAL; 4761 } 4762 4763 dv = soc_mem_field32_dest_get(unit, VFIm, 4764 &vfi_entry, UMC_DESTINATIONf, &dt); 4765 if (dt == SOC_MEM_FIF_DEST_IPMC) { 4766 _BCM_MULTICAST_GROUP_SET(info->unknown_multicast_group, 4767 _BCM_MULTICAST_TYPE_VPLS, dv); 4768 } else { 4769 return BCM_E_INTERNAL; 4770 } 4771 4772 } else { 4773 _BCM_MULTICAST_GROUP_SET(info->broadcast_group, 4774 _BCM_MULTICAST_TYPE_VPLS, 4775 soc_VFIm_field32_get(unit, &vfi_entry, BC_INDEXf)); 4776 _BCM_MULTICAST_GROUP_SET(info->unknown_unicast_group, 4777 _BCM_MULTICAST_TYPE_VPLS, 4778 soc_VFIm_field32_get(unit, &vfi_entry, UUC_INDEXf)); 4779 _BCM_MULTICAST_GROUP_SET(info->unknown_multicast_group, 4780 _BCM_MULTICAST_TYPE_VPLS, 4781 soc_VFIm_field32_get(unit, &vfi_entry, UMC_INDEXf)); 4782 } 4783 } else 4784 #endif 4785 { 4786 _BCM_MULTICAST_GROUP_SET(info->broadcast_group, 4787 _BCM_MULTICAST_TYPE_VPLS, 4788 soc_VFIm_field32_get(unit, &vfi_entry, L3MC_INDEXf)); 4789 info->unknown_multicast_group = info->broadcast_group; 4790 info->unknown_unicast_group = info->broadcast_group; 4791 } 4792 4793 if (SOC_MEM_FIELD_VALID (unit,VFIm, PROTOCOL_PKT_INDEXf)) { 4794 proto_pkt_inx = soc_VFIm_field32_get(unit, &vfi_entry, 4795 PROTOCOL_PKT_INDEXf); 4796 rv = _bcm_xgs3_protocol_pkt_ctrl_get(unit,proto_pkt_inx, 4797 &info->protocol_pkt); 4798 if (BCM_FAILURE(rv) && (rv != BCM_E_UNAVAIL)) { 4799 return (rv); 4800 } 4801 } 4802 4803 /* Set the returned VPN id */ 4804 _BCM_MPLS_VPN_SET(info->vpn, _BCM_MPLS_VPN_TYPE_VPLS, vfi_index); 4805 info->flags |= BCM_MPLS_VPN_VPLS; 4806 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) 4807 if (soc_feature(unit, soc_feature_global_meter)) { 4808 _bcm_esw_get_policer_from_table(unit, VFIm, vfi_index, &vfi_entry, 4809 &info->policer_id, 1); 4810 } 4811 #endif /* BCM_KATANA_SUPPORT or BCM_TRIUMPH3_SUPPORT */ 4812 } else if (_BCM_MPLS_VPN_IS_L3(vpn)) { 4813 int vrf_id; 4814 4815 _BCM_MPLS_VPN_GET(vrf_id, _BCM_MPLS_VPN_TYPE_L3, vpn); 4816 if ((vrf_id < 0) || (vrf_id > SOC_VRF_MAX(unit))) { 4817 return BCM_E_PARAM; 4818 } 4819 if (!_BCM_MPLS_VRF_USED_GET(unit, vrf_id)) { 4820 return BCM_E_NOT_FOUND; 4821 } 4822 _BCM_MPLS_VPN_SET(info->vpn, _BCM_MPLS_VPN_TYPE_L3, vrf_id); 4823 info->flags |= BCM_MPLS_VPN_L3; 4824 4825 } else { 4826 return BCM_E_PARAM; 4827 } 4828 4829 return BCM_E_NONE; 4830 } 4831 4832 /* 4833 * Function: 4834 * bcm_mpls_vpn_id_destroy 4835 * Purpose: 4836 * Delete a VPN instance 4837 * Parameters: 4838 * unit - Device Number 4839 * vpn - VPN instance ID 4840 * Returns: 4841 * BCM_E_XXX 4842 */ 4843 int 4844 bcm_tr_mpls_vpn_id_destroy (int unit, bcm_vpn_t vpn) 4845 { 4846 int rv; 4847 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) 4848 int policer = 0; 4849 #endif 4850 4851 if (_BCM_MPLS_VPN_IS_VPWS(vpn)) { 4852 bcm_vpn_t vpn_id; 4853 4854 _BCM_MPLS_VPN_GET(vpn_id, _BCM_MPLS_VPN_TYPE_VPWS, vpn); 4855 4856 if (!_BCM_MPLS_VPWS_USED_GET(unit, vpn_id)) { 4857 return BCM_E_NOT_FOUND; 4858 } 4859 4860 /* Delete all the mpls ports on this VPN */ 4861 rv = bcm_tr_mpls_port_delete_all(unit, vpn); 4862 BCM_IF_ERROR_RETURN(rv); 4863 4864 (void) _bcm_tr_mpls_vpws_vp_map_clear (unit, vpn_id); 4865 4866 /* Clear the VPWS pair in-use status */ 4867 _BCM_MPLS_VPWS_USED_CLR(unit, vpn_id); 4868 } else if (_BCM_MPLS_VPN_IS_VPLS(vpn)) { 4869 int vfi, num_vfi; 4870 vfi_entry_t vfi_entry; 4871 bcm_vpn_t vpls_vpn_min=0; 4872 4873 num_vfi = soc_mem_index_count(unit, VFIm); 4874 4875 _BCM_MPLS_VPN_SET(vpls_vpn_min, _BCM_MPLS_VPN_TYPE_VPLS, 0); 4876 if ( vpn < vpls_vpn_min || vpn > (vpls_vpn_min+num_vfi-1) ) { 4877 return BCM_E_PARAM; 4878 } 4879 4880 _BCM_MPLS_VPN_GET(vfi, _BCM_MPLS_VPN_TYPE_VPLS, vpn); 4881 4882 if (!_bcm_vfi_used_get(unit, vfi, _bcmVfiTypeMpls)) { 4883 return BCM_E_NOT_FOUND; 4884 } 4885 4886 /* Delete all the mpls ports on this VPN */ 4887 rv = bcm_tr_mpls_port_delete_all(unit, vpn); 4888 BCM_IF_ERROR_RETURN(rv); 4889 4890 /* 4891 * Clear the VFI table entry by setting L3MC_INDEX to 0 and 4892 * PFM to 3. The PFM==3 (invalid) indicates that the VFI entry is not used. 4893 * This can be used to recover SW state during warm reboot. 4894 */ 4895 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) 4896 if (soc_feature(unit, soc_feature_global_meter)) { 4897 rv = _bcm_esw_get_policer_from_table(unit,VFIm, vfi, &vfi_entry, 4898 &policer, 0); 4899 if(BCM_SUCCESS(rv)) { 4900 _bcm_esw_policer_decrement_ref_count(unit, policer); 4901 } else { 4902 return rv; 4903 } 4904 } 4905 #endif /* BCM_KATANA_SUPPORT or BCM_TRIUMPH3_SUPPORT */ 4906 if (SOC_MEM_FIELD_VALID(unit, VFIm, PROTOCOL_PKT_INDEXf)) { 4907 int ref_count; 4908 int proto_pkt_inx; 4909 4910 sal_memset(&vfi_entry, 0, sizeof(vfi_entry_t)); 4911 rv = READ_VFIm(unit, MEM_BLOCK_ALL, vfi, &vfi_entry); 4912 BCM_IF_ERROR_RETURN(rv); 4913 proto_pkt_inx = soc_VFIm_field32_get(unit, &vfi_entry, 4914 PROTOCOL_PKT_INDEXf); 4915 BCM_IF_ERROR_RETURN(_bcm_prot_pkt_ctrl_ref_count_get (unit, 4916 proto_pkt_inx, &ref_count)); 4917 if (ref_count > 0) { 4918 BCM_IF_ERROR_RETURN(_bcm_prot_pkt_ctrl_delete(unit,proto_pkt_inx)); 4919 } 4920 } 4921 4922 #ifdef BCM_TRIUMPH2_SUPPORT 4923 if (soc_feature(unit, soc_feature_gport_service_counters)) { 4924 /* Release Service counter, if any */ 4925 _bcm_esw_flex_stat_handle_free(unit, _bcmFlexStatTypeService, vpn); 4926 } 4927 #endif /* BCM_TRIUMPH2_SUPPORT */ 4928 4929 (void) _bcm_vfi_free(unit, _bcmVfiTypeMpls, vfi); 4930 4931 if (!soc_feature(unit, soc_feature_mpls_enhanced)) { 4932 if (SOC_MEM_FIELD_VALID(unit, VFIm, PFMf)) { 4933 BCM_IF_ERROR_RETURN(soc_mem_field32_modify(unit, VFIm, 4934 vfi, PFMf, 3)); 4935 } 4936 } 4937 } else if (_BCM_MPLS_VPN_IS_L3(vpn)) { 4938 int vrf; 4939 4940 _BCM_MPLS_VPN_GET(vrf, _BCM_MPLS_VPN_TYPE_L3, vpn); 4941 if ((vrf < 0) || (vrf > SOC_VRF_MAX(unit))) { 4942 return BCM_E_PARAM; 4943 } 4944 4945 if (!_BCM_MPLS_VRF_USED_GET(unit, vrf)) { 4946 return BCM_E_NOT_FOUND; 4947 } 4948 _BCM_MPLS_VRF_USED_CLR(unit, vrf); 4949 } else { 4950 return BCM_E_PARAM; 4951 } 4952 4953 #ifdef BCM_WARM_BOOT_SUPPORT 4954 SOC_CONTROL_LOCK(unit); 4955 SOC_CONTROL(unit)->scache_dirty = 1; 4956 SOC_CONTROL_UNLOCK(unit); 4957 #endif 4958 4959 return BCM_E_NONE; 4960 } 4961 4962 /* 4963 * Function: 4964 * bcm_mpls_vpn_id_destroy_all 4965 * Purpose: 4966 * Delete all VPN instances 4967 * Parameters: 4968 * unit - Device Number 4969 * Returns: 4970 * BCM_E_XXX 4971 */ 4972 4973 int 4974 bcm_tr_mpls_vpn_id_destroy_all (int unit) 4975 { 4976 int num_vpws = 0, num_vfi = 0, num_vrf, idx, rv, rv_error = BCM_E_NONE; 4977 bcm_vpn_t vpn; 4978 4979 4980 /* Destroy all VPWS VPNs */ 4981 if (SOC_MEM_IS_VALID(unit, SOURCE_VPm)) { 4982 num_vpws = soc_mem_index_count(unit, SOURCE_VPm) / 2; 4983 } 4984 for (idx = 0; idx < num_vpws; idx++) { 4985 if (_BCM_MPLS_VPWS_USED_GET(unit, idx)) { 4986 _BCM_MPLS_VPN_SET(vpn, _BCM_MPLS_VPN_TYPE_VPWS, (idx)); 4987 rv = bcm_tr_mpls_vpn_id_destroy(unit, vpn); 4988 if (rv < 0) { 4989 rv_error = rv; 4990 } 4991 } 4992 } 4993 4994 /* Destroy all VPLS VPNs */ 4995 if (SOC_MEM_IS_VALID(unit, VFIm)) { 4996 num_vfi = soc_mem_index_count(unit, VFIm); 4997 } 4998 for (idx = 0; idx < num_vfi; idx++) { 4999 if (_bcm_vfi_used_get(unit, idx, _bcmVfiTypeMpls)) { 5000 _BCM_MPLS_VPN_SET(vpn, _BCM_MPLS_VPN_TYPE_VPLS, idx); 5001 rv = bcm_tr_mpls_vpn_id_destroy(unit, vpn); 5002 if (rv < 0) { 5003 rv_error = rv; 5004 } 5005 } 5006 } 5007 5008 /* Destroy all L3 VPNs */ 5009 num_vrf = SOC_VRF_MAX(unit) + 1; 5010 for (idx = 0; idx < num_vrf; idx++) { 5011 if (_BCM_MPLS_VRF_USED_GET(unit, idx)) { 5012 _BCM_MPLS_VPN_SET(vpn, _BCM_MPLS_VPN_TYPE_L3, idx); 5013 rv = bcm_tr_mpls_vpn_id_destroy(unit, vpn); 5014 if (rv < 0) { 5015 rv_error = rv; 5016 } 5017 } 5018 } 5019 5020 /* Destroy default VP */ 5021 if (_bcm_vp_used_get(unit, 0, _bcmVpTypeMpls)) { 5022 _bcm_vp_free(unit, _bcmVpTypeMpls, 1, 0); 5023 } 5024 5025 return rv_error; 5026 } 5027 5028 /* 5029 * Function: 5030 * bcm_mpls_vpn_traverse 5031 * Purpose: 5032 * Get information about a VPN instance 5033 * Parameters: 5034 * unit - (IN) Device Number 5035 * cb - (IN) User-provided callback 5036 * info - (IN/OUT) Cookie 5037 * Returns: 5038 * BCM_E_XXX 5039 */ 5040 5041 int bcm_tr_mpls_vpn_traverse(int unit, bcm_mpls_vpn_traverse_cb cb, 5042 void *user_data) 5043 { 5044 int idx, num_vpws = 0, num_vfi = 0, num_vrf = 0, rv = BCM_E_NONE; 5045 int vpn; 5046 bcm_mpls_vpn_config_t info; 5047 5048 /* VPWS VPNs */ 5049 if (SOC_MEM_IS_VALID(unit, SOURCE_VPm)) { 5050 num_vpws = soc_mem_index_count(unit, SOURCE_VPm) / 2; 5051 } 5052 for (idx = 0; idx < num_vpws; idx++) { 5053 if (_BCM_MPLS_VPWS_USED_GET(unit, idx)) { 5054 _BCM_MPLS_VPN_SET(vpn, _BCM_MPLS_VPN_TYPE_VPWS, (idx)); 5055 bcm_mpls_vpn_config_t_init(&info); 5056 rv = bcm_tr_mpls_vpn_id_get(unit, vpn, &info); 5057 if (BCM_FAILURE(rv)) { 5058 return rv; 5059 } 5060 rv = cb(unit, &info, user_data); 5061 if (BCM_FAILURE(rv)) { 5062 return rv; 5063 } 5064 } 5065 } 5066 5067 /* VPLS VPNs */ 5068 if (SOC_MEM_IS_VALID(unit, SOURCE_VPm)) { 5069 num_vfi = soc_mem_index_count(unit, VFIm); 5070 } 5071 for (idx = 0; idx < num_vfi; idx++) { 5072 if (_bcm_vfi_used_get(unit, idx, _bcmVfiTypeMpls)) { 5073 _BCM_MPLS_VPN_SET(vpn, _BCM_MPLS_VPN_TYPE_VPLS, idx); 5074 bcm_mpls_vpn_config_t_init(&info); 5075 rv = bcm_tr_mpls_vpn_id_get(unit, vpn, &info); 5076 if (BCM_FAILURE(rv)) { 5077 return rv; 5078 } 5079 rv = cb(unit, &info, user_data); 5080 if (BCM_FAILURE(rv)) { 5081 return rv; 5082 } 5083 } 5084 } 5085 5086 /* L3 VPNs */ 5087 num_vrf = SOC_VRF_MAX(unit) + 1; 5088 for (idx = 0; idx < num_vrf; idx++) { 5089 if (_BCM_MPLS_VRF_USED_GET(unit, idx)) { 5090 _BCM_MPLS_VPN_SET(vpn, _BCM_MPLS_VPN_TYPE_L3, idx); 5091 bcm_mpls_vpn_config_t_init(&info); 5092 rv = bcm_tr_mpls_vpn_id_get(unit, vpn, &info); 5093 if (BCM_FAILURE(rv)) { 5094 return rv; 5095 } 5096 rv = cb(unit, &info, user_data); 5097 if (BCM_FAILURE(rv)) { 5098 return rv; 5099 } 5100 } 5101 } 5102 return rv; 5103 } 5104 5105 typedef struct _bcm_tr_ing_nh_info_s { 5106 bcm_port_t port; 5107 int module; 5108 bcm_trunk_t trunk; 5109 uint32 mtu; 5110 int qtag; 5111 int tag_type; 5112 } _bcm_tr_ing_nh_info_t; 5113 5114 typedef struct _bcm_tr_egr_nh_info_s { 5115 int entry_type; 5116 int dvp_is_network; 5117 int dvp_network_group_id; 5118 int sd_tag_action_present; 5119 int sd_tag_action_not_present; 5120 int dvp; 5121 int intf_num; 5122 int sd_tag_vlan; 5123 int sd_tag_pri; 5124 int sd_tag_cfi; 5125 int lltag_vlan; 5126 int lltag_pri; 5127 int lltag_cfi; 5128 int macda_index; 5129 int vc_swap_index; 5130 int tpid_index; 5131 int pw_init_cnt; 5132 int vintf_ctr_index; 5133 int flex_ctr_base_cnt_idx; 5134 int flex_ctr_pool_num; 5135 int flex_ctr_offset_mode; 5136 int class_id; 5137 uint16 oam_global_context_id; 5138 } _bcm_tr_egr_nh_info_t; 5139 5140 5141 STATIC int 5142 _bcm_tr_mpls_INITIAL_ING_L3_NEXT_HOP_add(int unit, _bcm_tr_ing_nh_info_t *ing_nh_info, 5143 int nh_index, bcm_port_t *local_port, int *is_local) 5144 { 5145 initial_ing_l3_next_hop_entry_t initial_ing_nh; 5146 int rv; 5147 int modid_local=0; 5148 #if defined(BCM_KATANA2_SUPPORT) 5149 bcm_port_t pp_port; 5150 #endif 5151 5152 sal_memset(&initial_ing_nh, 0, sizeof(initial_ing_l3_next_hop_entry_t)); 5153 if (ing_nh_info->trunk == -1) { 5154 if (soc_feature(unit, soc_feature_generic_dest)) { 5155 soc_mem_field32_dest_set(unit, INITIAL_ING_L3_NEXT_HOPm, &initial_ing_nh, 5156 DESTINATIONf, SOC_MEM_FIF_DEST_DGPP, 5157 ing_nh_info->module << SOC_MEM_FIF_DGPP_MOD_ID_SHIFT_BITS | ing_nh_info->port); 5158 } else { 5159 soc_mem_field32_set(unit, INITIAL_ING_L3_NEXT_HOPm, 5160 &initial_ing_nh, PORT_NUMf, ing_nh_info->port); 5161 soc_mem_field32_set(unit, INITIAL_ING_L3_NEXT_HOPm, 5162 &initial_ing_nh, MODULE_IDf, ing_nh_info->module); 5163 } 5164 BCM_IF_ERROR_RETURN( _bcm_esw_modid_is_local(unit, ing_nh_info->module, &modid_local)); 5165 5166 #if defined(BCM_HGPROXY_COE_SUPPORT) 5167 if(soc_feature(unit, soc_feature_hgproxy_subtag_coe) && 5168 _bcm_xgs5_subport_coe_mod_local(unit, ing_nh_info->module)) { 5169 5170 *is_local = 1; 5171 BCM_IF_ERROR_RETURN(_bcmi_coe_subport_mod_port_physical_port_get(unit, 5172 ing_nh_info->module, 5173 ing_nh_info->port, 5174 local_port)); 5175 } else 5176 #endif 5177 5178 #if defined(BCM_KATANA2_SUPPORT) 5179 if (soc_feature(unit, soc_feature_linkphy_coe) || 5180 soc_feature(unit, soc_feature_subtag_coe)) { 5181 if (modid_local == 0) { 5182 /* Check if this is local LinkPHYSubtag modid */ 5183 if (_bcm_kt2_mod_is_coe_mod_check(unit, ing_nh_info->module) == BCM_E_NONE) { 5184 BCM_IF_ERROR_RETURN(_bcm_kt2_modport_to_pp_port_get( 5185 unit, ing_nh_info->module, 5186 ing_nh_info->port, &pp_port)); 5187 if (_bcm_kt2_is_pp_port_linkphy_subtag(unit, pp_port)){ 5188 *is_local = 1; 5189 *local_port = pp_port; 5190 } 5191 } 5192 } 5193 } 5194 #endif 5195 if (modid_local) { 5196 /* Indicated to calling function that this is a local port */ 5197 *is_local = 1; 5198 *local_port = ing_nh_info->port; 5199 } 5200 } else { 5201 5202 if (soc_feature(unit, soc_feature_generic_dest)) { 5203 soc_mem_field32_dest_set(unit, INITIAL_ING_L3_NEXT_HOPm, &initial_ing_nh, 5204 DESTINATIONf, SOC_MEM_FIF_DEST_LAG, ing_nh_info->trunk); 5205 } else { 5206 soc_mem_field32_set(unit, INITIAL_ING_L3_NEXT_HOPm, 5207 &initial_ing_nh, Tf, 1); 5208 soc_mem_field32_set(unit, INITIAL_ING_L3_NEXT_HOPm, 5209 &initial_ing_nh, TGIDf, ing_nh_info->trunk); 5210 } 5211 *is_local = 1; 5212 BCM_GPORT_TRUNK_SET(*local_port, ing_nh_info->trunk); 5213 } 5214 5215 rv = soc_mem_write(unit, INITIAL_ING_L3_NEXT_HOPm, 5216 MEM_BLOCK_ALL, nh_index, &initial_ing_nh); 5217 5218 return rv; 5219 } 5220 5221 5222 STATIC int 5223 _bcm_tr_mpls_ING_L3_NEXT_HOP_add(int unit, _bcm_tr_ing_nh_info_t *ing_nh_info, 5224 int nh_index, int drop) 5225 { 5226 ing_l3_next_hop_entry_t ing_nh; 5227 int rv; 5228 #ifdef BCM_TRIUMPH3_SUPPORT 5229 uint32 mtu_profile_index = 0; 5230 #endif /* BCM_TRIUMPH3_SUPPORT */ 5231 5232 sal_memset(&ing_nh, 0, sizeof(ing_l3_next_hop_entry_t)); 5233 5234 soc_mem_field32_set(unit, ING_L3_NEXT_HOPm, &ing_nh, DROPf, drop); 5235 if (ing_nh_info->trunk == -1) { 5236 if (soc_feature(unit, soc_feature_generic_dest)) { 5237 if (ing_nh_info->port!=0) { 5238 soc_mem_field32_dest_set(unit, ING_L3_NEXT_HOPm, &ing_nh, 5239 DESTINATIONf, SOC_MEM_FIF_DEST_DGPP, 5240 ing_nh_info->module << SOC_MEM_FIF_DGPP_MOD_ID_SHIFT_BITS | ing_nh_info->port); 5241 } 5242 } else { 5243 soc_mem_field32_set(unit, ING_L3_NEXT_HOPm, 5244 &ing_nh, PORT_NUMf, ing_nh_info->port); 5245 soc_mem_field32_set(unit, ING_L3_NEXT_HOPm, 5246 &ing_nh, MODULE_IDf, ing_nh_info->module); 5247 } 5248 } else { 5249 if (soc_feature(unit, soc_feature_generic_dest)) { 5250 soc_mem_field32_dest_set(unit, ING_L3_NEXT_HOPm, &ing_nh, 5251 DESTINATIONf, SOC_MEM_FIF_DEST_LAG, ing_nh_info->trunk); 5252 } else { 5253 soc_mem_field32_set(unit, ING_L3_NEXT_HOPm, 5254 &ing_nh, Tf, 1); 5255 soc_mem_field32_set(unit, ING_L3_NEXT_HOPm, 5256 &ing_nh, TGIDf, ing_nh_info->trunk); 5257 } 5258 } 5259 soc_mem_field32_set(unit, ING_L3_NEXT_HOPm, 5260 &ing_nh, ENTRY_TYPEf, 0x2); /* L2 DVP */ 5261 if (SOC_MEM_FIELD_VALID(unit, ING_L3_NEXT_HOPm, MTU_SIZEf)) { 5262 if (ing_nh_info->mtu >= 5263 (1 << soc_mem_field_length(unit, ING_L3_NEXT_HOPm, MTU_SIZEf))) { 5264 soc_mem_field32_set(unit, ING_L3_NEXT_HOPm, 5265 &ing_nh, MTU_SIZEf, 0x3fff); 5266 } else { 5267 soc_mem_field32_set(unit, ING_L3_NEXT_HOPm, 5268 &ing_nh, MTU_SIZEf, ing_nh_info->mtu); 5269 } 5270 } 5271 #ifdef BCM_TRIUMPH3_SUPPORT 5272 else if (SOC_MEM_FIELD_VALID(unit, ING_L3_NEXT_HOPm, 5273 DVP_ATTRIBUTE_1_INDEXf)) { 5274 BCM_IF_ERROR_RETURN( 5275 _bcm_tr3_mtu_profile_index_get(unit, 0x3fff, &mtu_profile_index)); 5276 soc_mem_field32_set(unit, ING_L3_NEXT_HOPm, &ing_nh, 5277 DVP_ATTRIBUTE_1_INDEXf, mtu_profile_index); 5278 } 5279 #endif /*BCM_TRIUMPH3_SUPPORT */ 5280 5281 if ((ing_nh_info->qtag != -1) && 5282 SOC_MEM_FIELD_VALID(unit, ING_L3_NEXT_HOPm,EH_QUEUE_TAGf)) { 5283 soc_mem_field32_set(unit, ING_L3_NEXT_HOPm, &ing_nh, 5284 EH_QUEUE_TAGf, ing_nh_info->qtag); 5285 } 5286 if ((ing_nh_info->tag_type != -1) && 5287 SOC_MEM_FIELD_VALID(unit, ING_L3_NEXT_HOPm,EH_TAG_TYPEf)) { 5288 soc_mem_field32_set(unit, ING_L3_NEXT_HOPm, &ing_nh, 5289 EH_TAG_TYPEf, ing_nh_info->tag_type); 5290 } 5291 5292 rv = soc_mem_write (unit, ING_L3_NEXT_HOPm, 5293 MEM_BLOCK_ALL, nh_index, &ing_nh); 5294 return rv; 5295 } 5296 5297 5298 STATIC int 5299 _bcm_tr_mpls_EGR_L3_NEXT_HOP_add(int unit, _bcm_tr_egr_nh_info_t *egr_nh_info, 5300 uint32 flags, int nh_index, int *is_local, int is_vpws, int drop) 5301 { 5302 egr_l3_next_hop_entry_t egr_nh; 5303 int rv; 5304 5305 sal_memset(&egr_nh, 0, sizeof(egr_l3_next_hop_entry_t)); 5306 5307 if (egr_nh_info->entry_type == 0x1) { 5308 5309 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 5310 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 5311 &egr_nh, L3__INTF_NUMf, egr_nh_info->intf_num); 5312 } else { 5313 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 5314 &egr_nh, INTF_NUMf, egr_nh_info->intf_num); 5315 } 5316 if (egr_nh_info->macda_index != -1) { 5317 if (soc_feature(unit, soc_feature_mpls_enhanced)) { 5318 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 5319 &egr_nh, MPLS__MAC_DA_PROFILE_INDEXf, 5320 egr_nh_info->macda_index); 5321 } else { 5322 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 5323 &egr_nh, MAC_DA_PROFILE_INDEXf, 5324 egr_nh_info->macda_index); 5325 } 5326 } 5327 if (egr_nh_info->vc_swap_index != -1) { 5328 if (soc_feature(unit, soc_feature_mpls_enhanced)) { 5329 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 5330 &egr_nh, MPLS__VC_AND_SWAP_INDEXf, 5331 egr_nh_info->vc_swap_index); 5332 } else { 5333 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 5334 &egr_nh, VC_AND_SWAP_INDEXf, 5335 egr_nh_info->vc_swap_index); 5336 } 5337 } 5338 5339 if (soc_feature(unit, soc_feature_mpls_enhanced)) { 5340 5341 if (soc_mem_field_valid(unit, EGR_L3_NEXT_HOPm, MPLS__CLASS_IDf)) { 5342 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 5343 MPLS__CLASS_IDf, egr_nh_info->class_id); 5344 } 5345 5346 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) 5347 if ((egr_nh_info->flex_ctr_base_cnt_idx != -1) && 5348 soc_feature(unit,soc_feature_advanced_flex_counter)) { 5349 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 5350 MPLS__FLEX_CTR_BASE_COUNTER_IDXf, 5351 egr_nh_info->flex_ctr_base_cnt_idx); 5352 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 5353 MPLS__FLEX_CTR_POOL_NUMBERf, 5354 egr_nh_info->flex_ctr_pool_num); 5355 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 5356 MPLS__FLEX_CTR_OFFSET_MODEf, 5357 egr_nh_info->flex_ctr_offset_mode); 5358 } else 5359 #endif 5360 if ((egr_nh_info->vintf_ctr_index != -1) && 5361 soc_feature(unit, soc_feature_gport_service_counters)) { 5362 if (soc_mem_field_valid(unit, EGR_L3_NEXT_HOPm, 5363 MPLS__USE_VINTF_CTR_IDXf)) { 5364 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 5365 MPLS__USE_VINTF_CTR_IDXf, 5366 egr_nh_info->vintf_ctr_index ? 1 : 0); 5367 } 5368 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 5369 MPLS__VINTF_CTR_IDXf, 5370 egr_nh_info->vintf_ctr_index); 5371 } 5372 } 5373 5374 if (egr_nh_info->pw_init_cnt != -1) { 5375 if (soc_feature(unit, soc_feature_mpls_enhanced)) { 5376 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 5377 MPLS__PW_INIT_NUMf, egr_nh_info->pw_init_cnt); 5378 } else { 5379 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 5380 PW_INIT_NUMf, egr_nh_info->pw_init_cnt); 5381 } 5382 } 5383 5384 if (soc_feature(unit, soc_feature_vlan_xlate)) { 5385 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 5386 MPLS__USE_DVP_IN_EVXLT_KEYf, 0x1); 5387 } 5388 5389 if (soc_feature(unit, soc_feature_mpls_enhanced)) { 5390 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 5391 MPLS__BC_DROPf, drop ? 1 : 0); 5392 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 5393 MPLS__UUC_DROPf, drop ? 1 : 0); 5394 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 5395 MPLS__UMC_DROPf, drop ? 1 : 0); 5396 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 5397 MPLS__DVPf, egr_nh_info->dvp); 5398 if (soc_feature(unit, soc_feature_multiple_split_horizon_group)) { 5399 if (!(soc_feature(unit, soc_feature_td3_style_mpls))) { 5400 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 5401 &egr_nh, MPLS__DVP_NETWORK_GROUPf, 5402 egr_nh_info->dvp_network_group_id); 5403 } 5404 } else { 5405 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 5406 &egr_nh, MPLS__DVP_IS_NETWORK_PORTf, 5407 egr_nh_info->dvp_is_network); 5408 } 5409 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 5410 MPLS__HG_LEARN_OVERRIDEf, is_vpws ? 1 : 0); 5411 /* 5412 * Generally for L2 MPLS, 5413 * - VPWS application, MPLS tunnel header can be encapsulated 5414 * at ingress chip or egress chip, the suggestion is add MPLS 5415 * header at egress chip to save HG bandwidth. 5416 * 5417 * - VPLS application, L2 learning is needed on egress chip, 5418 * that means the MPLS tunnel header need to be encapsulated at 5419 * the egress chip. SVP and DVP field in PPD type 2 will provide 5420 * infomation for these requirements. 5421 */ 5422 if (flags & BCM_MPLS_PORT2_PROXY_MODE) { 5423 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 5424 MPLS__HG_MODIFY_ENABLEf, 0x1); 5425 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 5426 MPLS__HG_HDR_SELf, 0); 5427 } else { 5428 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 5429 MPLS__HG_MODIFY_ENABLEf, 0x0); 5430 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 5431 MPLS__HG_HDR_SELf, 1); 5432 } 5433 } else { 5434 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 5435 DVPf, egr_nh_info->dvp); 5436 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 5437 &egr_nh, DVP_IS_NETWORK_PORTf, 5438 egr_nh_info->dvp_is_network); 5439 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 5440 HG_LEARN_OVERRIDEf, is_vpws ? 1 : 0); 5441 /* For L2 MPLS, HG_MODIFY_ENABLE must be 0x0 for Ingress and Egress Chip */ 5442 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 5443 HG_MODIFY_ENABLEf, 0x0); 5444 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 5445 HG_HDR_SELf, 1); 5446 } 5447 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) 5448 if (soc_feature(unit, soc_feature_mpls_nh_ttl_control)) { 5449 if (flags & BCM_MPLS_PORT2_KEEP_TTL) { 5450 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 5451 MPLS__DISABLE_TTL_DECREMENTf, 1); 5452 } 5453 } 5454 #endif 5455 } else if (egr_nh_info->entry_type == 0x2) { 5456 5457 if (egr_nh_info->lltag_vlan != -1) { 5458 if (soc_feature(unit, soc_feature_lltag)) { 5459 if (egr_nh_info->lltag_pri != -1) { 5460 /* PCP, DE fields are copied from this table. */ 5461 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 5462 &egr_nh, SD_TAG__LLTAG_PCP_DE_SOURCEf, 0x02); 5463 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 5464 &egr_nh, SD_TAG__LLTAG_PCPf, egr_nh_info->lltag_pri); 5465 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 5466 &egr_nh, SD_TAG__LLTAG_DEf, egr_nh_info->lltag_cfi); 5467 } else { 5468 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 5469 &egr_nh, SD_TAG__LLTAG_PCP_DE_SOURCEf, 0x03); 5470 } 5471 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 5472 &egr_nh, SD_TAG__LLTAG_ACTIONSf, 0x04); 5473 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 5474 &egr_nh, SD_TAG__LLTAG_VIDf, egr_nh_info->lltag_vlan); 5475 5476 } 5477 } 5478 5479 if (egr_nh_info->sd_tag_vlan != -1) { 5480 if (soc_feature(unit, soc_feature_mpls_enhanced)) { 5481 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 5482 if (soc_feature(unit, soc_feature_vp_sharing)) { 5483 if (egr_nh_info->sd_tag_vlan == BCM_VLAN_INVALID) { 5484 if(SOC_MEM_FIELD_VALID(unit, 5485 EGR_L3_NEXT_HOPm, 5486 SD_TAG__SD_TAG_NOT_VALIDf)) { 5487 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 5488 &egr_nh, SD_TAG__SD_TAG_NOT_VALIDf, 1); 5489 } 5490 } else { 5491 if(SOC_MEM_FIELD_VALID(unit, 5492 EGR_L3_NEXT_HOPm, 5493 SD_TAG__SD_TAG_NOT_VALIDf)) { 5494 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 5495 &egr_nh, SD_TAG__SD_TAG_NOT_VALIDf, 0); 5496 } 5497 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 5498 &egr_nh, SD_TAG__SD_TAG_VIDf, egr_nh_info->sd_tag_vlan); 5499 } 5500 } else 5501 #endif 5502 { 5503 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 5504 &egr_nh, SD_TAG__SD_TAG_VIDf, egr_nh_info->sd_tag_vlan); 5505 } 5506 } else { 5507 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 5508 &egr_nh, SD_TAG_VIDf, egr_nh_info->sd_tag_vlan); 5509 } 5510 } 5511 5512 if (egr_nh_info->sd_tag_action_present != -1) { 5513 if (soc_feature(unit, soc_feature_mpls_enhanced)) { 5514 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 5515 SD_TAG__SD_TAG_ACTION_IF_PRESENTf, 5516 egr_nh_info->sd_tag_action_present); 5517 } else { 5518 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 5519 SD_TAG_ACTION_IF_PRESENTf, 5520 egr_nh_info->sd_tag_action_present); 5521 } 5522 } 5523 5524 if (egr_nh_info->sd_tag_action_not_present != -1) { 5525 if (soc_feature(unit, soc_feature_mpls_enhanced)) { 5526 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 5527 SD_TAG__SD_TAG_ACTION_IF_NOT_PRESENTf, 5528 egr_nh_info->sd_tag_action_not_present); 5529 } else { 5530 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 5531 SD_TAG_ACTION_IF_NOT_PRESENTf, 5532 egr_nh_info->sd_tag_action_not_present); 5533 } 5534 } 5535 5536 if (egr_nh_info->sd_tag_pri != -1) { 5537 if (soc_feature(unit, soc_feature_mpls_enhanced)) { 5538 if(soc_mem_field_valid(unit, EGR_L3_NEXT_HOPm, SD_TAG__NEW_PRIf)) { 5539 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 5540 SD_TAG__NEW_PRIf, 5541 egr_nh_info->sd_tag_pri); 5542 } 5543 } 5544 } 5545 5546 if (egr_nh_info->sd_tag_cfi != -1) { 5547 if (soc_feature(unit, soc_feature_mpls_enhanced)) { 5548 if(soc_mem_field_valid(unit, EGR_L3_NEXT_HOPm, SD_TAG__NEW_CFIf)) { 5549 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 5550 SD_TAG__NEW_CFIf, 5551 egr_nh_info->sd_tag_cfi); 5552 } 5553 if (soc_mem_field_valid(unit, EGR_L3_NEXT_HOPm, SD_TAG__SD_TAG_REMARK_CFIf)) { 5554 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 5555 SD_TAG__SD_TAG_REMARK_CFIf, 1); 5556 } 5557 } 5558 } 5559 5560 if (egr_nh_info->tpid_index != -1) { 5561 if (soc_feature(unit, soc_feature_mpls_enhanced)) { 5562 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 5563 &egr_nh, SD_TAG__SD_TAG_TPID_INDEXf, 5564 egr_nh_info->tpid_index); 5565 } else { 5566 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 5567 &egr_nh, SD_TAG_TPID_INDEXf, 5568 egr_nh_info->tpid_index); 5569 } 5570 } 5571 5572 if (soc_feature(unit, soc_feature_mpls_enhanced)) { 5573 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) 5574 if ((egr_nh_info->flex_ctr_base_cnt_idx != -1) && 5575 soc_feature(unit,soc_feature_advanced_flex_counter)) { 5576 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 5577 SD_TAG__FLEX_CTR_BASE_COUNTER_IDXf, 5578 egr_nh_info->flex_ctr_base_cnt_idx); 5579 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 5580 SD_TAG__FLEX_CTR_POOL_NUMBERf, 5581 egr_nh_info->flex_ctr_pool_num); 5582 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 5583 SD_TAG__FLEX_CTR_OFFSET_MODEf, 5584 egr_nh_info->flex_ctr_offset_mode); 5585 } else 5586 #endif 5587 if ((egr_nh_info->vintf_ctr_index != -1) && 5588 soc_feature(unit, soc_feature_gport_service_counters)) { 5589 if (soc_mem_field_valid(unit, EGR_L3_NEXT_HOPm, 5590 SD_TAG__USE_VINTF_CTR_IDXf)) { 5591 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 5592 SD_TAG__USE_VINTF_CTR_IDXf, 5593 egr_nh_info->vintf_ctr_index ? 1 : 0); 5594 } 5595 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 5596 SD_TAG__VINTF_CTR_IDXf, 5597 egr_nh_info->vintf_ctr_index); 5598 } 5599 } 5600 5601 if (soc_feature(unit, soc_feature_mpls_enhanced)) { 5602 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 5603 SD_TAG__BC_DROPf, drop ? 1 : 0); 5604 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 5605 SD_TAG__UUC_DROPf, drop ? 1 : 0); 5606 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 5607 SD_TAG__UMC_DROPf, drop ? 1 : 0); 5608 } 5609 5610 if (soc_feature(unit, soc_feature_mpls_enhanced)) { 5611 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 5612 SD_TAG__BC_DROPf, drop ? 1 : 0); 5613 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 5614 SD_TAG__UUC_DROPf, drop ? 1 : 0); 5615 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 5616 SD_TAG__UMC_DROPf, drop ? 1 : 0); 5617 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 5618 SD_TAG__DVPf, egr_nh_info->dvp); 5619 if (soc_feature(unit, soc_feature_multiple_split_horizon_group)) { 5620 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 5621 rv = soc_mem_field32_modify(unit, EGR_DVP_ATTRIBUTEm, 5622 egr_nh_info->dvp, COMMON__DVP_NETWORK_GROUPf, 5623 egr_nh_info->dvp_network_group_id); 5624 if (rv < 0) { 5625 return rv; 5626 } 5627 } else { 5628 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 5629 &egr_nh, SD_TAG__DVP_NETWORK_GROUPf, 5630 egr_nh_info->dvp_network_group_id); 5631 } 5632 } else { 5633 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 5634 &egr_nh, SD_TAG__DVP_IS_NETWORK_PORTf, 5635 egr_nh_info->dvp_is_network); 5636 } 5637 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 5638 SD_TAG__HG_LEARN_OVERRIDEf, is_vpws ? 1 : 0); 5639 /* 5640 * Generally for L2 MPLS, 5641 * - VPWS application, MPLS tunnel header can be encapsulated 5642 * at ingress chip or egress chip, the suggestion is add MPLS 5643 * header at egress chip to save HG bandwidth. 5644 * 5645 * - VPLS application, L2 learning is needed on egress chip, 5646 * that means the MPLS tunnel header need to be encapsulated at 5647 * the egress chip. SVP and DVP field in PPD type 2 will provide 5648 * infomation for these requirements. 5649 */ 5650 if (flags & BCM_MPLS_PORT2_PROXY_MODE) { 5651 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 5652 SD_TAG__HG_MODIFY_ENABLEf, 0x1); 5653 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 5654 SD_TAG__HG_HDR_SELf, 0); 5655 } else { 5656 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 5657 SD_TAG__HG_MODIFY_ENABLEf, 0x0); 5658 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 5659 SD_TAG__HG_HDR_SELf, 1); 5660 } 5661 5662 if (egr_nh_info->class_id != BCM_CLASS_ID_INVALID) { 5663 if (soc_mem_field_valid(unit, EGR_L3_NEXT_HOPm, SD_TAG__CLASS_IDf)) { 5664 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 5665 SD_TAG__CLASS_IDf, egr_nh_info->class_id); 5666 } 5667 } 5668 } else { 5669 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 5670 DVPf, egr_nh_info->dvp); 5671 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 5672 &egr_nh, DVP_IS_NETWORK_PORTf, 5673 egr_nh_info->dvp_is_network); 5674 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 5675 HG_LEARN_OVERRIDEf, is_vpws ? 1 : 0); 5676 /* For L2 MPLS, HG_MODIFY_ENABLE must be 0x0 for Ingress and Egress Chip */ 5677 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 5678 HG_MODIFY_ENABLEf, 0x0); 5679 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 5680 HG_HDR_SELf, 1); 5681 } 5682 } else { 5683 return BCM_E_PARAM; 5684 } 5685 5686 if ((_BCM_MPLS_MEPID_IN_VALID_RANGE(egr_nh_info->oam_global_context_id)) && 5687 (soc_mem_field_valid(unit, EGR_L3_NEXT_HOPm, MPLS__MEPIDf))) { 5688 /* Writing MPLS LM/DM value. it doesnt matter since 5689 data packets are similar for BHH and MPLS LM/DM */ 5690 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 5691 MPLS__MPLS_OAM_DOWNMEP_ENABLEf, 2); 5692 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 5693 MPLS__MEPIDf, egr_nh_info->oam_global_context_id); 5694 } 5695 5696 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 5697 nh_entry_type_field[unit], egr_nh_info->entry_type); 5698 5699 rv = soc_mem_write(unit, EGR_L3_NEXT_HOPm, 5700 MEM_BLOCK_ALL, nh_index, &egr_nh); 5701 5702 return rv; 5703 } 5704 5705 /* 5706 * Function: 5707 * _bcm_tr_mpls_compute_nhop_hash 5708 * Purpose: 5709 * Compute the hash Index from Egress Tunnel If 5710 * Parameters: 5711 * unit - (IN) bcm device. 5712 * egress_if - (IN) Egress Tunnel If 5713 * Returns: 5714 * BCM_E_XXX 5715 */ 5716 5717 STATIC void 5718 _bcm_tr_mpls_compute_nhop_hash (bcm_if_t egress_if, int *hash_idx) 5719 { 5720 *hash_idx = egress_if % 1024; 5721 } 5722 5723 /* 5724 * Function: 5725 * _bcm_tr_mpls_add_vp_nh 5726 * Purpose: 5727 * Add MPLS VP NextHop index into a list 5728 * Parameters: 5729 * unit - (IN) bcm device. 5730 * mpls_port - (IN) MPLS Port 5731 * nh_index - (IN) VP NextHop Index 5732 * Returns: 5733 * BCM_E_XXX 5734 */ 5735 5736 STATIC int 5737 _bcm_tr_mpls_add_vp_nh ( int unit, bcm_if_t egr_if, int nh_index ) 5738 { 5739 _bcm_mpls_egr_nhopList_t *nhop_cursorPtr; 5740 _bcm_mpls_vp_nh_list_t *vp_cursorPtr; 5741 _bcm_mpls_vp_nh_list_t *newVpNode; 5742 int hash_idx; 5743 5744 (void) _bcm_tr_mpls_compute_nhop_hash (egr_if, &hash_idx); 5745 5746 5747 /* If Node is present, then insert the VP_index */ 5748 for (nhop_cursorPtr = _bcm_tr_mpls_nhop_headPtr[unit][hash_idx]; 5749 nhop_cursorPtr != NULL; nhop_cursorPtr = nhop_cursorPtr->link) { 5750 if (nhop_cursorPtr->egr_if == egr_if ) { 5751 for (vp_cursorPtr = nhop_cursorPtr->vp_head_ptr; vp_cursorPtr != NULL; vp_cursorPtr = vp_cursorPtr->link) { 5752 if (vp_cursorPtr->vp_nh_idx == nh_index) { 5753 return BCM_E_NONE; 5754 } 5755 } 5756 newVpNode = (_bcm_mpls_vp_nh_list_t *) sal_alloc (sizeof (_bcm_mpls_vp_nh_list_t), "VP NH Index"); 5757 if (NULL == newVpNode) { 5758 return (BCM_E_MEMORY); 5759 } 5760 newVpNode->vp_nh_idx = nh_index; 5761 newVpNode->link = nhop_cursorPtr->vp_head_ptr; 5762 nhop_cursorPtr->vp_head_ptr = newVpNode; 5763 return BCM_E_NONE; 5764 } 5765 } 5766 return BCM_E_NOT_FOUND; 5767 } 5768 5769 5770 /* 5771 * Function: 5772 * bcm_tr_mpls_update_vp_nh 5773 * Purpose: 5774 * Update NextHop Table indexed by VP NextHop index 5775 * Parameters: 5776 *unit - (IN) bcm device. 5777 * egr_index - (IN) NextHop Index of Parent Egr Object 5778 * Returns: 5779 * BCM_E_XXX 5780 */ 5781 5782 int 5783 bcm_tr_mpls_update_vp_nh ( int unit, bcm_if_t egr_if ) 5784 { 5785 _bcm_mpls_egr_nhopList_t *nhop_cursorPtr; 5786 _bcm_mpls_vp_nh_list_t *vp_cursorPtr; 5787 ing_l3_next_hop_entry_t ing_nh; 5788 egr_l3_next_hop_entry_t egr_nh; 5789 initial_ing_l3_next_hop_entry_t initial_ing_nh; 5790 _bcm_tr_ing_nh_info_t ing_nh_info; 5791 _bcm_tr_egr_nh_info_t egr_nh_info; 5792 bcm_l3_egress_t nh_info; 5793 void *entries[1]; 5794 int vp_index=-1; 5795 int egr_index=-1; 5796 int hash_idx=-1; 5797 int old_macda_idx=-1; 5798 uint32 flags=0; 5799 egr_mac_da_profile_entry_t macda; 5800 5801 (void) _bcm_tr_mpls_compute_nhop_hash (egr_if, &hash_idx); 5802 5803 5804 for (nhop_cursorPtr = _bcm_tr_mpls_nhop_headPtr[unit][hash_idx]; 5805 nhop_cursorPtr != NULL; nhop_cursorPtr = nhop_cursorPtr->link) { 5806 if (nhop_cursorPtr->egr_if == egr_if) { 5807 for (vp_cursorPtr = nhop_cursorPtr->vp_head_ptr; vp_cursorPtr != NULL; vp_cursorPtr = vp_cursorPtr->link) { 5808 vp_index = vp_cursorPtr->vp_nh_idx; 5809 5810 /* Get the Egress Hext Hop Index from the Egress Object Id without incrementing ref_count*/ 5811 BCM_IF_ERROR_RETURN(bcm_xgs3_get_nh_from_egress_object(unit, egr_if, &flags, 0, &egr_index)); 5812 5813 /* Read the egress next_hop entry pointed by EGRess-Object */ 5814 BCM_IF_ERROR_RETURN(bcm_xgs3_nh_get(unit, egr_index, &nh_info)); 5815 5816 /* Obtain the MPLS tunnel destination port information. */ 5817 if (nh_info.flags & BCM_L3_TGID) { 5818 ing_nh_info.port = -1; 5819 ing_nh_info.module = -1; 5820 ing_nh_info.trunk = nh_info.trunk; 5821 } else { 5822 BCM_IF_ERROR_RETURN(_bcm_esw_stk_modmap_map(unit, 5823 BCM_STK_MODMAP_SET, 5824 nh_info.module, nh_info.port, 5825 &nh_info.module, &nh_info.port)); 5826 ing_nh_info.port = nh_info.port; 5827 ing_nh_info.module = nh_info.module; 5828 ing_nh_info.trunk = -1; 5829 } 5830 egr_nh_info.intf_num = nh_info.intf; 5831 egr_nh_info.entry_type = 0x1; /* MPLS_MACDA_PROFILE */ 5832 5833 /* Read the existing egress next_hop entry pointed by VP NextHop Index */ 5834 BCM_IF_ERROR_RETURN (soc_mem_read(unit, EGR_L3_NEXT_HOPm, MEM_BLOCK_ALL, 5835 vp_index, &egr_nh)); 5836 5837 /* Delete existing MACDA_PROFILE */ 5838 if (soc_feature(unit, soc_feature_mpls_enhanced)) { 5839 old_macda_idx = soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, 5840 MPLS__MAC_DA_PROFILE_INDEXf); 5841 } else { 5842 old_macda_idx = soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, 5843 MAC_DA_PROFILE_INDEXf); 5844 } 5845 5846 if (old_macda_idx != -1) { 5847 BCM_IF_ERROR_RETURN 5848 (_bcm_mac_da_profile_entry_delete(unit, old_macda_idx)); 5849 } 5850 5851 /* Obtain new MACDA_PROFILE */ 5852 5853 sal_memset(&macda, 0, sizeof(egr_mac_da_profile_entry_t)); 5854 soc_mem_mac_addr_set(unit, EGR_MAC_DA_PROFILEm, 5855 &macda, MAC_ADDRESSf, nh_info.mac_addr); 5856 entries[0] = &macda; 5857 BCM_IF_ERROR_RETURN(_bcm_mac_da_profile_entry_add(unit, entries, 1, 5858 (uint32 *) &egr_nh_info.macda_index)); 5859 5860 /* Modify the Egress NextHop entry pointed by VP NextHop Index */ 5861 if (soc_feature(unit, soc_feature_mpls_enhanced)) { 5862 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 5863 MPLS__MAC_DA_PROFILE_INDEXf, egr_nh_info.macda_index); 5864 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 5865 MPLS__INTF_NUMf, egr_nh_info.intf_num); 5866 } else { 5867 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 5868 MAC_DA_PROFILE_INDEXf, egr_nh_info.macda_index); 5869 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 5870 INTF_NUMf, egr_nh_info.intf_num); 5871 } 5872 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 5873 nh_entry_type_field[unit], egr_nh_info.entry_type); 5874 5875 if ((_BCM_MPLS_MEPID_IN_VALID_RANGE(nh_info.oam_global_context_id)) && 5876 (soc_mem_field_valid(unit, EGR_L3_NEXT_HOPm, MPLS__MEPIDf))) { 5877 /* Writing MPLS LM/DM value. it doesnt matter since 5878 data packets are similar for BHH and MPLS LM/DM */ 5879 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 5880 MPLS__MPLS_OAM_DOWNMEP_ENABLEf, 2); 5881 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 5882 MPLS__MEPIDf, nh_info.oam_global_context_id); 5883 } 5884 5885 5886 /* Update HW Table Memory */ 5887 BCM_IF_ERROR_RETURN (soc_mem_write(unit, EGR_L3_NEXT_HOPm, 5888 MEM_BLOCK_ALL, vp_index, &egr_nh)); 5889 5890 5891 /* Read the existing Ingress next_hop entry pointed by VP NextHop Index */ 5892 BCM_IF_ERROR_RETURN (soc_mem_read(unit, ING_L3_NEXT_HOPm, MEM_BLOCK_ALL, 5893 vp_index, &ing_nh)); 5894 5895 /* Modify the Ingress NextHop entry pointed by VP NextHop Index */ 5896 if (ing_nh_info.trunk == -1) { 5897 if (soc_feature(unit, soc_feature_generic_dest)) { 5898 soc_mem_field32_dest_set(unit, ING_L3_NEXT_HOPm, &ing_nh, 5899 DESTINATIONf, SOC_MEM_FIF_DEST_LAG, 0); 5900 soc_mem_field32_dest_set(unit, ING_L3_NEXT_HOPm, &ing_nh, 5901 DESTINATIONf, SOC_MEM_FIF_DEST_DGPP, 5902 ing_nh_info.module << SOC_MEM_FIF_DGPP_MOD_ID_SHIFT_BITS | ing_nh_info.port); 5903 } else { 5904 soc_mem_field32_set(unit, ING_L3_NEXT_HOPm, 5905 &ing_nh, Tf, 0); 5906 soc_mem_field32_set(unit, ING_L3_NEXT_HOPm, 5907 &ing_nh, TGIDf, 0); 5908 soc_mem_field32_set(unit, ING_L3_NEXT_HOPm, 5909 &ing_nh, PORT_NUMf, ing_nh_info.port); 5910 soc_mem_field32_set(unit, ING_L3_NEXT_HOPm, 5911 &ing_nh, MODULE_IDf, ing_nh_info.module); 5912 } 5913 5914 } else { 5915 5916 if (soc_feature(unit, soc_feature_generic_dest)) { 5917 soc_mem_field32_dest_set(unit, ING_L3_NEXT_HOPm, &ing_nh, 5918 DESTINATIONf, SOC_MEM_FIF_DEST_DGPP, 0); 5919 soc_mem_field32_dest_set(unit, ING_L3_NEXT_HOPm, &ing_nh, 5920 DESTINATIONf, SOC_MEM_FIF_DEST_LAG, ing_nh_info.trunk); 5921 } else { 5922 soc_mem_field32_set(unit, ING_L3_NEXT_HOPm, 5923 &ing_nh, PORT_NUMf, 0); 5924 soc_mem_field32_set(unit, ING_L3_NEXT_HOPm, 5925 &ing_nh, MODULE_IDf, 0); 5926 soc_mem_field32_set(unit, ING_L3_NEXT_HOPm, 5927 &ing_nh, Tf, 1); 5928 soc_mem_field32_set(unit, ING_L3_NEXT_HOPm, 5929 &ing_nh, TGIDf, ing_nh_info.trunk); 5930 } 5931 } 5932 5933 /* Update HW Table Memory */ 5934 BCM_IF_ERROR_RETURN (soc_mem_write (unit, ING_L3_NEXT_HOPm, 5935 MEM_BLOCK_ALL, vp_index, &ing_nh)); 5936 5937 /* Read the existing Initial-Ingress next_hop entry pointed by VP NextHop Index */ 5938 BCM_IF_ERROR_RETURN (soc_mem_read(unit, INITIAL_ING_L3_NEXT_HOPm, MEM_BLOCK_ALL, 5939 vp_index, &initial_ing_nh)); 5940 5941 /* Modify the Initial-Ingress NextHop entry pointed by VP NextHop Index */ 5942 if (ing_nh_info.trunk == -1) { 5943 5944 if (soc_feature(unit, soc_feature_generic_dest)) { 5945 soc_mem_field32_dest_set(unit, INITIAL_ING_L3_NEXT_HOPm, &initial_ing_nh, 5946 DESTINATIONf, SOC_MEM_FIF_DEST_LAG, 0); 5947 soc_mem_field32_dest_set(unit, INITIAL_ING_L3_NEXT_HOPm, &initial_ing_nh, 5948 DESTINATIONf, SOC_MEM_FIF_DEST_DGPP, 5949 ing_nh_info.module << SOC_MEM_FIF_DGPP_MOD_ID_SHIFT_BITS | ing_nh_info.port); 5950 } else { 5951 soc_mem_field32_set(unit, INITIAL_ING_L3_NEXT_HOPm, 5952 &initial_ing_nh, PORT_NUMf, ing_nh_info.port); 5953 soc_mem_field32_set(unit, INITIAL_ING_L3_NEXT_HOPm, 5954 &initial_ing_nh, MODULE_IDf, ing_nh_info.module); 5955 soc_mem_field32_set(unit, INITIAL_ING_L3_NEXT_HOPm, 5956 &initial_ing_nh, Tf, 0); 5957 } 5958 } else { 5959 5960 if (soc_feature(unit, soc_feature_generic_dest)) { 5961 soc_mem_field32_dest_set(unit, INITIAL_ING_L3_NEXT_HOPm, &initial_ing_nh, 5962 DESTINATIONf, SOC_MEM_FIF_DEST_DGPP, 0); 5963 soc_mem_field32_dest_set(unit, INITIAL_ING_L3_NEXT_HOPm, &initial_ing_nh, 5964 DESTINATIONf, SOC_MEM_FIF_DEST_LAG, ing_nh_info.trunk); 5965 } else { 5966 soc_mem_field32_set(unit, INITIAL_ING_L3_NEXT_HOPm, 5967 &initial_ing_nh, Tf, 1); 5968 soc_mem_field32_set(unit, INITIAL_ING_L3_NEXT_HOPm, 5969 &initial_ing_nh, TGIDf, ing_nh_info.trunk); 5970 } 5971 } 5972 5973 /* Update HW Table Memory */ 5974 BCM_IF_ERROR_RETURN (soc_mem_write(unit, INITIAL_ING_L3_NEXT_HOPm, 5975 MEM_BLOCK_ALL, vp_index, &initial_ing_nh)); 5976 5977 } 5978 } 5979 } 5980 return BCM_E_NONE; 5981 } 5982 5983 /* 5984 * Function: 5985 * bcm_dump_mpls_port 5986 * Purpose: 5987 * Displays MPLS Port Structure Information 5988 * Parameters: 5989 * mpls_port - (IN) MPLS Port Structure 5990 * Returns: 5991 * None 5992 */ 5993 5994 5995 void 5996 bcm_dump_mpls_port (bcm_mpls_port_t *mpls_port) 5997 { 5998 LOG_CLI((BSL_META("\n MPLS Port ID: %d"), (bcm_gport_t) mpls_port->mpls_port_id)); 5999 LOG_CLI((BSL_META("\n Egress Tunnel If: %d"), 6000 (bcm_if_t) mpls_port->egress_tunnel_if)); 6001 LOG_CLI((BSL_META("\n flags: %X"), mpls_port->flags)); 6002 LOG_CLI((BSL_META("\n service_tpid: %d"), mpls_port->service_tpid)); 6003 LOG_CLI((BSL_META("\n match_vlan: %d"), mpls_port->match_vlan)); 6004 LOG_CLI((BSL_META("\n mpls_label: %d"), (bcm_mpls_label_t) mpls_port->match_label)); 6005 LOG_CLI((BSL_META("\n encap_id: %d"), (bcm_if_t) mpls_port->encap_id)); 6006 } 6007 6008 /* 6009 * Function: * Function: 6010 * _bcm_tr_mpls_dump_egrNhop 6011 * Purpose: 6012 * Dump Egr NextHop List 6013 * Parameters: 6014 * unit - (IN) bcm device. 6015 * vp_idx - (IN) VP NextHop Index 6016 * Returns: 6017 * BCM_E_XXX 6018 */ 6019 6020 void 6021 _bcm_tr_mpls_dump_egrNhop (int unit) 6022 { 6023 _bcm_mpls_egr_nhopList_t *nhop_cursorPtr; 6024 _bcm_mpls_vp_nh_list_t *vp_cursorPtr; 6025 int index; 6026 6027 for(index=0; index < _BCM_TR_MPLS_HASH_ELEMENTS; ++index) { 6028 if (_bcm_tr_mpls_nhop_headPtr[unit][index] != NULL) { 6029 for (nhop_cursorPtr = _bcm_tr_mpls_nhop_headPtr[unit][index]; 6030 nhop_cursorPtr != NULL; nhop_cursorPtr = nhop_cursorPtr->link) { 6031 LOG_CLI((BSL_META_U(unit, 6032 "\n Egress Tunnel If: %d"), 6033 (bcm_if_t) nhop_cursorPtr->egr_if)); 6034 for (vp_cursorPtr = nhop_cursorPtr->vp_head_ptr; 6035 vp_cursorPtr != NULL; vp_cursorPtr = vp_cursorPtr->link) { 6036 LOG_CLI((BSL_META_U(unit, 6037 "\n VP Nhop Idx= %d"), 6038 vp_cursorPtr->vp_nh_idx)); 6039 } 6040 } 6041 } 6042 } 6043 } 6044 6045 6046 /* 6047 * Function: 6048 * _bcm_tr_mpls_add_egrNhop 6049 * Purpose: 6050 * Add Nhop information into a Hash-Table 6051 * Parameters: 6052 * unit - (IN) bcm device. 6053 * egress_if - (IN) Egress Tunnel If 6054 * Returns: 6055 * BCM_E_XXX 6056 */ 6057 6058 STATIC int 6059 _bcm_tr_mpls_add_egrNhop ( int unit, bcm_if_t egress_if) 6060 { 6061 _bcm_mpls_egr_nhopList_t *newNhopNode; 6062 _bcm_mpls_egr_nhopList_t *nhop_cursorPtr; 6063 int hash_idx; 6064 6065 (void) _bcm_tr_mpls_compute_nhop_hash (egress_if, &hash_idx); 6066 /* Does the Node exist? */ 6067 for (nhop_cursorPtr = _bcm_tr_mpls_nhop_headPtr[unit][hash_idx]; 6068 nhop_cursorPtr != NULL; nhop_cursorPtr = nhop_cursorPtr->link) { 6069 if (nhop_cursorPtr->egr_if == egress_if) { 6070 return (BCM_E_NONE); 6071 } 6072 } 6073 6074 newNhopNode = (_bcm_mpls_egr_nhopList_t *) 6075 sal_alloc (sizeof (_bcm_mpls_egr_nhopList_t), "MPLS Egr Nhop"); 6076 if (NULL == newNhopNode) { 6077 return (BCM_E_MEMORY); 6078 } 6079 newNhopNode->egr_if = (bcm_if_t) egress_if; 6080 newNhopNode->vp_head_ptr = ( _bcm_mpls_vp_nh_list_t *) NULL; 6081 newNhopNode->link = _bcm_tr_mpls_nhop_headPtr[unit][hash_idx]; 6082 _bcm_tr_mpls_nhop_headPtr[unit][hash_idx] = newNhopNode; 6083 return BCM_E_NONE; 6084 } 6085 6086 6087 /* 6088 * Function: 6089 * _bcm_tr_mpls_delete_egrNhop 6090 * Purpose: 6091 * Delete MPLS Egress NHOP from Hash-table 6092 * Parameters: 6093 * unit - (IN) bcm device. 6094 * egress_if - (IN) Egress Tunnel If 6095 * Returns: 6096 * BCM_E_XXX 6097 */ 6098 6099 STATIC int 6100 _bcm_tr_mpls_delete_egrNhop (int unit, bcm_if_t egress_if ) 6101 { 6102 _bcm_mpls_egr_nhopList_t *nhop_cursorPtr; 6103 _bcm_mpls_egr_nhopList_t *removeNode; 6104 int hash_idx; 6105 6106 (void) _bcm_tr_mpls_compute_nhop_hash (egress_if, &hash_idx); 6107 6108 removeNode = _bcm_tr_mpls_nhop_headPtr[unit][hash_idx]; 6109 if (removeNode != NULL) { 6110 if (removeNode->egr_if == egress_if) { 6111 if (removeNode->vp_head_ptr == NULL) { 6112 _bcm_tr_mpls_nhop_headPtr[unit][hash_idx] = removeNode->link; 6113 sal_free (removeNode); 6114 return BCM_E_NONE; 6115 } else { 6116 return BCM_E_BUSY; 6117 } 6118 } else { 6119 for (nhop_cursorPtr = _bcm_tr_mpls_nhop_headPtr[unit][hash_idx]; 6120 nhop_cursorPtr->link != NULL; nhop_cursorPtr = nhop_cursorPtr->link) { 6121 if (nhop_cursorPtr->link->egr_if == egress_if) { 6122 if (nhop_cursorPtr->link->vp_head_ptr == NULL) { 6123 removeNode = nhop_cursorPtr->link; 6124 nhop_cursorPtr->link = removeNode->link; 6125 sal_free (removeNode); 6126 return BCM_E_NONE; 6127 } else { 6128 return BCM_E_BUSY; 6129 } 6130 } 6131 } 6132 } 6133 } 6134 return BCM_E_NOT_FOUND; 6135 } 6136 6137 /* 6138 * Function: 6139 * _bcm_tr_mpls_delete_vp_nh 6140 * Purpose: 6141 * Delete VP NextHop information from List 6142 * Parameters: 6143 * unit - (IN) bcm device. 6144 * vp_idx - (IN) VP NextHop Index 6145 * egress_if - (IN) Egress Tunnel If 6146 * Returns: 6147 * BCM_E_XXX 6148 */ 6149 6150 STATIC int 6151 _bcm_tr_mpls_delete_vp_nh ( int unit, int vp_idx, bcm_if_t egress_if) 6152 { 6153 _bcm_mpls_egr_nhopList_t *nhop_cursorPtr; 6154 _bcm_mpls_vp_nh_list_t *vp_cursorPtr; 6155 _bcm_mpls_vp_nh_list_t *vpRemoveNode; 6156 int hash_idx; 6157 6158 (void) _bcm_tr_mpls_compute_nhop_hash (egress_if, &hash_idx); 6159 6160 for (nhop_cursorPtr = _bcm_tr_mpls_nhop_headPtr[unit][hash_idx]; 6161 nhop_cursorPtr != NULL; nhop_cursorPtr = nhop_cursorPtr->link) { 6162 vp_cursorPtr = nhop_cursorPtr->vp_head_ptr; 6163 if (vp_cursorPtr != NULL) { 6164 if (vp_cursorPtr->vp_nh_idx == vp_idx) { 6165 nhop_cursorPtr->vp_head_ptr = vp_cursorPtr->link; 6166 sal_free (vp_cursorPtr); 6167 if (nhop_cursorPtr->vp_head_ptr == NULL) { 6168 BCM_IF_ERROR_RETURN( 6169 _bcm_tr_mpls_delete_egrNhop (unit, nhop_cursorPtr->egr_if)); 6170 } 6171 return BCM_E_NONE; 6172 } else { 6173 for ( ; vp_cursorPtr->link != NULL; vp_cursorPtr = vp_cursorPtr->link){ 6174 if (vp_cursorPtr->link->vp_nh_idx == vp_idx) { 6175 vpRemoveNode = vp_cursorPtr->link; 6176 vp_cursorPtr->link = vpRemoveNode->link; 6177 sal_free (vpRemoveNode); 6178 return BCM_E_NONE; 6179 } 6180 } 6181 } 6182 } 6183 } 6184 return BCM_E_NOT_FOUND; 6185 } 6186 6187 /* 6188 * Function: 6189 * _bcm_tr_mpls_cleanup_egrNhop 6190 * Purpose: 6191 * Cleanup MPLS Egress NHOP from Hash-table 6192 * Parameters: 6193 * unit - (IN) bcm device. 6194 * Returns: 6195 * BCM_E_XXX 6196 */ 6197 6198 STATIC void 6199 _bcm_tr_mpls_cleanup_egrNhop (int unit) 6200 { 6201 _bcm_mpls_egr_nhopList_t *nhop_cursorPtr; 6202 _bcm_mpls_vp_nh_list_t *vp_cursorPtr; 6203 int index; 6204 6205 for(index=0; index < _BCM_TR_MPLS_HASH_ELEMENTS; ++index) { 6206 if (_bcm_tr_mpls_nhop_headPtr[unit][index] != NULL) { 6207 nhop_cursorPtr = _bcm_tr_mpls_nhop_headPtr[unit][index]; 6208 while ( nhop_cursorPtr != NULL ) { 6209 vp_cursorPtr = nhop_cursorPtr->vp_head_ptr; 6210 while (vp_cursorPtr != NULL) { 6211 (void)_bcm_tr_mpls_delete_vp_nh (unit, vp_cursorPtr->vp_nh_idx, 6212 nhop_cursorPtr->egr_if); 6213 nhop_cursorPtr = _bcm_tr_mpls_nhop_headPtr[unit][index]; 6214 if (nhop_cursorPtr != NULL) { 6215 vp_cursorPtr = nhop_cursorPtr->vp_head_ptr; 6216 } else { 6217 vp_cursorPtr = NULL; 6218 } 6219 } 6220 } 6221 } 6222 } 6223 } 6224 6225 /* 6226 * Function: * Function: 6227 * bcm_tr_mpls_get_vp_nh 6228 * Purpose: 6229 * Find whether VP NextHop is present within list 6230 * Parameters: 6231 * unit - (IN) bcm device. 6232 * vp_idx - (IN) VP NextHop Index 6233 * egress_if - (OUT) Egr_If 6234 * Returns: 6235 * BCM_E_XXX 6236 */ 6237 6238 int 6239 bcm_tr_mpls_get_vp_nh (int unit, int vp_index, bcm_if_t *egress_if) 6240 { 6241 _bcm_mpls_egr_nhopList_t *nhop_cursorPtr; 6242 _bcm_mpls_vp_nh_list_t *vp_cursorPtr; 6243 int index; 6244 6245 for(index=0; index < _BCM_TR_MPLS_HASH_ELEMENTS; ++index) { 6246 if (_bcm_tr_mpls_nhop_headPtr[unit][index] != NULL) { 6247 for (nhop_cursorPtr = _bcm_tr_mpls_nhop_headPtr[unit][index]; 6248 nhop_cursorPtr != NULL; nhop_cursorPtr = nhop_cursorPtr->link) { 6249 for (vp_cursorPtr = nhop_cursorPtr->vp_head_ptr; 6250 vp_cursorPtr != NULL; vp_cursorPtr = vp_cursorPtr->link) { 6251 if (vp_index == vp_cursorPtr->vp_nh_idx) { 6252 *egress_if = nhop_cursorPtr->egr_if; 6253 return BCM_E_NONE; 6254 } 6255 } 6256 } 6257 } 6258 } 6259 return BCM_E_NOT_FOUND; 6260 } 6261 6262 /* 6263 * Function: * Function: 6264 * _bcm_tr_mpls_create_vp_nh 6265 * Purpose: 6266 * Allocate MPLS VP NextHop index entry 6267 * Parameters: 6268 * unit - (IN) bcm device. 6269 * egress_if - (IN) Egr_If 6270 * vp_nh_index - (OUT) NextHop Index 6271 * Returns: 6272 * BCM_E_XXX 6273 */ 6274 6275 STATIC int 6276 _bcm_tr_mpls_create_vp_nh ( int unit, bcm_if_t egress_tunnel_if, 6277 int *vp_nh_index, bcm_mpls_port_t *mpls_port) 6278 { 6279 int rv; 6280 bcm_l3_egress_t nh_info; 6281 uint32 nh_flags; 6282 int flags = mpls_port->flags; 6283 int failover_nh_index = -1; 6284 int failover_vp; 6285 int i = 0; 6286 int num_elements = 1; 6287 ing_dvp_table_entry_t failover_dvp; 6288 /* 6289 * Allocate MPLS VP next-hop entry. By calling bcm_xgs3_nh_add() 6290 * with _BCM_L3_SHR_WRITE_DISABLE flag, a next-hop index is 6291 * allocated but nothing is written to hardware. The "nh_info" 6292 * in this case is not used, so just set to all zeros. 6293 */ 6294 6295 bcm_l3_egress_t_init(&nh_info); 6296 6297 nh_info.failover_id = mpls_port->failover_id; 6298 nh_info.failover_mc_group = mpls_port->failover_mc_group; 6299 6300 failover_vp = BCM_GPORT_MPLS_PORT_ID_GET(mpls_port->failover_port_id); 6301 if (failover_vp !=-1) { 6302 BCM_IF_ERROR_RETURN(READ_ING_DVP_TABLEm( 6303 unit, MEM_BLOCK_ANY, failover_vp, &failover_dvp)); 6304 6305 failover_nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &failover_dvp, 6306 NEXT_HOP_INDEXf); 6307 failover_nh_index += BCM_XGS3_DVP_EGRESS_IDX_MIN(unit); 6308 } 6309 6310 nh_info.failover_if_id = failover_nh_index; 6311 6312 nh_flags = _BCM_L3_SHR_MATCH_DISABLE | _BCM_L3_SHR_WRITE_DISABLE; 6313 if (flags & BCM_MPLS_PORT_ENCAP_WITH_ID) { 6314 nh_flags |= _BCM_L3_SHR_WITH_ID | _BCM_L3_SHR_UPDATE; 6315 } 6316 BCM_IF_ERROR_RETURN(bcm_xgs3_nh_add(unit, nh_flags, &nh_info, vp_nh_index)); 6317 6318 rv = _bcm_tr_mpls_add_egrNhop (unit, egress_tunnel_if); 6319 if (rv < 0) { 6320 num_elements = bcmi_l3_nh_multi_count_get(unit, *vp_nh_index); 6321 for (; i<num_elements; i++) { 6322 (void) bcm_xgs3_nh_del(unit, _BCM_L3_SHR_WRITE_DISABLE, *vp_nh_index+i); 6323 } 6324 return rv; 6325 } 6326 6327 rv = _bcm_tr_mpls_add_vp_nh (unit, egress_tunnel_if, *vp_nh_index); 6328 if (rv < 0) { 6329 num_elements = bcmi_l3_nh_multi_count_get(unit, *vp_nh_index); 6330 for (; i<num_elements; i++) { 6331 (void) bcm_xgs3_nh_del(unit, _BCM_L3_SHR_WRITE_DISABLE, *vp_nh_index+i); 6332 } 6333 (void) _bcm_tr_mpls_delete_egrNhop (unit, egress_tunnel_if); 6334 } 6335 6336 return rv; 6337 } 6338 6339 #ifdef BCM_KATANA_SUPPORT 6340 /* 6341 * Function: 6342 * _bcm_tr_mpls_ing_queue_map_ref_count_adjust 6343 * Purpose: 6344 * Increment / Decrement Reference Count for Ingress Queue Map 6345 * Parameters: 6346 * unit Unit number 6347 * index (IN) Entry Index 6348 * step (IN) usage reference 6349 */ 6350 6351 STATIC void 6352 _bcm_tr_mpls_ing_queue_map_ref_count_adjust (int unit, int index, int step) 6353 { 6354 _bcm_tr_mpls_bookkeeping_t *mpls_info = MPLS_INFO(unit); 6355 6356 if (( mpls_info->ing_qmap_ref_count[index] == 0 ) && (step < 0)) { 6357 mpls_info->ing_qmap_ref_count[index] = 0; 6358 } else { 6359 mpls_info->ing_qmap_ref_count[index] += step; 6360 } 6361 } 6362 6363 /* 6364 * Function: 6365 * _bcm_tr_mpls_ing_queue_map_index_reset 6366 * Purpose: 6367 * Reset ING_QUEUE_MAP_TABLE entry 6368 * Parameters: 6369 * IN : Unit 6370 * IN : ing_queue_map_index 6371 * Returns: 6372 * BCM_E_XXX 6373 */ 6374 STATIC int 6375 _bcm_tr_mpls_ing_queue_map_index_reset (int unit, int ing_queue_map_index) 6376 { 6377 ing_queue_map_entry_t ing_queue_entry; 6378 int rv = BCM_E_NONE; 6379 _bcm_tr_mpls_bookkeeping_t *mpls_info = MPLS_INFO(unit); 6380 6381 if ( mpls_info->ing_qmap_ref_count[ing_queue_map_index] != 0 ) { 6382 return BCM_E_NONE; 6383 } 6384 6385 sal_memset(&ing_queue_entry, 0, 6386 sizeof(ing_queue_map_entry_t)); 6387 6388 rv = BCM_XGS3_MEM_WRITE(unit, ING_QUEUE_MAPm, 6389 ing_queue_map_index, &ing_queue_entry); 6390 6391 return rv; 6392 } 6393 #endif /* BCM_KATANA_SUPPORT */ 6394 6395 #if defined(BCM_TRIUMPH3_SUPPORT) 6396 /* 6397 * Function: 6398 * _bcm_tr_mpls_vc_swap_table_hash_nhop_alloc 6399 * Purpose: 6400 * Allocate an nhop entry for vc and swap hash 6401 * Parameters: 6402 * unit - (IN) Device Number 6403 * nh_index -(IN) Next hop index 6404 * Returns: 6405 * The pointer of nhop entry 6406 */ 6407 6408 bcm_tr_mpls_vc_swap_table_nhop_list_t * 6409 _bcm_tr_mpls_vc_swap_table_hash_nhop_alloc(int unit, int nh_index) 6410 { 6411 bcm_tr_mpls_vc_swap_table_nhop_list_t *ptr; 6412 ptr = sal_alloc(sizeof(bcm_tr_mpls_vc_swap_table_nhop_list_t), 6413 "vc and swap table hash nhop list"); 6414 sal_memset(ptr, 0, sizeof(bcm_tr_mpls_vc_swap_table_nhop_list_t)); 6415 6416 ptr->nh_index = nh_index; 6417 ptr->next = NULL; 6418 6419 return ptr; 6420 } 6421 /* 6422 * Function: 6423 * _bcm_tr_mpls_vc_and_swap_hash_nhop_delete 6424 * Purpose: 6425 * Delete an nhop entry from vc and swap hash 6426 * Parameters: 6427 * unit - (IN) Device Number 6428 * vc_swap_index -(IN) Vc and swap table index 6429 * nh_index -(IN) Next hop index 6430 * Returns: 6431 * BCM_E_XXX 6432 */ 6433 STATIC int 6434 _bcm_tr_mpls_vc_and_swap_hash_nhop_delete (int unit, int vc_swap_index, 6435 int nh_index) 6436 { 6437 int hash_idx; 6438 bcm_tr_mpls_vc_swap_table_hash_t *hash_input; 6439 bcm_tr_mpls_vc_swap_table_hash_entry_t *temp_hash; 6440 bcm_tr_mpls_vc_swap_table_nhop_list_t *temp_nhop, *prev_nhop; 6441 egr_mpls_vc_and_swap_label_table_entry_t vc_entry; 6442 int action = 0; 6443 6444 /* Entry 0 is reserved with _bcm_tr_mpls_default_entry_setup during init */ 6445 if (vc_swap_index == VC_AND_SWAP_TABLE_RESV_INDEX) { 6446 LOG_INFO(BSL_LS_BCM_L3, 6447 (BSL_META_U(unit,"Not resetting reserved index: %d in " 6448 "VC AND SWAP TABLE\n"), VC_AND_SWAP_TABLE_RESV_INDEX)); 6449 return BCM_E_NONE; 6450 } 6451 6452 BCM_IF_ERROR_RETURN( 6453 soc_mem_read(unit, 6454 EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 6455 MEM_BLOCK_ALL, vc_swap_index, &vc_entry)); 6456 6457 #ifdef BCM_TRIDENT3_SUPPORT 6458 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 6459 if (MPLS_INFO(unit)->egr_vc_swap_lbl_action != NULL) { 6460 action = MPLS_INFO(unit)->egr_vc_swap_lbl_action[vc_swap_index]; 6461 } 6462 } else 6463 #endif 6464 { 6465 action = 0; 6466 } 6467 6468 BCM_IF_ERROR_RETURN( 6469 bcmi_tr_mpls_vc_swap_hash_index_get(unit, NULL, action, NULL, NULL, 6470 &vc_entry, &hash_idx)); 6471 hash_input = &(bcmi_vc_swap_label_hash[unit][hash_idx]); 6472 temp_hash = hash_input->head_link; 6473 while (temp_hash) { 6474 if (temp_hash->index == vc_swap_index) { 6475 temp_nhop = prev_nhop = temp_hash->nhop_list; 6476 while (temp_nhop) { 6477 if (temp_nhop->nh_index == nh_index) { 6478 if (temp_nhop == temp_hash->nhop_list) { 6479 temp_hash->nhop_list = temp_nhop->next; 6480 } else { 6481 prev_nhop->next = temp_nhop->next; 6482 } 6483 sal_free(temp_nhop); 6484 return BCM_E_NONE; 6485 } 6486 prev_nhop = temp_nhop; 6487 temp_nhop = temp_nhop->next; 6488 } 6489 return BCM_E_NOT_FOUND; 6490 } 6491 temp_hash = temp_hash->link; 6492 } 6493 return BCM_E_NOT_FOUND; 6494 } 6495 /* 6496 * Function: 6497 * _bcm_tr_mpls_vc_and_swap_hash_nhop_add 6498 * Purpose: 6499 * Add an nhop entry to vc and swap hash 6500 * Parameters: 6501 * unit - (IN) Device Number 6502 * vc_swap_index -(IN) Vc and swap table index 6503 * nh_index -(IN) Next hop index 6504 * Returns: 6505 * BCM_E_XXX 6506 */ 6507 6508 STATIC int 6509 _bcm_tr_mpls_vc_and_swap_hash_nhop_add (int unit, int vc_swap_index, 6510 int nh_index) 6511 { 6512 int hash_idx; 6513 bcm_tr_mpls_vc_swap_table_hash_t *hash_input; 6514 bcm_tr_mpls_vc_swap_table_hash_entry_t *temp_hash; 6515 bcm_tr_mpls_vc_swap_table_nhop_list_t *new_entry; 6516 bcm_tr_mpls_vc_swap_table_nhop_list_t *temp_nhop, *prev_nhop; 6517 egr_mpls_vc_and_swap_label_table_entry_t vc_entry; 6518 6519 BCM_IF_ERROR_RETURN( 6520 soc_mem_read(unit, 6521 EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 6522 MEM_BLOCK_ALL, vc_swap_index, &vc_entry)); 6523 6524 BCM_IF_ERROR_RETURN( 6525 bcmi_tr_mpls_vc_swap_hash_index_get(unit, NULL, 0, NULL, NULL, 6526 &vc_entry, &hash_idx)); 6527 6528 new_entry = _bcm_tr_mpls_vc_swap_table_hash_nhop_alloc(unit, nh_index); 6529 if (new_entry == NULL) { 6530 return BCM_E_MEMORY; 6531 } 6532 hash_input = &(bcmi_vc_swap_label_hash[unit][hash_idx]); 6533 temp_hash = hash_input->head_link; 6534 while (temp_hash) { 6535 if (temp_hash->index == vc_swap_index) { 6536 temp_nhop = prev_nhop = temp_hash->nhop_list; 6537 while (temp_nhop) { 6538 prev_nhop = temp_nhop; 6539 temp_nhop = temp_nhop->next; 6540 } 6541 if (prev_nhop == temp_nhop) { 6542 temp_hash->nhop_list = new_entry; 6543 } else { 6544 prev_nhop->next = new_entry; 6545 } 6546 return BCM_E_NONE; 6547 } 6548 temp_hash = temp_hash->link; 6549 } 6550 /* No entry was found, return BCM_E_NOT_FOUND */ 6551 sal_free(new_entry); 6552 return BCM_E_NOT_FOUND; 6553 } 6554 #endif /* BCM_TRIUMPH3_SUPPORT*/ 6555 /* 6556 * Function: 6557 * _bcm_tr_mpls_vc_and_swap_ref_count_adjust 6558 * Purpose: 6559 * Increment / Decrement Reference Count for VC usage 6560 * Parameters: 6561 * unit Unit number 6562 * index (IN) Entry Index 6563 * step (IN) usage reference 6564 */ 6565 6566 void 6567 _bcm_tr_mpls_vc_and_swap_ref_count_adjust (int unit, int index, int step) 6568 { 6569 _bcm_tr_mpls_bookkeeping_t *mpls_info = MPLS_INFO(unit); 6570 6571 if (( mpls_info->vc_swap_ref_count[index] == 0 ) && (step < 0)) { 6572 mpls_info->vc_swap_ref_count[index] = 0; 6573 } else { 6574 mpls_info->vc_swap_ref_count[index] += step; 6575 } 6576 6577 } 6578 6579 STATIC void 6580 _bcm_tr_mpls_vc_and_swap_ref_count_get(int unit, int index, int *cnt_value) 6581 { 6582 _bcm_tr_mpls_bookkeeping_t *mpls_info = MPLS_INFO(unit); 6583 *cnt_value = mpls_info->vc_swap_ref_count[index]; 6584 } 6585 6586 STATIC void 6587 _bcm_tr_mpls_vc_and_swap_ref_count_reset(int unit, int index) 6588 { 6589 _bcm_tr_mpls_bookkeeping_t *mpls_info = MPLS_INFO(unit); 6590 mpls_info->vc_swap_ref_count[index] = 0; 6591 } 6592 /* 6593 * Function: 6594 * bcmi_tr_mpls_vc_swap_hash_key_get 6595 * Purpose: 6596 * Generate hash key from incoming entry 6597 * Parameters: 6598 * IN : Unit 6599 * IN : mpls port entry 6600 * IN : next hop entry 6601 * IN : action 6602 * IN : VC table entry 6603 * IN : key buffer to be filled in 6604 * Returns: 6605 * BCM_E_XXX 6606 */ 6607 int 6608 bcmi_tr_mpls_vc_swap_hash_key_get(int unit, bcm_mpls_port_t *mpls_port, 6609 bcm_mpls_tunnel_switch_t *info, 6610 bcm_l3_egress_t *egr_obj, int action, 6611 egr_mpls_vc_and_swap_label_table_entry_t *vc_entry, 6612 int *key) 6613 { 6614 6615 if (key == NULL) { 6616 return BCM_E_INTERNAL; 6617 } 6618 /* make sure that key is zeroed out from wherever it is coming. */ 6619 sal_memset(key, 0, sizeof(int) * BCM_TR_MPLS_VC_SWAP_KEY_LEN_IN_WORDS); 6620 6621 /* Get hash key from various mpls_port, label info, egress_obj, hw_entry. 6622 below is the key. 6623 key[0] = label 6624 key[1] = action 6625 6626 All the fields will default to 0 if not present. 6627 */ 6628 if (mpls_port != NULL) { 6629 key[0] = mpls_port->egress_label.label; 6630 key[1] = action; 6631 6632 } else if (info !=NULL) { 6633 6634 key[0] = info->egress_label.label; 6635 key[1] = action; 6636 6637 } else if (egr_obj != NULL) { 6638 key[0] = egr_obj->mpls_label; 6639 key[1] = action; 6640 } else if (vc_entry != NULL) { 6641 key[0] = SOC_MEM_VC_SWAP_F32_GET(unit, 6642 EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 6643 vc_entry, MPLS_LABELf); 6644 6645 #ifdef BCM_TRIDENT3_SUPPORT 6646 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 6647 key[1] = action; 6648 } else 6649 #endif 6650 { 6651 key[1] = SOC_MEM_VC_SWAP_F32_GET(unit, 6652 EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 6653 vc_entry, MPLS_LABEL_ACTIONf); 6654 } 6655 6656 } 6657 #if defined(BCM_SWAP_TO_SELF_SUPPORT) 6658 if (soc_feature(unit, soc_feature_mpls_swap_label_preserve)) { 6659 if (key[1] == _BCM_MPLS_ACTION_PRESERVED) { 6660 key[0] = 0; 6661 return BCM_E_NONE; 6662 } 6663 } 6664 #endif 6665 6666 /* if the label is invalid then set the key as 0 */ 6667 if (key[0] == BCM_MPLS_LABEL_INVALID) { 6668 key[0] = 0; 6669 key[1] = _BCM_MPLS_ACTION_NOOP; 6670 } 6671 6672 return BCM_E_NONE; 6673 } 6674 6675 /* 6676 * Function: 6677 * _bcm_tr_mpls_vc_swap_compare 6678 * Purpose: 6679 * Compare two incoming entries 6680 * Parameters: 6681 * IN : Unit 6682 * IN : mpls port entry 6683 * IN : next hop entry 6684 * IN : action 6685 * IN : VC table entry 6686 6687 * Returns: 6688 * BCM_E_XXX 6689 */ 6690 STATIC int 6691 _bcm_tr_mpls_vc_swap_compare(int unit, bcm_mpls_port_t *mpls_port, 6692 bcm_mpls_tunnel_switch_t *info, 6693 bcm_l3_egress_t *egr_obj, 6694 egr_mpls_vc_and_swap_label_table_entry_t *in_vc_entry, 6695 int label_action, 6696 egr_mpls_vc_and_swap_label_table_entry_t *vc_entry) 6697 { 6698 bcm_mpls_label_t entry_label; 6699 uint32 ttl, entry_label_action, cw, exp; 6700 uint32 cfi, pri; 6701 uint32 sd_tag, sd_tag_action_present, sd_tag_action_not_present; 6702 uint32 exp_select, pri_mapping_ptr; 6703 int map_inx; 6704 6705 if (mpls_port != NULL) { 6706 entry_label = SOC_MEM_VC_SWAP_F32_GET(unit, 6707 EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 6708 vc_entry, MPLS_LABELf); 6709 if (entry_label != mpls_port->egress_label.label) { 6710 return BCM_E_NOT_FOUND; 6711 } 6712 entry_label_action = SOC_MEM_VC_SWAP_F32_GET(unit, 6713 EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,vc_entry, 6714 MPLS_LABEL_ACTIONf); 6715 if (label_action != entry_label_action) { 6716 return BCM_E_NOT_FOUND; 6717 } 6718 ttl = SOC_MEM_VC_SWAP_F32_GET(unit, 6719 EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 6720 vc_entry, MPLS_TTLf); 6721 if (mpls_port->egress_label.flags & BCM_MPLS_EGRESS_LABEL_TTL_SET && 6722 ttl != mpls_port->egress_label.ttl) { 6723 return BCM_E_NOT_FOUND; 6724 } 6725 cw = SOC_MEM_VC_SWAP_F32_GET(unit, 6726 EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 6727 vc_entry, CW_INSERT_FLAGf); 6728 if (mpls_port->flags & BCM_MPLS_PORT_SEQUENCED && cw != 0x2) { 6729 return BCM_E_NOT_FOUND; 6730 } else if (mpls_port->flags & BCM_MPLS_PORT_CONTROL_WORD && cw != 0x1) { 6731 return BCM_E_NOT_FOUND; 6732 } else if ((cw != 0) && 6733 (!(mpls_port->flags & BCM_MPLS_PORT_CONTROL_WORD) && 6734 !(mpls_port->flags & BCM_MPLS_PORT_SEQUENCED))) { 6735 return BCM_E_NOT_FOUND; 6736 } 6737 exp = SOC_MEM_VC_SWAP_F32_GET(unit, 6738 EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 6739 vc_entry, MPLS_EXPf); 6740 pri = SOC_MEM_VC_SWAP_F32_GET(unit, 6741 EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 6742 vc_entry, NEW_PRIf); 6743 cfi = SOC_MEM_VC_SWAP_F32_GET(unit, 6744 EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 6745 vc_entry, NEW_CFIf); 6746 if ((mpls_port->egress_label.flags & BCM_MPLS_EGRESS_LABEL_EXP_SET) || 6747 (mpls_port->egress_label.flags & BCM_MPLS_EGRESS_LABEL_PRI_SET)) { 6748 if (exp != mpls_port->egress_label.exp) { 6749 return BCM_E_NOT_FOUND; 6750 } 6751 if (pri != mpls_port->egress_label.pkt_pri) { 6752 return BCM_E_NOT_FOUND; 6753 } 6754 if (cfi != mpls_port->egress_label.pkt_cfi) { 6755 return BCM_E_NOT_FOUND; 6756 } 6757 } else if (exp || pri || cfi) { 6758 return BCM_E_NOT_FOUND; 6759 } 6760 sd_tag = SOC_MEM_VC_SWAP_F32_GET(unit, 6761 EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 6762 vc_entry, SD_TAG_VIDf); 6763 sd_tag_action_present = SOC_MEM_VC_SWAP_F32_GET(unit, 6764 EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 6765 vc_entry, SD_TAG_ACTION_IF_PRESENTf); 6766 sd_tag_action_not_present = SOC_MEM_VC_SWAP_F32_GET(unit, 6767 EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 6768 vc_entry, SD_TAG_ACTION_IF_NOT_PRESENTf); 6769 if (mpls_port->flags & BCM_MPLS_PORT_SERVICE_VLAN_ADD) { 6770 if (sd_tag != mpls_port->egress_service_vlan || 6771 sd_tag_action_not_present != 0x1) { 6772 return BCM_E_NOT_FOUND; 6773 } 6774 } else if (mpls_port->flags & BCM_MPLS_PORT_SERVICE_VLAN_TPID_REPLACE) { 6775 if (sd_tag != mpls_port->egress_service_vlan || 6776 sd_tag_action_present != 0x1) { 6777 return BCM_E_NOT_FOUND; 6778 } 6779 } else if (mpls_port->flags & BCM_MPLS_PORT_SERVICE_VLAN_REPLACE) { 6780 if (sd_tag != mpls_port->egress_service_vlan || 6781 sd_tag_action_present != 0x2) { 6782 return BCM_E_NOT_FOUND; 6783 } 6784 } else if (mpls_port->flags & BCM_MPLS_PORT_SERVICE_VLAN_DELETE) { 6785 if (sd_tag_action_present != 0x3) { 6786 return BCM_E_NOT_FOUND; 6787 } 6788 } else if (mpls_port->flags & BCM_MPLS_PORT_SERVICE_VLAN_PRI_TPID_REPLACE) { 6789 if (sd_tag_action_present != 0x4) { 6790 return BCM_E_NOT_FOUND; 6791 } 6792 } else if (mpls_port->flags & BCM_MPLS_PORT_SERVICE_VLAN_PRI_REPLACE) { 6793 if (sd_tag_action_present != 0x5) { 6794 return BCM_E_NOT_FOUND; 6795 } 6796 } else if (mpls_port->flags & BCM_MPLS_PORT_SERVICE_PRI_REPLACE) { 6797 if (sd_tag_action_present != 0x6) { 6798 return BCM_E_NOT_FOUND; 6799 } 6800 } else if (mpls_port->flags & BCM_MPLS_PORT_SERVICE_TPID_REPLACE) { 6801 if (sd_tag_action_present != 0x7) { 6802 return BCM_E_NOT_FOUND; 6803 } 6804 } else if (sd_tag_action_present) { 6805 return BCM_E_NOT_FOUND; 6806 } 6807 6808 #ifdef BCM_TRIDENT3_SUPPORT 6809 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 6810 if (soc_mem_field32_get(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 6811 vc_entry, SPECIAL_LABEL_PUSH_TYPEf)) { 6812 return BCM_E_NOT_FOUND; 6813 } 6814 } 6815 #endif 6816 6817 } else if (info != NULL) { 6818 #ifdef BCM_TRIDENT3_SUPPORT 6819 int vc_data_type = 0; 6820 6821 if (SOC_MEM_FIELD_VALID(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 6822 DATA_TYPEf)) { 6823 vc_data_type = soc_mem_field32_get(unit, 6824 EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 6825 vc_entry, DATA_TYPEf); 6826 } 6827 6828 if (soc_feature(unit, soc_feature_td3_style_mpls) && 6829 (vc_data_type == _BCM_VC_SWAP_TBL_FLEX_DATA_TYPE)) { 6830 uint32 flex_pdd_format[2]; 6831 int spl_label_push_type = 0; 6832 6833 sal_memset(flex_pdd_format, 0, sizeof(flex_pdd_format)); 6834 6835 soc_mem_field_get(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 6836 (uint32 *) vc_entry, 6837 MPLS_PHP__MPLS_ENTRY_0_ACTION_SETf, 6838 (uint32 *) flex_pdd_format); 6839 6840 ttl = soc_format_field32_get(unit, 6841 MPLS_ENTRY_ACTION_SETfmt, 6842 (uint32 *)flex_pdd_format, MPLS_TTLf); 6843 if ( ttl != info->egress_label.ttl) { 6844 return BCM_E_NOT_FOUND; 6845 } 6846 6847 exp = soc_format_field32_get(unit, 6848 MPLS_ENTRY_ACTION_SETfmt, 6849 (uint32 *)flex_pdd_format, MPLS_EXPf); 6850 if (exp != info->egress_label.exp) { 6851 return BCM_E_NOT_FOUND; 6852 } 6853 6854 pri = soc_format_field32_get(unit, 6855 MPLS_ENTRY_ACTION_SETfmt, 6856 (uint32 *)flex_pdd_format, NEW_PRIf); 6857 if (pri != info->egress_label.pkt_pri) { 6858 return BCM_E_NOT_FOUND; 6859 } 6860 6861 cfi = soc_format_field32_get(unit, 6862 MPLS_ENTRY_ACTION_SETfmt, 6863 (uint32 *)flex_pdd_format, NEW_CFIf); 6864 if (cfi != info->egress_label.pkt_cfi) { 6865 return BCM_E_NOT_FOUND; 6866 } 6867 6868 spl_label_push_type = soc_format_field32_get(unit, 6869 MPLS_ENTRY_ACTION_SETfmt, 6870 (uint32 *)flex_pdd_format, 6871 SPECIAL_LABEL_PUSH_TYPEf); 6872 6873 if (spl_label_push_type != info->egress_label.spl_label_push_type) { 6874 return BCM_E_NOT_FOUND; 6875 } 6876 } else 6877 #endif 6878 { 6879 if (!(_BCM_MPLS_EGRESS_LABEL_PRESERVE(unit, info->egress_label.flags))) { 6880 entry_label = SOC_MEM_VC_SWAP_F32_GET(unit, 6881 EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 6882 vc_entry, MPLS_LABELf); 6883 if (entry_label != info->egress_label.label) { 6884 return BCM_E_NOT_FOUND; 6885 } 6886 } 6887 entry_label_action = SOC_MEM_VC_SWAP_F32_GET(unit, 6888 EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 6889 vc_entry, MPLS_LABEL_ACTIONf); 6890 if (label_action != entry_label_action) { 6891 return BCM_E_NOT_FOUND; 6892 } 6893 ttl = SOC_MEM_VC_SWAP_F32_GET(unit, 6894 EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 6895 vc_entry, MPLS_TTLf); 6896 if ( ttl != info->egress_label.ttl) { 6897 return BCM_E_NOT_FOUND; 6898 } 6899 exp = SOC_MEM_VC_SWAP_F32_GET(unit, 6900 EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 6901 vc_entry, MPLS_EXPf); 6902 6903 if (exp != info->egress_label.exp) { 6904 return BCM_E_NOT_FOUND; 6905 } 6906 6907 pri = SOC_MEM_VC_SWAP_F32_GET(unit, 6908 EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 6909 vc_entry, NEW_PRIf); 6910 6911 if (pri != info->egress_label.pkt_pri) { 6912 return BCM_E_NOT_FOUND; 6913 } 6914 6915 cfi = SOC_MEM_VC_SWAP_F32_GET(unit, 6916 EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 6917 vc_entry, NEW_CFIf); 6918 6919 if (cfi != info->egress_label.pkt_cfi) { 6920 return BCM_E_NOT_FOUND; 6921 } 6922 #ifdef BCM_TRIDENT3_SUPPORT 6923 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 6924 if ((soc_mem_field32_get(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 6925 vc_entry, SPECIAL_LABEL_PUSH_TYPEf)) != 6926 info->egress_label.spl_label_push_type) { 6927 return BCM_E_NOT_FOUND; 6928 } 6929 } 6930 #endif 6931 } 6932 } else if (egr_obj != NULL) { 6933 if (!(_BCM_MPLS_EGRESS_LABEL_PRESERVE(unit, egr_obj->mpls_flags))) { 6934 entry_label = SOC_MEM_VC_SWAP_F32_GET(unit, 6935 EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 6936 vc_entry, MPLS_LABELf); 6937 if (entry_label != egr_obj->mpls_label) { 6938 return BCM_E_NOT_FOUND; 6939 } 6940 } 6941 entry_label_action = SOC_MEM_VC_SWAP_F32_GET(unit, 6942 EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 6943 vc_entry, MPLS_LABEL_ACTIONf); 6944 if (label_action != entry_label_action) { 6945 return BCM_E_NOT_FOUND; 6946 } 6947 ttl = SOC_MEM_VC_SWAP_F32_GET(unit, 6948 EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 6949 vc_entry, MPLS_TTLf); 6950 if ( ttl != egr_obj->mpls_ttl) { 6951 return BCM_E_NOT_FOUND; 6952 } 6953 6954 if ((egr_obj->mpls_flags & BCM_MPLS_EGRESS_LABEL_EXP_SET) || 6955 (egr_obj->mpls_flags & BCM_MPLS_EGRESS_LABEL_PRI_SET)) { 6956 exp = SOC_MEM_VC_SWAP_F32_GET(unit, 6957 EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 6958 vc_entry, MPLS_EXPf); 6959 pri = SOC_MEM_VC_SWAP_F32_GET(unit, 6960 EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 6961 vc_entry, NEW_PRIf); 6962 cfi = SOC_MEM_VC_SWAP_F32_GET(unit, 6963 EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 6964 vc_entry, NEW_CFIf); 6965 exp_select = SOC_MEM_VC_SWAP_F32_GET(unit, 6966 EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 6967 vc_entry, MPLS_EXP_SELECTf); 6968 if (exp_select != 0) { 6969 return BCM_E_NOT_FOUND; 6970 } 6971 if (exp != egr_obj->mpls_exp) { 6972 return BCM_E_NOT_FOUND; 6973 } 6974 if (pri != egr_obj->mpls_pkt_pri) { 6975 return BCM_E_NOT_FOUND; 6976 } 6977 if (cfi != egr_obj->mpls_pkt_cfi) { 6978 return BCM_E_NOT_FOUND; 6979 } 6980 } else if (egr_obj->mpls_flags & BCM_MPLS_EGRESS_LABEL_EXP_REMARK) { 6981 exp_select = SOC_MEM_VC_SWAP_F32_GET(unit, 6982 EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 6983 vc_entry, MPLS_EXP_SELECTf); 6984 pri_mapping_ptr = SOC_MEM_VC_SWAP_F32_GET(unit, 6985 EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 6986 vc_entry, MPLS_EXP_MAPPING_PTRf); 6987 if (exp_select != 1) { 6988 return BCM_E_NOT_FOUND; 6989 } 6990 BCM_IF_ERROR_RETURN( 6991 _egr_qos_id2hw_idx(unit,egr_obj->mpls_qos_map_id,&map_inx)); 6992 if ( pri_mapping_ptr != map_inx) { 6993 return BCM_E_NOT_FOUND; 6994 } 6995 } else if ((egr_obj->mpls_flags & BCM_MPLS_EGRESS_LABEL_EXP_COPY) && 6996 (label_action != _BCM_MPLS_ACTION_SWAP)) { 6997 exp_select = SOC_MEM_VC_SWAP_F32_GET(unit, 6998 EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 6999 vc_entry, MPLS_EXP_SELECTf); 7000 if (exp_select != 2) { 7001 return BCM_E_NOT_FOUND; 7002 } 7003 exp = SOC_MEM_VC_SWAP_F32_GET(unit, 7004 EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 7005 vc_entry, MPLS_EXPf); 7006 if (exp != egr_obj->mpls_exp) { 7007 return BCM_E_NOT_FOUND; 7008 } 7009 pri_mapping_ptr = SOC_MEM_VC_SWAP_F32_GET(unit, 7010 EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 7011 vc_entry, MPLS_EXP_MAPPING_PTRf); 7012 7013 if (egr_obj->mpls_qos_map_id == 0) { /* use default */ 7014 map_inx = 0; 7015 } else { 7016 BCM_IF_ERROR_RETURN( 7017 _egr_qos_id2hw_idx(unit,egr_obj->mpls_qos_map_id,&map_inx)); 7018 } 7019 if (pri_mapping_ptr != map_inx) { 7020 return BCM_E_NOT_FOUND; 7021 } 7022 } else if ((egr_obj->mpls_flags & BCM_MPLS_EGRESS_LABEL_EXP_COPY) && 7023 (label_action == _BCM_MPLS_ACTION_SWAP)) { 7024 exp_select = SOC_MEM_VC_SWAP_F32_GET(unit, 7025 EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 7026 vc_entry, MPLS_EXP_SELECTf); 7027 if (exp_select != 3) { 7028 return BCM_E_NOT_FOUND; 7029 } 7030 exp = SOC_MEM_VC_SWAP_F32_GET(unit, 7031 EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 7032 vc_entry, MPLS_EXPf); 7033 if (exp != egr_obj->mpls_exp) { 7034 return BCM_E_NOT_FOUND; 7035 } 7036 pri_mapping_ptr = SOC_MEM_VC_SWAP_F32_GET(unit, 7037 EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 7038 vc_entry, MPLS_EXP_MAPPING_PTRf); 7039 7040 if (egr_obj->mpls_qos_map_id == 0) { /* use default */ 7041 map_inx = 0; 7042 } else { 7043 BCM_IF_ERROR_RETURN( 7044 _egr_qos_id2hw_idx(unit,egr_obj->mpls_qos_map_id,&map_inx)); 7045 } 7046 if (pri_mapping_ptr != map_inx) { 7047 return BCM_E_NOT_FOUND; 7048 } 7049 } 7050 #ifdef BCM_TRIDENT3_SUPPORT 7051 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 7052 if (soc_mem_field32_get(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 7053 vc_entry, SPECIAL_LABEL_PUSH_TYPEf)) { 7054 return BCM_E_NOT_FOUND; 7055 } 7056 } 7057 #endif 7058 7059 } else if (in_vc_entry != NULL) { 7060 if (sal_memcmp(in_vc_entry, vc_entry, 7061 sizeof(egr_mpls_vc_and_swap_label_table_entry_t))) { 7062 return BCM_E_NOT_FOUND; 7063 } 7064 } 7065 7066 return BCM_E_NONE; 7067 } 7068 7069 7070 /* 7071 * Function: 7072 * bcmi_tr_mpls_vc_swap_hash_index_get 7073 * Purpose: 7074 * Get hash entry for an entry 7075 * Parameters: 7076 * IN : Unit 7077 * IN : mpls port entry 7078 * IN : action 7079 * IN : next hop entry 7080 * IN : VC table entry 7081 * OUT : index 7082 7083 * Returns: 7084 * BCM_E_XXX 7085 */ 7086 int 7087 bcmi_tr_mpls_vc_swap_hash_index_get(int unit, bcm_mpls_port_t *mpls_port, 7088 int action, bcm_mpls_tunnel_switch_t *info, 7089 bcm_l3_egress_t *egr_obj, 7090 egr_mpls_vc_and_swap_label_table_entry_t *vc_entry, 7091 int *idx) 7092 { 7093 int key[BCM_TR_MPLS_VC_SWAP_KEY_LEN_IN_WORDS]; 7094 7095 if ((mpls_port == NULL) && (egr_obj == NULL) && (vc_entry == NULL) 7096 && (info == NULL)) { 7097 return BCM_E_PARAM; 7098 } 7099 7100 sal_memset(key, 0, sizeof(int) * BCM_TR_MPLS_VC_SWAP_KEY_LEN_IN_WORDS); 7101 /* Generate key for hash table lookup */ 7102 BCM_IF_ERROR_RETURN(bcmi_tr_mpls_vc_swap_hash_key_get 7103 (unit, mpls_port, info, egr_obj, action, vc_entry, key)); 7104 LOG_INFO(BSL_LS_SOC_MPLS, (BSL_META_U(unit, 7105 "Printing Key : Label = %d , label_action = %d\n "), key[0], key[1])); 7106 7107 *idx = _shr_crc16b(0, (uint8*)key, 7108 sizeof(int)* BYTES2BITS(BCM_TR_MPLS_VC_SWAP_KEY_LEN_IN_WORDS)) % 7109 BCM_TR_MPLS_VC_SWAP_HASH_BUCKETS; 7110 7111 return BCM_E_NONE; 7112 } 7113 7114 /* 7115 * Function: 7116 * bcmi_tr_mpls_vc_swap_hash_delete 7117 * Purpose: 7118 * Delete hash table entry 7119 * Parameters: 7120 * IN : Unit 7121 * IN : hash table head 7122 * IN : table index 7123 * Returns: 7124 * BCM_E_XXX 7125 */ 7126 int 7127 bcmi_tr_mpls_vc_swap_hash_delete(int unit, bcm_tr_mpls_vc_swap_table_hash_t *hash, 7128 int vc_swap_idx) 7129 { 7130 7131 bcm_tr_mpls_vc_swap_table_hash_entry_t *temp, *prev; 7132 7133 if (hash == NULL) { 7134 return BCM_E_INTERNAL; 7135 } 7136 prev = temp = hash->head_link; 7137 7138 while (temp != NULL) { 7139 if (temp->index == vc_swap_idx) { 7140 if (temp == hash->head_link) { 7141 hash->head_link = temp->link; 7142 } else { 7143 prev->link = temp->link; 7144 } 7145 sal_free(temp); 7146 return BCM_E_NONE; 7147 } else { 7148 prev = temp; 7149 temp = temp->link; 7150 } 7151 } /* while */ 7152 7153 return BCM_E_NOT_FOUND; 7154 } 7155 7156 /* 7157 * Function: 7158 * bcmi_tr_mpls_vc_swap_hash_cleanup 7159 * Purpose: 7160 * Clean/Free hash table 7161 * Parameters: 7162 * IN : Unit 7163 * Returns: 7164 * void 7165 */ 7166 STATIC void 7167 bcmi_tr_mpls_vc_swap_hash_cleanup(int unit) 7168 { 7169 7170 bcm_tr_mpls_vc_swap_table_hash_entry_t *temp; 7171 bcm_tr_mpls_vc_swap_table_hash_t *hash; 7172 int i = 0; 7173 #if defined(BCM_TRIUMPH3_SUPPORT) 7174 bcm_tr_mpls_vc_swap_table_nhop_list_t *temp_nhop; 7175 #endif 7176 7177 for (; i < BCM_TR_MPLS_VC_SWAP_HASH_BUCKETS; i++) { 7178 hash = &(bcmi_vc_swap_label_hash[unit][i]); 7179 temp = hash->head_link; 7180 7181 while (temp != NULL) { 7182 hash->head_link = temp->link; 7183 #if defined(BCM_TRIUMPH3_SUPPORT) 7184 if (soc_feature(unit, 7185 soc_feature_vc_and_swap_table_overlaid)) { 7186 temp_nhop = temp->nhop_list; 7187 while (temp_nhop) { 7188 temp->nhop_list = temp_nhop->next; 7189 sal_free(temp_nhop); 7190 temp_nhop = temp->nhop_list; 7191 } 7192 } 7193 #endif 7194 sal_free(temp); 7195 temp = hash->head_link; 7196 } 7197 } 7198 if (bcmi_vc_swap_label_hash[unit]) { 7199 sal_free(bcmi_vc_swap_label_hash[unit]); 7200 bcmi_vc_swap_label_hash[unit] = NULL; 7201 } 7202 } 7203 7204 7205 /* 7206 * Function: 7207 * bcmi_tr_mpls_vc_swap_hash_entry_alloc 7208 * Purpose: 7209 * Allocates a hash table entry 7210 * Parameters: 7211 * IN : Unit 7212 * OUT : entry pointer. 7213 * Returns: 7214 * BCM_E_XXX 7215 */ 7216 7217 STATIC int 7218 bcmi_tr_mpls_vc_swap_hash_entry_alloc(int unit, 7219 bcm_tr_mpls_vc_swap_table_hash_entry_t **entry) 7220 { 7221 7222 bcm_tr_mpls_vc_swap_table_hash_entry_t *new_entry; 7223 7224 new_entry = sal_alloc( sizeof(bcm_tr_mpls_vc_swap_table_hash_entry_t), 7225 "hash_table_entry"); 7226 7227 if (new_entry == NULL) { 7228 return BCM_E_MEMORY; 7229 } 7230 7231 /* Set the link to NULL. adding entry at tail. */ 7232 new_entry->link = NULL; 7233 new_entry->nhop_list = NULL; 7234 *entry = new_entry; 7235 7236 return BCM_E_NONE; 7237 } 7238 7239 /* 7240 * Function: 7241 * bcmi_tr_mpls_vc_swap_hash_insert 7242 * Purpose: 7243 * Insert vc entry into hash table 7244 * Parameters: 7245 * IN : Unit 7246 * IN : hash table head 7247 * IN : table index 7248 * IN : hash index 7249 * IN : mpls port entry 7250 * IN : next hop entry 7251 * IN : VC table entry 7252 * OUT : vc_swap_index 7253 * IN : Compare Option 7254 * Returns: 7255 * BCM_E_XXX 7256 */ 7257 int 7258 bcmi_tr_mpls_vc_swap_hash_insert(int unit, 7259 bcm_tr_mpls_vc_swap_table_hash_t *hash, 7260 int table_idx, bcm_mpls_port_t *mpls_port, 7261 bcm_mpls_tunnel_switch_t *info, bcm_l3_egress_t *egr_obj, 7262 egr_mpls_vc_and_swap_label_table_entry_t *in_vc_entry, 7263 int action, int *vc_swap_index, int cmp) 7264 { 7265 7266 bcm_tr_mpls_vc_swap_table_hash_entry_t *new_entry = NULL; 7267 bcm_tr_mpls_vc_swap_table_hash_entry_t *temp, *prev; 7268 egr_mpls_vc_and_swap_label_table_entry_t vc_entry; 7269 7270 if (hash == NULL) { 7271 return BCM_E_INTERNAL; 7272 } 7273 prev = temp = hash->head_link; 7274 7275 while (temp != NULL) { 7276 if (cmp) { 7277 BCM_IF_ERROR_RETURN(soc_mem_read(unit, 7278 EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 7279 MEM_BLOCK_ALL, temp->index, &vc_entry)); 7280 7281 if (BCM_SUCCESS(_bcm_tr_mpls_vc_swap_compare 7282 (unit, mpls_port, info, egr_obj, in_vc_entry, action, &vc_entry))) { 7283 /* 7284 * Entry already exists. 7285 * return BCM_E_EXISTS to increase refcount. 7286 */ 7287 *vc_swap_index = temp->index; 7288 return BCM_E_EXISTS; 7289 } 7290 } 7291 prev = temp; 7292 temp = temp->link; 7293 } 7294 /* Entry does not exist, add a new one. */ 7295 BCM_IF_ERROR_RETURN(bcmi_tr_mpls_vc_swap_hash_entry_alloc 7296 (unit, &new_entry)); 7297 7298 new_entry->index = table_idx; 7299 7300 /* update the link table */ 7301 if (hash->head_link == NULL) { 7302 hash->head_link = new_entry; 7303 } else { 7304 prev->link = new_entry; 7305 } 7306 7307 *vc_swap_index = table_idx; 7308 return BCM_E_NONE; 7309 } 7310 #if defined(BCM_TRIUMPH3_SUPPORT) 7311 /* 7312 * Function: 7313 * _bcm_tr_mpls_vc_swap_hash_index_update 7314 * Purpose: 7315 * Update the vc and swap table index in hash entry and 7316 * EGR_L3_NEXT_HOP table. 7317 * Parameters: 7318 * unit - (IN) Device Number 7319 * hash -(IN) Hash input 7320 * new_vc_swap_index - (IN) New vc and swap table index 7321 * old_vc_swap_index - (IN) Old vc and swap table index 7322 * Returns: 7323 * BCM_E_XXX 7324 */ 7325 7326 STATIC int 7327 _bcm_tr_mpls_vc_swap_hash_index_update (int unit, 7328 bcm_tr_mpls_vc_swap_table_hash_t *hash, 7329 int new_vc_swap_index, 7330 int old_vc_swap_index) 7331 { 7332 bcm_tr_mpls_vc_swap_table_hash_entry_t *temp_hash; 7333 bcm_tr_mpls_vc_swap_table_nhop_list_t *temp_nhop; 7334 soc_field_t vc_swap_idxf; 7335 7336 if (soc_feature(unit, soc_feature_mpls_enhanced)) { 7337 vc_swap_idxf = MPLS__VC_AND_SWAP_INDEXf ; 7338 } else { 7339 vc_swap_idxf = VC_AND_SWAP_INDEXf; 7340 } 7341 7342 if (hash == NULL) { 7343 return BCM_E_INTERNAL; 7344 } 7345 temp_hash = hash->head_link; 7346 while (temp_hash) { 7347 if (temp_hash->index == old_vc_swap_index) { 7348 temp_hash->index = new_vc_swap_index; 7349 temp_nhop = temp_hash->nhop_list; 7350 while (temp_nhop) { 7351 BCM_IF_ERROR_RETURN 7352 (soc_mem_field32_modify(unit, EGR_L3_NEXT_HOPm, 7353 temp_nhop->nh_index, 7354 vc_swap_idxf, 7355 new_vc_swap_index)); 7356 temp_nhop = temp_nhop->next; 7357 } 7358 return BCM_E_NONE; 7359 } 7360 temp_hash = temp_hash->link; 7361 } 7362 return BCM_E_NOT_FOUND; 7363 } 7364 #endif /* BCM_TRIUMPH3_SUPPORT */ 7365 7366 /* 7367 * Function: 7368 * _bcmi_tr_mpls_entry_set_key 7369 * Purpose: 7370 * Convert key part of application format to HW entry 7371 * Parameters: 7372 * IN : Unit 7373 * IN : info 7374 * OUT : ment 7375 * Returns: 7376 * BCM_E_XXX 7377 */ 7378 STATIC int 7379 _bcmi_tr_mpls_entry_set_key(int unit, bcm_mpls_tunnel_switch_t *info, 7380 mpls_entry_entry_t *ment) 7381 { 7382 bcm_module_t mod_out; 7383 bcm_port_t port_out; 7384 bcm_trunk_t trunk_id; 7385 int rv, gport_id; 7386 soc_mem_t mem = MPLS_ENTRYm; 7387 soc_field_t validf = VALIDf; 7388 7389 if (soc_feature(unit, soc_feature_th3_style_simple_mpls)) { 7390 mem = MPLS_ENTRY_SINGLEm; 7391 validf = BASE_VALIDf; 7392 } 7393 7394 sal_memset(ment, 0, sizeof(mpls_entry_entry_t)); 7395 7396 if (info->port == BCM_GPORT_INVALID) { 7397 /* Global label, mod/port not part of lookup key */ 7398 if (SOC_MEM_FIELD_VALID(unit, mem, MODULE_IDf)) { 7399 soc_mem_field32_set(unit, mem, ment, MODULE_IDf, 0); 7400 } 7401 soc_mem_field32_set(unit, mem, ment, PORT_NUMf, 0); 7402 if (BCM_XGS3_L3_MPLS_LBL_VALID(info->label)) { 7403 soc_mem_field32_set(unit, mem, ment, MPLS_LABELf, info->label); 7404 } else { 7405 return BCM_E_PARAM; 7406 } 7407 7408 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 7409 soc_mem_field32_set(unit, mem, ment, BASE_VALID_0f, 3); 7410 soc_mem_field32_set(unit, mem, ment, BASE_VALID_1f, 7); 7411 } else if (SOC_MEM_FIELD_VALID(unit, mem, BASE_VALIDf)) { 7412 soc_mem_field32_set(unit, mem, ment, BASE_VALIDf, 1); 7413 } else { 7414 soc_mem_field32_set(unit, mem, ment, validf, 1); 7415 } 7416 return BCM_E_NONE; 7417 } 7418 7419 rv = _bcm_esw_gport_resolve(unit, info->port, &mod_out, 7420 &port_out, &trunk_id, &gport_id); 7421 BCM_IF_ERROR_RETURN(rv); 7422 7423 if (BCM_GPORT_IS_TRUNK(info->port)) { 7424 soc_mem_field32_set(unit, mem, ment, Tf, 1); 7425 soc_mem_field32_set(unit, mem, ment, TGIDf, trunk_id); 7426 } else { 7427 if (SOC_MEM_FIELD_VALID(unit, mem, MODULE_IDf)) { 7428 soc_mem_field32_set(unit, mem, ment, MODULE_IDf, mod_out); 7429 } 7430 soc_mem_field32_set(unit, mem, ment, PORT_NUMf, port_out); 7431 } 7432 if (BCM_XGS3_L3_MPLS_LBL_VALID(info->label)) { 7433 soc_mem_field32_set(unit, mem, ment, MPLS_LABELf, info->label); 7434 } else { 7435 return BCM_E_PARAM; 7436 } 7437 7438 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 7439 soc_mem_field32_set(unit, mem, ment, BASE_VALID_0f, 3); 7440 soc_mem_field32_set(unit, mem, ment, BASE_VALID_1f, 7); 7441 } else if (SOC_MEM_FIELD_VALID(unit, mem, BASE_VALIDf)){ 7442 soc_mem_field32_set(unit, mem, ment, BASE_VALIDf, 1); 7443 } else { 7444 soc_mem_field32_set(unit, mem, ment, validf, 1); 7445 } 7446 7447 return BCM_E_NONE; 7448 } 7449 7450 /* 7451 * Function: 7452 * _bcm_tr_mpls_get_vc_and_swap_table_index 7453 * Purpose: 7454 * Obtain Index into VC_AND_SWAP_TABLE 7455 * Parameters: 7456 * IN : Unit 7457 * IN : num_vc 7458 * IN : mpls port entry 7459 * IN : next hop entry 7460 * IN : action 7461 * OUT : vc_swap_index 7462 * Returns: 7463 * BCM_E_XXX 7464 */ 7465 int 7466 _bcm_tr_mpls_get_vc_and_swap_table_index (int unit, int flags, 7467 bcm_mpls_port_t *mpls_port, 7468 bcm_mpls_tunnel_switch_t *info, 7469 bcm_l3_egress_t *egr_obj, 7470 egr_mpls_vc_and_swap_label_table_entry_t *vc_entry, 7471 int action, int *vc_swap_index) 7472 { 7473 int hash_idx, num_vc; 7474 int imin; 7475 int rv; 7476 int action_flags = _BCM_MPLS_ACTION_GET(flags); 7477 int free_idx = 0, offset = 0; 7478 bcm_tr_mpls_vc_swap_table_hash_t *hash_input; 7479 7480 if (bcmi_vc_swap_label_hash[unit] == NULL) { 7481 return BCM_E_INTERNAL; 7482 } 7483 7484 imin = soc_mem_index_min(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm); 7485 num_vc = soc_mem_index_count(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm); 7486 7487 /* we are dividng the table in half to manage counted and 7488 * non-counted entries. 7489 */ 7490 num_vc /= 2; 7491 7492 BCM_IF_ERROR_RETURN(bcmi_tr_mpls_vc_swap_hash_index_get( 7493 unit, mpls_port, action, info, egr_obj, vc_entry, &hash_idx)); 7494 7495 /* Try getting index from 2nd half of MPLS_VC_AND_SWAP table */ 7496 if (!(action_flags & _BCM_MPLS_ACTION_SEQUENCE)) { 7497 for (free_idx = imin; free_idx < num_vc + imin; free_idx++) { 7498 if (!(_BCM_MPLS_VC_NON_COUNT_USED_GET(unit, free_idx) || 7499 (soc_feature(unit, soc_feature_vc_and_swap_table_overlaid) && 7500 _bcm_vp_used_get(unit, free_idx, _bcmVpTypeL2Gre)))) { 7501 break; 7502 } 7503 } 7504 } 7505 7506 if ((free_idx == (num_vc + imin)) || 7507 (action_flags & _BCM_MPLS_ACTION_SEQUENCE)) { 7508 7509 /* Get index from 1st half of MPLS_VC_AND_SWAP table */ 7510 for (free_idx = imin; free_idx < num_vc + imin; free_idx++) { 7511 if (!_BCM_MPLS_VC_COUNT_USED_GET(unit, free_idx - imin)) { 7512 break; 7513 } 7514 } 7515 if (free_idx == num_vc + imin) { 7516 return BCM_E_RESOURCE; 7517 } 7518 _BCM_MPLS_VC_COUNT_USED_SET(unit, free_idx - imin); 7519 offset = imin; 7520 } else { 7521 _BCM_MPLS_VC_NON_COUNT_USED_SET(unit, free_idx - imin); 7522 offset = num_vc + imin; 7523 } 7524 7525 hash_input = &(bcmi_vc_swap_label_hash[unit][hash_idx]); 7526 7527 if (flags & _BCM_MPLS_ACTION_LABEL_ALLOC) { 7528 /* insert the entry without comparison */ 7529 rv = bcmi_tr_mpls_vc_swap_hash_insert(unit, hash_input, 7530 free_idx + offset, mpls_port, info, 7531 egr_obj, vc_entry, action, vc_swap_index, FALSE); 7532 7533 } else { 7534 /* insert the entry with comparison */ 7535 rv = bcmi_tr_mpls_vc_swap_hash_insert(unit, hash_input, 7536 free_idx + offset, mpls_port, info, 7537 egr_obj, vc_entry, action, vc_swap_index, TRUE); 7538 } 7539 7540 if (BCM_FAILURE(rv)) { 7541 7542 if (offset == imin) { 7543 _BCM_MPLS_VC_COUNT_USED_CLR(unit, free_idx - imin); 7544 } else { 7545 _BCM_MPLS_VC_NON_COUNT_USED_CLR(unit, free_idx - imin); 7546 } 7547 7548 if (rv != BCM_E_EXISTS) { 7549 LOG_ERROR(BSL_LS_SOC_COMMON, (BSL_META_U(unit, 7550 "Hash Entry insertion failed = %d\n"), rv)); 7551 return rv; 7552 } 7553 } 7554 #ifdef BCM_TRIDENT3_SUPPORT 7555 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 7556 if ((info != NULL) && (rv == BCM_E_EXISTS) && 7557 (info->action == BCM_MPLS_SWITCH_ACTION_PHP)) { 7558 int index; 7559 mpls_entry_entry_t ment; 7560 BCM_IF_ERROR_RETURN(_bcmi_tr_mpls_entry_set_key(unit, info, &ment)); 7561 rv = soc_mem_search(unit, MPLS_ENTRYm, 7562 MEM_BLOCK_ANY, &index, &ment, &ment, 0); 7563 if (rv != SOC_E_NOT_FOUND) { 7564 return rv; 7565 } 7566 } 7567 } 7568 #endif 7569 /* Increase refcount on table idx */ 7570 if (*vc_swap_index >= 0) { 7571 _bcm_tr_mpls_vc_and_swap_ref_count_adjust(unit, *vc_swap_index , 1); 7572 } 7573 7574 return BCM_E_NONE; 7575 } 7576 7577 /* 7578 * Function: 7579 * _bcm_tr_mpls_vc_and_swap_table_reset 7580 * Purpose: 7581 * Reset VC_AND_SWAP_TABLE entry 7582 * Parameters: 7583 * IN : Unit 7584 * IN : vc_swap_index 7585 * Returns: 7586 * BCM_E_XXX 7587 */ 7588 int 7589 _bcm_tr_mpls_vc_and_swap_table_index_reset (int unit, int vc_swap_index) 7590 { 7591 egr_mpls_vc_and_swap_label_table_entry_t vc_entry; 7592 int rv = BCM_E_NONE; 7593 _bcm_tr_mpls_bookkeeping_t *mpls_info = MPLS_INFO(unit); 7594 int num_vc, idx; 7595 bcm_tr_mpls_vc_swap_table_hash_t *hash_input; 7596 int action = 0; 7597 7598 /* Entry 0 is reserved with _bcm_tr_mpls_default_entry_setup during init */ 7599 if (vc_swap_index == VC_AND_SWAP_TABLE_RESV_INDEX) { 7600 LOG_INFO(BSL_LS_BCM_L3, 7601 (BSL_META_U(unit,"Not resetting reserved index: %d in " 7602 "VC AND SWAP TABLE\n"), VC_AND_SWAP_TABLE_RESV_INDEX)); 7603 return BCM_E_NONE; 7604 } 7605 if ( mpls_info->vc_swap_ref_count[vc_swap_index] != 0 ) { 7606 return BCM_E_NONE; 7607 } 7608 if (bcmi_vc_swap_label_hash[unit] == NULL) { 7609 return BCM_E_INTERNAL; 7610 } 7611 num_vc = soc_mem_index_count(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm); 7612 num_vc /= 2; 7613 7614 BCM_IF_ERROR_RETURN(soc_mem_read(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 7615 MEM_BLOCK_ALL, vc_swap_index, &vc_entry)); 7616 7617 #ifdef BCM_TRIDENT3_SUPPORT 7618 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 7619 if (MPLS_INFO(unit)->egr_vc_swap_lbl_action != NULL) { 7620 action = MPLS_INFO(unit)->egr_vc_swap_lbl_action[vc_swap_index]; 7621 } 7622 } else 7623 #endif 7624 { 7625 action = 0; 7626 } 7627 7628 BCM_IF_ERROR_RETURN(bcmi_tr_mpls_vc_swap_hash_index_get( 7629 unit, NULL, action, NULL, NULL, &vc_entry, &idx)); 7630 7631 /* remove the entry from sw hash table */ 7632 hash_input = &(bcmi_vc_swap_label_hash[unit][idx]); 7633 BCM_IF_ERROR_RETURN(bcmi_tr_mpls_vc_swap_hash_delete( 7634 unit, hash_input, vc_swap_index)); 7635 7636 if (vc_swap_index >= num_vc) { 7637 _BCM_MPLS_VC_NON_COUNT_USED_CLR(unit, vc_swap_index - num_vc); 7638 } else { 7639 _BCM_MPLS_VC_COUNT_USED_CLR(unit, vc_swap_index); 7640 } 7641 7642 sal_memset(&vc_entry, 0, 7643 sizeof(egr_mpls_vc_and_swap_label_table_entry_t)); 7644 7645 rv = soc_mem_write(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 7646 MEM_BLOCK_ALL, vc_swap_index, 7647 &vc_entry); 7648 7649 #if defined(BCM_TRIDENT3_SUPPORT) 7650 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 7651 if (MPLS_INFO(unit)->egr_vc_swap_lbl_action != NULL) { 7652 mpls_info->egr_vc_swap_lbl_action[vc_swap_index] = 7653 _BCM_MPLS_ACTION_NOOP; 7654 } 7655 } 7656 #endif 7657 return rv; 7658 } 7659 7660 /* 7661 * Function: 7662 * _bcm_tr_mpls_vc_and_swap_table_entry_set 7663 * Purpose: 7664 * Set VC_AND_SWAP_TABLE entry 7665 * Parameters: 7666 * IN : Unit 7667 * IN : vc_swap_index 7668 * Returns: 7669 * BCM_E_XXX 7670 */ 7671 STATIC int 7672 _bcm_tr_mpls_vc_and_swap_table_entry_set (int unit, 7673 bcm_mpls_port_t *mpls_port, 7674 bcm_mpls_tunnel_switch_t *info, 7675 bcm_l3_egress_t *egr_obj, 7676 int label_action, 7677 egr_mpls_vc_and_swap_label_table_entry_t *vc_entry, 7678 int hw_map_idx, int vc_swap_index) 7679 { 7680 bcm_mpls_label_t mpls_label = BCM_MPLS_LABEL_INVALID; 7681 uint8 mpls_ttl = 0; 7682 uint32 mpls_flags = 0; 7683 uint8 mpls_exp = 0; 7684 uint8 mpls_pkt_pri = 0; 7685 uint8 mpls_pkt_cfi = 0; 7686 #if (defined(BCM_TOMAHAWK2_SUPPORT) || defined(BCM_TRIDENT3_SUPPORT)) 7687 int mpls_ecn_map_id = ECN_MAP_ID_INVALID; 7688 int mpls_int_cn_map_id = ECN_MAP_ID_INVALID; 7689 #endif 7690 uint8 spl_label_action = 0; 7691 int action = 0; 7692 int php_swap_to_self = 0; 7693 #if defined(BCM_TRIDENT3_SUPPORT) 7694 int mapping_ptr = 0; 7695 uint32 flex_pdd_format[2]; 7696 uint32 cancun_ver; 7697 #endif 7698 7699 #if defined(BCM_TRIDENT3_SUPPORT) 7700 /* data fields: flex view uses PDD */ 7701 sal_memset(flex_pdd_format, 0, sizeof(flex_pdd_format)); 7702 if (SOC_IS_TRIDENT3X(unit)) { 7703 SOC_IF_ERROR_RETURN(soc_cancun_version_get(unit, &cancun_ver)); 7704 } 7705 #endif 7706 if (mpls_port != NULL) { 7707 mpls_label = mpls_port->egress_label.label; 7708 mpls_ttl = mpls_port->egress_label.ttl; 7709 mpls_flags = mpls_port->egress_label.flags; 7710 mpls_pkt_pri = mpls_port->egress_label.pkt_pri; 7711 mpls_pkt_cfi = mpls_port->egress_label.pkt_cfi; 7712 mpls_exp = mpls_port->egress_label.exp; 7713 #if (defined(BCM_TOMAHAWK2_SUPPORT) || defined(BCM_TRIDENT3_SUPPORT)) 7714 if (soc_feature(unit, soc_feature_mpls_ecn)) { 7715 if (mpls_flags & BCM_MPLS_EGRESS_LABEL_ECN_TO_EXP_MAP) { 7716 mpls_ecn_map_id = mpls_port->egress_label.ecn_map_id; 7717 } 7718 if (mpls_flags & BCM_MPLS_EGRESS_LABEL_INT_CN_TO_EXP_MAP) { 7719 if (soc_feature(unit, soc_feature_intcn_to_exp_nosupport)) { 7720 return BCM_E_UNAVAIL; 7721 } 7722 mpls_int_cn_map_id = mpls_port->egress_label.int_cn_map_id; 7723 } 7724 } 7725 #endif 7726 } else if (info != NULL) { 7727 mpls_label = info->egress_label.label; 7728 mpls_ttl = info->egress_label.ttl; 7729 mpls_flags = info->egress_label.flags; 7730 mpls_pkt_pri = info->egress_label.pkt_pri; 7731 mpls_pkt_cfi = info->egress_label.pkt_cfi; 7732 mpls_exp = info->egress_label.exp; 7733 spl_label_action = info->egress_label.spl_label_push_type; 7734 action = info->action; 7735 #if (defined(BCM_TOMAHAWK2_SUPPORT) || defined(BCM_TRIDENT3_SUPPORT)) 7736 if (soc_feature(unit, soc_feature_mpls_ecn)) { 7737 if (mpls_flags & BCM_MPLS_EGRESS_LABEL_INT_CN_TO_EXP_MAP) { 7738 if (soc_feature(unit, soc_feature_intcn_to_exp_nosupport)) { 7739 return BCM_E_UNAVAIL; 7740 } 7741 mpls_int_cn_map_id = info->egress_label.int_cn_map_id; 7742 } 7743 7744 if (mpls_flags & BCM_MPLS_EGRESS_LABEL_ECN_TO_EXP_MAP) { 7745 mpls_ecn_map_id = info->egress_label.ecn_map_id; 7746 } 7747 } 7748 #endif 7749 } else if (egr_obj != NULL) { 7750 mpls_label = egr_obj->mpls_label; 7751 mpls_ttl = egr_obj->mpls_ttl; 7752 mpls_flags = egr_obj->mpls_flags; 7753 mpls_pkt_pri = egr_obj->mpls_pkt_pri; 7754 mpls_pkt_cfi = egr_obj->mpls_pkt_cfi; 7755 mpls_exp = egr_obj->mpls_exp; 7756 #if (defined(BCM_TOMAHAWK2_SUPPORT) || defined(BCM_TRIDENT3_SUPPORT)) 7757 if (soc_feature(unit, soc_feature_mpls_ecn)) { 7758 if (mpls_flags & BCM_MPLS_EGRESS_LABEL_INT_CN_TO_EXP_MAP) { 7759 if (soc_feature(unit, soc_feature_intcn_to_exp_nosupport)) { 7760 return BCM_E_UNAVAIL; 7761 } 7762 mpls_int_cn_map_id = egr_obj->mpls_ecn_map_id; 7763 } 7764 if (mpls_flags & BCM_MPLS_EGRESS_LABEL_ECN_TO_EXP_MAP) { 7765 mpls_ecn_map_id = egr_obj->mpls_ecn_map_id; 7766 } 7767 } 7768 #endif 7769 } 7770 7771 if ((mpls_exp > 7) || (mpls_pkt_pri > 7) || 7772 (mpls_pkt_cfi > 1)) { 7773 return BCM_E_PARAM; 7774 } 7775 7776 sal_memset(vc_entry, 0, 7777 sizeof(egr_mpls_vc_and_swap_label_table_entry_t)); 7778 7779 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 7780 soc_mem_field32_set(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 7781 vc_entry, SPECIAL_LABEL_PUSH_TYPEf, spl_label_action); 7782 } 7783 if (_BCM_MPLS_EGRESS_LABEL_PRESERVE(unit, mpls_flags) || 7784 ((soc_feature(unit, soc_feature_td3_style_mpls)) && 7785 (action & BCM_MPLS_SWITCH_ACTION_PHP))) { 7786 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 7787 #if defined(BCM_TRIDENT3_SUPPORT) 7788 if (((SOC_IS_TRIDENT3(unit) && (cancun_ver >= SOC_CANCUN_VERSION_DEF_6_0_0)) || 7789 (SOC_IS_MAVERICK2(unit) && (cancun_ver >= SOC_CANCUN_VERSION_DEF_4_0_0)) || 7790 (SOC_IS_HELIX5(unit) && (cancun_ver >= SOC_CANCUN_VERSION_DEF_4_0_0))) && 7791 (action & BCM_MPLS_SWITCH_ACTION_PHP)) { 7792 soc_format_field32_set(unit, MPLS_ENTRY_ACTION_SETfmt, 7793 flex_pdd_format, CONTAINER_IDf, 0); 7794 soc_format_field32_set(unit, MPLS_ENTRY_ACTION_SETfmt, 7795 flex_pdd_format, LABEL_SELECTf, 0); 7796 soc_mem_field32_set(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 7797 vc_entry, EDIT_CTRL_IDf, 7798 15); 7799 7800 } else { 7801 soc_format_field32_set(unit, MPLS_ENTRY_ACTION_SETfmt, 7802 flex_pdd_format, LABEL_SELECTf, 7803 1); 7804 /* CANCUN has fixed the container 3 for swap to self */ 7805 soc_format_field32_set(unit, MPLS_ENTRY_ACTION_SETfmt, 7806 flex_pdd_format, CONTAINER_IDf, 7807 3); 7808 } 7809 7810 soc_format_field32_set(unit, MPLS_ENTRY_ACTION_SETfmt, 7811 flex_pdd_format, MPLS_PUSH_ACTIONf, 7812 _BCM_MPLS_ACTION_PUSH); 7813 7814 soc_mem_field32_set(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 7815 vc_entry, FLOW_SELECT_CTRL_IDf, 7816 5); 7817 7818 soc_mem_field32_set(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 7819 vc_entry, DATA_TYPEf, 7820 5); 7821 /*For PHP/SWAPTOSELF by default Keep the old EXP value 7822 *from the last label decapped (swap label).*/ 7823 soc_format_field32_set(unit, MPLS_ENTRY_ACTION_SETfmt, 7824 flex_pdd_format, MPLS_EXP_SELECTf, 3); 7825 7826 if (MPLS_INFO(unit)->egr_vc_swap_lbl_action != NULL) { 7827 MPLS_INFO(unit)->egr_vc_swap_lbl_action[vc_swap_index] = 7828 _BCM_MPLS_ACTION_PRESERVED; 7829 } 7830 #endif 7831 php_swap_to_self = TRUE; 7832 } else { 7833 soc_mem_field32_set(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 7834 vc_entry, MPLS_LABEL_ACTIONf, 7835 _BCM_MPLS_ACTION_PRESERVED); 7836 } 7837 } else { 7838 if (BCM_XGS3_L3_MPLS_LBL_VALID(mpls_label)) { 7839 soc_mem_field32_set(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 7840 vc_entry, MPLS_LABELf, 7841 mpls_label); 7842 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 7843 #if defined(BCM_TRIDENT3_SUPPORT) 7844 if (MPLS_INFO(unit)->egr_vc_swap_lbl_action != NULL) { 7845 MPLS_INFO(unit)->egr_vc_swap_lbl_action[vc_swap_index] = 7846 label_action; 7847 } 7848 #endif 7849 if (label_action == _BCM_MPLS_ACTION_SWAP) { 7850 /*VC SWAP HW Tbl supports Label actions NOOP,PUSH in TD3. 7851 *Record software defined label actions in software 7852 *state to reuse existing code for L3MPLS*/ 7853 soc_mem_field32_set(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 7854 vc_entry, MPLS_LABEL_ACTIONf, 7855 _BCM_MPLS_ACTION_PUSH); 7856 } else { 7857 7858 soc_mem_field32_set(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 7859 vc_entry, MPLS_LABEL_ACTIONf, 7860 label_action); 7861 } 7862 } else { 7863 soc_mem_field32_set(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 7864 vc_entry, MPLS_LABEL_ACTIONf, 7865 label_action); 7866 } 7867 7868 } else { 7869 soc_mem_field32_set(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 7870 vc_entry, MPLS_LABEL_ACTIONf, 7871 _BCM_MPLS_ACTION_NOOP); 7872 } 7873 } 7874 if (mpls_flags & BCM_MPLS_EGRESS_LABEL_TTL_SET) { 7875 if (php_swap_to_self) { 7876 #if defined(BCM_TRIDENT3_SUPPORT) 7877 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 7878 soc_format_field32_set(unit, MPLS_ENTRY_ACTION_SETfmt, 7879 flex_pdd_format, MPLS_TTLf, mpls_ttl); 7880 } 7881 #endif 7882 } else { 7883 soc_mem_field32_set(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 7884 vc_entry, MPLS_TTLf, 7885 mpls_ttl); 7886 } 7887 } else { 7888 if (php_swap_to_self) { 7889 #if defined(BCM_TRIDENT3_SUPPORT) 7890 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 7891 soc_format_field32_set(unit, MPLS_ENTRY_ACTION_SETfmt, 7892 flex_pdd_format, MPLS_TTLf, 0x0); 7893 } 7894 #endif 7895 } else { 7896 soc_mem_field32_set(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 7897 vc_entry, MPLS_TTLf, 0x0); 7898 } 7899 } 7900 #ifdef BCM_MONTEREY_SUPPORT 7901 if (soc_feature(unit, soc_feature_roe) || 7902 soc_feature(unit, soc_feature_roe_custom)) { 7903 if (mpls_flags & BCM_MPLS_EGRESS_LABEL_ROE_BARE_MPLS) { 7904 soc_mem_field32_set(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 7905 vc_entry, BARE_MPLSf, 0x1); 7906 } else { 7907 soc_mem_field32_set(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 7908 vc_entry, BARE_MPLSf, 0x0); 7909 } 7910 } 7911 #endif 7912 #if (defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT)) 7913 if (soc_feature(unit, soc_feature_mpls_entropy) && (mpls_port != NULL)) { 7914 if ((mpls_port->flags & BCM_MPLS_PORT_ENTROPY_ENABLE) || 7915 (mpls_flags & BCM_MPLS_EGRESS_LABEL_ENTROPY_ENABLE)) { 7916 if (soc_mem_field_valid(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 7917 MPLS_INSERT_ENTROPY_LABELf)) { 7918 soc_mem_field32_set(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 7919 vc_entry, MPLS_INSERT_ENTROPY_LABELf, 0x1); 7920 } 7921 } 7922 } 7923 #endif /* defined(BCM_KATANA_SUPPORT) || defined(BCM_APACHE_SUPPORT) */ 7924 if (mpls_port != NULL) { 7925 if (mpls_port->flags & BCM_MPLS_PORT_SEQUENCED) { 7926 /* Append control word with sequence number */ 7927 soc_mem_field32_set(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 7928 vc_entry, CW_INSERT_FLAGf, 0x2); 7929 } else if (mpls_port->flags & BCM_MPLS_PORT_CONTROL_WORD) { 7930 /* Append control word with NO sequence number */ 7931 soc_mem_field32_set(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 7932 vc_entry, CW_INSERT_FLAGf, 0x1); 7933 } 7934 if ((mpls_port->flags & BCM_MPLS_PORT_COUNTED) || 7935 (mpls_port->flags & BCM_MPLS_PORT_SEQUENCED)) { 7936 soc_mem_field32_set(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 7937 vc_entry, UPDATE_PW_INIT_COUNTERSf, 0x1); 7938 } 7939 } 7940 if ((mpls_flags & BCM_MPLS_EGRESS_LABEL_EXP_SET) || 7941 (mpls_flags & BCM_MPLS_EGRESS_LABEL_PRI_SET)) { 7942 7943 if ((mpls_flags & BCM_MPLS_EGRESS_LABEL_EXP_REMARK) || 7944 (mpls_flags & BCM_MPLS_EGRESS_LABEL_EXP_COPY) || 7945 (mpls_flags & BCM_MPLS_EGRESS_LABEL_PRI_REMARK)) { 7946 return BCM_E_PARAM; 7947 } 7948 7949 if (php_swap_to_self) { 7950 #if defined(BCM_TRIDENT3_SUPPORT) 7951 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 7952 soc_format_field32_set(unit, MPLS_ENTRY_ACTION_SETfmt, 7953 flex_pdd_format, MPLS_EXP_SELECTf, 0x0); 7954 7955 soc_format_field32_set(unit, MPLS_ENTRY_ACTION_SETfmt, 7956 flex_pdd_format, MPLS_EXPf, mpls_exp); 7957 7958 soc_format_field32_set(unit, MPLS_ENTRY_ACTION_SETfmt, 7959 flex_pdd_format, NEW_PRIf, mpls_pkt_pri); 7960 7961 soc_format_field32_set(unit, MPLS_ENTRY_ACTION_SETfmt, 7962 flex_pdd_format, NEW_CFIf, mpls_pkt_cfi); 7963 } 7964 #endif 7965 } else { 7966 /* Use the specified EXP, PRI and CFI */ 7967 soc_mem_field32_set(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 7968 vc_entry, MPLS_EXP_SELECTf, 7969 0x0); /* USE_FIXED */ 7970 soc_mem_field32_set(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 7971 vc_entry, MPLS_EXPf, 7972 mpls_exp); 7973 soc_mem_field32_set(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 7974 vc_entry, NEW_PRIf, 7975 mpls_pkt_pri); 7976 soc_mem_field32_set(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 7977 vc_entry, NEW_CFIf, 7978 mpls_pkt_cfi); 7979 } 7980 } else if (mpls_flags & BCM_MPLS_EGRESS_LABEL_EXP_REMARK) { 7981 if (mpls_flags & BCM_MPLS_EGRESS_LABEL_PRI_SET) { 7982 return BCM_E_PARAM; 7983 } 7984 7985 if (php_swap_to_self) { 7986 #if defined(BCM_TRIDENT3_SUPPORT) 7987 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 7988 soc_format_field32_set(unit, MPLS_ENTRY_ACTION_SETfmt, 7989 flex_pdd_format, MPLS_EXP_SELECTf, 0x1); 7990 7991 soc_format_field32_set(unit, MPLS_ENTRY_ACTION_SETfmt, 7992 flex_pdd_format, MPLS_EXP_MAPPING_PTRf, 7993 hw_map_idx); 7994 } 7995 #endif 7996 } else { 7997 /* Use EXP-map for EXP, PRI and CFI */ 7998 soc_mem_field32_set(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 7999 vc_entry, MPLS_EXP_SELECTf, 8000 0x1); /* USE_MAPPING */ 8001 soc_mem_field32_set(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 8002 vc_entry, MPLS_EXP_MAPPING_PTRf, 8003 hw_map_idx); 8004 } 8005 } else if ((label_action != _BCM_MPLS_ACTION_SWAP) && 8006 (mpls_flags & BCM_MPLS_EGRESS_LABEL_EXP_COPY) ) { 8007 /* Use EXP from incoming label. If there is no incoming label, 8008 * use the specified EXP value. Use EXP-map for PRI/CFI. 8009 */ 8010 if (php_swap_to_self) { 8011 #if defined(BCM_TRIDENT3_SUPPORT) 8012 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 8013 soc_format_field32_set(unit, MPLS_ENTRY_ACTION_SETfmt, 8014 flex_pdd_format, MPLS_EXP_SELECTf, 0x2); 8015 8016 soc_format_field32_set(unit, MPLS_ENTRY_ACTION_SETfmt, 8017 flex_pdd_format, MPLS_EXPf, mpls_exp); 8018 8019 soc_format_field32_set(unit, MPLS_ENTRY_ACTION_SETfmt, 8020 flex_pdd_format, MPLS_EXP_MAPPING_PTRf, 8021 hw_map_idx); 8022 } 8023 #endif 8024 } else { 8025 soc_mem_field32_set(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 8026 vc_entry, MPLS_EXP_SELECTf, 8027 0x2); /* USE_INNER */ 8028 soc_mem_field32_set(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 8029 vc_entry, MPLS_EXPf, 8030 mpls_exp); 8031 8032 /* Use EXP-PRI-map for PRI/CFI */ 8033 soc_mem_field32_set(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 8034 vc_entry, MPLS_EXP_MAPPING_PTRf, 8035 hw_map_idx); 8036 } 8037 } else if ((label_action == _BCM_MPLS_ACTION_SWAP) && 8038 (mpls_flags & BCM_MPLS_EGRESS_LABEL_EXP_COPY) ) { 8039 8040 if (php_swap_to_self) { 8041 #if defined(BCM_TRIDENT3_SUPPORT) 8042 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 8043 soc_format_field32_set(unit, MPLS_ENTRY_ACTION_SETfmt, 8044 flex_pdd_format, MPLS_EXP_SELECTf, 0x3); 8045 8046 soc_format_field32_set(unit, MPLS_ENTRY_ACTION_SETfmt, 8047 flex_pdd_format, MPLS_EXPf, mpls_exp); 8048 8049 soc_format_field32_set(unit, MPLS_ENTRY_ACTION_SETfmt, 8050 flex_pdd_format, MPLS_EXP_MAPPING_PTRf, 8051 hw_map_idx); 8052 } 8053 #endif 8054 } else { 8055 soc_mem_field32_set(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 8056 vc_entry, MPLS_EXP_SELECTf, 8057 0x3); /* USE_SWAP */ 8058 soc_mem_field32_set(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 8059 vc_entry, MPLS_EXPf, mpls_exp); 8060 /* Use EXP-PRI-map for PRI/CFI */ 8061 soc_mem_field32_set(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 8062 vc_entry, MPLS_EXP_MAPPING_PTRf, 8063 hw_map_idx); 8064 } 8065 } 8066 #if defined(BCM_TRIDENT3_SUPPORT) 8067 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 8068 if (info != NULL && (info->action & BCM_MPLS_SWITCH_ACTION_PHP)) { 8069 if ((info->pkt_pri > 7) || (info->pkt_cfi > 1)) { 8070 return BCM_E_PARAM; 8071 } 8072 8073 if (info->flags2 & BCM_MPLS_SWITCH2_VLAN_PRI_SET) { 8074 soc_format_field32_set(unit, MPLS_ENTRY_ACTION_SETfmt, 8075 flex_pdd_format, PRI_CFI_SELf, 0); 8076 soc_format_field32_set(unit, MPLS_ENTRY_ACTION_SETfmt, 8077 flex_pdd_format, DOT1P_MAPPING_PTRf, 8078 (info->pkt_pri << 1) | info->pkt_cfi); 8079 } else if (info->flags2 & BCM_MPLS_SWITCH2_VLAN_PRI_PHB_REMARK) { 8080 BCM_IF_ERROR_RETURN( 8081 _bcm_tr2_qos_id2idx(unit, info->qos_map_id, &mapping_ptr)); 8082 soc_format_field32_set(unit, MPLS_ENTRY_ACTION_SETfmt, 8083 flex_pdd_format, PRI_CFI_SELf, 1); 8084 soc_format_field32_set(unit, MPLS_ENTRY_ACTION_SETfmt, 8085 flex_pdd_format, DOT1P_MAPPING_PTRf, mapping_ptr); 8086 } 8087 } 8088 } 8089 #endif 8090 #if (defined(BCM_TOMAHAWK2_SUPPORT) || defined(BCM_TRIDENT3_SUPPORT)) 8091 if (soc_feature(unit, soc_feature_mpls_ecn)) { 8092 if ((mpls_flags & BCM_MPLS_EGRESS_LABEL_INT_CN_TO_EXP_MAP) && 8093 (mpls_int_cn_map_id != ECN_MAP_ID_INVALID) && 8094 (!soc_feature(unit, soc_feature_intcn_to_exp_nosupport))) { 8095 int ecn_map_index; 8096 int ecn_map_type; 8097 int ecn_map_num; 8098 int ecn_map_hw_idx; 8099 ecn_map_type = mpls_int_cn_map_id & 8100 _BCM_XGS5_MPLS_ECN_MAP_TYPE_MASK; 8101 ecn_map_index = mpls_int_cn_map_id & 8102 _BCM_XGS5_MPLS_ECN_MAP_NUM_MASK; 8103 ecn_map_num = 8104 soc_mem_index_count(unit, EGR_INT_CN_TO_EXP_MAPPING_TABLEm) / 8105 _BCM_ECN_MAX_ENTRIES_PER_MAP; 8106 if (ecn_map_type != _BCM_XGS5_MPLS_ECN_MAP_TYPE_INTCN2EXP) { 8107 return BCM_E_PARAM; 8108 } 8109 if (ecn_map_index >= ecn_map_num) { 8110 return BCM_E_PARAM; 8111 } 8112 BCM_IF_ERROR_RETURN( 8113 bcmi_ecn_map_id2hw_idx(unit, mpls_int_cn_map_id, &ecn_map_hw_idx)); 8114 soc_mem_field32_set(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 8115 vc_entry, INT_CN_TO_EXP_MAPPING_PTRf, 8116 ecn_map_hw_idx); 8117 if (mpls_flags & BCM_MPLS_EGRESS_LABEL_ECN_EXP_MAP_TRUST) { 8118 soc_mem_field32_set(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 8119 vc_entry, INT_CN_TO_EXP_PRIORITYf, 1); 8120 8121 } else { 8122 soc_mem_field32_set(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 8123 vc_entry, INT_CN_TO_EXP_PRIORITYf, 0); 8124 8125 } 8126 } 8127 if ((mpls_flags & BCM_MPLS_EGRESS_LABEL_ECN_TO_EXP_MAP) && 8128 (mpls_ecn_map_id != ECN_MAP_ID_INVALID)) { 8129 int ecn_map_index; 8130 int ecn_map_type; 8131 int ecn_map_num; 8132 int ecn_map_hw_idx; 8133 soc_mem_t mem; 8134 soc_field_t ipecn_to_exp_ptr; 8135 soc_field_t ipecn_to_exp_priority; 8136 ecn_map_type = mpls_ecn_map_id & 8137 _BCM_XGS5_MPLS_ECN_MAP_TYPE_MASK; 8138 ecn_map_index = mpls_ecn_map_id & 8139 _BCM_XGS5_MPLS_ECN_MAP_NUM_MASK; 8140 #if defined(BCM_TRIDENT3_SUPPORT) 8141 if(soc_feature(unit, soc_feature_td3_style_mpls)) { 8142 mem = EGR_PKT_ECN_TO_EXP_MAPPING_1m; 8143 } else 8144 #endif 8145 { 8146 mem = EGR_IP_ECN_TO_EXP_MAPPING_TABLEm; 8147 } 8148 ecn_map_num = 8149 soc_mem_index_count(unit, mem) / 8150 _BCM_ECN_MAX_ENTRIES_PER_MAP; 8151 if (ecn_map_type != _BCM_XGS5_MPLS_ECN_MAP_TYPE_ECN2EXP) { 8152 return BCM_E_PARAM; 8153 } 8154 if (ecn_map_index >= ecn_map_num) { 8155 return BCM_E_PARAM; 8156 } 8157 8158 BCM_IF_ERROR_RETURN( 8159 bcmi_ecn_map_id2hw_idx(unit, mpls_ecn_map_id, &ecn_map_hw_idx)); 8160 8161 #if defined(BCM_TRIDENT3_SUPPORT) 8162 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 8163 ipecn_to_exp_ptr = PKT_ECN_TO_EXP_MAPPING_PTRf; 8164 ipecn_to_exp_priority = PKT_ECN_TO_EXP_PRIORITYf; 8165 /*Remap EXP to encode ECN.*/ 8166 soc_mem_field32_set(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 8167 vc_entry, ECN_MAPPING_ENABLEf, 1); 8168 /*Use EGR_PKT_ECN_TO_EXP_MAPPING_2 for vc labels*/ 8169 soc_mem_field32_set(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 8170 vc_entry, ECN_MAPPING_TABLE_SELECTf, 1); 8171 8172 } else 8173 #endif 8174 { 8175 ipecn_to_exp_ptr = IP_ECN_TO_EXP_MAPPING_PTRf; 8176 ipecn_to_exp_priority = IP_ECN_TO_EXP_PRIORITYf; 8177 } 8178 soc_mem_field32_set(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 8179 vc_entry, ipecn_to_exp_ptr, 8180 ecn_map_hw_idx); 8181 if (mpls_flags & BCM_MPLS_EGRESS_LABEL_ECN_EXP_MAP_TRUST) { 8182 soc_mem_field32_set(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 8183 vc_entry, ipecn_to_exp_priority, 1); 8184 8185 } else { 8186 soc_mem_field32_set(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 8187 vc_entry, ipecn_to_exp_priority, 0); 8188 } 8189 } 8190 } 8191 #endif 8192 8193 #if defined(BCM_TRIDENT3_SUPPORT) 8194 if (php_swap_to_self) { 8195 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 8196 soc_mem_field_set(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 8197 (uint32 *)vc_entry, MPLS_PHP__MPLS_ENTRY_0_ACTION_SETf, 8198 flex_pdd_format); 8199 } 8200 } 8201 #endif 8202 return BCM_E_NONE; 8203 } 8204 #if defined(BCM_TRIUMPH3_SUPPORT) 8205 /* 8206 * Function: 8207 * _bcm_tr_mpls_vc_and_swap_table_entry_adjust 8208 * Purpose: 8209 * Move the vc and swap table entry to another index. 8210 * The original index should be occupied by 8211 * EGR_DVP_ATTRIBUTE_1 8212 * Parameters: 8213 * unit - (IN) Device Number 8214 * VP -(IN) virtual port number 8215 * Returns: 8216 * BCM_E_XXX 8217 */ 8218 8219 int 8220 _bcm_tr_mpls_vc_and_swap_table_entry_adjust (int unit, int vp) 8221 { 8222 int hash_idx, num_vc; 8223 int imin = 0; 8224 int rv, ref_count; 8225 int free_idx = 0, offset = 0; 8226 int old_vc_swap_index, vc_swap_index; 8227 bcm_tr_mpls_vc_swap_table_hash_t *hash_input; 8228 egr_mpls_vc_and_swap_label_table_entry_t vc_entry; 8229 int action = 0; 8230 8231 if (bcmi_vc_swap_label_hash[unit] == NULL) { 8232 return BCM_E_INTERNAL; 8233 } 8234 rv = bcm_tr_mpls_lock(unit); 8235 _BCM_MPLS_CLEANUP(rv); 8236 8237 /* The entry is not occupied. */ 8238 if (!_BCM_MPLS_VC_NON_COUNT_USED_GET(unit, vp)) { 8239 bcm_tr_mpls_unlock(unit); 8240 return BCM_E_NONE; 8241 } 8242 8243 imin = soc_mem_index_min(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm); 8244 num_vc = soc_mem_index_count(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm); 8245 8246 /* we are dividng the table in half to manage counted and 8247 * non-counted entries. 8248 */ 8249 num_vc /= 2; 8250 8251 old_vc_swap_index = vp + num_vc; 8252 rv = soc_mem_read(unit, 8253 EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 8254 MEM_BLOCK_ALL, old_vc_swap_index, &vc_entry); 8255 _BCM_MPLS_CLEANUP(rv); 8256 /* Try getting index from 2nd half of MPLS_VC_AND_SWAP table */ 8257 for (free_idx = imin; free_idx < num_vc + imin; free_idx++) { 8258 if (!(_BCM_MPLS_VC_NON_COUNT_USED_GET(unit, free_idx) || 8259 _bcm_vp_used_get(unit, free_idx, _bcmVpTypeL2Gre))) { 8260 break; 8261 } 8262 } 8263 if (free_idx == (num_vc + imin)) { 8264 /* Get index from 1st half of MPLS_VC_AND_SWAP table */ 8265 for (free_idx = imin; free_idx < num_vc + imin; free_idx++) { 8266 if (!_BCM_MPLS_VC_COUNT_USED_GET(unit, free_idx - imin)) { 8267 break; 8268 } 8269 } 8270 if (free_idx == num_vc + imin) { 8271 bcm_tr_mpls_unlock(unit); 8272 return BCM_E_RESOURCE; 8273 } 8274 _BCM_MPLS_VC_COUNT_USED_SET(unit, free_idx - imin); 8275 offset = imin; 8276 } else { 8277 _BCM_MPLS_VC_NON_COUNT_USED_SET(unit, free_idx - imin); 8278 offset = num_vc + imin; 8279 } 8280 8281 vc_swap_index = free_idx + offset; 8282 rv = soc_mem_write(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 8283 MEM_BLOCK_ALL, vc_swap_index, 8284 &vc_entry); 8285 _BCM_MPLS_CLEANUP(rv); 8286 8287 #ifdef BCM_TRIDENT3_SUPPORT 8288 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 8289 if (MPLS_INFO(unit)->egr_vc_swap_lbl_action != NULL) { 8290 action = MPLS_INFO(unit)->egr_vc_swap_lbl_action[vc_swap_index]; 8291 } 8292 } else 8293 #endif 8294 { 8295 action = 0; 8296 } 8297 /* Update nhop entry and EGR_L3_NEXT_HOP table */ 8298 rv = bcmi_tr_mpls_vc_swap_hash_index_get(unit, NULL, action, NULL, NULL, 8299 &vc_entry, &hash_idx); 8300 _BCM_MPLS_CLEANUP(rv); 8301 hash_input = &(bcmi_vc_swap_label_hash[unit][hash_idx]); 8302 rv = _bcm_tr_mpls_vc_swap_hash_index_update(unit, 8303 hash_input, vc_swap_index, 8304 old_vc_swap_index); 8305 _BCM_MPLS_CLEANUP(rv); 8306 /* Clear the original entry */ 8307 rv = soc_mem_write(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 8308 MEM_BLOCK_ALL, old_vc_swap_index, 8309 soc_mem_entry_null(unit, 8310 EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm)); 8311 _BCM_MPLS_CLEANUP(rv); 8312 /* Adjust the ref count */ 8313 _bcm_tr_mpls_vc_and_swap_ref_count_get(unit, old_vc_swap_index, &ref_count); 8314 _bcm_tr_mpls_vc_and_swap_ref_count_reset(unit, old_vc_swap_index); 8315 _bcm_tr_mpls_vc_and_swap_ref_count_adjust(unit, vc_swap_index, ref_count); 8316 bcm_tr_mpls_unlock(unit); 8317 8318 return rv; 8319 cleanup: 8320 if (offset == imin) { 8321 _BCM_MPLS_VC_COUNT_USED_CLR(unit, free_idx - imin); 8322 } else { 8323 _BCM_MPLS_VC_NON_COUNT_USED_CLR(unit, free_idx - imin); 8324 } 8325 bcm_tr_mpls_unlock(unit); 8326 return rv; 8327 } 8328 #endif 8329 /* 8330 * Function: 8331 * _bcm_tr_mpls_pw_init_counter_set 8332 * Purpose: 8333 * Obtain the pw_init counter index, Set the EGR L3 NH entry parameter 8334 * Parameters: 8335 * unit - (IN) SOC unit # 8336 * egr_nh_info - (IN/OUT) Egress NHOP Internal Structurel 8337 * Returns: 8338 * BCM_E_XXX 8339 */ 8340 8341 STATIC int 8342 _bcm_tr_mpls_pw_init_counter_set (int unit, 8343 uint32 pw_seq_number, _bcm_tr_egr_nh_info_t *egr_nh_info) 8344 { 8345 int pw_init_cnt=-1; 8346 egr_pw_init_counters_entry_t pw_init_entry; 8347 egr_pw_init_counters_x_entry_t pw_init_entry_x; 8348 egr_pw_init_counters_y_entry_t pw_init_entry_y; 8349 int vc_swap_index; 8350 uint32 num_pw_mask; 8351 8352 #ifdef BCM_TRIDENT3_SUPPORT 8353 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 8354 egr_sequence_number_table_entry_t td3_pw_init_entry; 8355 8356 vc_swap_index = egr_nh_info->vc_swap_index; 8357 8358 /* pw_init_counter index is from the LSB bits of vc_and_swap_index */ 8359 num_pw_mask = soc_mem_index_count(unit, EGR_SEQUENCE_NUMBER_TABLEm) - 1; 8360 pw_init_cnt = vc_swap_index & num_pw_mask; 8361 8362 _BCM_MPLS_PW_INIT_USED_SET(unit, pw_init_cnt); 8363 8364 egr_nh_info->pw_init_cnt = pw_init_cnt; 8365 8366 sal_memset(&td3_pw_init_entry, 0, sizeof(egr_sequence_number_table_entry_t)); 8367 soc_EGR_SEQUENCE_NUMBER_TABLEm_field_set(unit, &td3_pw_init_entry, SEQUENCE_NUMBERf, 8368 (uint32 *)&pw_seq_number); 8369 8370 pw_init_cnt = EGR_PW_SEQNUM_VCSWAP_OFFSET + pw_init_cnt; 8371 WRITE_EGR_SEQUENCE_NUMBER_TABLEm(unit, MEM_BLOCK_ALL, pw_init_cnt, 8372 &td3_pw_init_entry); 8373 } else 8374 #endif 8375 { 8376 if (SOC_MEM_IS_VALID(unit, EGR_PW_INIT_COUNTERSm)) { 8377 vc_swap_index = egr_nh_info->vc_swap_index; 8378 8379 /* pw_init_counter index is from the LSB bits of vc_and_swap_index */ 8380 num_pw_mask = soc_mem_index_count(unit, EGR_PW_INIT_COUNTERSm) - 1; 8381 pw_init_cnt = vc_swap_index & num_pw_mask; 8382 8383 _BCM_MPLS_PW_INIT_USED_SET(unit, pw_init_cnt); 8384 8385 egr_nh_info->pw_init_cnt = pw_init_cnt; 8386 8387 sal_memset(&pw_init_entry, 0, sizeof(egr_pw_init_counters_entry_t)); 8388 soc_EGR_PW_INIT_COUNTERSm_field32_set(unit, &pw_init_entry, SEQ_NUMf, 8389 pw_seq_number); 8390 8391 WRITE_EGR_PW_INIT_COUNTERSm(unit, MEM_BLOCK_ALL, pw_init_cnt, 8392 &pw_init_entry); 8393 if (SOC_MEM_IS_VALID(unit, EGR_PW_INIT_COUNTERS_Xm)) { 8394 sal_memset(&pw_init_entry_x, 0, sizeof(egr_pw_init_counters_x_entry_t)); 8395 soc_EGR_PW_INIT_COUNTERS_Xm_field32_set(unit, &pw_init_entry_x, 8396 SEQ_NUMf, pw_seq_number); 8397 8398 WRITE_EGR_PW_INIT_COUNTERS_Xm(unit, MEM_BLOCK_ALL, pw_init_cnt, 8399 &pw_init_entry_x); 8400 } 8401 if (SOC_MEM_IS_VALID(unit, EGR_PW_INIT_COUNTERS_Ym)) { 8402 sal_memset(&pw_init_entry_y, 0, sizeof(egr_pw_init_counters_y_entry_t)); 8403 soc_EGR_PW_INIT_COUNTERS_Ym_field32_set(unit, &pw_init_entry_y, 8404 SEQ_NUMf, pw_seq_number); 8405 8406 WRITE_EGR_PW_INIT_COUNTERS_Ym(unit, MEM_BLOCK_ALL, pw_init_cnt, 8407 &pw_init_entry_y); 8408 } 8409 8410 } 8411 } 8412 return BCM_E_NONE; 8413 8414 } 8415 8416 /* 8417 * Function: 8418 * _bcm_tr_mpls_pw_init_counter_delete 8419 * Purpose: 8420 * Get L2 MPLS PW Stats 8421 * Parameters: 8422 * unit - (IN) SOC unit # 8423 * Returns: 8424 * BCM_E_XXX 8425 */ 8426 8427 STATIC int 8428 _bcm_tr_mpls_pw_init_counter_delete (int unit, int nh_index) 8429 { 8430 int pw_init_cnt=-1,rv; 8431 egr_l3_next_hop_entry_t egr_nh; 8432 egr_pw_init_counters_entry_t pw_init_entry; 8433 egr_pw_init_counters_x_entry_t pw_init_entry_x; 8434 egr_pw_init_counters_y_entry_t pw_init_entry_y; 8435 #if defined(BCM_TRIDENT3_SUPPORT) 8436 uint32 num_pw_mask; 8437 #endif 8438 int vc_swap_index = 0; 8439 int num_vc = 0; 8440 8441 #if defined(BCM_TRIDENT3_SUPPORT) 8442 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 8443 if (SOC_MEM_IS_VALID(unit, EGR_SEQUENCE_NUMBER_TABLEm)) { 8444 egr_sequence_number_table_entry_t td3_pw_init_entry; 8445 rv = soc_mem_read(unit, EGR_L3_NEXT_HOPm, MEM_BLOCK_ANY, 8446 nh_index, &egr_nh); 8447 if (rv < 0) { 8448 return rv; 8449 } 8450 8451 if (soc_feature(unit, soc_feature_mpls_enhanced)) { 8452 pw_init_cnt = 8453 soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, 8454 MPLS__PW_INIT_NUMf); 8455 } else { 8456 pw_init_cnt = 8457 soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, 8458 PW_INIT_NUMf); 8459 } 8460 8461 num_pw_mask = soc_mem_index_count(unit, EGR_SEQUENCE_NUMBER_TABLEm) - 1; 8462 pw_init_cnt &= num_pw_mask; 8463 8464 sal_memset(&td3_pw_init_entry, 0, sizeof(egr_sequence_number_table_entry_t)); 8465 WRITE_EGR_SEQUENCE_NUMBER_TABLEm(unit, MEM_BLOCK_ALL, pw_init_cnt, 8466 &td3_pw_init_entry); 8467 8468 _BCM_MPLS_PW_INIT_USED_CLR (unit, pw_init_cnt); 8469 } 8470 } else 8471 #endif 8472 { 8473 if (SOC_MEM_IS_VALID(unit, EGR_PW_INIT_COUNTERSm)) { 8474 rv = soc_mem_read(unit, EGR_L3_NEXT_HOPm, MEM_BLOCK_ANY, 8475 nh_index, &egr_nh); 8476 if (rv < 0) { 8477 return rv; 8478 } 8479 8480 if (soc_feature(unit, soc_feature_mpls_enhanced)) { 8481 pw_init_cnt = 8482 soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, 8483 MPLS__PW_INIT_NUMf); 8484 vc_swap_index = soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, 8485 MPLS__VC_AND_SWAP_INDEXf); 8486 } else { 8487 pw_init_cnt = 8488 soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, 8489 PW_INIT_NUMf); 8490 vc_swap_index = soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, 8491 VC_AND_SWAP_INDEXf); 8492 } 8493 8494 /* Validate if vc_swap_index is in upper half or lower half of swap table. 8495 * If in lower half then delete count references otherwise do nothing 8496 */ 8497 num_vc = soc_mem_index_count(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm); 8498 if (vc_swap_index < num_vc/2) { 8499 8500 sal_memset(&pw_init_entry, 0, sizeof(egr_pw_init_counters_entry_t)); 8501 WRITE_EGR_PW_INIT_COUNTERSm(unit, MEM_BLOCK_ALL, pw_init_cnt, 8502 &pw_init_entry); 8503 if (SOC_MEM_IS_VALID(unit, EGR_PW_INIT_COUNTERS_Xm)) { 8504 sal_memset(&pw_init_entry_x, 0, sizeof(egr_pw_init_counters_x_entry_t)); 8505 WRITE_EGR_PW_INIT_COUNTERS_Xm(unit, MEM_BLOCK_ALL, pw_init_cnt, 8506 &pw_init_entry_x); 8507 } 8508 if (SOC_MEM_IS_VALID(unit, EGR_PW_INIT_COUNTERS_Ym)) { 8509 sal_memset(&pw_init_entry_y, 0, sizeof(egr_pw_init_counters_y_entry_t)); 8510 WRITE_EGR_PW_INIT_COUNTERS_Ym(unit, MEM_BLOCK_ALL, pw_init_cnt, 8511 &pw_init_entry_y); 8512 } 8513 8514 _BCM_MPLS_PW_INIT_USED_CLR (unit, pw_init_cnt); 8515 } 8516 } 8517 } 8518 return BCM_E_NONE; 8519 } 8520 8521 /* 8522 * Function: 8523 * _bcm_tr_mpls_pw_term_counter_set 8524 * Purpose: 8525 * Obtain the pw_term counter index 8526 * Parameters: 8527 * unit - (IN) SOC unit # 8528 * ment - (IN/OUT) MPLS Entry Structure 8529 * Returns: 8530 * BCM_E_XXX 8531 */ 8532 8533 int 8534 _bcm_tr_mpls_pw_term_counter_set (int unit, int *pw_term_cnt) 8535 { 8536 int num_pw_term=-1; 8537 int pw_idx=0; 8538 ing_pw_term_counters_entry_t pw_term_entry; 8539 ing_pw_term_seq_num_entry_t pw_term_seq_num_entry; 8540 8541 if (SOC_MEM_IS_VALID(unit, ING_PW_TERM_COUNTERSm)) { 8542 num_pw_term = soc_mem_index_count(unit, ING_PW_TERM_COUNTERSm); 8543 for (pw_idx = 0; pw_idx < num_pw_term; pw_idx++) { 8544 if (!_BCM_MPLS_PW_TERM_USED_GET(unit, pw_idx)) { 8545 break; 8546 } 8547 } 8548 if (pw_idx == num_pw_term) { 8549 return BCM_E_RESOURCE; 8550 } 8551 _BCM_MPLS_PW_TERM_USED_SET(unit, pw_idx); 8552 8553 sal_memset(&pw_term_entry, 0, sizeof(ing_pw_term_counters_entry_t)); 8554 (void) WRITE_ING_PW_TERM_COUNTERSm(unit, MEM_BLOCK_ALL, pw_idx, 8555 &pw_term_entry); 8556 8557 *pw_term_cnt = pw_idx; 8558 } else if (SOC_MEM_IS_VALID(unit, ING_PW_TERM_SEQ_NUMm)) { 8559 num_pw_term = soc_mem_index_count(unit, ING_PW_TERM_SEQ_NUMm); 8560 for (pw_idx = 0; pw_idx < num_pw_term; pw_idx++) { 8561 if (!_BCM_MPLS_PW_TERM_USED_GET(unit, pw_idx)) { 8562 break; 8563 } 8564 } 8565 if (pw_idx == num_pw_term) { 8566 return BCM_E_RESOURCE; 8567 } 8568 _BCM_MPLS_PW_TERM_USED_SET(unit, pw_idx); 8569 8570 sal_memset(&pw_term_seq_num_entry, 0, sizeof(ing_pw_term_seq_num_entry_t)); 8571 WRITE_ING_PW_TERM_SEQ_NUMm(unit, MEM_BLOCK_ALL, pw_idx, 8572 &pw_term_seq_num_entry); 8573 8574 *pw_term_cnt = pw_idx; 8575 } 8576 return BCM_E_NONE; 8577 } 8578 8579 /* 8580 * Function: 8581 * _bcm_tr_mpls_pw_term_counter_delete 8582 * Purpose: 8583 * Delete pw_term counter 8584 * Parameters: 8585 * unit - (IN) SOC unit # 8586 * Returns: 8587 * BCM_E_XXX 8588 */ 8589 8590 STATIC int 8591 _bcm_tr_mpls_pw_term_counter_delete (int unit, int pw_term_cnt) 8592 { 8593 ing_pw_term_counters_entry_t pw_term_entry; 8594 ing_pw_term_seq_num_entry_t pw_term_seq_num_entry; 8595 8596 if (SOC_MEM_IS_VALID(unit, ING_PW_TERM_COUNTERSm)) { 8597 _BCM_MPLS_PW_TERM_USED_CLR(unit, pw_term_cnt); 8598 8599 sal_memset(&pw_term_entry, 0, sizeof(ing_pw_term_counters_entry_t)); 8600 (void) WRITE_ING_PW_TERM_COUNTERSm(unit, MEM_BLOCK_ALL, pw_term_cnt, 8601 &pw_term_entry); 8602 } else if (SOC_MEM_IS_VALID(unit, ING_PW_TERM_SEQ_NUMm)) { 8603 _BCM_MPLS_PW_TERM_USED_CLR(unit, pw_term_cnt); 8604 8605 sal_memset(&pw_term_seq_num_entry, 0, sizeof(ing_pw_term_seq_num_entry_t)); 8606 WRITE_ING_PW_TERM_SEQ_NUMm(unit, MEM_BLOCK_ALL, pw_term_cnt, 8607 &pw_term_seq_num_entry); 8608 } 8609 return BCM_E_NONE; 8610 } 8611 8612 /* 8613 * Function: 8614 * _bcm_tr_mpls_port_untagged_profile_set 8615 * Purpose: 8616 * Set VLan profile per Physical port entry 8617 * Parameters: 8618 * unit - (IN) SOC unit # 8619 * port - (IN) Physical port 8620 * Returns: 8621 * BCM_E_XXX 8622 */ 8623 8624 int 8625 bcm_tr_mpls_port_untagged_profile_set (int unit, bcm_port_t port) 8626 { 8627 int rv; 8628 bcm_vlan_action_set_t action; 8629 uint32 ing_profile_idx = 0xffffffff; 8630 int old_ing_profile_idx = -1; 8631 8632 bcm_vlan_action_set_t_init(&action); 8633 action.ut_outer = 0x0; /* No Op */ 8634 action.ut_inner = 0x0; /* No Op */ 8635 8636 SOC_IF_ERROR_RETURN( 8637 _bcm_esw_port_tab_get(unit, port, TAG_ACTION_PROFILE_PTRf, 8638 &old_ing_profile_idx)); 8639 8640 rv = _bcm_trx_vlan_action_profile_entry_add(unit, &action, &ing_profile_idx); 8641 if (rv < 0) { 8642 return rv; 8643 } 8644 8645 rv = _bcm_esw_port_tab_set_without_portlock(unit, port, _BCM_CPU_TABS_NONE, 8646 TAG_ACTION_PROFILE_PTRf, 8647 ing_profile_idx); 8648 if (rv < 0) { 8649 return rv; 8650 } 8651 8652 if(old_ing_profile_idx != ING_ACTION_PROFILE_DEFAULT) { 8653 rv = _bcm_trx_vlan_action_profile_entry_delete(unit, old_ing_profile_idx); 8654 } 8655 8656 return rv; 8657 } 8658 8659 /* 8660 * Function: 8661 * bcm_tr_mpls_port_untagged_profile_reset 8662 * Purpose: 8663 * Reset VLan profile per Physical port entry 8664 * Parameters: 8665 * unit - (IN) SOC unit # 8666 * port - (IN) Physical port 8667 * Returns: 8668 * BCM_E_XXX 8669 */ 8670 8671 int 8672 bcm_tr_mpls_port_untagged_profile_reset(int unit, bcm_port_t port) 8673 { 8674 int rv; 8675 int ing_profile_idx = -1; 8676 8677 SOC_IF_ERROR_RETURN( 8678 _bcm_esw_port_tab_get(unit, port, TAG_ACTION_PROFILE_PTRf, 8679 &ing_profile_idx)); 8680 8681 rv = _bcm_trx_vlan_action_profile_entry_delete(unit, ing_profile_idx); 8682 if (rv < 0) { 8683 return rv; 8684 } 8685 8686 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 8687 /*Reset TAG_ACTION_PROFILE_PTR to 1 in TD3*/ 8688 rv = _bcm_esw_port_tab_set_without_portlock(unit, port, _BCM_CPU_TABS_NONE, 8689 TAG_ACTION_PROFILE_PTRf, 1); 8690 } else { 8691 rv = _bcm_esw_port_tab_set_without_portlock(unit, port, _BCM_CPU_TABS_NONE, 8692 TAG_ACTION_PROFILE_PTRf, 0); 8693 } 8694 8695 return rv; 8696 } 8697 8698 /* 8699 * Function: 8700 * _bcm_tr_mpls_port_mtu_set 8701 * Purpose: 8702 * Set Vitual port MTU 8703 * Returns: 8704 * BCM_E_XXX 8705 */ 8706 8707 int 8708 _bcm_tr_mpls_port_mtu_set(int unit, int vp, int mtu) 8709 { 8710 int rv=BCM_E_UNAVAIL; 8711 egr_dvp_attribute_entry_t egr_dvp_attribute; 8712 8713 if (mtu == 0) { 8714 mtu = 0x3FFF; 8715 } 8716 8717 rv = READ_EGR_DVP_ATTRIBUTEm(unit, MEM_BLOCK_ALL, vp, 8718 &egr_dvp_attribute); 8719 if (BCM_SUCCESS(rv)) { 8720 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 8721 soc_mem_field32_set(unit, EGR_DVP_ATTRIBUTEm, 8722 &egr_dvp_attribute, 8723 DATA_TYPEf, 0x0); 8724 soc_mem_field32_set(unit, EGR_DVP_ATTRIBUTEm, 8725 &egr_dvp_attribute, 8726 COMMON__MTU_VALUEf, mtu); 8727 soc_mem_field32_set(unit, EGR_DVP_ATTRIBUTEm, 8728 &egr_dvp_attribute, 8729 COMMON__MTU_ENABLEf, 0x1); 8730 } else { 8731 soc_mem_field32_set(unit, EGR_DVP_ATTRIBUTEm, 8732 &egr_dvp_attribute, 8733 VP_TYPEf, 0x0); 8734 soc_mem_field32_set(unit, EGR_DVP_ATTRIBUTEm, 8735 &egr_dvp_attribute, 8736 MTU_VALUEf, mtu); 8737 soc_mem_field32_set(unit, EGR_DVP_ATTRIBUTEm, 8738 &egr_dvp_attribute, 8739 MTU_ENABLEf, 0x1); 8740 } 8741 8742 rv = WRITE_EGR_DVP_ATTRIBUTEm(unit, MEM_BLOCK_ALL, vp, 8743 &egr_dvp_attribute); 8744 } 8745 return rv; 8746 8747 } 8748 8749 /* 8750 * Function: 8751 * _bcm_tr_mpls_port_mtu_clear 8752 * Purpose: 8753 * Clear Vitual port MTU 8754 * Returns: 8755 * BCM_E_XXX 8756 */ 8757 8758 int 8759 _bcm_tr_mpls_port_mtu_clear (int unit, int vp) 8760 { 8761 int rv=BCM_E_UNAVAIL; 8762 egr_dvp_attribute_entry_t egr_dvp_attribute; 8763 8764 rv = soc_mem_read(unit, EGR_DVP_ATTRIBUTEm, 8765 MEM_BLOCK_ALL, vp, &egr_dvp_attribute); 8766 if (BCM_SUCCESS(rv)) { 8767 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 8768 if (soc_mem_field32_get(unit, EGR_DVP_ATTRIBUTEm, 8769 &egr_dvp_attribute, COMMON__MTU_ENABLEf)) { 8770 soc_mem_field32_set(unit, EGR_DVP_ATTRIBUTEm, &egr_dvp_attribute, 8771 COMMON__MTU_VALUEf, 0x0); 8772 soc_mem_field32_set(unit, EGR_DVP_ATTRIBUTEm, &egr_dvp_attribute, 8773 COMMON__MTU_ENABLEf, 0x0); 8774 rv = soc_mem_write(unit, EGR_DVP_ATTRIBUTEm, 8775 MEM_BLOCK_ALL, vp, &egr_dvp_attribute); 8776 } 8777 } else { 8778 if (soc_mem_field32_get(unit, EGR_DVP_ATTRIBUTEm, 8779 &egr_dvp_attribute, MTU_ENABLEf)) { 8780 soc_mem_field32_set(unit, EGR_DVP_ATTRIBUTEm, &egr_dvp_attribute, 8781 MTU_VALUEf, 0x0); 8782 soc_mem_field32_set(unit, EGR_DVP_ATTRIBUTEm, &egr_dvp_attribute, 8783 MTU_ENABLEf, 0x0); 8784 rv = soc_mem_write(unit, EGR_DVP_ATTRIBUTEm, 8785 MEM_BLOCK_ALL, vp, &egr_dvp_attribute); 8786 } 8787 } 8788 } 8789 return rv; 8790 } 8791 8792 /* 8793 * Function: 8794 * _bcm_tr_mpls_port_mtu_get 8795 * Purpose: 8796 * Get Vitual port MTU 8797 * Returns: 8798 * BCM_E_XXX 8799 */ 8800 8801 int 8802 _bcm_tr_mpls_port_mtu_get(int unit, int vp, int *mtu) 8803 { 8804 int rv=BCM_E_UNAVAIL; 8805 egr_dvp_attribute_entry_t egr_dvp_attribute; 8806 8807 rv = soc_mem_read(unit, EGR_DVP_ATTRIBUTEm, 8808 MEM_BLOCK_ALL, vp, &egr_dvp_attribute); 8809 if (BCM_SUCCESS(rv)) { 8810 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 8811 if (soc_mem_field32_get(unit, EGR_DVP_ATTRIBUTEm, 8812 &egr_dvp_attribute, COMMON__MTU_ENABLEf)) { 8813 *mtu = soc_mem_field32_get(unit, EGR_DVP_ATTRIBUTEm, 8814 &egr_dvp_attribute, COMMON__MTU_VALUEf); 8815 } 8816 } else { 8817 if (soc_mem_field32_get(unit, EGR_DVP_ATTRIBUTEm, 8818 &egr_dvp_attribute, MTU_ENABLEf)) { 8819 *mtu = soc_mem_field32_get(unit, EGR_DVP_ATTRIBUTEm, 8820 &egr_dvp_attribute, MTU_VALUEf); 8821 } 8822 } 8823 } 8824 return rv; 8825 } 8826 8827 /* 8828 * Function: 8829 * _bcm_tr_mpls_sd_tag_set 8830 * Purpose: 8831 * Program SD_TAG settings 8832 * Parameters: 8833 * unit - (IN) SOC unit # 8834 * mpls_port - (IN) MPLS VP 8835 * egr_nh_info (IN/OUT) Egress NHop Info 8836 * Returns: 8837 * BCM_E_XXX 8838 */ 8839 8840 STATIC int 8841 _bcm_tr_mpls_sd_tag_set( int unit, bcm_mpls_port_t *mpls_port, 8842 _bcm_tr_egr_nh_info_t *egr_nh_info, 8843 egr_mpls_vc_and_swap_label_table_entry_t *vc_entry, 8844 int *tpid_index ) 8845 { 8846 int rv = BCM_E_NONE; 8847 8848 if (mpls_port->flags & BCM_MPLS_PORT_EGRESS_TUNNEL) { 8849 if (mpls_port->flags & BCM_MPLS_PORT_SERVICE_VLAN_ADD) { 8850 if (mpls_port->egress_service_vlan >= BCM_VLAN_INVALID) { 8851 return BCM_E_PARAM; 8852 } 8853 soc_mem_field32_set(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 8854 vc_entry, SD_TAG_VIDf, 8855 mpls_port->egress_service_vlan); 8856 soc_mem_field32_set(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 8857 vc_entry, SD_TAG_ACTION_IF_NOT_PRESENTf, 8858 0x1); /* ADD */ 8859 } 8860 8861 if (mpls_port->flags & BCM_MPLS_PORT_SERVICE_VLAN_TPID_REPLACE) { 8862 if (mpls_port->egress_service_vlan >= BCM_VLAN_INVALID) { 8863 return BCM_E_PARAM; 8864 } 8865 soc_mem_field32_set(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 8866 vc_entry, SD_TAG_VIDf, 8867 mpls_port->egress_service_vlan); 8868 soc_mem_field32_set(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 8869 vc_entry, SD_TAG_ACTION_IF_PRESENTf, 8870 0x1); /* REPLACE_VID_TPID */ 8871 } else if (mpls_port->flags & BCM_MPLS_PORT_SERVICE_VLAN_REPLACE) { 8872 if (mpls_port->egress_service_vlan >= BCM_VLAN_INVALID) { 8873 return BCM_E_PARAM; 8874 } 8875 soc_mem_field32_set(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 8876 vc_entry, SD_TAG_VIDf, 8877 mpls_port->egress_service_vlan); 8878 soc_mem_field32_set(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 8879 vc_entry, SD_TAG_ACTION_IF_PRESENTf, 8880 0x2); /* REPLACE_VID_ONLY */ 8881 } else if (mpls_port->flags & BCM_MPLS_PORT_SERVICE_VLAN_DELETE) { 8882 soc_mem_field32_set(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 8883 vc_entry, SD_TAG_ACTION_IF_PRESENTf, 8884 0x3); /* DELETE */ 8885 } else if (mpls_port->flags & BCM_MPLS_PORT_SERVICE_VLAN_PRI_TPID_REPLACE) { 8886 if (soc_feature(unit, soc_feature_mpls_enhanced)) { 8887 if (mpls_port->egress_service_vlan >= BCM_VLAN_INVALID) { 8888 return BCM_E_PARAM; 8889 } 8890 soc_mem_field32_set(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 8891 vc_entry, SD_TAG_VIDf, 8892 mpls_port->egress_service_vlan); 8893 if (soc_mem_field_valid(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 8894 SD_TAG_NEW_PRIf)) { 8895 soc_mem_field32_set(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 8896 vc_entry, SD_TAG_NEW_PRIf, 8897 mpls_port->pkt_pri); 8898 } 8899 if (soc_mem_field_valid(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 8900 SD_TAG_NEW_CFIf)) { 8901 soc_mem_field32_set(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 8902 vc_entry, SD_TAG_NEW_CFIf, 8903 mpls_port->pkt_cfi); 8904 } 8905 8906 soc_mem_field32_set(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 8907 vc_entry, SD_TAG_ACTION_IF_PRESENTf, 8908 0x4); /* REPLACE_VID_PRI_TPID */ 8909 }else { 8910 return BCM_E_PARAM; 8911 } 8912 } else if (mpls_port->flags & BCM_MPLS_PORT_SERVICE_VLAN_PRI_REPLACE ) { 8913 if (soc_feature(unit, soc_feature_mpls_enhanced)) { 8914 if (mpls_port->egress_service_vlan >= BCM_VLAN_INVALID) { 8915 return BCM_E_PARAM; 8916 } 8917 soc_mem_field32_set(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 8918 vc_entry, SD_TAG_VIDf, 8919 mpls_port->egress_service_vlan); 8920 8921 if (soc_mem_field_valid(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 8922 SD_TAG_NEW_PRIf)) { 8923 soc_mem_field32_set(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 8924 vc_entry, SD_TAG_NEW_PRIf, 8925 mpls_port->pkt_pri); 8926 } 8927 if (soc_mem_field_valid(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 8928 SD_TAG_NEW_CFIf)) { 8929 soc_mem_field32_set(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 8930 vc_entry, SD_TAG_NEW_CFIf, 8931 mpls_port->pkt_cfi); 8932 } 8933 8934 soc_mem_field32_set(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 8935 vc_entry, SD_TAG_ACTION_IF_PRESENTf, 8936 0x5); /* REPLACE_VID_PRI */ 8937 } else { 8938 return BCM_E_PARAM; 8939 } 8940 }else if (mpls_port->flags & BCM_MPLS_PORT_SERVICE_PRI_REPLACE ) { 8941 if (soc_feature(unit, soc_feature_mpls_enhanced)) { 8942 if (soc_mem_field_valid(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 8943 SD_TAG_NEW_PRIf)) { 8944 soc_mem_field32_set(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 8945 vc_entry, SD_TAG_NEW_PRIf, 8946 mpls_port->pkt_pri); 8947 } 8948 if (soc_mem_field_valid(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 8949 SD_TAG_NEW_CFIf)) { 8950 soc_mem_field32_set(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 8951 vc_entry, SD_TAG_NEW_CFIf, 8952 mpls_port->pkt_cfi); 8953 } 8954 8955 soc_mem_field32_set(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 8956 vc_entry, SD_TAG_ACTION_IF_PRESENTf, 8957 0x6); /* REPLACE_PRI_ONLY */ 8958 } else { 8959 return BCM_E_PARAM; 8960 } 8961 8962 } else if (mpls_port->flags & BCM_MPLS_PORT_SERVICE_TPID_REPLACE ) { 8963 if (soc_feature(unit, soc_feature_mpls_enhanced)) { 8964 soc_mem_field32_set(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 8965 vc_entry, SD_TAG_ACTION_IF_PRESENTf, 8966 0x7); /* REPLACE_TPID_ONLY */ 8967 } else { 8968 return BCM_E_PARAM; 8969 } 8970 } 8971 8972 if ((mpls_port->flags & BCM_MPLS_PORT_SERVICE_VLAN_ADD) || 8973 (mpls_port->flags & BCM_MPLS_PORT_SERVICE_VLAN_TPID_REPLACE) || 8974 (mpls_port->flags & BCM_MPLS_PORT_SERVICE_TPID_REPLACE) || 8975 (mpls_port->flags & BCM_MPLS_PORT_SERVICE_VLAN_PRI_TPID_REPLACE)) { 8976 _bcm_fb2_outer_tpid_tab_lock(unit); 8977 /* TPID value is used */ 8978 rv = _bcm_fb2_outer_tpid_entry_add(unit, mpls_port->service_tpid, tpid_index); 8979 _bcm_fb2_outer_tpid_tab_unlock(unit); 8980 if (rv < 0) { 8981 return rv; 8982 } 8983 soc_mem_field32_set(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 8984 vc_entry, SD_TAG_TPID_INDEXf, *tpid_index); 8985 } 8986 8987 BCM_IF_ERROR_RETURN(soc_mem_write(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 8988 MEM_BLOCK_ALL, egr_nh_info->vc_swap_index, 8989 vc_entry)); 8990 } else { 8991 8992 if ((mpls_port->criteria == BCM_MPLS_PORT_MATCH_PORT_SUBPORT_PKT_VID) || 8993 (mpls_port->criteria == BCM_MPLS_PORT_MATCH_PORT_SUBPORT_PKT_VID_INNER_VLAN) || 8994 (mpls_port->criteria == BCM_MPLS_PORT_MATCH_PORT_SUBPORT_PKT_VID_OUTER_VLAN)) { 8995 if (soc_feature(unit, soc_feature_lltag)) { 8996 if (mpls_port->flags & BCM_MPLS_PORT_SERVICE_PRI_REPLACE) { 8997 egr_nh_info->lltag_cfi = mpls_port->pkt_cfi; 8998 egr_nh_info->lltag_pri = mpls_port->pkt_pri; 8999 } 9000 egr_nh_info->lltag_vlan = mpls_port->match_subport_pkt_vid; 9001 } else { 9002 return BCM_E_PARAM; 9003 } 9004 return BCM_E_NONE; 9005 } 9006 9007 if (mpls_port->flags & BCM_MPLS_PORT_SERVICE_VLAN_ADD) { 9008 if (mpls_port->egress_service_vlan >= BCM_VLAN_INVALID) { 9009 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 9010 if (soc_feature(unit, soc_feature_vp_sharing)) { 9011 egr_nh_info->sd_tag_vlan = BCM_VLAN_INVALID; 9012 } else 9013 #endif 9014 { 9015 return BCM_E_PARAM; 9016 } 9017 } 9018 if (egr_nh_info->sd_tag_vlan != BCM_VLAN_INVALID) { 9019 egr_nh_info->sd_tag_vlan = mpls_port->egress_service_vlan; 9020 } 9021 egr_nh_info->sd_tag_action_not_present = 0x1; /* ADD */ 9022 } 9023 9024 if (mpls_port->flags & BCM_MPLS_PORT_SERVICE_VLAN_TPID_REPLACE) { 9025 if (mpls_port->egress_service_vlan >= BCM_VLAN_INVALID) { 9026 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 9027 if (soc_feature(unit, soc_feature_vp_sharing)) { 9028 egr_nh_info->sd_tag_vlan = BCM_VLAN_INVALID; 9029 } else 9030 #endif 9031 { 9032 return BCM_E_PARAM; 9033 } 9034 } 9035 /* REPLACE_VID_TPID */ 9036 if (egr_nh_info->sd_tag_vlan != BCM_VLAN_INVALID) { 9037 egr_nh_info->sd_tag_vlan = mpls_port->egress_service_vlan; 9038 } 9039 egr_nh_info->sd_tag_action_present = 0x1; 9040 } else if (mpls_port->flags & BCM_MPLS_PORT_SERVICE_VLAN_REPLACE) { 9041 9042 if (mpls_port->egress_service_vlan >= BCM_VLAN_INVALID) { 9043 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 9044 if (soc_feature(unit, soc_feature_vp_sharing)) { 9045 egr_nh_info->sd_tag_vlan = BCM_VLAN_INVALID; 9046 } else 9047 #endif 9048 { 9049 return BCM_E_PARAM; 9050 } 9051 } 9052 /* REPLACE_VID_ONLY */ 9053 if (egr_nh_info->sd_tag_vlan != BCM_VLAN_INVALID) { 9054 egr_nh_info->sd_tag_vlan = mpls_port->egress_service_vlan; 9055 } 9056 egr_nh_info->sd_tag_action_present = 0x2; 9057 } else if (mpls_port->flags & BCM_MPLS_PORT_SERVICE_VLAN_DELETE) { 9058 egr_nh_info->sd_tag_action_present = 0x3; /* DELETE */ 9059 } else if (mpls_port->flags & BCM_MPLS_PORT_SERVICE_VLAN_PRI_TPID_REPLACE) { 9060 if (soc_feature(unit, soc_feature_mpls_enhanced)) { 9061 if (mpls_port->egress_service_vlan >= BCM_VLAN_INVALID) { 9062 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 9063 if (soc_feature(unit, soc_feature_vp_sharing)) { 9064 egr_nh_info->sd_tag_vlan = BCM_VLAN_INVALID; 9065 } else 9066 #endif 9067 { 9068 return BCM_E_PARAM; 9069 } 9070 } 9071 9072 /* REPLACE_VID_PRI_TPID */ 9073 if (egr_nh_info->sd_tag_vlan != BCM_VLAN_INVALID) { 9074 egr_nh_info->sd_tag_vlan = mpls_port->egress_service_vlan; 9075 } 9076 egr_nh_info->sd_tag_pri = mpls_port->pkt_pri; 9077 if (mpls_port->flags2 & BCM_MPLS_PORT2_SERVICE_CFI_REPLACE) { 9078 if ((mpls_port->pkt_cfi == 0) || (mpls_port->pkt_cfi == 1)) { 9079 egr_nh_info->sd_tag_cfi = mpls_port->pkt_cfi; 9080 } else { 9081 return BCM_E_PARAM; 9082 } 9083 } else { 9084 egr_nh_info->sd_tag_cfi = -1; 9085 } 9086 egr_nh_info->sd_tag_action_present = 0x4; 9087 } else { 9088 return BCM_E_PARAM; 9089 } 9090 } else if (mpls_port->flags & BCM_MPLS_PORT_SERVICE_VLAN_PRI_REPLACE ) { 9091 if (soc_feature(unit, soc_feature_mpls_enhanced)) { 9092 if (mpls_port->egress_service_vlan >= BCM_VLAN_INVALID) { 9093 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 9094 if (soc_feature(unit, soc_feature_vp_sharing)) { 9095 egr_nh_info->sd_tag_vlan = BCM_VLAN_INVALID; 9096 } else 9097 #endif 9098 { 9099 return BCM_E_PARAM; 9100 } 9101 } 9102 9103 /* REPLACE_VID_PRI_ONLY */ 9104 if (egr_nh_info->sd_tag_vlan != BCM_VLAN_INVALID) { 9105 egr_nh_info->sd_tag_vlan = mpls_port->egress_service_vlan; 9106 } 9107 egr_nh_info->sd_tag_pri = mpls_port->pkt_pri; 9108 if (mpls_port->flags2 & BCM_MPLS_PORT2_SERVICE_CFI_REPLACE) { 9109 if ((mpls_port->pkt_cfi == 0) || (mpls_port->pkt_cfi == 1)) { 9110 egr_nh_info->sd_tag_cfi = mpls_port->pkt_cfi; 9111 } else { 9112 return BCM_E_PARAM; 9113 } 9114 } else { 9115 egr_nh_info->sd_tag_cfi = -1; 9116 } 9117 egr_nh_info->sd_tag_action_present = 0x5; 9118 } else { 9119 return BCM_E_PARAM; 9120 } 9121 } else if (mpls_port->flags & BCM_MPLS_PORT_SERVICE_PRI_REPLACE ) { 9122 if (soc_feature(unit, soc_feature_mpls_enhanced)) { 9123 /* REPLACE_PRI_ONLY */ 9124 egr_nh_info->sd_tag_pri = mpls_port->pkt_pri; 9125 if (mpls_port->flags2 & BCM_MPLS_PORT2_SERVICE_CFI_REPLACE) { 9126 if ((mpls_port->pkt_cfi == 0) || (mpls_port->pkt_cfi == 1)) { 9127 egr_nh_info->sd_tag_cfi = mpls_port->pkt_cfi; 9128 } else { 9129 return BCM_E_PARAM; 9130 } 9131 } else { 9132 egr_nh_info->sd_tag_cfi = -1; 9133 } 9134 egr_nh_info->sd_tag_action_present = 0x6; 9135 } else { 9136 return BCM_E_PARAM; 9137 } 9138 } else if (mpls_port->flags & BCM_MPLS_PORT_SERVICE_TPID_REPLACE ) { 9139 if (soc_feature(unit, soc_feature_mpls_enhanced)) { 9140 /* REPLACE_TPID_ONLY */ 9141 egr_nh_info->sd_tag_action_present = 0x7; 9142 } else { 9143 return BCM_E_PARAM; 9144 } 9145 9146 } 9147 9148 if ((mpls_port->flags & BCM_MPLS_PORT_SERVICE_VLAN_ADD) || 9149 (mpls_port->flags & BCM_MPLS_PORT_SERVICE_VLAN_TPID_REPLACE) || 9150 (mpls_port->flags & BCM_MPLS_PORT_SERVICE_TPID_REPLACE) || 9151 (mpls_port->flags & BCM_MPLS_PORT_SERVICE_VLAN_PRI_TPID_REPLACE)) { 9152 _bcm_fb2_outer_tpid_tab_lock(unit); 9153 /* TPID value is used */ 9154 rv = _bcm_fb2_outer_tpid_entry_add(unit, mpls_port->service_tpid, tpid_index); 9155 _bcm_fb2_outer_tpid_tab_unlock(unit); 9156 if (rv < 0) { 9157 return rv; 9158 } 9159 egr_nh_info->tpid_index = *tpid_index; 9160 } 9161 } 9162 return BCM_E_NONE; 9163 } 9164 /* 9165 * Function: 9166 * _bcm_tr_mpls_l2_old_nh_info_delete 9167 * Purpose: 9168 * Delete old L2 MPLS Next Hop entry being replaced 9169 * Parameters: 9170 * Returns: 9171 * BCM_E_XXX 9172 */ 9173 STATIC int 9174 _bcm_tr_mpls_l2_old_nh_info_delete(int unit, bcm_mpls_port_t *mpls_port, 9175 int nh_index, _bcm_mpls_old_nh_info_t *old_nh_info) 9176 { 9177 int old_vp_nh_index = -1; 9178 int egress_nh_index = -1; 9179 uint32 mpath_flag = 0; 9180 9181 if (mpls_port->flags & BCM_MPLS_PORT_REPLACE && 9182 mpls_port->flags & BCM_MPLS_PORT_EGRESS_TUNNEL) { 9183 old_vp_nh_index = old_nh_info->old_nh_index; 9184 if (old_vp_nh_index == nh_index) { 9185 old_vp_nh_index = -1; 9186 } 9187 } 9188 9189 /* Handle old VC_SWAP index. */ 9190 if ((old_nh_info->old_vc_swap_idx != -1 && old_vp_nh_index == -1) || 9191 (old_nh_info->old_vc_swap_idx != -1 && (mpls_port->flags & BCM_MPLS_PORT_ENCAP_WITH_ID))) { 9192 #if defined(BCM_TRIUMPH3_SUPPORT) 9193 if (soc_feature(unit, soc_feature_vc_and_swap_table_overlaid)) { 9194 (void)_bcm_tr_mpls_vc_and_swap_hash_nhop_delete(unit, 9195 old_nh_info->old_vc_swap_idx, 9196 nh_index); 9197 } 9198 #endif 9199 (void)_bcm_tr_mpls_vc_and_swap_ref_count_adjust(unit, 9200 old_nh_info->old_vc_swap_idx, -1); 9201 (void)_bcm_tr_mpls_vc_and_swap_table_index_reset(unit, 9202 old_nh_info->old_vc_swap_idx); 9203 } 9204 9205 /* Delete old TPID, MAC indexes */ 9206 if (old_nh_info->old_tpid_idx != -1) { 9207 (void)_bcm_fb2_outer_tpid_entry_delete(unit, old_nh_info->old_tpid_idx); 9208 } 9209 9210 if (mpls_port->flags & BCM_MPLS_PORT_ENCAP_WITH_ID) { 9211 if (old_vp_nh_index == nh_index) { 9212 old_vp_nh_index = -1; 9213 } 9214 9215 if (mpls_port->flags & BCM_MPLS_PORT_EGRESS_TUNNEL) { 9216 (void)bcm_xgs3_get_nh_from_egress_object(unit, mpls_port->egress_tunnel_if, 9217 &mpath_flag, 0, &egress_nh_index); 9218 } 9219 9220 if (old_nh_info->old_tunnel_if == mpls_port->egress_tunnel_if) { 9221 if (! (mpls_port->flags & BCM_MPLS_PORT_REPLACE)) { 9222 if (egress_nh_index != -1) { 9223 BCM_XGS3_L3_ENT_REF_CNT_DEC 9224 (BCM_XGS3_L3_TBL_PTR(unit, next_hop), egress_nh_index, _BCM_SINGLE_WIDE); 9225 } 9226 } 9227 } else { 9228 if (old_nh_info->old_tunnel_if != 0) { 9229 BCM_IF_ERROR_RETURN(bcm_xgs3_nh_del(unit, 0, 9230 (old_nh_info->old_tunnel_if - BCM_XGS3_EGRESS_IDX_MIN(unit)))); 9231 BCM_IF_ERROR_RETURN(_bcm_tr_mpls_delete_vp_nh(unit, 9232 nh_index, old_nh_info->old_tunnel_if)); 9233 } 9234 } 9235 } 9236 9237 if (old_vp_nh_index != -1) { 9238 /* Free the old_vp_next-hop entry. */ 9239 (void)_bcm_tr_mpls_l2_nh_info_delete(unit, old_vp_nh_index); 9240 } else if (old_nh_info->old_macda_idx != -1) { 9241 (void)_bcm_mac_da_profile_entry_delete(unit, old_nh_info->old_macda_idx); 9242 } 9243 return BCM_E_NONE; 9244 } 9245 /* 9246 * Function: 9247 * _bcm_tr_mpls_l2_nh_info_add 9248 * Purpose: 9249 * Create the L2 MPLS Next Hop entry 9250 * Parameters: 9251 * Returns: 9252 * BCM_E_XXX 9253 */ 9254 9255 STATIC int 9256 _bcm_tr_mpls_l2_nh_info_add(int unit, bcm_mpls_port_t *mpls_port, int vp, 9257 int drop, int is_vpws, int *vp_nh_index, 9258 bcm_port_t *local_port, int *is_local, 9259 _bcm_mpls_old_nh_info_t *old_nh_info) 9260 { 9261 egr_l3_next_hop_entry_t egr_nh; 9262 egr_mpls_vc_and_swap_label_table_entry_t vc_entry; 9263 _bcm_tr_ing_nh_info_t ing_nh_info; 9264 _bcm_tr_egr_nh_info_t egr_nh_info; 9265 bcm_l3_egress_t nh_info; 9266 int gport_id, rv=0, num_vc=0; 9267 int egress_nh_index = -1, old_vp_nh_index= -1; 9268 bcm_module_t mod_out = 0; 9269 bcm_port_t port_out = 0; 9270 bcm_trunk_t trunk_id=0; 9271 int action_present, action_not_present, tpid_index = -1; 9272 int num_mpls_map, hw_map_idx; 9273 void *entries[1]; 9274 _bcm_port_info_t *info; 9275 uint32 mpath_flag=0; 9276 bcm_port_t phys_port; 9277 bcm_gport_t gport; 9278 uint32 port_flags; 9279 #if defined(BCM_TRIUMPH2_SUPPORT) 9280 int failover_vp, failover_nh_index = -1; 9281 ing_dvp_table_entry_t failover_dvp; 9282 uint32 protection_flags=0; 9283 #endif /* BCM_TRIUMPH2_SUPPORT */ 9284 #if defined(BCM_KATANA2_SUPPORT) 9285 int my_modid = 0; 9286 #endif 9287 #if defined(BCM_KATANA2_SUPPORT) || defined(BCM_HGPROXY_COE_SUPPORT) 9288 int is_local_subport = 0; 9289 #endif 9290 #if defined(BCM_KATANA_SUPPORT) 9291 bcm_module_t module_id; /* Module ID */ 9292 bcm_port_t port_id; /* Port ID. */ 9293 int local_id; /* Hardware ID. */ 9294 int extended_queue_id; /* Subscriber queue */ 9295 ing_queue_map_entry_t ing_queue_entry; 9296 #endif /* BCM_KATANA_SUPPORT */ 9297 egr_mac_da_profile_entry_t macda; 9298 int network_group=0; 9299 9300 /* Initialize values */ 9301 *local_port = 0; 9302 *is_local = 0; 9303 ing_nh_info.mtu = 0; /*Default, especially if MTU_SIZE is not valid */ 9304 if (mpls_port->mtu != 0) { 9305 ing_nh_info.mtu = mpls_port->mtu; 9306 } else if (SOC_MEM_FIELD_VALID(unit, ING_L3_NEXT_HOPm, MTU_SIZEf)) { 9307 ing_nh_info.mtu = 9308 (1 << soc_mem_field_length(unit, ING_L3_NEXT_HOPm, MTU_SIZEf)) - 1; 9309 } 9310 ing_nh_info.port = -1; 9311 ing_nh_info.module = -1; 9312 ing_nh_info.trunk = -1; 9313 ing_nh_info.qtag = -1; 9314 ing_nh_info.tag_type = -1; 9315 9316 egr_nh_info.dvp = vp; 9317 egr_nh_info.entry_type = -1; 9318 egr_nh_info.sd_tag_action_present = -1; 9319 egr_nh_info.sd_tag_action_not_present = -1; 9320 egr_nh_info.intf_num = -1; 9321 egr_nh_info.sd_tag_vlan = -1; 9322 egr_nh_info.sd_tag_pri = -1; 9323 egr_nh_info.sd_tag_cfi = -1; 9324 egr_nh_info.lltag_vlan = -1; 9325 egr_nh_info.lltag_pri = -1; 9326 egr_nh_info.lltag_cfi = -1; 9327 egr_nh_info.macda_index = -1; 9328 egr_nh_info.vc_swap_index = -1; 9329 egr_nh_info.tpid_index = -1; 9330 egr_nh_info.pw_init_cnt = -1; 9331 egr_nh_info.vintf_ctr_index = -1; 9332 egr_nh_info.flex_ctr_base_cnt_idx = -1; 9333 egr_nh_info.dvp_network_group_id = 0; 9334 egr_nh_info.class_id = -1; 9335 egr_nh_info.oam_global_context_id = 0; 9336 9337 old_nh_info->old_nh_index = *vp_nh_index; 9338 old_nh_info->old_tunnel_if = 0; 9339 old_nh_info->old_tpid_idx = -1; 9340 old_nh_info->old_macda_idx = -1; 9341 old_nh_info->old_vc_swap_idx = -1; 9342 9343 if (soc_feature(unit, soc_feature_multiple_split_horizon_group)) { 9344 network_group = mpls_port->network_group_id; 9345 rv = _bcm_validate_splithorizon_network_group(unit, 9346 mpls_port->flags & BCM_MPLS_PORT_NETWORK, &network_group); 9347 BCM_IF_ERROR_RETURN(rv); 9348 egr_nh_info.dvp_network_group_id = network_group; 9349 } 9350 if ((mpls_port->flags & BCM_MPLS_PORT_EGRESS_TUNNEL) && 9351 (mpls_port->flags & BCM_MPLS_PORT_NETWORK) ) { 9352 egr_nh_info.dvp_is_network = 1; 9353 } else { 9354 egr_nh_info.dvp_is_network = 0; 9355 } 9356 if ((mpls_port->flags & BCM_MPLS_PORT_ENCAP_WITH_ID) || 9357 (mpls_port->flags & BCM_MPLS_PORT_REPLACE)) { 9358 rv = bcm_tr_mpls_get_vp_nh (unit, *vp_nh_index, &old_nh_info->old_tunnel_if); 9359 if (rv == BCM_E_NOT_FOUND) { 9360 old_nh_info->old_tunnel_if = 0; 9361 } else if (BCM_FAILURE(rv)) { 9362 return rv; 9363 } 9364 } 9365 9366 if (mpls_port->flags & BCM_MPLS_PORT_REPLACE) { 9367 if ((*vp_nh_index > soc_mem_index_max(unit, EGR_L3_NEXT_HOPm)) || 9368 (*vp_nh_index < soc_mem_index_min(unit, EGR_L3_NEXT_HOPm))) { 9369 return BCM_E_PARAM; 9370 } 9371 /* Read the existing egress next_hop entry */ 9372 rv = soc_mem_read(unit, EGR_L3_NEXT_HOPm, MEM_BLOCK_ANY, 9373 *vp_nh_index, &egr_nh); 9374 BCM_IF_ERROR_RETURN(rv); 9375 } else { 9376 /* Allocate MPLS VP Next Hop */ 9377 BCM_IF_ERROR_RETURN(_bcm_tr_mpls_create_vp_nh 9378 (unit, mpls_port->egress_tunnel_if, vp_nh_index, mpls_port)); 9379 if ((mpls_port->flags & BCM_MPLS_PORT_ENCAP_WITH_ID) && (!old_nh_info->old_tunnel_if)) { 9380 /* increase the reference count to indicates the given next hop is used by mpls port*/ 9381 BCM_XGS3_L3_ENT_REF_CNT_INC 9382 (BCM_XGS3_L3_TBL_PTR(unit, next_hop), *vp_nh_index, _BCM_SINGLE_WIDE); 9383 9384 } 9385 } 9386 9387 /* 9388 * Indexes in the first half of EGR_MPLS_VC_AND_SWAP_LABEL_TABLE 9389 * also get used as the index into the EGR_PW_INIT_COUNTERS table. 9390 * Set num_vc to half the EGR_MPLS_VC_AND_SWAP_LABEL_TABLE size. 9391 */ 9392 num_vc = soc_mem_index_count(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm); 9393 num_vc /= 2; 9394 9395 if (mpls_port->flags & BCM_MPLS_PORT_EGRESS_TUNNEL) { 9396 9397 num_mpls_map = soc_mem_index_count(unit, EGR_MPLS_EXP_MAPPING_1m) / 64; 9398 if (mpls_port->egress_label.qos_map_id == 0) { 9399 hw_map_idx = 0; /* use default */ 9400 } else { 9401 BCM_IF_ERROR_RETURN(_egr_qos_id2hw_idx(unit, 9402 mpls_port->egress_label.qos_map_id,&hw_map_idx)); 9403 } 9404 9405 if (hw_map_idx < 0 || hw_map_idx >= num_mpls_map) { 9406 rv = BCM_E_PARAM; 9407 goto cleanup; 9408 } 9409 9410 /* Egressing into an MPLS tunnel */ 9411 if (!BCM_XGS3_L3_EGRESS_IDX_VALID(unit, mpls_port->egress_tunnel_if)) { 9412 /* invalid egress object */ 9413 rv = BCM_E_PARAM; 9414 goto cleanup; 9415 } else if (mpls_port->flags & BCM_MPLS_PORT_REPLACE) { 9416 /* Be sure that the existing entry is already setup to 9417 * egress into an MPLS tunnel. If not, return BCM_E_PARAM. 9418 */ 9419 egr_nh_info.entry_type = 9420 soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, nh_entry_type_field[unit]); 9421 if (egr_nh_info.entry_type != 0x1) { /* != MPLS_MACDA_PROFILE */ 9422 rv = BCM_E_PARAM; 9423 goto cleanup; 9424 } 9425 9426 if (soc_feature(unit, soc_feature_mpls_enhanced)) { 9427 /* TD2 should defines BCM_TRIUMPH3_SUPPORT */ 9428 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) 9429 if (soc_feature(unit,soc_feature_advanced_flex_counter)) { 9430 egr_nh_info.flex_ctr_base_cnt_idx = 9431 soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_nh, 9432 MPLS__FLEX_CTR_BASE_COUNTER_IDXf); 9433 egr_nh_info.flex_ctr_pool_num = 9434 soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_nh, 9435 MPLS__FLEX_CTR_POOL_NUMBERf); 9436 egr_nh_info.flex_ctr_offset_mode = 9437 soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_nh, 9438 MPLS__FLEX_CTR_OFFSET_MODEf); 9439 } else 9440 #endif 9441 if (soc_feature(unit, soc_feature_gport_service_counters)) { 9442 egr_nh_info.vintf_ctr_index = 9443 soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_nh, 9444 MPLS__VINTF_CTR_IDXf); 9445 } 9446 } 9447 9448 /* Remember old MAC_DA_PROFILE_INDEX, VC_AND_SWAP_INDEX */ 9449 if (soc_feature(unit, soc_feature_mpls_enhanced)) { 9450 old_nh_info->old_macda_idx = 9451 soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, 9452 MPLS__MAC_DA_PROFILE_INDEXf); 9453 old_nh_info->old_vc_swap_idx = 9454 soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, 9455 MPLS__VC_AND_SWAP_INDEXf); 9456 } else { 9457 old_nh_info->old_macda_idx = 9458 soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, 9459 MAC_DA_PROFILE_INDEXf); 9460 old_nh_info->old_vc_swap_idx = 9461 soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, 9462 VC_AND_SWAP_INDEXf); 9463 } 9464 9465 /* Remember old TPID index if it's used */ 9466 rv = soc_mem_read(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 9467 MEM_BLOCK_ALL, old_nh_info->old_vc_swap_idx, &vc_entry); 9468 _BCM_MPLS_CLEANUP(rv); 9469 action_present = 9470 soc_EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm_field32_get(unit, 9471 &vc_entry, 9472 SD_TAG_ACTION_IF_PRESENTf); 9473 action_not_present = 9474 soc_EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm_field32_get(unit, 9475 &vc_entry, 9476 SD_TAG_ACTION_IF_NOT_PRESENTf); 9477 if ((action_not_present == 0x1) || (action_present == 0x1)) { 9478 /* If SD tag action is ADD or REPLACE_VID_TPID, the tpid 9479 * index of the entry getting replaced is valid. Save 9480 * the old tpid index to be deleted later. 9481 */ 9482 old_nh_info->old_tpid_idx = 9483 soc_EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm_field32_get(unit, 9484 &vc_entry, SD_TAG_TPID_INDEXf); 9485 } 9486 9487 /* Remember old vc_nh_index */ 9488 old_vp_nh_index = *vp_nh_index; 9489 9490 /* Allocate MPLS VP Next Hop */ 9491 if (old_nh_info->old_tunnel_if != mpls_port->egress_tunnel_if) { 9492 BCM_IF_ERROR_RETURN(_bcm_tr_mpls_create_vp_nh 9493 (unit, mpls_port->egress_tunnel_if, vp_nh_index, 9494 mpls_port)); 9495 } 9496 } 9497 9498 /* 9499 * Get egress next-hop index from egress object and 9500 * increment egress object reference count. 9501 */ 9502 if (old_vp_nh_index != *vp_nh_index) { 9503 rv = bcm_xgs3_get_nh_from_egress_object(unit, mpls_port->egress_tunnel_if, 9504 &mpath_flag, 1, &egress_nh_index); 9505 } else { 9506 if ((mpls_port->flags & BCM_MPLS_PORT_ENCAP_WITH_ID) && 9507 (mpls_port->flags & BCM_MPLS_PORT_REPLACE) && 9508 (old_nh_info->old_tunnel_if != mpls_port->egress_tunnel_if)) { 9509 rv = bcm_xgs3_get_nh_from_egress_object(unit, mpls_port->egress_tunnel_if, 9510 &mpath_flag, 1, &egress_nh_index); 9511 } else { 9512 rv = bcm_xgs3_get_nh_from_egress_object(unit, mpls_port->egress_tunnel_if, 9513 &mpath_flag, 0, &egress_nh_index); 9514 } 9515 } 9516 _BCM_MPLS_CLEANUP(rv); 9517 9518 rv = bcm_xgs3_nh_get(unit, egress_nh_index, &nh_info); 9519 _BCM_MPLS_CLEANUP(rv); 9520 9521 #if defined(BCM_KATANA_SUPPORT) 9522 if (SOC_IS_KATANAX(unit)) { 9523 ing_l3_next_hop_entry_t in_nh; 9524 9525 rv = soc_mem_read (unit, ING_L3_NEXT_HOPm, 9526 MEM_BLOCK_ALL, egress_nh_index, &in_nh); 9527 _BCM_MPLS_CLEANUP(rv); 9528 ing_nh_info.qtag = soc_ING_L3_NEXT_HOPm_field32_get(unit, &in_nh, 9529 EH_QUEUE_TAGf); 9530 ing_nh_info.tag_type = soc_ING_L3_NEXT_HOPm_field32_get(unit, 9531 &in_nh, 9532 EH_TAG_TYPEf); 9533 } 9534 #endif 9535 9536 /* make sure (mod/port) is local(single modid) view */ 9537 rv = _bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_SET, 9538 nh_info.module, nh_info.port, 9539 &nh_info.module, &nh_info.port); 9540 BCM_IF_ERROR_RETURN(rv); 9541 9542 if (nh_info.flags & BCM_L3_TGID) { 9543 ing_nh_info.port = -1; 9544 ing_nh_info.module = -1; 9545 ing_nh_info.trunk = nh_info.trunk; 9546 trunk_id = nh_info.trunk; 9547 } else { 9548 ing_nh_info.port = nh_info.port; 9549 port_out = nh_info.port; 9550 ing_nh_info.module = nh_info.module; 9551 mod_out = nh_info.module; 9552 ing_nh_info.trunk = -1; 9553 } 9554 9555 egr_nh_info.intf_num = nh_info.intf; 9556 egr_nh_info.entry_type = 0x1; /* MPLS_MACDA_PROFILE */ 9557 egr_nh_info.oam_global_context_id = nh_info.oam_global_context_id; 9558 9559 sal_memset(&macda, 0, sizeof(egr_mac_da_profile_entry_t)); 9560 soc_mem_mac_addr_set(unit, EGR_MAC_DA_PROFILEm, 9561 &macda, MAC_ADDRESSf, nh_info.mac_addr); 9562 entries[0] = &macda; 9563 rv = _bcm_mac_da_profile_entry_add(unit, entries, 1, 9564 (uint32 *) &egr_nh_info.macda_index); 9565 _BCM_MPLS_CLEANUP(rv); 9566 9567 if ((mpls_port->flags & BCM_MPLS_PORT_COUNTED) || 9568 (mpls_port->flags & BCM_MPLS_PORT_SEQUENCED)) { 9569 9570 rv = _bcm_tr_mpls_get_vc_and_swap_table_index (unit, 9571 _BCM_MPLS_ACTION_SEQUENCE, 9572 mpls_port, NULL, NULL, NULL, 9573 _BCM_MPLS_ACTION_PUSH, 9574 &egr_nh_info.vc_swap_index); 9575 _BCM_MPLS_CLEANUP(rv); 9576 9577 rv = _bcm_tr_mpls_pw_init_counter_set (unit, mpls_port->pw_seq_number, &egr_nh_info); 9578 _BCM_MPLS_CLEANUP(rv); 9579 9580 } else { 9581 9582 rv = _bcm_tr_mpls_get_vc_and_swap_table_index (unit, 0, 9583 mpls_port, NULL, NULL, NULL, 9584 _BCM_MPLS_ACTION_PUSH, 9585 &egr_nh_info.vc_swap_index); 9586 _BCM_MPLS_CLEANUP(rv); 9587 } 9588 /* Program the MPLS_VC_AND_SWAP table entry */ 9589 rv = _bcm_tr_mpls_vc_and_swap_table_entry_set(unit, mpls_port, NULL, NULL, 9590 _BCM_MPLS_ACTION_PUSH, &vc_entry, hw_map_idx, 9591 egr_nh_info.vc_swap_index); 9592 _BCM_MPLS_CLEANUP(rv); 9593 /* SD_TAG setting */ 9594 rv = _bcm_tr_mpls_sd_tag_set(unit, mpls_port, &egr_nh_info, &vc_entry, &tpid_index); 9595 _BCM_MPLS_CLEANUP(rv); 9596 9597 rv = soc_mem_write(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 9598 MEM_BLOCK_ALL, egr_nh_info.vc_swap_index, 9599 &vc_entry); 9600 _BCM_MPLS_CLEANUP(rv); 9601 } else { 9602 if (mpls_port->flags & BCM_MPLS_PORT_REPLACE) { 9603 /* Be sure that the existing entry is not egressing into 9604 * an MPLS tunnel. If it is, return BCM_E_PARAM. 9605 */ 9606 egr_nh_info.entry_type = 9607 soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, nh_entry_type_field[unit]); 9608 if (egr_nh_info.entry_type != 0x2) { /* != MPLS_SD_TAG_ACTIONS */ 9609 rv = BCM_E_PARAM; 9610 goto cleanup; 9611 } 9612 9613 if (soc_feature(unit, soc_feature_mpls_enhanced)) { 9614 action_present = 9615 soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, 9616 SD_TAG__SD_TAG_ACTION_IF_PRESENTf); 9617 action_not_present = 9618 soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, 9619 SD_TAG__SD_TAG_ACTION_IF_NOT_PRESENTf); 9620 } else { 9621 action_present = 9622 soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, 9623 SD_TAG_ACTION_IF_PRESENTf); 9624 action_not_present = 9625 soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, 9626 SD_TAG_ACTION_IF_NOT_PRESENTf); 9627 } 9628 if ((action_not_present == 0x1) || (action_present == 0x1)) { 9629 /* If SD tag action is ADD or REPLACE_VID_TPID, the tpid 9630 * index of the entry getting replaced is valid. Save 9631 * the old tpid index to be deleted later. 9632 */ 9633 if (soc_feature(unit, soc_feature_mpls_enhanced)) { 9634 old_nh_info->old_tpid_idx = 9635 soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, 9636 SD_TAG__SD_TAG_TPID_INDEXf); 9637 } else { 9638 old_nh_info->old_tpid_idx = 9639 soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, 9640 SD_TAG_TPID_INDEXf); 9641 } 9642 } 9643 9644 if (soc_feature(unit, soc_feature_mpls_enhanced) && 9645 soc_feature(unit, soc_feature_gport_service_counters)) { 9646 egr_nh_info.vintf_ctr_index = 9647 soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_nh, 9648 SD_TAG__VINTF_CTR_IDXf); 9649 } 9650 if (soc_feature(unit, soc_feature_mpls_enhanced)) { 9651 /* TD2 should defines BCM_TRIUMPH3_SUPPORT */ 9652 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) 9653 if (soc_feature(unit,soc_feature_advanced_flex_counter)) { 9654 egr_nh_info.flex_ctr_base_cnt_idx = 9655 soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_nh, 9656 SD_TAG__FLEX_CTR_BASE_COUNTER_IDXf); 9657 egr_nh_info.flex_ctr_pool_num = 9658 soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_nh, 9659 SD_TAG__FLEX_CTR_POOL_NUMBERf); 9660 egr_nh_info.flex_ctr_offset_mode = 9661 soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_nh, 9662 SD_TAG__FLEX_CTR_OFFSET_MODEf); 9663 } else 9664 #endif 9665 if (soc_feature(unit, soc_feature_gport_service_counters)) { 9666 egr_nh_info.vintf_ctr_index = 9667 soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_nh, 9668 SD_TAG__VINTF_CTR_IDXf); 9669 } 9670 } 9671 } 9672 9673 egr_nh_info.entry_type = 0x2; /* MPLS_SD_TAG_ACTIONS */ 9674 9675 if ((mpls_port->criteria != BCM_MPLS_PORT_MATCH_VLAN) || 9676 (mpls_port->port != BCM_GPORT_INVALID)) { 9677 rv = _bcm_esw_gport_resolve(unit, mpls_port->port, &mod_out, 9678 &port_out, &trunk_id, &gport_id); 9679 _BCM_MPLS_CLEANUP(rv); 9680 } 9681 9682 if (BCM_GPORT_IS_TRUNK(mpls_port->port)) { 9683 ing_nh_info.module = -1; 9684 ing_nh_info.port = -1; 9685 ing_nh_info.trunk = trunk_id; 9686 } else { 9687 ing_nh_info.module = mod_out; 9688 ing_nh_info.port = port_out; 9689 ing_nh_info.trunk = -1; 9690 } 9691 9692 /* SD_TAG setting */ 9693 rv = _bcm_tr_mpls_sd_tag_set(unit, mpls_port, &egr_nh_info, &vc_entry, &tpid_index); 9694 _BCM_MPLS_CLEANUP(rv); 9695 9696 } 9697 9698 /* CLASS ID */ 9699 if (mpls_port->egress_class_id != BCM_CLASS_ID_INVALID) { 9700 int len = 0; 9701 9702 if ((mpls_port->flags & BCM_MPLS_PORT_EGRESS_TUNNEL) && 9703 (mpls_port->egress_class_id == nh_info.intf_class)) { 9704 /* 9705 * if you want to have same interface class, then 9706 * add it through next hop. 9707 */ 9708 return BCM_E_PARAM; 9709 } 9710 9711 len = soc_mem_field_length(unit, EGR_L3_NEXT_HOPm, MPLS__CLASS_IDf); 9712 if (mpls_port->egress_class_id >= (1 << len)) { 9713 return BCM_E_PARAM; 9714 } 9715 9716 egr_nh_info.class_id = mpls_port->egress_class_id; 9717 } else if (mpls_port->flags & BCM_MPLS_PORT_EGRESS_TUNNEL) { 9718 egr_nh_info.class_id = nh_info.intf_class; 9719 } 9720 9721 /* Update the physical port's SW state */ 9722 rv = _bcm_esw_modid_is_local(unit, ing_nh_info.module, is_local); 9723 _BCM_MPLS_CLEANUP(rv); 9724 9725 #if defined(BCM_HGPROXY_COE_SUPPORT) 9726 if (soc_feature(unit, soc_feature_hgproxy_subtag_coe) && 9727 BCM_GPORT_IS_SET(mpls_port->port) && 9728 _BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, 9729 mpls_port->port)) { 9730 9731 if(_bcmi_coe_subport_mod_port_physical_port_get(unit, mod_out, 9732 port_out, &phys_port) == BCM_E_NONE) { 9733 is_local_subport = 1; 9734 } 9735 } 9736 9737 if (is_local_subport) { 9738 _bcm_port_info_access(unit, phys_port, &info); 9739 info->vp_count++; 9740 /* Update the physical port's attributes */ 9741 rv = bcm_esw_port_vlan_member_get(unit, phys_port, &port_flags); 9742 _BCM_MPLS_CLEANUP(rv); 9743 9744 rv = bcm_esw_port_vlan_member_set(unit, phys_port, port_flags); 9745 _BCM_MPLS_CLEANUP(rv); 9746 } else 9747 #endif 9748 9749 #if defined(BCM_KATANA2_SUPPORT) 9750 if (BCM_GPORT_IS_SET(mpls_port->port) && 9751 _BCM_KT2_GPORT_IS_LINKPHY_OR_SUBTAG_SUBPORT_GPORT(unit, 9752 mpls_port->port)) { 9753 rv = bcm_esw_stk_my_modid_get(unit, &my_modid); 9754 _BCM_MPLS_CLEANUP(rv); 9755 if (_bcm_kt2_mod_is_coe_mod_check(unit, mod_out) == BCM_E_NONE) { 9756 rv = _bcm_kt2_modport_to_pp_port_get( 9757 unit, mod_out, port_out, &phys_port); 9758 _BCM_MPLS_CLEANUP(rv); 9759 if (_bcm_kt2_is_pp_port_linkphy_subtag(unit, phys_port)){ 9760 is_local_subport = 1; 9761 } 9762 } 9763 } 9764 9765 if (is_local_subport) { 9766 _bcm_port_info_access(unit, phys_port, &info); 9767 info->vp_count++; 9768 /* Update the physical port's attributes */ 9769 rv = bcm_esw_port_vlan_member_get(unit, phys_port, &port_flags); 9770 _BCM_MPLS_CLEANUP(rv); 9771 9772 rv = bcm_esw_port_vlan_member_set(unit, phys_port, port_flags); 9773 _BCM_MPLS_CLEANUP(rv); 9774 } else 9775 #endif 9776 9777 if (*is_local) { 9778 9779 BCM_GPORT_MODPORT_SET(gport, ing_nh_info.module, ing_nh_info.port); 9780 BCM_IF_ERROR_RETURN(bcm_esw_port_local_get(unit, gport, &phys_port)); 9781 9782 _bcm_port_info_access(unit, phys_port, &info); 9783 info->vp_count++; 9784 /* Update the physical port's attributes */ 9785 rv = bcm_esw_port_vlan_member_get(unit, phys_port, &port_flags); 9786 _BCM_MPLS_CLEANUP(rv); 9787 9788 rv = bcm_esw_port_vlan_member_set(unit, phys_port, port_flags); 9789 _BCM_MPLS_CLEANUP(rv); 9790 9791 } 9792 9793 /* If associated with a trunk, update each local physical port's SW state */ 9794 if (ing_nh_info.trunk != -1) { 9795 #if defined(BCM_ESW_SUPPORT) && (SOC_MAX_NUM_PP_PORTS > SOC_MAX_NUM_PORTS) 9796 int max_num_port = SOC_MAX_NUM_PP_PORTS; 9797 bcm_port_t local_member_array[SOC_MAX_NUM_PP_PORTS]; 9798 #else 9799 int max_num_port = SOC_MAX_NUM_PORTS; 9800 bcm_port_t local_member_array[SOC_MAX_NUM_PORTS]; 9801 #endif 9802 int local_member_count; 9803 int idx; 9804 uint32 port_flags; 9805 9806 rv = _bcm_esw_trunk_local_members_get(unit, trunk_id, 9807 max_num_port, local_member_array, &local_member_count); 9808 _BCM_MPLS_CLEANUP(rv); 9809 9810 for (idx = 0; idx < local_member_count; idx++) { 9811 _bcm_port_info_access(unit, local_member_array[idx], &info); 9812 info->vp_count++; 9813 9814 /* Update the physical port's attributes */ 9815 rv = bcm_esw_port_vlan_member_get(unit, local_member_array[idx], &port_flags); 9816 _BCM_MPLS_CLEANUP(rv); 9817 rv = bcm_esw_port_vlan_member_set(unit, local_member_array[idx], port_flags); 9818 _BCM_MPLS_CLEANUP(rv); 9819 } 9820 } 9821 9822 /* Write INITIAL_ING_L3_NEXT_HOP entry */ 9823 rv = _bcm_tr_mpls_INITIAL_ING_L3_NEXT_HOP_add(unit, 9824 &ing_nh_info, *vp_nh_index, 9825 local_port, is_local); 9826 _BCM_MPLS_CLEANUP(rv); 9827 9828 /* Write EGR_L3_NEXT_HOP entry */ 9829 rv = _bcm_tr_mpls_EGR_L3_NEXT_HOP_add(unit, &egr_nh_info, 9830 mpls_port->flags2, *vp_nh_index, 9831 is_local, is_vpws, drop); 9832 _BCM_MPLS_CLEANUP(rv); 9833 9834 #if defined(INCLUDE_XFLOW_MACSEC) && defined(BCM_MONTEREY_SUPPORT) 9835 if (soc_feature(unit, soc_feature_xflow_macsec) && 9836 BCM_XGS3_L3_EGRESS_IDX_VALID(unit, mpls_port->egress_tunnel_if) && 9837 SOC_IS_MONTEREY(unit)) { 9838 egr_l3_next_hop_entry_t egr_tunnel_nh; 9839 rv = soc_mem_read(unit, EGR_L3_NEXT_HOPm, MEM_BLOCK_ANY, egress_nh_index, &egr_tunnel_nh); 9840 _BCM_MPLS_CLEANUP(rv); 9841 9842 if (soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_tunnel_nh, 9843 MPLS__MACSEC_ENCRYPTf)) { 9844 rv = soc_mem_read(unit, EGR_L3_NEXT_HOPm, MEM_BLOCK_ANY, *vp_nh_index, &egr_nh); 9845 _BCM_MPLS_CLEANUP(rv); 9846 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 9847 MPLS__MACSEC_ENCRYPTf, 1); 9848 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 9849 MPLS__HG_MODIFY_ENABLEf, 9850 soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_tunnel_nh, 9851 MPLS__HG_MODIFY_ENABLEf)); 9852 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 9853 MPLS__HG_MC_DST_PORT_NUMf, 9854 soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_tunnel_nh, 9855 MPLS__HG_MC_DST_PORT_NUMf)); 9856 rv = soc_mem_write (unit, EGR_L3_NEXT_HOPm, MEM_BLOCK_ALL, *vp_nh_index, 9857 &egr_nh); 9858 9859 _BCM_MPLS_CLEANUP(rv); 9860 } 9861 } 9862 #endif 9863 #if defined(BCM_TRIUMPH3_SUPPORT) 9864 if (soc_feature(unit, soc_feature_mpls_enhanced)) { 9865 egr_l3_next_hop_entry_t egr_nh; 9866 rv = soc_mem_read(unit, EGR_L3_NEXT_HOPm, MEM_BLOCK_ANY, *vp_nh_index, &egr_nh); 9867 _BCM_MPLS_CLEANUP(rv); 9868 9869 if (SOC_IS_TRIUMPH3(unit) && soc_mem_field_valid(unit, EGR_L3_NEXT_HOPm, 9870 MPLS__DO_EVXLT_AFTER_TUNNEL_ENCAPf)) { 9871 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 9872 MPLS__DO_EVXLT_AFTER_TUNNEL_ENCAPf, 9873 (mpls_port->flags2 & 9874 BCM_MPLS_PORT2_TUNNEL_HEADER_EGRESS_VLAN_TRANSLATION) != 0); 9875 } 9876 rv = soc_mem_write (unit, EGR_L3_NEXT_HOPm, MEM_BLOCK_ALL, *vp_nh_index, 9877 &egr_nh); 9878 9879 _BCM_MPLS_CLEANUP(rv); 9880 } 9881 #endif 9882 9883 #ifdef BCM_TRIDENT2PLUS_SUPPORT 9884 if (soc_feature(unit, soc_feature_egress_failover)) { 9885 egr_l3_next_hop_entry_t egr_nh; 9886 int local_failover_id=0,prot_type=0; 9887 if (mpls_port->egress_failover_id!=0) { 9888 local_failover_id=mpls_port->egress_failover_id; 9889 _BCM_GET_FAILOVER_TYPE(local_failover_id, prot_type); 9890 if (prot_type & _BCM_FAILOVER_1_1_MC_PROTECTION_MODE) { 9891 _BCM_GET_FAILOVER_ID(local_failover_id); 9892 9893 BCM_IF_ERROR_RETURN (soc_mem_read(unit, EGR_L3_NEXT_HOPm, 9894 MEM_BLOCK_ANY, *vp_nh_index, &egr_nh)); 9895 9896 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 9897 MPLS__PROT_GROUPf, local_failover_id); 9898 9899 rv = soc_mem_write(unit, EGR_L3_NEXT_HOPm, 9900 MEM_BLOCK_ALL, *vp_nh_index, &egr_nh); 9901 } 9902 } 9903 } 9904 #endif 9905 #ifdef BCM_KATANA_SUPPORT 9906 if (soc_feature(unit, soc_feature_extended_queueing)) { 9907 if ((BCM_GPORT_IS_UCAST_QUEUE_GROUP(mpls_port->per_flow_queue_base)) || 9908 (BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP 9909 (mpls_port->per_flow_queue_base)) || 9910 (BCM_GPORT_IS_MCAST_SUBSCRIBER_QUEUE_GROUP 9911 (mpls_port->per_flow_queue_base))) { 9912 _BCM_MPLS_CLEANUP(_bcm_esw_gport_resolve(unit, 9913 mpls_port->per_flow_queue_base, 9914 &port_id, 9915 &module_id, 9916 &extended_queue_id, 9917 &local_id)); 9918 if (((mpls_port->qos_map_id >> _BCM_QOS_MAP_SHIFT) == 9919 _BCM_QOS_MAP_TYPE_ING_QUEUE_OFFSET_MAP_TABLE) && 9920 ((mpls_port->qos_map_id & _BCM_QOS_MAP_TYPE_MASK) <= 9921 _BCM_QOS_MAP_ING_QUEUE_OFFSET_MAX)) { 9922 /* ING_QUEUE_MAP needs to be configured */ 9923 sal_memset(&ing_queue_entry, 0, sizeof(ing_queue_map_entry_t)); 9924 soc_mem_field32_set(unit, ING_QUEUE_MAPm, &ing_queue_entry, 9925 QUEUE_SET_BASEf, extended_queue_id); 9926 soc_mem_field32_set(unit, ING_QUEUE_MAPm, &ing_queue_entry, 9927 QUEUE_OFFSET_PROFILE_INDEXf, 9928 (mpls_port->qos_map_id & _BCM_QOS_MAP_TYPE_MASK)); 9929 _BCM_MPLS_CLEANUP(BCM_XGS3_MEM_WRITE(unit, ING_QUEUE_MAPm, 9930 extended_queue_id, 9931 &ing_queue_entry)); 9932 /* Derive actual queue from qos map */ 9933 ing_nh_info.tag_type = EH_TAG_TYPE_ING_QUEUE_MAP; 9934 ing_nh_info.qtag = extended_queue_id; 9935 9936 /* Update ING_QUEUE_MAP reference count */ 9937 _bcm_tr_mpls_ing_queue_map_ref_count_adjust (unit, 9938 extended_queue_id, 9939 +1); 9940 9941 } else { 9942 /* use extended_queue_id as Queue */ 9943 ing_nh_info.tag_type = EH_TAG_TYPE_EXPLICT_QUEUE; 9944 ing_nh_info.qtag = extended_queue_id; 9945 } 9946 } 9947 if ((mpls_port->flags & BCM_MPLS_PORT_REPLACE) && 9948 (0 == mpls_port->per_flow_queue_base)) { 9949 if (ing_nh_info.qtag > 0) { 9950 if (ing_nh_info.tag_type == EH_TAG_TYPE_ING_QUEUE_MAP) { 9951 /* Update ING_QUEUE_MAP reference count */ 9952 _bcm_tr_mpls_ing_queue_map_ref_count_adjust (unit, 9953 ing_nh_info.qtag, 9954 -1); 9955 /* ING_QUEUE_MAP needs to be reset */ 9956 _BCM_MPLS_CLEANUP( 9957 _bcm_tr_mpls_ing_queue_map_index_reset (unit, 9958 ing_nh_info.qtag)); 9959 } 9960 ing_nh_info.qtag = 0; 9961 ing_nh_info.tag_type = EH_TAG_TYPE_NONE; /* No HQOS */ 9962 } 9963 } 9964 } 9965 #endif /* BCM_KATANA_SUPPORT */ 9966 /* Write ING_L3_NEXT_HOP entry */ 9967 rv = _bcm_tr_mpls_ING_L3_NEXT_HOP_add(unit, &ing_nh_info, 9968 *vp_nh_index, drop); 9969 _BCM_MPLS_CLEANUP(rv); 9970 9971 #if defined(BCM_TRIUMPH2_SUPPORT) 9972 if (soc_feature(unit, soc_feature_mpls_failover)) { 9973 if (BCM_SUCCESS(_bcm_esw_failover_mpls_check(unit, mpls_port))) { 9974 failover_vp = BCM_GPORT_MPLS_PORT_ID_GET(mpls_port->failover_port_id); 9975 if (failover_vp != -1) { 9976 rv = READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, failover_vp, &failover_dvp); 9977 _BCM_MPLS_CLEANUP(rv); 9978 9979 failover_nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &failover_dvp, 9980 NEXT_HOP_INDEXf); 9981 } 9982 9983 if (_BCM_MULTICAST_IS_SET(mpls_port->failover_mc_group)) { 9984 protection_flags |= _BCM_FAILOVER_1_PLUS_PROTECTION; 9985 } 9986 if (mpls_port->flags & BCM_MPLS_PORT_FAILOVER) { 9987 bcm_failover_t failover_id; 9988 int multicast_group; 9989 rv = _bcm_esw_failover_prot_nhi_get(unit, failover_nh_index, 9990 &failover_id, &old_nh_info->old_nh_index, &multicast_group); 9991 _BCM_MPLS_CLEANUP(rv); 9992 /* coverity[negative_returns : FALSE] */ 9993 rv = _bcm_esw_failover_prot_nhi_create(unit, protection_flags, failover_nh_index, 9994 (uint32) *vp_nh_index, mpls_port->failover_mc_group, mpls_port->failover_id); 9995 _BCM_MPLS_CLEANUP(rv); 9996 9997 if (old_nh_info->old_nh_index == 0) { 9998 old_nh_info->old_nh_index = -1; 9999 } 10000 } else { 10001 rv = _bcm_esw_failover_prot_nhi_create(unit, protection_flags, (uint32) *vp_nh_index, 10002 failover_nh_index, mpls_port->failover_mc_group, mpls_port->failover_id); 10003 10004 _BCM_MPLS_CLEANUP(rv); 10005 } 10006 } else if ((mpls_port->flags & BCM_MPLS_PORT_REPLACE) && 10007 (mpls_port->flags & BCM_MPLS_PORT_EGRESS_TUNNEL)&& 10008 (old_vp_nh_index != *vp_nh_index) && 10009 (mpls_port->flags & BCM_MPLS_PORT_FAILOVER)) { 10010 10011 rv = _bcm_esw_failover_prot_nhi_update(unit, old_vp_nh_index, (uint32) *vp_nh_index ); 10012 _BCM_MPLS_CLEANUP(rv); 10013 } 10014 } 10015 #endif /* BCM_TRIUMPH2_SUPPORT */ 10016 #if defined(BCM_TRIUMPH3_SUPPORT) 10017 if ((mpls_port->flags & BCM_MPLS_PORT_EGRESS_TUNNEL) && 10018 soc_feature(unit, soc_feature_vc_and_swap_table_overlaid)) { 10019 rv = _bcm_tr_mpls_vc_and_swap_hash_nhop_add(unit, 10020 egr_nh_info.vc_swap_index, 10021 *vp_nh_index); 10022 _BCM_MPLS_CLEANUP(rv); 10023 } 10024 #endif 10025 return rv; 10026 10027 cleanup: 10028 if (!(mpls_port->flags & BCM_MPLS_PORT_REPLACE)) { 10029 (void) bcm_xgs3_nh_del(unit, _BCM_L3_SHR_WRITE_DISABLE, *vp_nh_index); 10030 } 10031 if (egress_nh_index != -1) { 10032 (void) bcm_xgs3_nh_del(unit, 0, egress_nh_index); 10033 } 10034 if (tpid_index != -1) { 10035 (void) _bcm_fb2_outer_tpid_entry_delete(unit, tpid_index); 10036 } 10037 if (egr_nh_info.macda_index != -1) { 10038 (void) _bcm_mac_da_profile_entry_delete(unit, egr_nh_info.macda_index); 10039 } 10040 if (egr_nh_info.vc_swap_index >= 0) { 10041 _bcm_tr_mpls_vc_and_swap_ref_count_adjust (unit, 10042 egr_nh_info.vc_swap_index, -1); 10043 (void) _bcm_tr_mpls_vc_and_swap_table_index_reset (unit, 10044 egr_nh_info.vc_swap_index); 10045 } 10046 return rv; 10047 } 10048 10049 STATIC int 10050 _bcm_tr_mpls_l2_nh_info_delete(int unit, int nh_index) 10051 { 10052 int rv=BCM_E_NONE, is_local, old_macda_idx = -1, old_vc_swap_idx = -1; 10053 int action_present, action_not_present, old_tpid_idx = -1; 10054 bcm_if_t tunnel_if = 0; 10055 egr_mpls_vc_and_swap_label_table_entry_t vc_entry; 10056 initial_ing_l3_next_hop_entry_t initial_ing_nh; 10057 ing_l3_next_hop_entry_t ing_nh; 10058 egr_l3_next_hop_entry_t egr_nh; 10059 bcm_module_t modid = 0; 10060 bcm_trunk_t trunk_id = 0; 10061 _bcm_port_info_t *info; 10062 bcm_port_t phys_port = 0; 10063 uint32 port_flags; 10064 uint32 dest_type, dest_val; 10065 int is_trunk = 0; 10066 #if defined(BCM_KATANA2_SUPPORT) 10067 bcm_port_t pp_port = -1; 10068 #endif 10069 #if defined(BCM_KATANA_SUPPORT) 10070 int qtag, qtag_type; 10071 #endif 10072 #if defined(BCM_HGPROXY_COE_SUPPORT) 10073 int local_port; 10074 #endif 10075 10076 BCM_IF_ERROR_RETURN (soc_mem_read(unit, EGR_L3_NEXT_HOPm, 10077 MEM_BLOCK_ANY, nh_index, &egr_nh)); 10078 BCM_IF_ERROR_RETURN (soc_mem_read(unit, ING_L3_NEXT_HOPm, 10079 MEM_BLOCK_ANY, nh_index, &ing_nh)); 10080 BCM_IF_ERROR_RETURN (soc_mem_read(unit, INITIAL_ING_L3_NEXT_HOPm, 10081 MEM_BLOCK_ANY, nh_index, &initial_ing_nh)); 10082 10083 if (soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, nh_entry_type_field[unit]) == 0x1) { 10084 /* Egressing into an MPLS tunnel */ 10085 if (soc_feature(unit, soc_feature_mpls_enhanced)) { 10086 old_macda_idx = soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, 10087 MPLS__MAC_DA_PROFILE_INDEXf); 10088 old_vc_swap_idx = soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, 10089 MPLS__VC_AND_SWAP_INDEXf); 10090 } else { 10091 old_macda_idx = soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, 10092 MAC_DA_PROFILE_INDEXf); 10093 old_vc_swap_idx = soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, 10094 VC_AND_SWAP_INDEXf); 10095 } 10096 /* Get old TPID index if it's used */ 10097 rv = soc_mem_read(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 10098 MEM_BLOCK_ALL, old_vc_swap_idx, &vc_entry); 10099 BCM_IF_ERROR_RETURN(rv); 10100 action_present = 10101 soc_EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm_field32_get(unit, 10102 &vc_entry, 10103 SD_TAG_ACTION_IF_PRESENTf); 10104 action_not_present = 10105 soc_EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm_field32_get(unit, 10106 &vc_entry, 10107 SD_TAG_ACTION_IF_NOT_PRESENTf); 10108 if ((action_not_present == 0x1) || (action_present == 0x1)) { 10109 /* If SD tag action is ADD or REPLACE_VID_TPID, the tpid 10110 * index of the entry is valid. Save 10111 * the old tpid index to be deleted later. 10112 */ 10113 old_tpid_idx = 10114 soc_EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm_field32_get(unit, 10115 &vc_entry, SD_TAG_TPID_INDEXf); 10116 } 10117 10118 /* Find the tunnel_if */ 10119 rv = bcm_tr_mpls_get_vp_nh (unit, nh_index, &tunnel_if); 10120 if ( rv < 0) { 10121 return rv; 10122 } 10123 10124 rv = _bcm_tr_mpls_pw_init_counter_delete (unit, nh_index); 10125 if ( rv < 0) { 10126 return rv; 10127 } 10128 } else if (soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, 10129 nh_entry_type_field[unit]) == 0x2) { 10130 /* egressing into a regular port */ 10131 if (soc_feature(unit, soc_feature_mpls_enhanced)) { 10132 action_present = 10133 soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, 10134 SD_TAG__SD_TAG_ACTION_IF_PRESENTf); 10135 action_not_present = 10136 soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, 10137 SD_TAG__SD_TAG_ACTION_IF_NOT_PRESENTf); 10138 } else { 10139 action_present = 10140 soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, 10141 SD_TAG_ACTION_IF_PRESENTf); 10142 action_not_present = 10143 soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, 10144 SD_TAG_ACTION_IF_NOT_PRESENTf); 10145 } 10146 if ((action_not_present == 0x1) || (action_present == 0x1)) { 10147 /* If SD tag action is ADD or REPLACE_VID_TPID, the tpid 10148 * index of the entry is valid. Save 10149 * the old tpid index to be deleted later. 10150 */ 10151 if (soc_feature(unit, soc_feature_mpls_enhanced)) { 10152 old_tpid_idx = 10153 soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, 10154 SD_TAG__SD_TAG_TPID_INDEXf); 10155 } else { 10156 old_tpid_idx = 10157 soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, 10158 SD_TAG_TPID_INDEXf); 10159 } 10160 10161 } 10162 } else { 10163 return BCM_E_NOT_FOUND; 10164 } 10165 10166 #if defined(BCM_TRIUMPH2_SUPPORT) 10167 if (soc_feature(unit, soc_feature_mpls_failover)) { 10168 rv = _bcm_esw_failover_prot_nhi_cleanup(unit, nh_index); 10169 if ( (rv != BCM_E_NOT_FOUND) && (rv != BCM_E_NONE) ) { 10170 return rv; 10171 } 10172 } 10173 #endif /* BCM_TRIUMPH2_SUPPORT */ 10174 10175 /* Update the physical port's SW state */ 10176 10177 /*Read trunk_id,phy_port,modid*/ 10178 if (soc_feature(unit, soc_feature_generic_dest)) { 10179 dest_val = soc_mem_field32_dest_get(unit, ING_L3_NEXT_HOPm, 10180 &ing_nh, DESTINATIONf, &dest_type); 10181 if (dest_type == SOC_MEM_FIF_DEST_LAG) { 10182 /* Trunk group */ 10183 trunk_id = dest_val & SOC_MEM_FIF_DGPP_TGID_MASK; 10184 is_trunk = 1; 10185 } else { 10186 phys_port = dest_val & SOC_MEM_FIF_DGPP_PORT_MASK; 10187 modid = (dest_val & SOC_MEM_FIF_DGPP_MOD_ID_MASK) >> 10188 SOC_MEM_FIF_DGPP_MOD_ID_SHIFT_BITS; 10189 } 10190 } else { 10191 modid = soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, MODULE_IDf); 10192 if (soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, Tf)) { 10193 is_trunk = 1; 10194 trunk_id = soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, TGIDf); 10195 } else { 10196 phys_port = soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, 10197 PORT_NUMf); 10198 } 10199 } 10200 #if defined(BCM_HGPROXY_COE_SUPPORT) 10201 if (soc_feature(unit, soc_feature_hgproxy_subtag_coe) && 10202 _bcm_xgs5_subport_coe_mod_local(unit, modid)) { 10203 10204 if (soc_feature(unit, soc_feature_generic_dest)) { 10205 dest_val = soc_mem_field32_dest_get(unit, ING_L3_NEXT_HOPm, 10206 &ing_nh, DESTINATIONf, &dest_type); 10207 phys_port = dest_val & SOC_MEM_FIF_DGPP_PORT_MASK; 10208 } else { 10209 phys_port = 10210 soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, PORT_NUMf); 10211 } 10212 BCM_IF_ERROR_RETURN( 10213 _bcmi_coe_subport_mod_port_physical_port_get(unit, modid, 10214 phys_port, 10215 &local_port)); 10216 _bcm_port_info_access(unit, local_port, &info); 10217 info->vp_count--; 10218 /* Update the physical port's attributes */ 10219 BCM_IF_ERROR_RETURN(bcm_esw_port_vlan_member_get(unit, 10220 local_port, &port_flags)); 10221 BCM_IF_ERROR_RETURN(bcm_esw_port_vlan_member_set(unit, 10222 local_port, port_flags)); 10223 } else 10224 #endif 10225 { 10226 BCM_IF_ERROR_RETURN(_bcm_esw_modid_is_local(unit, modid, &is_local)); 10227 if (is_local && !is_trunk) { 10228 if (soc_feature(unit, soc_feature_sysport_remap)) { 10229 BCM_XLATE_SYSPORT_S2P(unit, &phys_port); 10230 } 10231 _bcm_port_info_access(unit, phys_port, &info); 10232 info->vp_count--; 10233 /* Update the physical port's attributes */ 10234 BCM_IF_ERROR_RETURN 10235 (bcm_esw_port_vlan_member_get(unit, phys_port, &port_flags)); 10236 BCM_IF_ERROR_RETURN 10237 /* coverity[stack_use_callee] */ 10238 /* coverity[stack_use_overflow] */ 10239 (bcm_esw_port_vlan_member_set(unit, phys_port, port_flags)); 10240 } 10241 } 10242 10243 #if defined(BCM_KATANA2_SUPPORT) 10244 if (soc_feature(unit, soc_feature_linkphy_coe) || 10245 soc_feature(unit, soc_feature_subtag_coe)) { 10246 /* For LinkPHY/SubportPktTag pp_ports, check if the mod is a valid one */ 10247 if (_bcm_kt2_mod_is_coe_mod_check(unit, modid) == BCM_E_NONE) { 10248 BCM_IF_ERROR_RETURN( 10249 _bcm_kt2_modport_to_pp_port_get(unit, modid, 10250 phys_port, &pp_port)); 10251 /*For KT2, pp_port >=42 are used for LinkPHY/SubportPktTag subport. 10252 * Get the subport info associated with the pp_port and form the 10253 * subport_gport */ 10254 if (_bcm_kt2_is_pp_port_linkphy_subtag(unit, pp_port)){ 10255 _bcm_port_info_access(unit, pp_port, &info); 10256 info->vp_count--; 10257 /* Update the physical port's attributes */ 10258 BCM_IF_ERROR_RETURN(bcm_esw_port_vlan_member_get(unit, 10259 pp_port, &port_flags)); 10260 BCM_IF_ERROR_RETURN(bcm_esw_port_vlan_member_set(unit, 10261 pp_port, port_flags)); 10262 } 10263 } 10264 } 10265 #endif 10266 10267 /* If associated with a trunk, update each local physical port's SW state */ 10268 if (is_trunk) { 10269 int idx; 10270 uint32 port_flags; 10271 #if defined(BCM_ESW_SUPPORT) && (SOC_MAX_NUM_PP_PORTS > SOC_MAX_NUM_PORTS) 10272 int max_num_port = SOC_MAX_NUM_PP_PORTS; 10273 bcm_port_t local_member_array[SOC_MAX_NUM_PP_PORTS]; 10274 #else 10275 int max_num_port = SOC_MAX_NUM_PORTS; 10276 bcm_port_t local_member_array[SOC_MAX_NUM_PORTS]; 10277 #endif 10278 int local_member_count; 10279 10280 rv = _bcm_esw_trunk_local_members_get(unit, trunk_id, 10281 max_num_port, local_member_array, 10282 &local_member_count); 10283 /* The resource(next_hop/vx_and_swap entry etc.) should be cleared even 10284 * if local members can't be got. 10285 */ 10286 if (BCM_E_NONE == rv) { 10287 for (idx = 0; idx < local_member_count; idx++) { 10288 _bcm_port_info_access(unit, local_member_array[idx], &info); 10289 info->vp_count--; 10290 10291 /* Update the physical port's attributes */ 10292 BCM_IF_ERROR_RETURN( 10293 bcm_esw_port_vlan_member_get(unit, local_member_array[idx], 10294 &port_flags)); 10295 BCM_IF_ERROR_RETURN( 10296 bcm_esw_port_vlan_member_set(unit, local_member_array[idx], 10297 port_flags)); 10298 } 10299 } 10300 } 10301 #if defined(BCM_KATANA_SUPPORT) 10302 if (soc_feature(unit, soc_feature_extended_queueing)) { 10303 qtag = soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, EH_QUEUE_TAGf); 10304 qtag_type = soc_ING_L3_NEXT_HOPm_field32_get(unit, 10305 &ing_nh, EH_TAG_TYPEf); 10306 if ((qtag > 0) && (qtag_type == EH_TAG_TYPE_ING_QUEUE_MAP)) { 10307 /* Update ING_QUEUE_MAP reference count */ 10308 _bcm_tr_mpls_ing_queue_map_ref_count_adjust (unit, qtag, -1); 10309 10310 /* ING_QUEUE_MAP needs to be reset */ 10311 BCM_IF_ERROR_RETURN( 10312 _bcm_tr_mpls_ing_queue_map_index_reset (unit, qtag)); 10313 } 10314 } 10315 #endif /* BCM_KATANA_SUPPORT */ 10316 10317 /* Clear ING_L3_NEXT_HOP entry */ 10318 sal_memset(&ing_nh, 0, sizeof(ing_l3_next_hop_entry_t)); 10319 BCM_IF_ERROR_RETURN (soc_mem_write (unit, ING_L3_NEXT_HOPm, 10320 MEM_BLOCK_ALL, nh_index, &ing_nh)); 10321 10322 /* Clear INITIAL_ING_L3_NEXT_HOP entry */ 10323 sal_memset(&initial_ing_nh, 0, sizeof(initial_ing_l3_next_hop_entry_t)); 10324 BCM_IF_ERROR_RETURN (soc_mem_write(unit, INITIAL_ING_L3_NEXT_HOPm, 10325 MEM_BLOCK_ALL, nh_index, &initial_ing_nh)); 10326 10327 /* Delete old TPID, MAC, tunnel next-hop and VC_SWAP indexes */ 10328 if (old_vc_swap_idx != -1) { 10329 #if defined(BCM_TRIUMPH3_SUPPORT) 10330 if (soc_feature(unit, soc_feature_vc_and_swap_table_overlaid)) { 10331 BCM_IF_ERROR_RETURN( 10332 _bcm_tr_mpls_vc_and_swap_hash_nhop_delete(unit, 10333 old_vc_swap_idx, 10334 nh_index)); 10335 } 10336 #endif 10337 _bcm_tr_mpls_vc_and_swap_ref_count_adjust (unit, old_vc_swap_idx, -1); 10338 BCM_IF_ERROR_RETURN 10339 (_bcm_tr_mpls_vc_and_swap_table_index_reset (unit, old_vc_swap_idx)); 10340 } 10341 if (old_macda_idx != -1) { 10342 rv = _bcm_mac_da_profile_entry_delete(unit, old_macda_idx); 10343 BCM_IF_ERROR_RETURN(rv); 10344 } 10345 if (old_tpid_idx != -1) { 10346 (void) _bcm_fb2_outer_tpid_entry_delete(unit, old_tpid_idx); 10347 } 10348 if (tunnel_if != 0) { 10349 rv = bcm_xgs3_nh_del(unit, 0, 10350 (tunnel_if - BCM_XGS3_EGRESS_IDX_MIN(unit))); 10351 BCM_IF_ERROR_RETURN(rv); 10352 } 10353 10354 BCM_IF_ERROR_RETURN(_bcm_tr_mpls_delete_vp_nh ( unit, nh_index, tunnel_if )); 10355 10356 /* Clear EGR_L3_NEXT_HOP entry */ 10357 sal_memset(&egr_nh, 0, sizeof(egr_l3_next_hop_entry_t)); 10358 BCM_IF_ERROR_RETURN (soc_mem_write(unit, EGR_L3_NEXT_HOPm, 10359 MEM_BLOCK_ALL, nh_index, &egr_nh)); 10360 10361 /* Free the next-hop entry. */ 10362 rv = bcm_xgs3_nh_del(unit, _BCM_L3_SHR_WRITE_DISABLE, nh_index); 10363 return rv; 10364 } 10365 10366 /* Translate hardware table index into map ID used by API */ 10367 int 10368 _egr_idx2id(int unit, int hw_map_idx) 10369 { 10370 int num_exp_map = soc_mem_index_count(unit, EGR_MPLS_EXP_MAPPING_1m) / 64; 10371 int id; 10372 10373 for (id = 0; id < num_exp_map; id++) { 10374 if (_BCM_EGR_MPLS_MAP_USED_GET(unit, id)) { 10375 if (MPLS_INFO(unit)->egr_mpls_hw_idx[id] == (uint32)hw_map_idx) { 10376 return id; 10377 } 10378 } 10379 } 10380 return -1; 10381 } 10382 10383 STATIC int 10384 _bcm_tr_mpls_l2_nh_info_get(int unit, int vp, bcm_mpls_port_t *mpls_port, 10385 int nh_index) 10386 { 10387 ing_l3_next_hop_entry_t ing_nh; 10388 egr_l3_next_hop_entry_t egr_nh; 10389 egr_l3_next_hop_entry_t egr_l3_nh; 10390 egr_mpls_vc_and_swap_label_table_entry_t vc_entry; 10391 int vc_swap_idx, action_present, action_not_present; 10392 bcm_module_t mod_out, mod_in; 10393 bcm_port_t port_out, port_in; 10394 bcm_trunk_t trunk_id; 10395 int ttl = 0, entry_type, ix; 10396 int network_port_flag = 0, tpid_index = 0; 10397 bcm_if_t tunnel_if = 0; 10398 _bcm_vp_info_t vp_info; 10399 #if defined(BCM_KATANA2_SUPPORT) 10400 bcm_port_t pp_port = 0; 10401 #endif 10402 #if defined(BCM_KATANA2_SUPPORT) | defined(BCM_HGPROXY_COE_SUPPORT) 10403 int is_local_subport = 0; 10404 #endif 10405 #if defined(BCM_KATANA_SUPPORT) 10406 ing_queue_map_entry_t ing_queue_entry; 10407 int qtag, qtag_type; 10408 #endif 10409 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 10410 int egress_failover_id; 10411 #endif 10412 uint32 dest_type=0,dest_val=0; 10413 int is_trunk = 0; 10414 10415 #if defined(BCM_TOMAHAWK2_SUPPORT) || defined(BCM_TRIDENT3_SUPPORT) 10416 int ecn_map_id; 10417 int ecn_map_hw_index; 10418 int ecn_map_pri; 10419 soc_field_t ipecn_to_exp_ptr; 10420 soc_field_t ipecn_to_exp_priority; 10421 #endif 10422 10423 uint32 base_class_id = 0; 10424 int base_nh_entry_type = 0; 10425 int nh_idx = 0,vc_data_type = 0; 10426 #if defined(BCM_TRIDENT3_SUPPORT) 10427 uint32 mpls_format[2]; 10428 #endif 10429 10430 /* Read the HW entries */ 10431 BCM_IF_ERROR_RETURN (soc_mem_read(unit, ING_L3_NEXT_HOPm, MEM_BLOCK_ANY, 10432 nh_index, &ing_nh)); 10433 BCM_IF_ERROR_RETURN (soc_mem_read(unit, EGR_L3_NEXT_HOPm, MEM_BLOCK_ANY, 10434 nh_index, &egr_nh)); 10435 entry_type = soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, nh_entry_type_field[unit]); 10436 10437 /* Egressing into an MPLS tunnel, find the tunnel_if */ 10438 if (entry_type == 0x1) { 10439 mpls_port->flags |= BCM_MPLS_PORT_EGRESS_TUNNEL; 10440 BCM_IF_ERROR_RETURN( 10441 bcm_tr_mpls_get_vp_nh(unit, nh_index, &tunnel_if)); 10442 mpls_port->egress_tunnel_if = tunnel_if; 10443 mpls_port->flags |= BCM_MPLS_PORT_NETWORK; 10444 network_port_flag = TRUE; 10445 10446 if (soc_feature(unit, soc_feature_mpls_enhanced)) { 10447 if (soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_nh, 10448 MPLS__HG_MODIFY_ENABLEf)) { 10449 mpls_port->flags2 |= BCM_MPLS_PORT2_PROXY_MODE; 10450 } 10451 } 10452 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) 10453 if (soc_feature(unit, soc_feature_mpls_nh_ttl_control)) { 10454 if (soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_nh, 10455 MPLS__DISABLE_TTL_DECREMENTf)) { 10456 mpls_port->flags2 |= BCM_MPLS_PORT2_KEEP_TTL; 10457 } 10458 } 10459 #endif 10460 /* Calculate next hop index. */ 10461 if (BCM_XGS3_L3_EGRESS_IDX_VALID(unit, tunnel_if)) { 10462 nh_idx = tunnel_if - BCM_XGS3_EGRESS_IDX_MIN(unit); 10463 } else { 10464 nh_idx = tunnel_if - BCM_XGS3_DVP_EGRESS_IDX_MIN(unit); 10465 } 10466 10467 if ((nh_idx > 0) && (nh_idx < BCM_XGS3_L3_NH_TBL_SIZE(unit))) { 10468 10469 if (soc_feature(unit, soc_feature_egr_nh_class_id_valid)) { 10470 10471 BCM_IF_ERROR_RETURN (soc_mem_read(unit, EGR_L3_NEXT_HOPm, 10472 MEM_BLOCK_ANY, 10473 nh_idx, &egr_l3_nh)); 10474 10475 base_nh_entry_type = soc_EGR_L3_NEXT_HOPm_field32_get(unit, 10476 &egr_l3_nh, 10477 ENTRY_TYPEf); 10478 if (base_nh_entry_type == 0) { 10479 /* Get class id for l3 unicast Nhs. 10480 */ 10481 base_class_id = soc_EGR_L3_NEXT_HOPm_field32_get(unit, 10482 &egr_l3_nh, 10483 L3__CLASS_IDf); 10484 } else if (base_nh_entry_type == 1) { 10485 /* Get class id for mpls unicast Nhs. 10486 */ 10487 base_class_id = soc_EGR_L3_NEXT_HOPm_field32_get(unit, 10488 &egr_l3_nh, 10489 MPLS__CLASS_IDf); 10490 } 10491 10492 mpls_port->egress_class_id = soc_EGR_L3_NEXT_HOPm_field32_get( 10493 unit, &egr_nh, 10494 MPLS__CLASS_IDf); 10495 10496 10497 if (base_class_id == mpls_port->egress_class_id) { 10498 /* if l3 nh class id and mpls class id is same 10499 * then the value has come from l3 nh. 10500 * User must had sent invalid class if mpls port. 10501 * We dont allow same class ids in mpls port and base l3 nh. 10502 */ 10503 mpls_port->egress_class_id = BCM_CLASS_ID_INVALID; 10504 } 10505 } else { 10506 mpls_port->egress_class_id = BCM_CLASS_ID_INVALID; 10507 } 10508 } else { 10509 return BCM_E_PARAM; 10510 } 10511 } else if (entry_type == 0x2) { 10512 if (soc_feature(unit, soc_feature_mpls_enhanced)) { 10513 if (soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_nh, 10514 SD_TAG__HG_MODIFY_ENABLEf)) { 10515 mpls_port->flags2 |= BCM_MPLS_PORT2_PROXY_MODE; 10516 } 10517 10518 if (soc_feature(unit, soc_feature_egr_nh_class_id_valid)) { 10519 mpls_port->egress_class_id = soc_EGR_L3_NEXT_HOPm_field32_get( 10520 unit, &egr_nh, 10521 SD_TAG__CLASS_IDf); 10522 if (mpls_port->egress_class_id == 0) { 10523 mpls_port->egress_class_id = BCM_CLASS_ID_INVALID; 10524 } 10525 10526 } 10527 } 10528 } 10529 10530 entry_type = soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, ENTRY_TYPEf); 10531 10532 if (entry_type == 0x2) { 10533 10534 if (soc_feature(unit, soc_feature_mpls_enhanced)) { 10535 if (soc_feature(unit, soc_feature_multiple_split_horizon_group)) { 10536 if (!(soc_feature(unit, soc_feature_td3_style_mpls))) { 10537 mpls_port->network_group_id = soc_EGR_L3_NEXT_HOPm_field32_get( 10538 unit, &egr_nh, MPLS__DVP_NETWORK_GROUPf); 10539 } 10540 } else { 10541 mpls_port->network_group_id = soc_EGR_L3_NEXT_HOPm_field32_get( 10542 unit, &egr_nh, MPLS__DVP_IS_NETWORK_PORTf); 10543 } 10544 } else { 10545 mpls_port->network_group_id = soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, 10546 DVP_IS_NETWORK_PORTf); 10547 } 10548 10549 BCM_IF_ERROR_RETURN(_bcm_vp_info_get(unit, vp, &vp_info)); 10550 if (vp_info.flags & _BCM_VP_INFO_NETWORK_PORT) { 10551 network_port_flag = TRUE; 10552 } 10553 10554 if (soc_feature(unit, soc_feature_mpls_enhanced)) { 10555 vc_swap_idx = soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, 10556 MPLS__VC_AND_SWAP_INDEXf); 10557 } else { 10558 vc_swap_idx = soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, 10559 VC_AND_SWAP_INDEXf); 10560 } 10561 10562 BCM_IF_ERROR_RETURN (soc_mem_read(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 10563 MEM_BLOCK_ANY, vc_swap_idx, &vc_entry)); 10564 10565 if (soc_mem_field32_get(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 10566 &vc_entry, MPLS_LABEL_ACTIONf)) { 10567 10568 if (SOC_MEM_FIELD_VALID(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 10569 DATA_TYPEf)) { 10570 vc_data_type = soc_mem_field32_get(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 10571 &vc_entry, DATA_TYPEf); 10572 } 10573 10574 if (vc_data_type == _BCM_VC_SWAP_TBL_FLEX_DATA_TYPE) { 10575 /*TD3 PHP/SWAPTOSELF VCSWAP Entry*/ 10576 #if defined(BCM_TRIDENT3_SUPPORT) 10577 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 10578 sal_memset(mpls_format, 0, sizeof(mpls_format)); 10579 soc_mem_field_get(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 10580 (uint32 *) &vc_entry, 10581 MPLS_ENTRY_ACTION_SETfmt, 10582 (uint32 *) mpls_format); 10583 mpls_port->egress_label.label = soc_format_field32_get(unit, 10584 MPLS_ENTRY_ACTION_SETfmt, 10585 (uint32 *)mpls_format, MPLS_LABELf); 10586 10587 ttl = soc_format_field32_get(unit, 10588 MPLS_ENTRY_ACTION_SETfmt, 10589 (uint32 *)mpls_format, MPLS_TTLf); 10590 10591 if (soc_format_field32_get(unit, MPLS_ENTRY_ACTION_SETfmt, 10592 (uint32 *)mpls_format, MPLS_EXP_SELECTf) == 0x0) { 10593 /* Use the specified EXP, PRI and CFI */ 10594 mpls_port->egress_label.flags |= BCM_MPLS_EGRESS_LABEL_EXP_SET; 10595 mpls_port->egress_label.flags |= BCM_MPLS_EGRESS_LABEL_PRI_SET; 10596 mpls_port->egress_label.exp = 10597 soc_format_field32_get(unit, MPLS_ENTRY_ACTION_SETfmt, 10598 (uint32 *)mpls_format, MPLS_EXPf); 10599 mpls_port->egress_label.pkt_pri = 10600 soc_format_field32_get(unit, MPLS_ENTRY_ACTION_SETfmt, 10601 (uint32 *)mpls_format, NEW_PRIf); 10602 mpls_port->egress_label.pkt_cfi = 10603 soc_format_field32_get(unit, MPLS_ENTRY_ACTION_SETfmt, 10604 (uint32 *)mpls_format, NEW_CFIf); 10605 } else if (soc_format_field32_get(unit, MPLS_ENTRY_ACTION_SETfmt, 10606 (uint32 *)mpls_format, MPLS_EXP_SELECTf) == 0x1) { 10607 /* Use EXP-map for EXP, PRI and CFI */ 10608 mpls_port->egress_label.flags |= BCM_MPLS_EGRESS_LABEL_EXP_REMARK; 10609 mpls_port->egress_label.flags |= BCM_MPLS_EGRESS_LABEL_PRI_REMARK; 10610 ix = soc_format_field32_get(unit, MPLS_ENTRY_ACTION_SETfmt, 10611 (uint32 *)mpls_format, MPLS_EXP_MAPPING_PTRf); 10612 BCM_IF_ERROR_RETURN( 10613 _egr_qos_hw_idx2id(unit, ix, &mpls_port->egress_label.qos_map_id)); 10614 10615 } else if (soc_format_field32_get(unit, MPLS_ENTRY_ACTION_SETfmt, 10616 (uint32 *)mpls_format, MPLS_EXP_SELECTf) == 0x2) { 10617 /* Use EXP from incoming MPLS label. If no incoming label, use the specified 10618 * EXP value. Use EXP-map for PRI/CFI. 10619 */ 10620 mpls_port->egress_label.flags |= BCM_MPLS_EGRESS_LABEL_EXP_COPY; 10621 mpls_port->egress_label.flags |= BCM_MPLS_EGRESS_LABEL_PRI_REMARK; 10622 mpls_port->egress_label.exp = 10623 soc_format_field32_get(unit, MPLS_ENTRY_ACTION_SETfmt, 10624 (uint32 *)mpls_format, MPLS_EXPf); 10625 ix = soc_format_field32_get(unit, MPLS_ENTRY_ACTION_SETfmt, 10626 (uint32 *)mpls_format, MPLS_EXP_MAPPING_PTRf); 10627 10628 BCM_IF_ERROR_RETURN( 10629 _egr_qos_hw_idx2id(unit, ix, &mpls_port->egress_label.qos_map_id)); 10630 } 10631 } 10632 #endif 10633 } else { 10634 mpls_port->egress_label.label = 10635 soc_mem_field32_get(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 10636 &vc_entry, MPLS_LABELf); 10637 ttl = soc_mem_field32_get(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 10638 &vc_entry, MPLS_TTLf); 10639 if (ttl) { 10640 mpls_port->egress_label.ttl = ttl; 10641 mpls_port->egress_label.flags |= BCM_MPLS_EGRESS_LABEL_TTL_SET; 10642 } else { 10643 mpls_port->egress_label.flags |= BCM_MPLS_EGRESS_LABEL_TTL_DECREMENT; 10644 } 10645 if (soc_mem_field32_get(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 10646 &vc_entry, MPLS_EXP_SELECTf) == 0x0) { 10647 /* Use the specified EXP, PRI and CFI */ 10648 mpls_port->egress_label.flags |= BCM_MPLS_EGRESS_LABEL_EXP_SET; 10649 mpls_port->egress_label.flags |= BCM_MPLS_EGRESS_LABEL_PRI_SET; 10650 mpls_port->egress_label.exp = 10651 soc_mem_field32_get(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 10652 &vc_entry, MPLS_EXPf); 10653 mpls_port->egress_label.pkt_pri = 10654 soc_mem_field32_get(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 10655 &vc_entry, NEW_PRIf); 10656 mpls_port->egress_label.pkt_cfi = 10657 soc_mem_field32_get(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 10658 &vc_entry, NEW_CFIf); 10659 } else if (soc_mem_field32_get(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 10660 &vc_entry, MPLS_EXP_SELECTf) == 0x1) { 10661 /* Use EXP-map for EXP, PRI and CFI */ 10662 mpls_port->egress_label.flags |= BCM_MPLS_EGRESS_LABEL_EXP_REMARK; 10663 mpls_port->egress_label.flags |= BCM_MPLS_EGRESS_LABEL_PRI_REMARK; 10664 ix = soc_mem_field32_get(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 10665 &vc_entry, MPLS_EXP_MAPPING_PTRf); 10666 BCM_IF_ERROR_RETURN( 10667 _egr_qos_hw_idx2id(unit, ix, &mpls_port->egress_label.qos_map_id)); 10668 10669 } else if (soc_mem_field32_get(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 10670 &vc_entry, MPLS_EXP_SELECTf) == 0x2) { 10671 /* Use EXP from incoming MPLS label. If no incoming label, use the specified 10672 * EXP value. Use EXP-map for PRI/CFI. 10673 */ 10674 mpls_port->egress_label.flags |= BCM_MPLS_EGRESS_LABEL_EXP_COPY; 10675 mpls_port->egress_label.flags |= BCM_MPLS_EGRESS_LABEL_PRI_REMARK; 10676 mpls_port->egress_label.exp = 10677 soc_mem_field32_get(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 10678 &vc_entry, MPLS_EXPf); 10679 ix = soc_mem_field32_get(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 10680 &vc_entry, MPLS_EXP_MAPPING_PTRf); 10681 10682 BCM_IF_ERROR_RETURN( 10683 _egr_qos_hw_idx2id(unit, ix, &mpls_port->egress_label.qos_map_id)); 10684 } 10685 #if defined(BCM_TOMAHAWK2_SUPPORT) || defined(BCM_TRIDENT3_SUPPORT) 10686 if (soc_feature(unit, soc_feature_mpls_ecn)) { 10687 int rv; 10688 if (!soc_feature(unit, soc_feature_intcn_to_exp_nosupport)) { 10689 ecn_map_hw_index = soc_mem_field32_get(unit, 10690 EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 10691 &vc_entry, 10692 INT_CN_TO_EXP_MAPPING_PTRf); 10693 rv = bcmi_ecn_map_hw_idx2id(unit, ecn_map_hw_index, 10694 _BCM_XGS5_MPLS_ECN_MAP_TYPE_INTCN2EXP, 10695 &ecn_map_id); 10696 if (BCM_SUCCESS(rv)) { 10697 mpls_port->egress_label.int_cn_map_id = ecn_map_id; 10698 ecn_map_pri = soc_mem_field32_get(unit, 10699 EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 10700 &vc_entry, 10701 INT_CN_TO_EXP_PRIORITYf); 10702 if (ecn_map_pri) { 10703 mpls_port->egress_label.flags |= 10704 BCM_MPLS_EGRESS_LABEL_ECN_EXP_MAP_TRUST; 10705 } 10706 mpls_port->egress_label.flags |= 10707 BCM_MPLS_EGRESS_LABEL_INT_CN_TO_EXP_MAP; 10708 } 10709 } 10710 #if defined(BCM_TRIDENT3_SUPPORT) 10711 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 10712 ipecn_to_exp_ptr = PKT_ECN_TO_EXP_MAPPING_PTRf; 10713 ipecn_to_exp_priority = PKT_ECN_TO_EXP_PRIORITYf; 10714 } else 10715 #endif 10716 { 10717 ipecn_to_exp_ptr = IP_ECN_TO_EXP_MAPPING_PTRf; 10718 ipecn_to_exp_priority = IP_ECN_TO_EXP_PRIORITYf; 10719 } 10720 ecn_map_hw_index = soc_mem_field32_get(unit, 10721 EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 10722 &vc_entry, ipecn_to_exp_ptr); 10723 10724 rv = bcmi_ecn_map_hw_idx2id(unit, ecn_map_hw_index, 10725 _BCM_XGS5_MPLS_ECN_MAP_TYPE_ECN2EXP, 10726 &ecn_map_id); 10727 if (BCM_SUCCESS(rv)) { 10728 mpls_port->egress_label.ecn_map_id = ecn_map_id; 10729 ecn_map_pri = soc_mem_field32_get(unit, 10730 EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 10731 &vc_entry, 10732 ipecn_to_exp_priority); 10733 if (ecn_map_pri) { 10734 mpls_port->egress_label.flags |= 10735 BCM_MPLS_EGRESS_LABEL_ECN_EXP_MAP_TRUST; 10736 } 10737 mpls_port->egress_label.flags |= 10738 BCM_MPLS_EGRESS_LABEL_ECN_TO_EXP_MAP; 10739 } 10740 } 10741 #endif /* BCM_TOMAHAWK2_SUPPORT */ 10742 } 10743 } else { 10744 /*Return egress label as zero for default VCSWAP label entry*/ 10745 if (vc_swap_idx == 0) { 10746 mpls_port->egress_label.label = 0; 10747 } 10748 } 10749 if (soc_mem_field32_get(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 10750 &vc_entry, CW_INSERT_FLAGf) == 0x2) { 10751 mpls_port->flags |= BCM_MPLS_PORT_SEQUENCED; 10752 } else if (soc_mem_field32_get(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 10753 &vc_entry, CW_INSERT_FLAGf) == 0x1) { 10754 mpls_port->flags |= BCM_MPLS_PORT_CONTROL_WORD; 10755 } 10756 if (soc_mem_field32_get(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 10757 &vc_entry, UPDATE_PW_INIT_COUNTERSf)) { 10758 mpls_port->flags |= BCM_MPLS_PORT_COUNTED; 10759 } 10760 #ifdef BCM_MONTEREY_SUPPORT 10761 if (soc_feature(unit, soc_feature_roe) || 10762 soc_feature(unit, soc_feature_roe_custom)) { 10763 if (soc_mem_field_valid(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 10764 BARE_MPLSf)) { 10765 if (soc_mem_field32_get(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 10766 &vc_entry, BARE_MPLSf)) { 10767 mpls_port->egress_label.flags |= BCM_MPLS_EGRESS_LABEL_ROE_BARE_MPLS; 10768 } 10769 } 10770 } 10771 #endif 10772 #if (defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT)) 10773 if (soc_feature(unit, soc_feature_mpls_entropy)) { 10774 if (soc_mem_field_valid(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 10775 MPLS_INSERT_ENTROPY_LABELf)) { 10776 if (soc_mem_field32_get(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 10777 &vc_entry, MPLS_INSERT_ENTROPY_LABELf)) { 10778 mpls_port->egress_label.flags |= 10779 BCM_MPLS_EGRESS_LABEL_ENTROPY_ENABLE; 10780 } 10781 } 10782 } 10783 #endif /* defined(BCM_KATANA_SUPPORT) || defined(BCM_APACHE_SUPPORT) */ 10784 10785 if (soc_feature(unit, soc_feature_generic_dest)) { 10786 dest_val = soc_mem_field32_dest_get(unit, ING_L3_NEXT_HOPm, 10787 &ing_nh, DESTINATIONf, &dest_type); 10788 10789 if (dest_type == SOC_MEM_FIF_DEST_LAG) { 10790 /* Trunk group */ 10791 trunk_id = dest_val & SOC_MEM_FIF_DGPP_TGID_MASK; 10792 is_trunk = 1; 10793 } else { 10794 port_in = dest_val & SOC_MEM_FIF_DGPP_PORT_MASK; 10795 mod_in = (dest_val & SOC_MEM_FIF_DGPP_MOD_ID_MASK) >> 10796 SOC_MEM_FIF_DGPP_MOD_ID_SHIFT_BITS; 10797 } 10798 } else { 10799 is_trunk = soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, Tf); 10800 trunk_id = soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, TGIDf); 10801 if(!is_trunk) { 10802 mod_in = soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, MODULE_IDf); 10803 port_in = soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, PORT_NUMf); 10804 } 10805 } 10806 10807 if (is_trunk) { 10808 BCM_GPORT_TRUNK_SET(mpls_port->port, trunk_id); 10809 } else { 10810 10811 #if defined(BCM_HGPROXY_COE_SUPPORT) 10812 if (soc_feature(unit, soc_feature_hgproxy_subtag_coe)) { 10813 10814 if(_bcm_xgs5_subport_coe_mod_port_local(unit, mod_in, port_in)) { 10815 is_local_subport = 1; 10816 } 10817 10818 if (is_local_subport) { 10819 /* Encode type and fill in the associated (mod,port) */ 10820 _BCM_SUBPORT_COE_PORT_ID_SET(mpls_port->port, mod_in, port_in); 10821 /* Set the bit on the outgoing param indicating this is subtag type */ 10822 _BCM_SUBPORT_COE_PORT_TYPE_SET(mpls_port->port, _BCM_SUBPORT_COE_TYPE_SUBTAG); 10823 } 10824 } 10825 #endif 10826 10827 #if defined(BCM_KATANA2_SUPPORT) 10828 if (soc_feature(unit, soc_feature_linkphy_coe) || 10829 soc_feature(unit, soc_feature_subtag_coe)) { 10830 if (_bcm_kt2_mod_is_coe_mod_check(unit, mod_in) == BCM_E_NONE) { 10831 BCM_IF_ERROR_RETURN(_bcm_kt2_modport_to_pp_port_get( 10832 unit, mod_in, port_in, &pp_port)); 10833 if (_bcm_kt2_is_pp_port_linkphy_subtag(unit, pp_port)){ 10834 is_local_subport = 1; 10835 } 10836 } 10837 10838 if (is_local_subport) { 10839 _BCM_KT2_SUBPORT_PORT_ID_SET(mpls_port->port, pp_port); 10840 if (BCM_PBMP_MEMBER(SOC_INFO(unit).linkphy_pp_port_pbm, 10841 pp_port)) { 10842 _BCM_KT2_SUBPORT_PORT_TYPE_SET(mpls_port->port, 10843 _BCM_KT2_SUBPORT_TYPE_LINKPHY); 10844 } else if (BCM_PBMP_MEMBER(SOC_INFO(unit).subtag_pp_port_pbm, 10845 pp_port)) { 10846 _BCM_KT2_SUBPORT_PORT_TYPE_SET(mpls_port->port, 10847 _BCM_KT2_SUBPORT_TYPE_SUBTAG); 10848 } else { 10849 return BCM_E_PORT; 10850 } 10851 } 10852 } 10853 #endif 10854 10855 #if defined(BCM_KATANA2_SUPPORT) || defined(BCM_HGPROXY_COE_SUPPORT) 10856 if (is_local_subport) { 10857 /* gport assigned above */ 10858 } else 10859 #endif 10860 { 10861 BCM_IF_ERROR_RETURN(_bcm_esw_stk_modmap_map(unit, 10862 BCM_STK_MODMAP_GET, mod_in, port_in, &mod_out, &port_out)); 10863 if ((mpls_port->criteria == BCM_MPLS_PORT_MATCH_VLAN) && 10864 port_out == 0) { 10865 mpls_port->port = BCM_GPORT_INVALID; 10866 } else { 10867 BCM_GPORT_MODPORT_SET(mpls_port->port, mod_out, port_out); 10868 } 10869 } 10870 } 10871 10872 if (network_port_flag) { 10873 10874 action_present = 10875 soc_EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm_field32_get(unit, 10876 &vc_entry, SD_TAG_ACTION_IF_PRESENTf); 10877 action_not_present = 10878 soc_EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm_field32_get(unit, 10879 &vc_entry, SD_TAG_ACTION_IF_NOT_PRESENTf); 10880 10881 switch (action_present) { 10882 10883 case 0: 10884 if (action_not_present == 1) { 10885 mpls_port->flags |= BCM_MPLS_PORT_SERVICE_VLAN_ADD; 10886 } 10887 mpls_port->egress_service_vlan = 10888 soc_mem_field32_get(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, &vc_entry, SD_TAG_VIDf); 10889 break; 10890 10891 case 1: 10892 if (action_not_present == 1) { 10893 mpls_port->flags |= BCM_MPLS_PORT_SERVICE_VLAN_ADD; 10894 } 10895 mpls_port->flags |= BCM_MPLS_PORT_SERVICE_VLAN_TPID_REPLACE; 10896 mpls_port->egress_service_vlan = 10897 soc_mem_field32_get(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, &vc_entry, SD_TAG_VIDf); 10898 break; 10899 10900 case 2: 10901 if (action_not_present == 1) { 10902 mpls_port->flags |= BCM_MPLS_PORT_SERVICE_VLAN_ADD; 10903 } 10904 mpls_port->flags |= BCM_MPLS_PORT_SERVICE_VLAN_REPLACE; 10905 mpls_port->egress_service_vlan = 10906 soc_mem_field32_get(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, &vc_entry, SD_TAG_VIDf); 10907 break; 10908 10909 case 3: 10910 if (action_not_present == 1) { 10911 mpls_port->flags |= BCM_MPLS_PORT_SERVICE_VLAN_ADD; 10912 } 10913 mpls_port->flags |= BCM_MPLS_PORT_SERVICE_VLAN_DELETE; 10914 mpls_port->egress_service_vlan = BCM_VLAN_INVALID; 10915 break; 10916 10917 case 4: 10918 if (action_not_present == 1) { 10919 mpls_port->flags |= BCM_MPLS_PORT_SERVICE_VLAN_ADD; 10920 } 10921 mpls_port->flags |= BCM_MPLS_PORT_SERVICE_VLAN_PRI_TPID_REPLACE; 10922 mpls_port->egress_service_vlan = 10923 soc_mem_field32_get(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 10924 &vc_entry, SD_TAG_VIDf); 10925 mpls_port->pkt_pri = 10926 soc_mem_field32_get(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 10927 &vc_entry, SD_TAG_NEW_PRIf); 10928 break; 10929 10930 case 5: 10931 if (action_not_present == 1) { 10932 mpls_port->flags |= BCM_MPLS_PORT_SERVICE_VLAN_ADD; 10933 } 10934 mpls_port->flags |= BCM_MPLS_PORT_SERVICE_VLAN_PRI_REPLACE; 10935 mpls_port->egress_service_vlan = 10936 soc_mem_field32_get(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 10937 &vc_entry, SD_TAG_VIDf); 10938 mpls_port->pkt_pri = 10939 soc_mem_field32_get(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 10940 &vc_entry, SD_TAG_NEW_PRIf); 10941 break; 10942 10943 case 6: 10944 if (action_not_present == 1) { 10945 mpls_port->flags |= BCM_MPLS_PORT_SERVICE_VLAN_ADD; 10946 } 10947 mpls_port->flags |= BCM_MPLS_PORT_SERVICE_PRI_REPLACE; 10948 mpls_port->pkt_pri = 10949 soc_mem_field32_get(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 10950 &vc_entry, SD_TAG_NEW_PRIf); 10951 break; 10952 10953 case 7: 10954 if (action_not_present == 1) { 10955 mpls_port->flags |= BCM_MPLS_PORT_SERVICE_VLAN_ADD; 10956 } 10957 mpls_port->flags |= BCM_MPLS_PORT_SERVICE_TPID_REPLACE; 10958 break; 10959 10960 default: 10961 break; 10962 } 10963 if ((mpls_port->flags & BCM_MPLS_PORT_SERVICE_VLAN_ADD) || 10964 (mpls_port->flags & BCM_MPLS_PORT_SERVICE_VLAN_TPID_REPLACE) || 10965 (mpls_port->flags & BCM_MPLS_PORT_SERVICE_TPID_REPLACE) || 10966 (mpls_port->flags & BCM_MPLS_PORT_SERVICE_VLAN_PRI_TPID_REPLACE)) { 10967 tpid_index = soc_mem_field32_get(unit, 10968 EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 10969 &vc_entry, SD_TAG_TPID_INDEXf); 10970 BCM_IF_ERROR_RETURN(_bcm_fb2_outer_tpid_entry_get(unit, 10971 &mpls_port->service_tpid, tpid_index)); 10972 } 10973 } else { 10974 10975 if (soc_feature(unit, soc_feature_mpls_enhanced)) { 10976 action_present = 10977 soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_nh, 10978 SD_TAG__SD_TAG_ACTION_IF_PRESENTf); 10979 action_not_present = 10980 soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_nh, 10981 SD_TAG__SD_TAG_ACTION_IF_NOT_PRESENTf); 10982 } else { 10983 action_present = 10984 soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_nh, 10985 SD_TAG_ACTION_IF_PRESENTf); 10986 action_not_present = 10987 soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_nh, 10988 SD_TAG_ACTION_IF_NOT_PRESENTf); 10989 } 10990 10991 switch (action_present) { 10992 10993 case 0: 10994 if (action_not_present == 1) { 10995 mpls_port->flags |= BCM_MPLS_PORT_SERVICE_VLAN_ADD; 10996 } 10997 if (soc_feature(unit, soc_feature_mpls_enhanced)) { 10998 mpls_port->egress_service_vlan = 10999 soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_nh, 11000 SD_TAG__SD_TAG_VIDf); 11001 } else { 11002 mpls_port->egress_service_vlan = 11003 soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_nh, 11004 SD_TAG_VIDf); 11005 } 11006 break; 11007 11008 case 1: 11009 if (action_not_present == 1) { 11010 mpls_port->flags |= BCM_MPLS_PORT_SERVICE_VLAN_ADD; 11011 } 11012 mpls_port->flags |= BCM_MPLS_PORT_SERVICE_VLAN_TPID_REPLACE; 11013 if (soc_feature(unit, soc_feature_mpls_enhanced)) { 11014 mpls_port->egress_service_vlan = 11015 soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_nh, 11016 SD_TAG__SD_TAG_VIDf); 11017 } else { 11018 mpls_port->egress_service_vlan = 11019 soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_nh, 11020 SD_TAG_VIDf); 11021 } 11022 break; 11023 11024 case 2: 11025 if (action_not_present == 1) { 11026 mpls_port->flags |= BCM_MPLS_PORT_SERVICE_VLAN_ADD; 11027 } 11028 mpls_port->flags |= BCM_MPLS_PORT_SERVICE_VLAN_REPLACE; 11029 if (soc_feature(unit, soc_feature_mpls_enhanced)) { 11030 mpls_port->egress_service_vlan = 11031 soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_nh, 11032 SD_TAG__SD_TAG_VIDf); 11033 } else { 11034 mpls_port->egress_service_vlan = 11035 soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_nh, 11036 SD_TAG_VIDf); 11037 } 11038 break; 11039 11040 case 3: 11041 if (action_not_present == 1) { 11042 mpls_port->flags |= BCM_MPLS_PORT_SERVICE_VLAN_ADD; 11043 } 11044 mpls_port->flags |= BCM_MPLS_PORT_SERVICE_VLAN_DELETE; 11045 mpls_port->egress_service_vlan = BCM_VLAN_INVALID; 11046 break; 11047 11048 case 4: 11049 if (action_not_present == 1) { 11050 mpls_port->flags |= BCM_MPLS_PORT_SERVICE_VLAN_ADD; 11051 } 11052 mpls_port->flags |= BCM_MPLS_PORT_SERVICE_VLAN_PRI_TPID_REPLACE; 11053 if (soc_feature(unit, soc_feature_mpls_enhanced)) { 11054 mpls_port->egress_service_vlan = 11055 soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_nh, 11056 SD_TAG__SD_TAG_VIDf); 11057 if(soc_mem_field_valid(unit, EGR_L3_NEXT_HOPm, 11058 SD_TAG__NEW_PRIf)) { 11059 mpls_port->pkt_pri = 11060 soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_nh, 11061 SD_TAG__NEW_PRIf); 11062 } 11063 if(soc_mem_field_valid(unit, EGR_L3_NEXT_HOPm, 11064 SD_TAG__SD_TAG_REMARK_CFIf)) { 11065 if (soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_nh, 11066 SD_TAG__SD_TAG_REMARK_CFIf)) { 11067 mpls_port->flags2 |= BCM_MPLS_PORT2_SERVICE_CFI_REPLACE; 11068 } 11069 } 11070 if(soc_mem_field_valid(unit, EGR_L3_NEXT_HOPm, 11071 SD_TAG__NEW_CFIf)) { 11072 mpls_port->pkt_cfi = 11073 soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_nh, 11074 SD_TAG__NEW_CFIf); 11075 } 11076 } 11077 break; 11078 11079 case 5: 11080 if (action_not_present == 1) { 11081 mpls_port->flags |= BCM_MPLS_PORT_SERVICE_VLAN_ADD; 11082 } 11083 mpls_port->flags |= BCM_MPLS_PORT_SERVICE_VLAN_PRI_REPLACE; 11084 if (soc_feature(unit, soc_feature_mpls_enhanced)) { 11085 mpls_port->egress_service_vlan = 11086 soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_nh, 11087 SD_TAG__SD_TAG_VIDf); 11088 if(soc_mem_field_valid(unit, EGR_L3_NEXT_HOPm, 11089 SD_TAG__NEW_PRIf)) { 11090 mpls_port->pkt_pri = 11091 soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_nh, 11092 SD_TAG__NEW_PRIf); 11093 } 11094 if(soc_mem_field_valid(unit, EGR_L3_NEXT_HOPm, 11095 SD_TAG__SD_TAG_REMARK_CFIf)) { 11096 if (soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_nh, 11097 SD_TAG__SD_TAG_REMARK_CFIf)) { 11098 mpls_port->flags2 |= BCM_MPLS_PORT2_SERVICE_CFI_REPLACE; 11099 } 11100 } 11101 if(soc_mem_field_valid(unit, EGR_L3_NEXT_HOPm, 11102 SD_TAG__NEW_CFIf)) { 11103 mpls_port->pkt_cfi = 11104 soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_nh, 11105 SD_TAG__NEW_CFIf); 11106 } 11107 } 11108 break; 11109 11110 case 6: 11111 if (action_not_present == 1) { 11112 mpls_port->flags |= BCM_MPLS_PORT_SERVICE_VLAN_ADD; 11113 } 11114 mpls_port->flags |= BCM_MPLS_PORT_SERVICE_PRI_REPLACE; 11115 if (soc_feature(unit, soc_feature_mpls_enhanced)) { 11116 if(soc_mem_field_valid(unit, EGR_L3_NEXT_HOPm, 11117 SD_TAG__NEW_PRIf)) { 11118 mpls_port->pkt_pri = 11119 soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_nh, 11120 SD_TAG__NEW_PRIf); 11121 } 11122 if(soc_mem_field_valid(unit, EGR_L3_NEXT_HOPm, 11123 SD_TAG__SD_TAG_REMARK_CFIf)) { 11124 if (soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_nh, 11125 SD_TAG__SD_TAG_REMARK_CFIf)) { 11126 mpls_port->flags2 |= BCM_MPLS_PORT2_SERVICE_CFI_REPLACE; 11127 } 11128 } 11129 if(soc_mem_field_valid(unit, EGR_L3_NEXT_HOPm, 11130 SD_TAG__NEW_CFIf)) { 11131 mpls_port->pkt_cfi = 11132 soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_nh, 11133 SD_TAG__NEW_CFIf); 11134 } 11135 } 11136 break; 11137 11138 case 7: 11139 if (action_not_present == 1) { 11140 mpls_port->flags |= BCM_MPLS_PORT_SERVICE_VLAN_ADD; 11141 } 11142 mpls_port->flags |= BCM_MPLS_PORT_SERVICE_TPID_REPLACE; 11143 break; 11144 11145 default: 11146 break; 11147 } 11148 if ((mpls_port->flags & BCM_MPLS_PORT_SERVICE_VLAN_ADD) || 11149 (mpls_port->flags & BCM_MPLS_PORT_SERVICE_VLAN_TPID_REPLACE) || 11150 (mpls_port->flags & BCM_MPLS_PORT_SERVICE_TPID_REPLACE) || 11151 (mpls_port->flags & BCM_MPLS_PORT_SERVICE_VLAN_PRI_TPID_REPLACE)) { 11152 if (soc_feature(unit, soc_feature_mpls_enhanced)) { 11153 tpid_index = soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, 11154 &egr_nh, SD_TAG__SD_TAG_TPID_INDEXf); 11155 } else { 11156 tpid_index = soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, 11157 &egr_nh, SD_TAG_TPID_INDEXf); 11158 } 11159 BCM_IF_ERROR_RETURN(_bcm_fb2_outer_tpid_entry_get(unit, 11160 &mpls_port->service_tpid, tpid_index)); 11161 } 11162 } 11163 11164 if (soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, DROPf)) { 11165 mpls_port->flags |= BCM_MPLS_PORT_DROP; 11166 } 11167 #if defined(BCM_TRIUMPH3_SUPPORT) 11168 if (soc_feature(unit, soc_feature_mpls_enhanced)) { 11169 if (SOC_IS_TRIUMPH3(unit) && soc_mem_field_valid(unit, EGR_L3_NEXT_HOPm, 11170 MPLS__DO_EVXLT_AFTER_TUNNEL_ENCAPf)) { 11171 if (soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, 11172 MPLS__DO_EVXLT_AFTER_TUNNEL_ENCAPf)) { 11173 mpls_port->flags2 |= BCM_MPLS_PORT2_TUNNEL_HEADER_EGRESS_VLAN_TRANSLATION; 11174 } 11175 } 11176 } 11177 #endif 11178 #if defined(BCM_KATANA_SUPPORT) 11179 if (soc_feature(unit, soc_feature_extended_queueing)) { 11180 qtag = soc_ING_L3_NEXT_HOPm_field32_get(unit, 11181 &ing_nh, EH_QUEUE_TAGf); 11182 qtag_type = soc_ING_L3_NEXT_HOPm_field32_get(unit, 11183 &ing_nh, EH_TAG_TYPEf); 11184 if (qtag_type == EH_TAG_TYPE_ING_QUEUE_MAP) { 11185 sal_memset(&ing_queue_entry, 0, sizeof(ing_queue_map_entry_t)); 11186 BCM_IF_ERROR_RETURN (soc_mem_read(unit, ING_QUEUE_MAPm, 11187 MEM_BLOCK_ANY, 11188 qtag, &ing_queue_entry)); 11189 mpls_port->qos_map_id = soc_ING_QUEUE_MAPm_field32_get(unit, 11190 &ing_queue_entry, QUEUE_OFFSET_PROFILE_INDEXf); 11191 mpls_port->qos_map_id |= 11192 (_BCM_QOS_MAP_TYPE_ING_QUEUE_OFFSET_MAP_TABLE 11193 << _BCM_QOS_MAP_SHIFT); 11194 } 11195 if (qtag_type > EH_TAG_TYPE_NONE) { 11196 /* We need to have a cosq function which returns the gport for 11197 the queue. Currently, creating the gport of type 11198 subscriber queue locally */ 11199 #ifdef BCM_KATANA2_SUPPORT 11200 if (SOC_IS_KATANA2(unit)) { 11201 bcm_kt2_cosq_subscriber_qid_set(unit, &qtag, qtag); 11202 } else 11203 #endif 11204 { 11205 BCM_GPORT_UCAST_SUBSCRIBER_QUEUE_GROUP_QID_SET(qtag, qtag); 11206 } 11207 qtag |= soc_ING_L3_NEXT_HOPm_field32_get(unit, 11208 &ing_nh, PORT_NUMf) << 16; 11209 mpls_port->per_flow_queue_base = qtag; 11210 } 11211 } 11212 #endif /* BCM_KATANA_SUPPORT */ 11213 #ifdef BCM_TRIDENT2PLUS_SUPPORT 11214 if (soc_feature(unit, soc_feature_egress_failover)) { 11215 egress_failover_id = soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, MPLS__PROT_GROUPf); 11216 if(egress_failover_id > 0) 11217 mpls_port->egress_failover_id = egress_failover_id; 11218 } 11219 #endif 11220 } else { 11221 return BCM_E_NOT_FOUND; 11222 } 11223 11224 return BCM_E_NONE; 11225 } 11226 11227 /* 11228 * Function: 11229 * _bcm_tr_mpls_match_trunk_idx_get 11230 * Purpose: 11231 * Obtain Trunk_Idx 11232 * Parameters: 11233 * unit - (IN) Device Number 11234 * mod_id - (IN) Module Id 11235 * port_id - (IN) Port Id 11236 * src_trk_idx - (OUT) trunk_idx 11237 * Returns: 11238 * BCM_E_XXX 11239 */ 11240 11241 STATIC int 11242 _bcm_tr_mpls_match_trunk_idx_get(int unit, 11243 bcm_module_t mod_id, 11244 bcm_port_t port_id, 11245 int *src_trk_idx) 11246 { 11247 int num_bits_for_port = 0; 11248 11249 #if defined(BCM_KATANA2_SUPPORT) 11250 if (soc_feature(unit, soc_feature_linkphy_coe) || 11251 soc_feature(unit, soc_feature_subtag_coe)) { 11252 BCM_IF_ERROR_RETURN(_bcm_kt2_pp_port_to_modport_get( 11253 unit, port_id, &mod_id, &port_id)); 11254 } 11255 #endif 11256 11257 #if defined(BCM_TRIDENT_SUPPORT) 11258 if (soc_feature(unit, soc_feature_src_modid_base_index)) { 11259 source_trunk_map_modbase_entry_t modbase_entry; 11260 11261 BCM_IF_ERROR_RETURN 11262 (soc_mem_read(unit, SOURCE_TRUNK_MAP_MODBASEm, 11263 MEM_BLOCK_ANY, mod_id, &modbase_entry)); 11264 *src_trk_idx = soc_mem_field32_get(unit, 11265 SOURCE_TRUNK_MAP_MODBASEm, 11266 &modbase_entry, BASEf) + port_id; 11267 } else 11268 #endif 11269 { 11270 num_bits_for_port = 11271 _shr_popcount((unsigned int)SOC_PORT_ADDR_MAX(unit)); 11272 *src_trk_idx = (mod_id << num_bits_for_port) | port_id; 11273 } 11274 return BCM_E_NONE; 11275 } 11276 11277 int 11278 bcm_tr_mpls_trunk_member_add(int unit, bcm_trunk_t trunk_id, 11279 int trunk_member_count, bcm_port_t *trunk_member_array) 11280 { 11281 int rv = BCM_E_NONE; 11282 _bcm_tr_mpls_bookkeeping_t *mpls_info = MPLS_INFO(unit); 11283 int i, my_modid, stm_idx, vp; 11284 11285 rv = _bcm_trunk_id_validate(unit, trunk_id); 11286 if (BCM_FAILURE(rv)) { 11287 return BCM_E_PORT; 11288 } 11289 if (!mpls_info->initialized) { 11290 LOG_ERROR(BSL_LS_BCM_MPLS, 11291 (BSL_META_U(unit, 11292 "MPLS module not initialized. \n"))); 11293 return BCM_E_INIT; 11294 } 11295 11296 vp = mpls_info->trunk_vp_map[trunk_id]; 11297 if (vp != -1) { 11298 BCM_IF_ERROR_RETURN( 11299 bcm_esw_stk_my_modid_get(unit, &my_modid)); 11300 /* Get index to source trunk map table */ 11301 11302 for (i = 0; i < trunk_member_count; i++) { 11303 BCM_IF_ERROR_RETURN 11304 (_bcm_esw_src_mod_port_table_index_get(unit, my_modid, 11305 trunk_member_array[i], &stm_idx)); 11306 BCM_IF_ERROR_RETURN 11307 (soc_mem_field32_modify(unit, SOURCE_TRUNK_MAP_TABLEm, 11308 stm_idx, SOURCE_VPf, vp)); 11309 if (SOC_MEM_FIELD_VALID(unit,SOURCE_TRUNK_MAP_TABLEm,SVP_VALIDf)) { 11310 BCM_IF_ERROR_RETURN 11311 (soc_mem_field32_modify(unit, SOURCE_TRUNK_MAP_TABLEm, 11312 stm_idx, SVP_VALIDf, 1)); 11313 } 11314 BCM_IF_ERROR_RETURN 11315 (_bcm_esw_port_tab_set(unit, trunk_member_array[i], 11316 _BCM_CPU_TABS_NONE, 11317 PORT_OPERATIONf, 0x1)); /* L2_SVP */ 11318 } 11319 } 11320 11321 return BCM_E_NONE; 11322 } 11323 11324 int 11325 bcm_tr_mpls_trunk_member_delete(int unit, bcm_trunk_t trunk_id, 11326 int trunk_member_count, bcm_port_t *trunk_member_array) 11327 { 11328 int rv = BCM_E_NONE; 11329 _bcm_tr_mpls_bookkeeping_t *mpls_info = MPLS_INFO(unit); 11330 int i, my_modid, stm_idx, vp; 11331 11332 rv = _bcm_trunk_id_validate(unit, trunk_id); 11333 if (BCM_FAILURE(rv)) { 11334 return BCM_E_PORT; 11335 } 11336 11337 vp = mpls_info->trunk_vp_map[trunk_id]; 11338 if (vp != -1) { 11339 BCM_IF_ERROR_RETURN( 11340 bcm_esw_stk_my_modid_get(unit, &my_modid)); 11341 /* Get index to source trunk map table */ 11342 11343 for (i = 0; i < trunk_member_count; i++) { 11344 BCM_IF_ERROR_RETURN 11345 (_bcm_esw_src_mod_port_table_index_get(unit, my_modid, 11346 trunk_member_array[i], &stm_idx)); 11347 BCM_IF_ERROR_RETURN 11348 (soc_mem_field32_modify(unit, SOURCE_TRUNK_MAP_TABLEm, 11349 stm_idx, SOURCE_VPf, 0)); 11350 if (SOC_MEM_FIELD_VALID(unit,SOURCE_TRUNK_MAP_TABLEm,SVP_VALIDf)) { 11351 BCM_IF_ERROR_RETURN 11352 (soc_mem_field32_modify(unit, SOURCE_TRUNK_MAP_TABLEm, 11353 stm_idx, SVP_VALIDf, 0)); 11354 } 11355 BCM_IF_ERROR_RETURN 11356 (_bcm_esw_port_tab_set(unit, trunk_member_array[i], 11357 _BCM_CPU_TABS_NONE, 11358 PORT_OPERATIONf, 0)); /* L2_SVP */ 11359 } 11360 } 11361 11362 return BCM_E_NONE; 11363 } 11364 11365 /* 11366 * Function: 11367 * bcm_tr_mpls_match_trunk_add 11368 * Purpose: 11369 * Assign SVP of an MPLS Trunk port 11370 * Parameters: 11371 * unit - (IN) Device Number 11372 * tgid - (IN) Trunk group Id 11373 * vp - (IN) Source Virtual Port 11374 * Returns: 11375 * BCM_E_XXX 11376 */ 11377 11378 int 11379 bcm_tr_mpls_match_trunk_add(int unit, bcm_trunk_t tgid, int vp) 11380 { 11381 int port_idx; 11382 bcm_module_t my_modid; 11383 #if defined(BCM_ESW_SUPPORT) && (SOC_MAX_NUM_PP_PORTS > SOC_MAX_NUM_PORTS) 11384 int max_num_port = SOC_MAX_NUM_PP_PORTS; 11385 #else 11386 int max_num_port = SOC_MAX_NUM_PORTS; 11387 #endif 11388 int * local_src_trk_idx = NULL; 11389 int * local_port_out = NULL; 11390 int local_member_count; 11391 int rv = BCM_E_NONE; 11392 int src_trk_idx = -1; 11393 bcm_port_t port_out; 11394 11395 local_src_trk_idx = sal_alloc(sizeof(int) * max_num_port, "local source Trunk index"); 11396 if (NULL == local_src_trk_idx) { 11397 return BCM_E_MEMORY; 11398 } 11399 sal_memset(local_src_trk_idx, 0, sizeof(int) * max_num_port); 11400 local_port_out = sal_alloc(sizeof(int) * max_num_port, "Local port out"); 11401 if (NULL == local_port_out) { 11402 sal_free(local_src_trk_idx); 11403 return BCM_E_MEMORY; 11404 } 11405 sal_memset(local_port_out, 0, sizeof(int) * max_num_port); 11406 rv = bcm_esw_stk_my_modid_get(unit, &my_modid); 11407 if (BCM_FAILURE(rv)) { 11408 sal_free(local_src_trk_idx); 11409 sal_free(local_port_out); 11410 return rv; 11411 } 11412 rv = _bcm_esw_trunk_local_members_get(unit, tgid, 11413 max_num_port, local_port_out, &local_member_count); 11414 if (BCM_FAILURE(rv)) { 11415 sal_free(local_src_trk_idx); 11416 sal_free(local_port_out); 11417 return rv; 11418 } 11419 for (port_idx = 0; port_idx < local_member_count; port_idx++) { 11420 rv = _bcm_tr_mpls_match_trunk_idx_get(unit, 11421 my_modid, local_port_out[port_idx], &src_trk_idx); 11422 if (BCM_FAILURE(rv)) { 11423 sal_free(local_src_trk_idx); 11424 sal_free(local_port_out); 11425 return rv; 11426 } 11427 local_src_trk_idx[port_idx] = src_trk_idx; 11428 11429 rv = soc_mem_field32_modify(unit, SOURCE_TRUNK_MAP_TABLEm, 11430 src_trk_idx, SOURCE_VPf, vp); 11431 if (BCM_FAILURE(rv)) { 11432 goto trunk_cleanup; 11433 } 11434 if (SOC_MEM_FIELD_VALID(unit,SOURCE_TRUNK_MAP_TABLEm,SVP_VALIDf)) { 11435 rv = soc_mem_field32_modify(unit, SOURCE_TRUNK_MAP_TABLEm, 11436 src_trk_idx, SVP_VALIDf, 1); 11437 if (BCM_FAILURE(rv)) { 11438 goto trunk_cleanup; 11439 } 11440 } 11441 11442 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 11443 rv = _bcm_esw_port_tab_set(unit, local_port_out[port_idx], 11444 _BCM_CPU_TABS_BOTH, 11445 PORT_OPERATIONf, 0x1); 11446 } else { 11447 rv = _bcm_esw_port_tab_set_without_portlock( 11448 unit, local_port_out[port_idx], _BCM_CPU_TABS_NONE, 11449 PORT_OPERATIONf, 0x1); /* L2_SVP */ 11450 } 11451 if (BCM_FAILURE(rv)) { 11452 goto trunk_cleanup; 11453 } 11454 11455 /* Set TAG_ACTION_PROFILE_PTR */ 11456 rv = bcm_tr_mpls_port_untagged_profile_set(unit, local_port_out[port_idx]); 11457 if (BCM_FAILURE(rv)) { 11458 goto trunk_cleanup; 11459 } 11460 } 11461 sal_free(local_src_trk_idx); 11462 sal_free(local_port_out); 11463 return BCM_E_NONE; 11464 11465 trunk_cleanup: 11466 for (;port_idx >= 0; port_idx--) { 11467 src_trk_idx = local_src_trk_idx[port_idx]; 11468 port_out = local_port_out[port_idx]; 11469 rv = soc_mem_field32_modify(unit, SOURCE_TRUNK_MAP_TABLEm, 11470 src_trk_idx, SOURCE_VPf, 0); 11471 if (rv < 0) { 11472 sal_free(local_src_trk_idx); 11473 sal_free(local_port_out); 11474 return rv; 11475 } 11476 if (SOC_MEM_FIELD_VALID(unit,SOURCE_TRUNK_MAP_TABLEm,SVP_VALIDf)) { 11477 rv = soc_mem_field32_modify(unit, SOURCE_TRUNK_MAP_TABLEm, 11478 src_trk_idx, SVP_VALIDf, 0); 11479 } 11480 if (BCM_SUCCESS(rv)) { 11481 11482 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 11483 rv = _bcm_esw_port_tab_set(unit, port_out, 11484 _BCM_CPU_TABS_BOTH, 11485 PORT_OPERATIONf, 0); 11486 } else { 11487 rv = _bcm_esw_port_tab_set_without_portlock( 11488 unit, port_out, _BCM_CPU_TABS_NONE, PORT_OPERATIONf, 0); 11489 } 11490 } 11491 } 11492 sal_free(local_src_trk_idx); 11493 sal_free(local_port_out); 11494 return rv; 11495 } 11496 11497 /* 11498 * Function: 11499 * bcm_tr_mpls_match_trunk_delete 11500 * Purpose: 11501 * Remove SVP of an MPLS Trunk port 11502 * Parameters: 11503 * unit - (IN) Device Number 11504 * tgid - (IN) Trunk group Id 11505 * vp - (IN) Source Virtual Port 11506 * Returns: 11507 * BCM_E_XXX 11508 */ 11509 11510 int 11511 bcm_tr_mpls_match_trunk_delete(int unit, bcm_trunk_t tgid, int vp) 11512 { 11513 int port_idx; 11514 bcm_module_t my_modid; 11515 #if defined(BCM_ESW_SUPPORT) && (SOC_MAX_NUM_PP_PORTS > SOC_MAX_NUM_PORTS) 11516 int max_num_port = SOC_MAX_NUM_PP_PORTS; 11517 int local_src_trk_idx[SOC_MAX_NUM_PP_PORTS]; 11518 int local_port_out[SOC_MAX_NUM_PP_PORTS]; 11519 #else 11520 int max_num_port = SOC_MAX_NUM_PORTS; 11521 int local_src_trk_idx[SOC_MAX_NUM_PORTS]; 11522 int local_port_out[SOC_MAX_NUM_PORTS]; 11523 #endif 11524 int local_member_count; 11525 int rv = BCM_E_NONE; 11526 int src_trk_idx = -1; 11527 bcm_port_t port_out; 11528 11529 BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &my_modid)); 11530 11531 BCM_IF_ERROR_RETURN(_bcm_esw_trunk_local_members_get(unit, tgid, 11532 max_num_port, local_port_out, &local_member_count)); 11533 11534 for (port_idx = 0; port_idx < local_member_count; port_idx++) { 11535 BCM_IF_ERROR_RETURN(_bcm_tr_mpls_match_trunk_idx_get(unit, 11536 my_modid, local_port_out[port_idx], &src_trk_idx)); 11537 local_src_trk_idx[port_idx] = src_trk_idx; 11538 11539 rv = soc_mem_field32_modify(unit, SOURCE_TRUNK_MAP_TABLEm, 11540 src_trk_idx, SOURCE_VPf, 0); 11541 if (BCM_FAILURE(rv)) { 11542 goto trunk_cleanup; 11543 } 11544 if (SOC_MEM_FIELD_VALID(unit,SOURCE_TRUNK_MAP_TABLEm,SVP_VALIDf)) { 11545 rv = soc_mem_field32_modify(unit, SOURCE_TRUNK_MAP_TABLEm, 11546 src_trk_idx, SVP_VALIDf, 0); 11547 if (BCM_FAILURE(rv)) { 11548 goto trunk_cleanup; 11549 } 11550 } 11551 11552 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 11553 rv = _bcm_esw_port_tab_set(unit, local_port_out[port_idx], 11554 _BCM_CPU_TABS_BOTH, 11555 PORT_OPERATIONf, 0x0); 11556 } else { 11557 rv = _bcm_esw_port_tab_set_without_portlock( 11558 unit, local_port_out[port_idx], _BCM_CPU_TABS_NONE, 11559 PORT_OPERATIONf, 0x0); /* L2_SVP */ 11560 } 11561 if (BCM_FAILURE(rv)) { 11562 goto trunk_cleanup; 11563 } 11564 11565 /* Reset TAG_ACTION_PROFILE_PTR */ 11566 /* coverity[stack_use_callee] */ 11567 /* coverity[stack_use_overflow] */ 11568 rv = bcm_tr_mpls_port_untagged_profile_reset(unit, local_port_out[port_idx]); 11569 BCM_IF_ERROR_RETURN(rv); 11570 } 11571 11572 return BCM_E_NONE; 11573 11574 trunk_cleanup: 11575 for (;port_idx >= 0; port_idx--) { 11576 src_trk_idx = local_src_trk_idx[port_idx]; 11577 port_out = local_port_out[port_idx]; 11578 (void)soc_mem_field32_modify(unit, SOURCE_TRUNK_MAP_TABLEm, 11579 src_trk_idx, SOURCE_VPf, vp); 11580 if (SOC_MEM_FIELD_VALID(unit,SOURCE_TRUNK_MAP_TABLEm,SVP_VALIDf)) { 11581 (void)soc_mem_field32_modify(unit, SOURCE_TRUNK_MAP_TABLEm, 11582 src_trk_idx, SVP_VALIDf, 1); 11583 } 11584 11585 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 11586 rv = _bcm_esw_port_tab_set(unit, port_out, 11587 _BCM_CPU_TABS_BOTH, 11588 PORT_OPERATIONf, 0x1); 11589 } else { 11590 (void)_bcm_esw_port_tab_set_without_portlock(unit, port_out, 11591 _BCM_CPU_TABS_NONE, 11592 PORT_OPERATIONf, 0x1); 11593 } 11594 } 11595 return rv; 11596 } 11597 11598 /* 11599 * Function: 11600 * _bcm_tr_mpls_match_vlan_entry_update 11601 * Purpose: 11602 * Update MPLS Match Vlan_xlate Entry 11603 * Parameters: 11604 * IN : Unit 11605 * IN : vlan_xlate_entry 11606 * OUT : vlan_xlate_entry 11607 11608 */ 11609 11610 STATIC int 11611 _bcm_tr_mpls_match_vlan_entry_update(int unit, bcm_mpls_port_t *mpls_port, 11612 uint32 *vent, uint32 *return_ent) 11613 { 11614 uint32 vp, key_type, value; 11615 soc_mem_t mem; 11616 11617 #if defined(BCM_TRIDENT3_SUPPORT) 11618 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 11619 mem = VLAN_XLATE_1_DOUBLEm; 11620 } else 11621 #endif 11622 { 11623 mem = VLAN_XLATEm; 11624 } 11625 11626 if ((vent == NULL) || (return_ent == NULL)) { 11627 return BCM_E_PARAM; 11628 } 11629 11630 /* Check if Key_Type identical */ 11631 key_type = soc_mem_field32_get(unit, mem, vent, KEY_TYPEf); 11632 value = soc_mem_field32_get(unit, mem, return_ent, KEY_TYPEf); 11633 if (key_type != value) { 11634 return BCM_E_PARAM; 11635 } 11636 11637 value = soc_mem_field32_get(unit, mem, return_ent, MPLS_ACTIONf); 11638 /* SVP_VALID and L3_IIF_VALID overlay high and low bits of MPLS_ACTION. */ 11639 if (SOC_MEM_FIELD_VALID(unit, mem, L3_IIF_VALIDf)) { 11640 value |= 0x1; 11641 } else { 11642 value = 0x1; 11643 } 11644 /* Retain original Keys -- Update data only */ 11645 soc_mem_field32_set(unit, mem, return_ent, MPLS_ACTIONf, value); 11646 if (!(mpls_port->flags & BCM_MPLS_PORT_REPLACE)) { 11647 soc_mem_field32_set(unit, mem, return_ent, DISABLE_VLAN_CHECKSf, 1); 11648 } 11649 vp = soc_mem_field32_get(unit, mem, vent, SOURCE_VPf); 11650 soc_mem_field32_set(unit, mem, return_ent, SOURCE_VPf, vp); 11651 /*set default tag action profile ptr*/ 11652 #if defined(BCM_TRIDENT3_SUPPORT) 11653 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 11654 soc_mem_field32_set(unit, mem, vent, XLATE__TAG_ACTION_PROFILE_PTRf, 1); 11655 } 11656 #endif 11657 11658 return BCM_E_NONE; 11659 } 11660 11661 11662 /* 11663 * Function: 11664 * _bcm_tr_mpls_match_label_entry_update 11665 * Purpose: 11666 * Update Match MPLS Entry 11667 * Parameters: 11668 * IN : Unit 11669 * IN : mpls_entry 11670 * OUT : mpls_entry 11671 11672 */ 11673 11674 STATIC void 11675 _bcm_tr_mpls_match_label_entry_update(int unit, bcm_mpls_port_t *mpls_port, 11676 mpls_entry_entry_t *ment, 11677 mpls_entry_entry_t *return_ment) 11678 { 11679 uint32 value; 11680 bcm_module_t mod_id; 11681 bcm_port_t port_id; 11682 bcm_trunk_t trunk_id; 11683 bcm_mpls_label_t match_label; 11684 11685 value = soc_MPLS_ENTRYm_field32_get (unit, ment, Tf); 11686 if (value) { 11687 soc_MPLS_ENTRYm_field32_set(unit, return_ment, Tf, value); 11688 trunk_id = soc_MPLS_ENTRYm_field32_get (unit, ment, TGIDf); 11689 soc_MPLS_ENTRYm_field32_set(unit, return_ment, TGIDf, trunk_id); 11690 } else { 11691 mod_id = soc_MPLS_ENTRYm_field32_get (unit, ment, MODULE_IDf); 11692 soc_MPLS_ENTRYm_field32_set(unit, return_ment, MODULE_IDf, mod_id); 11693 port_id = soc_MPLS_ENTRYm_field32_get (unit, ment, PORT_NUMf); 11694 soc_MPLS_ENTRYm_field32_set(unit, return_ment, PORT_NUMf, port_id); 11695 } 11696 11697 match_label = soc_MPLS_ENTRYm_field32_get(unit, ment, MPLS_LABELf); 11698 soc_MPLS_ENTRYm_field32_set(unit, return_ment, MPLS_LABELf, match_label); 11699 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 11700 soc_MPLS_ENTRYm_field32_set(unit, return_ment, BASE_VALID_0f, 3); 11701 soc_MPLS_ENTRYm_field32_set(unit, return_ment, BASE_VALID_1f, 7); 11702 } else { 11703 soc_MPLS_ENTRYm_field32_set(unit, return_ment, VALIDf, 1); 11704 } 11705 value = soc_MPLS_ENTRYm_field32_get(unit, ment, SOURCE_VPf); 11706 soc_MPLS_ENTRYm_field32_set(unit, return_ment, SOURCE_VPf, value); 11707 soc_MPLS_ENTRYm_field32_set(unit, return_ment, MPLS_ACTION_IF_BOSf, 0x1); /* L2 SVP */ 11708 soc_MPLS_ENTRYm_field32_set(unit, return_ment, MPLS_ACTION_IF_NOT_BOSf, 0x0); 11709 value = soc_MPLS_ENTRYm_field32_get(unit, ment, CW_CHECK_CTRLf); 11710 soc_MPLS_ENTRYm_field32_set(unit, return_ment, CW_CHECK_CTRLf, value); 11711 value = soc_MPLS_ENTRYm_field32_get(unit, ment, PW_TERM_NUM_VALIDf); 11712 soc_MPLS_ENTRYm_field32_set(unit, return_ment, PW_TERM_NUM_VALIDf, value); 11713 if(value) { 11714 value = soc_MPLS_ENTRYm_field32_get(unit, ment, PW_TERM_NUMf); 11715 soc_MPLS_ENTRYm_field32_set(unit, return_ment, PW_TERM_NUMf, value); 11716 } 11717 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) 11718 else { 11719 if ((soc_feature(unit, soc_feature_mpls_enhanced)) && 11720 (soc_feature(unit,soc_feature_advanced_flex_counter))) { 11721 value = soc_MPLS_ENTRYm_field32_get(unit, ment, MPLS__FLEX_CTR_POOL_NUMBERf); 11722 soc_MPLS_ENTRYm_field32_set(unit, return_ment, MPLS__FLEX_CTR_POOL_NUMBERf, value); 11723 value = soc_MPLS_ENTRYm_field32_get(unit, ment, MPLS__FLEX_CTR_BASE_COUNTER_IDXf); 11724 soc_MPLS_ENTRYm_field32_set(unit, return_ment, MPLS__FLEX_CTR_BASE_COUNTER_IDXf, value); 11725 value = soc_MPLS_ENTRYm_field32_get(unit, ment, MPLS__FLEX_CTR_OFFSET_MODEf); 11726 soc_MPLS_ENTRYm_field32_set(unit, return_ment, MPLS__FLEX_CTR_OFFSET_MODEf, value); 11727 } 11728 } 11729 #endif 11730 11731 value = soc_MPLS_ENTRYm_field32_get(unit, ment, DECAP_USE_EXP_FOR_PRIf); 11732 soc_MPLS_ENTRYm_field32_set(unit, return_ment, DECAP_USE_EXP_FOR_PRIf, 11733 value); 11734 value = soc_MPLS_ENTRYm_field32_get(unit, ment, EXP_MAPPING_PTRf); 11735 soc_MPLS_ENTRYm_field32_set(unit, return_ment, EXP_MAPPING_PTRf, value); 11736 value = soc_MPLS_ENTRYm_field32_get(unit, ment, NEW_PRIf); 11737 soc_MPLS_ENTRYm_field32_set(unit, return_ment, NEW_PRIf, value); 11738 if (soc_mem_field_valid(unit, MPLS_ENTRYm, TRUST_OUTER_DOT1P_PTRf)) { 11739 value = soc_MPLS_ENTRYm_field32_get(unit, ment, TRUST_OUTER_DOT1P_PTRf); 11740 soc_MPLS_ENTRYm_field32_set(unit, return_ment, TRUST_OUTER_DOT1P_PTRf, 11741 value); 11742 } 11743 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIDENT2PLUS_SUPPORT) 11744 if (soc_feature(unit, soc_feature_mpls_entropy)) { 11745 if ((mpls_port->flags & BCM_MPLS_PORT_ENTROPY_ENABLE) || 11746 (mpls_port->flags2 & BCM_MPLS_PORT2_INGRESS_ENTROPY_ENABLE)) { 11747 if (soc_mem_field_valid(unit, MPLS_ENTRYm, 11748 ENTROPY_LABEL_PRESENTf)) { 11749 soc_MPLS_ENTRYm_field32_set(unit, return_ment, 11750 ENTROPY_LABEL_PRESENTf, 0x1); 11751 soc_MPLS_ENTRYm_field32_set(unit, return_ment, MPLS_ACTION_IF_BOSf, 11752 0x0); /* INVALID */ 11753 if (SOC_IS_APACHE(unit)) { 11754 soc_MPLS_ENTRYm_field32_set(unit, return_ment, MPLS_ACTION_IF_NOT_BOSf, 11755 0x6); /* POP_SVP_ENTROPY */ 11756 } else { 11757 soc_MPLS_ENTRYm_field32_set(unit, return_ment, MPLS_ACTION_IF_NOT_BOSf, 11758 0x4); /* POP_SVP_ENTROPY */ 11759 } 11760 } 11761 } else if (soc_mem_field_valid(unit, MPLS_ENTRYm, 11762 ENTROPY_LABEL_PRESENTf)) { 11763 soc_MPLS_ENTRYm_field32_set(unit, return_ment, 11764 ENTROPY_LABEL_PRESENTf, 0x0); 11765 } 11766 } 11767 #endif 11768 #if defined(BCM_TOMAHAWK2_SUPPORT) || defined(BCM_TRIDENT3_SUPPORT) 11769 if (soc_feature(unit, soc_feature_mpls_ecn)) { 11770 #if defined(BCM_TRIDENT3_SUPPORT) 11771 if(soc_feature(unit, soc_feature_td3_style_mpls)) { 11772 value = soc_MPLS_ENTRYm_field32_get(unit, ment, MPLS__EXP_TO_ECN_MAPPING_PTRf); 11773 soc_MPLS_ENTRYm_field32_set(unit, return_ment, MPLS__EXP_TO_ECN_MAPPING_PTRf, value); 11774 } else 11775 #endif 11776 { 11777 value = soc_MPLS_ENTRYm_field32_get(unit, ment, MPLS__EXP_TO_IP_ECN_MAPPING_PTRf); 11778 soc_MPLS_ENTRYm_field32_set(unit, return_ment, MPLS__EXP_TO_IP_ECN_MAPPING_PTRf, value); 11779 } 11780 } 11781 #endif 11782 if (soc_mem_field_valid(unit, MPLS_ENTRYm,DO_NOT_CHANGE_PAYLOAD_DSCPf)) { 11783 value = 11784 soc_MPLS_ENTRYm_field32_get(unit, ment, DO_NOT_CHANGE_PAYLOAD_DSCPf); 11785 soc_MPLS_ENTRYm_field32_set( 11786 unit, return_ment, DO_NOT_CHANGE_PAYLOAD_DSCPf, value); 11787 } 11788 return; 11789 } 11790 11791 /* 11792 * Function: 11793 * _bcm_tr_mpls_vpless_failover_nh_index_find 11794 * Purpose: 11795 * Traverse the EGR_L3_NEXT_HOP table to find next hop 11796 * index for the failover mpls port of the same VP(vpless mpls port). 11797 * Parameters: 11798 * IN : Unit 11799 * IN : vp - the same vp for primary and vpless failover mpls ports 11800 * IN : primary_nh_index - primary mpls port next hop index 11801 * OUT : fo_nh_index - the failover mpls port next hop index 11802 * Returns: 11803 * BCM_E_XXX 11804 */ 11805 int 11806 _bcm_tr_mpls_vpless_failover_nh_index_find (int unit, int vp, 11807 int primary_nh_index, int *fo_nh_index) 11808 { 11809 /* Indexes to iterate over memories, chunks and entries */ 11810 int chnk_idx, ent_idx, chnk_idx_max, mem_idx_max; 11811 int buf_size, chunksize, chnk_end; 11812 uint32 *tbl_chnk; 11813 egr_l3_next_hop_entry_t *egr_nh; 11814 int rv = BCM_E_NONE; 11815 soc_mem_t mem; 11816 int dvp; 11817 int entry_type; 11818 11819 *fo_nh_index = 0; 11820 mem = EGR_L3_NEXT_HOPm; 11821 chunksize = 0x400; /* 1k */ 11822 buf_size = sizeof(egr_l3_next_hop_entry_t) * chunksize; 11823 tbl_chnk = soc_cm_salloc(unit, buf_size, "egr_l3_next_hop traverse"); 11824 if (NULL == tbl_chnk) { 11825 return BCM_E_MEMORY; 11826 } 11827 11828 mem_idx_max = soc_mem_index_max(unit, mem); 11829 for (chnk_idx = soc_mem_index_min(unit, mem); 11830 chnk_idx <= mem_idx_max; 11831 chnk_idx += chunksize) { 11832 sal_memset((void *)tbl_chnk, 0, buf_size); 11833 11834 chnk_idx_max = 11835 ((chnk_idx + chunksize) <= mem_idx_max) ? 11836 chnk_idx + chunksize - 1: mem_idx_max; 11837 11838 soc_mem_lock(unit, mem); 11839 rv = soc_mem_read_range(unit, mem, MEM_BLOCK_ANY, 11840 chnk_idx, chnk_idx_max, tbl_chnk); 11841 if (SOC_FAILURE(rv)) { 11842 soc_mem_unlock(unit, mem); 11843 soc_cm_sfree(unit, tbl_chnk); 11844 return rv; 11845 } 11846 chnk_end = (chnk_idx_max - chnk_idx); 11847 for (ent_idx = 0 ; ent_idx <= chnk_end; ent_idx ++) { 11848 egr_nh = soc_mem_table_idx_to_pointer(unit, mem, 11849 egr_l3_next_hop_entry_t *, 11850 tbl_chnk, ent_idx); 11851 11852 entry_type = soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, 11853 egr_nh, nh_entry_type_field[unit]); 11854 if (soc_feature(unit, soc_feature_mpls_enhanced)) { 11855 dvp = soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, 11856 egr_nh, MPLS__DVPf); 11857 } else { 11858 dvp = soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, 11859 egr_nh, DVPf); 11860 } 11861 11862 if ((entry_type == 1) && 11863 (dvp == vp) && ((ent_idx+chnk_idx) != primary_nh_index)) { 11864 *fo_nh_index = ent_idx+chnk_idx; 11865 soc_mem_unlock(unit, mem); 11866 soc_cm_sfree(unit, tbl_chnk); 11867 return BCM_E_NONE; 11868 } 11869 } 11870 soc_mem_unlock(unit, mem); 11871 } 11872 soc_cm_sfree(unit, tbl_chnk); 11873 return BCM_E_NOT_FOUND; 11874 } 11875 11876 /* 11877 * Function: 11878 * _bcm_tr_mpls_match_vlan_entry_set 11879 * Purpose: 11880 * Set MPLS Match Vlan Entry 11881 * Parameters: 11882 * IN : Unit 11883 * IN : mpls_port 11884 * IN : vlan_xlate_entry 11885 * Returns: 11886 * BCM_E_XXX 11887 */ 11888 11889 STATIC int 11890 _bcm_tr_mpls_match_vlan_entry_set(int unit, bcm_mpls_port_t *mpls_port, uint32 *vent) 11891 { 11892 uint32 return_vent[SOC_MAX_MEM_WORDS]; 11893 int rv = BCM_E_UNAVAIL; 11894 int index; 11895 soc_mem_t mem; 11896 11897 if (vent == NULL) { 11898 return rv; 11899 } 11900 #if defined(BCM_TRIDENT3_SUPPORT) 11901 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 11902 mem = VLAN_XLATE_1_DOUBLEm; 11903 } else 11904 #endif 11905 { 11906 mem = VLAN_XLATEm; 11907 } 11908 11909 rv = soc_mem_search(unit, mem, MEM_BLOCK_ANY, &index, 11910 vent, return_vent, 0); 11911 11912 if (rv == SOC_E_NONE) { 11913 BCM_IF_ERROR_RETURN( 11914 _bcm_tr_mpls_match_vlan_entry_update (unit, mpls_port, vent, return_vent)); 11915 11916 rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, index, 11917 return_vent); 11918 } else if (rv != SOC_E_NOT_FOUND) { 11919 return rv; 11920 } else { 11921 if (mpls_port->flags & BCM_MPLS_PORT_REPLACE) { 11922 return BCM_E_NOT_FOUND; 11923 } else { 11924 rv = soc_mem_insert(unit, mem, MEM_BLOCK_ALL, vent); 11925 } 11926 } 11927 11928 return rv; 11929 } 11930 11931 /* 11932 * Function: 11933 * _bcm_tr_mpls_match_label_entry_set 11934 * Purpose: 11935 * Set MPLS Match Label Entry 11936 * Parameters: 11937 * IN : Unit 11938 * IN : mpls_port 11939 * IN : mpls_entry 11940 * Returns: 11941 * BCM_E_XXX 11942 */ 11943 11944 STATIC int 11945 _bcm_tr_mpls_match_label_entry_set(int unit, bcm_mpls_port_t *mpls_port, mpls_entry_entry_t *ment) 11946 { 11947 mpls_entry_entry_t return_ment; 11948 int rv = BCM_E_UNAVAIL; 11949 int index; 11950 11951 rv = soc_mem_search(unit, MPLS_ENTRYm, MEM_BLOCK_ANY, &index, 11952 ment, &return_ment, 0); 11953 11954 if (rv == SOC_E_NONE) { 11955 (void) _bcm_tr_mpls_match_label_entry_update (unit, mpls_port, ment, &return_ment); 11956 rv = soc_mem_write(unit, MPLS_ENTRYm, 11957 MEM_BLOCK_ALL, index, 11958 &return_ment); 11959 } else if (rv != SOC_E_NOT_FOUND) { 11960 return rv; 11961 } else { 11962 rv = soc_mem_insert(unit, MPLS_ENTRYm, MEM_BLOCK_ALL, ment); 11963 } 11964 11965 return rv; 11966 } 11967 11968 /* 11969 * Function: 11970 * _bcm_tr_mpls_match_clear 11971 * Purpose: 11972 * Clear MPLS Match Software State 11973 * Parameters: 11974 * unit - (IN) Device Number 11975 * vp - (IN) Source Virtual Port 11976 * Returns: 11977 * void 11978 */ 11979 11980 void 11981 bcm_tr_mpls_match_clear (int unit, int vp) 11982 { 11983 _bcm_tr_mpls_bookkeeping_t *mpls_info = MPLS_INFO(unit); 11984 11985 mpls_info->match_key[vp].flags = 0; 11986 mpls_info->match_key[vp].match_vlan = 0; 11987 mpls_info->match_key[vp].match_inner_vlan = 0; 11988 mpls_info->match_key[vp].match_label = 0; 11989 mpls_info->match_key[vp].trunk_id = -1; 11990 mpls_info->match_key[vp].port = 0; 11991 mpls_info->match_key[vp].modid = -1; 11992 mpls_info->match_key[vp].index = 0; 11993 11994 return; 11995 } 11996 11997 /* 11998 * Function: 11999 * bcm_tr_mpls_entry_internal_qos_set 12000 * Purpose: 12001 * Set MPLS Entry QoS parameters 12002 * Parameters: 12003 * IN : Unit 12004 * IN : mpls_port 12005 * IN : mpls_entry 12006 * Returns: 12007 * BCM_E_XXX 12008 */ 12009 12010 void 12011 bcm_tr_mpls_entry_internal_qos_set(int unit, bcm_mpls_port_t *mpls_port, 12012 bcm_mpls_tunnel_switch_t *info, mpls_entry_entry_t *ment) 12013 { 12014 soc_mem_t mem = MPLS_ENTRYm; 12015 12016 if (soc_feature(unit, soc_feature_th3_style_simple_mpls)) { 12017 mem = MPLS_ENTRY_SINGLEm; 12018 } 12019 12020 if (mpls_port != NULL ) { 12021 if (mpls_port->flags & BCM_MPLS_PORT_INT_PRI_MAP) { 12022 soc_mem_field32_set(unit, mem, ment, DECAP_USE_EXP_FOR_PRIf, 12023 0x1); /* MAP_PRI_AND_CNG */ 12024 /* Use specified EXP-map to determine internal prio/color */ 12025 soc_mem_field32_set(unit, mem, ment, EXP_MAPPING_PTRf, 12026 mpls_port->exp_map & _BCM_TR_MPLS_EXP_MAP_TABLE_NUM_MASK); 12027 } else if ((mpls_port->flags & BCM_MPLS_PORT_INT_PRI_SET) && 12028 (mpls_port->flags & BCM_MPLS_PORT_COLOR_MAP)) { 12029 soc_mem_field32_set(unit, mem, ment, DECAP_USE_EXP_FOR_PRIf, 12030 0x2); /* NEW_PRI_MAP_CNG */ 12031 /* Use the specified internal priority value */ 12032 soc_mem_field32_set(unit, mem, ment, NEW_PRIf, 12033 mpls_port->int_pri); 12034 /* Use specified EXP-map to determine internal color */ 12035 soc_mem_field32_set(unit, mem, ment, EXP_MAPPING_PTRf, 12036 mpls_port->exp_map & _BCM_TR_MPLS_EXP_MAP_TABLE_NUM_MASK); 12037 } else if (mpls_port->flags & BCM_MPLS_PORT_INT_PRI_SET) { 12038 soc_mem_field32_set(unit, mem, ment, DECAP_USE_EXP_FOR_PRIf, 0x2); 12039 if (soc_mem_field_valid(unit, MPLS_ENTRYm, 12040 TRUST_OUTER_DOT1P_PTRf)) { 12041 soc_mem_field32_set(unit, mem, ment, 12042 TRUST_OUTER_DOT1P_PTRf, 12043 _BCM_TR_MPLS_PRI_CNG_MAP_NONE); 12044 } 12045 soc_mem_field32_set(unit, mem, ment, NEW_PRIf, 12046 mpls_port->int_pri); 12047 } else { 12048 /* Trust the encapsulated packet's 802.1p pri/cfi, 12049 * and use the incoming ports mapping. 12050 */ 12051 soc_mem_field32_set(unit, mem, ment, DECAP_USE_EXP_FOR_PRIf, 12052 0x0); /* NONE */ 12053 if (soc_mem_field_valid(unit, MPLS_ENTRYm, 12054 TRUST_OUTER_DOT1P_PTRf)) { 12055 soc_mem_field32_set(unit, mem, ment, 12056 TRUST_OUTER_DOT1P_PTRf, 12057 _BCM_TR_MPLS_PRI_CNG_MAP_IDENTITY); 12058 } 12059 } 12060 }else if ( info != NULL ) { 12061 if (info->flags & BCM_MPLS_SWITCH_INT_PRI_MAP) { 12062 soc_mem_field32_set(unit, mem, ment, DECAP_USE_EXP_FOR_PRIf, 12063 0x1); /* MAP_PRI_AND_CNG */ 12064 /* Use specified EXP-map to determine internal prio/color */ 12065 soc_mem_field32_set(unit, mem, ment, EXP_MAPPING_PTRf, 12066 info->exp_map & _BCM_TR_MPLS_EXP_MAP_TABLE_NUM_MASK); 12067 } else if ((info->flags & BCM_MPLS_SWITCH_INT_PRI_SET) && 12068 (info->flags & BCM_MPLS_SWITCH_COLOR_MAP)) { 12069 soc_mem_field32_set(unit, mem, ment, DECAP_USE_EXP_FOR_PRIf, 12070 0x2); /* NEW_PRI_MAP_CNG */ 12071 /* Use the specified internal priority value */ 12072 soc_mem_field32_set(unit, mem, ment, NEW_PRIf, 12073 info->int_pri); 12074 /* Use specified EXP-map to determine internal color */ 12075 soc_mem_field32_set(unit, mem, ment, EXP_MAPPING_PTRf, 12076 info->exp_map & _BCM_TR_MPLS_EXP_MAP_TABLE_NUM_MASK); 12077 } else if (info->flags & BCM_MPLS_SWITCH_INT_PRI_SET) { 12078 soc_mem_field32_set(unit, mem, ment, DECAP_USE_EXP_FOR_PRIf, 0x2); 12079 if (soc_mem_field_valid(unit, MPLS_ENTRYm, 12080 TRUST_OUTER_DOT1P_PTRf)) { 12081 soc_mem_field32_set(unit, mem, ment, 12082 TRUST_OUTER_DOT1P_PTRf, 12083 _BCM_TR_MPLS_PRI_CNG_MAP_NONE); 12084 } 12085 soc_mem_field32_set(unit, mem, ment, NEW_PRIf, 12086 info->int_pri); 12087 } else { 12088 /* Trust the encapsulated packet's 802.1p pri/cfi, 12089 * and use the incoming ports mapping. 12090 */ 12091 soc_mem_field32_set(unit, mem, ment, DECAP_USE_EXP_FOR_PRIf, 12092 0x0); /* NONE */ 12093 if (soc_mem_field_valid(unit, MPLS_ENTRYm, 12094 TRUST_OUTER_DOT1P_PTRf)) { 12095 soc_mem_field32_set(unit, mem, ment, 12096 TRUST_OUTER_DOT1P_PTRf, 12097 _BCM_TR_MPLS_PRI_CNG_MAP_IDENTITY); 12098 } 12099 } 12100 } 12101 } 12102 12103 /* 12104 * Function: 12105 * _bcm_tr_mpls_match_vp_find 12106 * Purpose: 12107 * Find MPLS VP has the same match 12108 * Parameters: 12109 * unit - (IN) SOC unit number. 12110 * vp1 - (IN) MPLS VP. 12111 * vp2 - (OUT) MPLS VP. 12112 * Returns: 12113 * TRUE - Found 12114 * FALSE - Not Found 12115 */ 12116 int 12117 _bcm_tr_mpls_match_vp_find(int unit, int vp1, int *vp2) 12118 { 12119 int vp = 0; 12120 int num_vp = 0; 12121 bcm_mpls_label_t label1 = 0; 12122 bcm_mpls_label_t label2 = 0; 12123 _bcm_tr_mpls_match_port_info_t *mkey1 = NULL; 12124 _bcm_tr_mpls_match_port_info_t *mkey2 = NULL; 12125 12126 mkey1 = &(MPLS_INFO(unit)->match_key[vp1]); 12127 label1 = mkey1->match_label; 12128 12129 if (mkey1->flags != _BCM_MPLS_PORT_MATCH_TYPE_LABEL) { 12130 return FALSE; 12131 } 12132 12133 num_vp = soc_mem_index_count(unit, SOURCE_VPm); 12134 for (vp = 0; vp < num_vp; vp++) { 12135 if (vp == vp1) { 12136 continue; 12137 } 12138 12139 mkey2 = &(MPLS_INFO(unit)->match_key[vp]); 12140 if (mkey2->flags == _BCM_MPLS_PORT_MATCH_TYPE_LABEL) { 12141 label2 = mkey2->match_label; 12142 12143 if (label1 == label2) { 12144 *vp2 = vp; 12145 return TRUE; 12146 } 12147 } 12148 } 12149 12150 return FALSE; 12151 } 12152 12153 /* 12154 * Function: 12155 * _bcm_tr_mpls_match_add 12156 * Purpose: 12157 * Assign match criteria of an MPLS port 12158 * Parameters: 12159 * unit - (IN) Device Number 12160 * mpls_port - (IN) mpls port information 12161 * vp - (IN) Source Virtual Port 12162 * vpn - (IN) VPN 12163 * Returns: 12164 * BCM_E_XXX 12165 */ 12166 12167 int 12168 _bcm_tr_mpls_match_add(int unit, bcm_mpls_port_t *mpls_port, int vp, int vpn, 12169 int hw_update) 12170 { 12171 _bcm_tr_mpls_bookkeeping_t *mpls_info = MPLS_INFO(unit); 12172 int rv = BCM_E_NONE, gport_id; 12173 bcm_module_t mod_out; 12174 bcm_port_t port_out; 12175 bcm_trunk_t trunk_id; 12176 int src_trk_idx=0; /*Source Trunk table index.*/ 12177 int vpless_failover_port = FALSE; /* the failover port without a dedicated vp */ 12178 bcm_mpls_label_t old_match_label; 12179 #if defined(BCM_KATANA2_SUPPORT) 12180 int my_modid = 0; 12181 #endif 12182 #if defined(BCM_KATANA2_SUPPORT) || defined(BCM_HGPROXY_COE_SUPPORT) 12183 int is_local_subport = 0, local_port = 0; 12184 #endif 12185 int vfi = 0; 12186 _bcm_vp_info_t vp_info; 12187 uint32 vent[SOC_MAX_MEM_WORDS]; 12188 soc_mem_t mem; 12189 12190 sal_memset(vent, 0, sizeof(uint32) * SOC_MAX_MEM_WORDS); 12191 #if defined(BCM_TRIDENT3_SUPPORT) 12192 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 12193 mem = VLAN_XLATE_1_DOUBLEm; 12194 } else 12195 #endif 12196 { 12197 mem = VLAN_XLATEm; 12198 } 12199 12200 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 12201 if (mpls_port->criteria == BCM_MPLS_PORT_MATCH_SHARE) { 12202 mpls_info->match_key[vp].flags = _BCM_MPLS_PORT_MATCH_TYPE_SHARE; 12203 return BCM_E_NONE; 12204 } 12205 12206 if (SOC_MEM_FIELD_VALID(unit, MPLS_ENTRYm, CLASS_IDf)) { 12207 /* Ensure that class_id doesnt overcross CLASS_IDf */ 12208 int bit_num = 0; 12209 if ((mpls_port->flags & (BCM_MPLS_PORT_COUNTED | 12210 BCM_MPLS_PORT_SEQUENCED)) && (mpls_port->class_id)) { 12211 return BCM_E_PARAM; 12212 } 12213 if (mpls_port->class_id) { 12214 bit_num = soc_mem_field_length(unit, MPLS_ENTRYm, CLASS_IDf); 12215 if (mpls_port->class_id > (( 1 << bit_num ) - 1)) { 12216 return BCM_E_PARAM; 12217 } 12218 } 12219 } 12220 #endif 12221 12222 if (_BCM_MPLS_GPORT_FAILOVER_VPLESS_GET(vp)) { 12223 if (mpls_port->criteria & BCM_MPLS_PORT_MATCH_LABEL) { 12224 /* should use same entry as primary */ 12225 return BCM_E_NONE; 12226 } 12227 vpless_failover_port = TRUE; 12228 vp = _BCM_MPLS_GPORT_FAILOVER_VPLESS_CLEAR(vp); 12229 } 12230 12231 12232 if ((mpls_port->criteria != BCM_MPLS_PORT_MATCH_LABEL) && 12233 (mpls_port->criteria != BCM_MPLS_PORT_MATCH_VLAN)) { 12234 rv = _bcm_esw_gport_resolve(unit, mpls_port->port, &mod_out, 12235 &port_out, &trunk_id, &gport_id); 12236 BCM_IF_ERROR_RETURN(rv); 12237 } 12238 12239 /* set default vlan_xlate key source field type as SGLP */ 12240 if (SOC_MEM_FIELD_VALID(unit, mem, SOURCE_TYPEf)) { 12241 soc_mem_field32_set(unit, mem, vent, SOURCE_TYPEf, 1); 12242 } 12243 /* VLAN Translation Action is valid for this lookup */ 12244 if (SOC_MEM_FIELD_VALID(unit, mem, XLATE__VLAN_ACTION_VALIDf)) { 12245 soc_mem_field32_set(unit, mem, vent, XLATE__VLAN_ACTION_VALIDf, 1); 12246 } 12247 if (mpls_port->criteria == BCM_MPLS_PORT_MATCH_PORT_VLAN ) { 12248 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 12249 soc_mem_field32_set(unit, mem, vent, BASE_VALID_0f, 3); 12250 soc_mem_field32_set(unit, mem, vent, BASE_VALID_1f, 7); 12251 soc_mem_field32_set(unit, mem, vent, 12252 DATA_TYPEf, TR_VLXLT_HASH_KEY_TYPE_OVID); 12253 /*set default tag action profile ptr*/ 12254 soc_mem_field32_set(unit, mem, vent, XLATE__TAG_ACTION_PROFILE_PTRf, 1); 12255 } else { 12256 soc_mem_field32_set(unit, mem, vent, VALIDf, 1); 12257 } 12258 12259 soc_mem_field32_set(unit, mem, vent, MPLS_ACTIONf, 0x1); /* SVP */ 12260 soc_mem_field32_set(unit, mem, vent, DISABLE_VLAN_CHECKSf, 1); 12261 soc_mem_field32_set(unit, mem, vent, SOURCE_VPf, vp); 12262 if (!BCM_VLAN_VALID(mpls_port->match_vlan)) { 12263 return BCM_E_PARAM; 12264 } 12265 soc_mem_field32_set(unit, mem, vent, KEY_TYPEf, 12266 TR_VLXLT_HASH_KEY_TYPE_OVID); 12267 soc_mem_field32_set(unit, mem, vent, OVIDf, 12268 mpls_port->match_vlan); 12269 12270 if (BCM_GPORT_IS_TRUNK(mpls_port->port)) { 12271 soc_mem_field32_set(unit, mem, vent, Tf, 1); 12272 soc_mem_field32_set(unit, mem, vent, TGIDf, trunk_id); 12273 } else { 12274 soc_mem_field32_set(unit, mem, vent, MODULE_IDf, mod_out); 12275 soc_mem_field32_set(unit, mem, vent, PORT_NUMf, port_out); 12276 } 12277 if (soc_feature(unit, soc_feature_vp_sharing)) { 12278 BCM_IF_ERROR_RETURN(_bcm_vp_info_get(unit, vp, &vp_info)); 12279 if (vp_info.flags & _BCM_VP_INFO_SHARED_PORT) { 12280 _BCM_MPLS_VPN_GET(vfi, _BCM_VPN_TYPE_VFI, vpn); 12281 soc_mem_field32_set(unit, mem, vent, VFIf, vfi); 12282 } 12283 } 12284 rv = _bcm_tr_mpls_match_vlan_entry_set(unit, mpls_port, vent); 12285 BCM_IF_ERROR_RETURN(rv); 12286 12287 if (!(mpls_info->match_key[vp].flags & _BCM_MPLS_PORT_MATCH_TYPE_SHARE)) { 12288 mpls_info->match_key[vp].flags = _BCM_MPLS_PORT_MATCH_TYPE_VLAN; 12289 mpls_info->match_key[vp].match_vlan = mpls_port->match_vlan; 12290 12291 if (BCM_GPORT_IS_TRUNK(mpls_port->port)) { 12292 mpls_info->match_key[vp].trunk_id = trunk_id; 12293 } else { 12294 mpls_info->match_key[vp].port = port_out; 12295 mpls_info->match_key[vp].modid = mod_out; 12296 } 12297 } 12298 if (!(mpls_port->flags & BCM_MPLS_PORT_REPLACE)) { 12299 bcm_tr_mpls_port_match_count_adjust(unit, vp, 1); 12300 } 12301 } else if (mpls_port->criteria == 12302 BCM_MPLS_PORT_MATCH_PORT_INNER_VLAN) { 12303 12304 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 12305 soc_mem_field32_set(unit, mem, vent, BASE_VALID_0f, 3); 12306 soc_mem_field32_set(unit, mem, vent, BASE_VALID_1f, 7); 12307 soc_mem_field32_set(unit, mem, vent, 12308 DATA_TYPEf, TR_VLXLT_HASH_KEY_TYPE_IVID); 12309 /*set default tag action profile ptr*/ 12310 soc_mem_field32_set(unit, mem, vent, XLATE__TAG_ACTION_PROFILE_PTRf, 1); 12311 } else { 12312 soc_mem_field32_set(unit, mem, vent, VALIDf, 1); 12313 } 12314 soc_mem_field32_set(unit, mem, vent, MPLS_ACTIONf, 0x1); /* SVP */ 12315 soc_mem_field32_set(unit, mem, vent, DISABLE_VLAN_CHECKSf, 1); 12316 soc_mem_field32_set(unit, mem, vent, SOURCE_VPf, vp); 12317 if (!BCM_VLAN_VALID(mpls_port->match_inner_vlan)) { 12318 return BCM_E_PARAM; 12319 } 12320 soc_mem_field32_set(unit, mem, vent, KEY_TYPEf, 12321 TR_VLXLT_HASH_KEY_TYPE_IVID); 12322 soc_mem_field32_set(unit, mem, vent, IVIDf, 12323 mpls_port->match_inner_vlan); 12324 12325 if (BCM_GPORT_IS_TRUNK(mpls_port->port)) { 12326 soc_mem_field32_set(unit, mem, vent, Tf, 1); 12327 soc_mem_field32_set(unit, mem, vent, TGIDf, trunk_id); 12328 } else { 12329 soc_mem_field32_set(unit, mem, vent, MODULE_IDf, mod_out); 12330 soc_mem_field32_set(unit, mem, vent, PORT_NUMf, port_out); 12331 } 12332 if (soc_feature(unit, soc_feature_vp_sharing)) { 12333 BCM_IF_ERROR_RETURN(_bcm_vp_info_get(unit, vp, &vp_info)); 12334 if (vp_info.flags & _BCM_VP_INFO_SHARED_PORT) { 12335 _BCM_MPLS_VPN_GET(vfi, _BCM_VPN_TYPE_VFI, vpn); 12336 soc_mem_field32_set(unit, mem, vent, VFIf, vfi); 12337 } 12338 } 12339 rv = _bcm_tr_mpls_match_vlan_entry_set(unit, mpls_port, vent); 12340 BCM_IF_ERROR_RETURN(rv); 12341 12342 if (!(mpls_info->match_key[vp].flags & _BCM_MPLS_PORT_MATCH_TYPE_SHARE)) { 12343 mpls_info->match_key[vp].flags = _BCM_MPLS_PORT_MATCH_TYPE_INNER_VLAN; 12344 mpls_info->match_key[vp].match_inner_vlan = mpls_port->match_inner_vlan; 12345 12346 if (BCM_GPORT_IS_TRUNK(mpls_port->port)) { 12347 mpls_info->match_key[vp].trunk_id = trunk_id; 12348 } else { 12349 mpls_info->match_key[vp].port = port_out; 12350 mpls_info->match_key[vp].modid = mod_out; 12351 } 12352 } 12353 if (!(mpls_port->flags & BCM_MPLS_PORT_REPLACE)) { 12354 bcm_tr_mpls_port_match_count_adjust(unit, vp, 1); 12355 } 12356 } else if (mpls_port->criteria == 12357 BCM_MPLS_PORT_MATCH_PORT_VLAN_STACKED) { 12358 12359 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 12360 soc_mem_field32_set(unit, mem, vent, BASE_VALID_0f, 3); 12361 soc_mem_field32_set(unit, mem, vent, BASE_VALID_1f, 7); 12362 soc_mem_field32_set(unit, mem, vent, 12363 DATA_TYPEf, TR_VLXLT_HASH_KEY_TYPE_IVID_OVID); 12364 /*set default tag action profile ptr*/ 12365 soc_mem_field32_set(unit, mem, vent, XLATE__TAG_ACTION_PROFILE_PTRf, 1); 12366 } else { 12367 soc_mem_field32_set(unit, mem, vent, VALIDf, 1); 12368 } 12369 soc_mem_field32_set(unit, mem, vent, MPLS_ACTIONf, 0x1); /* SVP */ 12370 soc_mem_field32_set(unit, mem, vent, DISABLE_VLAN_CHECKSf, 1); 12371 soc_mem_field32_set(unit, mem, vent, SOURCE_VPf, vp); 12372 if (!BCM_VLAN_VALID(mpls_port->match_vlan) || 12373 !BCM_VLAN_VALID(mpls_port->match_inner_vlan)) { 12374 return BCM_E_PARAM; 12375 } 12376 soc_mem_field32_set(unit, mem, vent, KEY_TYPEf, 12377 TR_VLXLT_HASH_KEY_TYPE_IVID_OVID); 12378 soc_mem_field32_set(unit, mem, vent, OVIDf, 12379 mpls_port->match_vlan); 12380 soc_mem_field32_set(unit, mem, vent, IVIDf, 12381 mpls_port->match_inner_vlan); 12382 if (BCM_GPORT_IS_TRUNK(mpls_port->port)) { 12383 soc_mem_field32_set(unit, mem, vent, Tf, 1); 12384 soc_mem_field32_set(unit, mem, vent, TGIDf, trunk_id); 12385 } else { 12386 soc_mem_field32_set(unit, mem, vent, MODULE_IDf, mod_out); 12387 soc_mem_field32_set(unit, mem, vent, PORT_NUMf, port_out); 12388 } 12389 if (soc_feature(unit, soc_feature_vp_sharing)) { 12390 BCM_IF_ERROR_RETURN(_bcm_vp_info_get(unit, vp, &vp_info)); 12391 if (vp_info.flags & _BCM_VP_INFO_SHARED_PORT) { 12392 _BCM_MPLS_VPN_GET(vfi, _BCM_VPN_TYPE_VFI, vpn); 12393 soc_mem_field32_set(unit, mem, vent, VFIf, vfi); 12394 } 12395 } 12396 rv = _bcm_tr_mpls_match_vlan_entry_set(unit, mpls_port, vent); 12397 BCM_IF_ERROR_RETURN(rv); 12398 12399 if (!(mpls_info->match_key[vp].flags & _BCM_MPLS_PORT_MATCH_TYPE_SHARE)) { 12400 mpls_info->match_key[vp].flags = _BCM_MPLS_PORT_MATCH_TYPE_VLAN_STACKED; 12401 mpls_info->match_key[vp].match_vlan = mpls_port->match_vlan; 12402 mpls_info->match_key[vp].match_inner_vlan = mpls_port->match_inner_vlan; 12403 if (BCM_GPORT_IS_TRUNK(mpls_port->port)) { 12404 mpls_info->match_key[vp].trunk_id = trunk_id; 12405 } else { 12406 mpls_info->match_key[vp].port = port_out; 12407 mpls_info->match_key[vp].modid = mod_out; 12408 } 12409 } 12410 if (!(mpls_port->flags & BCM_MPLS_PORT_REPLACE)) { 12411 bcm_tr_mpls_port_match_count_adjust(unit, vp, 1); 12412 } 12413 } else if (mpls_port->criteria == BCM_MPLS_PORT_MATCH_VLAN_PRI) { 12414 12415 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 12416 soc_mem_field32_set(unit, mem, vent, BASE_VALID_0f, 3); 12417 soc_mem_field32_set(unit, mem, vent, BASE_VALID_1f, 7); 12418 soc_mem_field32_set(unit, mem, vent, 12419 DATA_TYPEf, TR_VLXLT_HASH_KEY_TYPE_PRI_CFI); 12420 /*set default tag action profile ptr*/ 12421 soc_mem_field32_set(unit, mem, vent, XLATE__TAG_ACTION_PROFILE_PTRf, 1); 12422 } else { 12423 soc_mem_field32_set(unit, mem, vent, VALIDf, 1); 12424 } 12425 soc_mem_field32_set(unit, mem, vent, MPLS_ACTIONf, 0x1); /* SVP */ 12426 soc_mem_field32_set(unit, mem, vent, DISABLE_VLAN_CHECKSf, 1); 12427 soc_mem_field32_set(unit, mem, vent, SOURCE_VPf, vp); 12428 soc_mem_field32_set(unit, mem, vent, KEY_TYPEf, 12429 TR_VLXLT_HASH_KEY_TYPE_PRI_CFI); 12430 /* match_vlan : Bits 12-15 contains VLAN_PRI + CFI, vlan=BCM_E_NONE */ 12431 soc_mem_field32_set(unit, mem, vent, OTAGf, 12432 mpls_port->match_vlan); 12433 if (BCM_GPORT_IS_TRUNK(mpls_port->port)) { 12434 soc_mem_field32_set(unit, mem, vent, Tf, 1); 12435 soc_mem_field32_set(unit, mem, vent, TGIDf, trunk_id); 12436 } else { 12437 soc_mem_field32_set(unit, mem, vent, MODULE_IDf, mod_out); 12438 soc_mem_field32_set(unit, mem, vent, PORT_NUMf, port_out); 12439 } 12440 if (soc_feature(unit, soc_feature_vp_sharing)) { 12441 BCM_IF_ERROR_RETURN(_bcm_vp_info_get(unit, vp, &vp_info)); 12442 if (vp_info.flags & _BCM_VP_INFO_SHARED_PORT) { 12443 _BCM_MPLS_VPN_GET(vfi, _BCM_VPN_TYPE_VFI, vpn); 12444 soc_mem_field32_set(unit, mem, vent, VFIf, vfi); 12445 } 12446 } 12447 #if defined(BCM_TRIUMPH2_SUPPORT) 12448 if (SOC_MEM_FIELD_VALID(unit, SOURCE_VPm, TRUST_OUTER_DOT1Pf)) { 12449 source_vp_entry_t svp; 12450 BCM_IF_ERROR_RETURN(READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp, &svp)); 12451 soc_SOURCE_VPm_field32_set(unit, &svp, TRUST_OUTER_DOT1Pf, 1); 12452 BCM_IF_ERROR_RETURN(WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, vp, &svp)); 12453 } 12454 #endif /* BCM_TRIUMPH2_SUPPORT */ 12455 12456 rv = _bcm_tr_mpls_match_vlan_entry_set(unit, mpls_port, vent); 12457 BCM_IF_ERROR_RETURN(rv); 12458 12459 if (!(mpls_info->match_key[vp].flags & _BCM_MPLS_PORT_MATCH_TYPE_SHARE)) { 12460 mpls_info->match_key[vp].flags = _BCM_MPLS_PORT_MATCH_TYPE_VLAN_PRI; 12461 mpls_info->match_key[vp].match_vlan = mpls_port->match_vlan; 12462 12463 if (BCM_GPORT_IS_TRUNK(mpls_port->port)) { 12464 mpls_info->match_key[vp].trunk_id = trunk_id; 12465 } else { 12466 mpls_info->match_key[vp].port = port_out; 12467 mpls_info->match_key[vp].modid = mod_out; 12468 } 12469 } 12470 if (!(mpls_port->flags & BCM_MPLS_PORT_REPLACE)) { 12471 bcm_tr_mpls_port_match_count_adjust(unit, vp, 1); 12472 } 12473 } else if (mpls_port->criteria == BCM_MPLS_PORT_MATCH_PORT_VLAN_TAG) { 12474 12475 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 12476 soc_mem_field32_set(unit, mem, vent, BASE_VALID_0f, 3); 12477 soc_mem_field32_set(unit, mem, vent, BASE_VALID_1f, 7); 12478 soc_mem_field32_set(unit, mem, vent, 12479 DATA_TYPEf, TR_VLXLT_HASH_KEY_TYPE_OTAG); 12480 /*set default tag action profile ptr*/ 12481 soc_mem_field32_set(unit, mem, vent, XLATE__TAG_ACTION_PROFILE_PTRf, 1); 12482 } else { 12483 soc_mem_field32_set(unit, mem, vent, VALIDf, 1); 12484 } 12485 12486 soc_mem_field32_set(unit, mem, vent, MPLS_ACTIONf, 0x1); /* SVP */ 12487 soc_mem_field32_set(unit, mem, vent, DISABLE_VLAN_CHECKSf, 1); 12488 soc_mem_field32_set(unit, mem, vent, SOURCE_VPf, vp); 12489 12490 soc_mem_field32_set(unit, mem, vent, KEY_TYPEf, 12491 TR_VLXLT_HASH_KEY_TYPE_OTAG); 12492 soc_mem_field32_set(unit, mem, vent, OTAGf, 12493 mpls_port->match_vlan); 12494 12495 if (BCM_GPORT_IS_TRUNK(mpls_port->port)) { 12496 soc_mem_field32_set(unit, mem, vent, Tf, 1); 12497 soc_mem_field32_set(unit, mem, vent, TGIDf, trunk_id); 12498 } else { 12499 soc_mem_field32_set(unit, mem, vent, MODULE_IDf, mod_out); 12500 soc_mem_field32_set(unit, mem, vent, PORT_NUMf, port_out); 12501 } 12502 if (soc_feature(unit, soc_feature_vp_sharing)) { 12503 BCM_IF_ERROR_RETURN(_bcm_vp_info_get(unit, vp, &vp_info)); 12504 if (vp_info.flags & _BCM_VP_INFO_SHARED_PORT) { 12505 _BCM_MPLS_VPN_GET(vfi, _BCM_VPN_TYPE_VFI, vpn); 12506 soc_mem_field32_set(unit, mem, vent, VFIf, vfi); 12507 } 12508 } 12509 12510 #if defined(BCM_TRIUMPH2_SUPPORT) 12511 if (SOC_MEM_FIELD_VALID(unit, SOURCE_VPm, TRUST_OUTER_DOT1Pf)) { 12512 source_vp_entry_t svp; 12513 BCM_IF_ERROR_RETURN(READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp, &svp)); 12514 soc_SOURCE_VPm_field32_set(unit, &svp, TRUST_OUTER_DOT1Pf, 1); 12515 BCM_IF_ERROR_RETURN(WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, vp, &svp)); 12516 } 12517 #endif /* BCM_TRIUMPH2_SUPPORT */ 12518 12519 rv = _bcm_tr_mpls_match_vlan_entry_set(unit, mpls_port, vent); 12520 BCM_IF_ERROR_RETURN(rv); 12521 12522 if (!(mpls_info->match_key[vp].flags & _BCM_MPLS_PORT_MATCH_TYPE_SHARE)) { 12523 mpls_info->match_key[vp].flags = _BCM_MPLS_PORT_MATCH_TYPE_VLAN_TAG; 12524 mpls_info->match_key[vp].match_vlan = mpls_port->match_vlan; 12525 12526 if (BCM_GPORT_IS_TRUNK(mpls_port->port)) { 12527 mpls_info->match_key[vp].trunk_id = trunk_id; 12528 } else { 12529 mpls_info->match_key[vp].port = port_out; 12530 mpls_info->match_key[vp].modid = mod_out; 12531 } 12532 } 12533 if (!(mpls_port->flags & BCM_MPLS_PORT_REPLACE)) { 12534 bcm_tr_mpls_port_match_count_adjust(unit, vp, 1); 12535 } 12536 12537 } else if (mpls_port->criteria == BCM_MPLS_PORT_MATCH_PORT_INNER_VLAN_TAG) { 12538 12539 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 12540 soc_mem_field32_set(unit, mem, vent, BASE_VALID_0f, 3); 12541 soc_mem_field32_set(unit, mem, vent, BASE_VALID_1f, 7); 12542 soc_mem_field32_set(unit, mem, vent, 12543 DATA_TYPEf, TR_VLXLT_HASH_KEY_TYPE_ITAG); 12544 /*set default tag action profile ptr*/ 12545 soc_mem_field32_set(unit, mem, vent, XLATE__TAG_ACTION_PROFILE_PTRf, 1); 12546 } else { 12547 soc_mem_field32_set(unit, mem, vent, VALIDf, 1); 12548 } 12549 soc_mem_field32_set(unit, mem, vent, MPLS_ACTIONf, 0x1); /* SVP */ 12550 soc_mem_field32_set(unit, mem, vent, DISABLE_VLAN_CHECKSf, 1); 12551 soc_mem_field32_set(unit, mem, vent, SOURCE_VPf, vp); 12552 12553 soc_mem_field32_set(unit, mem, vent, KEY_TYPEf, 12554 TR_VLXLT_HASH_KEY_TYPE_ITAG); 12555 soc_mem_field32_set(unit, mem, vent, ITAGf, 12556 mpls_port->match_inner_vlan); 12557 12558 if (BCM_GPORT_IS_TRUNK(mpls_port->port)) { 12559 soc_mem_field32_set(unit, mem, vent, Tf, 1); 12560 soc_mem_field32_set(unit, mem, vent, TGIDf, trunk_id); 12561 } else { 12562 soc_mem_field32_set(unit, mem, vent, MODULE_IDf, mod_out); 12563 soc_mem_field32_set(unit, mem, vent, PORT_NUMf, port_out); 12564 } 12565 if (soc_feature(unit, soc_feature_vp_sharing)) { 12566 BCM_IF_ERROR_RETURN(_bcm_vp_info_get(unit, vp, &vp_info)); 12567 if (vp_info.flags & _BCM_VP_INFO_SHARED_PORT) { 12568 _BCM_MPLS_VPN_GET(vfi, _BCM_VPN_TYPE_VFI, vpn); 12569 soc_mem_field32_set(unit, mem, vent, VFIf, vfi); 12570 } 12571 } 12572 rv = _bcm_tr_mpls_match_vlan_entry_set(unit, mpls_port, vent); 12573 BCM_IF_ERROR_RETURN(rv); 12574 12575 if (!(mpls_info->match_key[vp].flags & _BCM_MPLS_PORT_MATCH_TYPE_SHARE)) { 12576 mpls_info->match_key[vp].flags = _BCM_MPLS_PORT_MATCH_TYPE_INNER_VLAN_TAG; 12577 mpls_info->match_key[vp].match_inner_vlan = mpls_port->match_inner_vlan; 12578 12579 if (BCM_GPORT_IS_TRUNK(mpls_port->port)) { 12580 mpls_info->match_key[vp].trunk_id = trunk_id; 12581 } else { 12582 mpls_info->match_key[vp].port = port_out; 12583 mpls_info->match_key[vp].modid = mod_out; 12584 } 12585 } 12586 if (!(mpls_port->flags & BCM_MPLS_PORT_REPLACE)) { 12587 bcm_tr_mpls_port_match_count_adjust(unit, vp, 1); 12588 } 12589 } else if (mpls_port->criteria == BCM_MPLS_PORT_MATCH_PORT) { 12590 12591 if (BCM_GPORT_IS_TRUNK(mpls_port->port)) { 12592 #ifdef BCM_TOMAHAWK_SUPPORT 12593 if (SOC_IS_TOMAHAWKX(unit)) { 12594 if (!(mpls_port->flags & BCM_MPLS_PORT_REPLACE) || 12595 ((mpls_info->match_key[vp].port != port_out) || 12596 (mpls_info->match_key[vp].modid != mod_out) || 12597 ((mpls_info->match_key[vp].flags & _BCM_MPLS_PORT_MATCH_TYPE_TRUNK) && 12598 (mpls_info->match_key[vp].trunk_id != trunk_id)))) { 12599 rv = bcm_tr_mpls_match_trunk_add(unit, trunk_id, vp); 12600 } 12601 } else 12602 #endif 12603 { 12604 rv = bcm_tr_mpls_match_trunk_add(unit, trunk_id, vp); 12605 } 12606 if (rv >= 0) { 12607 if (!(mpls_info->match_key[vp].flags & 12608 _BCM_MPLS_PORT_MATCH_TYPE_SHARE)) { 12609 /* Delete references associated with old port in mpls_port */ 12610 if (mpls_port->flags & BCM_MPLS_PORT_REPLACE) { 12611 if ((mpls_info->match_key[vp].port != port_out) || 12612 (mpls_info->match_key[vp].modid != mod_out) || 12613 ((mpls_info->match_key[vp].flags & 12614 _BCM_MPLS_PORT_MATCH_TYPE_TRUNK) && 12615 (mpls_info->match_key[vp].trunk_id != trunk_id))) { 12616 BCM_IF_ERROR_RETURN(_bcm_tr_mpls_match_delete(unit, vp, NULL, TRUE)); 12617 } 12618 } 12619 mpls_info->match_key[vp].flags = _BCM_MPLS_PORT_MATCH_TYPE_TRUNK; 12620 mpls_info->match_key[vp].trunk_id = trunk_id; 12621 mpls_info->trunk_vp_map[trunk_id] = vp; 12622 mpls_info->match_key[vp].port = port_out; 12623 mpls_info->match_key[vp].modid = mod_out; 12624 } 12625 } 12626 BCM_IF_ERROR_RETURN(rv); 12627 } else { 12628 int is_local; 12629 12630 BCM_IF_ERROR_RETURN 12631 ( _bcm_esw_modid_is_local(unit, mod_out, &is_local)); 12632 12633 /* Get index to source trunk map table */ 12634 BCM_IF_ERROR_RETURN( 12635 _bcm_esw_src_mod_port_table_index_get(unit, mod_out, 12636 port_out, &src_trk_idx)); 12637 12638 rv = soc_mem_field32_modify(unit, SOURCE_TRUNK_MAP_TABLEm, 12639 src_trk_idx, SOURCE_VPf, vp); 12640 BCM_IF_ERROR_RETURN(rv); 12641 if (SOC_MEM_FIELD_VALID(unit,SOURCE_TRUNK_MAP_TABLEm,SVP_VALIDf)) { 12642 rv = soc_mem_field32_modify(unit, SOURCE_TRUNK_MAP_TABLEm, 12643 src_trk_idx, SVP_VALIDf, 1); 12644 BCM_IF_ERROR_RETURN(rv); 12645 } 12646 12647 #if defined(BCM_HGPROXY_COE_SUPPORT) 12648 if (soc_feature(unit, soc_feature_hgproxy_subtag_coe) && 12649 BCM_GPORT_IS_SET(mpls_port->port) && 12650 _BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, 12651 mpls_port->port)) { 12652 local_port = mpls_port->port; 12653 is_local_subport = 1; 12654 } else 12655 #endif 12656 12657 #if defined(BCM_KATANA2_SUPPORT) 12658 if (BCM_GPORT_IS_SET(mpls_port->port) && 12659 _BCM_KT2_GPORT_IS_LINKPHY_OR_SUBTAG_SUBPORT_GPORT(unit, 12660 mpls_port->port)) { 12661 BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &my_modid)); 12662 if (_bcm_kt2_mod_is_coe_mod_check(unit, mod_out) == BCM_E_NONE) { 12663 BCM_IF_ERROR_RETURN(_bcm_kt2_modport_to_pp_port_get( 12664 unit, mod_out, port_out, &local_port)); 12665 if (_bcm_kt2_is_pp_port_linkphy_subtag(unit, local_port)){ 12666 is_local_subport = 1; 12667 } 12668 } 12669 } 12670 #endif 12671 12672 #if defined(BCM_HGPROXY_COE_SUPPORT) || defined(BCM_KATANA2_SUPPORT) 12673 if (is_local_subport) { 12674 12675 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 12676 rv = _bcm_esw_port_tab_set(unit, local_port, 12677 _BCM_CPU_TABS_BOTH, 12678 PORT_OPERATIONf, 0x1); 12679 } else { 12680 rv = _bcm_esw_port_tab_set_without_portlock( 12681 unit, local_port, _BCM_CPU_TABS_NONE, PORT_OPERATIONf, 12682 0x1); /* L2_SVP */ 12683 } 12684 BCM_IF_ERROR_RETURN(rv); 12685 12686 /* Set TAG_ACTION_PROFILE_PTR */ 12687 rv = bcm_tr_mpls_port_untagged_profile_set(unit, local_port); 12688 BCM_IF_ERROR_RETURN(rv); 12689 } else 12690 #endif 12691 if (is_local) { 12692 /* Convert system ports to physical ports */ 12693 if (soc_feature(unit, soc_feature_sysport_remap)) { 12694 BCM_XLATE_SYSPORT_S2P(unit, &port_out); 12695 } 12696 12697 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 12698 rv = _bcm_esw_port_tab_set(unit, port_out, 12699 _BCM_CPU_TABS_BOTH, 12700 PORT_OPERATIONf, 0x1); 12701 } else { 12702 rv = soc_mem_field32_modify(unit, PORT_TABm, port_out, 12703 PORT_OPERATIONf, 0x1); /* L2_SVP */ 12704 } 12705 BCM_IF_ERROR_RETURN(rv); 12706 12707 #ifdef BCM_TOMAHAWK_SUPPORT 12708 if (SOC_IS_TOMAHAWKX(unit)) { 12709 if (!(mpls_port->flags & BCM_MPLS_PORT_REPLACE) || 12710 ((mpls_info->match_key[vp].port != port_out) || 12711 (mpls_info->match_key[vp].modid != mod_out) || 12712 ((mpls_info->match_key[vp].flags & _BCM_MPLS_PORT_MATCH_TYPE_TRUNK) && 12713 (mpls_info->match_key[vp].trunk_id != trunk_id)))) { 12714 rv = bcm_tr_mpls_port_untagged_profile_set(unit, port_out); 12715 BCM_IF_ERROR_RETURN(rv); 12716 } 12717 } else 12718 #endif 12719 { 12720 /* Set TAG_ACTION_PROFILE_PTR */ 12721 rv = bcm_tr_mpls_port_untagged_profile_set(unit, port_out); 12722 BCM_IF_ERROR_RETURN(rv); 12723 } 12724 } 12725 12726 /* Delete references associated with old port in mpls_port */ 12727 if (mpls_port->flags & BCM_MPLS_PORT_REPLACE) { 12728 if ((mpls_info->match_key[vp].port != port_out) || 12729 (mpls_info->match_key[vp].modid != mod_out) || 12730 ((mpls_info->match_key[vp].flags & 12731 _BCM_MPLS_PORT_MATCH_TYPE_TRUNK) && 12732 (mpls_info->match_key[vp].trunk_id != trunk_id))) { 12733 BCM_IF_ERROR_RETURN(_bcm_tr_mpls_match_delete(unit, vp, NULL, TRUE)); 12734 } 12735 } 12736 /* 12737 * The vp has been created based on trunk. 12738 * When a new port is added into the trunk, a match will be 12739 * added for the vp through bcm_port_match_add. 12740 */ 12741 if ((mpls_info->match_key[vp].flags != _BCM_MPLS_PORT_MATCH_TYPE_TRUNK) && 12742 (!(mpls_info->match_key[vp].flags & _BCM_MPLS_PORT_MATCH_TYPE_SHARE))) { 12743 mpls_info->match_key[vp].flags = _BCM_MPLS_PORT_MATCH_TYPE_PORT; 12744 mpls_info->match_key[vp].index = src_trk_idx; 12745 mpls_info->match_key[vp].port = port_out; 12746 mpls_info->match_key[vp].modid = mod_out; 12747 } 12748 } 12749 } else if ((mpls_port->criteria == BCM_MPLS_PORT_MATCH_LABEL) || 12750 (mpls_port->criteria == BCM_MPLS_PORT_MATCH_LABEL_PORT)) { 12751 12752 mpls_entry_entry_t ment, return_ment; 12753 int old_pw_term_cntr_idx=-1, new_pw_term_cntr_idx=-1; 12754 int entry_index=-1; 12755 int old_mpls_entry_rv = BCM_E_NONE; 12756 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) 12757 uint32 flex_ctr_poolnum=0; 12758 uint32 flex_ctr_basectr_idx=0; 12759 uint32 flex_ctr_offset_mode=0; 12760 #endif 12761 #ifdef BCM_TRIUMPH2_SUPPORT 12762 int old_vintf_cntr_idx = -1; 12763 #endif 12764 12765 12766 sal_memset(&ment, 0, sizeof(mpls_entry_entry_t)); 12767 if (mpls_port->criteria == BCM_MPLS_PORT_MATCH_LABEL_PORT) { 12768 /* Check for Port_independent Label mapping */ 12769 rv = bcm_tr_mpls_port_independent_range (unit, mpls_port->match_label, mpls_port->port); 12770 if (rv < 0) { 12771 return rv; 12772 } 12773 if (BCM_GPORT_IS_TRUNK(mpls_port->port)) { 12774 soc_MPLS_ENTRYm_field32_set(unit, &ment, Tf, 1); 12775 soc_MPLS_ENTRYm_field32_set(unit, &ment, TGIDf, trunk_id); 12776 if (vpless_failover_port == FALSE) { 12777 mpls_info->match_key[vp].trunk_id = trunk_id; 12778 } else { 12779 mpls_info->match_key[vp].fo_trunk_id = trunk_id; 12780 } 12781 } else { 12782 soc_MPLS_ENTRYm_field32_set(unit, &ment, MODULE_IDf, mod_out); 12783 soc_MPLS_ENTRYm_field32_set(unit, &ment, PORT_NUMf, port_out); 12784 if (vpless_failover_port == FALSE) { 12785 mpls_info->match_key[vp].port = port_out; 12786 mpls_info->match_key[vp].modid = mod_out; 12787 } else { 12788 mpls_info->match_key[vp].fo_port = port_out; 12789 mpls_info->match_key[vp].fo_modid = mod_out; 12790 } 12791 } 12792 mpls_info->match_key[vp].flags = _BCM_MPLS_PORT_MATCH_TYPE_LABEL_PORT; 12793 } else if (mpls_port->criteria == BCM_MPLS_PORT_MATCH_LABEL) { 12794 soc_MPLS_ENTRYm_field32_set(unit, &ment, MODULE_IDf, 0); 12795 soc_MPLS_ENTRYm_field32_set(unit, &ment, PORT_NUMf, 0); 12796 mpls_info->match_key[vp].port = 0; 12797 mpls_info->match_key[vp].modid = 0; 12798 mpls_info->match_key[vp].flags = _BCM_MPLS_PORT_MATCH_TYPE_LABEL; 12799 } 12800 /* Use old label to get old mpls entry for replace operation */ 12801 old_match_label = mpls_info->match_key[vp].match_label; 12802 soc_MPLS_ENTRYm_field32_set(unit, &ment, MPLS_LABELf, 12803 old_match_label); 12804 12805 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 12806 soc_MPLS_ENTRYm_field32_set(unit, &ment, BASE_VALID_0f, 3); 12807 soc_MPLS_ENTRYm_field32_set(unit, &ment, BASE_VALID_1f, 7); 12808 } else { 12809 soc_MPLS_ENTRYm_field32_set(unit, &ment, VALIDf, 1); 12810 } 12811 soc_MPLS_ENTRYm_field32_set(unit, &ment, SOURCE_VPf, vp); 12812 soc_MPLS_ENTRYm_field32_set(unit, &ment, MPLS_ACTION_IF_BOSf, 12813 0x1); /* L2 SVP */ 12814 soc_MPLS_ENTRYm_field32_set(unit, &ment, MPLS_ACTION_IF_NOT_BOSf, 12815 0x0); /* INVALID */ 12816 12817 if (mpls_port->flags & BCM_MPLS_PORT_REPLACE) { 12818 /* Find Entry within Hardware */ 12819 old_mpls_entry_rv = soc_mem_search(unit, MPLS_ENTRYm, 12820 MEM_BLOCK_ANY, &entry_index, 12821 &ment, &return_ment, 0); 12822 12823 /* Obtain old pw_term counter-index and old label flex stat index */ 12824 if (BCM_SUCCESS(old_mpls_entry_rv)) { 12825 if (soc_MPLS_ENTRYm_field32_get(unit, &return_ment, 12826 PW_TERM_NUM_VALIDf)) { 12827 old_pw_term_cntr_idx = soc_MPLS_ENTRYm_field32_get(unit, 12828 &return_ment,PW_TERM_NUMf); 12829 } 12830 #ifdef BCM_TRIUMPH2_SUPPORT 12831 if (soc_feature(unit, soc_feature_gport_service_counters)) { 12832 if (soc_MPLS_ENTRYm_field32_get(unit, &return_ment, 12833 USE_VINTF_CTR_IDXf)) { 12834 old_vintf_cntr_idx = soc_MPLS_ENTRYm_field32_get(unit, 12835 &return_ment, VINTF_CTR_IDXf); 12836 } 12837 } 12838 #endif /* BCM_TRIUMPH2_SUPPORT */ 12839 12840 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) 12841 if ((soc_feature(unit, soc_feature_mpls_enhanced)) && 12842 (soc_feature(unit,soc_feature_advanced_flex_counter))) { 12843 /* Store Flex counter values */ 12844 flex_ctr_poolnum = soc_MPLS_ENTRYm_field32_get(unit, 12845 &return_ment, 12846 MPLS__FLEX_CTR_POOL_NUMBERf); 12847 if(flex_ctr_poolnum) { 12848 soc_MPLS_ENTRYm_field32_set(unit, &ment, 12849 MPLS__FLEX_CTR_POOL_NUMBERf, 12850 flex_ctr_poolnum); 12851 } 12852 flex_ctr_basectr_idx = soc_MPLS_ENTRYm_field32_get(unit, 12853 &return_ment, 12854 MPLS__FLEX_CTR_BASE_COUNTER_IDXf); 12855 if(flex_ctr_basectr_idx) { 12856 soc_MPLS_ENTRYm_field32_set(unit, &ment, 12857 MPLS__FLEX_CTR_BASE_COUNTER_IDXf, 12858 flex_ctr_basectr_idx); 12859 } 12860 flex_ctr_offset_mode = soc_MPLS_ENTRYm_field32_get(unit, 12861 &return_ment, 12862 MPLS__FLEX_CTR_OFFSET_MODEf); 12863 soc_MPLS_ENTRYm_field32_set(unit, &ment, 12864 MPLS__FLEX_CTR_OFFSET_MODEf, 12865 flex_ctr_offset_mode); 12866 } 12867 #endif /* (BCM_KATANA_SUPPORT) || (BCM_TRIUMPH3_SUPPORT) */ 12868 12869 #if defined(BCM_TRIDENT2_SUPPORT) 12870 if (soc_feature(unit, soc_feature_vp_lag)) { 12871 int svp = soc_MPLS_ENTRYm_field32_get(unit, &return_ment, SOURCE_VPf); 12872 if (_bcm_vp_used_get(unit, svp, _bcmVpTypeVpLag)) { 12873 soc_MPLS_ENTRYm_field32_set(unit, &ment, SOURCE_VPf, svp); 12874 } 12875 } 12876 #endif 12877 } 12878 } 12879 12880 /* Add the new MPLS label for the new entry*/ 12881 soc_MPLS_ENTRYm_field32_set(unit, &ment, MPLS_LABELf, 12882 mpls_port->match_label); 12883 12884 if (mpls_port->flags & BCM_MPLS_PORT_SEQUENCED) { 12885 /* Control word is present, check sequence number */ 12886 soc_MPLS_ENTRYm_field32_set(unit, &ment, CW_CHECK_CTRLf, 12887 0x3); /* CW_CHECK_LOOSE */ 12888 12889 12890 } else if (mpls_port->flags & BCM_MPLS_PORT_CONTROL_WORD) { 12891 /* Control word is present, but no sequence number check */ 12892 soc_MPLS_ENTRYm_field32_set(unit, &ment, CW_CHECK_CTRLf, 12893 0x1); /* CW_NO_CHECK */ 12894 } 12895 if (((mpls_port->flags & BCM_MPLS_PORT_COUNTED) || 12896 (mpls_port->flags & BCM_MPLS_PORT_SEQUENCED))) { 12897 /* Obtain pw_term_counter */ 12898 BCM_IF_ERROR_RETURN( 12899 _bcm_tr_mpls_pw_term_counter_set (unit, &new_pw_term_cntr_idx)); 12900 if ( new_pw_term_cntr_idx != -1) { 12901 soc_MPLS_ENTRYm_field32_set(unit, &ment, PW_TERM_NUMf, new_pw_term_cntr_idx); 12902 soc_MPLS_ENTRYm_field32_set(unit, &ment, PW_TERM_NUM_VALIDf, 1); 12903 } 12904 } 12905 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 12906 else if (SOC_MEM_FIELD_VALID(unit, MPLS_ENTRYm, CLASS_IDf)) { 12907 soc_MPLS_ENTRYm_field32_set(unit, &ment, CLASS_IDf, mpls_port->class_id); 12908 } 12909 #endif 12910 #if defined(BCM_TRIDENT2PLUS_SUPPORT) || defined(BCM_SABER2_SUPPORT) 12911 if (soc_mem_field_valid(unit, MPLS_ENTRYm, PW_CC_TYPEf)) { 12912 if (mpls_port->vccv_type == bcmMplsPortControlChannelGalUnderPw) { 12913 soc_MPLS_ENTRYm_field32_set(unit, &ment, 12914 MPLS_ACTION_IF_NOT_BOSf, 0x1); 12915 } 12916 } 12917 #endif 12918 12919 (void) bcm_tr_mpls_entry_internal_qos_set(unit, mpls_port, NULL, &ment); 12920 12921 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIDENT2_SUPPORT) 12922 if (soc_feature(unit, soc_feature_mpls_entropy)) { 12923 if ((mpls_port->flags & BCM_MPLS_PORT_ENTROPY_ENABLE) || 12924 (mpls_port->flags2 & BCM_MPLS_PORT2_INGRESS_ENTROPY_ENABLE)) { 12925 if (soc_mem_field_valid(unit, MPLS_ENTRYm, 12926 ENTROPY_LABEL_PRESENTf)) { 12927 soc_MPLS_ENTRYm_field32_set(unit, &ment, 12928 ENTROPY_LABEL_PRESENTf, 0x1); 12929 soc_MPLS_ENTRYm_field32_set(unit, &ment, MPLS_ACTION_IF_BOSf, 12930 0x0); /* INVALID */ 12931 12932 if (SOC_IS_APACHE(unit)) { 12933 soc_MPLS_ENTRYm_field32_set(unit, &ment, MPLS_ACTION_IF_NOT_BOSf, 12934 0x6); /* POP_SVP_ENTROPY */ 12935 } else { 12936 soc_MPLS_ENTRYm_field32_set(unit, &ment, MPLS_ACTION_IF_NOT_BOSf, 12937 0x4); /* POP_SVP_ENTROPY */ 12938 } 12939 } 12940 } 12941 } 12942 12943 /* VCCV defines 3 control-channels */ 12944 if (soc_mem_field_valid(unit, MPLS_ENTRYm, PW_CC_TYPEf)) { 12945 soc_MPLS_ENTRYm_field32_set(unit, &ment, PW_CC_TYPEf, 12946 mpls_port->vccv_type); 12947 } 12948 #endif /* defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIDENT2PLUS_SUPPORT) */ 12949 12950 #ifdef BCM_TRIUMPH2_SUPPORT 12951 if (soc_feature(unit, soc_feature_gport_service_counters)) { 12952 if ((mpls_port->flags & BCM_MPLS_PORT_REPLACE) && 12953 (old_vintf_cntr_idx != -1)) { 12954 if (old_match_label != mpls_port->match_label) { 12955 /* If MPLS label stat is used for this MPLS_ENTRY then 12956 * it must be released first using stat_detach*/ 12957 LOG_ERROR(BSL_LS_BCM_MPLS, 12958 (BSL_META_U(unit, 12959 "The flex stat counter %d for the " 12960 "old label %d must be detached first\n before performing " 12961 "the MPLS label replace action.\n"), 12962 old_vintf_cntr_idx, old_match_label)); 12963 return BCM_E_INTERNAL; 12964 } else { 12965 /* copy the old label flex sat counter index if old_label == new_label*/ 12966 soc_MPLS_ENTRYm_field32_set(unit, &ment, 12967 USE_VINTF_CTR_IDXf, 1); 12968 soc_MPLS_ENTRYm_field32_set(unit, &ment, VINTF_CTR_IDXf, 12969 old_vintf_cntr_idx); 12970 } 12971 } 12972 } 12973 #endif /* BCM_TRIUMPH2_SUPPORT */ 12974 #if defined(BCM_TOMAHAWK2_SUPPORT) || defined(BCM_TRIDENT3_SUPPORT) 12975 if (soc_feature(unit, soc_feature_mpls_ecn)) { 12976 if (mpls_port->flags2 & BCM_MPLS_PORT2_INGRESS_ECN_MAP) { 12977 int ecn_map_index; 12978 int ecn_map_hw_idx; 12979 int ecn_map_type; 12980 int ecn_map_num; 12981 12982 ecn_map_type = mpls_port->ecn_map_id & 12983 _BCM_XGS5_MPLS_ECN_MAP_TYPE_MASK; 12984 ecn_map_index = mpls_port->ecn_map_id & 12985 _BCM_XGS5_MPLS_ECN_MAP_NUM_MASK; 12986 #if defined(BCM_TRIDENT3_SUPPORT) 12987 if(soc_feature(unit, soc_feature_td3_style_mpls)) { 12988 mem = ING_EXP_TO_ECN_MAPPING_1m; 12989 } else 12990 #endif 12991 { 12992 mem = ING_EXP_TO_IP_ECN_MAPPINGm; 12993 } 12994 12995 ecn_map_num = 12996 soc_mem_index_count(unit, mem) / 12997 _BCM_ECN_MAX_ENTRIES_PER_MAP; 12998 if (ecn_map_type != _BCM_XGS5_MPLS_ECN_MAP_TYPE_EXP2ECN) { 12999 return BCM_E_PARAM; 13000 } 13001 if (ecn_map_index >= ecn_map_num) { 13002 return BCM_E_PARAM; 13003 } 13004 if (!bcmi_xgs5_ecn_map_used_get(unit, ecn_map_index, 13005 _bcmEcnmapTypeExp2Ecn)) { 13006 return BCM_E_PARAM; 13007 } 13008 BCM_IF_ERROR_RETURN( 13009 bcmi_ecn_map_id2hw_idx(unit, mpls_port->ecn_map_id, &ecn_map_hw_idx)); 13010 13011 #if defined(BCM_TRIDENT3_SUPPORT) 13012 if(soc_feature(unit, soc_feature_td3_style_mpls)) { 13013 soc_MPLS_ENTRYm_field32_set(unit, &ment, 13014 EXP_TO_ECN_MAPPING_PTRf, 13015 ecn_map_hw_idx); 13016 } else 13017 #endif 13018 { 13019 soc_MPLS_ENTRYm_field32_set(unit, &ment, 13020 EXP_TO_IP_ECN_MAPPING_PTRf, 13021 ecn_map_hw_idx); 13022 } 13023 } 13024 } 13025 #endif /* BCM_TOMAHAWK2_SUPPORT */ 13026 13027 13028 if (soc_mem_field_valid(unit, MPLS_ENTRYm, DO_NOT_CHANGE_PAYLOAD_DSCPf)) { 13029 if (_BCM_MPLS_VPN_IS_VPLS(vpn) || _BCM_MPLS_VPN_IS_VPWS(vpn)) { 13030 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 13031 soc_MPLS_ENTRYm_field32_set(unit, &ment, 13032 DO_NOT_CHANGE_PAYLOAD_DSCPf, 0); 13033 } else { 13034 soc_MPLS_ENTRYm_field32_set(unit, &ment, 13035 DO_NOT_CHANGE_PAYLOAD_DSCPf, 1); 13036 } 13037 } 13038 } 13039 13040 /* Add the new MPLS entry */ 13041 if (hw_update) { 13042 rv = _bcm_tr_mpls_match_label_entry_set(unit, mpls_port, &ment); 13043 } 13044 13045 /* update the new label in match key of the VP*/ 13046 if (BCM_SUCCESS(rv)) { 13047 mpls_info->match_key[vp].match_label = mpls_port->match_label; 13048 } 13049 13050 /* Delete the old MPLS entry */ 13051 if (BCM_SUCCESS(rv) && (mpls_port->flags & BCM_MPLS_PORT_REPLACE)) { 13052 int failover_vp = -1; 13053 bcm_mpls_label_t failover_match_label = -1; 13054 13055 failover_vp = BCM_GPORT_MPLS_PORT_ID_GET(mpls_port->failover_port_id); 13056 if ((failover_vp >= 0) && 13057 _bcm_vp_used_get(unit, failover_vp, _bcmVpTypeMpls)) { 13058 failover_match_label = mpls_info->match_key[failover_vp].match_label; 13059 } 13060 13061 if ((old_pw_term_cntr_idx != -1) && 13062 (new_pw_term_cntr_idx != old_pw_term_cntr_idx)) { 13063 /* Delete old pw_term counter associated with old mpls label */ 13064 (void) _bcm_tr_mpls_pw_term_counter_delete (unit, 13065 old_pw_term_cntr_idx); 13066 } 13067 /* 13068 * When replace match criteria of primary port, old match entry keeps 13069 * unchanged if 1: new match info is same as old one; 2: backup port 13070 * has the same match info. 13071 */ 13072 if ((old_mpls_entry_rv == BCM_E_NONE) 13073 && (old_match_label != mpls_port->match_label)){ 13074 if ((failover_match_label != -1) && (old_match_label == failover_match_label)) { 13075 soc_MPLS_ENTRYm_field32_set(unit, &return_ment, SOURCE_VPf, failover_vp); 13076 BCM_IF_ERROR_RETURN(soc_mem_write(unit, MPLS_ENTRYm, 13077 MEM_BLOCK_ALL, entry_index, 13078 &return_ment)); 13079 } else { 13080 BCM_IF_ERROR_RETURN(soc_mem_delete(unit, MPLS_ENTRYm, 13081 MEM_BLOCK_ANY, &return_ment)); 13082 } 13083 } 13084 } 13085 } else if (mpls_port->criteria == BCM_MPLS_PORT_MATCH_NONE) { 13086 (void) bcm_tr_mpls_match_clear (unit, vp); 13087 mpls_info->match_key[vp].flags = _BCM_MPLS_PORT_MATCH_TYPE_NONE; 13088 if (!(mpls_port->flags & BCM_MPLS_PORT_REPLACE)) { 13089 bcm_tr_mpls_port_match_count_adjust(unit, vp, 1); 13090 } 13091 } 13092 #if defined(BCM_KATANA2_SUPPORT) 13093 else if ((mpls_port->criteria == BCM_MPLS_PORT_MATCH_PORT_SUBPORT_PKT_VID) || 13094 (mpls_port->criteria == BCM_MPLS_PORT_MATCH_PORT_SUBPORT_PKT_VID_INNER_VLAN) || 13095 (mpls_port->criteria == BCM_MPLS_PORT_MATCH_PORT_SUBPORT_PKT_VID_OUTER_VLAN)) { 13096 13097 int is_local = 0; 13098 13099 BCM_IF_ERROR_RETURN 13100 (_bcm_esw_modid_is_local(unit, mod_out, &is_local)); 13101 13102 if (is_local) { 13103 /* Convert system ports to physical ports */ 13104 if (soc_feature(unit, soc_feature_sysport_remap)) { 13105 BCM_XLATE_SYSPORT_S2P(unit, &port_out); 13106 } 13107 /*TD3:VT_PORT_TYPE_SELECT_1f*/ 13108 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 13109 rv = _bcm_esw_port_tab_set(unit, port_out, 13110 _BCM_CPU_TABS_BOTH, 13111 VT_PORT_TYPE_SELECT_1f, 1); 13112 } else { 13113 rv = soc_mem_field32_modify(unit, PORT_TABm, port_out, 13114 VT_PORT_TYPE_SELECTf, 1);/*default*/ 13115 } 13116 BCM_IF_ERROR_RETURN(rv); 13117 } 13118 13119 if (!soc_feature(unit, soc_feature_lltag)) { 13120 return BCM_E_UNAVAIL; 13121 } 13122 13123 soc_mem_field32_set(unit, mem, vent, VALIDf, 0x1); 13124 soc_mem_field32_set(unit, mem, vent, LLTAG__MPLS_ACTIONf, 0x1); /* SVP */ 13125 soc_mem_field32_set(unit, mem, vent, LLTAG__DISABLE_VLAN_CHECKSf, 1); 13126 soc_mem_field32_set(unit, mem, vent, LLTAG__SOURCE_VPf, vp); 13127 if (!BCM_VLAN_VALID(mpls_port->match_subport_pkt_vid)) { 13128 return BCM_E_PARAM; 13129 } 13130 13131 if (mpls_port->criteria == BCM_MPLS_PORT_MATCH_PORT_SUBPORT_PKT_VID) { 13132 soc_mem_field32_set(unit, mem, vent, KEY_TYPEf, 13133 KT2_PT_XLT_KEY_TYPE_LLVID); 13134 } else if (mpls_port->criteria == 13135 BCM_MPLS_PORT_MATCH_PORT_SUBPORT_PKT_VID_INNER_VLAN) { 13136 soc_mem_field32_set(unit, mem, vent, KEY_TYPEf, 13137 KT2_PT_XLT_KEY_TYPE_LLVID_IVID); 13138 soc_mem_field32_set(unit, mem, vent, LLTAG__IVIDf, 13139 mpls_port->match_inner_vlan); 13140 } else { 13141 soc_mem_field32_set(unit, mem, vent, KEY_TYPEf, 13142 KT2_PT_XLT_KEY_TYPE_LLVID_OVID); 13143 soc_mem_field32_set(unit, mem, vent, LLTAG__OVIDf, 13144 mpls_port->match_vlan); 13145 } 13146 13147 soc_mem_field32_set(unit, mem, vent, LLTAG__LLVIDf, 13148 mpls_port->match_subport_pkt_vid); 13149 13150 if (BCM_GPORT_IS_TRUNK(mpls_port->port)) { 13151 soc_mem_field32_set(unit, mem, vent, LLTAG__Tf, 1); 13152 soc_mem_field32_set(unit, mem, vent, LLTAG__TGIDf, trunk_id); 13153 mpls_info->match_key[vp].trunk_id = trunk_id; 13154 } else { 13155 soc_mem_field32_set(unit, mem, vent, LLTAG__MODULE_IDf, mod_out); 13156 soc_mem_field32_set(unit, mem, vent, LLTAG__PORT_NUMf, port_out); 13157 mpls_info->match_key[vp].port = port_out; 13158 mpls_info->match_key[vp].modid = mod_out; 13159 } 13160 rv = _bcm_tr_mpls_match_vlan_entry_set(unit, mpls_port, vent); 13161 BCM_IF_ERROR_RETURN(rv); 13162 /*Update S/W information only after match entry set successfully*/ 13163 if (mpls_port->criteria == BCM_MPLS_PORT_MATCH_PORT_SUBPORT_PKT_VID) { 13164 if (is_local) { 13165 13166 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 13167 rv = _bcm_esw_port_tab_set(unit, port_out, 13168 _BCM_CPU_TABS_BOTH, 13169 VT_KEY_TYPEf, KT2_PT_XLT_KEY_TYPE_LLVID); 13170 } else { 13171 rv = soc_mem_field32_modify(unit, PORT_TABm, port_out, 13172 VT_KEY_TYPEf, KT2_PT_XLT_KEY_TYPE_LLVID); 13173 } 13174 BCM_IF_ERROR_RETURN(rv); 13175 } 13176 mpls_info->match_key[vp].flags = _BCM_MPLS_PORT_MATCH_TYPE_PORT_SUBPORT_PKT_VID; 13177 } else if (mpls_port->criteria == 13178 BCM_MPLS_PORT_MATCH_PORT_SUBPORT_PKT_VID_INNER_VLAN) { 13179 if (is_local) { 13180 13181 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 13182 rv = _bcm_esw_port_tab_set(unit, port_out, 13183 _BCM_CPU_TABS_BOTH, 13184 VT_KEY_TYPEf, KT2_PT_XLT_KEY_TYPE_LLVID_IVID); 13185 } else { 13186 rv = soc_mem_field32_modify(unit, PORT_TABm, port_out, 13187 VT_KEY_TYPEf, KT2_PT_XLT_KEY_TYPE_LLVID_IVID); 13188 } 13189 BCM_IF_ERROR_RETURN(rv); 13190 } 13191 mpls_info->match_key[vp].flags = 13192 _BCM_MPLS_PORT_MATCH_TYPE_PORT_SUBPORT_PKT_VID_INNER_VLAN; 13193 mpls_info->match_key[vp].match_inner_vlan = mpls_port->match_inner_vlan; 13194 } else { 13195 if (is_local) { 13196 13197 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 13198 rv = _bcm_esw_port_tab_set(unit, port_out, 13199 _BCM_CPU_TABS_BOTH, 13200 VT_KEY_TYPEf, KT2_PT_XLT_KEY_TYPE_LLVID_OVID); 13201 } else { 13202 rv = soc_mem_field32_modify(unit, PORT_TABm, port_out, 13203 VT_KEY_TYPEf, KT2_PT_XLT_KEY_TYPE_LLVID_OVID); 13204 } 13205 BCM_IF_ERROR_RETURN(rv); 13206 } 13207 mpls_info->match_key[vp].flags = 13208 _BCM_MPLS_PORT_MATCH_TYPE_PORT_SUBPORT_PKT_VID_OUTER_VLAN; 13209 mpls_info->match_key[vp].match_vlan = mpls_port->match_vlan; 13210 } 13211 13212 mpls_info->match_key[vp].match_subport_pkt_vid = mpls_port->match_subport_pkt_vid; 13213 if (BCM_GPORT_IS_TRUNK(mpls_port->port)) { 13214 mpls_info->match_key[vp].trunk_id = trunk_id; 13215 } else { 13216 mpls_info->match_key[vp].port = port_out; 13217 mpls_info->match_key[vp].modid = mod_out; 13218 } 13219 13220 if (!(mpls_port->flags & BCM_MPLS_PORT_REPLACE)) { 13221 bcm_tr_mpls_port_match_count_adjust(unit, vp, 1); 13222 } 13223 } 13224 #endif /* end BCM_KATANA2-SUPPORT */ 13225 else if (mpls_port->criteria == BCM_MPLS_PORT_MATCH_VLAN) { 13226 if (!soc_mem_field_valid(unit, mem, SOURCE_TYPEf)) { 13227 return BCM_E_PARAM; 13228 } 13229 soc_mem_field32_set(unit, mem, vent, SOURCE_TYPEf, 0); 13230 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 13231 soc_mem_field32_set(unit, mem, vent, BASE_VALID_0f, 3); 13232 soc_mem_field32_set(unit, mem, vent, BASE_VALID_1f, 7); 13233 soc_mem_field32_set(unit, mem, vent, DATA_TYPEf, TR_VLXLT_HASH_KEY_TYPE_OVID); 13234 /*set default tag action profile ptr*/ 13235 soc_mem_field32_set(unit, mem, vent, XLATE__TAG_ACTION_PROFILE_PTRf, 13236 1); 13237 } else { 13238 soc_mem_field32_set(unit, mem, vent, VALIDf, 1); 13239 } 13240 13241 soc_mem_field32_set(unit, mem, vent, MPLS_ACTIONf, 0x1); /* SVP */ 13242 soc_mem_field32_set(unit, mem, vent, DISABLE_VLAN_CHECKSf, 1); 13243 soc_mem_field32_set(unit, mem, vent, SOURCE_VPf, vp); 13244 if (!BCM_VLAN_VALID(mpls_port->match_vlan)) { 13245 return BCM_E_PARAM; 13246 } 13247 soc_mem_field32_set(unit, mem, vent, KEY_TYPEf, 13248 TR_VLXLT_HASH_KEY_TYPE_OVID); 13249 soc_mem_field32_set(unit, mem, vent, OVIDf, mpls_port->match_vlan); 13250 13251 /* incoming port not used in lookup key, set field to all 1's */ 13252 soc_mem_field32_set(unit, mem, vent, GLPf, 13253 SOC_VLAN_XLATE_GLP_WILDCARD(unit)); 13254 13255 if (soc_feature(unit, soc_feature_vp_sharing)) { 13256 BCM_IF_ERROR_RETURN(_bcm_vp_info_get(unit, vp, &vp_info)); 13257 if (vp_info.flags & _BCM_VP_INFO_SHARED_PORT) { 13258 _BCM_MPLS_VPN_GET(vfi, _BCM_VPN_TYPE_VFI, vpn); 13259 soc_mem_field32_set(unit, mem, vent, VFIf, vfi); 13260 } 13261 } 13262 rv = _bcm_tr_mpls_match_vlan_entry_set(unit, mpls_port, vent); 13263 BCM_IF_ERROR_RETURN(rv); 13264 13265 if (!(mpls_info->match_key[vp].flags & 13266 _BCM_MPLS_PORT_MATCH_TYPE_SHARE)) { 13267 mpls_info->match_key[vp].flags = _BCM_MPLS_PORT_MATCH_TYPE_VLAN; 13268 mpls_info->match_key[vp].match_vlan = mpls_port->match_vlan; 13269 } 13270 if (!(mpls_port->flags & BCM_MPLS_PORT_REPLACE)) { 13271 bcm_tr_mpls_port_match_count_adjust(unit, vp, 1); 13272 } 13273 } 13274 return rv; 13275 } 13276 13277 /* 13278 * Function: 13279 * _bcm_tr_mpls_match_delete 13280 * Purpose: 13281 * Delete match criteria of an MPLS port 13282 * Parameters: 13283 * unit - (IN) Device Number 13284 * mpls_port - (IN) mpls port information 13285 * vp - (IN) Source Virtual Port 13286 * Returns: 13287 * BCM_E_XXX 13288 */ 13289 13290 int 13291 _bcm_tr_mpls_match_delete(int unit, int vp, bcm_mpls_port_t *mpls_port, 13292 int sw_clear) 13293 { 13294 _bcm_tr_mpls_bookkeeping_t *mpls_info = MPLS_INFO(unit); 13295 int rv=BCM_E_NONE; 13296 bcm_trunk_t trunk_id; 13297 int src_trk_idx=0; /*Source Trunk table index.*/ 13298 int mod_id_idx=0; /* Module_Id */ 13299 int port; 13300 int vpless_failover_port = FALSE; 13301 #if defined(BCM_KATANA2_SUPPORT) 13302 bcm_port_t pp_port = 0; 13303 #endif 13304 #if defined(BCM_KATANA2_SUPPORT) || defined(BCM_HGPROXY_COE_SUPPORT) 13305 int is_local_subport = 0; 13306 int local_port = 0; 13307 #endif 13308 uint32 vent[SOC_MAX_MEM_WORDS]; 13309 soc_mem_t mem; 13310 13311 #if defined(BCM_TRIDENT3_SUPPORT) 13312 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 13313 mem = VLAN_XLATE_1_DOUBLEm; 13314 } else 13315 #endif 13316 { 13317 mem = VLAN_XLATEm; 13318 } 13319 13320 sal_memset(vent, 0, sizeof(uint32) * SOC_MAX_MEM_WORDS); 13321 13322 if (_BCM_MPLS_GPORT_FAILOVER_VPLESS_GET(vp)) { 13323 vp = _BCM_MPLS_GPORT_FAILOVER_VPLESS_CLEAR(vp); 13324 if (mpls_info->match_key[vp].flags & _BCM_MPLS_PORT_MATCH_TYPE_LABEL) { 13325 /* label entry belongs to primary port */ 13326 return BCM_E_NONE; 13327 } 13328 vpless_failover_port = TRUE; 13329 } 13330 13331 /* Get module id for unit. */ 13332 BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &mod_id_idx)); 13333 13334 if (mpls_info->match_key[vp].flags == _BCM_MPLS_PORT_MATCH_TYPE_NONE) { 13335 if (sw_clear) { 13336 (void) bcm_tr_mpls_match_clear (unit, vp); 13337 bcm_tr_mpls_port_match_count_adjust(unit, vp, -1); 13338 } 13339 } else if (mpls_info->match_key[vp].flags == 13340 _BCM_MPLS_PORT_MATCH_TYPE_VLAN) { 13341 13342 /* default to SGLP type. TD2 */ 13343 if (SOC_MEM_FIELD_VALID(unit, mem, SOURCE_TYPEf)) { 13344 soc_mem_field32_set(unit, mem, vent, SOURCE_TYPEf, 1); 13345 } 13346 13347 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 13348 soc_mem_field32_set(unit, mem, vent, BASE_VALID_0f, 3); 13349 soc_mem_field32_set(unit, mem, vent, BASE_VALID_1f, 7); 13350 soc_mem_field32_set(unit, mem, vent, 13351 DATA_TYPEf, TR_VLXLT_HASH_KEY_TYPE_OVID); 13352 } else { 13353 soc_mem_field32_set(unit, mem, vent, VALIDf, 1); 13354 } 13355 soc_mem_field32_set(unit, mem, vent, KEY_TYPEf, 13356 TR_VLXLT_HASH_KEY_TYPE_OVID); 13357 soc_mem_field32_set(unit, mem, vent, OVIDf, 13358 mpls_info->match_key[vp].match_vlan); 13359 if (mpls_info->match_key[vp].modid != -1) { 13360 soc_mem_field32_set(unit, mem, vent, MODULE_IDf, 13361 mpls_info->match_key[vp].modid); 13362 soc_mem_field32_set(unit, mem, vent, PORT_NUMf, 13363 mpls_info->match_key[vp].port); 13364 } else if (mpls_info->match_key[vp].trunk_id != -1) { 13365 soc_mem_field32_set(unit, mem, vent, Tf, 1); 13366 soc_mem_field32_set(unit, mem, vent, TGIDf, 13367 mpls_info->match_key[vp].trunk_id); 13368 } else { 13369 if (SOC_MEM_FIELD_VALID(unit, mem, SOURCE_TYPEf)) { 13370 soc_mem_field32_set(unit, mem, vent, SOURCE_TYPEf, 0); 13371 } 13372 /* incoming port not used in lookup key, set field to all 1's */ 13373 soc_mem_field32_set(unit, mem, vent, GLPf, 13374 SOC_VLAN_XLATE_GLP_WILDCARD(unit)); 13375 } 13376 rv = soc_mem_delete(unit, mem, MEM_BLOCK_ANY, vent); 13377 if ((rv == BCM_E_NOT_FOUND) || (rv == BCM_E_NONE)) { 13378 /* if we are not able to search for matching entry then we 13379 * return BCM_E_NONE. so it is good to clean the local 13380 * state also. 13381 */ 13382 if (sw_clear) { 13383 (void) bcm_tr_mpls_match_clear (unit, vp); 13384 bcm_tr_mpls_port_match_count_adjust(unit, vp, -1); 13385 } 13386 } 13387 13388 BCM_IF_ERROR_RETURN(rv); 13389 } else if (mpls_info->match_key[vp].flags == 13390 _BCM_MPLS_PORT_MATCH_TYPE_INNER_VLAN) { 13391 13392 /* default to SGLP type. TD2 */ 13393 if (SOC_MEM_FIELD_VALID(unit, mem, SOURCE_TYPEf)) { 13394 soc_mem_field32_set(unit, mem, vent, SOURCE_TYPEf, 1); 13395 } 13396 13397 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 13398 soc_mem_field32_set(unit, mem, vent, BASE_VALID_0f, 3); 13399 soc_mem_field32_set(unit, mem, vent, BASE_VALID_1f, 7); 13400 soc_mem_field32_set(unit, mem, vent, 13401 DATA_TYPEf, TR_VLXLT_HASH_KEY_TYPE_IVID); 13402 } else { 13403 soc_mem_field32_set(unit, mem, vent, VALIDf, 1); 13404 } 13405 soc_mem_field32_set(unit, mem, vent, KEY_TYPEf, 13406 TR_VLXLT_HASH_KEY_TYPE_IVID); 13407 soc_mem_field32_set(unit, mem, vent, IVIDf, 13408 mpls_info->match_key[vp].match_inner_vlan); 13409 if (mpls_info->match_key[vp].modid != -1) { 13410 soc_mem_field32_set(unit, mem, vent, MODULE_IDf, 13411 mpls_info->match_key[vp].modid); 13412 soc_mem_field32_set(unit, mem, vent, PORT_NUMf, 13413 mpls_info->match_key[vp].port); 13414 } else { 13415 soc_mem_field32_set(unit, mem, vent, Tf, 1); 13416 soc_mem_field32_set(unit, mem, vent, TGIDf, 13417 mpls_info->match_key[vp].trunk_id); 13418 } 13419 rv = soc_mem_delete(unit, mem, MEM_BLOCK_ANY, vent); 13420 if ((rv == BCM_E_NOT_FOUND) || (rv == BCM_E_NONE)) { 13421 /* if we are not able to search for matching entry then we 13422 * return BCM_E_NONE. so it is good to clean the local 13423 * state also. 13424 */ 13425 13426 if (sw_clear) { 13427 (void) bcm_tr_mpls_match_clear (unit, vp); 13428 bcm_tr_mpls_port_match_count_adjust(unit, vp, -1); 13429 } 13430 } 13431 13432 BCM_IF_ERROR_RETURN(rv); 13433 13434 }else if (mpls_info->match_key[vp].flags == 13435 _BCM_MPLS_PORT_MATCH_TYPE_VLAN_STACKED) { 13436 13437 /* default to SGLP type. TD2 */ 13438 if (SOC_MEM_FIELD_VALID(unit, mem, SOURCE_TYPEf)) { 13439 soc_mem_field32_set(unit, mem, vent, SOURCE_TYPEf, 1); 13440 } 13441 13442 soc_mem_field32_set(unit, mem, vent, KEY_TYPEf, 13443 TR_VLXLT_HASH_KEY_TYPE_IVID_OVID); 13444 soc_mem_field32_set(unit, mem, vent, OVIDf, 13445 mpls_info->match_key[vp].match_vlan); 13446 soc_mem_field32_set(unit, mem, vent, IVIDf, 13447 mpls_info->match_key[vp].match_inner_vlan); 13448 if (mpls_info->match_key[vp].modid != -1) { 13449 soc_mem_field32_set(unit, mem, vent, MODULE_IDf, 13450 mpls_info->match_key[vp].modid); 13451 soc_mem_field32_set(unit, mem, vent, PORT_NUMf, 13452 mpls_info->match_key[vp].port); 13453 } else { 13454 soc_mem_field32_set(unit, mem, vent, Tf, 1); 13455 soc_mem_field32_set(unit, mem, vent, TGIDf, 13456 mpls_info->match_key[vp].trunk_id); 13457 } 13458 rv = soc_mem_delete(unit, mem, MEM_BLOCK_ANY, vent); 13459 if ((rv == BCM_E_NOT_FOUND) || (rv == BCM_E_NONE)) { 13460 /* if we are not able to search for matching entry then we 13461 * return BCM_E_NONE. so it is good to clean the local 13462 * state also. 13463 */ 13464 13465 if (sw_clear) { 13466 (void) bcm_tr_mpls_match_clear (unit, vp); 13467 bcm_tr_mpls_port_match_count_adjust(unit, vp, -1); 13468 } 13469 } 13470 13471 BCM_IF_ERROR_RETURN(rv); 13472 13473 } else if (mpls_info->match_key[vp].flags == 13474 _BCM_MPLS_PORT_MATCH_TYPE_VLAN_PRI) { 13475 13476 /* default to SGLP type. TD2 */ 13477 if (SOC_MEM_FIELD_VALID(unit, mem, SOURCE_TYPEf)) { 13478 soc_mem_field32_set(unit, mem, vent, SOURCE_TYPEf, 1); 13479 } 13480 13481 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 13482 soc_mem_field32_set(unit, mem, vent, BASE_VALID_0f, 3); 13483 soc_mem_field32_set(unit, mem, vent, BASE_VALID_1f, 7); 13484 soc_mem_field32_set(unit, mem, vent, 13485 DATA_TYPEf, TR_VLXLT_HASH_KEY_TYPE_PRI_CFI); 13486 } else { 13487 soc_mem_field32_set(unit, mem, vent, VALIDf, 1); 13488 } 13489 soc_mem_field32_set(unit, mem, vent, KEY_TYPEf, 13490 TR_VLXLT_HASH_KEY_TYPE_PRI_CFI); 13491 soc_mem_field32_set(unit, mem, vent, OTAGf, 13492 mpls_info->match_key[vp].match_vlan); 13493 if (mpls_info->match_key[vp].modid != -1) { 13494 soc_mem_field32_set(unit, mem, vent, MODULE_IDf, 13495 mpls_info->match_key[vp].modid); 13496 soc_mem_field32_set(unit, mem, vent, PORT_NUMf, 13497 mpls_info->match_key[vp].port); 13498 } else { 13499 soc_mem_field32_set(unit, mem, vent, Tf, 1); 13500 soc_mem_field32_set(unit, mem, vent, TGIDf, 13501 mpls_info->match_key[vp].trunk_id); 13502 } 13503 rv = soc_mem_delete(unit, mem, MEM_BLOCK_ANY, vent); 13504 if ((rv == BCM_E_NOT_FOUND) || (rv == BCM_E_NONE)) { 13505 /* if we are not able to search for matching entry then we 13506 * return BCM_E_NONE. so it is good to clean the local 13507 * state also. 13508 */ 13509 13510 if (sw_clear) { 13511 (void) bcm_tr_mpls_match_clear (unit, vp); 13512 bcm_tr_mpls_port_match_count_adjust(unit, vp, -1); 13513 } 13514 } 13515 13516 BCM_IF_ERROR_RETURN(rv); 13517 13518 #if defined(BCM_TRIUMPH2_SUPPORT) 13519 if (SOC_MEM_FIELD_VALID(unit, SOURCE_VPm, TRUST_OUTER_DOT1Pf)) { 13520 source_vp_entry_t svp; 13521 BCM_IF_ERROR_RETURN(READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp, &svp)); 13522 soc_SOURCE_VPm_field32_set(unit, &svp, TRUST_OUTER_DOT1Pf, 0); 13523 BCM_IF_ERROR_RETURN(WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, vp, &svp)); 13524 } 13525 #endif /* BCM_TRIUMPH2_SUPPORT */ 13526 13527 } else if (mpls_info->match_key[vp].flags == 13528 _BCM_MPLS_PORT_MATCH_TYPE_VLAN_TAG) { 13529 /* default to SGLP type. TD2 */ 13530 if (SOC_MEM_FIELD_VALID(unit, mem, SOURCE_TYPEf)) { 13531 soc_mem_field32_set(unit, mem, vent, SOURCE_TYPEf, 1); 13532 } 13533 13534 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 13535 soc_mem_field32_set(unit, mem, vent, BASE_VALID_0f, 3); 13536 soc_mem_field32_set(unit, mem, vent, BASE_VALID_1f, 7); 13537 soc_mem_field32_set(unit, mem, vent, 13538 DATA_TYPEf, TR_VLXLT_HASH_KEY_TYPE_OTAG); 13539 } else { 13540 soc_mem_field32_set(unit, mem, vent, VALIDf, 1); 13541 } 13542 soc_mem_field32_set(unit, mem, vent, KEY_TYPEf, 13543 TR_VLXLT_HASH_KEY_TYPE_OTAG); 13544 soc_mem_field32_set(unit, mem, vent, OTAGf, 13545 mpls_info->match_key[vp].match_vlan); 13546 if (mpls_info->match_key[vp].modid != -1) { 13547 soc_mem_field32_set(unit, mem, vent, MODULE_IDf, 13548 mpls_info->match_key[vp].modid); 13549 soc_mem_field32_set(unit, mem, vent, PORT_NUMf, 13550 mpls_info->match_key[vp].port); 13551 } else { 13552 soc_mem_field32_set(unit, mem, vent, Tf, 1); 13553 soc_mem_field32_set(unit, mem, vent, TGIDf, 13554 mpls_info->match_key[vp].trunk_id); 13555 } 13556 rv = soc_mem_delete(unit, mem, MEM_BLOCK_ANY, vent); 13557 if ((rv == BCM_E_NOT_FOUND) || (rv == BCM_E_NONE)) { 13558 /* if we are not able to search for matching entry then we 13559 * return BCM_E_NONE. so it is good to clean the local 13560 * state also. 13561 */ 13562 if (sw_clear) { 13563 (void) bcm_tr_mpls_match_clear (unit, vp); 13564 bcm_tr_mpls_port_match_count_adjust(unit, vp, -1); 13565 } 13566 } 13567 13568 BCM_IF_ERROR_RETURN(rv); 13569 13570 } else if (mpls_info->match_key[vp].flags == 13571 _BCM_MPLS_PORT_MATCH_TYPE_INNER_VLAN_TAG) { 13572 /* default to SGLP type. TD2 */ 13573 if (SOC_MEM_FIELD_VALID(unit, mem, SOURCE_TYPEf)) { 13574 soc_mem_field32_set(unit, mem, vent, SOURCE_TYPEf, 1); 13575 } 13576 13577 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 13578 soc_mem_field32_set(unit, mem, vent, BASE_VALID_0f, 3); 13579 soc_mem_field32_set(unit, mem, vent, BASE_VALID_1f, 7); 13580 soc_mem_field32_set(unit, mem, vent, 13581 DATA_TYPEf, TR_VLXLT_HASH_KEY_TYPE_ITAG); 13582 } else { 13583 soc_mem_field32_set(unit, mem, vent, VALIDf, 1); 13584 } 13585 soc_mem_field32_set(unit, mem, vent, KEY_TYPEf, 13586 TR_VLXLT_HASH_KEY_TYPE_ITAG); 13587 soc_mem_field32_set(unit, mem, vent, ITAGf, 13588 mpls_info->match_key[vp].match_inner_vlan); 13589 if (mpls_info->match_key[vp].modid != -1) { 13590 soc_mem_field32_set(unit, mem, vent, MODULE_IDf, 13591 mpls_info->match_key[vp].modid); 13592 soc_mem_field32_set(unit, mem, vent, PORT_NUMf, 13593 mpls_info->match_key[vp].port); 13594 } else { 13595 soc_mem_field32_set(unit, mem, vent, Tf, 1); 13596 soc_mem_field32_set(unit, mem, vent, TGIDf, 13597 mpls_info->match_key[vp].trunk_id); 13598 } 13599 rv = soc_mem_delete(unit, mem, MEM_BLOCK_ANY, vent); 13600 if ((rv == BCM_E_NOT_FOUND) || (rv == BCM_E_NONE)) { 13601 /* if we are not able to search for matching entry then we 13602 * return BCM_E_NONE. so it is good to clean the local 13603 * state also. 13604 */ 13605 13606 if (sw_clear) { 13607 (void) bcm_tr_mpls_match_clear (unit, vp); 13608 bcm_tr_mpls_port_match_count_adjust(unit, vp, -1); 13609 } 13610 } 13611 13612 BCM_IF_ERROR_RETURN(rv); 13613 13614 } else if (mpls_info->match_key[vp].flags == 13615 _BCM_MPLS_PORT_MATCH_TYPE_SHARE) { 13616 bcm_module_t mod_out = -1; 13617 bcm_port_t port_out = -1; 13618 int gport_id =-1; 13619 bcm_trunk_t trunk_id; 13620 13621 if (SOC_MEM_FIELD_VALID(unit, mem, SOURCE_TYPEf)) { 13622 soc_mem_field32_set(unit, mem, vent, SOURCE_TYPEf, 1); 13623 } 13624 13625 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 13626 soc_mem_field32_set(unit, mem, vent, BASE_VALID_0f, 3); 13627 soc_mem_field32_set(unit, mem, vent, BASE_VALID_1f, 7); 13628 } else { 13629 soc_mem_field32_set(unit, mem, vent, VALIDf, 1); 13630 } 13631 13632 if (BCM_MPLS_PORT_MATCH_PORT_VLAN == mpls_port->criteria) { 13633 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 13634 soc_mem_field32_set(unit, mem, vent, 13635 DATA_TYPEf, TR_VLXLT_HASH_KEY_TYPE_OVID); 13636 } 13637 soc_mem_field32_set(unit, mem, vent, KEY_TYPEf, 13638 TR_VLXLT_HASH_KEY_TYPE_OVID); 13639 soc_mem_field32_set(unit, mem, vent, OVIDf, 13640 mpls_port->match_vlan); 13641 } else if (BCM_MPLS_PORT_MATCH_PORT_VLAN_STACKED == mpls_port->criteria) { 13642 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 13643 soc_mem_field32_set(unit, mem, vent, 13644 DATA_TYPEf, TR_VLXLT_HASH_KEY_TYPE_IVID_OVID); 13645 } 13646 soc_mem_field32_set(unit, mem, vent, KEY_TYPEf, 13647 TR_VLXLT_HASH_KEY_TYPE_IVID_OVID); 13648 soc_mem_field32_set(unit, mem, vent, OVIDf, 13649 mpls_port->match_vlan); 13650 soc_mem_field32_set(unit, mem, vent, IVIDf, 13651 mpls_port->match_inner_vlan); 13652 } else if (BCM_MPLS_PORT_MATCH_PORT_INNER_VLAN == mpls_port->criteria) { 13653 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 13654 soc_mem_field32_set(unit, mem, vent, 13655 DATA_TYPEf, TR_VLXLT_HASH_KEY_TYPE_IVID); 13656 } 13657 soc_mem_field32_set(unit, mem, vent, KEY_TYPEf, 13658 TR_VLXLT_HASH_KEY_TYPE_IVID); 13659 soc_mem_field32_set(unit, mem, vent, IVIDf, 13660 mpls_port->match_inner_vlan); 13661 } else if (BCM_MPLS_PORT_MATCH_VLAN_PRI == mpls_port->criteria) { 13662 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 13663 soc_mem_field32_set(unit, mem, vent, 13664 DATA_TYPEf, TR_VLXLT_HASH_KEY_TYPE_PRI_CFI); 13665 } 13666 soc_mem_field32_set(unit, mem, vent, KEY_TYPEf, 13667 TR_VLXLT_HASH_KEY_TYPE_PRI_CFI); 13668 soc_mem_field32_set(unit, mem, vent, OTAGf, 13669 mpls_port->match_vlan); 13670 } else if (BCM_MPLS_PORT_MATCH_PORT_VLAN_TAG == mpls_port->criteria) { 13671 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 13672 soc_mem_field32_set(unit, mem, vent, 13673 DATA_TYPEf, TR_VLXLT_HASH_KEY_TYPE_OTAG); 13674 } 13675 soc_mem_field32_set(unit, mem, vent, KEY_TYPEf, 13676 TR_VLXLT_HASH_KEY_TYPE_OTAG); 13677 soc_mem_field32_set(unit, mem, vent, OTAGf, 13678 mpls_port->match_vlan); 13679 13680 } else if (BCM_MPLS_PORT_MATCH_PORT_INNER_VLAN_TAG == mpls_port->criteria) { 13681 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 13682 soc_mem_field32_set(unit, mem, vent, 13683 DATA_TYPEf, TR_VLXLT_HASH_KEY_TYPE_ITAG); 13684 } 13685 soc_mem_field32_set(unit, mem, vent, KEY_TYPEf, 13686 TR_VLXLT_HASH_KEY_TYPE_ITAG); 13687 soc_mem_field32_set(unit, mem, vent, ITAGf, 13688 mpls_port->match_inner_vlan); 13689 13690 } else { 13691 return BCM_E_UNAVAIL; 13692 } 13693 rv = _bcm_esw_gport_resolve(unit, mpls_port->port, &mod_out, 13694 &port_out, &trunk_id, &gport_id); 13695 BCM_IF_ERROR_RETURN(rv); 13696 13697 if (BCM_GPORT_IS_TRUNK(mpls_port->port)) { 13698 soc_mem_field32_set(unit, mem, vent, Tf, 1); 13699 soc_mem_field32_set(unit, mem, vent, TGIDf, trunk_id); 13700 } else { 13701 soc_mem_field32_set(unit, mem, vent, MODULE_IDf, mod_out); 13702 soc_mem_field32_set(unit, mem, vent, PORT_NUMf, port_out); 13703 } 13704 rv = soc_mem_delete(unit, mem, MEM_BLOCK_ANY, vent); 13705 BCM_IF_ERROR_RETURN(rv); 13706 13707 bcm_tr_mpls_port_match_count_adjust(unit, vp, -1); 13708 } else if ((mpls_info->match_key[vp].flags == _BCM_MPLS_PORT_MATCH_TYPE_PORT) 13709 || ((mpls_info->match_key[vp].flags == _BCM_MPLS_PORT_MATCH_TYPE_TRUNK) 13710 && (mpls_port != NULL) && (!BCM_GPORT_IS_TRUNK(mpls_port->port)))) { 13711 13712 int is_local; 13713 bcm_module_t mod_out; 13714 bcm_port_t port_out; 13715 int gport_id; 13716 13717 if (mpls_info->match_key[vp].flags == _BCM_MPLS_PORT_MATCH_TYPE_PORT) { 13718 src_trk_idx = mpls_info->match_key[vp].index; 13719 } else { 13720 /* 13721 * The vp has been created based on trunk. 13722 * When a new port is deleted from the trunk, a match will be deleted 13723 * for the vp through bcm_port_match_delete. 13724 */ 13725 if (mpls_port == NULL) { 13726 return BCM_E_PARAM; 13727 } 13728 BCM_IF_ERROR_RETURN( 13729 _bcm_esw_gport_resolve(unit, mpls_port->port, &mod_out, 13730 &port_out, &trunk_id, &gport_id)); 13731 /* Get index to source trunk map table */ 13732 BCM_IF_ERROR_RETURN( 13733 _bcm_esw_src_mod_port_table_index_get( 13734 unit, mod_out, port_out, &src_trk_idx)); 13735 } 13736 13737 rv = soc_mem_field32_modify(unit, SOURCE_TRUNK_MAP_TABLEm, 13738 src_trk_idx, SOURCE_VPf, 0); 13739 BCM_IF_ERROR_RETURN(rv); 13740 if (SOC_MEM_FIELD_VALID(unit,SOURCE_TRUNK_MAP_TABLEm,SVP_VALIDf)) { 13741 rv = soc_mem_field32_modify(unit, SOURCE_TRUNK_MAP_TABLEm, 13742 src_trk_idx, SVP_VALIDf, 0); 13743 BCM_IF_ERROR_RETURN(rv); 13744 } 13745 13746 BCM_IF_ERROR_RETURN(_bcm_esw_src_modid_port_get( unit, src_trk_idx, 13747 &mod_id_idx, &port)); 13748 BCM_IF_ERROR_RETURN 13749 ( _bcm_esw_modid_is_local(unit, mod_id_idx, &is_local)); 13750 13751 #if defined(BCM_HGPROXY_COE_SUPPORT) 13752 if (soc_feature(unit, soc_feature_hgproxy_subtag_coe)) { 13753 13754 if (is_local == 0) { 13755 if(_bcm_xgs5_subport_coe_mod_port_local(unit, mod_id_idx, port)) { 13756 is_local_subport = 1; 13757 local_port = mpls_port->port; 13758 } 13759 } 13760 } else 13761 #endif 13762 13763 #if defined(BCM_KATANA2_SUPPORT) 13764 if (soc_feature(unit, soc_feature_linkphy_coe) || 13765 soc_feature(unit, soc_feature_subtag_coe)) { 13766 if (is_local == 0) { 13767 is_local_subport = 0; 13768 if (_bcm_kt2_mod_is_coe_mod_check(unit, mod_id_idx) == BCM_E_NONE) { 13769 rv = _bcm_kt2_modport_to_pp_port_get( 13770 unit, mod_id_idx, port, &pp_port); 13771 if (_bcm_kt2_is_pp_port_linkphy_subtag(unit, pp_port)){ 13772 is_local_subport = 1; 13773 local_port = pp_port; 13774 } 13775 } 13776 } 13777 } 13778 #endif 13779 13780 #if defined(BCM_KATANA2_SUPPORT) || defined(BCM_HGPROXY_COE_SUPPORT) 13781 if (is_local_subport) { 13782 13783 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 13784 rv = _bcm_esw_port_tab_set(unit, local_port, 13785 _BCM_CPU_TABS_BOTH, 13786 PORT_OPERATIONf, 0x0); 13787 } else { 13788 rv = _bcm_esw_port_tab_set_without_portlock( 13789 unit, local_port, _BCM_CPU_TABS_NONE, PORT_OPERATIONf, 13790 0x0); /* Normal */ 13791 } 13792 BCM_IF_ERROR_RETURN(rv); 13793 13794 /* Set TAG_ACTION_PROFILE_PTR */ 13795 rv = bcm_tr_mpls_port_untagged_profile_reset(unit, local_port); 13796 BCM_IF_ERROR_RETURN(rv); 13797 } else 13798 #endif 13799 if (is_local) { 13800 /* Convert system ports to physical ports */ 13801 if (soc_feature(unit, soc_feature_sysport_remap)) { 13802 BCM_XLATE_SYSPORT_S2P(unit, &port); 13803 } 13804 13805 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 13806 rv = _bcm_esw_port_tab_set(unit, port, 13807 _BCM_CPU_TABS_BOTH, 13808 PORT_OPERATIONf, 0x0); 13809 } else { 13810 rv = soc_mem_field32_modify(unit, PORT_TABm, port, 13811 PORT_OPERATIONf, 0x0); /* NORMAL */ 13812 } 13813 BCM_IF_ERROR_RETURN(rv); 13814 13815 /* Reset TAG_ACTION_PROFILE_PTR */ 13816 rv = bcm_tr_mpls_port_untagged_profile_reset(unit, port); 13817 BCM_IF_ERROR_RETURN(rv); 13818 } 13819 13820 if (sw_clear) { 13821 (void) bcm_tr_mpls_match_clear (unit, vp); 13822 } 13823 } else if (mpls_info->match_key[vp].flags == 13824 _BCM_MPLS_PORT_MATCH_TYPE_TRUNK) { 13825 trunk_id = mpls_info->match_key[vp].trunk_id; 13826 rv = bcm_tr_mpls_match_trunk_delete(unit, trunk_id, vp); 13827 BCM_IF_ERROR_RETURN(rv); 13828 mpls_info->trunk_vp_map[trunk_id] = -1; 13829 13830 if (sw_clear) { 13831 (void) bcm_tr_mpls_match_clear (unit, vp); 13832 } 13833 } else if ((mpls_info->match_key[vp].flags & 13834 _BCM_MPLS_PORT_MATCH_TYPE_LABEL) || 13835 (mpls_info->match_key[vp].flags == 13836 _BCM_MPLS_PORT_MATCH_TYPE_LABEL_PORT)) { 13837 mpls_entry_entry_t ment, ret_ment; 13838 int pw_cnt; 13839 int svp = 0; 13840 13841 sal_memset(&ment, 0, sizeof(mpls_entry_entry_t)); 13842 sal_memset(&ret_ment, 0, sizeof(mpls_entry_entry_t)); 13843 if (vpless_failover_port) { 13844 if (mpls_info->match_key[vp].fo_modid != -1) { 13845 soc_MPLS_ENTRYm_field32_set(unit, &ment, MPLS__MODULE_IDf, 13846 mpls_info->match_key[vp].fo_modid); 13847 soc_MPLS_ENTRYm_field32_set(unit, &ment, MPLS__PORT_NUMf, 13848 mpls_info->match_key[vp].fo_port); 13849 } else { 13850 soc_MPLS_ENTRYm_field32_set(unit, &ment, MPLS__Tf, 1); 13851 soc_MPLS_ENTRYm_field32_set(unit, &ment, MPLS__TGIDf, 13852 mpls_info->match_key[vp].fo_trunk_id); 13853 } 13854 } else { 13855 if (mpls_info->match_key[vp].modid != -1) { 13856 soc_MPLS_ENTRYm_field32_set(unit, &ment, MODULE_IDf, 13857 mpls_info->match_key[vp].modid); 13858 soc_MPLS_ENTRYm_field32_set(unit, &ment, PORT_NUMf, 13859 mpls_info->match_key[vp].port); 13860 } else { 13861 soc_MPLS_ENTRYm_field32_set(unit, &ment, Tf, 1); 13862 soc_MPLS_ENTRYm_field32_set(unit, &ment, TGIDf, 13863 mpls_info->match_key[vp].trunk_id); 13864 } 13865 } 13866 soc_MPLS_ENTRYm_field32_set(unit, &ment, MPLS_LABELf, 13867 mpls_info->match_key[vp].match_label); 13868 13869 rv = soc_mem_search(unit, MPLS_ENTRYm, MEM_BLOCK_ANY, &src_trk_idx, 13870 &ment, &ret_ment, 0); 13871 13872 if (rv == SOC_E_NONE) { 13873 if (soc_MPLS_ENTRYm_field32_get(unit, &ret_ment, PW_TERM_NUM_VALIDf)) { 13874 pw_cnt = soc_MPLS_ENTRYm_field32_get(unit, &ret_ment, PW_TERM_NUMf); 13875 (void) _bcm_tr_mpls_pw_term_counter_delete (unit, pw_cnt); 13876 soc_MPLS_ENTRYm_field32_set(unit, &ret_ment, PW_TERM_NUM_VALIDf, 0); 13877 soc_MPLS_ENTRYm_field32_set(unit, &ret_ment, PW_TERM_NUMf, 0); 13878 } 13879 13880 #ifdef BCM_TRIUMPH2_SUPPORT 13881 if (soc_feature(unit, soc_feature_gport_service_counters)) { 13882 if ((0 != soc_MPLS_ENTRYm_field32_get(unit, &ret_ment, 13883 USE_VINTF_CTR_IDXf)) && 13884 (0 != soc_MPLS_ENTRYm_field32_get(unit, &ret_ment, 13885 VINTF_CTR_IDXf))) { 13886 /* Release MPLS label stat use, if any */ 13887 _bcm_flex_stat_handle_t mpls_fsh; 13888 _BCM_FLEX_STAT_HANDLE_CLEAR(mpls_fsh); 13889 _BCM_FLEX_STAT_HANDLE_COPY(mpls_fsh, ment); 13890 _bcm_esw_flex_stat_ext_handle_free(unit, 13891 _bcmFlexStatTypeMplsLabel, 13892 mpls_fsh); 13893 } 13894 } 13895 #endif /* BCM_TRIUMPH2_SUPPORT */ 13896 13897 svp = soc_mem_field32_get(unit, MPLS_ENTRYm, &ret_ment, SOURCE_VPf); 13898 if (svp == vp) { 13899 if (_bcm_tr_mpls_match_vp_find(unit, vp, &svp)) { 13900 soc_mem_field32_set(unit, MPLS_ENTRYm, &ret_ment, SOURCE_VPf, svp); 13901 rv = soc_mem_write(unit, MPLS_ENTRYm, MEM_BLOCK_ANY, src_trk_idx, &ret_ment); 13902 } else { 13903 rv = soc_mem_delete(unit, MPLS_ENTRYm, MEM_BLOCK_ANY, &ret_ment); 13904 } 13905 } 13906 13907 if ((rv == BCM_E_NOT_FOUND) || (rv == BCM_E_NONE)) { 13908 if (vpless_failover_port) { 13909 mpls_info->match_key[vp].fo_trunk_id = -1; 13910 mpls_info->match_key[vp].fo_port = 0; 13911 mpls_info->match_key[vp].fo_modid = -1; 13912 } else { 13913 if (sw_clear) { 13914 if (mpls_info->match_key[vp].flags & 13915 _BCM_MPLS_PORT_MATCH_TYPE_NONE) { 13916 bcm_tr_mpls_port_match_count_adjust(unit, vp, -1); 13917 } 13918 (void) bcm_tr_mpls_match_clear (unit, vp); 13919 } 13920 } 13921 } 13922 BCM_IF_ERROR_RETURN(rv); 13923 } 13924 } 13925 #if defined(BCM_KATANA2_SUPPORT) 13926 else if ((mpls_info->match_key[vp].flags == 13927 BCM_MPLS_PORT_MATCH_PORT_SUBPORT_PKT_VID) || 13928 (mpls_info->match_key[vp].flags == 13929 BCM_MPLS_PORT_MATCH_PORT_SUBPORT_PKT_VID_INNER_VLAN) || 13930 (mpls_info->match_key[vp].flags == 13931 BCM_MPLS_PORT_MATCH_PORT_SUBPORT_PKT_VID_OUTER_VLAN)) { 13932 int is_local = 0; 13933 13934 BCM_IF_ERROR_RETURN 13935 ( _bcm_esw_modid_is_local(unit, mod_id_idx, &is_local)); 13936 13937 /* default to SGLP type. TD2 */ 13938 if (SOC_MEM_FIELD_VALID(unit, mem, SOURCE_TYPEf)) { 13939 soc_mem_field32_set(unit, mem, vent, SOURCE_TYPEf, 1); 13940 } 13941 13942 soc_mem_field32_set(unit, mem, vent, VALIDf, 1); 13943 if (mpls_info->match_key[vp].flags == 13944 BCM_MPLS_PORT_MATCH_PORT_SUBPORT_PKT_VID) { 13945 soc_mem_field32_set(unit, mem, vent, KEY_TYPEf, 13946 KT2_PT_XLT_KEY_TYPE_LLVID); 13947 } else if (mpls_info->match_key[vp].flags == 13948 BCM_MPLS_PORT_MATCH_PORT_SUBPORT_PKT_VID_OUTER_VLAN) { 13949 soc_mem_field32_set(unit, mem, vent, KEY_TYPEf, 13950 KT2_PT_XLT_KEY_TYPE_LLVID_OVID); 13951 soc_mem_field32_set(unit, mem, vent, LLTAG__OVIDf, 13952 mpls_info->match_key[vp].match_vlan); 13953 } else { 13954 soc_mem_field32_set(unit, mem, vent, KEY_TYPEf, 13955 KT2_PT_XLT_KEY_TYPE_LLVID_IVID); 13956 soc_mem_field32_set(unit, mem, vent, LLTAG__IVIDf, 13957 mpls_info->match_key[vp].match_inner_vlan); 13958 } 13959 13960 soc_mem_field32_set(unit, mem, vent, LLTAG__LLVIDf, 13961 mpls_info->match_key[vp].match_subport_pkt_vid); 13962 if (mpls_info->match_key[vp].modid != -1) { 13963 soc_mem_field32_set(unit, mem, vent, LLTAG__MODULE_IDf, 13964 mpls_info->match_key[vp].modid); 13965 soc_mem_field32_set(unit, mem, vent, LLTAG__PORT_NUMf, 13966 mpls_info->match_key[vp].port); 13967 } else { 13968 soc_mem_field32_set(unit, mem, vent, LLTAG__Tf, 1); 13969 soc_mem_field32_set(unit, mem, vent, LLTAG__TGIDf, 13970 mpls_info->match_key[vp].trunk_id); 13971 } 13972 rv = soc_mem_delete(unit, mem, MEM_BLOCK_ANY, vent); 13973 BCM_IF_ERROR_RETURN(rv); 13974 if (is_local) { 13975 pp_port = mpls_info->match_key[vp].port; 13976 if (soc_feature(unit, soc_feature_sysport_remap)) { 13977 BCM_XLATE_SYSPORT_S2P(unit, &pp_port); 13978 } 13979 13980 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 13981 rv = _bcm_esw_port_tab_set(unit, pp_port, 13982 _BCM_CPU_TABS_BOTH, 13983 VT_KEY_TYPEf, KT2_PT_XLT_KEY_TYPE_OVID); 13984 } else { 13985 rv = soc_mem_field32_modify(unit, PORT_TABm, pp_port, 13986 VT_KEY_TYPEf, KT2_PT_XLT_KEY_TYPE_OVID);/*default*/ 13987 } 13988 BCM_IF_ERROR_RETURN(rv); 13989 13990 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 13991 rv = _bcm_esw_port_tab_set(unit, pp_port, 13992 _BCM_CPU_TABS_BOTH, 13993 VT_PORT_TYPE_SELECT_1f, 1); 13994 } else { 13995 rv = soc_mem_field32_modify(unit, PORT_TABm, pp_port, 13996 VT_PORT_TYPE_SELECTf, 1);/*default*/ 13997 } 13998 BCM_IF_ERROR_RETURN(rv); 13999 } 14000 14001 if (sw_clear) { 14002 (void) bcm_tr_mpls_match_clear (unit, vp); 14003 bcm_tr_mpls_port_match_count_adjust(unit, vp, -1); 14004 } 14005 } 14006 #endif /* end BCM_KATANA2_SUPPORT */ 14007 return rv; 14008 } 14009 14010 /* 14011 * Function: 14012 * _bcm_tr_mpls_failover_nw_port_match_get 14013 * Purpose: 14014 * Get match criteria of an MPLS port 14015 * Parameters: 14016 * unit - (IN) Device Number 14017 * mpls_port - (IN) mpls port information 14018 * vp - (IN) Source Virtual Port 14019 * return_ment - (OUT) matched entry 14020 * Returns: 14021 * BCM_E_XXX 14022 */ 14023 int 14024 _bcm_tr_mpls_failover_nw_port_match_get(int unit, bcm_mpls_port_t *mpls_port, 14025 int vp, mpls_entry_entry_t *return_ment) 14026 { 14027 14028 _bcm_tr_mpls_bookkeeping_t *mpls_info = MPLS_INFO(unit); 14029 mpls_entry_entry_t ment; 14030 int entry_index = -1; 14031 int key_type = 0; /* mpls_key_type */ 14032 int rv = BCM_E_NONE; 14033 bcm_module_t mod_out; 14034 bcm_port_t port_out; 14035 bcm_trunk_t trunk_id; 14036 bcm_gport_t gport_id; 14037 14038 /* return not found if both inputs are invalid. */ 14039 if ((mpls_port == NULL) && (vp == -1)) { 14040 return BCM_E_NOT_FOUND; 14041 } 14042 14043 sal_memset(&ment, 0, sizeof(mpls_entry_entry_t)); 14044 if (mpls_port != NULL) { 14045 if (mpls_port->criteria == BCM_MPLS_PORT_MATCH_LABEL_PORT) { 14046 /* Check for Port_independent Label mapping */ 14047 rv = bcm_tr_mpls_port_independent_range (unit, mpls_port->match_label, mpls_port->port); 14048 if (rv < 0) { 14049 return rv; 14050 } 14051 14052 rv = _bcm_esw_gport_resolve(unit, mpls_port->port, &mod_out, 14053 &port_out, &trunk_id, &gport_id); 14054 BCM_IF_ERROR_RETURN(rv); 14055 14056 if (BCM_GPORT_IS_TRUNK(mpls_port->port)) { 14057 soc_MPLS_ENTRYm_field32_set(unit, &ment, Tf, 1); 14058 soc_MPLS_ENTRYm_field32_set(unit, &ment, TGIDf, mpls_port->port); 14059 } else { 14060 soc_MPLS_ENTRYm_field32_set(unit, &ment, MODULE_IDf, mod_out); 14061 soc_MPLS_ENTRYm_field32_set(unit, &ment, PORT_NUMf, port_out); 14062 } 14063 14064 } else if (mpls_port->criteria == BCM_MPLS_PORT_MATCH_LABEL) { 14065 soc_MPLS_ENTRYm_field32_set(unit, &ment, MODULE_IDf, 0); 14066 soc_MPLS_ENTRYm_field32_set(unit, &ment, PORT_NUMf, 0); 14067 } else { 14068 return BCM_E_NOT_FOUND; 14069 } 14070 14071 /* Use old label to get old mpls entry for replace operation */ 14072 soc_MPLS_ENTRYm_field32_set(unit, &ment, MPLS_LABELf, 14073 mpls_port->match_label); 14074 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 14075 soc_MPLS_ENTRYm_field32_set(unit, &ment, BASE_VALID_0f, 3); 14076 soc_MPLS_ENTRYm_field32_set(unit, &ment, BASE_VALID_1f, 7); 14077 } else { 14078 soc_MPLS_ENTRYm_field32_set(unit, &ment, VALIDf, 1); 14079 } 14080 soc_MPLS_ENTRYm_field32_set(unit, &ment, MPLS_ACTION_IF_BOSf, 14081 0x1); /* L2 SVP */ 14082 soc_MPLS_ENTRYm_field32_set(unit, &ment, MPLS_ACTION_IF_NOT_BOSf, 14083 0x0); /* INVALID */ 14084 soc_MPLS_ENTRYm_field32_set(unit, &ment, KEY_TYPEf, key_type); 14085 } else { 14086 14087 if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeMpls)) { 14088 return BCM_E_NOT_FOUND; 14089 } 14090 14091 if ((mpls_info->match_key[vp].flags & 14092 _BCM_MPLS_PORT_MATCH_TYPE_LABEL) || 14093 (mpls_info->match_key[vp].flags == 14094 _BCM_MPLS_PORT_MATCH_TYPE_LABEL_PORT)) { 14095 14096 if (mpls_info->match_key[vp].flags & 14097 _BCM_MPLS_PORT_MATCH_TYPE_LABEL_PORT) { 14098 14099 if (mpls_info->match_key[vp].trunk_id != -1) { 14100 soc_MPLS_ENTRYm_field32_set(unit, &ment, Tf, 1); 14101 soc_MPLS_ENTRYm_field32_set(unit, &ment, TGIDf, 14102 mpls_info->match_key[vp].trunk_id); 14103 } else { 14104 soc_MPLS_ENTRYm_field32_set(unit, &ment, MODULE_IDf, 14105 mpls_info->match_key[vp].modid); 14106 soc_MPLS_ENTRYm_field32_set(unit, &ment, PORT_NUMf, 14107 mpls_info->match_key[vp].port); 14108 } 14109 } 14110 14111 soc_MPLS_ENTRYm_field32_set(unit, &ment, MPLS_LABELf, 14112 mpls_info->match_key[vp].match_label); 14113 soc_MPLS_ENTRYm_field32_set(unit, &ment, KEY_TYPEf, key_type); 14114 14115 } else { 14116 return BCM_E_NOT_FOUND; 14117 } 14118 } 14119 14120 rv = soc_mem_search(unit, MPLS_ENTRYm, MEM_BLOCK_ANY, &entry_index, 14121 &ment, return_ment, 0); 14122 14123 return rv; 14124 } 14125 14126 14127 #ifdef BCM_TRIDENT2_SUPPORT 14128 /* 14129 * Function: 14130 * _bcm_td2_mpls_match_vp_replace 14131 * Purpose: 14132 * Replace vp value in mpls vp's match entry. 14133 * Parameters: 14134 * unit - (IN) SOC unit number. 14135 * vp - (IN) mpls vp whose match entry is being replaced. 14136 * new_vp - (IN) New vp value. 14137 * old_vp - (OUT) Old vp value. 14138 * Returns: 14139 * BCM_X_XXX 14140 */ 14141 STATIC int 14142 _bcm_td2_mpls_match_vp_replace(int unit, int vp, int new_vp, int *old_vp) 14143 { 14144 int i = 0; 14145 int rv = BCM_E_NONE; 14146 int key_type = bcmVlanTranslateKeyInvalid; 14147 int port = 0; 14148 int my_modid = 0; 14149 int stm_idx = 0; 14150 int entry_index = 0; 14151 int local_port[SOC_MAX_NUM_PORTS]; 14152 int local_port_count = 0; 14153 int match_trunk_id = 0; 14154 int match_modid = 0; 14155 int match_port = 0; 14156 soc_mem_t mem; 14157 uint32 svp_valid; 14158 uint32 match_label; 14159 uint32 vent[SOC_MAX_MEM_WORDS]; 14160 uint32 ment[SOC_MAX_MEM_WORDS]; 14161 source_trunk_map_table_entry_t stm_entry; 14162 _bcm_tr_mpls_match_port_info_t *mkey = NULL; 14163 14164 mkey = &(MPLS_INFO(unit)->match_key[vp]); 14165 14166 #define _BCM_VLXLT_KTYPE_ASSIGN(_ktype, _k) \ 14167 do { \ 14168 if (_ktype == bcmVlanTranslateKeyInvalid) { \ 14169 _ktype = _k; \ 14170 } \ 14171 } while(0) 14172 14173 switch(mkey->flags) { 14174 case _BCM_MPLS_PORT_MATCH_TYPE_VLAN: 14175 _BCM_VLXLT_KTYPE_ASSIGN(key_type, bcmVlanTranslateKeyPortOuter); 14176 /* Fall through */ 14177 case _BCM_MPLS_PORT_MATCH_TYPE_INNER_VLAN: 14178 _BCM_VLXLT_KTYPE_ASSIGN(key_type, bcmVlanTranslateKeyPortInner); 14179 /* Fall through */ 14180 case _BCM_MPLS_PORT_MATCH_TYPE_VLAN_STACKED: 14181 _BCM_VLXLT_KTYPE_ASSIGN(key_type, bcmVlanTranslateKeyPortDouble); 14182 /* Fall through */ 14183 case _BCM_MPLS_PORT_MATCH_TYPE_VLAN_PRI: 14184 _BCM_VLXLT_KTYPE_ASSIGN(key_type, bcmVlanTranslateKeyPortOuterPri); 14185 /* Construct lookup key */ 14186 sal_memset(vent, 0, sizeof(uint32) * SOC_MAX_MEM_WORDS); 14187 14188 #if defined(BCM_TRIDENT3_SUPPORT) 14189 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 14190 mem = VLAN_XLATE_1_DOUBLEm; 14191 14192 soc_mem_field32_set(unit, mem, vent, BASE_VALID_0f, 3); 14193 soc_mem_field32_set(unit, mem, vent, BASE_VALID_1f, 7); 14194 } else 14195 #endif 14196 { 14197 mem = VLAN_XLATEm; 14198 14199 soc_mem_field32_set(unit, mem, vent, VALIDf, 0x1); 14200 } 14201 14202 if (mkey->modid != -1) { 14203 BCM_GPORT_MODPORT_SET(port, mkey->modid, mkey->port); 14204 } else { 14205 BCM_GPORT_TRUNK_SET(port, mkey->trunk_id); 14206 } 14207 14208 BCM_IF_ERROR_RETURN( 14209 _bcm_trx_vlan_translate_entry_assemble(unit, &vent, 14210 port, key_type, 14211 mkey->match_inner_vlan, 14212 mkey->match_vlan)); 14213 soc_mem_lock(unit, mem); 14214 /* Lookup existing entry */ 14215 rv = soc_mem_search(unit, mem, MEM_BLOCK_ALL, 14216 &entry_index, &vent, &vent, 0); 14217 if (BCM_FAILURE(rv)) { 14218 soc_mem_unlock(unit, mem); 14219 return rv; 14220 } 14221 /* Replace entry's VP value */ 14222 *old_vp = soc_mem_field32_get(unit, mem, vent, SOURCE_VPf); 14223 soc_mem_field32_set(unit, mem, vent, SOURCE_VPf, new_vp); 14224 14225 /* Insert new entry */ 14226 rv = soc_mem_insert(unit, mem, MEM_BLOCK_ALL, &vent); 14227 soc_mem_unlock(unit, mem); 14228 if (rv == SOC_E_EXISTS) { 14229 rv = BCM_E_NONE; 14230 } else { 14231 return BCM_E_INTERNAL; 14232 } 14233 break; 14234 case _BCM_MPLS_PORT_MATCH_TYPE_PORT: 14235 mem = SOURCE_TRUNK_MAP_TABLEm; 14236 14237 soc_mem_lock(unit, mem); 14238 14239 rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, 14240 mkey->index, &stm_entry); 14241 if (BCM_FAILURE(rv)) { 14242 soc_mem_unlock(unit, mem); 14243 return rv; 14244 } 14245 /* Resolve SVP Mode */ 14246 if (soc_mem_field_valid(unit, mem, SVP_VALIDf)) { 14247 svp_valid = soc_mem_field32_get(unit, mem, 14248 &stm_entry, SVP_VALIDf); 14249 if (svp_valid == 0) { 14250 soc_mem_unlock(unit, mem); 14251 return BCM_E_INTERNAL; 14252 } 14253 } 14254 *old_vp = soc_mem_field32_get(unit, mem, 14255 &stm_entry, SOURCE_VPf); 14256 rv = soc_mem_field32_modify(unit, mem, mkey->index, 14257 SOURCE_VPf, new_vp); 14258 14259 soc_mem_unlock(unit, mem); 14260 break; 14261 case _BCM_MPLS_PORT_MATCH_TYPE_TRUNK: 14262 mem = SOURCE_TRUNK_MAP_TABLEm; 14263 14264 /* Get module id for unit. */ 14265 BCM_IF_ERROR_RETURN( 14266 bcm_esw_stk_my_modid_get(unit, &my_modid)); 14267 14268 BCM_IF_ERROR_RETURN( 14269 _bcm_esw_trunk_local_members_get(unit, mkey->trunk_id, 14270 SOC_MAX_NUM_PORTS, 14271 local_port, 14272 &local_port_count)); 14273 soc_mem_lock(unit, mem); 14274 14275 for (i = 0; i < local_port_count; i++) { 14276 /* Get index to source trunk map table */ 14277 rv = _bcm_esw_src_mod_port_table_index_get(unit, my_modid, 14278 local_port[i], 14279 &stm_idx); 14280 if (BCM_FAILURE(rv)) { 14281 soc_mem_unlock(unit, mem); 14282 return rv; 14283 } 14284 14285 rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, 14286 stm_idx, &stm_entry); 14287 if (BCM_FAILURE(rv)) { 14288 soc_mem_unlock(unit, mem); 14289 return rv; 14290 } 14291 14292 /* Resolve SVP Mode */ 14293 if (soc_mem_field_valid(unit, mem, SVP_VALIDf)) { 14294 svp_valid = soc_mem_field32_get(unit, mem, 14295 &stm_entry, SVP_VALIDf); 14296 if (svp_valid == 0) { 14297 soc_mem_unlock(unit, mem); 14298 return BCM_E_INTERNAL; 14299 } 14300 } 14301 *old_vp = soc_mem_field32_get(unit, mem, 14302 &stm_entry, SOURCE_VPf); 14303 14304 rv = soc_mem_field32_modify(unit, mem, stm_idx, 14305 SOURCE_VPf, new_vp); 14306 if (BCM_FAILURE(rv)) { 14307 soc_mem_unlock(unit, mem); 14308 return rv; 14309 } 14310 } 14311 14312 soc_mem_unlock(unit, mem); 14313 break; 14314 case _BCM_MPLS_PORT_MATCH_TYPE_LABEL: 14315 case _BCM_MPLS_PORT_MATCH_TYPE_LABEL_PORT: 14316 match_trunk_id = mkey->trunk_id; 14317 match_modid = mkey->modid; 14318 match_port = mkey->port; 14319 match_label = mkey->match_label; 14320 14321 sal_memset(ment, 0, sizeof(uint32) * SOC_MAX_MEM_WORDS); 14322 mem = MPLS_ENTRYm; 14323 #if defined(BCM_TRIDENT3_SUPPORT) 14324 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 14325 soc_mem_field32_set(unit, mem, &ment, BASE_VALID_0f, 3); 14326 soc_mem_field32_set(unit, mem, &ment, BASE_VALID_1f, 7); 14327 } else 14328 #endif 14329 { 14330 soc_mem_field32_set(unit, mem, &ment, VALIDf, 1); 14331 } 14332 14333 if (match_trunk_id != -1) { 14334 soc_mem_field32_set(unit, mem, &ment, Tf, 1); 14335 soc_mem_field32_set(unit, mem, &ment, TGIDf, match_trunk_id); 14336 } else { 14337 soc_mem_field32_set(unit, mem, &ment, MODULE_IDf, match_modid); 14338 soc_mem_field32_set(unit, mem, &ment, PORT_NUMf, match_port); 14339 } 14340 14341 soc_mem_field32_set(unit, mem, &ment, MPLS_LABELf, match_label); 14342 soc_mem_lock(unit, mem); 14343 rv = soc_mem_search(unit, mem, MEM_BLOCK_ANY, 14344 &entry_index, &ment, &ment, 0); 14345 14346 if (rv == BCM_E_NOT_FOUND) { 14347 rv = BCM_E_PARAM; 14348 } 14349 14350 if (BCM_FAILURE(rv)) { 14351 soc_mem_unlock(unit, mem); 14352 return rv; 14353 } 14354 14355 /* Replace entry's VP value */ 14356 *old_vp = soc_mem_field32_get(unit, mem, &ment, SOURCE_VPf); 14357 soc_mem_field32_set(unit, mem, &ment, SOURCE_VPf, new_vp); 14358 /* Insert new entry */ 14359 rv = soc_mem_insert(unit, mem, MEM_BLOCK_ALL, ment); 14360 14361 soc_mem_unlock(unit, mem); 14362 14363 if (rv == SOC_E_EXISTS) { 14364 rv = BCM_E_NONE; 14365 } else { 14366 return BCM_E_INTERNAL; 14367 } 14368 break; 14369 case _BCM_MPLS_PORT_MATCH_TYPE_NONE: 14370 *old_vp = vp; 14371 break; 14372 default: 14373 return BCM_E_PARAM; 14374 } 14375 14376 #undef _BCM_VLXLT_KTYPE_ASSIGN 14377 14378 return rv; 14379 } 14380 14381 /* 14382 * Function: 14383 * bcm_td2_mpls_port_source_vp_lag_set 14384 * Purpose: 14385 * Set source vp LAG for a mpls virtual port. 14386 * Parameters: 14387 * unit - (IN) SOC unit number. 14388 * gport - (IN) mpls virtual port GPORT ID. 14389 * vp_lag_vp - (IN) VP representing the VP LAG. 14390 * Returns: 14391 * BCM_X_XXX 14392 */ 14393 int 14394 bcm_td2_mpls_port_source_vp_lag_set(int unit, bcm_gport_t gport, 14395 int vp_lag_vp) 14396 { 14397 int vp, old_vp; 14398 14399 if (!BCM_GPORT_IS_MPLS_PORT(gport)) { 14400 return BCM_E_PARAM; 14401 } 14402 vp = BCM_GPORT_MPLS_PORT_ID_GET(gport); 14403 if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeMpls)) { 14404 return BCM_E_PARAM; 14405 } 14406 14407 BCM_IF_ERROR_RETURN 14408 (_bcm_td2_mpls_match_vp_replace(unit, vp, vp_lag_vp, &old_vp)); 14409 14410 return BCM_E_NONE; 14411 } 14412 14413 /* 14414 * Function: 14415 * bcm_td2_mpls_port_source_vp_lag_clear 14416 * Purpose: 14417 * Clear source VP LAG for a mpls virtual port. 14418 * Parameters: 14419 * unit - (IN) SOC unit number. 14420 * gport - (IN) mpls virtual port GPORT ID. 14421 * vp_lag_vp - (IN) VP representing the VP LAG. 14422 * Returns: 14423 * BCM_X_XXX 14424 */ 14425 int 14426 bcm_td2_mpls_port_source_vp_lag_clear(int unit, bcm_gport_t gport, 14427 int vp_lag_vp) 14428 { 14429 int vp, old_vp; 14430 14431 if (!BCM_GPORT_IS_MPLS_PORT(gport)) { 14432 return BCM_E_PARAM; 14433 } 14434 vp = BCM_GPORT_MPLS_PORT_ID_GET(gport); 14435 if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeMpls)) { 14436 return BCM_E_PARAM; 14437 } 14438 14439 BCM_IF_ERROR_RETURN 14440 (_bcm_td2_mpls_match_vp_replace(unit, vp, vp, &old_vp)); 14441 14442 return BCM_E_NONE; 14443 } 14444 14445 /* 14446 * Function: 14447 * bcm_td2_mpls_port_source_vp_lag_get 14448 * Purpose: 14449 * Get source VP LAG for a mpls virtual port. 14450 * Parameters: 14451 * unit - (IN) SOC unit number. 14452 * gport - (IN) mpls virtual port GPORT ID. 14453 * vp_lag_vp - (OUT) VP representing the VP LAG. 14454 * Returns: 14455 * BCM_X_XXX 14456 */ 14457 int 14458 bcm_td2_mpls_port_source_vp_lag_get(int unit, bcm_gport_t gport, 14459 int *vp_lag_vp) 14460 { 14461 int rv = BCM_E_NONE; 14462 int key_type = bcmVlanTranslateKeyInvalid; 14463 int port = 0; 14464 int my_modid = 0; 14465 int stm_idx = 0; 14466 int entry_index = 0; 14467 int local_port[SOC_MAX_NUM_PORTS]; 14468 int local_port_count = 0; 14469 int match_trunk_id = 0; 14470 int match_modid = 0; 14471 int match_port = 0; 14472 soc_mem_t mem; 14473 bcm_gport_t vp; 14474 uint32 svp_valid; 14475 uint32 match_label; 14476 uint32 vent[SOC_MAX_MEM_WORDS]; 14477 uint32 ment[SOC_MAX_MEM_WORDS]; 14478 source_trunk_map_table_entry_t stm_entry; 14479 _bcm_tr_mpls_match_port_info_t *mkey = NULL; 14480 14481 if (!BCM_GPORT_IS_MPLS_PORT(gport)) { 14482 return BCM_E_PARAM; 14483 } 14484 14485 vp = BCM_GPORT_MPLS_PORT_ID_GET(gport); 14486 if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeMpls)) { 14487 return BCM_E_PARAM; 14488 } 14489 14490 mkey = &(MPLS_INFO(unit)->match_key[vp]); 14491 14492 #define _BCM_VLXLT_KTYPE_ASSIGN(_ktype, _k) \ 14493 do { \ 14494 if (_ktype == bcmVlanTranslateKeyInvalid) { \ 14495 _ktype = _k; \ 14496 } \ 14497 } while(0) 14498 14499 switch(mkey->flags) { 14500 case _BCM_MPLS_PORT_MATCH_TYPE_VLAN: 14501 _BCM_VLXLT_KTYPE_ASSIGN(key_type, bcmVlanTranslateKeyPortOuter); 14502 /* Fall through */ 14503 case _BCM_MPLS_PORT_MATCH_TYPE_INNER_VLAN: 14504 _BCM_VLXLT_KTYPE_ASSIGN(key_type, bcmVlanTranslateKeyPortInner); 14505 /* Fall through */ 14506 case _BCM_MPLS_PORT_MATCH_TYPE_VLAN_STACKED: 14507 _BCM_VLXLT_KTYPE_ASSIGN(key_type, bcmVlanTranslateKeyPortDouble); 14508 /* Fall through */ 14509 case _BCM_MPLS_PORT_MATCH_TYPE_VLAN_PRI: 14510 _BCM_VLXLT_KTYPE_ASSIGN(key_type, bcmVlanTranslateKeyPortOuterPri); 14511 14512 sal_memset(vent, 0, sizeof(uint32) * SOC_MAX_MEM_WORDS); 14513 #if defined(BCM_TRIDENT3_SUPPORT) 14514 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 14515 mem = VLAN_XLATE_1_DOUBLEm; 14516 14517 soc_mem_field32_set(unit, mem, vent, BASE_VALID_0f, 3); 14518 soc_mem_field32_set(unit, mem, vent, BASE_VALID_1f, 7); 14519 } else 14520 #endif 14521 { 14522 mem = VLAN_XLATEm; 14523 14524 soc_mem_field32_set(unit, mem, vent, VALIDf, 0x1); 14525 } 14526 14527 if (mkey->modid != -1) { 14528 BCM_GPORT_MODPORT_SET(port, mkey->modid, mkey->port); 14529 } else { 14530 BCM_GPORT_TRUNK_SET(port, mkey->trunk_id); 14531 } 14532 /* Construct lookup key */ 14533 BCM_IF_ERROR_RETURN( 14534 _bcm_trx_vlan_translate_entry_assemble(unit, vent, 14535 port, key_type, 14536 mkey->match_inner_vlan, 14537 mkey->match_vlan)); 14538 soc_mem_lock(unit, mem); 14539 /* Lookup existing entry */ 14540 rv = soc_mem_search(unit, mem, MEM_BLOCK_ALL, 14541 &entry_index, vent, vent, 0); 14542 soc_mem_unlock(unit, mem); 14543 if (BCM_FAILURE(rv)) { 14544 return rv; 14545 } 14546 /* Get VP value representing VP LAG */ 14547 *vp_lag_vp = soc_mem_field32_get(unit, mem, vent, SOURCE_VPf); 14548 break; 14549 case _BCM_MPLS_PORT_MATCH_TYPE_PORT: 14550 mem = SOURCE_TRUNK_MAP_TABLEm; 14551 14552 soc_mem_lock(unit, mem); 14553 14554 rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, 14555 mkey->index, &stm_entry); 14556 soc_mem_unlock(unit, mem); 14557 if (BCM_FAILURE(rv)) { 14558 return rv; 14559 } 14560 /* Resolve SVP Mode */ 14561 if (soc_mem_field_valid(unit, mem, SVP_VALIDf)) { 14562 svp_valid = soc_mem_field32_get(unit, mem, 14563 &stm_entry, SVP_VALIDf); 14564 if (svp_valid == 0) { 14565 return BCM_E_INTERNAL; 14566 } 14567 } 14568 /* Get VP value representing VP LAG */ 14569 *vp_lag_vp = soc_mem_field32_get(unit, mem, 14570 &stm_entry, SOURCE_VPf); 14571 break; 14572 case _BCM_MPLS_PORT_MATCH_TYPE_TRUNK: 14573 mem = SOURCE_TRUNK_MAP_TABLEm; 14574 14575 /* Get module id for unit. */ 14576 BCM_IF_ERROR_RETURN( 14577 bcm_esw_stk_my_modid_get(unit, &my_modid)); 14578 14579 BCM_IF_ERROR_RETURN( 14580 _bcm_esw_trunk_local_members_get(unit, mkey->trunk_id, 14581 SOC_MAX_NUM_PORTS, 14582 local_port, 14583 &local_port_count)); 14584 14585 /* Get index to source trunk map table, 14586 * Only get it from the first member in LAG 14587 */ 14588 rv = _bcm_esw_src_mod_port_table_index_get(unit, my_modid, 14589 local_port[0], 14590 &stm_idx); 14591 if (BCM_FAILURE(rv)) { 14592 return rv; 14593 } 14594 14595 soc_mem_lock(unit, mem); 14596 rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, 14597 stm_idx, &stm_entry); 14598 soc_mem_unlock(unit, mem); 14599 if (BCM_FAILURE(rv)) { 14600 return rv; 14601 } 14602 14603 /* Resolve SVP Mode */ 14604 if (soc_mem_field_valid(unit, mem, SVP_VALIDf)) { 14605 svp_valid = soc_mem_field32_get(unit, mem, 14606 &stm_entry, SVP_VALIDf); 14607 if (svp_valid == 0) { 14608 return BCM_E_INTERNAL; 14609 } 14610 } 14611 /* Get VP value representing VP LAG */ 14612 *vp_lag_vp = soc_mem_field32_get(unit, mem, 14613 &stm_entry, SOURCE_VPf); 14614 break; 14615 case _BCM_MPLS_PORT_MATCH_TYPE_LABEL: 14616 case _BCM_MPLS_PORT_MATCH_TYPE_LABEL_PORT: 14617 match_trunk_id = mkey->trunk_id; 14618 match_modid = mkey->modid; 14619 match_port = mkey->port; 14620 match_label = mkey->match_label; 14621 14622 sal_memset(ment, 0, sizeof(uint32) * SOC_MAX_MEM_WORDS); 14623 mem = MPLS_ENTRYm; 14624 #if defined(BCM_TRIDENT3_SUPPORT) 14625 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 14626 soc_mem_field32_set(unit, mem, &ment, BASE_VALID_0f, 3); 14627 soc_mem_field32_set(unit, mem, &ment, BASE_VALID_1f, 7); 14628 } else 14629 #endif 14630 { 14631 soc_mem_field32_set(unit, mem, &ment, VALIDf, 1); 14632 } 14633 14634 if (match_trunk_id != -1) { 14635 soc_mem_field32_set(unit, mem, &ment, Tf, 1); 14636 soc_mem_field32_set(unit, mem, &ment, TGIDf, match_trunk_id); 14637 } else { 14638 soc_mem_field32_set(unit, mem, &ment, MODULE_IDf, match_modid); 14639 soc_mem_field32_set(unit, mem, &ment, PORT_NUMf, match_port); 14640 } 14641 14642 soc_mem_field32_set(unit, mem, &ment, MPLS_LABELf, match_label); 14643 soc_mem_lock(unit, mem); 14644 rv = soc_mem_search(unit, mem, MEM_BLOCK_ANY, 14645 &entry_index, &ment, &ment, 0); 14646 14647 if (rv == BCM_E_NOT_FOUND) { 14648 rv = BCM_E_PARAM; 14649 } 14650 14651 soc_mem_unlock(unit, mem); 14652 if (BCM_FAILURE(rv)) { 14653 return rv; 14654 } 14655 14656 *vp_lag_vp = soc_mem_field32_get(unit, mem, &ment, SOURCE_VPf); 14657 break; 14658 default: 14659 return BCM_E_PARAM; 14660 } 14661 14662 #undef _BCM_VLXLT_KTYPE_ASSIGN 14663 14664 if (!_bcm_vp_used_get(unit, *vp_lag_vp, _bcmVpTypeVpLag)) { 14665 return BCM_E_INTERNAL; 14666 } 14667 14668 return BCM_E_NONE; 14669 } 14670 14671 /* 14672 * Function: 14673 * _bcm_td2_mpls_vplag_vp_update 14674 * Purpose: 14675 * Update vplag vp according to MPLS port 14676 * Parameters: 14677 * unit - (IN) Device Number 14678 * gport - (IN) MPLS port 14679 * Returns: 14680 * BCM_E_XXX 14681 */ 14682 STATIC int 14683 _bcm_td2_mpls_vplag_vp_update(int unit, bcm_gport_t gport) 14684 { 14685 int rv = 0; 14686 int vp = 0; 14687 int vplag_vp = 0; 14688 uint32 vfi = 0; 14689 uint32 network_port = 0; 14690 uint32 network_group = 0; 14691 uint32 tpid_enable = 0; 14692 uint32 sd_tag_mode = 0; 14693 source_vp_entry_t svp_entry; 14694 source_vp_entry_t svp_entry1; 14695 14696 rv = bcm_td2_mpls_port_source_vp_lag_get(unit, gport, &vplag_vp); 14697 if (BCM_SUCCESS(rv)) { 14698 vp = BCM_GPORT_MPLS_PORT_ID_GET(gport); 14699 BCM_IF_ERROR_RETURN(READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp, &svp_entry)); 14700 BCM_IF_ERROR_RETURN(READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vplag_vp, &svp_entry1)); 14701 14702 vfi = soc_SOURCE_VPm_field32_get(unit, &svp_entry, VFIf); 14703 sd_tag_mode = soc_SOURCE_VPm_field32_get(unit, &svp_entry, SD_TAG_MODEf); 14704 soc_SOURCE_VPm_field32_set(unit, &svp_entry1, VFIf, vfi); 14705 soc_SOURCE_VPm_field32_set(unit, &svp_entry1, SD_TAG_MODEf, sd_tag_mode); 14706 14707 if (soc_feature(unit, soc_feature_multiple_split_horizon_group)) { 14708 network_group = soc_SOURCE_VPm_field32_get(unit, &svp_entry, NETWORK_GROUPf); 14709 soc_SOURCE_VPm_field32_set(unit, &svp_entry1, NETWORK_GROUPf, network_group); 14710 } else { 14711 network_port = soc_SOURCE_VPm_field32_get(unit, &svp_entry, NETWORK_PORTf); 14712 soc_SOURCE_VPm_field32_set(unit, &svp_entry1, NETWORK_PORTf, network_port); 14713 } 14714 #if defined(BCM_TRIDENT3_SUPPORT) 14715 if (SOC_IS_TRIDENT3X(unit)) { 14716 uint32 svp1[SOC_MAX_MEM_WORDS]; 14717 uint32 svp2[SOC_MAX_MEM_WORDS]; 14718 BCM_IF_ERROR_RETURN(READ_SVP_ATTRS_1m(unit, MEM_BLOCK_ANY, vp, svp1)); 14719 BCM_IF_ERROR_RETURN(READ_SVP_ATTRS_1m(unit, MEM_BLOCK_ANY, vplag_vp, svp2)); 14720 soc_SVP_ATTRS_1m_field_get(unit, &svp1, TPID_ENABLEf, &tpid_enable); 14721 soc_SVP_ATTRS_1m_field_set(unit, &svp2, TPID_ENABLEf, &tpid_enable); 14722 BCM_IF_ERROR_RETURN(WRITE_SVP_ATTRS_1m(unit, MEM_BLOCK_ALL, vplag_vp, &svp2)); 14723 } else 14724 #endif 14725 { 14726 tpid_enable = soc_SOURCE_VPm_field32_get(unit, &svp_entry, TPID_ENABLEf); 14727 soc_SOURCE_VPm_field32_set(unit, &svp_entry1, TPID_ENABLEf, tpid_enable); 14728 } 14729 BCM_IF_ERROR_RETURN(WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, vplag_vp, &svp_entry1)); 14730 } 14731 14732 return BCM_E_NONE; 14733 } 14734 14735 #endif 14736 14737 /* 14738 * Function: 14739 * _bcm_tr_mpls_match_get 14740 * Purpose: 14741 * Obtain match information of an MPLS port 14742 * Parameters: 14743 * unit - (IN) Device Number 14744 * mpls_port - (OUT) mpls port information 14745 * vp - (IN) Source Virtual Port 14746 * Returns: 14747 * BCM_E_XXX 14748 */ 14749 14750 int 14751 _bcm_tr_mpls_match_get(int unit, bcm_mpls_port_t *mpls_port, int vp) 14752 { 14753 _bcm_tr_mpls_bookkeeping_t *mpls_info = MPLS_INFO(unit); 14754 int num_bits_for_port, rv = BCM_E_NONE; 14755 uint32 port_mask; 14756 bcm_module_t mod_in=0, mod_out; 14757 bcm_port_t port_in=0, port_out; 14758 bcm_trunk_t trunk_id=0; 14759 int src_trk_idx=0; /*Source Trunk table index.*/ 14760 int mode_in=0; /* Module_Id */ 14761 int vpless_failover_port = FALSE; /* the failover port without a dedicated vp */ 14762 int match_trunk_id; 14763 int match_modid; 14764 int match_port; 14765 14766 if (_BCM_MPLS_GPORT_FAILOVER_VPLESS_GET(vp)) { 14767 vp = _BCM_MPLS_GPORT_FAILOVER_VPLESS_CLEAR(vp); 14768 14769 if (!(mpls_info->match_key[vp].flags & 14770 _BCM_MPLS_PORT_MATCH_TYPE_LABEL)) { 14771 vpless_failover_port = TRUE; 14772 } 14773 } 14774 14775 if (vpless_failover_port == FALSE) { 14776 match_trunk_id = mpls_info->match_key[vp].trunk_id; 14777 match_modid = mpls_info->match_key[vp].modid; 14778 match_port = mpls_info->match_key[vp].port; 14779 } else { 14780 match_trunk_id = mpls_info->match_key[vp].fo_trunk_id; 14781 match_modid = mpls_info->match_key[vp].fo_modid; 14782 match_port = mpls_info->match_key[vp].fo_port; 14783 } 14784 14785 /* Get module id for unit. */ 14786 BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &mode_in)); 14787 14788 if (mpls_info->match_key[vp].flags & _BCM_MPLS_PORT_MATCH_TYPE_VLAN) { 14789 14790 mpls_port->criteria = BCM_MPLS_PORT_MATCH_PORT_VLAN; 14791 mpls_port->match_vlan = mpls_info->match_key[vp].match_vlan; 14792 14793 if (mpls_info->match_key[vp].trunk_id != -1) { 14794 trunk_id = mpls_info->match_key[vp].trunk_id; 14795 BCM_GPORT_TRUNK_SET(mpls_port->port, trunk_id); 14796 } else if (mpls_info->match_key[vp].modid != -1) { 14797 port_in = mpls_info->match_key[vp].port; 14798 mod_in = mpls_info->match_key[vp].modid; 14799 rv = _bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET, 14800 mod_in, port_in, &mod_out, &port_out); 14801 BCM_GPORT_MODPORT_SET(mpls_port->port, mod_out, port_out); 14802 } else { 14803 mpls_port->criteria = BCM_MPLS_PORT_MATCH_VLAN; 14804 } 14805 } else if (mpls_info->match_key[vp].flags & 14806 _BCM_MPLS_PORT_MATCH_TYPE_INNER_VLAN) { 14807 mpls_port->criteria = BCM_MPLS_PORT_MATCH_PORT_INNER_VLAN; 14808 mpls_port->match_inner_vlan = mpls_info->match_key[vp].match_inner_vlan; 14809 14810 if (mpls_info->match_key[vp].trunk_id != -1) { 14811 trunk_id = mpls_info->match_key[vp].trunk_id; 14812 BCM_GPORT_TRUNK_SET(mpls_port->port, trunk_id); 14813 } else { 14814 port_in = mpls_info->match_key[vp].port; 14815 mod_in = mpls_info->match_key[vp].modid; 14816 rv = _bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET, 14817 mod_in, port_in, &mod_out, &port_out); 14818 BCM_GPORT_MODPORT_SET(mpls_port->port, mod_out, port_out); 14819 } 14820 }else if (mpls_info->match_key[vp].flags & 14821 _BCM_MPLS_PORT_MATCH_TYPE_VLAN_STACKED) { 14822 14823 mpls_port->criteria = BCM_MPLS_PORT_MATCH_PORT_VLAN_STACKED; 14824 mpls_port->match_vlan = mpls_info->match_key[vp].match_vlan; 14825 mpls_port->match_inner_vlan = mpls_info->match_key[vp].match_inner_vlan; 14826 14827 if (mpls_info->match_key[vp].trunk_id != -1) { 14828 trunk_id = mpls_info->match_key[vp].trunk_id; 14829 BCM_GPORT_TRUNK_SET(mpls_port->port, trunk_id); 14830 } else { 14831 port_in = mpls_info->match_key[vp].port; 14832 mod_in = mpls_info->match_key[vp].modid; 14833 rv = _bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET, 14834 mod_in, port_in, &mod_out, &port_out); 14835 BCM_GPORT_MODPORT_SET(mpls_port->port, mod_out, port_out); 14836 } 14837 } else if (mpls_info->match_key[vp].flags & _BCM_MPLS_PORT_MATCH_TYPE_VLAN_PRI) { 14838 14839 mpls_port->criteria = BCM_MPLS_PORT_MATCH_VLAN_PRI; 14840 mpls_port->match_vlan = mpls_info->match_key[vp].match_vlan; 14841 14842 if (mpls_info->match_key[vp].trunk_id != -1) { 14843 trunk_id = mpls_info->match_key[vp].trunk_id; 14844 BCM_GPORT_TRUNK_SET(mpls_port->port, trunk_id); 14845 } else { 14846 port_in = mpls_info->match_key[vp].port; 14847 mod_in = mpls_info->match_key[vp].modid; 14848 rv = _bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET, 14849 mod_in, port_in, &mod_out, &port_out); 14850 BCM_GPORT_MODPORT_SET(mpls_port->port, mod_out, port_out); 14851 } 14852 } else if (mpls_info->match_key[vp].flags & 14853 _BCM_MPLS_PORT_MATCH_TYPE_VLAN_TAG) { 14854 14855 mpls_port->criteria = BCM_MPLS_PORT_MATCH_PORT_VLAN_TAG; 14856 mpls_port->match_vlan = mpls_info->match_key[vp].match_vlan; 14857 14858 if (mpls_info->match_key[vp].trunk_id != -1) { 14859 trunk_id = mpls_info->match_key[vp].trunk_id; 14860 BCM_GPORT_TRUNK_SET(mpls_port->port, trunk_id); 14861 } else { 14862 port_in = mpls_info->match_key[vp].port; 14863 mod_in = mpls_info->match_key[vp].modid; 14864 rv = _bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET, 14865 mod_in, port_in, &mod_out, &port_out); 14866 BCM_GPORT_MODPORT_SET(mpls_port->port, mod_out, port_out); 14867 } 14868 14869 } else if (mpls_info->match_key[vp].flags & 14870 _BCM_MPLS_PORT_MATCH_TYPE_INNER_VLAN_TAG) { 14871 14872 mpls_port->criteria = BCM_MPLS_PORT_MATCH_PORT_INNER_VLAN_TAG; 14873 mpls_port->match_inner_vlan = mpls_info->match_key[vp].match_inner_vlan; 14874 14875 if (mpls_info->match_key[vp].trunk_id != -1) { 14876 trunk_id = mpls_info->match_key[vp].trunk_id; 14877 BCM_GPORT_TRUNK_SET(mpls_port->port, trunk_id); 14878 } else { 14879 port_in = mpls_info->match_key[vp].port; 14880 mod_in = mpls_info->match_key[vp].modid; 14881 rv = _bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET, 14882 mod_in, port_in, &mod_out, &port_out); 14883 BCM_GPORT_MODPORT_SET(mpls_port->port, mod_out, port_out); 14884 } 14885 14886 } else if (mpls_info->match_key[vp].flags & 14887 _BCM_MPLS_PORT_MATCH_TYPE_PORT) { 14888 14889 src_trk_idx = mpls_info->match_key[vp].index; 14890 14891 if (soc_feature(unit, soc_feature_src_modid_base_index)) { 14892 source_trunk_map_modbase_entry_t modbase_entry; 14893 14894 BCM_IF_ERROR_RETURN 14895 (soc_mem_read(unit, SOURCE_TRUNK_MAP_MODBASEm, 14896 MEM_BLOCK_ANY, mode_in, &modbase_entry)); 14897 port_in = src_trk_idx - soc_mem_field32_get(unit, 14898 SOURCE_TRUNK_MAP_MODBASEm, 14899 &modbase_entry, BASEf); 14900 } else { 14901 num_bits_for_port = 14902 _shr_popcount((unsigned int)SOC_PORT_ADDR_MAX(unit)); 14903 port_mask = (1 << num_bits_for_port) - 1; 14904 14905 port_in = src_trk_idx & port_mask; 14906 mod_in = src_trk_idx >> num_bits_for_port; 14907 } 14908 14909 mpls_port->criteria = BCM_MPLS_PORT_MATCH_PORT; 14910 rv = _bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET, 14911 mod_in, port_in, &mod_out, &port_out); 14912 BCM_GPORT_MODPORT_SET(mpls_port->port, mod_out, port_out); 14913 }else if (mpls_info->match_key[vp].flags & 14914 _BCM_MPLS_PORT_MATCH_TYPE_TRUNK) { 14915 14916 trunk_id = mpls_info->match_key[vp].trunk_id; 14917 mpls_port->criteria = BCM_MPLS_PORT_MATCH_PORT; 14918 BCM_GPORT_TRUNK_SET(mpls_port->port, trunk_id); 14919 } else if ((mpls_info->match_key[vp].flags & 14920 _BCM_MPLS_PORT_MATCH_TYPE_LABEL) || 14921 (mpls_info->match_key[vp].flags == 14922 _BCM_MPLS_PORT_MATCH_TYPE_LABEL_PORT)) { 14923 mpls_entry_entry_t ment, ret_ment; 14924 14925 sal_memset(&ment, 0, sizeof(mpls_entry_entry_t)); 14926 sal_memset(&ret_ment, 0, sizeof(mpls_entry_entry_t)); 14927 14928 if (mpls_info->match_key[vp].flags & 14929 _BCM_MPLS_PORT_MATCH_TYPE_LABEL) { 14930 mpls_port->criteria = BCM_MPLS_PORT_MATCH_LABEL; 14931 } else if (mpls_info->match_key[vp].flags & 14932 _BCM_MPLS_PORT_MATCH_TYPE_LABEL_PORT) { 14933 mpls_port->criteria = BCM_MPLS_PORT_MATCH_LABEL_PORT; 14934 } 14935 mpls_port->match_label = mpls_info->match_key[vp].match_label; 14936 14937 if (match_trunk_id != -1) { 14938 trunk_id = match_trunk_id; 14939 soc_MPLS_ENTRYm_field32_set(unit, &ment, Tf, 1); 14940 soc_MPLS_ENTRYm_field32_set(unit, &ment, TGIDf, trunk_id); 14941 BCM_GPORT_TRUNK_SET(mpls_port->port, trunk_id); 14942 } else { 14943 mod_in = match_modid; 14944 port_in = match_port; 14945 soc_MPLS_ENTRYm_field32_set(unit, &ment, MODULE_IDf, mod_in); 14946 soc_MPLS_ENTRYm_field32_set(unit, &ment, PORT_NUMf, port_in); 14947 14948 BCM_IF_ERROR_RETURN(_bcm_esw_stk_modmap_map(unit, 14949 BCM_STK_MODMAP_GET, mod_in, port_in, 14950 &mod_out, &port_out)); 14951 BCM_GPORT_MODPORT_SET(mpls_port->port, mod_out, port_out); 14952 } 14953 soc_MPLS_ENTRYm_field32_set(unit, &ment, MPLS_LABELf, 14954 mpls_info->match_key[vp].match_label); 14955 14956 rv = soc_mem_search(unit, MPLS_ENTRYm, MEM_BLOCK_ANY, &src_trk_idx, 14957 &ment, &ret_ment, 0); 14958 14959 if (rv == SOC_E_NONE) { 14960 if (soc_MPLS_ENTRYm_field32_get(unit, &ret_ment, 14961 CW_CHECK_CTRLf) == 0x3) { 14962 14963 /* Control word is present, and check sequence number */ 14964 mpls_port->flags |= BCM_MPLS_PORT_SEQUENCED; 14965 } else if (soc_MPLS_ENTRYm_field32_get(unit, &ret_ment, 14966 CW_CHECK_CTRLf) == 0x1) { 14967 mpls_port->flags |= BCM_MPLS_PORT_CONTROL_WORD; 14968 } 14969 14970 if (soc_MPLS_ENTRYm_field32_get(unit, &ret_ment, PW_TERM_NUM_VALIDf)) { 14971 mpls_port->flags |= BCM_MPLS_PORT_COUNTED; 14972 } 14973 14974 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 14975 else if (SOC_MEM_FIELD_VALID(unit, MPLS_ENTRYm, CLASS_IDf)) { 14976 mpls_port->class_id = soc_MPLS_ENTRYm_field32_get(unit, &ret_ment, 14977 CLASS_IDf); 14978 } 14979 #endif 14980 14981 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIDENT2_SUPPORT) 14982 if (soc_feature(unit, soc_feature_mpls_entropy)) { 14983 if (soc_MPLS_ENTRYm_field32_get(unit, &ret_ment, ENTROPY_LABEL_PRESENTf)) { 14984 mpls_port->flags2 |= BCM_MPLS_PORT2_INGRESS_ENTROPY_ENABLE; 14985 } 14986 } 14987 /* VCCV defines 3 control-channels */ 14988 if (soc_mem_field_valid(unit, MPLS_ENTRYm, PW_CC_TYPEf)) { 14989 mpls_port->vccv_type = soc_MPLS_ENTRYm_field32_get(unit, 14990 &ret_ment, PW_CC_TYPEf); 14991 } 14992 #endif /* defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIDENT2PLUS_SUPPORT_SUPPORT) */ 14993 if (soc_MPLS_ENTRYm_field32_get(unit, &ret_ment, 14994 DECAP_USE_EXP_FOR_PRIf) == 0x1) { 14995 /* MAP_PRI_AND_CNG */ 14996 /* Use specified EXP-map to determine internal prio/color */ 14997 mpls_port->exp_map = 14998 soc_MPLS_ENTRYm_field32_get(unit, &ret_ment, EXP_MAPPING_PTRf); 14999 mpls_port->exp_map |= _BCM_TR_MPLS_EXP_MAP_TABLE_TYPE_INGRESS; 15000 mpls_port->flags |= BCM_MPLS_PORT_INT_PRI_MAP; 15001 } else if (soc_MPLS_ENTRYm_field32_get(unit, &ret_ment, 15002 DECAP_USE_EXP_FOR_PRIf) == 0x2) { 15003 /* NEW_PRI_MAP_CNG */ 15004 /* Use the specified internal priority value */ 15005 mpls_port->int_pri = 15006 soc_MPLS_ENTRYm_field32_get(unit, &ret_ment, NEW_PRIf); 15007 mpls_port->flags |= BCM_MPLS_PORT_INT_PRI_SET; 15008 15009 /* Use specified EXP-map to determine internal color */ 15010 mpls_port->exp_map = 15011 soc_MPLS_ENTRYm_field32_get(unit, &ret_ment, EXP_MAPPING_PTRf); 15012 mpls_port->exp_map |= _BCM_TR_MPLS_EXP_MAP_TABLE_TYPE_INGRESS; 15013 mpls_port->flags |= BCM_MPLS_PORT_COLOR_MAP; 15014 } else { 15015 if (soc_mem_field_valid(unit, MPLS_ENTRYm, 15016 TRUST_OUTER_DOT1P_PTRf)) { 15017 if (soc_MPLS_ENTRYm_field32_get(unit, &ret_ment, 15018 TRUST_OUTER_DOT1P_PTRf) == 15019 _BCM_TR_MPLS_PRI_CNG_MAP_NONE) { 15020 /* 15021 * Don't trust the encapsulated packet's 802.1p pri/cfi. 15022 * Use a fixed value for internal priority. 15023 */ 15024 mpls_port->int_pri = 15025 soc_MPLS_ENTRYm_field32_get(unit, &ret_ment, NEW_PRIf); 15026 mpls_port->flags |= BCM_MPLS_PORT_INT_PRI_SET; 15027 } 15028 } 15029 } 15030 } 15031 #if defined(BCM_TOMAHAWK2_SUPPORT) || defined(BCM_TRIDENT3_SUPPORT) 15032 if (soc_feature(unit, soc_feature_mpls_ecn)) { 15033 int ecn_map_id; 15034 int ecn_map_hw_idx; 15035 int ret; 15036 #if defined(BCM_TRIDENT3_SUPPORT) 15037 if(soc_feature(unit, soc_feature_td3_style_mpls)) { 15038 ecn_map_hw_idx = soc_MPLS_ENTRYm_field32_get(unit, &ret_ment, 15039 EXP_TO_ECN_MAPPING_PTRf); 15040 } else 15041 #endif 15042 { 15043 ecn_map_hw_idx = soc_MPLS_ENTRYm_field32_get(unit, &ret_ment, 15044 EXP_TO_IP_ECN_MAPPING_PTRf); 15045 } 15046 ret = bcmi_ecn_map_hw_idx2id(unit, ecn_map_hw_idx, 15047 _BCM_XGS5_MPLS_ECN_MAP_TYPE_EXP2ECN, 15048 &ecn_map_id); 15049 if (BCM_SUCCESS(ret)) { 15050 mpls_port->flags2 |= BCM_MPLS_PORT2_INGRESS_ECN_MAP; 15051 mpls_port->ecn_map_id = ecn_map_id; 15052 } 15053 } 15054 #endif 15055 } else if (mpls_info->match_key[vp].flags & _BCM_MPLS_PORT_MATCH_TYPE_SHARE) { 15056 mpls_port->criteria = BCM_MPLS_PORT_MATCH_SHARE; 15057 } else { 15058 mpls_port->criteria = BCM_MPLS_PORT_MATCH_NONE; 15059 } 15060 return rv; 15061 } 15062 15063 /* 15064 * Function: 15065 * _bcm_tr_mpls_nh_drop 15066 * Purpose: 15067 * Set MPLS Next-Hop based Drop setting 15068 * Parameters: 15069 * unit - (IN) Device Number 15070 * drop - (IN) Drop setting 15071 * Returns: 15072 * BCM_E_XXX 15073 */ 15074 int 15075 _bcm_tr_mpls_nh_drop(int unit, int vp, int drop) 15076 { 15077 int nh_index; 15078 ing_dvp_table_entry_t dvp; 15079 15080 BCM_IF_ERROR_RETURN (READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp, &dvp)); 15081 nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, NEXT_HOP_INDEXf); 15082 return soc_mem_field32_modify(unit, ING_L3_NEXT_HOPm, nh_index, DROPf, drop); 15083 } 15084 15085 /* 15086 * Function: 15087 * _bcm_tr_mpls_l2vpn_source_port_set 15088 * Purpose: 15089 * Set L2 VPN source Modid/port 15090 * Parameters: 15091 * unit - (IN) Device Number 15092 * mpls_port - (IN) MPLS port 15093 * Returns: 15094 * BCM_E_XXX 15095 */ 15096 STATIC int 15097 _bcm_tr_mpls_l2vpn_source_port_set(int unit, bcm_mpls_port_t *mpls_port, source_vp_entry_t *svp) 15098 { 15099 int rv = BCM_E_NONE, gport_id; 15100 bcm_module_t mod_in; 15101 bcm_port_t port_in; 15102 bcm_trunk_t trunk_id; 15103 15104 rv = _bcm_esw_gport_resolve(unit, mpls_port->mpls_port_id, &mod_in, 15105 &port_in, &trunk_id, &gport_id); 15106 BCM_IF_ERROR_RETURN(rv); 15107 if (mod_in != -1) { 15108 soc_SOURCE_VPm_field32_set(unit, svp, SRC_MODIDf, mod_in); 15109 } 15110 if (port_in != -1) { 15111 soc_SOURCE_VPm_field32_set(unit, svp, SRC_PORTf, port_in); 15112 } 15113 return rv; 15114 } 15115 15116 /* 15117 * Function: 15118 * bcmi_mpls_clear_mpls_entry_for_vp 15119 * Purpose: 15120 * This function checks whether to clear MPLS entry for 15121 * this vpws vp. THis could be a backup port so 15122 * we may not need to clean the entry as entry should be cleaned 15123 * only when primary port is removed. 15124 * Parameters: 15125 * unit - (IN) Device Number 15126 * vpn - (IN) vpn 15127 * vp - (IN) virtual port 15128 * Returns: 15129 * TRUE/FALSE 15130 */ 15131 int 15132 bcmi_mpls_clear_mpls_entry_for_vp(int unit, bcm_vpn_t vpn, int vp) 15133 { 15134 15135 _bcm_tr_mpls_bookkeeping_t *mpls_info = MPLS_INFO(unit); 15136 int max_vpws_vpn, num_vp; 15137 15138 num_vp = soc_mem_index_count(unit, SOURCE_VPm); 15139 max_vpws_vpn = num_vp / 2; 15140 15141 if (vpn <= max_vpws_vpn) { 15142 /* if vp3 port is not valid then vp2 could be a primary port */ 15143 if (mpls_info->vpws_vp_map[vpn].vp3 == -1) { 15144 /* if vp3 in invalid and vp2 is valid then vp2 is 15145 first backup port to be created so we should 15146 remove the mpls entry. 15147 For all others we should not remove the mpls 15148 label entry. 15149 */ 15150 if (mpls_info->vpws_vp_map[vpn].vp2 == vp) { 15151 return 0; 15152 } else { 15153 return 1; 15154 } 15155 } else { 15156 if ((mpls_info->vpws_vp_map[vpn].vp2 == vp) && 15157 (sal_memcmp(&mpls_info->match_key[vp], 15158 &mpls_info->match_key[mpls_info->vpws_vp_map[vpn].vp3], 15159 sizeof(_bcm_tr_mpls_match_port_info_t)))) { 15160 return 0; 15161 } else { 15162 return 1; 15163 } 15164 } 15165 } 15166 return 0; 15167 } 15168 15169 /* 15170 * Function: 15171 * _bcm_tr_mpls_vpws_vp_map_backup_port_clear 15172 * Purpose: 15173 * Clear VPWS VPN member Virtual backup ports 15174 * Parameters: 15175 * unit - (IN) Device Number 15176 * vpn - (IN) VPN instance ID 15177 * vp - (IN) Network Virtual Port 15178 * Returns: 15179 * void 15180 */ 15181 STATIC void 15182 _bcm_tr_mpls_vpws_vp_map_backup_port_clear(int unit, bcm_vpn_t vpn, int vp) 15183 { 15184 _bcm_tr_mpls_bookkeeping_t *mpls_info = MPLS_INFO(unit); 15185 int max_vpws_vpn, num_vp; 15186 15187 num_vp = soc_mem_index_count(unit, SOURCE_VPm); 15188 max_vpws_vpn = num_vp / 2; 15189 15190 if (vpn <= max_vpws_vpn) { 15191 15192 if (mpls_info->vpws_vp_map[vpn].vp_b_1 == vp) { 15193 (void) _bcm_vp_free(unit, _bcmVpTypeMpls, 1, 15194 mpls_info->vpws_vp_map[vpn].vp_b_1 ); 15195 mpls_info->vpws_vp_map[vpn].vp_b_1 = -1; 15196 } else if ( mpls_info->vpws_vp_map[vpn].vp_b_2 == vp) { 15197 (void) _bcm_vp_free(unit, _bcmVpTypeMpls, 1, 15198 mpls_info->vpws_vp_map[vpn].vp_b_2 ); 15199 mpls_info->vpws_vp_map[vpn].vp_b_2 = -1; 15200 } else if ( mpls_info->vpws_vp_map[vpn].vp_b_3 == vp) { 15201 (void) _bcm_vp_free(unit, _bcmVpTypeMpls, 1, 15202 mpls_info->vpws_vp_map[vpn].vp_b_3 ); 15203 mpls_info->vpws_vp_map[vpn].vp_b_3 = -1; 15204 } else if(mpls_info->vpws_vp_map[vpn].vp2 == vp) { 15205 (void) _bcm_vp_free(unit, _bcmVpTypeMpls, 1, 15206 mpls_info->vpws_vp_map[vpn].vp2); 15207 mpls_info->vpws_vp_map[vpn].vp2 = -1; 15208 } 15209 } 15210 } 15211 15212 /* 15213 * Function: 15214 * bcmi_mpls_port_failover_update_is_required 15215 * Purpose: 15216 * Check if update to failover entry is required at this nh index. 15217 * Parameters: 15218 * unit - (IN) Device Number 15219 * mpls_port - (IN) Mpls Port Id 15220 * primary_nh_index - (IN) primary next hop index 15221 * nh_index - (IN) next hop index 15222 * Returns: 15223 * TRUE/FALSE 15224 */ 15225 int 15226 bcmi_mpls_port_failover_update_is_required(int unit, bcm_mpls_port_t *mpls_port, 15227 bcm_if_t primary_nh_index, bcm_if_t nh_index) 15228 { 15229 15230 if (_BCM_FAILOVER_IS_MULTI_LEVEL(mpls_port->failover_id)) { 15231 /* in case of multicast group, we need to create entry */ 15232 if (mpls_port->failover_mc_group > 1) { 15233 return 1; 15234 } 15235 /* 15236 * if backup nh index is next to primary then create entry. 15237 * Also make sure that primary nh is start of nh chain. 15238 */ 15239 if (((primary_nh_index+1) == nh_index) && 15240 (bcmi_l3_nh_multi_count_get(unit, primary_nh_index) == 4)) { 15241 return 1; 15242 } 15243 /* 15244 * if we are adding a backup port where primary is not in same chain 15245 * then backup will have chain of 4. this is case where we have 15246 * one separate primary and 4 other backup ports. 15247 * In this case, primary nh will point to double wide prot entry 15248 * and should have a chain of 2 nhs. 15249 */ 15250 if ((bcmi_l3_nh_multi_count_get(unit, nh_index) == 4) && 15251 ((bcmi_l3_nh_multi_count_get(unit, primary_nh_index) == 2))) { 15252 return 1; 15253 } else { 15254 return 0; 15255 } 15256 } 15257 return 1; 15258 } 15259 15260 /* 15261 * Function: 15262 * _bcm_tr_mpls_vpws_vp_map_set 15263 * Purpose: 15264 * Set VPWS VPN member Virtual ports 15265 * Parameters: 15266 * unit - (IN) Device Number 15267 * vpn - (IN) VPN instance ID 15268 * vp1 - (IN) Access Virtual Port 15269 * vp2 - (IN) Network Virtual Port 15270 * vp3 - (IN) Primary Network VPort 15271 * Returns: 15272 * BCM_E_XXX 15273 */ 15274 STATIC void 15275 _bcm_tr_mpls_vpws_vp_map_set (int unit, bcm_vpn_t vpn, int vp1, int vp2, 15276 int vp3) 15277 { 15278 _bcm_tr_mpls_bookkeeping_t *mpls_info = MPLS_INFO(unit); 15279 int max_vpws_vpn, num_vp; 15280 15281 num_vp = soc_mem_index_count(unit, SOURCE_VPm); 15282 max_vpws_vpn = num_vp / 2; 15283 15284 if ( vpn <= max_vpws_vpn ) { 15285 mpls_info->vpws_vp_map[vpn].vp1 = vp1; 15286 mpls_info->vpws_vp_map[vpn].vp2 = vp2; 15287 mpls_info->vpws_vp_map[vpn].vp3 = vp3; 15288 } 15289 } 15290 15291 /* 15292 * Function: 15293 * bcmi_mpls_vpws_vp_map_backup_port_set 15294 * Purpose: 15295 * Set VPWS VPN member Virtual backup ports 15296 * Parameters: 15297 * unit - (IN) Device Number 15298 * vpn - (IN) VPN instance ID 15299 * vp - (IN) Network Virtual Port 15300 * Returns: 15301 * BCM_E_XXX 15302 */ 15303 STATIC int 15304 bcmi_mpls_vpws_vp_map_backup_port_set(int unit, bcm_vpn_t vpn, int vp) 15305 { 15306 _bcm_tr_mpls_bookkeeping_t *mpls_info = MPLS_INFO(unit); 15307 int max_vpws_vpn, num_vp; 15308 if (!(soc_feature(unit, soc_feature_hierarchical_protection))) { 15309 return BCM_E_NONE; 15310 } 15311 15312 num_vp = soc_mem_index_count(unit, SOURCE_VPm); 15313 max_vpws_vpn = num_vp / 2; 15314 15315 if (vpn <= max_vpws_vpn) { 15316 if (mpls_info->vpws_vp_map[vpn].vp_b_1 == -1) { 15317 mpls_info->vpws_vp_map[vpn].vp_b_1 = vp; 15318 } else if ( mpls_info->vpws_vp_map[vpn].vp_b_2 == -1) { 15319 mpls_info->vpws_vp_map[vpn].vp_b_2 = vp; 15320 } else if ( mpls_info->vpws_vp_map[vpn].vp_b_3 == -1) { 15321 mpls_info->vpws_vp_map[vpn].vp_b_3 = vp; 15322 } else { 15323 return BCM_E_CONFIG; 15324 } 15325 } 15326 return BCM_E_NONE; 15327 } 15328 15329 /* 15330 * Function: 15331 * bcmi_mpls_match_backup_ports 15332 * Purpose: 15333 * Match a virtual port in VPWS VPN member Virtual backup ports 15334 * Parameters: 15335 * unit - (IN) Device Number 15336 * vpn - (IN) VPN instance ID 15337 * vp - (IN) Network Virtual Port 15338 * Returns: 15339 * BCM_E_XXX 15340 */ 15341 STATIC int 15342 bcmi_mpls_match_backup_ports(int unit, bcm_vpn_t vpn, int vp) 15343 { 15344 _bcm_tr_mpls_bookkeeping_t *mpls_info = MPLS_INFO(unit); 15345 int max_vpws_vpn, num_vp; 15346 15347 if (!(soc_feature(unit, soc_feature_hierarchical_protection))) { 15348 return 0; 15349 } 15350 15351 num_vp = soc_mem_index_count(unit, SOURCE_VPm); 15352 max_vpws_vpn = num_vp / 2; 15353 15354 if (vpn <= max_vpws_vpn) { 15355 if ((mpls_info->vpws_vp_map[vpn].vp_b_1 == vp) || 15356 (mpls_info->vpws_vp_map[vpn].vp_b_2 == vp) || 15357 ( mpls_info->vpws_vp_map[vpn].vp_b_3 == vp)) { 15358 return 1; 15359 } 15360 } 15361 return 0; 15362 } 15363 15364 /* 15365 * Function: 15366 * bcmi_mpls_update_backup_svp 15367 * Purpose: 15368 * Update source vp for a backup port. 15369 * Parameters: 15370 * unit - (IN) Device Number 15371 * vp - (IN) source virtual port 15372 * dvp - (IN) Destination Virtual Port 15373 * Returns: 15374 * BCM_E_XXX 15375 */ 15376 STATIC int 15377 bcmi_mpls_update_backup_svp(int unit, int vp, int dvp) 15378 { 15379 source_vp_entry_t svp; 15380 15381 BCM_IF_ERROR_RETURN(READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp, &svp)); 15382 if (soc_feature(unit, soc_feature_generic_dest)) { 15383 soc_mem_field32_dest_set(unit, SOURCE_VPm, &svp, 15384 DESTINATIONf, SOC_MEM_FIF_DEST_DVP, dvp); 15385 } else { 15386 soc_SOURCE_VPm_field32_set(unit, &svp, DVPf, dvp); 15387 } 15388 BCM_IF_ERROR_RETURN(WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, vp, &svp)); 15389 15390 return BCM_E_NONE; 15391 } 15392 15393 /* 15394 * Function: 15395 * bcmi_mpls_update_dvp_in_backup_ports 15396 * Purpose: 15397 * Update destination vp for a matching backup port. 15398 * Parameters: 15399 * unit - (IN) Device Number 15400 * vpn - (IN) VPN instance ID 15401 * dvp - (IN) Destination Virtual Port 15402 * Returns: 15403 * BCM_E_XXX 15404 */ 15405 STATIC int 15406 bcmi_mpls_update_dvp_in_backup_ports(int unit, bcm_vpn_t vpn, int uni_vp) 15407 { 15408 _bcm_tr_mpls_bookkeeping_t *mpls_info = MPLS_INFO(unit); 15409 int max_vpws_vpn, num_vp; 15410 15411 if (!(soc_feature(unit, soc_feature_hierarchical_protection))) { 15412 return BCM_E_NONE; 15413 } 15414 15415 num_vp = soc_mem_index_count(unit, SOURCE_VPm); 15416 max_vpws_vpn = num_vp / 2; 15417 15418 if (uni_vp == -1) { 15419 /* clearing the dvp from entry */ 15420 uni_vp = 0; 15421 } 15422 15423 if (vpn <= max_vpws_vpn) { 15424 if (mpls_info->vpws_vp_map[vpn].vp_b_1 != -1) { 15425 BCM_IF_ERROR_RETURN(bcmi_mpls_update_backup_svp(unit, 15426 mpls_info->vpws_vp_map[vpn].vp_b_1, uni_vp)); 15427 } 15428 15429 if (mpls_info->vpws_vp_map[vpn].vp_b_2 != -1) { 15430 BCM_IF_ERROR_RETURN(bcmi_mpls_update_backup_svp(unit, 15431 mpls_info->vpws_vp_map[vpn].vp_b_2, uni_vp)); 15432 } 15433 15434 if (mpls_info->vpws_vp_map[vpn].vp_b_3 != -1) { 15435 BCM_IF_ERROR_RETURN(bcmi_mpls_update_backup_svp(unit, 15436 mpls_info->vpws_vp_map[vpn].vp_b_3, uni_vp)); 15437 } 15438 15439 } 15440 return BCM_E_NONE; 15441 } 15442 15443 STATIC int 15444 bcmi_mpls_failover_nhi_cleanup_check(int unit, bcm_vpn_t vpn, int incoming_vp, 15445 bcm_failover_t failover_id, 15446 bcm_if_t failover_nh_index, 15447 bcm_if_t primary_nh_index, 15448 bcm_if_t nh_index, int *cleanup) 15449 { 15450 15451 uint32 vfi, vp; 15452 source_vp_entry_t svp; 15453 egr_l3_next_hop_entry_t egr_nh; 15454 int i, base_nh_index; 15455 15456 if (_BCM_FAILOVER_IS_MULTI_LEVEL(failover_id)) { 15457 /* if the primary index is the base index of multi level group, 15458 * then its failover port should should have next nh index. 15459 */ 15460 if ((primary_nh_index + 1) == failover_nh_index) { 15461 base_nh_index = primary_nh_index; 15462 } else { 15463 base_nh_index = failover_nh_index; 15464 } 15465 15466 /* 15467 * in case of multi level failover, all the backup links 15468 * have to be in consecutive order. 15469 * therefore we can check if this incoming NH is part of 15470 * that group and vp on it is valid. 15471 */ 15472 for (i=0 ; i<4; i++) { 15473 BCM_IF_ERROR_RETURN (soc_mem_read(unit, EGR_L3_NEXT_HOPm, 15474 MEM_BLOCK_ANY, base_nh_index + i, &egr_nh)); 15475 /* 15476 * Reading dvp here and reading svp. we keep 15477 * svp and dvp same for a particular flow. 15478 */ 15479 if (soc_feature(unit, soc_feature_mpls_enhanced)) { 15480 vp = soc_EGR_L3_NEXT_HOPm_field32_get(unit, 15481 &egr_nh, MPLS__DVPf); 15482 } else { 15483 vp = soc_EGR_L3_NEXT_HOPm_field32_get(unit, 15484 &egr_nh, DVPf); 15485 } 15486 15487 /* Check for the validity of the VP */ 15488 if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeMpls)) { 15489 continue; 15490 } 15491 15492 /* 15493 * we should have some other port than incoming to see 15494 * if we want to delete the failover entry. 15495 */ 15496 if (vp == incoming_vp) { 15497 continue; 15498 } 15499 _BCM_MPLS_VPN_GET(vfi, _BCM_MPLS_VPN_TYPE_VPLS, vpn); 15500 BCM_IF_ERROR_RETURN(READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp, &svp)); 15501 if ((soc_SOURCE_VPm_field32_get 15502 (unit, &svp, ENTRY_TYPEf) != 0x1) || 15503 (vfi != soc_SOURCE_VPm_field32_get(unit, &svp, VFIf))) { 15504 15505 continue; 15506 } 15507 /* if the incoming NH is in the range of multi 15508 * level failover NH group then cleanup is not required. 15509 */ 15510 if ((nh_index > base_nh_index) && 15511 (nh_index < (base_nh_index + 4))) { 15512 *cleanup = 0; 15513 } 15514 } 15515 } else { 15516 if (failover_nh_index == nh_index) { 15517 *cleanup = 1; 15518 } else { 15519 *cleanup = 0; 15520 } 15521 } 15522 return BCM_E_NONE; 15523 } 15524 15525 /* 15526 * Function: 15527 * _bcm_tr_mpls_vpws_vp_map_get 15528 * Purpose: 15529 * Get VPWS VPN member Virtual ports 15530 * Parameters: 15531 * unit - (IN) Device Number 15532 * vpn - (IN) VPN instance ID 15533 * vp1 - (OUT) Access Virtual Port 15534 * vp2 - (OUT) Network Virtual Port 15535 * vp3 - (OUT) Primary Network VPort. 15536 * Returns: 15537 * BCM_E_XXX 15538 */ 15539 15540 STATIC void 15541 _bcm_tr_mpls_vpws_vp_map_get (int unit, bcm_vpn_t vpn, int *vp1, int *vp2, 15542 int *vp3) 15543 { 15544 _bcm_tr_mpls_bookkeeping_t *mpls_info = MPLS_INFO(unit); 15545 int max_vpws_vpn, num_vp; 15546 15547 num_vp = soc_mem_index_count(unit, SOURCE_VPm); 15548 max_vpws_vpn = num_vp / 2; 15549 15550 if ( vpn <= max_vpws_vpn ) { 15551 *vp1 = mpls_info->vpws_vp_map[vpn].vp1; 15552 *vp2 = mpls_info->vpws_vp_map[vpn].vp2; 15553 *vp3 = mpls_info->vpws_vp_map[vpn].vp3; 15554 } 15555 } 15556 15557 /* 15558 * Function: 15559 * _bcm_tr_mpls_vpws_vp_map_get 15560 * Purpose: 15561 * Clear VPWS VPN member Virtual ports 15562 * Parameters: 15563 * unit - (IN) Device Number 15564 * vpn - (IN) VPN instance ID 15565 * Returns: 15566 * BCM_E_XXX 15567 */ 15568 15569 STATIC void 15570 _bcm_tr_mpls_vpws_vp_map_clear (int unit, bcm_vpn_t vpn) 15571 { 15572 _bcm_tr_mpls_bookkeeping_t *mpls_info = MPLS_INFO(unit); 15573 int max_vpws_vpn, num_vp; 15574 15575 num_vp = soc_mem_index_count(unit, SOURCE_VPm); 15576 max_vpws_vpn = num_vp / 2; 15577 15578 if ( vpn <= max_vpws_vpn ) { 15579 if (mpls_info->vpws_vp_map[vpn].vp1 != -1) { 15580 (void) _bcm_vp_free(unit, _bcmVpTypeMpls, 1, mpls_info->vpws_vp_map[vpn].vp1 ); 15581 mpls_info->vpws_vp_map[vpn].vp1 = -1; 15582 } 15583 if (mpls_info->vpws_vp_map[vpn].vp2 != -1) { 15584 (void) _bcm_vp_free(unit, _bcmVpTypeMpls, 1, mpls_info->vpws_vp_map[vpn].vp2 ); 15585 mpls_info->vpws_vp_map[vpn].vp2 = -1; 15586 } 15587 if (mpls_info->vpws_vp_map[vpn].vp3 != -1) { 15588 mpls_info->vpws_vp_map[vpn].vp3 = -1; 15589 } 15590 } 15591 } 15592 15593 #if defined(BCM_TRIUMPH2_SUPPORT) 15594 STATIC int 15595 _bcm_mpls_source_vp_set(int unit, bcm_mpls_port_t* mpls_port, int active_vp) 15596 { 15597 source_vp_entry_t svp; 15598 bcm_port_t local_port; 15599 int value; 15600 int rv = BCM_E_NONE; 15601 int dscp_map_chunk = 0, ing_pri_cng_chunk = 0; 15602 soc_mem_t port_tbl; 15603 15604 #if defined(BCM_TRIDENT3_SUPPORT) 15605 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 15606 ing_pri_cng_chunk = 64; 15607 dscp_map_chunk = 64; 15608 } else 15609 #endif 15610 { 15611 ing_pri_cng_chunk = 16; 15612 dscp_map_chunk = 64; 15613 } 15614 15615 15616 /* Sanity Checking */ 15617 if (mpls_port == NULL || active_vp < 0) { 15618 return BCM_E_PARAM; 15619 } 15620 15621 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 15622 port_tbl = LPORT_TABm; 15623 } else { 15624 port_tbl = PORT_TABm; 15625 } 15626 15627 /* For Katana for each SVP set TRUST_DSCP_PTR in SOURCE_VP with 15628 * the TRUST_DSCP_PTR of the physical port 15629 */ 15630 if (!(mpls_port->flags & BCM_MPLS_PORT_EGRESS_TUNNEL)) { 15631 /* Deal with physical ports */ 15632 if (BCM_GPORT_IS_SET(mpls_port->port) && !BCM_GPORT_IS_TRUNK(mpls_port->port)) { 15633 if (bcm_esw_port_local_get(unit, mpls_port->port, &local_port) < 0) { 15634 return BCM_E_PARAM; 15635 } 15636 } else { 15637 return BCM_E_PARAM; 15638 } 15639 15640 if (!SOC_PORT_VALID(unit, local_port)) { 15641 return BCM_E_PARAM; 15642 } 15643 15644 switch(mpls_port->criteria) { 15645 case BCM_MPLS_PORT_MATCH_PORT: 15646 case BCM_MPLS_PORT_MATCH_PORT_VLAN: 15647 case BCM_MPLS_PORT_MATCH_PORT_INNER_VLAN: 15648 case BCM_MPLS_PORT_MATCH_PORT_VLAN_STACKED: 15649 case BCM_MPLS_PORT_MATCH_VLAN: 15650 /* Read PORT Table */ 15651 if (!soc_mem_field_valid(unit, SOURCE_VPm, TRUST_DSCP_PTRf) || 15652 !soc_mem_field_valid(unit, port_tbl, TRUST_DOT1P_PTRf) || 15653 !soc_mem_field_valid(unit, SOURCE_VPm, TRUST_DOT1P_PTRf)) { 15654 return BCM_E_NONE; 15655 } 15656 15657 rv = READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, active_vp, &svp); 15658 if (rv < 0) { 15659 return rv; 15660 } 15661 15662 if (soc_feature(unit, soc_feature_dscp_map_per_port)) { 15663 int index_min = 0; 15664 /* Delete the old profile first */ 15665 if (mpls_port->flags & BCM_MPLS_PORT_REPLACE) { 15666 value = soc_SOURCE_VPm_field32_get(unit, 15667 &svp, 15668 TRUST_DSCP_PTRf); 15669 BCM_IF_ERROR_RETURN( 15670 _bcm_dscp_table_entry_delete(unit, 15671 value * dscp_map_chunk)); 15672 15673 value = soc_SOURCE_VPm_field32_get(unit, 15674 &svp, 15675 TRUST_DOT1P_PTRf); 15676 BCM_IF_ERROR_RETURN( 15677 _bcm_ing_pri_cng_map_entry_delete( 15678 unit, value * ing_pri_cng_chunk)); 15679 } 15680 15681 /* Get dscp table profile min index */ 15682 BCM_IF_ERROR_RETURN( 15683 _bcm_dscp_table_entry_range(unit, &index_min, NULL)); 15684 15685 /* 15686 * Increase the profile ref_count 15687 * If index_min is zero, means there is no reserved dscp profile 15688 * Otherwise need to handle specially 15689 */ 15690 if (index_min == 0) { 15691 15692 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 15693 rv = _bcm_esw_port_tab_get(unit, local_port, 15694 TRUST_DSCP_PTRf, 15695 &value); 15696 } else { 15697 rv = _bcm_tr2_port_tab_get(unit, local_port, 15698 TRUST_DSCP_PTRf, 15699 &value); 15700 } 15701 if (rv == BCM_E_NONE) { 15702 BCM_IF_ERROR_RETURN( 15703 _bcm_dscp_table_entry_reference( 15704 unit, (value * dscp_map_chunk), 15705 dscp_map_chunk)); 15706 soc_SOURCE_VPm_field32_set(unit, &svp, 15707 TRUST_DSCP_PTRf, value); 15708 } 15709 } else { 15710 /* Create a dscp profile, copy content from phy_port */ 15711 void *dscp_table; 15712 int alloc_size; 15713 void *entries[2]; 15714 15715 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 15716 alloc_size = dscp_map_chunk * 15717 sizeof(phb_mapping_tbl_2_entry_t); 15718 } else { 15719 alloc_size = dscp_map_chunk * 15720 sizeof(dscp_table_entry_t); 15721 } 15722 15723 dscp_table = soc_cm_salloc(unit, alloc_size, 15724 "TR2 dscp table"); 15725 if (NULL == dscp_table) { 15726 return BCM_E_MEMORY; 15727 } 15728 entries[0] = dscp_table; 15729 15730 /* Read the port chunk */ 15731 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 15732 rv = soc_mem_read_range(unit, PHB_MAPPING_TBL_2m, MEM_BLOCK_ANY, 15733 local_port * dscp_map_chunk, 15734 (local_port + 1) * dscp_map_chunk - 1, 15735 dscp_table); 15736 } else { 15737 rv = soc_mem_read_range(unit, DSCP_TABLEm, MEM_BLOCK_ANY, 15738 local_port * dscp_map_chunk, 15739 (local_port + 1) * dscp_map_chunk - 1, 15740 dscp_table); 15741 } 15742 15743 if (BCM_FAILURE(rv)) { 15744 soc_cm_sfree(unit, dscp_table); 15745 return rv; 15746 } 15747 /* Write the profile chunk */ 15748 rv = _bcm_dscp_table_entry_add(unit, entries, 15749 dscp_map_chunk, 15750 (uint32 *)&value); 15751 if (BCM_FAILURE(rv)) { 15752 soc_cm_sfree(unit, dscp_table); 15753 return rv; 15754 } 15755 15756 soc_cm_sfree(unit, dscp_table); 15757 soc_SOURCE_VPm_field32_set(unit, &svp, TRUST_DSCP_PTRf, 15758 (value / dscp_map_chunk)); 15759 } 15760 } 15761 15762 if (soc_feature(unit, soc_feature_color_prio_map_profile)) { 15763 /* Increase profile ref_count */ 15764 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 15765 rv = _bcm_esw_port_tab_get(unit, local_port, TRUST_DOT1P_PTRf, 15766 &value); 15767 } else { 15768 rv = _bcm_tr2_port_tab_get(unit, local_port, TRUST_DOT1P_PTRf, 15769 &value); 15770 } 15771 if (rv == BCM_E_NONE) { 15772 BCM_IF_ERROR_RETURN( 15773 _bcm_ing_pri_cng_map_entry_reference( 15774 unit, (value * ing_pri_cng_chunk), 15775 ing_pri_cng_chunk)); 15776 soc_SOURCE_VPm_field32_set(unit, &svp, TRUST_DOT1P_PTRf, 15777 value); 15778 } 15779 } 15780 15781 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 15782 rv = _bcm_esw_port_tab_get(unit, local_port, TRUST_DSCP_V4f, 15783 &value); 15784 } else { 15785 rv = _bcm_tr2_port_tab_get(unit, local_port, TRUST_DSCP_V4f, 15786 &value); 15787 } 15788 if (rv == BCM_E_NONE) { 15789 soc_SOURCE_VPm_field32_set(unit, &svp, TRUST_DSCP_V4f, value); 15790 } 15791 15792 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 15793 rv = _bcm_esw_port_tab_get(unit, local_port, TRUST_DSCP_V6f, 15794 &value); 15795 } else { 15796 rv = _bcm_tr2_port_tab_get(unit, local_port, TRUST_DSCP_V6f, 15797 &value); 15798 } 15799 if (rv == BCM_E_NONE) { 15800 soc_SOURCE_VPm_field32_set(unit, &svp, TRUST_DSCP_V6f, value); 15801 } 15802 15803 rv = WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, active_vp, &svp); 15804 if (rv == BCM_E_NONE) { 15805 _BCM_MPLS_SVP_PROFILE_SET_USED_SET(unit, active_vp); 15806 } 15807 break; 15808 default: 15809 break; 15810 } 15811 } 15812 return rv; 15813 } 15814 15815 STATIC int 15816 _bcm_mpls_source_vp_clear(int unit, int criteria, int vp, bcm_vpn_t vpn) 15817 { 15818 source_vp_entry_t svp; 15819 bcm_mpls_port_t mpls_port; 15820 int rv = BCM_E_NONE; 15821 int value = 0; 15822 int dscp_map_chunk = 0, ing_pri_cng_chunk = 0; 15823 soc_mem_t port_tbl; 15824 #if defined(BCM_TRIDENT3_SUPPORT) 15825 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 15826 ing_pri_cng_chunk = 64; 15827 dscp_map_chunk = 64; 15828 } else 15829 #endif 15830 { 15831 ing_pri_cng_chunk = 16; 15832 dscp_map_chunk = 64; 15833 } 15834 15835 if (!_BCM_MPLS_SVP_PROFILE_SET_USED_GET(unit, vp)) { 15836 return rv; 15837 } 15838 15839 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 15840 port_tbl = LPORT_TABm; 15841 } else { 15842 port_tbl = PORT_TABm; 15843 } 15844 15845 /* Decrease svp DSCP&DOT1P profiles ref_count */ 15846 if ((criteria == _BCM_MPLS_PORT_MATCH_TYPE_PORT) || 15847 (criteria == _BCM_MPLS_PORT_MATCH_TYPE_VLAN) || 15848 (criteria == _BCM_MPLS_PORT_MATCH_TYPE_INNER_VLAN) || 15849 (criteria == _BCM_MPLS_PORT_MATCH_TYPE_VLAN_STACKED) || 15850 (criteria == _BCM_MPLS_PORT_MATCH_TYPE_TRUNK)) { 15851 15852 /* Read PORT Table */ 15853 if (!soc_mem_field_valid(unit, SOURCE_VPm, TRUST_DSCP_PTRf) || 15854 !soc_mem_field_valid(unit, port_tbl, TRUST_DOT1P_PTRf) || 15855 !soc_mem_field_valid(unit, SOURCE_VPm, TRUST_DOT1P_PTRf)) { 15856 return BCM_E_NONE; 15857 } 15858 15859 rv = READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp, &svp); 15860 if (rv < 0) { 15861 return rv; 15862 } 15863 /* avoid using wrong index to delete DSCP entry 15864 * and get error return code, 0 is not always min index for DSCP 15865 * in some chips. 15866 */ 15867 rv = _bcm_tr_mpls_port_get(unit, vpn, vp, &mpls_port); 15868 if (rv < 0) { 15869 return rv; 15870 } 15871 if (mpls_port.flags & BCM_MPLS_PORT_EGRESS_TUNNEL) { 15872 return BCM_E_NONE; 15873 } 15874 if (soc_feature(unit, soc_feature_dscp_map_per_port)) { 15875 if (soc_mem_field_valid(unit, SOURCE_VPm, TRUST_DSCP_PTRf)) { 15876 value = soc_SOURCE_VPm_field32_get(unit, 15877 &svp, 15878 TRUST_DSCP_PTRf); 15879 rv = _bcm_dscp_table_entry_delete(unit, value * dscp_map_chunk); 15880 if (rv != BCM_E_NONE) { 15881 return rv; 15882 } else { 15883 rv = BCM_E_NONE; 15884 } 15885 } 15886 } 15887 if (soc_feature(unit, soc_feature_color_prio_map_profile)) { 15888 if (soc_mem_field_valid(unit, SOURCE_VPm, TRUST_DOT1P_PTRf)) { 15889 value = soc_SOURCE_VPm_field32_get(unit, 15890 &svp, 15891 TRUST_DOT1P_PTRf); 15892 rv = _bcm_ing_pri_cng_map_entry_delete(unit, 15893 value * ing_pri_cng_chunk); 15894 if (rv != BCM_E_NONE) { 15895 return rv; 15896 } else { 15897 rv = BCM_E_NONE; 15898 } 15899 } 15900 } 15901 _BCM_MPLS_SVP_PROFILE_SET_USED_CLR(unit, vp); 15902 } 15903 return rv; 15904 } 15905 15906 /* 15907 * Function: 15908 * bcm_tr_mpls_share_vp_bitmap_get 15909 * Purpose: 15910 * Get shared VPs info per VPN 15911 * Parameters: 15912 * unit - (IN) Device Number 15913 * vpn - (IN) VPN that shared vp belong to 15914 * vp_bitmap - (OUT) shared vp bitmap 15915 * Returns: 15916 * BCM_E_XXX 15917 */ 15918 int 15919 bcm_tr_mpls_share_vp_bitmap_get(int unit, bcm_vpn_t vpn, SHR_BITDCL *vp_bitmap) 15920 { 15921 vlan_xlate_entry_t *vent; 15922 soc_mem_t mem; 15923 int index_min = 0; 15924 int index_max = 0; 15925 uint8 *xlate_buf = NULL; 15926 int buf_size = 0; 15927 int i = 0; 15928 int rv = BCM_E_NONE; 15929 int vfi = -1; 15930 int vp = -1; 15931 15932 if (vpn != BCM_MPLS_VPLS_VPN_INVALID) { 15933 _BCM_MPLS_VPN_GET(vfi, _BCM_MPLS_VPN_TYPE_VPLS, vpn); 15934 if (!_bcm_vfi_used_get(unit, vfi, _bcmVfiTypeMpls)) { 15935 return BCM_E_NOT_FOUND; 15936 } 15937 } 15938 15939 #if defined(BCM_TRIDENT3_SUPPORT) 15940 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 15941 mem = VLAN_XLATE_1_DOUBLEm; 15942 } else 15943 #endif 15944 { 15945 mem = VLAN_XLATEm; 15946 } 15947 index_min = soc_mem_index_min(unit, mem); 15948 index_max = soc_mem_index_max(unit, mem); 15949 15950 buf_size = SOC_MEM_TABLE_BYTES(unit, mem); 15951 xlate_buf = soc_cm_salloc(unit, buf_size, "VLAN_XLATE buffer"); 15952 if (NULL == xlate_buf) { 15953 return BCM_E_MEMORY; 15954 } 15955 rv = soc_mem_read_range(unit, mem, MEM_BLOCK_ANY, index_min, index_max, xlate_buf); 15956 if (rv < 0) { 15957 soc_cm_sfree(unit, xlate_buf); 15958 return rv; 15959 } 15960 15961 for (i = index_min; i <= index_max; i++) { 15962 vent = soc_mem_table_idx_to_pointer(unit, 15963 mem, vlan_xlate_entry_t *, xlate_buf, i); 15964 15965 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 15966 if ((soc_mem_field32_get(unit, mem, vent, BASE_VALID_0f) == 0) || 15967 (soc_mem_field32_get(unit, mem, vent, BASE_VALID_1f) == 0)) { 15968 continue; 15969 } 15970 } else { 15971 if (soc_mem_field32_get(unit, mem, vent, VALIDf) == 0) { 15972 continue; 15973 } 15974 } 15975 15976 if (soc_mem_field32_get(unit, mem, vent, XLATE__MPLS_ACTIONf) != 0x1) { 15977 continue; 15978 } 15979 15980 if (vfi != -1 && soc_mem_field32_get(unit, mem, vent, XLATE__VFIf) != vfi) { 15981 continue; 15982 } 15983 15984 vp = soc_mem_field32_get(unit, mem, vent, XLATE__SOURCE_VPf); 15985 SHR_BITSET(vp_bitmap, vp); 15986 } 15987 15988 (void)soc_cm_sfree(unit, xlate_buf); 15989 15990 return BCM_E_NONE; 15991 } 15992 #endif 15993 15994 /* 15995 * Function: 15996 * _bcm_tr_mpls_vpws_port_add 15997 * Purpose: 15998 * Add VPWS port to a VPN 15999 * Parameters: 16000 * unit - (IN) Device Number 16001 * vpn - (IN) VPN instance ID 16002 * mpls_port - (IN/OUT) mpls port information (OUT : mpls_port_id) 16003 * Returns: 16004 * BCM_E_XXX 16005 */ 16006 16007 STATIC int 16008 _bcm_tr_mpls_vpws_port_add(int unit, bcm_vpn_t vpn, bcm_mpls_port_t *mpls_port) 16009 { 16010 int active_vp = -1; 16011 source_vp_entry_t svp1, svp2; 16012 ing_dvp_table_entry_t dvp1, dvp2; 16013 egr_l3_next_hop_entry_t egr_nh; 16014 uint8 vp_valid_flag = 0; 16015 bcm_port_t local_port; 16016 int tpid_enable = 0, tpid_index; 16017 int customer_drop=0, is_local = 0, rv = BCM_E_PARAM, nh_index = 0; 16018 int vp3= -1, num_vp, match_vp=0, vp3_read = -1; 16019 source_vp_entry_t svp3; 16020 ing_dvp_table_entry_t dvp3; 16021 bcm_vpn_t vpn_id; 16022 int vp1=-1, vp2=-1, backup_vp2 = -1; 16023 _bcm_mpls_old_nh_info_t old_nh_info; 16024 int prot_index = -1; 16025 #ifdef BCM_ENDURO_SUPPORT 16026 svp_disable_vlan_checks_tab_entry_t svp_disable_check; 16027 #endif /* BCM_ENDURO_SUPPORT */ 16028 _bcm_tr_mpls_bookkeeping_t *mpls_info = MPLS_INFO(unit); 16029 int match_add = TRUE; 16030 bcm_mpls_label_t vp3_match_label; 16031 _bcm_vp_info_t vp_info; 16032 bcm_switch_network_group_t network_group; 16033 uint32 dest_type, dest_val; 16034 soc_field_t dest_field = 0; 16035 egr_dvp_attribute_entry_t egr_dvp_attribute; 16036 16037 if (SOC_MEM_FIELD_VALID(unit, SOURCE_VPm,DESTINATIONf)) { 16038 dest_field = DESTINATIONf; 16039 } 16040 16041 network_group = mpls_port->network_group_id; 16042 rv = _bcm_validate_splithorizon_network_group(unit, 16043 mpls_port->flags & BCM_MPLS_PORT_NETWORK, &network_group); 16044 BCM_IF_ERROR_RETURN(rv); 16045 num_vp = soc_mem_index_count(unit, SOURCE_VPm); 16046 _BCM_MPLS_VPN_GET(vpn_id, _BCM_MPLS_VPN_TYPE_VPWS, vpn); 16047 _bcm_vp_info_init(&vp_info); 16048 vp_info.vp_type = _bcmVpTypeMpls; 16049 16050 sal_memset(&svp2, 0, sizeof(source_vp_entry_t)); 16051 sal_memset(&svp1, 0, sizeof(source_vp_entry_t)); 16052 sal_memset(&egr_dvp_attribute, 0, 16053 sizeof(egr_dvp_attribute_entry_t)); 16054 if ( vpn != BCM_MPLS_VPWS_VPN_INVALID) { 16055 16056 (void) _bcm_tr_mpls_vpws_vp_map_get (unit, vpn_id, &vp1, &vp2, &vp3_read); 16057 if (!(mpls_port->flags & BCM_MPLS_PORT_REPLACE)) { 16058 if (BCM_SUCCESS(_bcm_esw_failover_mpls_check(unit, 16059 mpls_port))) { 16060 if (vp2 == -1 && vp1 != -1 && vp3_read != -1) { 16061 /* Add new primary port: failover port should be set into vp2 */ 16062 vp2 = vp3_read; 16063 vp3_read = -1; 16064 _bcm_tr_mpls_vpws_vp_map_set(unit, vpn_id, vp1, 16065 vp2, vp3_read); 16066 } 16067 } 16068 } 16069 backup_vp2 = vp2; 16070 /* ---- Read in current table values for VP1 and VP2 ----- */ 16071 if (vp1 != -1) { 16072 BCM_IF_ERROR_RETURN ( 16073 READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp1, &svp1)); 16074 if (soc_SOURCE_VPm_field32_get(unit, &svp1, ENTRY_TYPEf) != 0) { 16075 vp_valid_flag |= 0x1; /* -- VP1 Valid ----- */ 16076 } 16077 BCM_IF_ERROR_RETURN ( 16078 READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp1, &dvp1)); 16079 } 16080 16081 if (vp2 != -1) { 16082 BCM_IF_ERROR_RETURN ( 16083 READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp2, &svp2)); 16084 if (soc_SOURCE_VPm_field32_get(unit, &svp2, ENTRY_TYPEf) != 0) { 16085 vp_valid_flag |= 0x2; /* -- VP2 Valid ----- */ 16086 } 16087 BCM_IF_ERROR_RETURN ( 16088 READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp2, &dvp2)); 16089 } 16090 16091 /* ---- Read in current table values for VP3 ----- */ 16092 if (mpls_port->flags & BCM_MPLS_PORT_REPLACE) { 16093 active_vp = BCM_GPORT_MPLS_PORT_ID_GET(mpls_port->mpls_port_id); 16094 if (active_vp == -1) { 16095 return BCM_E_PARAM; 16096 } 16097 if (_BCM_MPLS_GPORT_FAILOVER_VPLESS_GET(active_vp)) { 16098 active_vp = 16099 _BCM_MPLS_GPORT_FAILOVER_VPLESS_CLEAR(active_vp); 16100 } 16101 if (!_bcm_vp_used_get(unit, active_vp, _bcmVpTypeMpls)) { 16102 return BCM_E_NOT_FOUND; 16103 } 16104 /* IN case of multi level failover, we can have backup 16105 * ports which are not vp2, but to resue the same code, 16106 * we will try to use them through vp2 variables. 16107 */ 16108 if ((active_vp != vp1) && (active_vp != vp2)) { 16109 if (bcmi_mpls_match_backup_ports(unit, vpn_id, active_vp)) { 16110 16111 vp2 = active_vp; 16112 BCM_IF_ERROR_RETURN ( 16113 READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp2, &svp2)); 16114 16115 if (soc_SOURCE_VPm_field32_get(unit, &svp2, ENTRY_TYPEf) != 0) { 16116 vp_valid_flag |= 0x2; /* -- VP2 Valid ----- */ 16117 } 16118 BCM_IF_ERROR_RETURN ( 16119 READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp2, &dvp2)); 16120 } else { 16121 /* Read in current table values for VP3 */ 16122 vp3 = active_vp; 16123 BCM_IF_ERROR_RETURN ( 16124 READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp3, &dvp3)); 16125 BCM_IF_ERROR_RETURN ( 16126 READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp3, &svp3)); 16127 } 16128 } 16129 16130 if (soc_SOURCE_VPm_field32_get(unit, &svp1, ENTRY_TYPEf) == 0) { 16131 vp_valid_flag |= 0x10; 16132 } 16133 if (soc_SOURCE_VPm_field32_get(unit, &svp2, ENTRY_TYPEf) == 0) { 16134 vp_valid_flag |= 0x20; 16135 } 16136 } 16137 } else if (vpn == BCM_MPLS_VPWS_VPN_INVALID) { 16138 16139 if (mpls_port->flags & BCM_MPLS_PORT_REPLACE) { 16140 active_vp = BCM_GPORT_MPLS_PORT_ID_GET(mpls_port->mpls_port_id); 16141 if (active_vp == -1) { 16142 return BCM_E_PARAM; 16143 } 16144 16145 if (!_bcm_vp_used_get(unit, active_vp, _bcmVpTypeMpls)) { 16146 return BCM_E_NOT_FOUND; 16147 } 16148 16149 BCM_IF_ERROR_RETURN ( 16150 READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, active_vp, &svp2)); 16151 16152 if (soc_feature(unit, soc_feature_generic_dest)) { 16153 dest_val = soc_mem_field32_dest_get(unit, SOURCE_VPm, 16154 &svp2, DESTINATIONf, &dest_type); 16155 if (dest_type == SOC_MEM_FIF_DEST_DVP) { 16156 match_vp = dest_val; 16157 } 16158 } else { 16159 match_vp = soc_SOURCE_VPm_field32_get(unit, &svp2, DVPf); 16160 } 16161 16162 soc_SOURCE_VPm_field32_set(unit, &svp2, 16163 ENTRY_TYPEf, 0x0); 16164 rv = WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, active_vp, &svp2); 16165 if (BCM_SUCCESS(rv)) { 16166 BCM_IF_ERROR_RETURN ( 16167 READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, match_vp, &svp1)); 16168 soc_SOURCE_VPm_field32_set(unit, &svp1, 16169 ENTRY_TYPEf, 0x0); 16170 rv = WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, match_vp, &svp1); 16171 } 16172 return rv; 16173 } else { 16174 /* VP3 Add */ 16175 vp_valid_flag = 0x4; 16176 } 16177 } 16178 16179 16180 switch (vp_valid_flag) { 16181 16182 case 0x0: /* No VP is valid */ 16183 if (mpls_port->flags & BCM_MPLS_PORT_REPLACE) { 16184 return BCM_E_NOT_FOUND; 16185 } 16186 16187 if (mpls_port->flags & BCM_MPLS_PORT_WITH_ID) { 16188 if (mpls_port->flags & BCM_MPLS_PORT_NETWORK) { 16189 vp2 = BCM_GPORT_MPLS_PORT_ID_GET(mpls_port->mpls_port_id); 16190 if (vp2 == -1) { 16191 return BCM_E_PARAM; 16192 } 16193 16194 if (_bcm_vp_used_get(unit, vp2, _bcmVpTypeMpls)) { 16195 return BCM_E_EXISTS; 16196 } 16197 if (vp2 >= num_vp) { 16198 return (BCM_E_BADID); 16199 } 16200 vp_info.flags |= _BCM_VP_INFO_NETWORK_PORT; 16201 BCM_IF_ERROR_RETURN(_bcm_vp_used_set(unit, vp2, vp_info)); 16202 } 16203 else { 16204 vp1 = BCM_GPORT_MPLS_PORT_ID_GET(mpls_port->mpls_port_id); 16205 if (vp1 == -1) { 16206 return BCM_E_PARAM; 16207 } 16208 16209 if (_bcm_vp_used_get(unit, vp1, _bcmVpTypeMpls)) { 16210 return BCM_E_EXISTS; 16211 } 16212 if (vp1 >= num_vp) { 16213 return (BCM_E_BADID); 16214 } 16215 vp_info.flags &= ~(_BCM_VP_INFO_NETWORK_PORT); 16216 BCM_IF_ERROR_RETURN(_bcm_vp_used_set(unit, vp1, vp_info)); 16217 } 16218 16219 } else { 16220 /* No entries are used, allocate a new VP index for VP1 */ 16221 if (mpls_port->flags & BCM_MPLS_PORT_NETWORK) { 16222 /* Allocate a new VP index for VP2 */ 16223 vp_info.flags |= _BCM_VP_INFO_NETWORK_PORT; 16224 rv = _bcm_vp_alloc(unit, 0, (num_vp - 1), 1, SOURCE_VPm, vp_info, &vp2); 16225 if (rv < 0) { 16226 (void) _bcm_vp_free(unit, _bcmVpTypeMpls, 1, vp1); 16227 return rv; 16228 } 16229 _BCM_MPLS_NETWORK_VP_USED_SET(unit, vp2); 16230 } else { 16231 vp_info.flags &= ~(_BCM_VP_INFO_NETWORK_PORT); 16232 rv = _bcm_vp_alloc(unit, 0, (num_vp - 1), 1, SOURCE_VPm, vp_info, &vp1); 16233 if (rv < 0) { 16234 return rv; 16235 } 16236 } 16237 } 16238 16239 /* 16240 * This is the first port being added. If it's a network side port, it should go 16241 * into VP2. If it's a customer side port, it should go into VP1. 16242 */ 16243 if (mpls_port->flags & BCM_MPLS_PORT_NETWORK) { 16244 active_vp = vp2; 16245 vp_valid_flag = 0x2; 16246 if (SOC_MEM_IS_VALID(unit, EGR_DVP_ATTRIBUTEm)) { 16247 BCM_IF_ERROR_RETURN(WRITE_EGR_DVP_ATTRIBUTEm(unit, 16248 MEM_BLOCK_ALL, vp2, &egr_dvp_attribute)); 16249 } 16250 } else { 16251 active_vp = vp1; 16252 vp_valid_flag = 1; 16253 if (SOC_MEM_IS_VALID(unit, EGR_DVP_ATTRIBUTEm)) { 16254 BCM_IF_ERROR_RETURN(WRITE_EGR_DVP_ATTRIBUTEm(unit, 16255 MEM_BLOCK_ALL, vp1, &egr_dvp_attribute)); 16256 } 16257 } 16258 16259 sal_memset(&svp1, 0, sizeof(source_vp_entry_t)); 16260 sal_memset(&dvp1, 0, sizeof(ing_dvp_table_entry_t)); 16261 sal_memset(&svp2, 0, sizeof(source_vp_entry_t)); 16262 sal_memset(&dvp2, 0, sizeof(ing_dvp_table_entry_t)); 16263 16264 (void) _bcm_tr_mpls_vpws_vp_map_set(unit, vpn_id, vp1, vp2, vp3_read); 16265 break; 16266 16267 16268 case 0x1: /* Only VP1 is valid */ 16269 if (mpls_port->flags & BCM_MPLS_PORT_REPLACE) { 16270 if (active_vp != vp1) { 16271 return BCM_E_NOT_FOUND; 16272 } 16273 nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp1, 16274 NEXT_HOP_INDEXf); 16275 } else if (mpls_port->flags & BCM_MPLS_PORT_WITH_ID) { 16276 vp2 = BCM_GPORT_MPLS_PORT_ID_GET(mpls_port->mpls_port_id); 16277 if (vp2 == -1) { 16278 return BCM_E_PARAM; 16279 } 16280 16281 if (_bcm_vp_used_get(unit, vp2, _bcmVpTypeMpls)) { 16282 return BCM_E_EXISTS; 16283 } 16284 if (vp2 >= num_vp) { 16285 return (BCM_E_BADID); 16286 } 16287 if (mpls_port->flags & BCM_MPLS_PORT_NETWORK) { 16288 vp_info.flags |= _BCM_VP_INFO_NETWORK_PORT; 16289 } 16290 BCM_IF_ERROR_RETURN(_bcm_vp_used_set(unit, vp2, vp_info)); 16291 (void) _bcm_tr_mpls_vpws_vp_map_set(unit, vpn_id, vp1, vp2, vp3_read); 16292 16293 active_vp = vp2; 16294 vp_valid_flag = 3; 16295 sal_memset(&svp2, 0, sizeof(source_vp_entry_t)); 16296 sal_memset(&dvp2, 0, sizeof(ing_dvp_table_entry_t)); 16297 16298 } else { 16299 if(vp2 == -1) { 16300 16301 if (mpls_port->flags & BCM_MPLS_PORT_NETWORK) { 16302 vp_info.flags |= _BCM_VP_INFO_NETWORK_PORT; 16303 } 16304 /* Allocate a new VP index for VP2 */ 16305 rv = _bcm_vp_alloc(unit, 0, (num_vp - 1), 1, SOURCE_VPm, vp_info, &vp2); 16306 if (rv < 0) { 16307 return rv; 16308 } 16309 if (mpls_port->flags & BCM_MPLS_PORT_NETWORK) { 16310 _BCM_MPLS_NETWORK_VP_USED_SET(unit, vp2); 16311 } 16312 } 16313 16314 active_vp = vp2; 16315 vp_valid_flag = 3; 16316 sal_memset(&svp2, 0, sizeof(source_vp_entry_t)); 16317 sal_memset(&dvp2, 0, sizeof(ing_dvp_table_entry_t)); 16318 (void) _bcm_tr_mpls_vpws_vp_map_set(unit, vpn_id, vp1, vp2, vp3_read); 16319 } 16320 if (SOC_MEM_IS_VALID(unit, EGR_DVP_ATTRIBUTEm)) { 16321 BCM_IF_ERROR_RETURN(WRITE_EGR_DVP_ATTRIBUTEm(unit, 16322 MEM_BLOCK_ALL, active_vp, &egr_dvp_attribute)); 16323 } 16324 break; 16325 16326 16327 16328 case 0x2: /* Only VP2 is valid */ 16329 if (!(mpls_port->flags & BCM_MPLS_PORT_NETWORK)) { 16330 /* 16331 * Since only VP2 is valid and the port being added is not a network port, 16332 * it's customer side port i.e. VP1 16333 */ 16334 if (mpls_port->flags & BCM_MPLS_PORT_WITH_ID) { 16335 vp1 = BCM_GPORT_MPLS_PORT_ID_GET(mpls_port->mpls_port_id); 16336 if (vp1 == -1) { 16337 return BCM_E_PARAM; 16338 } 16339 16340 if (_bcm_vp_used_get(unit, vp1, _bcmVpTypeMpls)) { 16341 return BCM_E_EXISTS; 16342 } 16343 if (vp1 >= num_vp) { 16344 return (BCM_E_BADID); 16345 } 16346 vp_info.flags &= ~(_BCM_VP_INFO_NETWORK_PORT); 16347 BCM_IF_ERROR_RETURN(_bcm_vp_used_set(unit, vp1, vp_info)); 16348 (void) _bcm_tr_mpls_vpws_vp_map_set(unit, vpn_id, vp1, vp2, vp3_read); 16349 16350 active_vp = vp1; 16351 vp_valid_flag = 3; 16352 sal_memset(&svp1, 0, sizeof(source_vp_entry_t)); 16353 sal_memset(&dvp1, 0, sizeof(ing_dvp_table_entry_t)); 16354 } else { 16355 if (vp1 == -1) { 16356 /* Allocate a new VP index for VP1 */ 16357 vp_info.flags &= ~(_BCM_VP_INFO_NETWORK_PORT); 16358 rv = _bcm_vp_alloc(unit, 0, (num_vp - 1), 1, SOURCE_VPm, vp_info, &vp1); 16359 if (rv < 0) { 16360 return rv; 16361 } 16362 } 16363 16364 active_vp = vp1; 16365 vp_valid_flag = 3; 16366 sal_memset(&svp1, 0, sizeof(source_vp_entry_t)); 16367 sal_memset(&dvp1, 0, sizeof(ing_dvp_table_entry_t)); 16368 (void) _bcm_tr_mpls_vpws_vp_map_set(unit, vpn_id, vp1, vp2, vp3_read); 16369 } 16370 if (SOC_MEM_IS_VALID(unit, EGR_DVP_ATTRIBUTEm)) { 16371 BCM_IF_ERROR_RETURN(WRITE_EGR_DVP_ATTRIBUTEm(unit, 16372 MEM_BLOCK_ALL, active_vp, &egr_dvp_attribute)); 16373 } 16374 } else { 16375 /* 16376 * Since only VP2 is valid and the port being 16377 * added is a network port, its either existing 16378 * network port (VP2) being replaced or a 16379 * primary network port (VP3) being added. 16380 */ 16381 if (mpls_port->flags & BCM_MPLS_PORT_REPLACE) { 16382 /* in case of multi level protection, 16383 * we have already changed the vp2 above for 16384 * matching backup port. 16385 */ 16386 if (active_vp != vp2) { 16387 return BCM_E_NOT_FOUND; 16388 } 16389 nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp2, 16390 NEXT_HOP_INDEXf); 16391 break; 16392 } 16393 #if defined(BCM_TRIUMPH2_SUPPORT) 16394 if (soc_feature(unit, soc_feature_mpls_failover)) { 16395 if (BCM_SUCCESS(_bcm_esw_failover_mpls_check(unit, mpls_port))) { 16396 16397 if (mpls_port->flags & BCM_MPLS_PORT_WITH_ID) { 16398 vp3 = BCM_GPORT_MPLS_PORT_ID_GET(mpls_port->mpls_port_id); 16399 if (vp3 == -1) { 16400 return BCM_E_PARAM; 16401 } 16402 16403 if (_bcm_vp_used_get(unit, vp3, _bcmVpTypeMpls)) { 16404 return BCM_E_EXISTS; 16405 } 16406 if (vp3 >= num_vp) { 16407 return (BCM_E_BADID); 16408 } 16409 16410 sal_memset(&svp3, 0, sizeof(source_vp_entry_t)); 16411 sal_memset(&dvp3, 0, sizeof(ing_dvp_table_entry_t)); 16412 active_vp = vp3; 16413 16414 /* 16415 * Book keep the Primary Network VP (vp3). It's required to link to 16416 * the SVP of customer side when it's created 16417 */ 16418 (void) _bcm_tr_mpls_vpws_vp_map_set(unit, vpn_id, vp1, vp2, vp3); 16419 vp_info.flags |= _BCM_VP_INFO_NETWORK_PORT; 16420 BCM_IF_ERROR_RETURN( 16421 _bcm_vp_used_set(unit, active_vp, vp_info)); 16422 } else { 16423 if (mpls_port->flags & BCM_MPLS_PORT_FAILOVER) { 16424 /* VP conservation */ 16425 vp3 = BCM_GPORT_MPLS_PORT_ID_GET(mpls_port->failover_port_id); 16426 if (vp3 == -1) { 16427 return BCM_E_PARAM; 16428 } 16429 } else { 16430 /* allocate a new VP index */ 16431 vp_info.flags |= _BCM_VP_INFO_NETWORK_PORT; 16432 rv = _bcm_vp_alloc(unit, 0, (num_vp - 1), 1, SOURCE_VPm, vp_info, &vp3); 16433 if (vp3 == -1) { 16434 return BCM_E_PARAM; 16435 } 16436 if (rv < 0) { 16437 return rv; 16438 } 16439 _BCM_MPLS_NETWORK_VP_USED_SET(unit, vp3); 16440 } 16441 sal_memset(&svp3, 0, sizeof(source_vp_entry_t)); 16442 sal_memset(&dvp3, 0, sizeof(ing_dvp_table_entry_t)); 16443 active_vp = vp3; 16444 /* 16445 * Book keep the Primary Network VP (vp3). It's required to link to 16446 * the SVP of customer side when it's created 16447 */ 16448 (void) _bcm_tr_mpls_vpws_vp_map_set(unit, vpn_id, vp1, vp2, vp3); 16449 vp_info.flags |= _BCM_VP_INFO_NETWORK_PORT; 16450 BCM_IF_ERROR_RETURN( 16451 _bcm_vp_used_set(unit, active_vp, vp_info)); 16452 } 16453 if (SOC_MEM_IS_VALID(unit, EGR_DVP_ATTRIBUTEm)) { 16454 BCM_IF_ERROR_RETURN(WRITE_EGR_DVP_ATTRIBUTEm(unit, 16455 MEM_BLOCK_ALL, active_vp, &egr_dvp_attribute)); 16456 } 16457 } else if (_BCM_FAILOVER_IS_MULTI_LEVEL(mpls_port->failover_id)) { 16458 /* We can get another backup port here in case this is multi level failover */ 16459 if (mpls_port->flags & BCM_MPLS_PORT_WITH_ID) { 16460 vp2 = BCM_GPORT_MPLS_PORT_ID_GET(mpls_port->mpls_port_id); 16461 if (vp2 == -1) { 16462 return BCM_E_PARAM; 16463 } 16464 if (_bcm_vp_used_get(unit, vp2, _bcmVpTypeMpls)) { 16465 return BCM_E_EXISTS; 16466 } 16467 if (vp2 >= num_vp) { 16468 return (BCM_E_BADID); 16469 } 16470 sal_memset(&svp2, 0, sizeof(source_vp_entry_t)); 16471 sal_memset(&dvp2, 0, sizeof(ing_dvp_table_entry_t)); 16472 active_vp = vp2; 16473 /* We need to update backup ports */ 16474 BCM_IF_ERROR_RETURN( 16475 bcmi_mpls_vpws_vp_map_backup_port_set( 16476 unit, vpn_id, vp2)); 16477 } else { 16478 /* allocate a new VP index */ 16479 vp_info.flags |= _BCM_VP_INFO_NETWORK_PORT; 16480 rv = _bcm_vp_alloc(unit, 0, (num_vp - 1), 1, SOURCE_VPm, vp_info, &vp2); 16481 if (vp2 == -1) { 16482 return BCM_E_PARAM; 16483 } 16484 if (rv < 0) { 16485 return rv; 16486 } 16487 _BCM_MPLS_NETWORK_VP_USED_SET(unit, vp2); 16488 sal_memset(&svp2, 0, sizeof(source_vp_entry_t)); 16489 sal_memset(&dvp2, 0, sizeof(ing_dvp_table_entry_t)); 16490 active_vp = vp2; 16491 vp_info.flags |= _BCM_VP_INFO_NETWORK_PORT; 16492 BCM_IF_ERROR_RETURN( 16493 _bcm_vp_used_set(unit, active_vp, vp_info)); 16494 BCM_IF_ERROR_RETURN( 16495 bcmi_mpls_vpws_vp_map_backup_port_set( 16496 unit, vpn_id, vp2)); 16497 } 16498 } 16499 } else 16500 #endif /* BCM_TRIUMPH2_SUPPORT */ 16501 { 16502 if (soc_feature(unit, soc_feature_mpls_software_failover) && 16503 (mpls_port->flags & BCM_MPLS_PORT_FAILOVER)) { 16504 active_vp = BCM_GPORT_MPLS_PORT_ID_GET( 16505 mpls_port->failover_port_id); 16506 } else { 16507 if (!(mpls_port->flags & BCM_MPLS_PORT_REPLACE)) { 16508 return BCM_E_FULL; 16509 } 16510 } 16511 } 16512 16513 if (active_vp == vp1) { 16514 /* Replacing VP1 */ 16515 nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp1, 16516 NEXT_HOP_INDEXf); 16517 } else if (active_vp == vp2) { 16518 /* Replacing VP2 */ 16519 nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp2, 16520 NEXT_HOP_INDEXf); 16521 } else if (active_vp == vp3) { 16522 nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp3, 16523 NEXT_HOP_INDEXf); 16524 } 16525 } 16526 break; 16527 16528 16529 16530 case 0x3: /* VP1 and VP2 are valid */ 16531 #if defined(BCM_TRIUMPH2_SUPPORT) 16532 if (soc_feature(unit, soc_feature_mpls_failover)) { 16533 if ((mpls_port->flags & BCM_MPLS_PORT_FAILOVER) && 16534 (mpls_port->flags & BCM_MPLS_PORT_REPLACE)) { 16535 int failover_nh_index = -1; 16536 int failover_id = -1; 16537 int failover_mc_group = -1; 16538 if (active_vp != vp2) { 16539 return BCM_E_NOT_FOUND; 16540 } 16541 nh_index = 16542 soc_ING_DVP_TABLEm_field32_get( 16543 unit, &dvp2, NEXT_HOP_INDEXf); 16544 rv = _bcm_esw_failover_prot_nhi_get( 16545 unit, nh_index, &failover_id, 16546 &failover_nh_index, &failover_mc_group); 16547 if (BCM_SUCCESS(rv) && (failover_mc_group > 0)) { 16548 rv = _bcm_tr_mpls_vpless_failover_nh_index_find(unit, vp2, 16549 nh_index, &failover_nh_index); 16550 if (BCM_SUCCESS(rv) && (failover_nh_index > 0)) { 16551 nh_index = failover_nh_index; 16552 } 16553 } else if (BCM_SUCCESS(rv) && (failover_nh_index > 0)) { 16554 nh_index = failover_nh_index; 16555 } 16556 break; 16557 } else if (BCM_SUCCESS(_bcm_esw_failover_mpls_check(unit, mpls_port))) { 16558 if (mpls_port->flags & BCM_MPLS_PORT_REPLACE) { 16559 if (active_vp != vp3) { 16560 return BCM_E_NOT_FOUND; 16561 } 16562 nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp3, 16563 NEXT_HOP_INDEXf); 16564 } else if (mpls_port->flags & BCM_MPLS_PORT_WITH_ID) { 16565 vp3 = BCM_GPORT_MPLS_PORT_ID_GET(mpls_port->mpls_port_id); 16566 if (vp3 == -1) { 16567 return BCM_E_PARAM; 16568 } 16569 16570 if (_bcm_vp_used_get(unit, vp3, _bcmVpTypeMpls)) { 16571 return BCM_E_EXISTS; 16572 } 16573 if (vp3 >= num_vp) { 16574 return (BCM_E_BADID); 16575 } 16576 vp_info.flags |= _BCM_VP_INFO_NETWORK_PORT; 16577 BCM_IF_ERROR_RETURN(_bcm_vp_used_set(unit, vp3, vp_info)); 16578 sal_memset(&svp3, 0, sizeof(source_vp_entry_t)); 16579 sal_memset(&dvp3, 0, sizeof(ing_dvp_table_entry_t)); 16580 active_vp = vp3; 16581 (void) _bcm_tr_mpls_vpws_vp_map_set(unit, vpn_id, vp1, vp2, vp3); 16582 BCM_IF_ERROR_RETURN( 16583 _bcm_vp_used_set(unit, active_vp, vp_info)); 16584 if (SOC_MEM_IS_VALID(unit, EGR_DVP_ATTRIBUTEm)) { 16585 BCM_IF_ERROR_RETURN(WRITE_EGR_DVP_ATTRIBUTEm(unit, 16586 MEM_BLOCK_ALL, active_vp, &egr_dvp_attribute)); 16587 } 16588 } else { 16589 if (mpls_port->flags & BCM_MPLS_PORT_FAILOVER) { 16590 /* VP conservation */ 16591 vp3 = BCM_GPORT_MPLS_PORT_ID_GET(mpls_port->failover_port_id); 16592 if (vp3 == -1) { 16593 return BCM_E_PARAM; 16594 } 16595 } else { 16596 /* allocate a new VP index */ 16597 vp_info.flags |= _BCM_VP_INFO_NETWORK_PORT; 16598 rv = _bcm_vp_alloc(unit, 0, (num_vp - 1), 1, SOURCE_VPm, vp_info, &vp3); 16599 if (vp3 == -1) { 16600 return BCM_E_PARAM; 16601 } 16602 if (rv < 0) { 16603 return rv; 16604 } 16605 _BCM_MPLS_NETWORK_VP_USED_SET(unit, vp3); 16606 } 16607 sal_memset(&svp3, 0, sizeof(source_vp_entry_t)); 16608 sal_memset(&dvp3, 0, sizeof(ing_dvp_table_entry_t)); 16609 active_vp = vp3; 16610 if (!(mpls_port->flags & BCM_MPLS_PORT_FAILOVER)) { 16611 (void) _bcm_tr_mpls_vpws_vp_map_set(unit, vpn_id, vp1, vp2, vp3); 16612 vp_info.flags |= _BCM_VP_INFO_NETWORK_PORT; 16613 BCM_IF_ERROR_RETURN( 16614 _bcm_vp_used_set(unit, active_vp, vp_info)); 16615 if (SOC_MEM_IS_VALID(unit, EGR_DVP_ATTRIBUTEm)) { 16616 BCM_IF_ERROR_RETURN(WRITE_EGR_DVP_ATTRIBUTEm(unit, 16617 MEM_BLOCK_ALL, active_vp, &egr_dvp_attribute)); 16618 } 16619 } 16620 } 16621 } else if (_BCM_FAILOVER_IS_MULTI_LEVEL(mpls_port->failover_id)) { 16622 if (mpls_port->flags & BCM_MPLS_PORT_REPLACE) { 16623 if (active_vp != vp2) { 16624 return BCM_E_NOT_FOUND; 16625 } 16626 nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp2, 16627 NEXT_HOP_INDEXf); 16628 } else if (mpls_port->flags & BCM_MPLS_PORT_WITH_ID) { 16629 vp2 = BCM_GPORT_MPLS_PORT_ID_GET(mpls_port->mpls_port_id); 16630 if (vp2 == -1) { 16631 return BCM_E_PARAM; 16632 } 16633 16634 if (_bcm_vp_used_get(unit, vp2, _bcmVpTypeMpls)) { 16635 return BCM_E_EXISTS; 16636 } 16637 if (vp2 >= num_vp) { 16638 return (BCM_E_BADID); 16639 } 16640 vp_info.flags |= _BCM_VP_INFO_NETWORK_PORT; 16641 BCM_IF_ERROR_RETURN(_bcm_vp_used_set(unit, vp2, vp_info)); 16642 sal_memset(&svp2, 0, sizeof(source_vp_entry_t)); 16643 sal_memset(&dvp2, 0, sizeof(ing_dvp_table_entry_t)); 16644 active_vp = vp2; 16645 BCM_IF_ERROR_RETURN( 16646 _bcm_vp_used_set(unit, active_vp, vp_info)); 16647 BCM_IF_ERROR_RETURN( 16648 bcmi_mpls_vpws_vp_map_backup_port_set( 16649 unit, vpn_id, vp2)); 16650 } else { 16651 if (mpls_port->flags & BCM_MPLS_PORT_FAILOVER) { 16652 /* VP conservation */ 16653 vp2 = BCM_GPORT_MPLS_PORT_ID_GET(mpls_port->failover_port_id); 16654 if (vp2 == -1) { 16655 return BCM_E_PARAM; 16656 } 16657 } else { 16658 /* allocate a new VP index */ 16659 vp_info.flags |= _BCM_VP_INFO_NETWORK_PORT; 16660 rv = _bcm_vp_alloc(unit, 0, (num_vp - 1), 1, SOURCE_VPm, vp_info, &vp2); 16661 if (vp2 == -1) { 16662 return BCM_E_PARAM; 16663 } 16664 if (rv < 0) { 16665 return rv; 16666 } 16667 _BCM_MPLS_NETWORK_VP_USED_SET(unit, vp2); 16668 } 16669 sal_memset(&svp2, 0, sizeof(source_vp_entry_t)); 16670 sal_memset(&dvp2, 0, sizeof(ing_dvp_table_entry_t)); 16671 active_vp = vp2; 16672 16673 if (!(mpls_port->flags & BCM_MPLS_PORT_FAILOVER)) { 16674 vp_info.flags |= _BCM_VP_INFO_NETWORK_PORT; 16675 BCM_IF_ERROR_RETURN( 16676 _bcm_vp_used_set(unit, active_vp, vp_info)); 16677 BCM_IF_ERROR_RETURN( 16678 bcmi_mpls_vpws_vp_map_backup_port_set( 16679 unit, vpn_id, vp2)); 16680 } 16681 } 16682 } 16683 } else 16684 #endif /* BCM_TRIUMPH2_SUPPORT */ 16685 { 16686 if (soc_feature(unit, soc_feature_mpls_software_failover) && 16687 (mpls_port->flags & BCM_MPLS_PORT_FAILOVER)) { 16688 active_vp = BCM_GPORT_MPLS_PORT_ID_GET( 16689 mpls_port->failover_port_id); 16690 } else { 16691 if (!(mpls_port->flags & BCM_MPLS_PORT_REPLACE)) { 16692 return BCM_E_FULL; 16693 } 16694 } 16695 } 16696 16697 if (active_vp == vp1) { 16698 /* Replacing VP1 */ 16699 nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp1, 16700 NEXT_HOP_INDEXf); 16701 } 16702 16703 else if (active_vp == vp2) { 16704 /* Replacing VP2 */ 16705 nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp2, 16706 NEXT_HOP_INDEXf); 16707 } 16708 16709 else if (active_vp == vp3) { 16710 nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp3, 16711 NEXT_HOP_INDEXf); 16712 } 16713 break; 16714 16715 16716 16717 case 0x4: /* Only VP3 is valid - For Software based Failover purposes */ 16718 if (soc_feature(unit, soc_feature_mpls_software_failover)) { 16719 if (mpls_port->flags & BCM_MPLS_PORT_WITH_ID) { 16720 vp3 = BCM_GPORT_MPLS_PORT_ID_GET(mpls_port->mpls_port_id); 16721 if (vp3 == -1) { 16722 return BCM_E_PARAM; 16723 } 16724 16725 if (_bcm_vp_used_get(unit, vp3, _bcmVpTypeMpls)) { 16726 return BCM_E_EXISTS; 16727 } 16728 if (vp3 >= num_vp) { 16729 return (BCM_E_BADID); 16730 } 16731 vp_info.flags |= _BCM_VP_INFO_NETWORK_PORT; 16732 BCM_IF_ERROR_RETURN( 16733 _bcm_vp_used_set(unit, vp3, vp_info)); 16734 } else { 16735 /* allocate a new VP index */ 16736 vp_info.flags |= _BCM_VP_INFO_NETWORK_PORT; 16737 rv = _bcm_vp_alloc(unit, 0, (num_vp - 1), 16738 1, SOURCE_VPm, vp_info, &vp3); 16739 if (rv < 0) { 16740 return rv; 16741 } 16742 _BCM_MPLS_NETWORK_VP_USED_SET(unit, vp3); 16743 } 16744 sal_memset(&svp3, 0, sizeof(source_vp_entry_t)); 16745 sal_memset(&dvp3, 0, sizeof(ing_dvp_table_entry_t)); 16746 active_vp = vp3; 16747 vp_info.flags |= _BCM_VP_INFO_NETWORK_PORT; 16748 BCM_IF_ERROR_RETURN( 16749 _bcm_vp_used_set(unit, active_vp, vp_info)); 16750 } 16751 break; 16752 16753 case 0x12: 16754 if (mpls_port->flags & BCM_MPLS_PORT_REPLACE) { 16755 if (active_vp == vp2) { 16756 nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp2, 16757 NEXT_HOP_INDEXf); 16758 } else if (active_vp == vp3_read) { 16759 nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp3, 16760 NEXT_HOP_INDEXf); 16761 } else { 16762 return BCM_E_NOT_FOUND; 16763 } 16764 } 16765 break; 16766 16767 case 0x21: 16768 if (mpls_port->flags & BCM_MPLS_PORT_REPLACE) { 16769 if (active_vp == vp1) { 16770 nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp1, 16771 NEXT_HOP_INDEXf); 16772 } else if (active_vp == vp3_read) { 16773 nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp3, 16774 NEXT_HOP_INDEXf); 16775 } else { 16776 return BCM_E_NOT_FOUND; 16777 } 16778 } 16779 break; 16780 16781 case 0x30: 16782 if (soc_feature(unit, soc_feature_mpls_software_failover)) { 16783 if ( vpn != BCM_MPLS_VPWS_VPN_INVALID) { 16784 if (active_vp == vp2) { 16785 soc_SOURCE_VPm_field32_set(unit, &svp2, 16786 ENTRY_TYPEf, 0x2); 16787 rv = WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, vp2, &svp2); 16788 if (BCM_SUCCESS(rv) && (vp1 != -1)) { 16789 soc_SOURCE_VPm_field32_set(unit, &svp1, 16790 ENTRY_TYPEf, 0x2); 16791 if (soc_feature(unit, soc_feature_generic_dest)) { 16792 soc_mem_field32_dest_set(unit, SOURCE_VPm, &svp1, 16793 DESTINATIONf, SOC_MEM_FIF_DEST_DVP, vp2); 16794 } else { 16795 soc_SOURCE_VPm_field32_set(unit, &svp1, 16796 DVPf, vp2); 16797 } 16798 rv = WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, vp1, &svp1); 16799 } 16800 } else if (active_vp == vp3) { 16801 soc_SOURCE_VPm_field32_set(unit, &svp3, 16802 ENTRY_TYPEf, 0x2); 16803 16804 if (vp1 != -1) { 16805 if (soc_feature(unit, soc_feature_generic_dest)) { 16806 soc_mem_field32_dest_set(unit, SOURCE_VPm, &svp3, 16807 DESTINATIONf, SOC_MEM_FIF_DEST_DVP, vp1); 16808 } else { 16809 soc_SOURCE_VPm_field32_set(unit, &svp3, 16810 DVPf, vp1); 16811 } 16812 } 16813 rv = WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, vp3, &svp3); 16814 if (BCM_SUCCESS(rv) && (vp1 != -1)) { 16815 soc_SOURCE_VPm_field32_set(unit, &svp1, 16816 ENTRY_TYPEf, 0x2); 16817 16818 if (soc_feature(unit, soc_feature_generic_dest)) { 16819 soc_mem_field32_dest_set(unit, SOURCE_VPm, &svp1, 16820 DESTINATIONf, SOC_MEM_FIF_DEST_DVP, vp3); 16821 } else { 16822 soc_SOURCE_VPm_field32_set(unit, &svp1, 16823 DVPf, vp3); 16824 } 16825 rv = WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, vp1, &svp1); 16826 } 16827 if (mpls_port->flags & BCM_MPLS_PORT_REPLACE) { 16828 (void) _bcm_tr_mpls_vpws_vp_map_set(unit, vpn_id, vp1, active_vp, -1); 16829 } 16830 } 16831 } 16832 return rv; 16833 } 16834 break; 16835 16836 default: 16837 return BCM_E_CONFIG; 16838 } 16839 16840 if (active_vp == -1) { 16841 return BCM_E_CONFIG; 16842 } 16843 16844 if (!(mpls_port->flags & BCM_MPLS_PORT_REPLACE)) { 16845 /* Set the MPLS port ID */ 16846 BCM_GPORT_MPLS_PORT_ID_SET(mpls_port->mpls_port_id, active_vp); 16847 } 16848 if (mpls_port->flags & BCM_MPLS_PORT_ENCAP_WITH_ID) { 16849 /* Input parameters check. */ 16850 if (!BCM_XGS3_L3_EGRESS_IDX_VALID(unit, mpls_port->encap_id) && 16851 !BCM_XGS3_DVP_EGRESS_IDX_VALID(unit, mpls_port->encap_id)) { 16852 return (BCM_E_PARAM); 16853 } 16854 16855 /* Calculate next hop index. */ 16856 if (BCM_XGS3_L3_EGRESS_IDX_VALID(unit, mpls_port->encap_id)) { 16857 nh_index = mpls_port->encap_id - BCM_XGS3_EGRESS_IDX_MIN(unit); 16858 } else { 16859 nh_index = mpls_port->encap_id - BCM_XGS3_DVP_EGRESS_IDX_MIN(unit); 16860 } 16861 } else { 16862 mpls_port->encap_id = 0; 16863 } 16864 16865 switch (vp_valid_flag) { 16866 16867 case 0x30: 16868 if (soc_feature(unit, soc_feature_vlan_xlate)) { 16869 rv = soc_mem_read(unit, EGR_L3_NEXT_HOPm, MEM_BLOCK_ANY, nh_index, &egr_nh); 16870 if (rv < 0) { 16871 goto vpws_cleanup; 16872 } 16873 16874 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, MPLS__USE_DVP_IN_EVXLT_KEYf, 0x1); 16875 rv = soc_mem_write (unit, EGR_L3_NEXT_HOPm, MEM_BLOCK_ALL, nh_index, &egr_nh); 16876 16877 if (rv < 0) { 16878 goto vpws_cleanup; 16879 } 16880 } 16881 break; 16882 16883 default: 16884 customer_drop = (mpls_port->flags & BCM_MPLS_PORT_DROP) ? 1:0; 16885 rv = _bcm_tr_mpls_l2_nh_info_add(unit, mpls_port, active_vp, customer_drop, 1, 16886 &nh_index, &local_port, &is_local, &old_nh_info); 16887 if (rv < 0) { 16888 return rv; 16889 } 16890 16891 if (mpls_port->flags & BCM_MPLS_PORT_SERVICE_TAGGED) { 16892 rv = _bcm_fb2_outer_tpid_lkup(unit, mpls_port->service_tpid, 16893 &tpid_index); 16894 if (rv < 0) { 16895 goto vpws_cleanup; 16896 } 16897 tpid_enable = (1 << tpid_index); 16898 } 16899 break; 16900 } 16901 16902 if (mpls_port->flags & BCM_MPLS_PORT_FAILOVER) { 16903 rv = _bcm_esw_mpls_match_add(unit, mpls_port, 16904 _BCM_MPLS_GPORT_FAILOVER_VPLESS_SET(active_vp), vpn, TRUE); 16905 mpls_port->mpls_port_id = 16906 _BCM_MPLS_GPORT_FAILOVER_VPLESS_SET(mpls_port->mpls_port_id); 16907 mpls_port->encap_id = BCM_XGS3_DVP_EGRESS_IDX_MIN(unit) + nh_index; 16908 if (soc_feature(unit, soc_feature_mpls_software_failover)) { 16909 if (mpls_port->flags & BCM_MPLS_PORT_ENCAP_WITH_ID) { 16910 rv = soc_mem_field32_modify(unit, ING_DVP_TABLEm, 16911 active_vp, NEXT_HOP_INDEXf, nh_index); 16912 if (rv < 0) { 16913 goto vpws_cleanup; 16914 } 16915 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 16916 if (SOC_IS_TRIDENT2PLUS(unit)) { 16917 rv = soc_mem_field32_modify(unit, ING_DVP_2_TABLEm, 16918 active_vp, NEXT_HOP_INDEXf, nh_index); 16919 } 16920 if (rv < 0) { 16921 goto vpws_cleanup; 16922 } 16923 #endif 16924 } 16925 } 16926 if (mpls_port->flags & BCM_MPLS_PORT_REPLACE) { 16927 (void)_bcm_tr_mpls_l2_old_nh_info_delete( 16928 unit, mpls_port, nh_index, &old_nh_info); 16929 } 16930 goto vpws_cleanup; 16931 } 16932 16933 if (active_vp == vp1) { 16934 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) || \ 16935 defined(BCM_APACHE_SUPPORT) 16936 if (SOC_IS_KATANAX(unit) || SOC_IS_TRIUMPH3(unit) || 16937 SOC_IS_APACHE(unit)) { 16938 rv = _bcm_esw_add_policer_to_table(unit, 16939 mpls_port->policer_id, 16940 SOURCE_VPm, 0, &svp1); 16941 BCM_IF_ERROR_RETURN(rv); 16942 } 16943 #endif /* BCM_KATANA_SUPPORT or BCM_TRIUMPH3_SUPPORT or BCM_APACHE_SUPPORT */ 16944 /* Set SOURCE_VP */ 16945 soc_SOURCE_VPm_field32_set(unit, &svp1, CLASS_IDf, 16946 mpls_port->if_class); 16947 if (soc_feature(unit, 16948 soc_feature_multiple_split_horizon_group)) { 16949 soc_SOURCE_VPm_field32_set( 16950 unit, &svp1, NETWORK_GROUPf, network_group); 16951 } else { 16952 soc_SOURCE_VPm_field32_set( 16953 unit, &svp1, NETWORK_PORTf, 16954 (mpls_port->flags & BCM_MPLS_PORT_NETWORK) ? 16955 1 : 0); 16956 } 16957 if (mpls_port->flags & BCM_MPLS_PORT_SERVICE_TAGGED) { 16958 soc_SOURCE_VPm_field32_set(unit, &svp1, SD_TAG_MODEf, 1); 16959 16960 if (SOC_MEM_FIELD_VALID(unit, SOURCE_VPm, TPID_ENABLEf)) { 16961 soc_SOURCE_VPm_field32_set(unit, &svp1, TPID_ENABLEf, tpid_enable); 16962 } 16963 if (SOC_MEM_FIELD_VALID(unit, SOURCE_VPm, TRUST_OUTER_DOT1Pf)) { 16964 soc_SOURCE_VPm_field32_set(unit, &svp1, TRUST_OUTER_DOT1Pf, 1); 16965 } 16966 } else { 16967 soc_SOURCE_VPm_field32_set(unit, &svp1, SD_TAG_MODEf, 0); 16968 } 16969 16970 if (mpls_port->flags & BCM_MPLS_PORT_REPLACE) { 16971 rv = WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, vp1, &svp1); 16972 if (rv < 0) { 16973 goto vpws_cleanup; 16974 } 16975 16976 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 16977 uint32 svp_attrs_1[SOC_MAX_MEM_WORDS]; 16978 16979 sal_memset(svp_attrs_1, 0, 16980 sizeof(uint32) * SOC_MAX_MEM_WORDS); 16981 soc_SVP_ATTRS_1m_field_set(unit, 16982 &svp_attrs_1, TPID_ENABLEf, 16983 (uint32 *)&tpid_enable); 16984 BCM_IF_ERROR_RETURN( 16985 WRITE_SVP_ATTRS_1m(unit, 16986 MEM_BLOCK_ALL, vp1, 16987 &svp_attrs_1)); 16988 } 16989 /* Link in the newly allocated next-hop entry */ 16990 soc_ING_DVP_TABLEm_field32_set(unit, &dvp1, NEXT_HOP_INDEXf, 16991 nh_index); 16992 /* Enable DVP as Network_port */ 16993 if (soc_mem_field_valid(unit, ING_DVP_TABLEm, NETWORK_PORTf)) { 16994 soc_ING_DVP_TABLEm_field32_set(unit, &dvp1, NETWORK_PORTf, 16995 ((mpls_port->flags & BCM_MPLS_PORT_EGRESS_TUNNEL) && 16996 (mpls_port->flags & BCM_MPLS_PORT_NETWORK) ) ? 1 : 0); 16997 } 16998 if (soc_feature(unit, 16999 soc_feature_multiple_split_horizon_group)) { 17000 if (soc_mem_field_valid( 17001 unit, ING_DVP_TABLEm, NETWORK_GROUPf)) { 17002 soc_ING_DVP_TABLEm_field32_set( 17003 unit, &dvp1, NETWORK_GROUPf, 17004 network_group); 17005 } 17006 17007 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 17008 rv = soc_mem_field32_modify(unit, EGR_DVP_ATTRIBUTEm, 17009 active_vp, 17010 COMMON__DVP_NETWORK_GROUPf, 17011 network_group); 17012 if (rv < 0) { 17013 goto vpws_cleanup; 17014 } 17015 } 17016 } 17017 17018 rv = WRITE_ING_DVP_TABLEm(unit, MEM_BLOCK_ALL, active_vp, &dvp1); 17019 if (rv < 0) { 17020 goto vpws_cleanup; 17021 } 17022 rv = _bcm_vp_ing_dvp_to_ing_dvp2(unit, &dvp1, active_vp); 17023 if (rv < 0) { 17024 goto vpws_cleanup; 17025 } 17026 } else { 17027 17028 /* Link in the newly allocated next-hop entry to DVP */ 17029 soc_ING_DVP_TABLEm_field32_set(unit, &dvp1, NEXT_HOP_INDEXf, 17030 nh_index); 17031 /* Enable DVP as Network_port */ 17032 if (soc_mem_field_valid(unit, ING_DVP_TABLEm, NETWORK_PORTf)) { 17033 soc_ING_DVP_TABLEm_field32_set(unit, &dvp1, NETWORK_PORTf, 17034 ((mpls_port->flags & BCM_MPLS_PORT_EGRESS_TUNNEL) && 17035 (mpls_port->flags & BCM_MPLS_PORT_NETWORK) ) ? 1 : 0); 17036 } 17037 17038 if (soc_feature(unit, 17039 soc_feature_multiple_split_horizon_group)) { 17040 if (soc_mem_field_valid( 17041 unit, ING_DVP_TABLEm, NETWORK_GROUPf)) { 17042 soc_ING_DVP_TABLEm_field32_set( 17043 unit, &dvp1, NETWORK_GROUPf, 17044 network_group); 17045 17046 } 17047 17048 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 17049 rv = soc_mem_field32_modify(unit, EGR_DVP_ATTRIBUTEm, 17050 active_vp, 17051 COMMON__DVP_NETWORK_GROUPf, 17052 network_group); 17053 if (rv < 0) { 17054 goto vpws_cleanup; 17055 } 17056 } 17057 } 17058 17059 rv = WRITE_ING_DVP_TABLEm(unit, MEM_BLOCK_ALL, active_vp, &dvp1); 17060 if (rv < 0) { 17061 goto vpws_cleanup; 17062 } 17063 rv = _bcm_vp_ing_dvp_to_ing_dvp2(unit, &dvp1, active_vp); 17064 if (rv < 0) { 17065 goto vpws_cleanup; 17066 } 17067 17068 /* Tie the SVP to DVP. */ 17069 soc_SOURCE_VPm_field32_set(unit, &svp1, 17070 ENTRY_TYPEf, 0x2); /* VPWS */ 17071 switch (vp_valid_flag) { 17072 case 1: 17073 if (soc_feature(unit, soc_feature_generic_dest)) { 17074 soc_mem_field32_dest_set(unit, SOURCE_VPm, &svp1, 17075 DESTINATIONf, SOC_MEM_FIF_DEST_DVP, 0); 17076 } else { 17077 soc_SOURCE_VPm_field32_set(unit, &svp1, DVPf, 0); 17078 } 17079 break; 17080 case 3: 17081 if (vp3_read != -1) { 17082 if (soc_feature(unit, soc_feature_generic_dest)) { 17083 soc_mem_field32_dest_set(unit, SOURCE_VPm, &svp1, 17084 DESTINATIONf, SOC_MEM_FIF_DEST_DVP, vp3_read); 17085 } else { 17086 soc_SOURCE_VPm_field32_set(unit, &svp1, DVPf, vp3_read); 17087 } 17088 } else if (vp2 != -1) { 17089 if (soc_feature(unit, soc_feature_generic_dest)) { 17090 soc_mem_field32_dest_set(unit, SOURCE_VPm, &svp1, 17091 DESTINATIONf, SOC_MEM_FIF_DEST_DVP, vp2); 17092 } else { 17093 soc_SOURCE_VPm_field32_set(unit, &svp1, DVPf, vp2); 17094 } 17095 } 17096 break; 17097 default: 17098 if (soc_feature(unit, soc_feature_generic_dest)) { 17099 soc_mem_field32_dest_set(unit, SOURCE_VPm, &svp1, 17100 DESTINATIONf, SOC_MEM_FIF_DEST_DVP, vp1); 17101 } else { 17102 soc_SOURCE_VPm_field32_set(unit, &svp1, DVPf, vp1); 17103 } 17104 break; 17105 } 17106 if (soc_mem_field_valid(unit, SOURCE_VPm, DISABLE_VLAN_CHECKSf)) { 17107 soc_SOURCE_VPm_field32_set(unit, &svp1, DISABLE_VLAN_CHECKSf, 1); 17108 } 17109 if (soc_mem_field_valid(unit, SOURCE_VPm, SRC_PORTf) && 17110 soc_mem_field_valid(unit, SOURCE_VPm, SRC_MODIDf)) { 17111 rv = _bcm_tr_mpls_l2vpn_source_port_set(unit, mpls_port, &svp1); 17112 } 17113 if (rv < 0) { 17114 goto vpws_cleanup; 17115 } 17116 17117 if (soc_mem_field_valid(unit, SOURCE_VPm, SVP_PROFILE_INDEXf)) { 17118 if(mpls_port->flags & BCM_MPLS_PORT_EGRESS_TUNNEL) { 17119 soc_SOURCE_VPm_field32_set(unit, &svp1, SVP_PROFILE_INDEXf, 3); 17120 } else { 17121 soc_SOURCE_VPm_field32_set(unit, &svp1, SVP_PROFILE_INDEXf, 2); 17122 } 17123 } 17124 17125 rv = WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, vp1, &svp1); 17126 if ((rv >= 0) && (vp_valid_flag == 3)) { 17127 if (soc_feature(unit, soc_feature_generic_dest)) { 17128 soc_mem_field32_dest_set(unit, SOURCE_VPm, &svp2, 17129 DESTINATIONf, SOC_MEM_FIF_DEST_DVP, vp1); 17130 } else { 17131 soc_SOURCE_VPm_field32_set(unit, &svp2, DVPf, vp1); 17132 } 17133 rv = WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, vp2, &svp2); 17134 } else if ((rv >= 0) && (vp_valid_flag == 1)) { 17135 if (vp2 != -1) { 17136 rv = WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, vp2, &svp2); 17137 } 17138 } 17139 if ((rv >= 0) && (vp3_read != -1)) { 17140 source_vp_entry_t svp3_read; 17141 sal_memset(&svp3_read, 0, sizeof(source_vp_entry_t)); 17142 BCM_IF_ERROR_RETURN (READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp3_read, &svp3_read)); 17143 if (soc_feature(unit, soc_feature_generic_dest)) { 17144 dest_val = soc_mem_field32_dest_get(unit, SOURCE_VPm, 17145 &svp2, DESTINATIONf, &dest_type); 17146 if (dest_type == SOC_MEM_FIF_DEST_DVP) { 17147 if (vp1 != dest_val) { 17148 rv = bcmi_td3_soc_mem_fields32_modify(unit, 17149 SOURCE_VPm, vp3_read, dest_field, vp1); 17150 } 17151 } 17152 } else { 17153 if (vp1 != soc_SOURCE_VPm_field32_get(unit, &svp3_read, DVPf)) { 17154 rv = soc_mem_field32_modify(unit, SOURCE_VPm, vp3_read, DVPf, vp1); 17155 } 17156 } 17157 } 17158 17159 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 17160 uint32 svp_attrs_1[SOC_MAX_MEM_WORDS]; 17161 17162 sal_memset(svp_attrs_1, 0, 17163 sizeof(uint32) * SOC_MAX_MEM_WORDS); 17164 soc_SVP_ATTRS_1m_field_set(unit, 17165 &svp_attrs_1, TPID_ENABLEf, 17166 (uint32 *)&tpid_enable); 17167 BCM_IF_ERROR_RETURN( 17168 WRITE_SVP_ATTRS_1m(unit, 17169 MEM_BLOCK_ALL, vp1, 17170 &svp_attrs_1)); 17171 } 17172 /* update other backup ports also here */ 17173 bcmi_mpls_update_dvp_in_backup_ports(unit, vpn_id, vp1); 17174 #ifdef BCM_ENDURO_SUPPORT 17175 if (SOC_IS_ENDURO(unit)) { 17176 BCM_IF_ERROR_RETURN ( 17177 READ_SVP_DISABLE_VLAN_CHECKS_TABm(unit, MEM_BLOCK_ANY, vp1, &svp_disable_check)); 17178 soc_SVP_DISABLE_VLAN_CHECKS_TABm_field32_set(unit, &svp_disable_check, DISABLE_VLAN_CHECKSf, 1); 17179 BCM_IF_ERROR_RETURN ( 17180 WRITE_SVP_DISABLE_VLAN_CHECKS_TABm(unit, MEM_BLOCK_ALL, vp1, &svp_disable_check)); 17181 } 17182 #endif /* BCM_ENDURO_SUPPORT */ 17183 } 17184 if (rv < 0) { 17185 goto vpws_cleanup; 17186 } 17187 } 17188 17189 17190 17191 else if (active_vp == vp2) { 17192 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_APACHE_SUPPORT) 17193 if (SOC_IS_KATANAX(unit) || SOC_IS_TRIUMPH3(unit) || SOC_IS_APACHE(unit)) { 17194 rv = _bcm_esw_add_policer_to_table(unit, 17195 mpls_port->policer_id, 17196 SOURCE_VPm, 0, &svp2); 17197 BCM_IF_ERROR_RETURN(rv); 17198 } 17199 #endif /* BCM_KATANA_SUPPORT or BCM_TRIUMPH3_SUPPORT or BCM_APACHE_SUPPORT */ 17200 /* Set SOURCE_VP */ 17201 soc_SOURCE_VPm_field32_set(unit, &svp2, CLASS_IDf, 17202 mpls_port->if_class); 17203 if (soc_feature(unit, 17204 soc_feature_multiple_split_horizon_group)) { 17205 soc_SOURCE_VPm_field32_set( 17206 unit, &svp2, NETWORK_GROUPf, network_group); 17207 } else { 17208 soc_SOURCE_VPm_field32_set( 17209 unit, &svp2, NETWORK_PORTf, 17210 (mpls_port->flags & BCM_MPLS_PORT_NETWORK) ? 17211 1 : 0); 17212 } 17213 if (mpls_port->flags & BCM_MPLS_PORT_SERVICE_TAGGED) { 17214 soc_SOURCE_VPm_field32_set(unit, &svp2, SD_TAG_MODEf, 1); 17215 17216 #if defined(BCM_TRIDENT3_SUPPORT) 17217 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 17218 uint32 svp_attrs_1[SOC_MAX_MEM_WORDS]; 17219 17220 sal_memset(svp_attrs_1, 0, 17221 sizeof(uint32) * SOC_MAX_MEM_WORDS); 17222 soc_SVP_ATTRS_1m_field_set(unit, 17223 &svp_attrs_1, TPID_ENABLEf, 17224 (uint32 *)&tpid_enable); 17225 BCM_IF_ERROR_RETURN( 17226 WRITE_SVP_ATTRS_1m(unit, 17227 MEM_BLOCK_ALL, active_vp, 17228 &svp_attrs_1)); 17229 } else 17230 #endif 17231 { 17232 soc_SOURCE_VPm_field32_set(unit, &svp2, TPID_ENABLEf, tpid_enable); 17233 } 17234 if (SOC_MEM_FIELD_VALID(unit, SOURCE_VPm, TRUST_OUTER_DOT1Pf)) { 17235 soc_SOURCE_VPm_field32_set(unit, &svp2, TRUST_OUTER_DOT1Pf, 1); 17236 } 17237 } else { 17238 soc_SOURCE_VPm_field32_set(unit, &svp2, SD_TAG_MODEf, 0); 17239 } 17240 17241 if (mpls_port->flags & BCM_MPLS_PORT_REPLACE) { 17242 rv = WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, vp2, &svp2); 17243 if (rv < 0) { 17244 goto vpws_cleanup; 17245 } 17246 /* Link in the newly allocated next-hop entry */ 17247 soc_ING_DVP_TABLEm_field32_set(unit, &dvp2, NEXT_HOP_INDEXf, 17248 nh_index); 17249 /* Enable DVP as Network_port */ 17250 if (soc_mem_field_valid(unit, ING_DVP_TABLEm, NETWORK_PORTf)) { 17251 soc_ING_DVP_TABLEm_field32_set(unit, &dvp2, NETWORK_PORTf, 17252 ((mpls_port->flags & BCM_MPLS_PORT_EGRESS_TUNNEL) && 17253 (mpls_port->flags & BCM_MPLS_PORT_NETWORK) ) ? 1 : 0); 17254 } 17255 if (soc_feature(unit, 17256 soc_feature_multiple_split_horizon_group)) { 17257 if (soc_mem_field_valid( 17258 unit, ING_DVP_TABLEm, NETWORK_GROUPf)) { 17259 soc_ING_DVP_TABLEm_field32_set( 17260 unit, &dvp2, NETWORK_GROUPf, 17261 network_group); 17262 17263 } 17264 17265 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 17266 rv = soc_mem_field32_modify(unit, EGR_DVP_ATTRIBUTEm, 17267 active_vp, 17268 COMMON__DVP_NETWORK_GROUPf, 17269 network_group); 17270 if (rv < 0) { 17271 goto vpws_cleanup; 17272 } 17273 } 17274 } 17275 17276 rv = WRITE_ING_DVP_TABLEm(unit, MEM_BLOCK_ALL, active_vp, &dvp2); 17277 if (rv < 0) { 17278 goto vpws_cleanup; 17279 } 17280 rv = _bcm_vp_ing_dvp_to_ing_dvp2(unit, &dvp2, active_vp); 17281 if (rv < 0) { 17282 goto vpws_cleanup; 17283 } 17284 17285 if (vp3_read != -1) { 17286 /* 17287 * A primary network port already exists. 17288 * vp2 is backup network port. 17289 */ 17290 vp3_match_label = mpls_info->match_key[vp3_read].match_label; 17291 if (mpls_port->criteria == BCM_MPLS_PORT_MATCH_LABEL) { 17292 if (vp3_match_label == mpls_port->match_label) { 17293 /* 17294 * If same label is used for match on primary and backup, 17295 * no need to add another MPLS_ENTRY for backup 17296 */ 17297 match_add = FALSE; 17298 if(!((mpls_info->match_key[vp2].match_label == -1) || 17299 (vp3_match_label == mpls_info->match_key[vp2].match_label))){ 17300 /* Delete old MPLS_ENTRY, update software record*/ 17301 (void)_bcm_esw_mpls_match_delete(unit, vp2, TRUE); 17302 mpls_info->match_key[vp2].flags = 17303 _BCM_MPLS_PORT_MATCH_TYPE_LABEL; 17304 mpls_info->match_key[vp2].match_label = 17305 mpls_port->match_label; 17306 mpls_info->match_key[vp2].modid = 0; 17307 mpls_info->match_key[vp2].port = 0; 17308 } 17309 } 17310 } 17311 } 17312 } else { 17313 /* we may have other backup ports coming up with 17314 * the same label as vp2 label, So we might have 17315 * to make sure that we dont update the match entry. 17316 */ 17317 if ((backup_vp2 != -1) && (backup_vp2 != vp2)) { 17318 if ((mpls_port->criteria == 17319 BCM_MPLS_PORT_MATCH_LABEL) && 17320 (mpls_info->match_key[backup_vp2].match_label == 17321 mpls_port->match_label)) { 17322 /* 17323 * If same label is used for match on other backup, 17324 * no need to add another MPLS_ENTRY for backup 17325 */ 17326 match_add = FALSE; 17327 } 17328 } 17329 17330 /* Link in the newly allocated next-hop entry to DVP */ 17331 soc_ING_DVP_TABLEm_field32_set(unit, &dvp2, NEXT_HOP_INDEXf, 17332 nh_index); 17333 /* Enable DVP as Network_port */ 17334 if (soc_mem_field_valid(unit, ING_DVP_TABLEm, NETWORK_PORTf)) { 17335 soc_ING_DVP_TABLEm_field32_set(unit, &dvp2, NETWORK_PORTf, 17336 ((mpls_port->flags & BCM_MPLS_PORT_EGRESS_TUNNEL) && 17337 (mpls_port->flags & BCM_MPLS_PORT_NETWORK) ) ? 1 : 0); 17338 } 17339 17340 if (soc_feature(unit, 17341 soc_feature_multiple_split_horizon_group)) { 17342 if (soc_mem_field_valid( 17343 unit, ING_DVP_TABLEm, NETWORK_GROUPf)) { 17344 soc_ING_DVP_TABLEm_field32_set( 17345 unit, &dvp2, NETWORK_GROUPf, 17346 network_group); 17347 17348 } 17349 17350 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 17351 rv = soc_mem_field32_modify(unit, EGR_DVP_ATTRIBUTEm, 17352 active_vp, 17353 COMMON__DVP_NETWORK_GROUPf, 17354 network_group); 17355 if (rv < 0) { 17356 goto vpws_cleanup; 17357 } 17358 } 17359 } 17360 17361 rv = WRITE_ING_DVP_TABLEm(unit, MEM_BLOCK_ALL, active_vp, &dvp2); 17362 if (rv < 0) { 17363 goto vpws_cleanup; 17364 } 17365 rv = _bcm_vp_ing_dvp_to_ing_dvp2(unit, &dvp2, active_vp); 17366 if (rv < 0) { 17367 goto vpws_cleanup; 17368 } 17369 17370 /* Tie the SVP to DVP. If only one port is valid, point to itself */ 17371 soc_SOURCE_VPm_field32_set(unit, &svp2, 17372 ENTRY_TYPEf, 0x2); /* VPWS */ 17373 17374 if (soc_feature(unit, soc_feature_generic_dest)) { 17375 soc_mem_field32_dest_set(unit, SOURCE_VPm, &svp2, 17376 DESTINATIONf, SOC_MEM_FIF_DEST_DVP, 17377 (vp_valid_flag == 0x3) ? vp1 : vp2); 17378 } else { 17379 soc_SOURCE_VPm_field32_set(unit, &svp2, DVPf, 17380 (vp_valid_flag == 0x3) ? vp1 : vp2); 17381 } 17382 if (soc_mem_field_valid(unit, SOURCE_VPm, DISABLE_VLAN_CHECKSf)) { 17383 soc_SOURCE_VPm_field32_set(unit, &svp2, DISABLE_VLAN_CHECKSf, 1); 17384 } 17385 if (soc_mem_field_valid(unit, SOURCE_VPm, SRC_PORTf) && 17386 soc_mem_field_valid(unit, SOURCE_VPm, SRC_MODIDf)) { 17387 rv = _bcm_tr_mpls_l2vpn_source_port_set(unit, mpls_port, &svp2); 17388 } 17389 if (rv < 0) { 17390 goto vpws_cleanup; 17391 } 17392 17393 if (soc_mem_field_valid(unit, SOURCE_VPm, SVP_PROFILE_INDEXf)) { 17394 if(mpls_port->flags & BCM_MPLS_PORT_EGRESS_TUNNEL) { 17395 soc_SOURCE_VPm_field32_set(unit, &svp2, SVP_PROFILE_INDEXf, 3); 17396 } else { 17397 soc_SOURCE_VPm_field32_set(unit, &svp2, SVP_PROFILE_INDEXf, 2); 17398 } 17399 17400 17401 } 17402 rv = WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, active_vp, &svp2); 17403 /* we write source_vp entry only when we create the first port or it is primary port. 17404 usually primary port will be vp3, as failover needs to be created first */ 17405 if (rv >= 0) { 17406 int vp3_valid = 0; 17407 if (vp_valid_flag == 0x3) { 17408 if (soc_feature(unit, soc_feature_generic_dest)) { 17409 dest_val = soc_mem_field32_dest_get(unit, SOURCE_VPm, 17410 &svp1, DESTINATIONf, &dest_type); 17411 if (dest_type == SOC_MEM_FIF_DEST_DVP) { 17412 vp3 = dest_val; 17413 } 17414 } else { 17415 vp3 = soc_SOURCE_VPm_field32_get(unit, &svp1, DVPf); 17416 } 17417 } 17418 else if (vp3_read != -1) { 17419 vp3 = vp3_read; 17420 } 17421 if ((vp3 != -1) && (_bcm_vp_used_get(unit, vp3, _bcmVpTypeMpls))) { 17422 vp3_valid = 1; 17423 } 17424 if (!vp3_valid || (vp3_valid && 17425 BCM_SUCCESS(_bcm_esw_failover_mpls_check(unit, mpls_port)))) { 17426 if (vp_valid_flag == 0x3) { 17427 if (soc_feature(unit, soc_feature_generic_dest)) { 17428 soc_mem_field32_dest_set(unit, SOURCE_VPm, &svp1, 17429 DESTINATIONf, SOC_MEM_FIF_DEST_DVP, vp2); 17430 } else { 17431 soc_SOURCE_VPm_field32_set(unit, &svp1, DVPf, vp2); 17432 } 17433 if (vp1 != -1) { 17434 rv = WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, vp1, &svp1); 17435 } 17436 } 17437 } else { 17438 rv = READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp3, &dvp3); 17439 prot_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp3, 17440 NEXT_HOP_INDEXf); 17441 17442 if (bcmi_mpls_port_failover_update_is_required 17443 (unit, mpls_port, prot_index, nh_index)) { 17444 /* if user does not send any if id then he might 17445 * want to use the same NH as prot NH. 17446 * that way next 3 NHs are used as backup NHs. 17447 * other option is that he might be sending mc group, 17448 * but in that case we will not even use failover_if_id. 17449 */ 17450 17451 rv = _bcm_esw_failover_prot_nhi_create 17452 (unit, 0, (uint32)prot_index, 17453 nh_index, mpls_port->failover_mc_group, 17454 mpls_port->failover_id); 17455 17456 } 17457 } 17458 17459 } 17460 if (rv < 0) { 17461 goto vpws_cleanup; 17462 } 17463 #ifdef BCM_ENDURO_SUPPORT 17464 if (SOC_IS_ENDURO(unit)) { 17465 BCM_IF_ERROR_RETURN ( 17466 READ_SVP_DISABLE_VLAN_CHECKS_TABm(unit, MEM_BLOCK_ANY, active_vp, &svp_disable_check)); 17467 soc_SVP_DISABLE_VLAN_CHECKS_TABm_field32_set(unit, &svp_disable_check, DISABLE_VLAN_CHECKSf, 1); 17468 BCM_IF_ERROR_RETURN ( 17469 WRITE_SVP_DISABLE_VLAN_CHECKS_TABm(unit, MEM_BLOCK_ALL, active_vp, &svp_disable_check)); 17470 } 17471 #endif /* BCM_ENDURO_SUPPORT */ 17472 } 17473 } 17474 17475 17476 17477 else if (active_vp == vp3) { 17478 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_APACHE_SUPPORT) 17479 if (SOC_IS_KATANAX(unit) || SOC_IS_TRIUMPH3(unit) || SOC_IS_APACHE(unit)) { 17480 rv = _bcm_esw_add_policer_to_table(unit, 17481 mpls_port->policer_id, 17482 SOURCE_VPm, 0, &svp3); 17483 BCM_IF_ERROR_RETURN(rv); 17484 } 17485 #endif /* BCM_KATANA_SUPPORT or BCM_TRIUMPH3_SUPPORT or BCM_APACHE_SUPPORT */ 17486 /* Set SOURCE_VP */ 17487 soc_SOURCE_VPm_field32_set(unit, &svp3, CLASS_IDf, 17488 mpls_port->if_class); 17489 if (soc_feature(unit, 17490 soc_feature_multiple_split_horizon_group)) { 17491 soc_SOURCE_VPm_field32_set( 17492 unit, &svp3, NETWORK_GROUPf, network_group); 17493 } else { 17494 soc_SOURCE_VPm_field32_set( 17495 unit, &svp3, NETWORK_PORTf, 17496 (mpls_port->flags & BCM_MPLS_PORT_NETWORK) ? 17497 1 : 0); 17498 } 17499 if (mpls_port->flags & BCM_MPLS_PORT_SERVICE_TAGGED) { 17500 soc_SOURCE_VPm_field32_set(unit, &svp3, 17501 SD_TAG_MODEf, 1); 17502 17503 #if defined(BCM_TRIDENT3_SUPPORT) 17504 if (SOC_IS_TRIDENT3X(unit)) { 17505 uint32 svp_attrs_1[SOC_MAX_MEM_WORDS]; 17506 17507 sal_memset(svp_attrs_1, 0, 17508 sizeof(uint32) * SOC_MAX_MEM_WORDS); 17509 soc_SVP_ATTRS_1m_field_set(unit, 17510 &svp_attrs_1, TPID_ENABLEf, 17511 (uint32 *)&tpid_enable); 17512 BCM_IF_ERROR_RETURN( 17513 WRITE_SVP_ATTRS_1m(unit, 17514 MEM_BLOCK_ALL, active_vp, 17515 &svp_attrs_1)); 17516 } else 17517 #endif 17518 { 17519 soc_SOURCE_VPm_field32_set(unit, &svp3, 17520 TPID_ENABLEf, tpid_enable); 17521 } 17522 if (SOC_MEM_FIELD_VALID(unit, SOURCE_VPm, TRUST_OUTER_DOT1Pf)) { 17523 soc_SOURCE_VPm_field32_set(unit, &svp3, TRUST_OUTER_DOT1Pf, 1); 17524 } 17525 } else { 17526 soc_SOURCE_VPm_field32_set(unit, &svp3, 17527 SD_TAG_MODEf, 0); 17528 } 17529 if (mpls_port->flags & BCM_MPLS_PORT_REPLACE) { 17530 rv = WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, vp3, &svp3); 17531 if (rv < 0) { 17532 goto vpws_cleanup; 17533 } 17534 /* Link in the newly allocated next-hop entry */ 17535 soc_ING_DVP_TABLEm_field32_set(unit, &dvp3, 17536 NEXT_HOP_INDEXf, nh_index); 17537 /* Enable DVP as Network_port */ 17538 if (soc_mem_field_valid(unit, ING_DVP_TABLEm, NETWORK_PORTf)) { 17539 soc_ING_DVP_TABLEm_field32_set(unit, &dvp3, NETWORK_PORTf, 17540 ((mpls_port->flags & BCM_MPLS_PORT_EGRESS_TUNNEL) && 17541 (mpls_port->flags & BCM_MPLS_PORT_NETWORK) ) ? 1 : 0); 17542 } 17543 17544 if (soc_feature(unit, 17545 soc_feature_multiple_split_horizon_group)) { 17546 if (soc_mem_field_valid( 17547 unit, ING_DVP_TABLEm, NETWORK_GROUPf)) { 17548 soc_ING_DVP_TABLEm_field32_set( 17549 unit, &dvp3, NETWORK_GROUPf, network_group); 17550 } 17551 17552 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 17553 rv = soc_mem_field32_modify(unit, EGR_DVP_ATTRIBUTEm, 17554 active_vp, 17555 COMMON__DVP_NETWORK_GROUPf, 17556 network_group); 17557 if (rv < 0) { 17558 goto vpws_cleanup; 17559 } 17560 } 17561 } 17562 17563 rv = WRITE_ING_DVP_TABLEm(unit, MEM_BLOCK_ALL, 17564 active_vp, &dvp3); 17565 if (rv < 0) { 17566 goto vpws_cleanup; 17567 } 17568 rv = _bcm_vp_ing_dvp_to_ing_dvp2(unit, &dvp3, active_vp); 17569 if (rv < 0) { 17570 goto vpws_cleanup; 17571 } 17572 17573 } else { 17574 /* Link in the newly allocated next-hop entry to DVP */ 17575 soc_ING_DVP_TABLEm_field32_set(unit, &dvp3, 17576 NEXT_HOP_INDEXf, nh_index); 17577 /* Enable DVP as Network_port */ 17578 if (soc_mem_field_valid(unit, ING_DVP_TABLEm, NETWORK_PORTf)) { 17579 soc_ING_DVP_TABLEm_field32_set(unit, &dvp3, NETWORK_PORTf, 17580 ((mpls_port->flags & BCM_MPLS_PORT_EGRESS_TUNNEL) && 17581 (mpls_port->flags & BCM_MPLS_PORT_NETWORK) ) ? 1 : 0); 17582 } 17583 17584 if (soc_feature(unit, 17585 soc_feature_multiple_split_horizon_group)) { 17586 if (soc_mem_field_valid( 17587 unit, ING_DVP_TABLEm, NETWORK_GROUPf)) { 17588 soc_ING_DVP_TABLEm_field32_set( 17589 unit, &dvp3, NETWORK_GROUPf, network_group); 17590 } 17591 17592 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 17593 rv = soc_mem_field32_modify(unit, EGR_DVP_ATTRIBUTEm, 17594 active_vp, 17595 COMMON__DVP_NETWORK_GROUPf, 17596 network_group); 17597 if (rv < 0) { 17598 goto vpws_cleanup; 17599 } 17600 } 17601 } 17602 17603 rv = WRITE_ING_DVP_TABLEm(unit, MEM_BLOCK_ALL, 17604 active_vp, &dvp3); 17605 if (rv < 0) { 17606 goto vpws_cleanup; 17607 } 17608 rv = _bcm_vp_ing_dvp_to_ing_dvp2(unit, &dvp3, active_vp); 17609 if (rv < 0) { 17610 goto vpws_cleanup; 17611 } 17612 17613 if (vpn == BCM_MPLS_VPWS_VPN_INVALID) { 17614 /* Set SVP Invalid */ 17615 soc_SOURCE_VPm_field32_set(unit, &svp3, 17616 ENTRY_TYPEf, 0x0); 17617 } else { 17618 /* Set SVP Valid */ 17619 soc_SOURCE_VPm_field32_set(unit, &svp3, 17620 ENTRY_TYPEf, 0x2); 17621 /* Tie SVP to DVP. */ 17622 if (vp1 != -1) { 17623 if (soc_feature(unit, soc_feature_generic_dest)) { 17624 soc_mem_field32_dest_set(unit, SOURCE_VPm, &svp3, 17625 DESTINATIONf, SOC_MEM_FIF_DEST_DVP, vp1); 17626 } else { 17627 soc_SOURCE_VPm_field32_set(unit, &svp3, DVPf, vp1); 17628 } 17629 } 17630 } 17631 if (soc_mem_field_valid(unit, SOURCE_VPm, DISABLE_VLAN_CHECKSf)) { 17632 soc_SOURCE_VPm_field32_set(unit, &svp3, DISABLE_VLAN_CHECKSf, 1); 17633 } 17634 if (soc_mem_field_valid(unit, SOURCE_VPm, SRC_PORTf) && 17635 soc_mem_field_valid(unit, SOURCE_VPm, SRC_MODIDf)) { 17636 rv = _bcm_tr_mpls_l2vpn_source_port_set(unit, mpls_port, &svp3); 17637 } 17638 if (rv < 0) { 17639 goto vpws_cleanup; 17640 } 17641 17642 if (soc_mem_field_valid(unit, SOURCE_VPm, SVP_PROFILE_INDEXf)) { 17643 if(mpls_port->flags & BCM_MPLS_PORT_EGRESS_TUNNEL) { 17644 soc_SOURCE_VPm_field32_set(unit, &svp3, SVP_PROFILE_INDEXf, 3); 17645 } else { 17646 soc_SOURCE_VPm_field32_set(unit, &svp3, SVP_PROFILE_INDEXf, 2); 17647 } 17648 17649 } 17650 rv = WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, 17651 active_vp, &svp3); 17652 if ((rv >= 0) && (vp_valid_flag == 0x3)) { 17653 if (soc_feature(unit, soc_feature_generic_dest)) { 17654 soc_mem_field32_dest_set(unit, SOURCE_VPm, &svp1, 17655 DESTINATIONf, SOC_MEM_FIF_DEST_DVP, vp3); 17656 } else { 17657 soc_SOURCE_VPm_field32_set(unit, &svp1, DVPf, vp3); 17658 } 17659 rv = WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, vp1, &svp1); 17660 } 17661 if (rv < 0) { 17662 goto vpws_cleanup; 17663 } 17664 #ifdef BCM_ENDURO_SUPPORT 17665 if (SOC_IS_ENDURO(unit)) { 17666 BCM_IF_ERROR_RETURN ( 17667 READ_SVP_DISABLE_VLAN_CHECKS_TABm(unit, MEM_BLOCK_ANY, active_vp, &svp_disable_check)); 17668 soc_SVP_DISABLE_VLAN_CHECKS_TABm_field32_set(unit, &svp_disable_check, DISABLE_VLAN_CHECKSf, 1); 17669 BCM_IF_ERROR_RETURN ( 17670 WRITE_SVP_DISABLE_VLAN_CHECKS_TABm(unit, MEM_BLOCK_ALL, active_vp, &svp_disable_check)); 17671 } 17672 #endif /* BCM_ENDURO_SUPPORT */ 17673 } 17674 17675 } 17676 17677 #if defined(BCM_TRIUMPH2_SUPPORT) 17678 if (soc_feature(unit, soc_feature_mpls_failover)) { 17679 int failover_vp = 0; 17680 bcm_mpls_port_t failover_mpls_port; 17681 17682 if (BCM_SUCCESS(_bcm_esw_failover_mpls_check(unit, mpls_port))) { 17683 17684 failover_vp = BCM_GPORT_MPLS_PORT_ID_GET(mpls_port->failover_port_id); 17685 17686 if (failover_vp >= 0) { 17687 if (!_bcm_vp_used_get(unit, failover_vp, _bcmVpTypeMpls)) { 17688 rv = BCM_E_NOT_FOUND; 17689 goto vpws_cleanup; 17690 } 17691 rv = _bcm_esw_mpls_match_get(unit, &failover_mpls_port, failover_vp); 17692 if ( rv < 0 ) { 17693 if (rv != BCM_E_NOT_FOUND) { 17694 goto vpws_cleanup; 17695 } 17696 } 17697 if (mpls_port->criteria == BCM_MPLS_PORT_MATCH_LABEL_PORT) { 17698 if ((mpls_port->match_label == failover_mpls_port.match_label) && 17699 (mpls_port->port == failover_mpls_port.port)) { 17700 17701 /* 17702 * Replace failover_vp with Primary vp, keep software record 17703 * for get operation. 17704 */ 17705 rv = _bcm_esw_mpls_match_delete(unit, failover_vp, FALSE); 17706 } 17707 } else if (mpls_port->criteria == BCM_MPLS_PORT_MATCH_LABEL) { 17708 if (mpls_port->match_label == failover_mpls_port.match_label) { 17709 /* 17710 * Replace failover_vp with Primary vp, keep software record 17711 * for get operation. 17712 */ 17713 rv = _bcm_esw_mpls_match_delete(unit, failover_vp, FALSE); 17714 } 17715 } 17716 } 17717 } 17718 } 17719 #endif /* BCM_TRIUMPH2_SUPPORT */ 17720 17721 if (soc_mem_field_valid(unit, EGR_DVP_ATTRIBUTEm, MTU_VALUEf) || 17722 soc_mem_field_valid(unit, EGR_DVP_ATTRIBUTEm, COMMON__MTU_VALUEf)) { 17723 rv = _bcm_tr_mpls_port_mtu_set(unit, active_vp, mpls_port->mtu); 17724 if (rv < 0) { 17725 goto vpws_cleanup; 17726 } 17727 } 17728 17729 /*CMH SVP ATTRIBUTES*/ 17730 if (soc_feature(unit,soc_feature_td3_style_mpls)) { 17731 int entry_type = 2; 17732 rv = bcmi_cmh_svp_attributes_set(unit, entry_type, active_vp, 17733 TRUE, mpls_port->flags); 17734 if (rv < 0) { 17735 goto vpws_cleanup; 17736 } 17737 } 17738 17739 if (TRUE == match_add) { 17740 rv = _bcm_esw_mpls_match_add(unit, mpls_port, active_vp, vpn, TRUE); 17741 } 17742 17743 /* Set the MPLS port ID */ 17744 if (!(mpls_port->flags & BCM_MPLS_PORT_REPLACE)) { 17745 BCM_GPORT_MPLS_PORT_ID_SET(mpls_port->mpls_port_id, active_vp); 17746 mpls_port->encap_id = BCM_XGS3_DVP_EGRESS_IDX_MIN(unit) + nh_index; 17747 } 17748 #if defined(BCM_TRIUMPH2_SUPPORT) 17749 if (!BCM_GPORT_IS_TRUNK(mpls_port->port)) { 17750 if (!(mpls_port->flags2 & BCM_MPLS_PORT2_QOS_NONE)) { 17751 _bcm_mpls_source_vp_set(unit, mpls_port, active_vp); 17752 } 17753 } 17754 #endif 17755 17756 /* Free the old next-hop entry. */ 17757 if (vp_valid_flag != 0x30) { 17758 (void)_bcm_tr_mpls_l2_old_nh_info_delete(unit, mpls_port, nh_index, 17759 &old_nh_info); 17760 } 17761 17762 vpws_cleanup: 17763 if (rv < 0) { 17764 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) || \ 17765 defined(BCM_APACHE_SUPPORT) 17766 if (SOC_IS_KATANAX(unit) || SOC_IS_TRIUMPH3(unit) || 17767 SOC_IS_APACHE(unit)) { 17768 _bcm_esw_reset_policer_from_table(unit, 17769 mpls_port->policer_id, 17770 SOURCE_VPm, active_vp, &svp1); 17771 } 17772 #endif /* BCM_KATANA_SUPPORT or BCM_TRIUMPH3_SUPPORT or BCM_APACHE_SUPPORT */ 17773 if (tpid_enable) { 17774 (void) _bcm_fb2_outer_tpid_entry_delete(unit, tpid_index); 17775 } 17776 17777 if (!(mpls_port->flags & BCM_MPLS_PORT_REPLACE)) { 17778 (void) _bcm_tr_mpls_l2_nh_info_delete(unit, nh_index); 17779 17780 /* Free the VP's */ 17781 if (vp_valid_flag) { 17782 if (vp1 == active_vp) { 17783 (void) _bcm_vp_free(unit, _bcmVpTypeMpls, 1, vp1); 17784 if (vpn != BCM_MPLS_VPWS_VPN_INVALID) { 17785 (void) _bcm_tr_mpls_vpws_vp_map_set(unit, vpn_id, -1, vp2, vp3_read); 17786 } 17787 } 17788 if (vp2 == active_vp) { 17789 (void) _bcm_vp_free(unit, _bcmVpTypeMpls, 1, vp2); 17790 _BCM_MPLS_NETWORK_VP_USED_CLR(unit, vp2); 17791 if (vpn != BCM_MPLS_VPWS_VPN_INVALID) { 17792 (void) _bcm_tr_mpls_vpws_vp_map_set(unit, vpn_id, vp1, -1, vp3_read); 17793 } 17794 } 17795 } 17796 } 17797 17798 return rv; 17799 } 17800 17801 return rv; 17802 } 17803 17804 /* 17805 * Function: 17806 * _bcm_tr_mpls_vpls_port_add 17807 * Purpose: 17808 * Add VPLS port to a VPN 17809 * Parameters: 17810 * unit - (IN) Device Number 17811 * vpn - (IN) VPN instance ID 17812 * mpls_port - (IN/OUT) mpls port information (OUT : mpls_port_id) 17813 * Returns: 17814 * BCM_E_XXX 17815 */ 17816 17817 STATIC int 17818 _bcm_tr_mpls_vpls_port_add(int unit, bcm_vpn_t vpn, bcm_mpls_port_t *mpls_port) 17819 { 17820 int vp, num_vp, vfi = 0; 17821 source_vp_entry_t svp; 17822 ing_dvp_table_entry_t dvp; 17823 #if defined(BCM_TRIDENT2_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) \ 17824 || defined(BCM_TRIDENT_SUPPORT) 17825 ing_dvp_2_table_entry_t dvp2; 17826 #endif /* BCM_TRIDENT2_SUPPORT or BCM_TRIUMPH3_SUPPORT or BCM_TRIDENT_SUPPORT */ 17827 ing_l3_next_hop_entry_t ing_nh; 17828 int modid_local=0, module_id, is_trunk=0; 17829 bcm_port_t local_port; 17830 bcm_trunk_t trunk_id = -1; 17831 int tpid_enable = 0, tpid_index; 17832 int drop, is_local = 0, rv = BCM_E_PARAM, nh_index = 0; 17833 int cml_default_enable=0, cml_default_new=0, cml_default_move=0; 17834 _bcm_mpls_old_nh_info_t old_nh_info; 17835 #ifdef BCM_ENDURO_SUPPORT 17836 svp_disable_vlan_checks_tab_entry_t svp_disable_check; 17837 #endif /* BCM_ENDURO_SUPPORT */ 17838 int entry_update = TRUE; 17839 _bcm_vp_info_t vp_info; 17840 bcm_switch_network_group_t network_group; 17841 uint32 dest_type, dest_val; 17842 int port_in = 0; 17843 egr_dvp_attribute_entry_t egr_dvp_attribute; 17844 17845 #ifdef BCM_TRIUMPH2_SUPPORT 17846 _bcm_tr_mpls_bookkeeping_t *mpls_info = MPLS_INFO(unit); 17847 uint32 old_failover_vp = 0; 17848 #endif 17849 _bcm_vp_info_init(&vp_info); 17850 vp_info.vp_type = _bcmVpTypeMpls; 17851 17852 if (mpls_port->criteria != BCM_MPLS_PORT_MATCH_SHARE) { 17853 if ( vpn != BCM_MPLS_VPLS_VPN_INVALID) { 17854 _BCM_MPLS_VPN_GET(vfi, _BCM_MPLS_VPN_TYPE_VPLS, vpn); 17855 if (!_bcm_vfi_used_get(unit, vfi, _bcmVfiTypeMpls)) { 17856 return BCM_E_NOT_FOUND; 17857 } 17858 } else { 17859 vfi = 0x3FF; 17860 } 17861 } 17862 17863 sal_memset(&egr_dvp_attribute, 0, 17864 sizeof(egr_dvp_attribute_entry_t)); 17865 if (mpls_port->flags & BCM_MPLS_PORT_REPLACE) { 17866 vp = BCM_GPORT_MPLS_PORT_ID_GET(mpls_port->mpls_port_id); 17867 17868 if (vp == -1) { 17869 return BCM_E_PARAM; 17870 } 17871 17872 if (_BCM_MPLS_GPORT_FAILOVER_VPLESS_GET(vp)) { 17873 vp = _BCM_MPLS_GPORT_FAILOVER_VPLESS_CLEAR(vp); 17874 } 17875 17876 if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeMpls)) { 17877 return BCM_E_NOT_FOUND; 17878 } 17879 rv = READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp, &svp); 17880 if (rv < 0) { 17881 return rv; 17882 } 17883 rv = READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp, &dvp); 17884 if (rv < 0) { 17885 return rv; 17886 } 17887 nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, 17888 NEXT_HOP_INDEXf); 17889 if (soc_feature(unit, soc_feature_mpls_software_failover)) { 17890 /* VP Detach */ 17891 if ((soc_SOURCE_VPm_field32_get(unit, &svp, ENTRY_TYPEf) == 0x1) && 17892 (vpn == BCM_MPLS_VPLS_VPN_INVALID)){ 17893 soc_SOURCE_VPm_field32_set(unit, &svp, ENTRY_TYPEf, 0x0); 17894 BCM_IF_ERROR_RETURN (soc_mem_read(unit, ING_L3_NEXT_HOPm, 17895 MEM_BLOCK_ANY, nh_index, &ing_nh)); 17896 /* Set Drop */ 17897 soc_mem_field32_set(unit, ING_L3_NEXT_HOPm, &ing_nh, DROPf, 0x1); 17898 BCM_IF_ERROR_RETURN(soc_mem_write (unit, ING_L3_NEXT_HOPm, 17899 MEM_BLOCK_ALL, nh_index, &ing_nh)); 17900 rv = WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, vp, &svp); 17901 return rv; 17902 } 17903 17904 /* VP Attach */ 17905 if ((soc_SOURCE_VPm_field32_get(unit, &svp, ENTRY_TYPEf) == 0x0) && 17906 (vpn != BCM_MPLS_VPLS_VPN_INVALID)){ 17907 soc_SOURCE_VPm_field32_set(unit, &svp, ENTRY_TYPEf, 0x1); 17908 BCM_IF_ERROR_RETURN (soc_mem_read(unit, ING_L3_NEXT_HOPm, 17909 MEM_BLOCK_ANY, nh_index, &ing_nh)); 17910 /* Reset Drop */ 17911 soc_mem_field32_set(unit, ING_L3_NEXT_HOPm, &ing_nh, DROPf, 0x0); 17912 BCM_IF_ERROR_RETURN(soc_mem_write (unit, ING_L3_NEXT_HOPm, 17913 MEM_BLOCK_ALL, nh_index, &ing_nh)); 17914 if (mpls_port->criteria != BCM_MPLS_PORT_MATCH_SHARE) { 17915 soc_SOURCE_VPm_field32_set(unit, &svp, VFIf, vfi); 17916 _bcm_vp_vfi_set(unit, vp, vpn); 17917 } 17918 rv = WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, vp, &svp); 17919 return rv; 17920 } 17921 } 17922 17923 } else if (mpls_port->flags & BCM_MPLS_PORT_WITH_ID ) { 17924 int vpless_port = FALSE; 17925 if (!BCM_GPORT_IS_MPLS_PORT(mpls_port->mpls_port_id)) { 17926 return (BCM_E_BADID); 17927 } 17928 17929 num_vp = soc_mem_index_count(unit, SOURCE_VPm); 17930 vp = BCM_GPORT_MPLS_PORT_ID_GET(mpls_port->mpls_port_id); 17931 if (_BCM_MPLS_GPORT_FAILOVER_VPLESS_GET(vp)) { 17932 vp = _BCM_MPLS_GPORT_FAILOVER_VPLESS_CLEAR(vp); 17933 vpless_port = TRUE; 17934 } 17935 17936 if (vp == -1) { 17937 return BCM_E_PARAM; 17938 } 17939 17940 if (vp >= num_vp) { 17941 return (BCM_E_BADID); 17942 } 17943 17944 if ((vpn != BCM_MPLS_VPLS_VPN_INVALID) && (!vpless_port)) { 17945 if (_bcm_vp_used_get(unit, vp, _bcmVpTypeMpls)) { 17946 return BCM_E_EXISTS; 17947 } 17948 } 17949 17950 if (mpls_port->flags & BCM_MPLS_PORT_NETWORK) { 17951 vp_info.flags |= _BCM_VP_INFO_NETWORK_PORT; 17952 } else { 17953 vp_info.flags &= ~(_BCM_VP_INFO_NETWORK_PORT); 17954 } 17955 17956 BCM_IF_ERROR_RETURN(_bcm_vp_used_set(unit, vp, vp_info)); 17957 17958 /* ------------ SW Failover - Applicable for TRIUMPH/VL only ---- */ 17959 if (soc_feature(unit, soc_feature_mpls_software_failover)) { 17960 17961 if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeMpls)) { 17962 return BCM_E_NOT_FOUND; 17963 } 17964 rv = READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp, &svp); 17965 if (rv < 0) { 17966 return rv; 17967 } 17968 rv = READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp, &dvp); 17969 if (rv < 0) { 17970 return rv; 17971 } 17972 nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, NEXT_HOP_INDEXf); 17973 if ((nh_index != 0) && (nh_index < soc_mem_index_count(unit, ING_L3_NEXT_HOPm))) { 17974 BCM_IF_ERROR_RETURN (soc_mem_read(unit, ING_L3_NEXT_HOPm, 17975 MEM_BLOCK_ANY, nh_index, &ing_nh)); 17976 17977 17978 if (soc_feature(unit, soc_feature_generic_dest)) { 17979 dest_val = soc_mem_field32_dest_get(unit, ING_L3_NEXT_HOPm, 17980 &ing_nh, DESTINATIONf, &dest_type); 17981 if (dest_type == SOC_MEM_FIF_DEST_LAG) { 17982 /* Trunk group */ 17983 trunk_id = dest_val & SOC_MEM_FIF_DGPP_TGID_MASK; 17984 is_trunk = 1; 17985 17986 } else { 17987 port_in = dest_val & SOC_MEM_FIF_DGPP_PORT_MASK; 17988 module_id = (dest_val & SOC_MEM_FIF_DGPP_MOD_ID_MASK) >> 17989 SOC_MEM_FIF_DGPP_MOD_ID_SHIFT_BITS; 17990 } 17991 17992 if (!is_trunk) { 17993 BCM_IF_ERROR_RETURN 17994 ( _bcm_esw_modid_is_local(unit, module_id, &modid_local)); 17995 } 17996 if (modid_local) { 17997 local_port = port_in; 17998 } else if (is_trunk) { 17999 BCM_GPORT_TRUNK_SET(local_port, trunk_id); 18000 } 18001 } else { 18002 module_id = soc_mem_field32_get(unit, ING_L3_NEXT_HOPm, 18003 &ing_nh, MODULE_IDf); 18004 is_trunk = soc_mem_field32_get(unit, ING_L3_NEXT_HOPm, 18005 &ing_nh, Tf); 18006 if (!is_trunk) { 18007 BCM_IF_ERROR_RETURN 18008 ( _bcm_esw_modid_is_local(unit, module_id, &modid_local)); 18009 } 18010 if (modid_local) { 18011 local_port = 18012 soc_mem_field32_get(unit, ING_L3_NEXT_HOPm, &ing_nh, PORT_NUMf); 18013 } else if (is_trunk) { 18014 trunk_id = 18015 soc_mem_field32_get(unit, ING_L3_NEXT_HOPm, &ing_nh, TGIDf); 18016 BCM_GPORT_TRUNK_SET(local_port, trunk_id); 18017 } 18018 } 18019 /* VP Detach */ 18020 if ((soc_SOURCE_VPm_field32_get(unit, &svp, ENTRY_TYPEf) == 0x1) && 18021 (vpn == BCM_MPLS_VPLS_VPN_INVALID)){ 18022 soc_SOURCE_VPm_field32_set(unit, &svp, ENTRY_TYPEf, 0x0); 18023 /* Set Drop */ 18024 soc_mem_field32_set(unit, ING_L3_NEXT_HOPm, &ing_nh, DROPf, 0x1); 18025 BCM_IF_ERROR_RETURN(soc_mem_write (unit, ING_L3_NEXT_HOPm, 18026 MEM_BLOCK_ALL, nh_index, &ing_nh)); 18027 rv = WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, vp, &svp); 18028 return rv; 18029 } 18030 18031 /* VP Attach */ 18032 if ((soc_SOURCE_VPm_field32_get(unit, &svp, ENTRY_TYPEf) == 0x0) && 18033 (vpn != BCM_MPLS_VPLS_VPN_INVALID)){ 18034 soc_SOURCE_VPm_field32_set(unit, &svp, ENTRY_TYPEf, 0x1); 18035 /* Reset Drop */ 18036 soc_mem_field32_set(unit, ING_L3_NEXT_HOPm, &ing_nh, DROPf, 0x0); 18037 BCM_IF_ERROR_RETURN(soc_mem_write (unit, ING_L3_NEXT_HOPm, 18038 MEM_BLOCK_ALL, nh_index, &ing_nh)); 18039 rv = WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, vp, &svp); 18040 return rv; 18041 } 18042 } 18043 } 18044 18045 sal_memset(&svp, 0, sizeof(source_vp_entry_t)); 18046 sal_memset(&dvp, 0, sizeof(ing_dvp_table_entry_t)); 18047 #if defined(BCM_TRIDENT2_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) \ 18048 || defined(BCM_TRIDENT_SUPPORT) 18049 if (SOC_IS_TRIUMPH3(unit) || SOC_IS_TRIDENT2X(unit) 18050 || SOC_IS_TRIDENT(unit) || SOC_IS_TRIDENT3X(unit) || 18051 SOC_IS_TOMAHAWKX(unit)) { 18052 sal_memset(&dvp2, 0, sizeof(ing_dvp_2_table_entry_t)); 18053 } 18054 #endif /* BCM_TRIDENT2_SUPPORT or BCM_TRIUMPH3_SUPPORT or BCM_TRIDENT_SUPPORT */ 18055 /*Set EGR_DVP_ATTRIBUTE indexed by vp to zero*/ 18056 if (SOC_MEM_IS_VALID(unit, EGR_DVP_ATTRIBUTEm)) { 18057 BCM_IF_ERROR_RETURN(WRITE_EGR_DVP_ATTRIBUTEm(unit, 18058 MEM_BLOCK_ALL, vp, &egr_dvp_attribute)); 18059 } 18060 } else { 18061 if (mpls_port->flags & BCM_MPLS_PORT_NETWORK) { 18062 vp_info.flags |= _BCM_VP_INFO_NETWORK_PORT; 18063 } else { 18064 vp_info.flags &= ~(_BCM_VP_INFO_NETWORK_PORT); 18065 } 18066 18067 if (mpls_port->criteria == BCM_MPLS_PORT_MATCH_SHARE) { 18068 vp_info.flags |= _BCM_VP_INFO_SHARED_PORT; 18069 } 18070 18071 if (mpls_port->flags & BCM_MPLS_PORT_FAILOVER) { 18072 /* VP conservation */ 18073 vp = BCM_GPORT_MPLS_PORT_ID_GET(mpls_port->failover_port_id); 18074 if (vp == -1) { 18075 return BCM_E_PARAM; 18076 } 18077 } else { 18078 /* allocate a new VP index */ 18079 num_vp = soc_mem_index_count(unit, SOURCE_VPm); 18080 rv = _bcm_vp_alloc(unit, 0, (num_vp - 1), 1, SOURCE_VPm, vp_info, &vp); 18081 if (rv < 0) { 18082 return rv; 18083 } 18084 } 18085 sal_memset(&svp, 0, sizeof(source_vp_entry_t)); 18086 sal_memset(&dvp, 0, sizeof(ing_dvp_table_entry_t)); 18087 #if defined(BCM_TRIDENT2_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) \ 18088 || defined(BCM_TRIDENT_SUPPORT) 18089 if (SOC_IS_TRIUMPH3(unit) || SOC_IS_TRIDENT2X(unit) 18090 || SOC_IS_TRIDENT(unit) || SOC_IS_TRIDENT3X(unit) || 18091 SOC_IS_TOMAHAWKX(unit)) { 18092 sal_memset(&dvp2, 0, sizeof(ing_dvp_2_table_entry_t)); 18093 } 18094 #endif /* BCM_TRIDENT2_SUPPORT or BCM_TRIUMPH3_SUPPORT or BCM_TRIDENT_SUPPORT */ 18095 BCM_IF_ERROR_RETURN(_bcm_vp_used_set(unit, vp, vp_info)); 18096 18097 /*Set EGR_DVP_ATTRIBUTE indexed by vp to zero*/ 18098 if (SOC_MEM_IS_VALID(unit, EGR_DVP_ATTRIBUTEm)) { 18099 BCM_IF_ERROR_RETURN(WRITE_EGR_DVP_ATTRIBUTEm(unit, 18100 MEM_BLOCK_ALL, vp, &egr_dvp_attribute)); 18101 } 18102 } 18103 #ifdef BCM_TRIUMPH2_SUPPORT 18104 if (soc_feature(unit, soc_feature_mpls_failover)) { 18105 old_failover_vp = mpls_info->failover_vp[vp]; 18106 } 18107 #endif 18108 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) || \ 18109 defined(BCM_APACHE_SUPPORT) 18110 if (SOC_IS_KATANAX(unit) || SOC_IS_TRIUMPH3(unit) || SOC_IS_APACHE(unit)) { 18111 rv = _bcm_esw_add_policer_to_table(unit, mpls_port->policer_id, 18112 SOURCE_VPm, 0, &svp); 18113 BCM_IF_ERROR_RETURN(rv); 18114 } 18115 #endif /* BCM_KATANA_SUPPORT or BCM_TRIUMPH3_SUPPORT BCM_APACHE_SUPPORT */ 18116 18117 if (!(mpls_port->flags & BCM_MPLS_PORT_REPLACE)) { 18118 /* Set the MPLS port ID */ 18119 BCM_GPORT_MPLS_PORT_ID_SET(mpls_port->mpls_port_id, vp); 18120 } 18121 18122 if (mpls_port->flags & BCM_MPLS_PORT_ENCAP_WITH_ID) { 18123 /* Input parameters check. */ 18124 if (!BCM_XGS3_L3_EGRESS_IDX_VALID(unit, mpls_port->encap_id) && 18125 !BCM_XGS3_DVP_EGRESS_IDX_VALID(unit, mpls_port->encap_id)) { 18126 return (BCM_E_PARAM); 18127 } 18128 18129 /* Calculate next hop index. */ 18130 if (BCM_XGS3_L3_EGRESS_IDX_VALID(unit, mpls_port->encap_id)) { 18131 nh_index = mpls_port->encap_id - BCM_XGS3_EGRESS_IDX_MIN(unit); 18132 } else { 18133 nh_index = mpls_port->encap_id - BCM_XGS3_DVP_EGRESS_IDX_MIN(unit); 18134 } 18135 } 18136 18137 if (soc_feature(unit, soc_feature_multiple_split_horizon_group)) { 18138 network_group = mpls_port->network_group_id; 18139 rv = _bcm_validate_splithorizon_network_group(unit, 18140 mpls_port->flags & BCM_MPLS_PORT_NETWORK, &network_group); 18141 BCM_IF_ERROR_RETURN(rv); 18142 } 18143 18144 drop = (mpls_port->flags & BCM_MPLS_PORT_DROP) ? 1 : 0; 18145 rv = _bcm_tr_mpls_l2_nh_info_add(unit, mpls_port, vp, drop, 0, 18146 &nh_index, &local_port, &is_local, 18147 &old_nh_info); 18148 if (rv < 0) { 18149 if (!(mpls_port->flags & BCM_MPLS_PORT_REPLACE)) { 18150 (void) _bcm_vp_free(unit, _bcmVpTypeMpls, 1, vp); 18151 _BCM_MPLS_NETWORK_VP_USED_CLR(unit, vp); 18152 } 18153 return rv; 18154 } 18155 18156 if (mpls_port->flags & BCM_MPLS_PORT_FAILOVER) { 18157 rv = _bcm_esw_mpls_match_add(unit, mpls_port, 18158 _BCM_MPLS_GPORT_FAILOVER_VPLESS_SET(vp), vpn, TRUE); 18159 mpls_port->mpls_port_id = 18160 _BCM_MPLS_GPORT_FAILOVER_VPLESS_SET(mpls_port->mpls_port_id); 18161 mpls_port->encap_id = BCM_XGS3_DVP_EGRESS_IDX_MIN(unit) + nh_index; 18162 if (soc_feature(unit, soc_feature_mpls_software_failover)) { 18163 if (mpls_port->flags & BCM_MPLS_PORT_ENCAP_WITH_ID) { 18164 rv = soc_mem_field32_modify(unit, ING_DVP_TABLEm, 18165 vp, NEXT_HOP_INDEXf, nh_index); 18166 #if defined(BCM_TRIDENT2_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) \ 18167 || defined(BCM_TRIDENT_SUPPORT) 18168 if (SOC_IS_TRIUMPH3(unit) || SOC_IS_TRIDENT2X(unit) 18169 || SOC_IS_TRIDENT(unit) || SOC_IS_TRIDENT3X(unit)) { 18170 rv = soc_mem_field32_modify(unit, ING_DVP_2_TABLEm, 18171 vp, NEXT_HOP_INDEXf, nh_index); 18172 } 18173 #endif /* BCM_TRIDENT2_SUPPORT or BCM_TRIUMPH3_SUPPORT or BCM_TRIDENT_SUPPORT */ 18174 } 18175 } 18176 goto vpls_cleanup; 18177 } 18178 18179 if (mpls_port->flags & BCM_MPLS_PORT_SERVICE_TAGGED) { 18180 rv = _bcm_fb2_outer_tpid_lkup(unit, mpls_port->service_tpid, 18181 &tpid_index); 18182 if (rv < 0) { 18183 goto vpls_cleanup; 18184 } 18185 tpid_enable = (1 << tpid_index); 18186 soc_SOURCE_VPm_field32_set(unit, &svp, SD_TAG_MODEf, 1); 18187 18188 #if defined(BCM_TRIDENT3_SUPPORT) 18189 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 18190 uint32 svp_attrs_1[SOC_MAX_MEM_WORDS]; 18191 18192 sal_memset(svp_attrs_1, 0, 18193 sizeof(uint32) * SOC_MAX_MEM_WORDS); 18194 BCM_IF_ERROR_RETURN(READ_SVP_ATTRS_1m(unit, 18195 MEM_BLOCK_ANY, vp, svp_attrs_1)); 18196 soc_SVP_ATTRS_1m_field_set(unit, 18197 &svp_attrs_1, TPID_ENABLEf, 18198 (uint32 *)&tpid_enable); 18199 BCM_IF_ERROR_RETURN( 18200 WRITE_SVP_ATTRS_1m(unit, 18201 MEM_BLOCK_ALL, vp, 18202 &svp_attrs_1)); 18203 } else 18204 #endif 18205 { 18206 soc_SOURCE_VPm_field32_set(unit, &svp, TPID_ENABLEf, tpid_enable); 18207 } 18208 if (SOC_MEM_FIELD_VALID(unit, SOURCE_VPm, TRUST_OUTER_DOT1Pf)) { 18209 soc_SOURCE_VPm_field32_set(unit, &svp, TRUST_OUTER_DOT1Pf, 1); 18210 } 18211 } else { 18212 soc_SOURCE_VPm_field32_set(unit, &svp, SD_TAG_MODEf, 0); 18213 } 18214 soc_SOURCE_VPm_field32_set(unit, &svp, CLASS_IDf, 18215 mpls_port->if_class); 18216 if (soc_feature(unit, soc_feature_multiple_split_horizon_group)) { 18217 soc_SOURCE_VPm_field32_set(unit, &svp, NETWORK_GROUPf, network_group); 18218 } else { 18219 soc_SOURCE_VPm_field32_set(unit, &svp, NETWORK_PORTf, 18220 (mpls_port->flags & BCM_MPLS_PORT_NETWORK) ? 1 : 0); 18221 } 18222 if (mpls_port->flags & BCM_MPLS_PORT_NETWORK) { 18223 _BCM_MPLS_NETWORK_VP_USED_SET(unit, vp); 18224 } 18225 18226 if (mpls_port->flags & BCM_MPLS_PORT_REPLACE) { 18227 rv = WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, vp, &svp); 18228 18229 /* Link in the newly allocated next-hop entry in ING_DVP_TABLE */ 18230 soc_ING_DVP_TABLEm_field32_set(unit, &dvp, NEXT_HOP_INDEXf, 18231 nh_index); 18232 18233 if (soc_mem_field_valid(unit, ING_DVP_TABLEm, NETWORK_PORTf)) { 18234 if ((mpls_port->flags & BCM_MPLS_PORT_EGRESS_TUNNEL) && 18235 (mpls_port->flags & BCM_MPLS_PORT_NETWORK)) { /* Network */ 18236 #ifdef BCM_RIOT_SUPPORT 18237 if (BCMI_RIOT_IS_ENABLED(unit)) { 18238 soc_ING_DVP_TABLEm_field32_set(unit, &dvp, NETWORK_PORTf, 0); 18239 } else 18240 #endif 18241 { 18242 soc_ING_DVP_TABLEm_field32_set(unit, &dvp, NETWORK_PORTf, 1); 18243 } 18244 } else { /* Access */ 18245 soc_ING_DVP_TABLEm_field32_set(unit, &dvp, NETWORK_PORTf, 0); 18246 } 18247 } 18248 18249 if (soc_feature(unit, soc_feature_multiple_split_horizon_group)) { 18250 if (soc_mem_field_valid(unit, ING_DVP_TABLEm, NETWORK_GROUPf)) { 18251 #ifdef BCM_RIOT_SUPPORT 18252 if (BCMI_RIOT_IS_ENABLED(unit)) { 18253 soc_ING_DVP_TABLEm_field32_set(unit, &dvp, NETWORK_GROUPf, 0); 18254 } else 18255 #endif 18256 { 18257 soc_ING_DVP_TABLEm_field32_set(unit, &dvp, NETWORK_GROUPf, network_group); 18258 } 18259 } 18260 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 18261 rv = soc_mem_field32_modify(unit, EGR_DVP_ATTRIBUTEm, 18262 vp,COMMON__DVP_NETWORK_GROUPf, 18263 network_group); 18264 if (rv < 0) { 18265 goto vpls_cleanup; 18266 } 18267 } 18268 } 18269 18270 rv = WRITE_ING_DVP_TABLEm(unit, MEM_BLOCK_ALL, vp, &dvp); 18271 if (rv < 0) { 18272 goto vpls_cleanup; 18273 } 18274 #if defined(BCM_TRIDENT2_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) \ 18275 || defined(BCM_TRIDENT_SUPPORT) 18276 if (SOC_IS_TRIUMPH3(unit) || SOC_IS_TRIDENT2X(unit) 18277 || SOC_IS_TRIDENT(unit) || SOC_IS_TRIDENT3X(unit) || 18278 SOC_IS_TOMAHAWKX(unit)) { 18279 /* Link in the newly allocated next-hop entry in ING_DVP_2_TABLE 18280 * Since Field module uses DVP_2_TABLE for REDIRECT_TO_DVP Action 18281 * for devices TD/TD2/TR3 18282 */ 18283 sal_memset(&dvp2, 0, sizeof(ing_dvp_2_table_entry_t)); 18284 BCM_IF_ERROR_RETURN(READ_ING_DVP_2_TABLEm(unit, MEM_BLOCK_ANY, 18285 vp, &dvp2)); 18286 soc_ING_DVP_2_TABLEm_field32_set(unit, &dvp2, NEXT_HOP_INDEXf, 18287 nh_index); 18288 18289 if (soc_mem_field_valid(unit, ING_DVP_2_TABLEm, NETWORK_PORTf)) { 18290 if ((mpls_port->flags & BCM_MPLS_PORT_EGRESS_TUNNEL) && 18291 (mpls_port->flags & BCM_MPLS_PORT_NETWORK)) { /* Network */ 18292 #ifdef BCM_RIOT_SUPPORT 18293 if (BCMI_RIOT_IS_ENABLED(unit)) { 18294 soc_ING_DVP_2_TABLEm_field32_set(unit, &dvp2, NETWORK_PORTf, 0); 18295 } else 18296 #endif 18297 { 18298 soc_ING_DVP_2_TABLEm_field32_set(unit, &dvp2, NETWORK_PORTf, 1); 18299 } 18300 } else { /* Access */ 18301 soc_ING_DVP_2_TABLEm_field32_set(unit, &dvp2, NETWORK_PORTf, 0); 18302 } 18303 } 18304 18305 if ((soc_feature(unit, soc_feature_multiple_split_horizon_group)) && 18306 (soc_mem_field_valid(unit, ING_DVP_2_TABLEm, NETWORK_GROUPf))) { 18307 #ifdef BCM_RIOT_SUPPORT 18308 if (BCMI_RIOT_IS_ENABLED(unit)) { 18309 soc_ING_DVP_2_TABLEm_field32_set(unit, &dvp2, NETWORK_GROUPf, 0); 18310 } else 18311 #endif 18312 { 18313 soc_ING_DVP_2_TABLEm_field32_set(unit, &dvp2, NETWORK_GROUPf, network_group); 18314 } 18315 } 18316 18317 rv = WRITE_ING_DVP_2_TABLEm(unit, MEM_BLOCK_ALL, vp, &dvp2); 18318 if (rv < 0) { 18319 goto vpls_cleanup; 18320 } 18321 } 18322 #endif /* BCM_TRIDENT2_SUPPORT or BCM_TRIUMPH3_SUPPORT or BCM_TRIDENT_SUPPORT */ 18323 } else { 18324 /* Link in the newly allocated next-hop entry in ING_DVP_TABLE */ 18325 soc_ING_DVP_TABLEm_field32_set(unit, &dvp, NEXT_HOP_INDEXf, 18326 nh_index); 18327 18328 if (soc_mem_field_valid(unit, ING_DVP_TABLEm, NETWORK_PORTf)) { 18329 if ((mpls_port->flags & BCM_MPLS_PORT_EGRESS_TUNNEL) && 18330 (mpls_port->flags & BCM_MPLS_PORT_NETWORK)) { /* Network */ 18331 #ifdef BCM_RIOT_SUPPORT 18332 if (BCMI_RIOT_IS_ENABLED(unit)) { 18333 soc_ING_DVP_TABLEm_field32_set(unit, &dvp, NETWORK_PORTf, 0); 18334 } else 18335 #endif 18336 { 18337 soc_ING_DVP_TABLEm_field32_set(unit, &dvp, NETWORK_PORTf, 1); 18338 } 18339 } else { /* Access */ 18340 soc_ING_DVP_TABLEm_field32_set(unit, &dvp, NETWORK_PORTf, 0); 18341 } 18342 } 18343 18344 if (soc_feature(unit, soc_feature_multiple_split_horizon_group)) { 18345 if (soc_mem_field_valid(unit, ING_DVP_TABLEm, NETWORK_GROUPf)) { 18346 #ifdef BCM_RIOT_SUPPORT 18347 if (BCMI_RIOT_IS_ENABLED(unit)) { 18348 soc_ING_DVP_TABLEm_field32_set(unit, &dvp, NETWORK_GROUPf, 0); 18349 } else 18350 #endif 18351 { 18352 soc_ING_DVP_TABLEm_field32_set(unit, &dvp, NETWORK_GROUPf, network_group); 18353 } 18354 } 18355 18356 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 18357 rv = soc_mem_field32_modify(unit, EGR_DVP_ATTRIBUTEm, 18358 vp, COMMON__DVP_NETWORK_GROUPf, 18359 network_group); 18360 if (rv < 0) { 18361 goto vpls_cleanup; 18362 } 18363 } 18364 } 18365 18366 rv = WRITE_ING_DVP_TABLEm(unit, MEM_BLOCK_ALL, vp, &dvp); 18367 if (rv < 0) { 18368 goto vpls_cleanup; 18369 } 18370 #if defined(BCM_TRIDENT2_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) \ 18371 || defined(BCM_TRIDENT_SUPPORT) 18372 if (SOC_IS_TRIUMPH3(unit) || SOC_IS_TRIDENT2X(unit) 18373 || SOC_IS_TRIDENT(unit) || SOC_IS_TRIDENT3X(unit) || 18374 SOC_IS_TOMAHAWKX(unit)) { 18375 /* Link in the newly allocated next-hop entry in ING_DVP_2_TABLE 18376 * Since Field module uses DVP_2_TABLE for REDIRECT_TO_DVP Action 18377 * for devices TD/TD2/TR3 18378 */ 18379 soc_ING_DVP_2_TABLEm_field32_set(unit, &dvp2, NEXT_HOP_INDEXf, 18380 nh_index); 18381 18382 if (soc_mem_field_valid(unit, ING_DVP_2_TABLEm, NETWORK_PORTf)) { 18383 if ((mpls_port->flags & BCM_MPLS_PORT_EGRESS_TUNNEL) && 18384 (mpls_port->flags & BCM_MPLS_PORT_NETWORK)) { /* Network */ 18385 #ifdef BCM_RIOT_SUPPORT 18386 if (BCMI_RIOT_IS_ENABLED(unit)) { 18387 soc_ING_DVP_2_TABLEm_field32_set(unit, &dvp2, NETWORK_PORTf, 0); 18388 } else 18389 #endif 18390 { 18391 soc_ING_DVP_2_TABLEm_field32_set(unit, &dvp2, NETWORK_PORTf, 1); 18392 } 18393 } else { /* Access */ 18394 soc_ING_DVP_2_TABLEm_field32_set(unit, &dvp2, NETWORK_PORTf, 0); 18395 } 18396 } 18397 18398 if (soc_feature(unit, soc_feature_multiple_split_horizon_group)) { 18399 if (soc_mem_field_valid(unit, ING_DVP_2_TABLEm, NETWORK_GROUPf)) { 18400 #ifdef BCM_RIOT_SUPPORT 18401 if (BCMI_RIOT_IS_ENABLED(unit)) { 18402 soc_ING_DVP_2_TABLEm_field32_set(unit, &dvp2, NETWORK_GROUPf, 0); 18403 } else 18404 #endif 18405 { 18406 soc_ING_DVP_2_TABLEm_field32_set(unit, &dvp2, NETWORK_GROUPf, network_group); 18407 } 18408 } 18409 } 18410 18411 rv = WRITE_ING_DVP_2_TABLEm(unit, MEM_BLOCK_ALL, vp, &dvp2); 18412 if (rv < 0) { 18413 goto vpls_cleanup; 18414 } 18415 } 18416 #endif /* BCM_TRIDENT2_SUPPORT or BCM_TRIUMPH3_SUPPORT or BCM_TRIDENT_SUPPORT */ 18417 18418 if (vpn == BCM_MPLS_VPLS_VPN_INVALID) { 18419 soc_SOURCE_VPm_field32_set(unit, &svp, 18420 ENTRY_TYPEf, 0x0); /* INVALID */ 18421 rv = soc_mem_read(unit, ING_L3_NEXT_HOPm, MEM_BLOCK_ANY, nh_index, &ing_nh); 18422 if (rv < 0) { 18423 goto vpls_cleanup; 18424 } 18425 soc_mem_field32_set(unit, ING_L3_NEXT_HOPm, &ing_nh, DROPf, 0x1); /* Set Drop */ 18426 rv = soc_mem_write (unit, ING_L3_NEXT_HOPm, MEM_BLOCK_ALL, nh_index, &ing_nh); 18427 if (rv < 0) { 18428 goto vpls_cleanup; 18429 } 18430 } else { 18431 /* Initialize the SVP parameters */ 18432 soc_SOURCE_VPm_field32_set(unit, &svp, 18433 ENTRY_TYPEf, 0x1); /* VPLS */ 18434 } 18435 18436 if (mpls_port->criteria != BCM_MPLS_PORT_MATCH_SHARE) { 18437 soc_SOURCE_VPm_field32_set(unit, &svp, VFIf, vfi); 18438 _bcm_vp_vfi_set(unit, vp, vpn); 18439 } 18440 18441 rv = _bcm_vp_default_cml_mode_get (unit, 18442 &cml_default_enable, &cml_default_new, 18443 &cml_default_move); 18444 if (rv < 0) { 18445 goto vpls_cleanup; 18446 } 18447 18448 if (cml_default_enable) { 18449 /* Set the CML to default values */ 18450 soc_SOURCE_VPm_field32_set(unit, &svp, CML_FLAGS_NEWf, cml_default_new); 18451 soc_SOURCE_VPm_field32_set(unit, &svp, CML_FLAGS_MOVEf, cml_default_move); 18452 } else { 18453 /* Set the CML to PVP_CML_SWITCH by default (hw learn and forward) */ 18454 soc_SOURCE_VPm_field32_set(unit, &svp, CML_FLAGS_NEWf, 0x8); 18455 soc_SOURCE_VPm_field32_set(unit, &svp, CML_FLAGS_MOVEf, 0x8); 18456 } 18457 if (soc_mem_field_valid(unit, SOURCE_VPm, DISABLE_VLAN_CHECKSf)) { 18458 if (!soc_feature(unit, soc_feature_vlan_vfi_membership)) { 18459 soc_SOURCE_VPm_field32_set(unit, &svp, DISABLE_VLAN_CHECKSf, 1); 18460 } 18461 } 18462 if (soc_mem_field_valid(unit, SOURCE_VPm, SRC_PORTf) && 18463 soc_mem_field_valid(unit, SOURCE_VPm, SRC_MODIDf)) { 18464 rv = _bcm_tr_mpls_l2vpn_source_port_set(unit, mpls_port, &svp); 18465 } 18466 if (rv < 0) { 18467 goto vpls_cleanup; 18468 } 18469 18470 /*CMH SVP ATTRS*/ 18471 if (soc_feature(unit,soc_feature_td3_style_mpls)) { 18472 int entry_type = 1; 18473 rv = bcmi_cmh_svp_attributes_set(unit, entry_type, vp, TRUE, 18474 mpls_port->flags); 18475 if (rv < 0) { 18476 goto vpls_cleanup; 18477 } 18478 18479 if (soc_mem_field_valid(unit, SOURCE_VPm, SVP_PROFILE_INDEXf)) { 18480 if (mpls_port->flags & BCM_MPLS_PORT_EGRESS_TUNNEL) { 18481 soc_SOURCE_VPm_field32_set(unit, &svp, 18482 SVP_PROFILE_INDEXf, 1); 18483 } 18484 } 18485 } 18486 18487 rv = WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, vp, &svp); 18488 if (rv < 0) { 18489 goto vpls_cleanup; 18490 } 18491 #ifdef BCM_ENDURO_SUPPORT 18492 if (SOC_IS_ENDURO(unit)) { 18493 BCM_IF_ERROR_RETURN ( 18494 READ_SVP_DISABLE_VLAN_CHECKS_TABm(unit, MEM_BLOCK_ANY, vp, &svp_disable_check)); 18495 soc_SVP_DISABLE_VLAN_CHECKS_TABm_field32_set(unit, &svp_disable_check, DISABLE_VLAN_CHECKSf, 1); 18496 BCM_IF_ERROR_RETURN ( 18497 WRITE_SVP_DISABLE_VLAN_CHECKS_TABm(unit, MEM_BLOCK_ALL, vp, &svp_disable_check)); 18498 } 18499 #endif /* BCM_ENDURO_SUPPORT */ 18500 } 18501 18502 #if defined(BCM_TRIUMPH2_SUPPORT) 18503 if (soc_feature(unit, soc_feature_mpls_failover)) { 18504 int failover_vp = 0; 18505 bcm_mpls_port_t failover_mpls_port; 18506 18507 if (BCM_SUCCESS(_bcm_esw_failover_mpls_check(unit, mpls_port))) { 18508 failover_vp = BCM_GPORT_MPLS_PORT_ID_GET(mpls_port->failover_port_id); 18509 if (failover_vp >=0 ) { 18510 if (!_bcm_vp_used_get(unit, failover_vp, _bcmVpTypeMpls)) { 18511 rv = BCM_E_NOT_FOUND; 18512 goto vpls_cleanup; 18513 } 18514 rv = _bcm_esw_mpls_match_get(unit, &failover_mpls_port, failover_vp); 18515 if ( rv < 0 ) { 18516 if (rv != BCM_E_NOT_FOUND) { 18517 goto vpls_cleanup; 18518 } 18519 } 18520 if (mpls_port->match_label == failover_mpls_port.match_label) { 18521 /* Replace failover_vp with Primary vp 18522 * As part of doing this, we should only remove the 18523 * h/w entry for backup port and not the software state. 18524 */ 18525 rv = _bcm_esw_mpls_match_delete(unit, failover_vp, FALSE); 18526 if (BCM_FAILURE(rv)) { 18527 if (rv != BCM_E_NOT_FOUND) { 18528 return rv; 18529 } 18530 } 18531 } 18532 mpls_info->failover_vp[vp] = failover_vp; 18533 } 18534 } else if (mpls_port->failover_id) { 18535 /* 18536 * If this is not a primary port but user 18537 * is providing failover id then this is a failover 18538 * port and we need to make sure we dont overwrite 18539 * primary matching entry,if present. 18540 */ 18541 mpls_entry_entry_t return_ment; 18542 int primary_port = 0, primary_nh_index = 0; 18543 18544 rv = _bcm_esw_mpls_failover_nw_port_match_get(unit, mpls_port, -1, 18545 &return_ment); 18546 18547 if (rv == BCM_E_NONE) { 18548 /* entry exists. dont update h/w entry as this is failover port */ 18549 entry_update = FALSE; 18550 primary_port = soc_MPLS_ENTRYm_field32_get(unit, 18551 &return_ment, MPLS__SOURCE_VPf); 18552 18553 if (primary_port > 0) { 18554 ing_dvp_table_entry_t p_dvp; 18555 18556 BCM_IF_ERROR_RETURN (READ_ING_DVP_TABLEm(unit, 18557 MEM_BLOCK_ANY, primary_port, &p_dvp)); 18558 primary_nh_index = soc_ING_DVP_TABLEm_field32_get(unit, 18559 &p_dvp, NEXT_HOP_INDEXf); 18560 } 18561 /* 18562 * if we are adding a failover port to existing primary 18563 * port then create protection table entry also. 18564 */ 18565 if (bcmi_mpls_port_failover_update_is_required( 18566 unit, mpls_port, primary_nh_index, nh_index)) { 18567 rv = _bcm_esw_failover_prot_nhi_create(unit, 0, 18568 (uint32) primary_nh_index, nh_index, 18569 mpls_port->failover_mc_group, 18570 mpls_port->failover_id); 18571 18572 if (BCM_FAILURE(rv)) { 18573 goto vpls_cleanup; 18574 } 18575 } 18576 } else if (rv != BCM_E_NOT_FOUND) { 18577 return rv; 18578 } 18579 } 18580 } 18581 #endif /* BCM_TRIUMPH2_SUPPORT */ 18582 18583 if (soc_mem_field_valid(unit, EGR_DVP_ATTRIBUTEm, MTU_VALUEf) || 18584 soc_mem_field_valid(unit, EGR_DVP_ATTRIBUTEm, COMMON__MTU_VALUEf)) { 18585 rv = _bcm_tr_mpls_port_mtu_set(unit, vp, mpls_port->mtu); 18586 if (rv < 0) { 18587 goto vpls_cleanup; 18588 } 18589 } 18590 /* 18591 * Add the matching entry in s/w and h/w tables. 18592 * If this is a failover port, you may not want to write this 18593 * entry in h/w tables as that would overwrite primary entry. 18594 * entry_update is made false above to achieve that behavior. 18595 */ 18596 rv = _bcm_esw_mpls_match_add(unit, mpls_port, vp, vpn, entry_update); 18597 if (rv == BCM_E_NONE) { 18598 /* Set the MPLS port ID */ 18599 BCM_GPORT_MPLS_PORT_ID_SET(mpls_port->mpls_port_id, vp); 18600 mpls_port->encap_id = BCM_XGS3_DVP_EGRESS_IDX_MIN(unit) + nh_index; 18601 } 18602 18603 #if defined(BCM_TRIUMPH2_SUPPORT) 18604 if (!BCM_GPORT_IS_TRUNK(mpls_port->port)) { 18605 if (!(mpls_port->flags2 & BCM_MPLS_PORT2_QOS_NONE)) { 18606 _bcm_mpls_source_vp_set(unit, mpls_port, vp); 18607 } 18608 } 18609 #endif 18610 /* Free the old next-hop entry. */ 18611 18612 (void)_bcm_tr_mpls_l2_old_nh_info_delete(unit, mpls_port, nh_index, 18613 &old_nh_info); 18614 #if defined(BCM_TRIDENT2_SUPPORT) 18615 if (soc_feature(unit, soc_feature_vp_lag)) { 18616 if (mpls_port->flags & BCM_MPLS_PORT_REPLACE) { 18617 if (rv == BCM_E_NONE) { 18618 rv = _bcm_td2_mpls_vplag_vp_update(unit, mpls_port->mpls_port_id); 18619 } 18620 } 18621 } 18622 #endif 18623 18624 vpls_cleanup: 18625 if (rv < 0) { 18626 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) || \ 18627 defined(BCM_APACHE_SUPPORT) 18628 if (SOC_IS_KATANAX(unit) || SOC_IS_TRIUMPH3(unit) || SOC_IS_APACHE(unit)) { 18629 _bcm_esw_reset_policer_from_table(unit, mpls_port->policer_id, 18630 SOURCE_VPm, vp, &svp); 18631 } 18632 #endif /* BCM_KATANA_SUPPORT or BCM_TRIUMPH3_SUPPORT or BCM_APACHE_SUPPORT */ 18633 if (tpid_enable) { 18634 (void) _bcm_fb2_outer_tpid_entry_delete(unit, tpid_index); 18635 } 18636 if (!(mpls_port->flags & BCM_MPLS_PORT_REPLACE)) { 18637 (void) _bcm_vp_free(unit, _bcmVpTypeMpls, 1, vp); 18638 _BCM_MPLS_NETWORK_VP_USED_CLR(unit, vp); 18639 (void) _bcm_tr_mpls_l2_nh_info_delete(unit, nh_index); 18640 } 18641 #ifdef BCM_TRIUMPH2_SUPPORT 18642 if (soc_feature(unit, soc_feature_mpls_failover)) { 18643 mpls_info->failover_vp[vp] = old_failover_vp; 18644 } 18645 #endif 18646 18647 return rv; 18648 } 18649 18650 return rv; 18651 } 18652 18653 /* 18654 * Function: 18655 * bcm_mpls_port_add 18656 * Purpose: 18657 * Add an mpls port to a VPN 18658 * Parameters: 18659 * unit - (IN) Device Number 18660 * vpn - (IN) VPN instance ID 18661 * mpls_port - (IN/OUT) mpls port information (OUT : mpls_port_id) 18662 * Returns: 18663 * BCM_E_XXX 18664 */ 18665 int 18666 bcm_tr_mpls_port_add(int unit, bcm_vpn_t vpn, bcm_mpls_port_t *mpls_port) 18667 { 18668 int mode, rv = BCM_E_PARAM, bit_num = 0; 18669 18670 BCM_IF_ERROR_RETURN(bcm_xgs3_l3_egress_mode_get(unit, &mode)); 18671 if (!mode) { 18672 LOG_INFO(BSL_LS_BCM_L3, 18673 (BSL_META_U(unit, 18674 "L3 egress mode must be set first\n"))); 18675 return BCM_E_DISABLED; 18676 } 18677 18678 if (mpls_port->criteria == BCM_MPLS_PORT_MATCH_SHARE) { 18679 if (!soc_feature(unit, soc_feature_vp_sharing)) { 18680 return BCM_E_UNAVAIL; 18681 } 18682 } 18683 18684 if (!_BCM_MPLS_VPN_IS_VPLS(vpn) && 18685 !_BCM_MPLS_VPN_IS_VPWS(vpn)) { 18686 18687 if ((vpn != BCM_MPLS_VPWS_VPN_INVALID) && (vpn != BCM_MPLS_VPLS_VPN_INVALID)) { 18688 return BCM_E_PARAM; 18689 } 18690 } 18691 18692 if (mpls_port->if_class) { 18693 bit_num = soc_mem_field_length(unit, SOURCE_VPm, CLASS_IDf); 18694 if (mpls_port->if_class > (( 1 << bit_num ) - 1)) { 18695 return BCM_E_PARAM; 18696 } 18697 } 18698 18699 /* BCM_MPLS_PORT_INT_PRI_MAP or BCM_MPLS_PORT_INT_PRI_SET indicates 18700 * how to generate the internal Priority and Color values, and they don't coexist. 18701 */ 18702 if ((mpls_port->flags & BCM_MPLS_PORT_INT_PRI_MAP) && 18703 (mpls_port->flags & BCM_MPLS_PORT_INT_PRI_SET)) { 18704 return BCM_E_PARAM; 18705 } 18706 18707 if ((mpls_port->criteria == BCM_MPLS_PORT_MATCH_LABEL_VLAN) || 18708 (mpls_port->criteria == BCM_MPLS_PORT_MATCH_INVALID)) { 18709 return BCM_E_PARAM; 18710 } 18711 18712 if ((mpls_port->flags & BCM_MPLS_PORT_CONTROL_WORD) && 18713 (mpls_port->flags & BCM_MPLS_PORT_SEQUENCED)) { 18714 return BCM_E_PARAM; 18715 } 18716 18717 if (soc_mem_field_valid(unit, MPLS_ENTRYm, PW_CC_TYPEf)) { 18718 if (mpls_port->vccv_type >= 18719 (1 << soc_mem_field_length(unit, MPLS_ENTRYm, PW_CC_TYPEf))) { 18720 return BCM_E_PARAM; 18721 } 18722 } 18723 18724 #if defined(BCM_TRIUMPH3_SUPPORT) 18725 if (SOC_IS_TRIUMPH3(unit)) { 18726 if (soc_mem_field_valid(unit, MPLS_ENTRY_1m, MPLS__PW_CC_TYPEf)) { 18727 if (mpls_port->vccv_type >= 18728 (1 << soc_mem_field_length(unit, MPLS_ENTRY_1m, 18729 MPLS__PW_CC_TYPEf))) { 18730 return BCM_E_PARAM; 18731 } 18732 } 18733 } 18734 #endif 18735 18736 if (_BCM_MPLS_VPN_IS_VPWS(vpn) || (vpn == BCM_MPLS_VPWS_VPN_INVALID) ) { 18737 rv = _bcm_tr_mpls_vpws_port_add(unit, vpn, mpls_port); 18738 } else if (_BCM_MPLS_VPN_IS_VPLS(vpn) || (vpn == BCM_MPLS_VPLS_VPN_INVALID)) { 18739 rv = _bcm_tr_mpls_vpls_port_add(unit, vpn, mpls_port); 18740 } 18741 18742 #ifdef BCM_WARM_BOOT_SUPPORT 18743 SOC_CONTROL_LOCK(unit); 18744 SOC_CONTROL(unit)->scache_dirty = 1; 18745 SOC_CONTROL_UNLOCK(unit); 18746 #endif 18747 18748 return rv; 18749 } 18750 18751 /* 18752 * Function: 18753 * _bcm_share_mpls_vp_delete 18754 * Purpose: 18755 * Delete match criteria of shared VPs 18756 * Parameters: 18757 * unit - (IN) Device Number 18758 * vpn - (IN) VPN that shared vp belong to 18759 * vp - (IN) Source Virtual Port 18760 * Returns: 18761 * BCM_E_XXX 18762 */ 18763 int 18764 _bcm_share_mpls_vp_delete(int unit, bcm_vpn_t vpn, int vp) 18765 { 18766 vlan_xlate_entry_t *vent; 18767 soc_mem_t mem; 18768 int index_min = 0; 18769 int index_max = 0; 18770 uint8 *xlate_buf = NULL; 18771 int buf_size = 0; 18772 int i = 0; 18773 int rv = BCM_E_NONE; 18774 int vfi = -1; 18775 int source_vp = -1; 18776 18777 _BCM_MPLS_VPN_GET(vfi, _BCM_VPN_TYPE_VFI, vpn); 18778 18779 #if defined(BCM_TRIDENT3_SUPPORT) 18780 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 18781 mem = VLAN_XLATE_1_DOUBLEm; 18782 } else 18783 #endif 18784 { 18785 mem = VLAN_XLATEm; 18786 } 18787 index_min = soc_mem_index_min(unit, mem); 18788 index_max = soc_mem_index_max(unit, mem); 18789 18790 buf_size = SOC_MEM_TABLE_BYTES(unit, mem); 18791 xlate_buf = soc_cm_salloc(unit, buf_size, "VLAN_XLATE buffer"); 18792 if (NULL == xlate_buf) { 18793 return BCM_E_MEMORY; 18794 } 18795 rv = soc_mem_read_range(unit, mem, MEM_BLOCK_ANY, index_min, index_max, xlate_buf); 18796 if (rv < 0) { 18797 soc_cm_sfree(unit, xlate_buf); 18798 return rv; 18799 } 18800 18801 for (i = index_min; i <= index_max; i++) { 18802 vent = soc_mem_table_idx_to_pointer(unit, 18803 mem, vlan_xlate_entry_t *, xlate_buf, i); 18804 18805 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 18806 if ((soc_mem_field32_get(unit, mem, vent, BASE_VALID_0f) == 0) || 18807 (soc_mem_field32_get(unit, mem, vent, BASE_VALID_1f) == 0)) { 18808 continue; 18809 } 18810 } else { 18811 if (soc_mem_field32_get(unit, mem, vent, VALIDf) == 0) { 18812 continue; 18813 } 18814 } 18815 18816 if (soc_mem_field32_get(unit, mem, vent, XLATE__MPLS_ACTIONf) != 0x1) { 18817 continue; 18818 } 18819 18820 if (vfi != -1 && soc_mem_field32_get(unit, mem, vent, XLATE__VFIf) != vfi) { 18821 continue; 18822 } 18823 18824 source_vp = soc_mem_field32_get(unit, mem, vent, XLATE__SOURCE_VPf); 18825 if (vp != source_vp) { 18826 continue; 18827 } 18828 rv = soc_mem_delete_index(unit, mem, MEM_BLOCK_ALL, i); 18829 if (rv < BCM_E_NONE) { 18830 (void)soc_cm_sfree(unit, xlate_buf); 18831 return rv; 18832 } 18833 bcm_tr_mpls_port_match_count_adjust(unit, source_vp, -1); 18834 } 18835 18836 (void)soc_cm_sfree(unit, xlate_buf); 18837 18838 return BCM_E_NONE; 18839 } 18840 18841 18842 STATIC int 18843 _bcm_tr_mpls_port_delete(int unit, bcm_vpn_t vpn, int vp) 18844 { 18845 int rv = BCM_E_NONE; 18846 _bcm_tr_mpls_bookkeeping_t *mpls_info = MPLS_INFO(unit); 18847 int failover_nh_index=-1; 18848 int failover_id =-1; 18849 int failover_mc_group=-1; 18850 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) 18851 bcm_policer_t policer = 0; 18852 #endif 18853 int vpless_failover_port = FALSE; /* the failover port without a dedicated vp */ 18854 int failover_port = FALSE; 18855 int prot_index; 18856 int dvp = 0; 18857 _bcm_vp_info_t vp_info; 18858 #if defined(BCM_TRIUMPH2_SUPPORT) 18859 int criteria, is_trunk = 0; 18860 int failover_dvp; 18861 egr_l3_next_hop_entry_t egr_nh; 18862 int nh_index = 0; 18863 ing_l3_next_hop_entry_t ing_nh; 18864 #endif 18865 uint32 dest_type, dest_val; 18866 int temp_vp3 = 0; 18867 soc_field_t dest_field = 0; 18868 18869 if(SOC_MEM_FIELD_VALID(unit, SOURCE_VPm,DESTINATIONf)) { 18870 dest_field = DESTINATIONf; 18871 } 18872 18873 if (_BCM_MPLS_GPORT_FAILOVER_VPLESS_GET(vp)) { 18874 vpless_failover_port = TRUE; 18875 vp = _BCM_MPLS_GPORT_FAILOVER_VPLESS_CLEAR(vp); 18876 } 18877 18878 BCM_IF_ERROR_RETURN(_bcm_vp_info_get(unit, vp, &vp_info)); 18879 if ((vp_info.flags & _BCM_VP_INFO_SHARED_PORT)) { 18880 if (mpls_info->match_key[vp].match_count >= 1) { 18881 BCM_IF_ERROR_RETURN(_bcm_share_mpls_vp_delete(unit, vpn, vp)); 18882 } 18883 if (mpls_info->match_key[vp].match_count > 0) { 18884 return BCM_E_NONE; 18885 } else if (mpls_info->match_key[vp].match_count == 0) { 18886 bcm_tr_mpls_match_clear (unit, vp); 18887 } 18888 } else if (mpls_info->match_key[vp].match_count > 1) { 18889 return BCM_E_BUSY; 18890 } 18891 18892 #if defined(BCM_TRIUMPH2_SUPPORT) 18893 criteria = mpls_info->match_key[vp].flags; 18894 if ((vp_info.flags & _BCM_VP_INFO_SHARED_PORT)) { 18895 rv = READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp, &dvp); 18896 if (rv < 0) { 18897 return rv; 18898 } 18899 nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, 18900 NEXT_HOP_INDEXf); 18901 BCM_IF_ERROR_RETURN (soc_mem_read(unit, ING_L3_NEXT_HOPm, 18902 MEM_BLOCK_ANY, nh_index, &ing_nh)); 18903 18904 if (soc_feature(unit, soc_feature_generic_dest)) { 18905 dest_val = soc_mem_field32_dest_get(unit, ING_L3_NEXT_HOPm, 18906 &ing_nh, DESTINATIONf, &dest_type); 18907 if (dest_type == SOC_MEM_FIF_DEST_LAG) { 18908 /* Trunk group */ 18909 is_trunk = 1; 18910 } 18911 } else { 18912 is_trunk = soc_mem_field32_get(unit, ING_L3_NEXT_HOPm, &ing_nh, Tf); 18913 } 18914 } else { 18915 is_trunk = (mpls_info->match_key[vp].trunk_id != -1) ? TRUE : FALSE; 18916 } 18917 #endif 18918 if ((vpn == BCM_MPLS_VPWS_VPN_INVALID) || (vpn == BCM_MPLS_VPLS_VPN_INVALID)) { 18919 source_vp_entry_t svp; 18920 if (!soc_feature(unit, soc_feature_mpls_software_failover)) { 18921 return BCM_E_UNAVAIL; 18922 } 18923 BCM_IF_ERROR_RETURN ( 18924 READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp, &svp)); 18925 if (soc_SOURCE_VPm_field32_get(unit, &svp, ENTRY_TYPEf) == 0) { 18926 ing_dvp_table_entry_t dvp; 18927 int nh_index = 0; 18928 BCM_IF_ERROR_RETURN ( 18929 READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp, &dvp)); 18930 nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, 18931 NEXT_HOP_INDEXf); 18932 BCM_IF_ERROR_RETURN(_bcm_esw_mpls_match_delete(unit, vp, TRUE)); 18933 sal_memset(&svp, 0, sizeof(source_vp_entry_t)); 18934 rv = WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, vp, &svp); 18935 if (BCM_FAILURE(rv)) { 18936 return rv; 18937 } 18938 sal_memset(&dvp, 0, sizeof(ing_dvp_table_entry_t)); 18939 rv = WRITE_ING_DVP_TABLEm(unit, MEM_BLOCK_ALL, vp, &dvp); 18940 if (rv < 0) { 18941 return rv; 18942 } 18943 rv = _bcm_vp_ing_dvp_to_ing_dvp2(unit, &dvp, vp); 18944 if (rv < 0) { 18945 return rv; 18946 } 18947 rv = _bcm_tr_mpls_l2_nh_info_delete(unit, nh_index); 18948 if (BCM_FAILURE(rv)) { 18949 return rv;; 18950 } 18951 (void) _bcm_vp_free(unit, _bcmVpTypeMpls, 1, vp); 18952 _BCM_MPLS_NETWORK_VP_USED_CLR(unit, vp); 18953 } else { 18954 return BCM_E_PARAM; 18955 } 18956 } else if (_BCM_MPLS_VPN_IS_VPWS(vpn)) { 18957 int nh_index = 0, vp3=0; 18958 source_vp_entry_t svp1, svp2, svp3; 18959 ing_dvp_table_entry_t dvp1, dvp2, dvp3; 18960 uint8 valid = 0; 18961 bcm_vpn_t vpn_id; 18962 int vp1=-1, vp2=-1, vp3_read = -1; 18963 18964 sal_memset(&svp1, 0, sizeof(source_vp_entry_t)); 18965 sal_memset(&svp2, 0, sizeof(source_vp_entry_t)); 18966 sal_memset(&svp3, 0, sizeof(source_vp_entry_t)); 18967 18968 sal_memset(&dvp1, 0, sizeof(ing_dvp_table_entry_t)); 18969 sal_memset(&dvp2, 0, sizeof(ing_dvp_table_entry_t)); 18970 sal_memset(&dvp3, 0, sizeof(ing_dvp_table_entry_t)); 18971 18972 18973 _BCM_MPLS_VPN_GET(vpn_id, _BCM_MPLS_VPN_TYPE_VPWS, vpn); 18974 18975 (void) _bcm_tr_mpls_vpws_vp_map_get (unit, vpn_id, &vp1, &vp2, &vp3_read); 18976 18977 if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeMpls)) { 18978 return BCM_E_NOT_FOUND; 18979 } 18980 18981 if (vp1 != -1) { 18982 BCM_IF_ERROR_RETURN ( 18983 READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp1, &svp1)); 18984 if (soc_SOURCE_VPm_field32_get(unit, &svp1, ENTRY_TYPEf) != 0) { 18985 valid |= 1; 18986 BCM_IF_ERROR_RETURN ( 18987 READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp1, &dvp1)); 18988 } 18989 } 18990 18991 if ((vp2 != -1) || (bcmi_mpls_match_backup_ports(unit, vpn_id, vp))) { 18992 if ((vp != vp2) && (bcmi_mpls_match_backup_ports(unit, vpn_id, vp))) { 18993 vp2 = vp; 18994 } 18995 if (vp2 != -1) { 18996 BCM_IF_ERROR_RETURN ( 18997 READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp2, &svp2)); 18998 if (soc_SOURCE_VPm_field32_get(unit, &svp2, ENTRY_TYPEf) != 0) { 18999 valid |= 2; 19000 BCM_IF_ERROR_RETURN ( 19001 READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp2, &dvp2)); 19002 } 19003 } 19004 } 19005 19006 if (vp == vp1) { 19007 if (!(valid & 1)) { 19008 return BCM_E_NOT_FOUND; 19009 } 19010 if (soc_feature(unit, soc_feature_generic_dest)) { 19011 dest_val = soc_mem_field32_dest_get(unit, SOURCE_VPm, 19012 &svp1, DESTINATIONf, &dest_type); 19013 if (dest_type == SOC_MEM_FIF_DEST_DVP) { 19014 dvp = dest_val; 19015 } 19016 } else { 19017 dvp = soc_SOURCE_VPm_field32_get(unit, &svp1, DVPf); 19018 } 19019 nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp1, 19020 NEXT_HOP_INDEXf); 19021 } else if (vp == vp2) { 19022 if (!(valid & 2)) { 19023 return BCM_E_NOT_FOUND; 19024 } 19025 19026 if (soc_feature(unit, soc_feature_generic_dest)) { 19027 dest_val = soc_mem_field32_dest_get(unit, SOURCE_VPm, 19028 &svp2, DESTINATIONf, &dest_type); 19029 if (dest_type == SOC_MEM_FIF_DEST_DVP) { 19030 dvp = dest_val; 19031 } 19032 } else { 19033 dvp = soc_SOURCE_VPm_field32_get(unit, &svp2, DVPf); 19034 } 19035 nh_index = soc_ING_DVP_TABLEm_field32_get(unit, 19036 &dvp2, NEXT_HOP_INDEXf); 19037 } else { 19038 /* Read in current table values for VP3 */ 19039 vp3 = vp; 19040 BCM_IF_ERROR_RETURN ( 19041 READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp3, &dvp3)); 19042 BCM_IF_ERROR_RETURN ( 19043 READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp3, &svp3)); 19044 nh_index = soc_ING_DVP_TABLEm_field32_get(unit, 19045 &dvp3, NEXT_HOP_INDEXf); 19046 } 19047 19048 if ((soc_feature(unit, soc_feature_td3_style_mpls)) && 19049 (soc_feature(unit, 19050 soc_feature_multiple_split_horizon_group))) { 19051 rv = soc_mem_field32_modify(unit, EGR_DVP_ATTRIBUTEm, 19052 vp, COMMON__DVP_NETWORK_GROUPf, 0); 19053 if (rv < 0) { 19054 return rv; 19055 } 19056 } 19057 if (soc_mem_field_valid(unit, EGR_DVP_ATTRIBUTEm, MTU_VALUEf) || 19058 soc_mem_field_valid(unit, EGR_DVP_ATTRIBUTEm, COMMON__MTU_VALUEf)) { 19059 rv = _bcm_tr_mpls_port_mtu_clear(unit, vp); 19060 if (rv < 0) { 19061 return rv; 19062 } 19063 } 19064 19065 if (vpless_failover_port) { 19066 failover_port = TRUE; 19067 } else { 19068 source_vp_entry_t svp_uni; 19069 ing_dvp_table_entry_t dvp_nni; 19070 int dvp_num_nni = 0; /* network side dvp number*/ 19071 19072 /* check if vp is a failover port. Both failover port and 19073 * primary port should point to the same DVP customer(uni) side. 19074 */ 19075 if (vp3_read != -1) { 19076 int del_fo_nh = 0; 19077 sal_memset(&svp_uni, 0, sizeof(source_vp_entry_t)); 19078 sal_memset(&dvp_nni, 0, sizeof(ing_dvp_table_entry_t)); 19079 if (dvp == 0) { 19080 del_fo_nh = 1; 19081 } else { 19082 BCM_IF_ERROR_RETURN (READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, 19083 dvp, &svp_uni)); 19084 19085 if (soc_feature(unit, soc_feature_generic_dest)) { 19086 dest_val = soc_mem_field32_dest_get(unit, SOURCE_VPm, 19087 &svp_uni, DESTINATIONf, &dest_type); 19088 if (dest_type == SOC_MEM_FIF_DEST_DVP) { 19089 dvp_num_nni = dest_val; 19090 } 19091 } else { 19092 dvp_num_nni = soc_SOURCE_VPm_field32_get(unit, &svp_uni, DVPf); 19093 } 19094 if (dvp_num_nni && (dvp_num_nni != vp)) { 19095 /* we need to check if this is the prime multi level backup port 19096 get the nh index */ 19097 del_fo_nh = 1; 19098 } 19099 } 19100 if (del_fo_nh) { 19101 /* possbile failover port case */ 19102 BCM_IF_ERROR_RETURN (READ_ING_DVP_TABLEm(unit, 19103 MEM_BLOCK_ANY, vp3_read, &dvp_nni)); 19104 prot_index = soc_ING_DVP_TABLEm_field32_get(unit, 19105 &dvp_nni, NEXT_HOP_INDEXf); 19106 rv = _bcm_esw_failover_prot_nhi_get (unit, prot_index, 19107 &failover_id, &failover_nh_index, &failover_mc_group); 19108 /* For 1+1 protection NHI use failover multicast group index */ 19109 /* Do this only if this is not a multi level level protection. 19110 * For multi level protection, we wil have mc group pointing to 19111 * backup links 19112 */ 19113 if (BCM_SUCCESS(rv) && (failover_mc_group > 0) && 19114 (!(_BCM_FAILOVER_IS_MULTI_LEVEL(failover_id)))) { 19115 19116 rv = _bcm_tr_mpls_vpless_failover_nh_index_find(unit, vp, 19117 prot_index, &failover_nh_index); 19118 } 19119 if (BCM_SUCCESS(rv)) { 19120 if (failover_nh_index == nh_index) { 19121 /* confirm the failover port */ 19122 failover_port = TRUE; 19123 BCM_IF_ERROR_RETURN(_bcm_esw_failover_prot_nhi_cleanup(unit, 19124 prot_index)); 19125 } 19126 } 19127 } 19128 } 19129 if (bcmi_mpls_match_backup_ports(unit, vpn_id, vp)) { 19130 failover_port = TRUE; 19131 } 19132 } 19133 19134 /* If the other port is valid, point it to itself */ 19135 if (vp == vp1) { 19136 rv = _bcm_esw_mpls_match_delete(unit, 19137 vpless_failover_port == FALSE? 19138 vp: 19139 _BCM_MPLS_GPORT_FAILOVER_VPLESS_SET(vp), TRUE); 19140 if ( rv < 0 ) { 19141 if (rv != BCM_E_NOT_FOUND) { 19142 return rv; 19143 } else { 19144 rv = BCM_E_NONE; 19145 } 19146 } 19147 19148 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) 19149 if (soc_feature(unit, soc_feature_global_meter)) { 19150 rv = _bcm_esw_get_policer_from_table(unit, SOURCE_VPm, vp1, &svp1, 19151 &policer, 1); 19152 if(BCM_SUCCESS(rv)) { 19153 _bcm_esw_policer_decrement_ref_count(unit, policer); 19154 } else { 19155 return rv; 19156 } 19157 } 19158 #endif /* BCM_KATANA_SUPPORT or BCM_TRIUMPH3_SUPPORT */ 19159 19160 if (soc_feature(unit, soc_feature_generic_dest)) { 19161 dest_val = soc_mem_field32_dest_get(unit, SOURCE_VPm, 19162 &svp2, DESTINATIONf, &dest_type); 19163 if (dest_type == SOC_MEM_FIF_DEST_DVP) { 19164 temp_vp3 = dest_val; 19165 } 19166 19167 } else { 19168 temp_vp3 = soc_SOURCE_VPm_field32_get(unit, &svp2, DVPf); 19169 } 19170 if ((rv >= 0) && (failover_port == FALSE)) { 19171 if ((vp2 != -1) && 19172 (vp1 == temp_vp3)) { 19173 if (soc_feature(unit, soc_feature_generic_dest)) { 19174 dest_val = 0; 19175 rv = bcmi_td3_soc_mem_fields32_modify(unit, 19176 SOURCE_VPm, vp2, dest_field, dest_val); 19177 } else { 19178 rv = soc_mem_field32_modify(unit, SOURCE_VPm, 19179 vp2, DVPf, 0); 19180 } 19181 /* Please update other backup ports here */ 19182 bcmi_mpls_update_dvp_in_backup_ports(unit, vpn_id, -1); 19183 } 19184 19185 if ((rv >= 0) && (vp3_read != -1)) { 19186 BCM_IF_ERROR_RETURN ( 19187 READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp3_read, &svp3)); 19188 if (vp1 == temp_vp3) { 19189 if (soc_feature(unit, soc_feature_generic_dest)) { 19190 dest_val = 0; 19191 rv = bcmi_td3_soc_mem_fields32_modify(unit, 19192 SOURCE_VPm, vp3_read, dest_field, dest_val); 19193 } else { 19194 rv = soc_mem_field32_modify(unit, SOURCE_VPm, 19195 vp3_read, DVPf, 0); 19196 } 19197 } 19198 } 19199 } 19200 } else if (vp == vp2) { 19201 if (bcmi_mpls_clear_mpls_entry_for_vp(unit, vpn_id, vp)) { 19202 (void) bcm_tr_mpls_match_clear (unit, vp); 19203 } else { 19204 rv = _bcm_esw_mpls_match_delete(unit, 19205 vpless_failover_port == FALSE? 19206 vp: 19207 _BCM_MPLS_GPORT_FAILOVER_VPLESS_SET(vp), TRUE); 19208 19209 if ( rv < 0 ) { 19210 if (rv != BCM_E_NOT_FOUND) { 19211 return rv; 19212 } else { 19213 rv = BCM_E_NONE; 19214 } 19215 } 19216 } 19217 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) 19218 if (soc_feature(unit, soc_feature_global_meter)) { 19219 rv = _bcm_esw_get_policer_from_table(unit, SOURCE_VPm, vp2, &svp2, 19220 &policer, 1); 19221 if(BCM_SUCCESS(rv)) { 19222 _bcm_esw_policer_decrement_ref_count(unit, policer); 19223 } else { 19224 return rv; 19225 } 19226 } 19227 #endif /* BCM_KATANA_SUPPORT or BCM_TRIUMPH3_SUPPORT */ 19228 19229 if (rv >= 0 && (failover_port == FALSE)) { 19230 if (vp1 != -1) { 19231 if (soc_feature(unit, soc_feature_generic_dest)) { 19232 dest_val = 0; 19233 rv = bcmi_td3_soc_mem_fields32_modify(unit, 19234 SOURCE_VPm, vp1, dest_field, dest_val); 19235 } else { 19236 rv = soc_mem_field32_modify(unit, SOURCE_VPm, 19237 vp1, DVPf, 0); 19238 } 19239 } 19240 } 19241 } else if (vp == vp3) { 19242 /* vp1: customer side mpls port 19243 * vp2: failover port 19244 * vp3: service side primary mpls port 19245 */ 19246 int match_label_delete = TRUE; 19247 int fo_vp = -1; 19248 if (soc_feature(unit, soc_feature_generic_dest)) { 19249 dest_val = soc_mem_field32_dest_get(unit, SOURCE_VPm, 19250 &svp3, DESTINATIONf, &dest_type); 19251 if (dest_type == SOC_MEM_FIF_DEST_DVP) { 19252 dvp = dest_val; 19253 } 19254 } else { 19255 dvp = soc_SOURCE_VPm_field32_get(unit, &svp3, DVPf); 19256 } 19257 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) 19258 if (soc_feature(unit, soc_feature_global_meter)) { 19259 rv = _bcm_esw_get_policer_from_table(unit, SOURCE_VPm, vp3, &svp3, 19260 &policer, 1); 19261 if(BCM_SUCCESS(rv)) { 19262 _bcm_esw_policer_decrement_ref_count(unit, policer); 19263 } else { 19264 return rv; 19265 } 19266 } 19267 #endif /* BCM_KATANA_SUPPORT or BCM_TRIUMPH3_SUPPORT */ 19268 if (rv >= 0) { 19269 if (soc_feature(unit, soc_feature_generic_dest)) { 19270 dest_val = 0; 19271 rv = bcmi_td3_soc_mem_fields32_modify(unit, 19272 SOURCE_VPm, vp3, dest_field, dest_val); 19273 } else { 19274 rv = soc_mem_field32_modify(unit, SOURCE_VPm, 19275 vp3, DVPf, 0); 19276 } 19277 } 19278 failover_nh_index = -1; 19279 failover_mc_group = -1; 19280 if (BCM_SUCCESS(rv)) { 19281 rv = _bcm_esw_failover_prot_nhi_get (unit, nh_index, 19282 &failover_id, &failover_nh_index, &failover_mc_group); 19283 } 19284 if (BCM_SUCCESS(rv) && 19285 ((failover_nh_index > 0) || (failover_mc_group > 0))) { 19286 19287 if (failover_nh_index > 0) { 19288 /* a failover port exists, vc_term label is shared with failover 19289 * port. let the failover port delete it. 19290 */ 19291 fo_vp = dvp==vp1?vp2:vp1; 19292 if ((dvp > 0) && (fo_vp != -1)) { 19293 if (soc_feature(unit, soc_feature_generic_dest)) { 19294 rv = bcmi_td3_soc_mem_fields32_modify(unit, 19295 SOURCE_VPm, dvp, dest_field, fo_vp); 19296 } else { 19297 rv = soc_mem_field32_modify(unit, SOURCE_VPm, 19298 dvp, DVPf, fo_vp); 19299 } 19300 } 19301 if ((fo_vp != -1) && 19302 (mpls_info->match_key[vp3].flags == 19303 _BCM_MPLS_PORT_MATCH_TYPE_LABEL)) { 19304 mpls_info->match_key[fo_vp].match_label = 19305 mpls_info->match_key[vp3].match_label; 19306 mpls_info->match_key[fo_vp].flags |= 19307 _BCM_MPLS_PORT_MATCH_TYPE_LABEL; 19308 mpls_info->match_key[fo_vp].modid = 0; 19309 mpls_info->match_key[fo_vp].port = 0; 19310 match_label_delete = FALSE; 19311 } 19312 } 19313 if (BCM_SUCCESS(rv)) { 19314 rv = _bcm_esw_failover_prot_nhi_cleanup(unit,nh_index); 19315 } 19316 } 19317 if (rv < 0 ) { 19318 if ((rv == BCM_E_NOT_FOUND) || (rv == BCM_E_UNAVAIL)) { 19319 rv = 0; 19320 } else { 19321 return rv; 19322 } 19323 } 19324 if (match_label_delete) { 19325 rv = _bcm_esw_mpls_match_delete(unit, vp, TRUE); 19326 if ( rv < 0 ) { 19327 if (rv != BCM_E_NOT_FOUND) { 19328 return rv; 19329 } else { 19330 rv = BCM_E_NONE; 19331 } 19332 } 19333 } else { 19334 /* Update source vp in mpls entry on primary vp deletion */ 19335 if (fo_vp != -1) { 19336 (void) _bcm_esw_mpls_match_failover_update(unit, vp, fo_vp); 19337 } 19338 (void) bcm_tr_mpls_match_clear (unit, vp); 19339 } 19340 } 19341 19342 if (rv >= 0) { 19343 /* Invalidate the VP being deleted */ 19344 if ((vp == vp1) && (vpless_failover_port == FALSE)) { 19345 #if defined(BCM_TRIUMPH2_SUPPORT) 19346 if (!is_trunk) { 19347 rv = _bcm_mpls_source_vp_clear(unit, criteria, vp, vpn); 19348 if (BCM_FAILURE(rv)) { 19349 return rv; 19350 } 19351 } 19352 #endif 19353 sal_memset(&svp1, 0, sizeof(source_vp_entry_t)); 19354 rv = WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, vp1, &svp1); 19355 if (rv >= 0) { 19356 ing_dvp_table_entry_t dvp_tmp; 19357 sal_memset(&dvp_tmp, 0, sizeof(ing_dvp_table_entry_t)); 19358 rv = WRITE_ING_DVP_TABLEm(unit, MEM_BLOCK_ALL, vp1, &dvp_tmp); 19359 } 19360 19361 /*Reset CMH SVP ATTRIBUTES*/ 19362 if (soc_feature(unit,soc_feature_td3_style_mpls)) { 19363 rv = bcmi_cmh_svp_attributes_set(unit, 2, vp1, 19364 FALSE, 0); 19365 if (rv < 0) { 19366 return rv; 19367 } 19368 } 19369 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 19370 if (rv >= 0 && 19371 soc_feature(unit, soc_feature_ifp_redirect_to_dvp)) { 19372 ing_dvp_2_table_entry_t dvp_tmp; 19373 sal_memset(&dvp_tmp, 0, sizeof(ing_dvp_2_table_entry_t)); 19374 rv = WRITE_ING_DVP_2_TABLEm(unit, MEM_BLOCK_ALL, vp1, &dvp_tmp); 19375 } 19376 #endif 19377 } else if ((vp == vp2) && (vpless_failover_port == FALSE)) { 19378 #if defined(BCM_TRIUMPH2_SUPPORT) 19379 if (!is_trunk) { 19380 rv = _bcm_mpls_source_vp_clear(unit, criteria, vp, vpn); 19381 if (BCM_FAILURE(rv)) { 19382 return rv; 19383 } 19384 } 19385 #endif 19386 sal_memset(&svp2, 0, sizeof(source_vp_entry_t)); 19387 rv = WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, vp2, &svp2); 19388 if (rv >= 0) { 19389 ing_dvp_table_entry_t dvp_tmp; 19390 sal_memset(&dvp_tmp, 0, sizeof(ing_dvp_table_entry_t)); 19391 rv = WRITE_ING_DVP_TABLEm(unit, MEM_BLOCK_ALL, vp2, &dvp_tmp); 19392 } 19393 19394 /*Reset CMH SVP ATTRIBUTES*/ 19395 if (soc_feature(unit,soc_feature_td3_style_mpls)) { 19396 rv = bcmi_cmh_svp_attributes_set(unit, 2, vp2, 19397 FALSE, 0); 19398 if (rv < 0) { 19399 return rv; 19400 } 19401 } 19402 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 19403 if (rv >= 0 && 19404 soc_feature(unit, soc_feature_ifp_redirect_to_dvp)) { 19405 ing_dvp_2_table_entry_t dvp_tmp; 19406 sal_memset(&dvp_tmp, 0, sizeof(ing_dvp_2_table_entry_t)); 19407 rv = WRITE_ING_DVP_2_TABLEm(unit, MEM_BLOCK_ALL, vp2, &dvp_tmp); 19408 } 19409 #endif 19410 } else if (vp == vp3) { 19411 sal_memset(&svp3, 0, sizeof(source_vp_entry_t)); 19412 rv = WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, vp3, &svp3); 19413 if (rv >= 0) { 19414 ing_dvp_table_entry_t dvp_tmp; 19415 sal_memset(&dvp_tmp, 0, sizeof(ing_dvp_table_entry_t)); 19416 rv = WRITE_ING_DVP_TABLEm(unit, MEM_BLOCK_ALL, vp3, &dvp_tmp); 19417 } 19418 19419 /*Reset CMH SVP ATTRIBUTES*/ 19420 if (soc_feature(unit,soc_feature_td3_style_mpls)) { 19421 rv = bcmi_cmh_svp_attributes_set(unit, 2, vp3, 19422 FALSE, 0); 19423 if (rv < 0) { 19424 return rv; 19425 } 19426 } 19427 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 19428 if (rv >= 0 && 19429 soc_feature(unit, soc_feature_ifp_redirect_to_dvp)) { 19430 ing_dvp_2_table_entry_t dvp_tmp; 19431 sal_memset(&dvp_tmp, 0, sizeof(ing_dvp_2_table_entry_t)); 19432 rv = WRITE_ING_DVP_2_TABLEm(unit, MEM_BLOCK_ALL, vp3, &dvp_tmp); 19433 } 19434 #endif 19435 if (vp1 != -1) { 19436 if (vp2 != -1) { 19437 if (soc_feature(unit, soc_feature_generic_dest)) { 19438 rv = bcmi_td3_soc_mem_fields32_modify(unit, 19439 SOURCE_VPm, vp1, dest_field, vp2); 19440 } else { 19441 rv = soc_mem_field32_modify(unit, SOURCE_VPm, vp1, DVPf, vp2); 19442 } 19443 } else { 19444 if (soc_feature(unit, soc_feature_generic_dest)) { 19445 dest_val = 0; 19446 rv = bcmi_td3_soc_mem_fields32_modify(unit, SOURCE_VPm, 19447 vp1, dest_field, dest_val); 19448 } else { 19449 rv = soc_mem_field32_modify(unit, SOURCE_VPm, vp1, DVPf, 0); 19450 } 19451 } 19452 } 19453 } 19454 19455 if (vp != vp3) { 19456 /* Free vp-less failover port resource when deleting 19457 * either vp-less failover port or its primary port. 19458 */ 19459 failover_nh_index = -1; 19460 failover_mc_group = -1; 19461 rv = _bcm_esw_failover_prot_nhi_get (unit, nh_index, 19462 &failover_id, &failover_nh_index, &failover_mc_group); 19463 if (BCM_SUCCESS(rv)) { 19464 if (failover_mc_group > 0) { 19465 rv = _bcm_tr_mpls_vpless_failover_nh_index_find(unit,vp,nh_index, 19466 &failover_nh_index); 19467 } 19468 if (failover_nh_index > 0) { 19469 rv = _bcm_tr_mpls_l2_nh_info_delete(unit, 19470 failover_nh_index); 19471 if (BCM_SUCCESS(rv)) { 19472 rv = _bcm_esw_failover_prot_nhi_cleanup(unit,nh_index); 19473 } 19474 } 19475 } else if (rv == BCM_E_UNAVAIL) { 19476 if (soc_feature(unit, soc_feature_mpls_software_failover) && 19477 (vpless_failover_port == TRUE) ) { 19478 rv = _bcm_tr_mpls_vpless_failover_nh_index_find(unit,vp,nh_index, 19479 &failover_nh_index); 19480 if (BCM_SUCCESS(rv)) { 19481 rv = _bcm_tr_mpls_l2_nh_info_delete(unit, failover_nh_index); 19482 } 19483 } 19484 } 19485 19486 if (rv < 0 ) { 19487 if ((rv == BCM_E_NOT_FOUND) || (rv == BCM_E_UNAVAIL)) { 19488 rv = 0; 19489 } else { 19490 return rv; 19491 } 19492 } 19493 } 19494 19495 /* Delete the next-hop info */ 19496 if ((rv >= 0) && (vpless_failover_port == FALSE)) { 19497 rv = _bcm_tr_mpls_l2_nh_info_delete(unit, nh_index); 19498 } 19499 if ( rv < 0 ) { 19500 if (rv != BCM_E_NOT_FOUND) { 19501 return rv; 19502 } else { 19503 rv = 0; 19504 } 19505 } 19506 /* Free the VP */ 19507 if (vpless_failover_port == FALSE) { 19508 (void) _bcm_vp_free(unit, _bcmVpTypeMpls, 1, vp); 19509 _BCM_MPLS_NETWORK_VP_USED_CLR(unit, vp); 19510 if (vp == vp1) { 19511 _bcm_tr_mpls_vpws_vp_map_set(unit, vpn_id, -1, vp2, vp3_read); 19512 } else if (vp == vp2) { 19513 _bcm_tr_mpls_vpws_vp_map_backup_port_clear(unit, vpn_id, vp2); 19514 } else if (vp == vp3) { 19515 _bcm_tr_mpls_vpws_vp_map_set(unit, vpn_id, vp1, vp2, -1); 19516 } 19517 } 19518 } 19519 } else if (_BCM_MPLS_VPN_IS_VPLS(vpn)) { 19520 int nh_index = 0, vfi; 19521 source_vp_entry_t svp; 19522 ing_dvp_table_entry_t dvp; 19523 #if defined(BCM_TRIDENT2_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) \ 19524 || defined(BCM_TRIDENT_SUPPORT) 19525 ing_dvp_2_table_entry_t dvp2; 19526 #endif /* BCM_TRIDENT2_SUPPORT or BCM_TRIUMPH3_SUPPORT or BCM_TRIDENT_SUPPORT */ 19527 19528 sal_memset(&svp, 0, sizeof(source_vp_entry_t)); 19529 sal_memset(&dvp, 0, sizeof(ing_dvp_table_entry_t)); 19530 #if defined(BCM_TRIDENT2_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) \ 19531 || defined(BCM_TRIDENT_SUPPORT) 19532 if (SOC_IS_TRIUMPH3(unit) || SOC_IS_TRIDENT2X(unit) 19533 || SOC_IS_TRIDENT(unit) || SOC_IS_TRIDENT3X(unit) || 19534 SOC_IS_TOMAHAWKX(unit)) { 19535 sal_memset(&dvp2, 0, sizeof(ing_dvp_2_table_entry_t)); 19536 } 19537 #endif /* BCM_TRIDENT2_SUPPORT or BCM_TRIUMPH3_SUPPORT or BCM_TRIDENT_SUPPORT */ 19538 19539 _BCM_MPLS_VPN_GET(vfi, _BCM_MPLS_VPN_TYPE_VPLS, vpn); 19540 if (!_bcm_vfi_used_get(unit, vfi, _bcmVfiTypeMpls)) { 19541 return BCM_E_NOT_FOUND; 19542 } 19543 if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeMpls)) { 19544 return BCM_E_NOT_FOUND; 19545 } 19546 19547 BCM_IF_ERROR_RETURN ( 19548 READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp, &svp)); 19549 if (soc_SOURCE_VPm_field32_get(unit, &svp, ENTRY_TYPEf) == 0) { 19550 return BCM_E_NOT_FOUND; 19551 } 19552 19553 rv = READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp, &dvp); 19554 if (rv < 0) { 19555 return rv; 19556 } 19557 nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, NEXT_HOP_INDEXf); 19558 if (soc_mem_field_valid(unit, EGR_DVP_ATTRIBUTEm, MTU_VALUEf) || 19559 soc_mem_field_valid(unit, EGR_DVP_ATTRIBUTEm, COMMON__MTU_VALUEf)) { 19560 rv = _bcm_tr_mpls_port_mtu_clear(unit, vp); 19561 if (rv < 0) { 19562 return rv; 19563 } 19564 } 19565 19566 /* 19567 * In case we are removing the failover port, 19568 * we should clean protection tables also. 19569 * check for primary matching entry and then 19570 * make sure that this is failover port for that entry. 19571 */ 19572 if (soc_feature(unit, soc_feature_mpls_failover)) { 19573 mpls_entry_entry_t ret_ment; 19574 int primary_port=0, primary_nh_index=0; 19575 int cleanup = 1; 19576 19577 rv = _bcm_esw_mpls_failover_nw_port_match_get(unit, NULL, vp, &ret_ment); 19578 19579 if (rv == BCM_E_NONE) { 19580 ing_dvp_table_entry_t p_dvp; 19581 19582 primary_port = 19583 soc_MPLS_ENTRYm_field32_get(unit, &ret_ment, MPLS__SOURCE_VPf); 19584 19585 if (primary_port > 0) { 19586 BCM_IF_ERROR_RETURN (READ_ING_DVP_TABLEm(unit, 19587 MEM_BLOCK_ANY, primary_port, &p_dvp)); 19588 primary_nh_index = soc_ING_DVP_TABLEm_field32_get(unit, 19589 &p_dvp, NEXT_HOP_INDEXf); 19590 19591 19592 rv = _bcm_esw_failover_prot_nhi_get (unit, 19593 primary_nh_index, &failover_id, 19594 &failover_nh_index, &failover_mc_group); 19595 19596 if (failover_nh_index > 0) { 19597 /* check if we can cleanup the failover entry if failover port 19598 * is getting deleted 19599 */ 19600 rv = bcmi_mpls_failover_nhi_cleanup_check( 19601 unit, vpn, vp, failover_id, 19602 failover_nh_index, primary_nh_index, nh_index, &cleanup); 19603 if (rv) { 19604 return(rv); 19605 } 19606 19607 if (cleanup) { 19608 /* Clean failover protection entry.*/ 19609 rv = _bcm_esw_failover_prot_nhi_cleanup(unit, primary_nh_index); 19610 if (rv) { 19611 return(rv); 19612 } 19613 } 19614 if (primary_port != vp) { 19615 /* clean s/w state so that match delete does not 19616 * find this port to delete matching entry. 19617 * else, match_delete routing can remove 19618 * primary port entry as that is with same label */ 19619 (void) bcm_tr_mpls_match_clear (unit, vp); 19620 } 19621 } 19622 } 19623 } else if (rv != BCM_E_NOT_FOUND) { 19624 return rv; 19625 } 19626 } 19627 19628 BCM_IF_ERROR_RETURN(_bcm_vp_info_get(unit, vp, &vp_info)); 19629 if (!(vp_info.flags & _BCM_VP_INFO_SHARED_PORT)) { 19630 rv = _bcm_esw_mpls_match_delete(unit, 19631 vpless_failover_port == FALSE? vp: 19632 _BCM_MPLS_GPORT_FAILOVER_VPLESS_SET(vp), TRUE); 19633 if ( rv < 0 ) { 19634 if (rv != BCM_E_NOT_FOUND) { 19635 return rv; 19636 } 19637 } 19638 } else { 19639 if (mpls_info->match_key[vp].match_count == 0) { 19640 bcm_tr_mpls_match_clear (unit, vp); 19641 } 19642 } 19643 19644 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) 19645 if (soc_feature(unit, soc_feature_global_meter)) { 19646 rv = _bcm_esw_get_policer_from_table(unit, SOURCE_VPm, vp, &svp, 19647 &policer, 0); 19648 if(BCM_SUCCESS(rv)) { 19649 _bcm_esw_policer_decrement_ref_count(unit, policer); 19650 } else { 19651 return rv; 19652 } 19653 } 19654 #endif /* BCM_KATANA_SUPPORT or BCM_TRIUMPH3_SUPPORT*/ 19655 19656 if (vpless_failover_port == FALSE) { 19657 #if defined(BCM_TRIUMPH2_SUPPORT) 19658 if (!is_trunk) { 19659 rv = _bcm_mpls_source_vp_clear(unit, criteria, vp, vpn); 19660 if (BCM_FAILURE(rv)) { 19661 return rv; 19662 } 19663 } 19664 #endif 19665 /* Clear the SVP and DVP table entries */ 19666 sal_memset(&svp, 0, sizeof(source_vp_entry_t)); 19667 rv = WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, vp, &svp); 19668 if (rv < 0) { 19669 return rv; 19670 } 19671 19672 _bcm_vp_vfi_set(unit, vp, 0); 19673 19674 /*Reset CMH SVP ATTRIBUTES*/ 19675 if (soc_feature(unit,soc_feature_td3_style_mpls)) { 19676 rv = bcmi_cmh_svp_attributes_set(unit, 1, vp, 19677 FALSE, 0); 19678 if (rv < 0) { 19679 return rv; 19680 } 19681 } 19682 19683 sal_memset(&dvp, 0, sizeof(ing_dvp_table_entry_t)); 19684 rv = WRITE_ING_DVP_TABLEm(unit, MEM_BLOCK_ALL, vp, &dvp); 19685 if (rv < 0) { 19686 return rv; 19687 } 19688 rv = _bcm_vp_ing_dvp_to_ing_dvp2(unit, &dvp, vp); 19689 if (rv < 0) { 19690 return rv; 19691 } 19692 #if defined(BCM_TRIDENT2_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) \ 19693 || defined(BCM_TRIDENT_SUPPORT) 19694 if (SOC_IS_TRIUMPH3(unit) || SOC_IS_TRIDENT2X(unit) 19695 || SOC_IS_TRIDENT(unit) || SOC_IS_TRIDENT3X(unit) || 19696 SOC_IS_TOMAHAWKX(unit)) { 19697 sal_memset(&dvp2, 0, sizeof(ing_dvp_2_table_entry_t)); 19698 rv = WRITE_ING_DVP_2_TABLEm(unit, MEM_BLOCK_ALL, vp, &dvp2); 19699 if (rv < 0) { 19700 return rv; 19701 } 19702 } 19703 #endif /* BCM_TRIDENT2_SUPPORT or BCM_TRIUMPH3_SUPPORT or BCM_TRIDENT_SUPPORT */ 19704 19705 if ((soc_feature(unit, soc_feature_td3_style_mpls)) && 19706 (soc_feature(unit, 19707 soc_feature_multiple_split_horizon_group))) { 19708 rv = soc_mem_field32_modify(unit, EGR_DVP_ATTRIBUTEm, 19709 vp, COMMON__DVP_NETWORK_GROUPf, 0); 19710 if (rv < 0) { 19711 return rv; 19712 } 19713 } 19714 } 19715 19716 #if defined(BCM_TRIUMPH2_SUPPORT) 19717 if (soc_feature(unit, soc_feature_mpls_failover)) { 19718 rv = _bcm_esw_failover_prot_nhi_get (unit, nh_index, 19719 &failover_id, &failover_nh_index, &failover_mc_group); 19720 /*For 1+1 vpless failover get failover nhi using multicast group index*/ 19721 if(failover_mc_group > 0){ 19722 rv = _bcm_tr_mpls_vpless_failover_nh_index_find(unit,vp,nh_index, 19723 &failover_nh_index); 19724 } 19725 if ((failover_nh_index > 0) && (!(_BCM_FAILOVER_IS_MULTI_LEVEL(failover_id)))) { 19726 BCM_IF_ERROR_RETURN (soc_mem_read(unit, EGR_L3_NEXT_HOPm, 19727 MEM_BLOCK_ANY, failover_nh_index, &egr_nh)); 19728 if (soc_feature(unit, soc_feature_mpls_enhanced)) { 19729 failover_dvp = soc_EGR_L3_NEXT_HOPm_field32_get(unit, 19730 &egr_nh, MPLS__DVPf); 19731 } else { 19732 failover_dvp = soc_EGR_L3_NEXT_HOPm_field32_get(unit, 19733 &egr_nh, DVPf); 19734 } 19735 /* 19736 * If vpless failover, delete failover nh index also. 19737 * If non-vpless failover, do not delete failover nh index. 19738 * .If this is the VPLESS primary port being deleted, then the 19739 * VPLESS backup port's nh index is also removed. 19740 * .If this is the VPLESS backup port being deleted, 19741 * failover_nh_index is its own nh index, so backup port's 19742 * nh index will be removed. 19743 */ 19744 if (failover_dvp == vp) { 19745 rv = _bcm_tr_mpls_l2_nh_info_delete(unit, failover_nh_index); 19746 } else { 19747 int rv1; 19748 bcm_mpls_port_t failover_mpls_port; 19749 bcm_mpls_port_t_init(&failover_mpls_port); 19750 rv1 = _bcm_esw_mpls_match_get(unit, &failover_mpls_port, failover_dvp); 19751 if (rv1 == BCM_E_NOT_FOUND) { 19752 BCM_IF_ERROR_RETURN(_bcm_esw_mpls_match_add(unit, &failover_mpls_port, 19753 failover_dvp, vpn, TRUE)); 19754 } 19755 } 19756 } 19757 if (BCM_SUCCESS(rv)) { 19758 rv = _bcm_esw_failover_prot_nhi_cleanup(unit,nh_index); 19759 } 19760 19761 if ( rv < 0 ) { 19762 if (rv != BCM_E_NOT_FOUND) { 19763 return rv; 19764 } else { 19765 rv = 0; 19766 } 19767 } 19768 } else 19769 #endif /* BCM_TRIUMPH2_SUPPORT */ 19770 if (soc_feature(unit, soc_feature_mpls_software_failover) && 19771 (vpless_failover_port == TRUE) ) { 19772 rv = _bcm_tr_mpls_vpless_failover_nh_index_find(unit,vp,nh_index, 19773 &failover_nh_index); 19774 if (BCM_SUCCESS(rv)) { 19775 rv = _bcm_tr_mpls_l2_nh_info_delete(unit, failover_nh_index); 19776 } 19777 if (rv < 0 ) { 19778 if (rv != BCM_E_NOT_FOUND) { 19779 return rv; 19780 } else { 19781 rv = 0; 19782 } 19783 } 19784 } 19785 19786 if (vpless_failover_port == FALSE) { 19787 /* Delete the next-hop info */ 19788 if (rv >= 0) { 19789 rv = _bcm_tr_mpls_l2_nh_info_delete(unit, nh_index); 19790 } 19791 if ( rv < 0 ) { 19792 if (rv != BCM_E_NOT_FOUND) { 19793 return rv; 19794 } else { 19795 rv = 0; 19796 } 19797 } 19798 19799 /* Free the VP */ 19800 (void) _bcm_vp_free(unit, _bcmVpTypeMpls, 1, vp); 19801 _BCM_MPLS_NETWORK_VP_USED_CLR(unit, vp); 19802 #ifdef BCM_TRIUMPH2_SUPPORT 19803 if (soc_feature(unit, soc_feature_mpls_failover)) { 19804 int i; 19805 int num_vp = soc_mem_index_count(unit, SOURCE_VPm); 19806 for (i = 0; i < num_vp; i++) { 19807 if (mpls_info->failover_vp[i] == vp) { 19808 mpls_info->failover_vp[i] = 0; 19809 } 19810 } 19811 mpls_info->failover_vp[vp] = 0; 19812 19813 } 19814 #endif 19815 } 19816 } 19817 19818 #ifdef BCM_TRIUMPH2_SUPPORT 19819 if (soc_feature(unit, soc_feature_gport_service_counters)) { 19820 bcm_gport_t gport; 19821 19822 /* Release Service counter, if any */ 19823 BCM_GPORT_MPLS_PORT_ID_SET(gport, vp); 19824 _bcm_esw_flex_stat_handle_free(unit, _bcmFlexStatTypeGport, gport); 19825 } 19826 #endif 19827 19828 #ifdef BCM_WARM_BOOT_SUPPORT 19829 SOC_CONTROL_LOCK(unit); 19830 SOC_CONTROL(unit)->scache_dirty = 1; 19831 SOC_CONTROL_UNLOCK(unit); 19832 #endif 19833 19834 return rv; 19835 } 19836 19837 /* 19838 * Function: 19839 * bcm_mpls_port_delete 19840 * Purpose: 19841 * Delete an mpls port from a VPN 19842 * Parameters: 19843 * unit - (IN) Device Number 19844 * vpn - (IN) VPN instance ID 19845 * mpls_port_id - (IN) mpls port information 19846 * Returns: 19847 * BCM_E_XXX 19848 */ 19849 int 19850 bcm_tr_mpls_port_delete(int unit, bcm_vpn_t vpn, bcm_gport_t mpls_port_id) 19851 { 19852 int vp; 19853 19854 if (((vpn == BCM_MPLS_VPWS_VPN_INVALID) || 19855 (vpn == BCM_MPLS_VPLS_VPN_INVALID)) && 19856 !soc_feature(unit, soc_feature_mpls_software_failover)) { 19857 return BCM_E_PARAM; 19858 } 19859 if (!_BCM_MPLS_VPN_IS_VPLS(vpn) && 19860 !_BCM_MPLS_VPN_IS_VPWS(vpn) ) { 19861 return BCM_E_PARAM; 19862 } 19863 19864 vp = BCM_GPORT_MPLS_PORT_ID_GET(mpls_port_id); 19865 if (vp == -1) { 19866 return BCM_E_PARAM; 19867 } 19868 19869 if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeMpls)) { 19870 return BCM_E_NOT_FOUND; 19871 } 19872 if (_BCM_MPLS_GPORT_FAILOVER_VPLESS_GET(mpls_port_id)) { 19873 vp = _BCM_MPLS_GPORT_FAILOVER_VPLESS_SET(vp); 19874 } 19875 return (_bcm_tr_mpls_port_delete(unit, vpn, vp)); 19876 } 19877 /* 19878 * Function: 19879 * bcmi_mpls_delete_backup_ports 19880 * Purpose: 19881 * Delete an mpls backup port 19882 * Parameters: 19883 * unit - (IN) Device Number 19884 * vpn - (IN) VPN instance ID 19885 * vp - (IN) mpls backup port 19886 * Returns: 19887 * BCM_E_XXX 19888 */ 19889 int 19890 bcmi_mpls_delete_backup_ports(int unit, int vpn, int vp) 19891 { 19892 19893 int rv; 19894 source_vp_entry_t svp; 19895 ing_dvp_table_entry_t dvp; 19896 19897 rv = READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp, &svp); 19898 if (rv < 0) { 19899 return rv; 19900 } 19901 19902 rv = READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp, &dvp); 19903 if (rv < 0) { 19904 return rv; 19905 } 19906 if (soc_SOURCE_VPm_field32_get(unit, &svp, ENTRY_TYPEf) != 0) { 19907 rv = _bcm_tr_mpls_port_delete(unit, vpn, vp); 19908 if (rv < 0) { 19909 return rv; 19910 } 19911 } 19912 return BCM_E_NONE; 19913 } 19914 /* 19915 * Function: 19916 * bcmi_mpls_delete_all_backup_ports 19917 * Purpose: 19918 * Delete all mpls backup ports in that vpn 19919 * Parameters: 19920 * unit - (IN) Device Number 19921 * vpn - (IN) VPN instance ID 19922 * Returns: 19923 * BCM_E_XXX 19924 */ 19925 int 19926 bcmi_mpls_delete_all_backup_ports(int unit, bcm_vpn_t vpn) 19927 { 19928 19929 _bcm_tr_mpls_bookkeeping_t *mpls_info = MPLS_INFO(unit); 19930 int max_vpws_vpn, num_vp; 19931 bcm_vpn_t vpn_id; 19932 19933 if (!_BCM_MPLS_VPN_IS_VPWS(vpn)) { 19934 return BCM_E_PARAM; 19935 } 19936 19937 _BCM_MPLS_VPN_GET(vpn_id, _BCM_MPLS_VPN_TYPE_VPWS, vpn); 19938 19939 num_vp = soc_mem_index_count(unit, SOURCE_VPm); 19940 max_vpws_vpn = num_vp / 2; 19941 19942 if (vpn_id <= max_vpws_vpn) { 19943 if (mpls_info->vpws_vp_map[vpn_id].vp_b_1 != -1) { 19944 BCM_IF_ERROR_RETURN(bcmi_mpls_delete_backup_ports(unit, vpn, 19945 mpls_info->vpws_vp_map[vpn_id].vp_b_1)); 19946 } 19947 19948 if (mpls_info->vpws_vp_map[vpn_id].vp_b_2 != -1) { 19949 BCM_IF_ERROR_RETURN(bcmi_mpls_delete_backup_ports(unit, vpn, 19950 mpls_info->vpws_vp_map[vpn_id].vp_b_2)); 19951 } 19952 19953 if (mpls_info->vpws_vp_map[vpn_id].vp_b_3 != -1) { 19954 BCM_IF_ERROR_RETURN(bcmi_mpls_delete_backup_ports(unit, vpn, 19955 mpls_info->vpws_vp_map[vpn_id].vp_b_3)); 19956 } 19957 } 19958 return BCM_E_NONE; 19959 } 19960 19961 /* 19962 * Function: 19963 * bcm_mpls_port_delete_all 19964 * Purpose: 19965 * Delete all mpls ports from a VPN 19966 * Parameters: 19967 * unit - Device Number 19968 * vpn - VPN instance ID 19969 * Returns: 19970 * BCM_E_XXX 19971 */ 19972 int 19973 bcm_tr_mpls_port_delete_all(int unit, bcm_vpn_t vpn) 19974 { 19975 int rv = BCM_E_NONE; 19976 19977 if (!_BCM_MPLS_VPN_IS_VPLS(vpn) && 19978 !_BCM_MPLS_VPN_IS_VPWS(vpn)) { 19979 return BCM_E_PARAM; 19980 } 19981 19982 if (_BCM_MPLS_VPN_IS_VPWS(vpn)) { 19983 int vp1=-1, vp2=-1, vp3_read = -1; 19984 source_vp_entry_t svp1, svp2, svp3; 19985 ing_dvp_table_entry_t dvp1, dvp2, dvp3; 19986 bcm_vpn_t vpn_id; 19987 19988 sal_memset(&svp1, 0, sizeof(source_vp_entry_t)); 19989 sal_memset(&svp2, 0, sizeof(source_vp_entry_t)); 19990 sal_memset(&svp3, 0, sizeof(source_vp_entry_t)); 19991 sal_memset(&dvp1, 0, sizeof(ing_dvp_table_entry_t)); 19992 sal_memset(&dvp2, 0, sizeof(ing_dvp_table_entry_t)); 19993 sal_memset(&dvp3, 0, sizeof(ing_dvp_table_entry_t)); 19994 19995 _BCM_MPLS_VPN_GET(vpn_id, _BCM_MPLS_VPN_TYPE_VPWS, vpn); 19996 19997 (void) _bcm_tr_mpls_vpws_vp_map_get (unit, vpn_id, &vp1, &vp2, &vp3_read); 19998 19999 if (vp1 != -1) { 20000 rv = READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp1, &svp1); 20001 if (rv < 0) { 20002 goto done; 20003 } 20004 rv = READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp1, &dvp1); 20005 if (rv < 0) { 20006 goto done; 20007 } 20008 /* See if the entry already exists */ 20009 if (soc_SOURCE_VPm_field32_get(unit, &svp1, ENTRY_TYPEf) != 0) { 20010 rv = _bcm_tr_mpls_port_delete(unit, vpn, vp1); 20011 if (rv < 0) { 20012 goto done; 20013 } 20014 } 20015 } 20016 20017 if (vp2 != -1) { 20018 rv = READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp2, &svp2); 20019 if (rv < 0) { 20020 goto done; 20021 } 20022 rv = READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp2, &dvp2); 20023 if (rv < 0) { 20024 goto done; 20025 } 20026 if (soc_SOURCE_VPm_field32_get(unit, &svp2, ENTRY_TYPEf) != 0) { 20027 rv = _bcm_tr_mpls_port_delete(unit, vpn, vp2); 20028 if (rv < 0) { 20029 goto done; 20030 } 20031 } 20032 } 20033 #ifdef BCM_MULTI_LEVEL_FAILOVER_SUPPORT 20034 if (soc_feature(unit, soc_feature_hierarchical_protection)) { 20035 rv = bcmi_mpls_delete_all_backup_ports(unit, vpn); 20036 if (rv < 0) { 20037 goto done; 20038 } 20039 } 20040 #endif 20041 /* need to delete vp3 for there may be a dedicated vp for failover port. */ 20042 if (vp3_read != -1) { 20043 rv = READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp3_read, &svp3); 20044 if (rv < 0) { 20045 goto done; 20046 } 20047 rv = READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp3_read, &dvp3); 20048 if (rv < 0) { 20049 goto done; 20050 } 20051 if (soc_SOURCE_VPm_field32_get(unit, &svp3, ENTRY_TYPEf) != 0) { 20052 rv = _bcm_tr_mpls_port_delete(unit, vpn, vp3_read); 20053 if (rv < 0) { 20054 goto done; 20055 } 20056 } 20057 } 20058 } else if (_BCM_MPLS_VPN_IS_VPLS(vpn)) { 20059 uint32 vfi, vp, num_vp; 20060 source_vp_entry_t svp; 20061 20062 sal_memset(&svp, 0, sizeof(source_vp_entry_t)); 20063 20064 _BCM_MPLS_VPN_GET(vfi, _BCM_MPLS_VPN_TYPE_VPLS, vpn); 20065 20066 if (!_bcm_vfi_used_get(unit, vfi, _bcmVfiTypeMpls)) { 20067 rv = BCM_E_NOT_FOUND; 20068 goto done; 20069 } 20070 num_vp = soc_mem_index_count(unit, SOURCE_VPm); 20071 for (vp = 0; vp < num_vp; vp++) { 20072 /* Check for the validity of the VP */ 20073 if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeMpls)) { 20074 continue; 20075 } 20076 rv = READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp, &svp); 20077 if (rv < 0) { 20078 goto done; 20079 } 20080 if ((soc_SOURCE_VPm_field32_get(unit, &svp, ENTRY_TYPEf) == 0x1) && 20081 (vfi == soc_SOURCE_VPm_field32_get(unit, &svp, VFIf))) { 20082 rv = _bcm_tr_mpls_port_delete(unit, vpn, vp); 20083 if (rv < 0) { 20084 goto done; 20085 } 20086 } else if ((soc_feature(unit, soc_feature_vp_sharing) || 20087 soc_feature(unit, soc_feature_nexthop_share_dvp)) && 20088 (_bcm_virtual_bk_info[unit].vp_shared_vp_bitmap)) { 20089 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 20090 if (SHR_BITGET((&_bcm_virtual_bk_info[unit])->vp_shared_vp_bitmap, vp) && 20091 MPLS_INFO(unit)->match_key[vp].match_count > 0) { 20092 rv = _bcm_tr_mpls_port_delete(unit, vpn, vp); 20093 if (rv < 0) { 20094 goto done; 20095 } 20096 } 20097 #endif 20098 } 20099 } 20100 } 20101 20102 done: 20103 return rv; 20104 } 20105 20106 STATIC int 20107 _bcm_tr_mpls_port_get(int unit, bcm_vpn_t vpn, int vp, 20108 bcm_mpls_port_t *mpls_port) 20109 { 20110 #if defined(BCM_TRIDENT3_SUPPORT) 20111 int nw_group = 0; 20112 #endif 20113 int i, nh_index, tpid_enable = 0, rv = BCM_E_NONE; 20114 ing_dvp_table_entry_t dvp; 20115 source_vp_entry_t svp; 20116 int split_horizon_port_flag=0; 20117 int vpless_failover_port = FALSE; /* the failover port without a dedicated vp */ 20118 _bcm_vp_info_t vp_info; 20119 #if defined(BCM_TRIUMPH2_SUPPORT) 20120 int vp1, vp2, vp3; 20121 vp1 = vp2 = vp3 = -1; 20122 #endif 20123 20124 if (soc_feature(unit, soc_feature_th3_style_simple_mpls)) { 20125 return BCM_E_UNAVAIL; 20126 } 20127 20128 /* Initialize the structure */ 20129 bcm_mpls_port_t_init(mpls_port); 20130 BCM_GPORT_MPLS_PORT_ID_SET(mpls_port->mpls_port_id, vp); 20131 20132 if (_BCM_MPLS_GPORT_FAILOVER_VPLESS_GET(vp)) { 20133 vpless_failover_port = TRUE; 20134 mpls_port->mpls_port_id = 20135 _BCM_MPLS_GPORT_FAILOVER_VPLESS_SET(mpls_port->mpls_port_id); 20136 vp = _BCM_MPLS_GPORT_FAILOVER_VPLESS_CLEAR(vp); 20137 20138 mpls_port->flags |= BCM_MPLS_PORT_FAILOVER; 20139 } 20140 20141 BCM_IF_ERROR_RETURN (READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp, &dvp)); 20142 nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, NEXT_HOP_INDEXf); 20143 20144 #if defined(BCM_TRIUMPH2_SUPPORT) 20145 if (soc_feature(unit, soc_feature_mpls_failover)) { 20146 int prot_nh_index =-1; 20147 int prot_mc_group=-1; 20148 int failover_id; 20149 int dvp = -1; 20150 egr_l3_next_hop_entry_t egr_nh; 20151 20152 BCM_IF_ERROR_RETURN(_bcm_esw_failover_prot_nhi_get(unit, nh_index, 20153 &failover_id, &prot_nh_index, &prot_mc_group)); 20154 if (vpless_failover_port == TRUE) { 20155 if (prot_mc_group > 0) { 20156 rv = _bcm_tr_mpls_vpless_failover_nh_index_find(unit, vp, 20157 nh_index, &prot_nh_index); 20158 if (BCM_SUCCESS(rv) && (prot_nh_index > 0)) { 20159 nh_index = prot_nh_index; 20160 } 20161 } else if (prot_nh_index > 0) { 20162 nh_index = prot_nh_index; 20163 } 20164 } 20165 20166 if (failover_id != 0) { 20167 if (prot_mc_group > 0) { 20168 if ((_BCM_MPLS_VPN_IS_VPWS(vpn)) && 20169 (!_BCM_FAILOVER_IS_MULTI_LEVEL(failover_id))){ 20170 bcm_vpn_t vpn_id; 20171 20172 _BCM_MPLS_VPN_GET(vpn_id, _BCM_MPLS_VPN_TYPE_VPWS, vpn); 20173 (void) _bcm_tr_mpls_vpws_vp_map_get (unit, vpn_id, &vp1, 20174 &vp2, &vp3); 20175 if (((FALSE == vpless_failover_port) && (vp3 == vp)) || 20176 (TRUE == vpless_failover_port)) { 20177 BCM_GPORT_MPLS_PORT_ID_SET(mpls_port->failover_port_id, 20178 vp2); 20179 mpls_port->failover_id = failover_id; 20180 mpls_port->failover_mc_group = prot_mc_group; 20181 } 20182 } else { 20183 mpls_port->failover_id = failover_id; 20184 mpls_port->failover_mc_group = prot_mc_group; 20185 #ifdef BCM_TRIUMPH2_SUPPORT 20186 if (soc_feature(unit, soc_feature_mpls_failover)) { 20187 if ((_BCM_MPLS_VPN_IS_VPLS(vpn)) && 20188 (!_BCM_FAILOVER_IS_MULTI_LEVEL(failover_id))) { 20189 if (vpless_failover_port == FALSE) { 20190 _bcm_tr_mpls_bookkeeping_t *mpls_info = MPLS_INFO(unit); 20191 BCM_GPORT_MPLS_PORT_ID_SET(mpls_port->failover_port_id, 20192 mpls_info->failover_vp[vp]); 20193 } else { 20194 BCM_GPORT_MPLS_PORT_ID_SET(mpls_port->failover_port_id, 20195 vp); 20196 } 20197 } 20198 } 20199 #endif 20200 } 20201 } else { 20202 /* Retrieve EGR L3 NHOP Entry */ 20203 BCM_IF_ERROR_RETURN (soc_mem_read(unit, EGR_L3_NEXT_HOPm, 20204 MEM_BLOCK_ANY, prot_nh_index, &egr_nh)); 20205 if (soc_feature(unit, soc_feature_mpls_enhanced)) { 20206 dvp = soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, MPLS__DVPf); 20207 } else { 20208 dvp = soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, DVPf); 20209 } 20210 if (vpless_failover_port == TRUE) { 20211 mpls_port->failover_id = failover_id; 20212 BCM_GPORT_MPLS_PORT_ID_SET(mpls_port->failover_port_id, dvp); 20213 } else { 20214 int primary_dvp = -1; 20215 BCM_IF_ERROR_RETURN (soc_mem_read(unit, EGR_L3_NEXT_HOPm, 20216 MEM_BLOCK_ANY, nh_index, &egr_nh)); 20217 if (soc_feature(unit, soc_feature_mpls_enhanced)) { 20218 primary_dvp = soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, MPLS__DVPf); 20219 } else { 20220 primary_dvp = soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, DVPf); 20221 } 20222 if (primary_dvp != dvp) { 20223 mpls_port->failover_id = failover_id; 20224 BCM_GPORT_MPLS_PORT_ID_SET(mpls_port->failover_port_id, dvp); 20225 } 20226 } 20227 } 20228 } 20229 } 20230 #endif /* BCM_TRIUMPH2_SUPPORT */ 20231 20232 if (soc_mem_field_valid(unit, EGR_DVP_ATTRIBUTEm, MTU_VALUEf) || 20233 soc_mem_field_valid(unit, EGR_DVP_ATTRIBUTEm, COMMON__MTU_VALUEf)) { 20234 rv = _bcm_tr_mpls_port_mtu_get(unit, vp, &mpls_port->mtu); 20235 BCM_IF_ERROR_RETURN(rv); 20236 } 20237 20238 /* Get the match parameters */ 20239 rv = _bcm_esw_mpls_match_get(unit, mpls_port, 20240 vpless_failover_port == FALSE? vp: 20241 _BCM_MPLS_GPORT_FAILOVER_VPLESS_SET(vp)); 20242 BCM_IF_ERROR_RETURN(rv); 20243 20244 /* Check for Network-Port */ 20245 BCM_IF_ERROR_RETURN(_bcm_vp_info_get(unit, vp, &vp_info)); 20246 if (vp_info.flags & _BCM_VP_INFO_NETWORK_PORT) { 20247 split_horizon_port_flag = TRUE; 20248 } 20249 20250 /* Get the next-hop parameters */ 20251 rv = _bcm_tr_mpls_l2_nh_info_get(unit, vp, mpls_port, nh_index); 20252 BCM_IF_ERROR_RETURN(rv); 20253 20254 if ((mpls_port->egress_label.flags & BCM_MPLS_EGRESS_LABEL_ENTROPY_ENABLE) && 20255 (mpls_port->flags2 & BCM_MPLS_PORT2_INGRESS_ENTROPY_ENABLE)) { 20256 mpls_port->flags |= BCM_MPLS_PORT_ENTROPY_ENABLE; 20257 } 20258 20259 if(nh_index>0) 20260 mpls_port->encap_id = nh_index + BCM_XGS3_DVP_EGRESS_IDX_MIN(unit); 20261 /* Fill in SVP parameters */ 20262 BCM_IF_ERROR_RETURN (READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp, &svp)); 20263 mpls_port->if_class = soc_SOURCE_VPm_field32_get(unit, &svp, CLASS_IDf); 20264 if (split_horizon_port_flag) { 20265 mpls_port->flags |= BCM_MPLS_PORT_NETWORK; 20266 } 20267 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) 20268 if (soc_feature(unit, soc_feature_global_meter)) { 20269 _bcm_esw_get_policer_from_table(unit, SOURCE_VPm, vp, &svp, 20270 &mpls_port->policer_id, 1); 20271 } 20272 #endif 20273 if (soc_SOURCE_VPm_field32_get(unit, &svp, SD_TAG_MODEf)) { 20274 #if defined(BCM_TRIDENT3_SUPPORT) 20275 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 20276 uint32 svp_attrs_1[SOC_MAX_MEM_WORDS]; 20277 20278 BCM_IF_ERROR_RETURN(READ_SVP_ATTRS_1m(unit, 20279 MEM_BLOCK_ANY, vp, svp_attrs_1)); 20280 soc_SVP_ATTRS_1m_field_get(unit, 20281 &svp_attrs_1, TPID_ENABLEf, (uint32 *)&tpid_enable); 20282 } else 20283 #endif 20284 { 20285 tpid_enable = soc_SOURCE_VPm_field32_get(unit, &svp, TPID_ENABLEf); 20286 } 20287 if (tpid_enable) { 20288 mpls_port->flags |= BCM_MPLS_PORT_SERVICE_TAGGED; 20289 if (!((mpls_port->flags & BCM_MPLS_PORT_SERVICE_VLAN_ADD) || 20290 (mpls_port->flags & BCM_MPLS_PORT_SERVICE_VLAN_TPID_REPLACE) || 20291 (mpls_port->flags & BCM_MPLS_PORT_SERVICE_TPID_REPLACE) || 20292 (mpls_port->flags & BCM_MPLS_PORT_SERVICE_VLAN_PRI_TPID_REPLACE))) { 20293 for (i = 0; i < 4; i++) { 20294 if (tpid_enable & (1 << i)) { 20295 _bcm_fb2_outer_tpid_entry_get(unit, &mpls_port->service_tpid, i); 20296 } 20297 } 20298 } 20299 } 20300 } 20301 20302 #if defined(BCM_TRIDENT3_SUPPORT) 20303 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 20304 rv = bcmi_egr_dvp_attribute_nwgroup_get(unit, vp, &nw_group); 20305 if (rv == BCM_E_NONE) { 20306 mpls_port->network_group_id = nw_group; 20307 } 20308 } 20309 #endif 20310 20311 return rv; 20312 } 20313 20314 /* 20315 * Function: 20316 * bcm_mpls_port_get 20317 * Purpose: 20318 * Get an mpls port from a VPN 20319 * Parameters: 20320 * unit - (IN) Device Number 20321 * vpn - (IN) VPN instance ID 20322 * mpls_port - (IN/OUT) mpls port information 20323 */ 20324 int 20325 bcm_tr_mpls_port_get(int unit, bcm_vpn_t vpn, bcm_mpls_port_t *mpls_port) 20326 { 20327 int vp; 20328 20329 if (!_BCM_MPLS_VPN_IS_VPLS(vpn) && 20330 !_BCM_MPLS_VPN_IS_VPWS(vpn)) { 20331 if ((vpn != BCM_MPLS_VPWS_VPN_INVALID) && 20332 (vpn != BCM_MPLS_VPLS_VPN_INVALID)) { 20333 return BCM_E_PARAM; 20334 } 20335 } 20336 20337 vp = BCM_GPORT_MPLS_PORT_ID_GET(mpls_port->mpls_port_id); 20338 if (vp == -1) { 20339 return BCM_E_PARAM; 20340 } 20341 20342 if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeMpls)) { 20343 return BCM_E_NOT_FOUND; 20344 } 20345 if (_BCM_MPLS_GPORT_FAILOVER_VPLESS_GET(mpls_port->mpls_port_id)) { 20346 vp = _BCM_MPLS_GPORT_FAILOVER_VPLESS_SET(vp); 20347 } 20348 return _bcm_tr_mpls_port_get(unit, vpn, vp, mpls_port); 20349 } 20350 20351 /* 20352 * Function: 20353 * bcm_mpls_port_get_all 20354 * Purpose: 20355 * Get all mpls ports from a VPN 20356 * Parameters: 20357 * unit - (IN) Device Number 20358 * vpn - (IN) VPN instance ID 20359 * port_max - (IN) Maximum number of interfaces in array 20360 * port_array - (OUT) Array of mpls ports 20361 * port_count - (OUT) Number of interfaces returned in array 20362 */ 20363 int 20364 bcm_tr_mpls_port_get_all(int unit, bcm_vpn_t vpn, int port_max, 20365 bcm_mpls_port_t *port_array, int *port_count) 20366 { 20367 int vp, rv = BCM_E_NONE; 20368 int vp1=-1, vp2=-1, vp3_read = -1; 20369 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 20370 SHR_BITDCL *share_vp_bitmap = NULL; 20371 #endif 20372 20373 if (!_BCM_MPLS_VPN_IS_VPLS(vpn) && 20374 !_BCM_MPLS_VPN_IS_VPWS(vpn)) { 20375 return BCM_E_PARAM; 20376 } 20377 20378 *port_count = 0; 20379 20380 if (_BCM_MPLS_VPN_IS_VPWS(vpn)) { 20381 bcm_vpn_t vpn_id; 20382 20383 _BCM_MPLS_VPN_GET(vpn_id, _BCM_MPLS_VPN_TYPE_VPWS, vpn); 20384 20385 (void) _bcm_tr_mpls_vpws_vp_map_get (unit, vpn_id, &vp1, &vp2, &vp3_read); 20386 20387 vp = vp1; 20388 if (_bcm_vp_used_get(unit, vp, _bcmVpTypeMpls)) { 20389 if (*port_count < port_max) { 20390 rv = _bcm_tr_mpls_port_get(unit, vpn, vp, 20391 &port_array[*port_count]); 20392 if (rv < 0) { 20393 goto done; 20394 } 20395 (*port_count)++; 20396 } 20397 } 20398 20399 vp = vp2; 20400 if (_bcm_vp_used_get(unit, vp, _bcmVpTypeMpls)) { 20401 if (*port_count < port_max) { 20402 rv = _bcm_tr_mpls_port_get(unit, vpn, vp, 20403 &port_array[*port_count]); 20404 if (rv < 0) { 20405 goto done; 20406 } 20407 (*port_count)++; 20408 } 20409 } 20410 20411 vp = vp3_read; 20412 if (_bcm_vp_used_get(unit, vp, _bcmVpTypeMpls)) { 20413 if (*port_count < port_max) { 20414 rv = _bcm_tr_mpls_port_get(unit, vpn, vp, 20415 &port_array[*port_count]); 20416 if (rv < 0) { 20417 goto done; 20418 } 20419 (*port_count)++; 20420 } 20421 } 20422 } else if (_BCM_MPLS_VPN_IS_VPLS(vpn)) { 20423 uint32 vfi, entry_type; 20424 int num_vp; 20425 source_vp_entry_t svp; 20426 int vpls_vpn_min = 0; 20427 int vpls_vpn_max = 0; 20428 20429 _BCM_MPLS_VPN_SET(vpls_vpn_min, _BCM_MPLS_VPN_TYPE_VPLS, 0); 20430 vpls_vpn_max = soc_mem_index_count(unit, VFIm) + vpls_vpn_min - 1; 20431 if (vpn < vpls_vpn_min || vpn > vpls_vpn_max) { 20432 return BCM_E_PARAM; 20433 } 20434 20435 _BCM_MPLS_VPN_GET(vfi, _BCM_MPLS_VPN_TYPE_VPLS, vpn); 20436 20437 if (!_bcm_vfi_used_get(unit, vfi, _bcmVfiTypeMpls)) { 20438 rv = BCM_E_NOT_FOUND; 20439 goto done; 20440 } 20441 num_vp = soc_mem_index_count(unit, SOURCE_VPm); 20442 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 20443 /*get sharing VP bitmap*/ 20444 share_vp_bitmap = sal_alloc(SHR_BITALLOCSIZE(num_vp), "sharr_vp_bitmap"); 20445 if (share_vp_bitmap == NULL) { 20446 return BCM_E_MEMORY; 20447 } 20448 sal_memset(share_vp_bitmap, 0, SHR_BITALLOCSIZE(num_vp)); 20449 20450 if (soc_feature(unit, soc_feature_vp_sharing)) { 20451 rv = bcm_tr_mpls_share_vp_bitmap_get(unit, vpn, share_vp_bitmap); 20452 if (rv < 0) { 20453 goto cleanup; 20454 } 20455 } 20456 #endif 20457 for (vp = 0; vp < num_vp; vp++) { 20458 if (*port_count == port_max) { 20459 break; 20460 } 20461 20462 if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeMpls)) { 20463 continue; 20464 } 20465 20466 rv = READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp, &svp); 20467 if (rv < 0) { 20468 goto cleanup; 20469 } 20470 entry_type = soc_SOURCE_VPm_field32_get(unit, &svp, ENTRY_TYPEf); 20471 20472 if ((vfi == soc_SOURCE_VPm_field32_get(unit, &svp, VFIf) && entry_type == 0x1) 20473 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 20474 || SHR_BITGET(share_vp_bitmap, vp) 20475 #endif 20476 ) { 20477 rv = _bcm_tr_mpls_port_get(unit, vpn, vp, 20478 &port_array[*port_count]); 20479 if (rv < 0) { 20480 goto cleanup; 20481 } 20482 (*port_count)++; 20483 } 20484 } 20485 cleanup:; 20486 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 20487 sal_free(share_vp_bitmap); 20488 #endif 20489 } 20490 done: 20491 return rv; 20492 } 20493 20494 /* 20495 * Function: 20496 * _bcm_tr_mpls_port_resolve 20497 * Purpose: 20498 * Get the modid, port, trunk values for a MPLS port 20499 * Returns: 20500 * BCM_E_XXX 20501 */ 20502 int 20503 _bcm_tr_mpls_port_resolve(int unit, bcm_gport_t mpls_port_id, 20504 bcm_module_t *modid, bcm_port_t *port, 20505 bcm_trunk_t *trunk_id, int *id) 20506 20507 { 20508 int rv = BCM_E_NONE, nh_index, vp; 20509 ing_l3_next_hop_entry_t ing_nh; 20510 ing_dvp_table_entry_t dvp; 20511 uint32 dest_type, dest_val; 20512 20513 if(!SOC_WARM_BOOT(unit)) { 20514 /* Warmboot re-init is in progress. So skip init check */ 20515 rv = _bcm_tr_mpls_check_init (unit); 20516 if (rv < 0) { 20517 return rv; 20518 } 20519 } 20520 20521 if (!BCM_GPORT_IS_MPLS_PORT(mpls_port_id)) { 20522 return (BCM_E_BADID); 20523 } 20524 20525 vp = BCM_GPORT_MPLS_PORT_ID_GET(mpls_port_id); 20526 if (vp == -1) { 20527 return BCM_E_PARAM; 20528 } 20529 20530 if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeMpls)) { 20531 return BCM_E_NOT_FOUND; 20532 } 20533 BCM_IF_ERROR_RETURN (READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp, &dvp)); 20534 nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, 20535 NEXT_HOP_INDEXf); 20536 BCM_IF_ERROR_RETURN (soc_mem_read(unit, ING_L3_NEXT_HOPm, MEM_BLOCK_ANY, 20537 nh_index, &ing_nh)); 20538 20539 if (soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, ENTRY_TYPEf) != 0x2) { 20540 /* Entry type is not L2 DVP */ 20541 return BCM_E_NOT_FOUND; 20542 } 20543 20544 if (soc_feature(unit, soc_feature_generic_dest)) { 20545 dest_val = soc_mem_field32_dest_get(unit, ING_L3_NEXT_HOPm, 20546 &ing_nh, DESTINATIONf, &dest_type); 20547 if (dest_type == SOC_MEM_FIF_DEST_LAG) { 20548 /* Trunk group */ 20549 *trunk_id = dest_val & SOC_MEM_FIF_DGPP_TGID_MASK; 20550 20551 } else { 20552 *port = dest_val & SOC_MEM_FIF_DGPP_PORT_MASK; 20553 *modid = (dest_val & SOC_MEM_FIF_DGPP_MOD_ID_MASK) >> 20554 SOC_MEM_FIF_DGPP_MOD_ID_SHIFT_BITS; 20555 } 20556 } else { 20557 if (soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, Tf)) { 20558 *trunk_id = soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, TGIDf); 20559 } else { 20560 /* Only add this to replication set if destination is local */ 20561 *modid = soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, MODULE_IDf); 20562 *port = soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, PORT_NUMf); 20563 } 20564 } 20565 *id = vp; 20566 return rv; 20567 } 20568 20569 void 20570 bcm_tr_mpls_port_match_count_adjust(int unit, int vp, int step) 20571 { 20572 _bcm_tr_mpls_bookkeeping_t *mpls_info = MPLS_INFO(unit); 20573 20574 mpls_info->match_key[vp].match_count += step; 20575 } 20576 20577 static soc_field_t _tnl_label_f[] = 20578 { MPLS_LABEL_0f, MPLS_LABEL_1f, MPLS_LABEL_2f, MPLS_LABEL_3f, 20579 MPLS_LABEL_4f, MPLS_LABEL_5f, MPLS_LABEL_6f, MPLS_LABEL_7f }; 20580 static soc_field_t _tnl_exp_select_f[] = 20581 { MPLS_EXP_SELECT_0f, MPLS_EXP_SELECT_1f, 20582 MPLS_EXP_SELECT_2f, MPLS_EXP_SELECT_3f, 20583 MPLS_EXP_SELECT_4f, MPLS_EXP_SELECT_5f, 20584 MPLS_EXP_SELECT_6f, MPLS_EXP_SELECT_7f }; 20585 static soc_field_t _tnl_exp_ptr_f[] = 20586 { MPLS_EXP_MAPPING_PTR_0f, MPLS_EXP_MAPPING_PTR_1f, 20587 MPLS_EXP_MAPPING_PTR_2f, MPLS_EXP_MAPPING_PTR_3f, 20588 MPLS_EXP_MAPPING_PTR_4f, MPLS_EXP_MAPPING_PTR_5f, 20589 MPLS_EXP_MAPPING_PTR_6f, MPLS_EXP_MAPPING_PTR_7f }; 20590 static soc_field_t _tnl_exp_f[] = 20591 { MPLS_EXP_0f, MPLS_EXP_1f, MPLS_EXP_2f, MPLS_EXP_3f, 20592 MPLS_EXP_4f, MPLS_EXP_5f, MPLS_EXP_6f, MPLS_EXP_7f}; 20593 static soc_field_t _tnl_ttl_f[] = 20594 { MPLS_TTL_0f, MPLS_TTL_1f, MPLS_TTL_2f, MPLS_TTL_3f, 20595 MPLS_TTL_4f, MPLS_TTL_5f, MPLS_TTL_6f, MPLS_TTL_7f}; 20596 static soc_field_t _tnl_pri_f[] = 20597 { NEW_PRI_0f, NEW_PRI_1f, NEW_PRI_2f, NEW_PRI_3f, 20598 NEW_PRI_4f, NEW_PRI_5f, NEW_PRI_6f, NEW_PRI_7f}; 20599 static soc_field_t _tnl_cfi_f[] = 20600 { NEW_CFI_0f, NEW_CFI_1f, NEW_CFI_2f, NEW_CFI_3f, 20601 NEW_CFI_4f, NEW_CFI_5f, NEW_CFI_6f, NEW_CFI_7f}; 20602 20603 /* 20604 * Function: 20605 * bcm_tr_mpls_tunnel_intf_valid 20606 * Purpose: 20607 * Set MPLS Tunnel 20608 * Parameters: 20609 * unit - Device Number 20610 * nh_index - Next Hop Index 20611 * Returns: 20612 * BCM_E_XXX 20613 */ 20614 20615 int 20616 bcm_tr_mpls_tunnel_intf_valid (int unit, int nh_index) 20617 { 20618 egr_ip_tunnel_mpls_entry_t tnl_entry; 20619 egr_l3_intf_entry_t if_entry; 20620 egr_l3_next_hop_entry_t egr_nh; 20621 #ifdef BCM_TOMAHAWK3_SUPPORT 20622 egr_l3_next_hop_2_entry_t egr_nh_2; 20623 #endif 20624 bcm_if_t l3_intf = 0; 20625 int tnl_index = 0, mpls_index = 0; 20626 #ifdef BCM_TRIDENT3_SUPPORT 20627 egr_ip_tunnel_mpls_double_wide_entry_t tnl_entry_double; 20628 #endif 20629 20630 BCM_IF_ERROR_RETURN (soc_mem_read(unit, EGR_L3_NEXT_HOPm, MEM_BLOCK_ANY, 20631 nh_index, &egr_nh)); 20632 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 20633 l3_intf = soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, 20634 L3__INTF_NUMf); 20635 } else 20636 #ifdef BCM_TOMAHAWK3_SUPPORT 20637 if (soc_feature(unit, soc_feature_th3_style_simple_mpls)) { 20638 BCM_IF_ERROR_RETURN (soc_mem_read(unit, EGR_L3_NEXT_HOP_2m, MEM_BLOCK_ANY, 20639 nh_index, &egr_nh_2)); 20640 l3_intf = soc_mem_field32_get(unit, EGR_L3_NEXT_HOP_2m, &egr_nh_2, 20641 INTF_NUMf); 20642 } else 20643 #endif 20644 { 20645 l3_intf = soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, 20646 INTF_NUMf); 20647 } 20648 20649 if (!BCM_L3_INTF_USED_GET(unit, l3_intf)) { 20650 return BCM_E_NOT_FOUND; 20651 } 20652 20653 BCM_IF_ERROR_RETURN ( READ_EGR_L3_INTFm(unit, 20654 MEM_BLOCK_ANY, l3_intf, &if_entry)); 20655 mpls_index = soc_EGR_L3_INTFm_field32_get(unit, &if_entry, 20656 MPLS_TUNNEL_INDEXf); 20657 tnl_index = mpls_index / _BCM_MPLS_NUM_MPLS_ENTRIES_PER_INDEX(unit); 20658 20659 if ((mpls_index != 0) && (_BCM_MPLS_TNL_USED_GET(unit, mpls_index))) { 20660 #if defined(BCM_TRIDENT3_SUPPORT) 20661 if (SOC_MEM_IS_VALID(unit, EGR_IP_TUNNEL_MPLS_DOUBLE_WIDEm)) { 20662 BCM_IF_ERROR_RETURN( 20663 READ_EGR_IP_TUNNEL_MPLS_DOUBLE_WIDEm(unit, 20664 MEM_BLOCK_ANY, 20665 tnl_index, &tnl_entry_double)); 20666 if (soc_mem_field32_get(unit, 20667 EGR_IP_TUNNEL_MPLS_DOUBLE_WIDEm, 20668 &tnl_entry_double, 20669 DATA_TYPEf) == 0x14) { 20670 return BCM_E_NONE; 20671 } 20672 } else 20673 #endif 20674 { 20675 BCM_IF_ERROR_RETURN (READ_EGR_IP_TUNNEL_MPLSm(unit, MEM_BLOCK_ANY, 20676 tnl_index, &tnl_entry)); 20677 if (soc_mem_field32_get(unit, EGR_IP_TUNNEL_MPLSm, &tnl_entry, 20678 ENTRY_TYPEf) == 3) { 20679 return BCM_E_NONE; 20680 } 20681 } 20682 } 20683 return BCM_E_NOT_FOUND; 20684 } 20685 20686 /* 20687 * Function: 20688 * _bcm_tr_mpls_egr_tunnel_ref_count_adjust 20689 * Purpose: 20690 * Increment / Decrement Reference Count for Egress Tunnel 20691 * Parameters: 20692 * unit Unit number 20693 * index (IN) Entry Index 20694 * step (IN) usage reference 20695 */ 20696 20697 STATIC void 20698 _bcm_tr_mpls_egr_tunnel_ref_count_adjust (int unit, int index, int step) 20699 { 20700 _bcm_tr_mpls_bookkeeping_t *mpls_info = MPLS_INFO(unit); 20701 20702 if (( mpls_info->egr_tunnel_ref_count[index] == 0 ) && (step < 0)) { 20703 mpls_info->egr_tunnel_ref_count[index] = 0; 20704 } else { 20705 mpls_info->egr_tunnel_ref_count[index] += step; 20706 } 20707 20708 } 20709 20710 /* 20711 * Function: 20712 * _bcm_tr_mpls_egr_tunnel_ref_count_reset 20713 * Purpose: 20714 * reset the reference Count 20715 * Parameters: 20716 * unit Unit number 20717 * index (IN) Entry Index 20718 */ 20719 20720 STATIC void 20721 _bcm_tr_mpls_egr_tunnel_ref_count_reset (int unit, int index) 20722 { 20723 _bcm_tr_mpls_bookkeeping_t *mpls_info = MPLS_INFO(unit); 20724 20725 mpls_info->egr_tunnel_ref_count[index] = 0; 20726 } 20727 20728 /* 20729 * Function: 20730 * _bcm_tr_mpls_egr_tunnel_ref_count_get 20731 * Purpose: 20732 * get the current reference Count 20733 * Parameters: 20734 * unit Unit number 20735 * index (IN) Entry Index 20736 */ 20737 20738 STATIC void 20739 _bcm_tr_mpls_egr_tunnel_ref_count_get (int unit, int index, int *cnt_value) 20740 { 20741 _bcm_tr_mpls_bookkeeping_t *mpls_info = MPLS_INFO(unit); 20742 20743 *cnt_value = mpls_info->egr_tunnel_ref_count[index]; 20744 } 20745 20746 /* 20747 * Function: 20748 * _bcm_tr_mpls_get_vc_and_swap_table_index 20749 * Purpose: 20750 * Obtain Index into EGR_IP_TUNNEL_MPLS 20751 * Parameters: 20752 * IN : Unit 20753 * IN : push_action 20754 * IN : label_array 20755 * OUT : match_mpls_tunnel_index 20756 * Returns: 20757 * BCM_E_XXX 20758 */ 20759 20760 STATIC int 20761 _bcm_tr_mpls_egr_tunnel_lookup (int unit, int push_action, 20762 bcm_mpls_egress_label_t *label_array, 20763 int *match_mpls_tunnel_index) 20764 { 20765 uint32 label_value[8]; 20766 uint32 entry_ttl, entry_exp, entry_push_action; 20767 int num_ip_tnl; 20768 int i = 0, tnl_index = -1, mpls_index = -1; 20769 egr_ip_tunnel_mpls_entry_t tnl_entry; 20770 20771 num_ip_tnl = soc_mem_index_count(unit, EGR_IP_TUNNEL_MPLSm); 20772 20773 /* parameter checking */ 20774 if (push_action != 0 && label_array == NULL) { 20775 return BCM_E_PARAM; 20776 } 20777 20778 for (tnl_index = 0; tnl_index < num_ip_tnl; tnl_index++) { 20779 BCM_IF_ERROR_RETURN( 20780 READ_EGR_IP_TUNNEL_MPLSm(unit, MEM_BLOCK_ANY, 20781 tnl_index, &tnl_entry)); 20782 if (!_BCM_MPLS_IP_TNL_USED_GET(unit, tnl_index)) { 20783 continue; 20784 } 20785 if (soc_mem_field32_get(unit, EGR_IP_TUNNEL_MPLSm, &tnl_entry, 20786 ENTRY_TYPEf) != 3) { 20787 return BCM_E_INTERNAL; 20788 } 20789 mpls_index = tnl_index * _BCM_MPLS_NUM_MPLS_ENTRIES_PER_INDEX(unit); 20790 for (i = 0; i < _BCM_MPLS_NUM_MPLS_ENTRIES_PER_INDEX(unit); i++) { 20791 if (!(_BCM_MPLS_TNL_USED_GET(unit, mpls_index))) { 20792 mpls_index++; 20793 continue; 20794 } 20795 label_value[i] = soc_mem_field32_get(unit, EGR_IP_TUNNEL_MPLSm, 20796 &tnl_entry, _tnl_label_f[i]); 20797 entry_ttl = soc_mem_field32_get(unit, EGR_IP_TUNNEL_MPLSm, 20798 &tnl_entry, _tnl_ttl_f[i]); 20799 entry_exp = soc_mem_field32_get(unit, EGR_IP_TUNNEL_MPLSm, 20800 &tnl_entry, _tnl_exp_f[i]); 20801 entry_push_action = soc_mem_field32_get(unit, EGR_IP_TUNNEL_MPLSm, 20802 &tnl_entry, _tnl_push_action_f[i]); 20803 20804 if ((push_action == 0x2) && 20805 (i < (_BCM_MPLS_NUM_MPLS_ENTRIES_PER_INDEX(unit) - 1)) && 20806 (_BCM_MPLS_TNL_USED_GET(unit, mpls_index+1))){ 20807 /* Match 2 consecutive label entries. */ 20808 label_value[i+1] = soc_mem_field32_get(unit, EGR_IP_TUNNEL_MPLSm, 20809 &tnl_entry, _tnl_label_f[i+1]); 20810 if ( (label_array[0].label == label_value[i]) && 20811 (label_array[1].label == label_value[i+1]) && 20812 (push_action == entry_push_action)) { 20813 *match_mpls_tunnel_index = (tnl_index * 20814 _BCM_MPLS_NUM_MPLS_ENTRIES_PER_INDEX(unit)) + i; 20815 return BCM_E_NONE; 20816 } 20817 } else if (push_action == 0x1) { 20818 if ((label_array[0].label == label_value[i]) && 20819 (label_array[0].ttl == entry_ttl) && 20820 (label_array[0].exp == entry_exp) && 20821 (push_action == entry_push_action)) { 20822 *match_mpls_tunnel_index = (tnl_index * 20823 _BCM_MPLS_NUM_MPLS_ENTRIES_PER_INDEX(unit)) + i; 20824 return BCM_E_NONE; 20825 } 20826 } else if (push_action == 0x0) { 20827 /* Case of Dummy entry */ 20828 if ((0 == label_value[i]) && 20829 (0 == entry_ttl) && 20830 (0 == entry_exp) && 20831 (0 == entry_push_action)) { 20832 *match_mpls_tunnel_index = (tnl_index * 20833 _BCM_MPLS_NUM_MPLS_ENTRIES_PER_INDEX(unit)) + i; 20834 return BCM_E_NONE; 20835 } 20836 } 20837 mpls_index++; 20838 } 20839 } 20840 return BCM_E_NONE; 20841 } 20842 20843 /* 20844 * Function: 20845 * _tr_mpls_tunnel_entry_copy 20846 * Purpose: 20847 * Copy a source EGR_IP_TUNNEL_MPLS table entry to the 20848 destination. 20849 * Parameters: 20850 * IN : Unit 20851 * IN : dst_mpls_inx - destination tunnel mpls index 20852 * OUT : dst_entry - destination tunnel entry 20853 * IN : src_mpls_inx - source tunnel mpls index 20854 * IN : src_entry - source tunnel entry 20855 * Returns: 20856 * BCM_E_XXX 20857 */ 20858 20859 STATIC int 20860 _tr_mpls_tunnel_entry_copy (int unit, int dst_mpls_inx, 20861 egr_ip_tunnel_mpls_entry_t *dst_entry, 20862 int src_mpls_inx, 20863 egr_ip_tunnel_mpls_entry_t *src_entry) 20864 { 20865 int dst_offset; 20866 int src_offset; 20867 int src_value; 20868 20869 dst_offset = dst_mpls_inx & 20870 _BCM_MPLS_EGR_L3_INTF_MPLS_INDEX_OFFSET_MASK(unit); 20871 src_offset = src_mpls_inx & 20872 _BCM_MPLS_EGR_L3_INTF_MPLS_INDEX_OFFSET_MASK(unit); 20873 20874 src_value = soc_mem_field32_get(unit, EGR_IP_TUNNEL_MPLSm, src_entry, 20875 _tnl_push_action_f[src_offset]); 20876 soc_mem_field32_set(unit, EGR_IP_TUNNEL_MPLSm, dst_entry, 20877 _tnl_push_action_f[dst_offset], src_value); 20878 src_value = soc_mem_field32_get(unit, EGR_IP_TUNNEL_MPLSm, src_entry, 20879 _tnl_label_f[src_offset]); 20880 soc_mem_field32_set(unit, EGR_IP_TUNNEL_MPLSm, dst_entry, 20881 _tnl_label_f[dst_offset], src_value); 20882 src_value = soc_mem_field32_get(unit, EGR_IP_TUNNEL_MPLSm, src_entry, 20883 _tnl_exp_select_f[src_offset]); 20884 soc_mem_field32_set(unit, EGR_IP_TUNNEL_MPLSm, dst_entry, 20885 _tnl_exp_select_f[dst_offset], src_value); 20886 src_value = soc_mem_field32_get(unit, EGR_IP_TUNNEL_MPLSm, src_entry, 20887 _tnl_exp_f[src_offset]); 20888 soc_mem_field32_set(unit, EGR_IP_TUNNEL_MPLSm, dst_entry, 20889 _tnl_exp_f[dst_offset], src_value); 20890 src_value = soc_mem_field32_get(unit, EGR_IP_TUNNEL_MPLSm, src_entry, 20891 _tnl_pri_f[src_offset]); 20892 soc_mem_field32_set(unit, EGR_IP_TUNNEL_MPLSm, dst_entry, 20893 _tnl_pri_f[dst_offset], src_value); 20894 src_value = soc_mem_field32_get(unit, EGR_IP_TUNNEL_MPLSm, src_entry, 20895 _tnl_cfi_f[src_offset]); 20896 soc_mem_field32_set(unit, EGR_IP_TUNNEL_MPLSm, dst_entry, 20897 _tnl_cfi_f[dst_offset], src_value); 20898 src_value = soc_mem_field32_get(unit, EGR_IP_TUNNEL_MPLSm, src_entry, 20899 _tnl_exp_ptr_f[src_offset]); 20900 soc_mem_field32_set(unit, EGR_IP_TUNNEL_MPLSm, dst_entry, 20901 _tnl_exp_ptr_f[dst_offset], src_value); 20902 src_value = soc_mem_field32_get(unit, EGR_IP_TUNNEL_MPLSm, src_entry, 20903 _tnl_ttl_f[src_offset]); 20904 soc_mem_field32_set(unit, EGR_IP_TUNNEL_MPLSm, dst_entry, 20905 _tnl_ttl_f[dst_offset], src_value); 20906 return BCM_E_NONE; 20907 } 20908 20909 /* 20910 * Function: 20911 * _tr_egr_l3_intf_tunnel_index_replace 20912 * Purpose: 20913 * Traverse the EGR_L3_INTF table to replace the old tunnel 20914 * index with the new index. 20915 * Parameters: 20916 * IN : Unit 20917 * IN : old_mpls_inx - old tunnel mpls index 20918 * IN : new_mpls_inx - new tunnel mpls index 20919 * Returns: 20920 * BCM_E_XXX 20921 */ 20922 STATIC int 20923 _tr_egr_l3_intf_tunnel_index_replace (int unit, int old_mpls_inx, 20924 int new_mpls_inx) 20925 { 20926 /* Indexes to iterate over memories, chunks and entries */ 20927 int chnk_idx, ent_idx, chnk_idx_max, mem_idx_max; 20928 int buf_size, chunksize, chnk_end; 20929 uint32 *tbl_chnk; 20930 uint32 *el3inf_entry; 20931 int rv = BCM_E_NONE; 20932 soc_mem_t mem; 20933 int mpls_inx; 20934 20935 mem = EGR_L3_INTFm; 20936 20937 chunksize = 0x400; /* 1k */ 20938 buf_size = sizeof(egr_l3_intf_entry_t) * chunksize; 20939 tbl_chnk = soc_cm_salloc(unit, buf_size, "egr_l3_intf traverse"); 20940 if (NULL == tbl_chnk) { 20941 return BCM_E_MEMORY; 20942 } 20943 20944 mem_idx_max = soc_mem_index_max(unit, mem); 20945 for (chnk_idx = soc_mem_index_min(unit, mem); 20946 chnk_idx <= mem_idx_max; 20947 chnk_idx += chunksize) { 20948 sal_memset((void *)tbl_chnk, 0, buf_size); 20949 20950 chnk_idx_max = 20951 ((chnk_idx + chunksize) <= mem_idx_max) ? 20952 chnk_idx + chunksize - 1: mem_idx_max; 20953 20954 soc_mem_lock(unit, mem); 20955 rv = soc_mem_read_range(unit, mem, MEM_BLOCK_ANY, 20956 chnk_idx, chnk_idx_max, tbl_chnk); 20957 if (SOC_FAILURE(rv)) { 20958 soc_mem_unlock(unit, mem); 20959 break; 20960 } 20961 chnk_end = (chnk_idx_max - chnk_idx); 20962 for (ent_idx = 0 ; ent_idx <= chnk_end; ent_idx ++) { 20963 el3inf_entry = 20964 soc_mem_table_idx_to_pointer(unit, mem, uint32 *, 20965 tbl_chnk, ent_idx); 20966 20967 mpls_inx = soc_mem_field32_get(unit, mem, el3inf_entry, 20968 MPLS_TUNNEL_INDEXf); 20969 20970 if (mpls_inx != old_mpls_inx) { 20971 continue; 20972 } 20973 /* replace with new tunnel index */ 20974 soc_mem_field32_set(unit, mem,el3inf_entry, 20975 MPLS_TUNNEL_INDEXf, new_mpls_inx); 20976 rv = soc_mem_write(unit, mem, MEM_BLOCK_ANY, chnk_idx+ent_idx, 20977 el3inf_entry); 20978 if (BCM_FAILURE(rv)) { 20979 break; 20980 } 20981 } 20982 soc_mem_unlock(unit, mem); 20983 if (BCM_FAILURE(rv)) { 20984 break; 20985 } 20986 } 20987 soc_cm_sfree(unit, tbl_chnk); 20988 return rv; 20989 } 20990 20991 /* 20992 * Function: 20993 * _tr_egr_tunnel_mpls_free_slots_reorder 20994 * Purpose: 20995 * Re-arrange two non-consecutive free slots in EGR_TUNNEL_MPLS table 20996 * to make it consective for the purpose of pushing two labels. 20997 * This involves to move a occupied slot ajacent to the first free slot 20998 * to the second free slot and traverse the EGR_L3_INTF table to 20999 * replace the tunnel index accordingly. 21000 * Parameters: 21001 * IN : Unit 21002 * IN : free_slot1 - first free slot 21003 * IN : free_slot2 - second free slot 21004 * IN : src_tnl_entry - tunnel entry with first free MPLS slot 21005 * Returns: 21006 * BCM_E_XXX 21007 */ 21008 STATIC int 21009 _tr_egr_tunnel_mpls_free_slots_reorder (int unit, int free_slot1, int free_slot2, 21010 egr_ip_tunnel_mpls_entry_t *src_tnl_entry) 21011 { 21012 int src_tnl_mpls_inx; 21013 int dst_tnl_mpls_inx; 21014 int ref_count; 21015 int rv; 21016 egr_ip_tunnel_mpls_entry_t dst_tnl_entry; 21017 21018 if (free_slot1 & 0x1) { /* need to free even entry above */ 21019 src_tnl_mpls_inx = free_slot1 - 1; 21020 } else { /* free odd entry below */ 21021 src_tnl_mpls_inx = free_slot1 + 1; 21022 } 21023 dst_tnl_mpls_inx = free_slot2; 21024 21025 /* read destination tunnel entry */ 21026 rv = READ_EGR_IP_TUNNEL_MPLSm(unit, MEM_BLOCK_ANY, 21027 (dst_tnl_mpls_inx / _BCM_MPLS_NUM_MPLS_ENTRIES_PER_INDEX(unit)), 21028 &dst_tnl_entry); 21029 BCM_IF_ERROR_RETURN(rv); 21030 21031 /* copy the source mpls entry to the destination */ 21032 rv = _tr_mpls_tunnel_entry_copy(unit,dst_tnl_mpls_inx,&dst_tnl_entry, 21033 src_tnl_mpls_inx,src_tnl_entry); 21034 BCM_IF_ERROR_RETURN(rv); 21035 21036 /* write the destination entry to HW */ 21037 rv = WRITE_EGR_IP_TUNNEL_MPLSm(unit, MEM_BLOCK_ANY, 21038 (dst_tnl_mpls_inx / _BCM_MPLS_NUM_MPLS_ENTRIES_PER_INDEX(unit)), 21039 &dst_tnl_entry); 21040 BCM_IF_ERROR_RETURN(rv); 21041 21042 /* now search the egr_l3_intf table to update the new tunnel index */ 21043 rv = _tr_egr_l3_intf_tunnel_index_replace(unit, 21044 src_tnl_mpls_inx,dst_tnl_mpls_inx); 21045 BCM_IF_ERROR_RETURN(rv); 21046 21047 /* get the moved entry's original ref counter number */ 21048 _bcm_tr_mpls_egr_tunnel_ref_count_get (unit, 21049 src_tnl_mpls_inx,&ref_count); 21050 _bcm_tr_mpls_egr_tunnel_ref_count_reset (unit, src_tnl_mpls_inx); 21051 _bcm_tr_mpls_egr_tunnel_ref_count_adjust (unit, 21052 dst_tnl_mpls_inx, ref_count); 21053 _BCM_MPLS_TNL_USED_SET(unit, dst_tnl_mpls_inx); 21054 _BCM_MPLS_TNL_USED_CLR(unit, src_tnl_mpls_inx); 21055 return rv; 21056 } 21057 21058 /* 21059 * Function: 21060 * bcm_mpls_tunnel_initiator_set 21061 * Purpose: 21062 * Set MPLS Tunnel initiator 21063 * Parameters: 21064 * unit - Device Number 21065 * intf - The egress L3 interface 21066 * num_labels - Number of labels in the array 21067 * label_array - Array of MPLS label and header information 21068 * Returns: 21069 * BCM_E_XXX 21070 */ 21071 int 21072 bcm_tr_mpls_tunnel_initiator_set(int unit, bcm_if_t intf, int num_labels, 21073 bcm_mpls_egress_label_t *label_array) 21074 { 21075 egr_ip_tunnel_mpls_entry_t tnl_entry; 21076 egr_l3_intf_entry_t if_entry; 21077 int rv, i, num_mpls_map, num_ip_tnl, push_action=0, offset; 21078 int found = 0, tnl_index = 0, mpls_index = 0; 21079 int hw_map_idx; 21080 bcm_tunnel_initiator_t tnl_init; 21081 uint32 tnl_flags; 21082 int old_push_act_value; 21083 int match_mpls_tunnel_index=-1; 21084 int free_slot1; 21085 int free_slot2; 21086 21087 if ((num_labels < 0) || (num_labels > 2) || 21088 (intf < 0) || (intf >= L3_INFO(unit)->l3_intf_table_size)) { 21089 return BCM_E_PARAM; 21090 } 21091 21092 if (num_labels == 2) { 21093 push_action = 0x2; /* push 2 labels */ 21094 } else if (num_labels == 1) { 21095 push_action = 0x1; /* push 1 label */ 21096 } 21097 21098 /* Param checking */ 21099 num_mpls_map = soc_mem_index_count(unit, EGR_MPLS_EXP_MAPPING_1m) / 64; 21100 for (i = 0; i < num_labels; i++) { 21101 if (label_array[i].qos_map_id == 0) { /* treat it as using default */ 21102 hw_map_idx = 0; 21103 } else { 21104 BCM_IF_ERROR_RETURN(_egr_qos_id2hw_idx(unit, 21105 label_array[i].qos_map_id,&hw_map_idx)); 21106 } 21107 if ((label_array[i].label > 0xfffff) || 21108 (hw_map_idx < 0) || 21109 (hw_map_idx >= num_mpls_map) || 21110 (label_array[i].exp > 7) || (label_array[i].pkt_pri > 7) || 21111 (label_array[i].pkt_cfi > 1)) { 21112 return BCM_E_PARAM; 21113 } 21114 } 21115 21116 if (!BCM_L3_INTF_USED_GET(unit, intf)) { 21117 LOG_INFO(BSL_LS_BCM_L3, 21118 (BSL_META_U(unit, 21119 "L3 interface not created\n"))); 21120 return BCM_E_NOT_FOUND; 21121 } 21122 21123 /* L3 interface info */ 21124 rv = READ_EGR_L3_INTFm(unit, MEM_BLOCK_ANY, intf, &if_entry); 21125 if (rv < 0) { 21126 return rv; 21127 } 21128 21129 /* init the allocated entry */ 21130 sal_memset(&tnl_entry, 0, sizeof(egr_ip_tunnel_mpls_entry_t)); 21131 21132 /* Case of Dummy Tunnel entry sharing by multiple L3_INTF */ 21133 if (num_labels == 0) { 21134 /* Lookup if Tunnel Entry with Tunnel Label exists? */ 21135 rv = _bcm_tr_mpls_egr_tunnel_lookup (unit, push_action, 21136 NULL, &match_mpls_tunnel_index); 21137 if (rv < 0) { 21138 return rv; 21139 } 21140 21141 if (match_mpls_tunnel_index != -1) { 21142 /* L3_Interface to point to mpls_tunnel */ 21143 soc_EGR_L3_INTFm_field32_set(unit, &if_entry, 21144 MPLS_TUNNEL_INDEXf, match_mpls_tunnel_index); 21145 /* Increment Ref count */ 21146 _bcm_tr_mpls_egr_tunnel_ref_count_adjust (unit, 21147 match_mpls_tunnel_index, 1); 21148 rv = WRITE_EGR_L3_INTFm(unit, MEM_BLOCK_ANY, intf, &if_entry); 21149 return rv; 21150 } 21151 } 21152 21153 for (i = 0; i < num_labels; i++) { 21154 /* Check for Port_independent Label mapping */ 21155 rv = bcm_tr_mpls_port_independent_range (unit, label_array[i].label, 21156 BCM_GPORT_INVALID); 21157 /* Either Port-scope-label or Explicit-Null-label */ 21158 if ((rv == BCM_E_CONFIG) || (label_array[i].label == 0)) { 21159 /* Tunnel-label is Port-based */ 21160 /* Lookup if Tunnel Entry with Tunnel Label exists? */ 21161 rv = _bcm_tr_mpls_egr_tunnel_lookup (unit, push_action, 21162 label_array, &match_mpls_tunnel_index); 21163 if (rv < 0) { 21164 return rv; 21165 } 21166 21167 if (match_mpls_tunnel_index != -1) { 21168 /* L3_Interface to point to mpls_tunnel */ 21169 soc_EGR_L3_INTFm_field32_set(unit, &if_entry, 21170 MPLS_TUNNEL_INDEXf, match_mpls_tunnel_index); 21171 /* Increment Ref count */ 21172 _bcm_tr_mpls_egr_tunnel_ref_count_adjust (unit, 21173 match_mpls_tunnel_index, 1); 21174 if (push_action == 2) { 21175 _bcm_tr_mpls_egr_tunnel_ref_count_adjust (unit, 21176 match_mpls_tunnel_index+1, 1); 21177 } 21178 rv = WRITE_EGR_L3_INTFm(unit, MEM_BLOCK_ANY, intf, &if_entry); 21179 return rv; 21180 } 21181 } 21182 } 21183 21184 mpls_index = soc_EGR_L3_INTFm_field32_get(unit, &if_entry, 21185 MPLS_TUNNEL_INDEXf); 21186 tnl_index = mpls_index / _BCM_MPLS_NUM_MPLS_ENTRIES_PER_INDEX(unit); 21187 21188 if ((mpls_index != 0) && (_BCM_MPLS_TNL_USED_GET(unit, mpls_index))) { 21189 /* Obtain referenced Tunnel entry */ 21190 rv = READ_EGR_IP_TUNNEL_MPLSm(unit, MEM_BLOCK_ANY, 21191 tnl_index, &tnl_entry); 21192 if (rv < 0) { 21193 return rv; 21194 } 21195 if (soc_mem_field32_get(unit, EGR_IP_TUNNEL_MPLSm, &tnl_entry, 21196 ENTRY_TYPEf) != 3) { 21197 return BCM_E_INTERNAL; 21198 } 21199 offset = mpls_index & _BCM_MPLS_EGR_L3_INTF_MPLS_INDEX_OFFSET_MASK(unit); 21200 old_push_act_value = soc_mem_field32_get(unit, EGR_IP_TUNNEL_MPLSm, 21201 &tnl_entry, _tnl_push_action_f[offset]); 21202 if (old_push_act_value != push_action) { 21203 /* Changing push action is not permitted, need to clear/set */ 21204 return BCM_E_PARAM; 21205 } 21206 } else { 21207 /* allocate an unused EGR_IP_TUNNEL_MPLS_ENTRY */ 21208 num_ip_tnl = soc_mem_index_count(unit, EGR_IP_TUNNEL_MPLSm); 21209 21210 /* 21211 * First try finding an allocated tunnel entry with 21212 * unused MPLS entries. 21213 */ 21214 free_slot1 = -1; 21215 free_slot2 = -1; 21216 for (tnl_index = 0; tnl_index < num_ip_tnl; tnl_index++) { 21217 if (!_BCM_MPLS_IP_TNL_USED_GET(unit, tnl_index)) { 21218 continue; 21219 } 21220 mpls_index = tnl_index * _BCM_MPLS_NUM_MPLS_ENTRIES_PER_INDEX(unit); 21221 for (i = 0; i < _BCM_MPLS_NUM_MPLS_ENTRIES_PER_INDEX(unit); i++) { 21222 if (!(_BCM_MPLS_TNL_USED_GET(unit, mpls_index))) { 21223 if (free_slot1 == -1) { 21224 free_slot1 = mpls_index; 21225 } else if (free_slot2 == -1) { 21226 free_slot2 = mpls_index; 21227 } 21228 } 21229 if ((push_action == 0x2) && 21230 (i == (_BCM_MPLS_NUM_MPLS_ENTRIES_PER_INDEX(unit) - 1))) { 21231 /* Pushing 2 labels, need 2 consecutive entries. */ 21232 break; 21233 } 21234 if (!(_BCM_MPLS_TNL_USED_GET(unit, mpls_index))) { 21235 if (push_action == 0x2) { 21236 /* Pushing 2 labels, need 2 consecutive entries with even base */ 21237 if (!(_BCM_MPLS_TNL_USED_GET(unit, mpls_index + 1))) { 21238 if(mpls_index % 2 == 0) { 21239 found = 1; 21240 break; 21241 } 21242 } 21243 } else { 21244 found = 1; 21245 break; 21246 } 21247 } 21248 mpls_index++; 21249 } 21250 if (found) { 21251 break; 21252 } 21253 } 21254 if (found) { 21255 /* Mark entry as used */ 21256 _BCM_MPLS_TNL_USED_SET(unit, mpls_index); 21257 _bcm_tr_mpls_egr_tunnel_ref_count_adjust (unit, 21258 mpls_index, 1); 21259 if (push_action == 0x2) { 21260 _BCM_MPLS_TNL_USED_SET(unit, mpls_index+1); 21261 _bcm_tr_mpls_egr_tunnel_ref_count_adjust (unit, 21262 mpls_index+1, 1); 21263 } 21264 21265 /* Read existing entry */ 21266 rv = READ_EGR_IP_TUNNEL_MPLSm(unit, MEM_BLOCK_ANY, 21267 tnl_index, &tnl_entry); 21268 if (rv < 0) { 21269 goto cleanup; 21270 } 21271 } else { 21272 /* 21273 * Alloc an egr_ip_tunnel entry. By calling bcm_xgs3_tnl_init_add 21274 * with _BCM_L3_SHR_WRITE_DISABLE flag, a tunnel index is 21275 * allocated but nothing is written to hardware. The "tnl_init" 21276 * information is not used, set to all zero. 21277 */ 21278 bcm_tunnel_initiator_t_init(&tnl_init); 21279 tnl_flags = _BCM_L3_SHR_MATCH_DISABLE | _BCM_L3_SHR_WRITE_DISABLE | 21280 _BCM_L3_SHR_SKIP_INDEX_ZERO; 21281 rv = bcm_xgs3_tnl_init_add(unit, tnl_flags, &tnl_init, &tnl_index); 21282 if (rv == BCM_E_FULL) { 21283 if (free_slot2 == -1 || push_action != 2) { 21284 return rv; /* table truely full */ 21285 } 21286 /* process the case of table fragmentation fo two labels. 21287 * push_action==2 21288 */ 21289 21290 tnl_index = (free_slot1 / 21291 _BCM_MPLS_NUM_MPLS_ENTRIES_PER_INDEX(unit)); 21292 rv = READ_EGR_IP_TUNNEL_MPLSm(unit, MEM_BLOCK_ANY, 21293 tnl_index, &tnl_entry); 21294 BCM_IF_ERROR_RETURN(rv); 21295 rv = _tr_egr_tunnel_mpls_free_slots_reorder(unit, free_slot1, 21296 free_slot2, &tnl_entry); 21297 BCM_IF_ERROR_RETURN(rv); 21298 21299 /*sync up after update if both free slots in same entry*/ 21300 if ((free_slot1 / _BCM_MPLS_NUM_MPLS_ENTRIES_PER_INDEX(unit)) == 21301 (free_slot2 / _BCM_MPLS_NUM_MPLS_ENTRIES_PER_INDEX(unit))) { 21302 rv = READ_EGR_IP_TUNNEL_MPLSm(unit, MEM_BLOCK_ANY, 21303 tnl_index, &tnl_entry); 21304 BCM_IF_ERROR_RETURN(rv); 21305 } 21306 21307 mpls_index = free_slot1 & (~1); 21308 /* Mark entries as used */ 21309 _BCM_MPLS_TNL_USED_SET(unit, mpls_index); 21310 _bcm_tr_mpls_egr_tunnel_ref_count_adjust (unit, 21311 mpls_index, 1); 21312 _BCM_MPLS_TNL_USED_SET(unit, mpls_index + 1); 21313 _bcm_tr_mpls_egr_tunnel_ref_count_adjust (unit, 21314 mpls_index+1, 1); 21315 found = 1; /* for cleanup */ 21316 } else if (rv < 0) { 21317 return rv; 21318 } else { 21319 mpls_index = tnl_index * _BCM_MPLS_NUM_MPLS_ENTRIES_PER_INDEX(unit); 21320 21321 /* Mark entries as used */ 21322 _BCM_MPLS_IP_TNL_USED_SET(unit, tnl_index); 21323 _BCM_MPLS_TNL_USED_SET(unit, mpls_index); 21324 _bcm_tr_mpls_egr_tunnel_ref_count_adjust (unit, 21325 mpls_index, 1); 21326 if (push_action == 0x2) { 21327 _BCM_MPLS_TNL_USED_SET(unit, mpls_index + 1); 21328 _bcm_tr_mpls_egr_tunnel_ref_count_adjust (unit, 21329 mpls_index+1, 1); 21330 } 21331 /* Clear and set ENTRY_TYPE */ 21332 sal_memset(&tnl_entry, 0, sizeof(egr_ip_tunnel_mpls_entry_t)); 21333 soc_mem_field32_set(unit, EGR_IP_TUNNEL_MPLSm, &tnl_entry, 21334 ENTRY_TYPEf, 0x3); 21335 } 21336 } 21337 } 21338 21339 offset = mpls_index & _BCM_MPLS_EGR_L3_INTF_MPLS_INDEX_OFFSET_MASK(unit); 21340 for (i = 0; i < num_labels; i++) { 21341 if (label_array[i].qos_map_id == 0) { /* treat it as using default */ 21342 hw_map_idx = 0; 21343 } else { 21344 rv = _egr_qos_id2hw_idx(unit, 21345 label_array[i].qos_map_id,&hw_map_idx); 21346 if (rv < 0) { 21347 goto cleanup; 21348 } 21349 } 21350 21351 soc_mem_field32_set(unit, EGR_IP_TUNNEL_MPLSm, &tnl_entry, 21352 _tnl_push_action_f[offset], push_action); 21353 if (push_action > 0) { 21354 soc_mem_field32_set(unit, EGR_IP_TUNNEL_MPLSm, &tnl_entry, 21355 _tnl_label_f[offset], label_array[i].label); 21356 } 21357 /*For Two Label push set Second label push action as 1*/ 21358 if ((push_action == 0x2) && (i == 1)) { 21359 soc_mem_field32_set(unit, EGR_IP_TUNNEL_MPLSm, &tnl_entry, 21360 _tnl_push_action_f[offset], 1); 21361 21362 } 21363 21364 if ((label_array[i].flags & BCM_MPLS_EGRESS_LABEL_EXP_SET) || 21365 (label_array[i].flags & BCM_MPLS_EGRESS_LABEL_PRI_SET)) { 21366 21367 /* Use the specified EXP, PRI and CFI */ 21368 if ((label_array[i].flags & BCM_MPLS_EGRESS_LABEL_EXP_REMARK) || 21369 (label_array[i].flags & BCM_MPLS_EGRESS_LABEL_EXP_COPY) || 21370 (label_array[i].flags & BCM_MPLS_EGRESS_LABEL_PRI_REMARK)) { 21371 rv = BCM_E_PARAM; 21372 goto cleanup; 21373 } 21374 soc_mem_field32_set(unit, EGR_IP_TUNNEL_MPLSm, &tnl_entry, 21375 _tnl_exp_select_f[offset], 0x0); /* USE_FIXED */ 21376 soc_mem_field32_set(unit, EGR_IP_TUNNEL_MPLSm, &tnl_entry, 21377 _tnl_exp_f[offset], label_array[i].exp); 21378 soc_mem_field32_set(unit, EGR_IP_TUNNEL_MPLSm, &tnl_entry, 21379 _tnl_pri_f[offset], label_array[i].pkt_pri); 21380 soc_mem_field32_set(unit, EGR_IP_TUNNEL_MPLSm, &tnl_entry, 21381 _tnl_cfi_f[offset], label_array[i].pkt_cfi); 21382 } else if (label_array[i].flags & BCM_MPLS_EGRESS_LABEL_EXP_REMARK) { 21383 if (label_array[i].flags & BCM_MPLS_EGRESS_LABEL_PRI_SET) { 21384 rv = BCM_E_PARAM; 21385 goto cleanup; 21386 } 21387 /* Use EXP-map for EXP, PRI and CFI */ 21388 soc_mem_field32_set(unit, EGR_IP_TUNNEL_MPLSm, &tnl_entry, 21389 _tnl_exp_select_f[offset], 0x1); /* USE_MAPPING */ 21390 soc_mem_field32_set(unit, EGR_IP_TUNNEL_MPLSm, &tnl_entry, 21391 _tnl_exp_ptr_f[offset], hw_map_idx); 21392 } else { /* BCM_MPLS_EGRESS_LABEL_EXP_COPY */ 21393 /* Use EXP from inner label. If there is no inner label, 21394 * use the specified EXP value. Use EXP-map for PRI/CFI. 21395 */ 21396 soc_mem_field32_set(unit, EGR_IP_TUNNEL_MPLSm, &tnl_entry, 21397 _tnl_exp_select_f[offset], 0x2); /* USE_INNER */ 21398 21399 soc_mem_field32_set(unit, EGR_IP_TUNNEL_MPLSm, &tnl_entry, 21400 _tnl_exp_f[offset], label_array[i].exp); 21401 21402 /* Use EXP-map for PRI/CFI */ 21403 soc_mem_field32_set(unit, EGR_IP_TUNNEL_MPLSm, &tnl_entry, 21404 _tnl_exp_ptr_f[offset], hw_map_idx); 21405 } 21406 21407 if (label_array[i].flags & BCM_MPLS_EGRESS_LABEL_TTL_SET) { 21408 /* Use specified TTL */ 21409 soc_mem_field32_set(unit, EGR_IP_TUNNEL_MPLSm, &tnl_entry, 21410 _tnl_ttl_f[offset], label_array[i].ttl); 21411 } else { 21412 soc_mem_field32_set(unit, EGR_IP_TUNNEL_MPLSm, &tnl_entry, 21413 _tnl_ttl_f[offset], 0); 21414 } 21415 offset++; 21416 } 21417 21418 /* Commit the values to HW */ 21419 rv = WRITE_EGR_IP_TUNNEL_MPLSm(unit, MEM_BLOCK_ANY, 21420 tnl_index, &tnl_entry); 21421 if (rv < 0) { 21422 goto cleanup; 21423 } 21424 21425 /* Update the EGR_L3_INTF to point to the MPLS tunnel entry */ 21426 rv = soc_mem_field32_modify(unit, EGR_L3_INTFm, intf, 21427 MPLS_TUNNEL_INDEXf, mpls_index); 21428 21429 #ifdef BCM_WARM_BOOT_SUPPORT 21430 SOC_CONTROL_LOCK(unit); 21431 SOC_CONTROL(unit)->scache_dirty = 1; 21432 SOC_CONTROL_UNLOCK(unit); 21433 #endif 21434 21435 return rv; 21436 21437 cleanup: 21438 if (!found) { 21439 /* Free the tunnel entry */ 21440 tnl_flags = _BCM_L3_SHR_WRITE_DISABLE; 21441 (void) bcm_xgs3_tnl_init_del(unit, tnl_flags, tnl_index); 21442 21443 /* Clear "in-use" for the IP tunnel entry */ 21444 _BCM_MPLS_IP_TNL_USED_CLR(unit, tnl_index); 21445 } 21446 /* Clear "in-use" for the MPLS tunnel entry(s) */ 21447 _BCM_MPLS_TNL_USED_CLR(unit, mpls_index); 21448 if (push_action == 0x2) { 21449 _BCM_MPLS_TNL_USED_CLR(unit, mpls_index + 1); 21450 } 21451 return rv; 21452 } 21453 21454 /* 21455 * Function: 21456 * _bcm_tr_mpls_tunnel_initiator_clear 21457 * Purpose: 21458 * Clear MPLS Tunnel initiator 21459 * Parameters: 21460 * unit - Device Number 21461 * intf - The egress L3 interface 21462 * num_labels - Number of labels in the array 21463 * label_array - Array of MPLS label and header information 21464 * Returns: 21465 * BCM_E_XXX 21466 */ 21467 21468 STATIC int 21469 _bcm_tr_mpls_tunnel_initiator_clear(int unit, int intf_id) 21470 { 21471 egr_ip_tunnel_mpls_entry_t tnl_entry; 21472 egr_l3_intf_entry_t if_entry; 21473 int rv, offset, push_action, mpls_entry_used; 21474 int tnl_index = 0, mpls_index = 0; 21475 uint32 tnl_flags; 21476 _bcm_tr_mpls_bookkeeping_t *mpls_info = MPLS_INFO(unit); 21477 21478 21479 /* L3 interface info */ 21480 rv = READ_EGR_L3_INTFm(unit, MEM_BLOCK_ANY, intf_id, &if_entry); 21481 if (rv < 0) { 21482 return rv; 21483 } 21484 mpls_index = soc_EGR_L3_INTFm_field32_get(unit, &if_entry, 21485 MPLS_TUNNEL_INDEXf); 21486 tnl_index = mpls_index / _BCM_MPLS_NUM_MPLS_ENTRIES_PER_INDEX(unit); 21487 21488 if (!_BCM_MPLS_TNL_USED_GET(unit, mpls_index)) { 21489 return BCM_E_NOT_FOUND; 21490 } 21491 rv = READ_EGR_IP_TUNNEL_MPLSm(unit, MEM_BLOCK_ANY, 21492 tnl_index, &tnl_entry); 21493 if (rv < 0) { 21494 return rv; 21495 } 21496 if (soc_mem_field32_get(unit, EGR_IP_TUNNEL_MPLSm, &tnl_entry, 21497 ENTRY_TYPEf) != 3) { 21498 return BCM_E_NOT_FOUND; 21499 } 21500 offset = mpls_index & _BCM_MPLS_EGR_L3_INTF_MPLS_INDEX_OFFSET_MASK(unit); 21501 push_action = soc_mem_field32_get(unit, EGR_IP_TUNNEL_MPLSm, &tnl_entry, 21502 _tnl_push_action_f[offset]); 21503 21504 /* Decrement Reference Count */ 21505 _bcm_tr_mpls_egr_tunnel_ref_count_adjust (unit, 21506 mpls_index, -1); 21507 if (push_action == 0x2) { 21508 _bcm_tr_mpls_egr_tunnel_ref_count_adjust (unit, 21509 mpls_index+1, -1); 21510 } 21511 21512 /* Update the EGR_L3_INTF to no longer point to the MPLS tunnel entry */ 21513 soc_mem_field32_set(unit, EGR_L3_INTFm, &if_entry, 21514 MPLS_TUNNEL_INDEXf, 0); 21515 rv = WRITE_EGR_L3_INTFm(unit, MEM_BLOCK_ANY, intf_id, &if_entry); 21516 if (rv < 0) { 21517 return rv; 21518 } 21519 21520 if ( mpls_info->egr_tunnel_ref_count[mpls_index] != 0x0 ) { 21521 return BCM_E_NONE; 21522 } 21523 21524 /* Clear the MPLS tunnel entry(s) */ 21525 soc_mem_field32_set(unit, EGR_IP_TUNNEL_MPLSm, &tnl_entry, 21526 _tnl_label_f[offset], 0); 21527 soc_mem_field32_set(unit, EGR_IP_TUNNEL_MPLSm, &tnl_entry, 21528 _tnl_push_action_f[offset], 0); 21529 soc_mem_field32_set(unit, EGR_IP_TUNNEL_MPLSm, &tnl_entry, 21530 _tnl_exp_select_f[offset], 0); 21531 soc_mem_field32_set(unit, EGR_IP_TUNNEL_MPLSm, &tnl_entry, 21532 _tnl_exp_ptr_f[offset], 0); 21533 soc_mem_field32_set(unit, EGR_IP_TUNNEL_MPLSm, &tnl_entry, 21534 _tnl_exp_f[offset], 0); 21535 soc_mem_field32_set(unit, EGR_IP_TUNNEL_MPLSm, &tnl_entry, 21536 _tnl_ttl_f[offset], 0); 21537 if (push_action == 0x2) { 21538 offset++; 21539 soc_mem_field32_set(unit, EGR_IP_TUNNEL_MPLSm, &tnl_entry, 21540 _tnl_label_f[offset], 0); 21541 soc_mem_field32_set(unit, EGR_IP_TUNNEL_MPLSm, &tnl_entry, 21542 _tnl_push_action_f[offset], 0); 21543 soc_mem_field32_set(unit, EGR_IP_TUNNEL_MPLSm, &tnl_entry, 21544 _tnl_exp_select_f[offset], 0); 21545 soc_mem_field32_set(unit, EGR_IP_TUNNEL_MPLSm, &tnl_entry, 21546 _tnl_exp_ptr_f[offset], 0); 21547 soc_mem_field32_set(unit, EGR_IP_TUNNEL_MPLSm, &tnl_entry, 21548 _tnl_exp_f[offset], 0); 21549 soc_mem_field32_set(unit, EGR_IP_TUNNEL_MPLSm, &tnl_entry, 21550 _tnl_ttl_f[offset], 0); 21551 } 21552 21553 /* Clear "in-use" for the MPLS tunnel entry(s) */ 21554 _BCM_MPLS_TNL_USED_CLR(unit, mpls_index); 21555 if (push_action == 0x2) { 21556 _BCM_MPLS_TNL_USED_CLR(unit, mpls_index + 1); 21557 } 21558 21559 mpls_index = tnl_index * _BCM_MPLS_NUM_MPLS_ENTRIES_PER_INDEX(unit); 21560 21561 /* See if we can free the IP tunnel base entry */ 21562 _BCM_MPLS_TNL_USED_RANGE_GET(unit, mpls_index, 21563 _BCM_MPLS_NUM_MPLS_ENTRIES_PER_INDEX(unit), mpls_entry_used); 21564 21565 if (!mpls_entry_used) { 21566 /* None of the 4 or 8 entries are used, free base entry */ 21567 tnl_flags = _BCM_L3_SHR_WRITE_DISABLE; 21568 (void) bcm_xgs3_tnl_init_del(unit, tnl_flags, tnl_index); 21569 21570 /* Clear "in-use" for the IP tunnel entry */ 21571 _BCM_MPLS_IP_TNL_USED_CLR(unit, tnl_index); 21572 21573 /* Clear HW Entry-Type */ 21574 soc_mem_field32_set(unit, EGR_IP_TUNNEL_MPLSm, &tnl_entry, 21575 ENTRY_TYPEf, 0); 21576 } 21577 21578 rv = WRITE_EGR_IP_TUNNEL_MPLSm(unit, MEM_BLOCK_ANY, 21579 tnl_index, &tnl_entry); 21580 if (rv < 0) { 21581 return rv; 21582 } 21583 21584 #ifdef BCM_WARM_BOOT_SUPPORT 21585 SOC_CONTROL_LOCK(unit); 21586 SOC_CONTROL(unit)->scache_dirty = 1; 21587 SOC_CONTROL_UNLOCK(unit); 21588 #endif 21589 21590 return BCM_E_NONE; 21591 } 21592 21593 /* 21594 * Function: 21595 * bcm_mpls_tunnel_initiator_clear 21596 * Purpose: 21597 * Clear MPLS Tunnel Initiator 21598 * Parameters: 21599 * unit - Device Number 21600 * intf - The egress L3 interface 21601 * Returns: 21602 * BCM_E_XXX 21603 */ 21604 int 21605 bcm_tr_mpls_tunnel_initiator_clear(int unit, bcm_if_t intf) 21606 { 21607 if ((intf < 0) || (intf >= L3_INFO(unit)->l3_intf_table_size)) { 21608 return BCM_E_PARAM; 21609 } 21610 21611 if (!BCM_L3_INTF_USED_GET(unit, intf)) { 21612 LOG_INFO(BSL_LS_BCM_L3, 21613 (BSL_META_U(unit, 21614 "L3 interface not created\n"))); 21615 return BCM_E_NOT_FOUND; 21616 } 21617 return _bcm_tr_mpls_tunnel_initiator_clear(unit, intf); 21618 } 21619 21620 /* 21621 * Function: 21622 * bcm_mpls_tunnel_initiator_get 21623 * Purpose: 21624 * Get MPLS Tunnel Initiator info 21625 * Parameters: 21626 * unit - (IN) Device Number 21627 * intf - (IN) The egress L3 interface 21628 * label_max - (IN) Number of entries in label_array 21629 * label_array - (OUT) MPLS header information 21630 * label_count - (OUT) Actual number of labels returned 21631 * Returns: 21632 * BCM_E_XXX 21633 */ 21634 int 21635 bcm_tr_mpls_tunnel_initiator_get(int unit, bcm_if_t intf, int label_max, 21636 bcm_mpls_egress_label_t *label_array, 21637 int *label_count) 21638 { 21639 egr_ip_tunnel_mpls_entry_t tnl_entry; 21640 egr_l3_intf_entry_t if_entry; 21641 int rv, i, ix, push_action, offset; 21642 int tnl_index = 0, mpls_index = 0; 21643 21644 if ((label_array == NULL) || 21645 (intf < 0) || (intf >= L3_INFO(unit)->l3_intf_table_size)) { 21646 return BCM_E_PARAM; 21647 } 21648 21649 if (!BCM_L3_INTF_USED_GET(unit, intf)) { 21650 LOG_INFO(BSL_LS_BCM_L3, 21651 (BSL_META_U(unit, 21652 "L3 interface not created\n"))); 21653 return BCM_E_NOT_FOUND; 21654 } 21655 21656 /* L3 interface info */ 21657 rv = READ_EGR_L3_INTFm(unit, MEM_BLOCK_ANY, intf, &if_entry); 21658 if (rv < 0) { 21659 return rv; 21660 } 21661 mpls_index = soc_EGR_L3_INTFm_field32_get(unit, &if_entry, 21662 MPLS_TUNNEL_INDEXf); 21663 tnl_index = mpls_index / _BCM_MPLS_NUM_MPLS_ENTRIES_PER_INDEX(unit); 21664 21665 if (!_BCM_MPLS_TNL_USED_GET(unit, mpls_index)) { 21666 return BCM_E_NOT_FOUND; 21667 } 21668 rv = READ_EGR_IP_TUNNEL_MPLSm(unit, MEM_BLOCK_ANY, 21669 tnl_index, &tnl_entry); 21670 if (rv < 0) { 21671 return rv; 21672 } 21673 if (soc_mem_field32_get(unit, EGR_IP_TUNNEL_MPLSm, &tnl_entry, 21674 ENTRY_TYPEf) != 3) { 21675 return BCM_E_NOT_FOUND; 21676 } 21677 21678 *label_count = 0; 21679 sal_memset(label_array, 0, sizeof(bcm_mpls_egress_label_t) * label_max); 21680 offset = mpls_index & _BCM_MPLS_EGR_L3_INTF_MPLS_INDEX_OFFSET_MASK(unit); 21681 push_action = soc_mem_field32_get(unit, EGR_IP_TUNNEL_MPLSm, &tnl_entry, 21682 _tnl_push_action_f[offset]); 21683 if (push_action == 0x1) { 21684 *label_count = 1; 21685 } else if (push_action == 0x2) { 21686 *label_count = 2; 21687 } 21688 if (label_max < *label_count) { 21689 *label_count = label_max; 21690 } 21691 for (i = 0; i < *label_count; i++) { 21692 label_array[i].label = 21693 soc_mem_field32_get(unit, EGR_IP_TUNNEL_MPLSm, 21694 &tnl_entry, _tnl_label_f[offset]); 21695 if (soc_mem_field32_get(unit, EGR_IP_TUNNEL_MPLSm, &tnl_entry, 21696 _tnl_exp_select_f[offset]) == 0x0) { 21697 /* Use the specified EXP, PRI and CFI */ 21698 label_array[i].flags |= BCM_MPLS_EGRESS_LABEL_EXP_SET; 21699 label_array[i].flags |= BCM_MPLS_EGRESS_LABEL_PRI_SET; 21700 label_array[i].exp = 21701 soc_mem_field32_get(unit, EGR_IP_TUNNEL_MPLSm, 21702 &tnl_entry, _tnl_exp_f[offset]); 21703 label_array[i].pkt_pri = 21704 soc_mem_field32_get(unit, EGR_IP_TUNNEL_MPLSm, 21705 &tnl_entry, _tnl_pri_f[offset]); 21706 label_array[i].pkt_cfi = 21707 soc_mem_field32_get(unit, EGR_IP_TUNNEL_MPLSm, 21708 &tnl_entry, _tnl_cfi_f[offset]); 21709 } else if (soc_mem_field32_get(unit, EGR_IP_TUNNEL_MPLSm, &tnl_entry, 21710 _tnl_exp_select_f[offset]) == 0x1) { 21711 /* Use EXP-map for EXP, PRI and CFI */ 21712 label_array[i].flags |= BCM_MPLS_EGRESS_LABEL_EXP_REMARK; 21713 label_array[i].flags |= BCM_MPLS_EGRESS_LABEL_PRI_REMARK; 21714 21715 ix = soc_mem_field32_get(unit, EGR_IP_TUNNEL_MPLSm, 21716 &tnl_entry, _tnl_exp_ptr_f[offset]); 21717 21718 BCM_IF_ERROR_RETURN( 21719 _egr_qos_hw_idx2id(unit, ix, &label_array[i].qos_map_id)); 21720 } else { 21721 /* Use EXP from incoming label. If there is no incoming label, 21722 * use the specified EXP value. 21723 */ 21724 label_array[i].flags |= BCM_MPLS_EGRESS_LABEL_EXP_COPY; 21725 label_array[i].flags |= BCM_MPLS_EGRESS_LABEL_PRI_REMARK; 21726 label_array[i].exp = 21727 soc_mem_field32_get(unit, EGR_IP_TUNNEL_MPLSm, 21728 &tnl_entry, _tnl_exp_f[offset]); 21729 21730 /* Use EXP-map for PRI/CFI */ 21731 ix = soc_mem_field32_get(unit, EGR_IP_TUNNEL_MPLSm, 21732 &tnl_entry, _tnl_exp_ptr_f[offset]); 21733 BCM_IF_ERROR_RETURN( 21734 _egr_qos_hw_idx2id(unit, ix, &label_array[i].qos_map_id)); 21735 } 21736 if (soc_mem_field32_get(unit, EGR_IP_TUNNEL_MPLSm, &tnl_entry, 21737 _tnl_ttl_f[offset])) { 21738 /* Use specified TTL value */ 21739 label_array[i].flags |= BCM_MPLS_EGRESS_LABEL_TTL_SET; 21740 label_array[i].ttl = 21741 soc_mem_field32_get(unit, EGR_IP_TUNNEL_MPLSm, 21742 &tnl_entry, _tnl_ttl_f[offset]); 21743 } else { 21744 label_array[i].flags |= BCM_MPLS_EGRESS_LABEL_TTL_DECREMENT; 21745 } 21746 offset++; 21747 } 21748 return BCM_E_NONE; 21749 } 21750 21751 /* 21752 * Function: 21753 * _bcm_tr_mpls_tunnel_chain_label_count_get 21754 * Purpose: 21755 * Get number of labels in a single chain 21756 * Parameters: 21757 * unit - (IN) Device Number 21758 * index - (IN) Mpls index 21759 * label_count - (OUT) Actual number of labels returned 21760 * Returns: 21761 * BCM_E_XXX 21762 */ 21763 int 21764 _bcm_tr_mpls_tunnel_chain_label_count_get(int unit, uint32 index, 21765 int *label_count) 21766 { 21767 egr_ip_tunnel_mpls_entry_t tnl_entry; 21768 int rv, i, push_action, offset; 21769 int tnl_index = 0; 21770 rv = BCM_E_NONE; 21771 21772 tnl_index = index / _BCM_MPLS_NUM_MPLS_ENTRIES_PER_INDEX(unit); 21773 if (!_BCM_MPLS_TNL_USED_GET(unit, index)) { 21774 return BCM_E_NOT_FOUND; 21775 } 21776 21777 rv = READ_EGR_IP_TUNNEL_MPLSm(unit, MEM_BLOCK_ANY, 21778 tnl_index, &tnl_entry); 21779 21780 if (rv < 0) { 21781 return rv; 21782 } 21783 if (soc_mem_field32_get(unit, EGR_IP_TUNNEL_MPLSm, &tnl_entry, 21784 ENTRY_TYPEf) != 3) { 21785 return BCM_E_NOT_FOUND; 21786 } 21787 *label_count = 0; 21788 offset = index & _BCM_MPLS_EGR_L3_INTF_MPLS_INDEX_OFFSET_MASK(unit); 21789 21790 for(i = 0; i < _BCM_MPLS_NUM_MPLS_ENTRIES_PER_INDEX(unit) ; i++) { 21791 push_action = soc_mem_field32_get(unit, EGR_IP_TUNNEL_MPLSm, &tnl_entry, 21792 _tnl_push_action_f[offset+i]); 21793 if (push_action == 0x1) { 21794 break; 21795 } 21796 } 21797 *label_count = i+1; 21798 return rv; 21799 } 21800 21801 /* 21802 * Function: 21803 * bcm_mpls_tunnel_initiator_clear_all 21804 * Purpose: 21805 * Clear all MPLS Tunnel Initiators 21806 * Parameters: 21807 * unit - Device Number 21808 * Returns: 21809 * BCM_E_XXX 21810 */ 21811 int 21812 bcm_tr_mpls_tunnel_initiator_clear_all(int unit) 21813 { 21814 egr_l3_intf_entry_t if_entry; 21815 int mpls_index, i; 21816 int rv=BCM_E_NONE; 21817 21818 for (i = 0; i < L3_INFO(unit)->l3_intf_table_size; i++) { 21819 if (!BCM_L3_INTF_USED_GET(unit, i)) { 21820 continue; 21821 } 21822 rv = READ_EGR_L3_INTFm(unit, MEM_BLOCK_ANY, i, &if_entry); 21823 if (rv < 0) { 21824 return rv; 21825 } 21826 mpls_index = soc_EGR_L3_INTFm_field32_get(unit, &if_entry, 21827 MPLS_TUNNEL_INDEXf); 21828 if (!_BCM_MPLS_TNL_USED_GET(unit, mpls_index)) { 21829 continue; 21830 } 21831 rv = _bcm_tr_mpls_tunnel_initiator_clear(unit, i); 21832 if (rv < 0) { 21833 return rv; 21834 } 21835 } 21836 return rv; 21837 } 21838 21839 /* 21840 * Function: 21841 * bcm_tr_mpls_get_entry_type 21842 * Purpose: 21843 * To get Entry_type of EGR_L3_NEXT_HOP Entry for a specific EGR_NH Index 21844 * Parameters: 21845 * IN : Unit 21846 * IN : nh_index 21847 * OUT: entry_type 21848 * Returns: 21849 * BCM_E_XXX 21850 */ 21851 21852 int 21853 bcm_tr_mpls_get_entry_type (int unit, int nh_index, uint32 *entry_type ) 21854 { 21855 egr_l3_next_hop_entry_t egr_nh; 21856 int rv=BCM_E_NONE; 21857 21858 /* Retrieve EGR L3 NHOP Entry */ 21859 BCM_IF_ERROR_RETURN (soc_mem_read(unit, EGR_L3_NEXT_HOPm, MEM_BLOCK_ANY, 21860 nh_index, &egr_nh)); 21861 *entry_type = 21862 soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, nh_entry_type_field[unit]); 21863 21864 return rv; 21865 } 21866 21867 /* 21868 * Function: 21869 * bcm_tr_mpls_get_label_action 21870 * Purpose: 21871 * To get MPLS Label action for a specific next_hop_index 21872 * Parameters: 21873 * IN : Unit 21874 * IN : nh_index 21875 * OUT : label_action 21876 * Returns: 21877 * BCM_E_XXX 21878 */ 21879 21880 int 21881 bcm_tr_mpls_get_label_action (int unit, int nh_index, uint32 *label_action ) 21882 { 21883 21884 egr_l3_next_hop_entry_t egr_nh; 21885 egr_mpls_vc_and_swap_label_table_entry_t vc_entry; 21886 int vc_swap_idx; 21887 uint32 label_select = 0; 21888 21889 BCM_IF_ERROR_RETURN (soc_mem_read(unit, EGR_L3_NEXT_HOPm, MEM_BLOCK_ANY, 21890 nh_index, &egr_nh)); 21891 21892 if (soc_feature(unit, soc_feature_th3_style_simple_mpls)) { 21893 *label_action = soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, 21894 &egr_nh, MPLS__MPLS_LABEL_ACTIONf); 21895 return BCM_E_NONE; 21896 } else if (soc_feature(unit, soc_feature_mpls_enhanced)) { 21897 vc_swap_idx = soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, 21898 MPLS__VC_AND_SWAP_INDEXf); 21899 } else { 21900 vc_swap_idx = soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, 21901 VC_AND_SWAP_INDEXf); 21902 } 21903 21904 BCM_IF_ERROR_RETURN (soc_mem_read(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 21905 MEM_BLOCK_ANY, vc_swap_idx, &vc_entry)); 21906 21907 #if defined(BCM_TRIDENT3_SUPPORT) 21908 /*SWAP Action is similar to PUSH in TD3*/ 21909 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 21910 if (MPLS_INFO(unit)->egr_vc_swap_lbl_action != NULL) { 21911 *label_action = 21912 MPLS_INFO(unit)->egr_vc_swap_lbl_action[vc_swap_idx]; 21913 } 21914 } else 21915 #endif 21916 { 21917 *label_action = soc_mem_field32_get(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 21918 &vc_entry, MPLS_LABEL_ACTIONf); 21919 } 21920 #if defined(BCM_TRIDENT3_SUPPORT) 21921 if(soc_feature(unit, soc_feature_td3_style_mpls)) { 21922 label_select = soc_mem_field32_get(unit, 21923 EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 21924 &vc_entry, LABEL_SELECTf); 21925 } 21926 #endif 21927 if (label_select) { 21928 *label_action = _BCM_MPLS_ACTION_PRESERVED; 21929 } 21930 return BCM_E_NONE; 21931 21932 } 21933 21934 /* 21935 * Function: 21936 * bcm_tr_mpls_egress_entry_mac_replace 21937 * Purpose: 21938 * Replace MAC_DA within MAC_DA_PROFILE 21939 * Parameters: 21940 * IN : Unit 21941 * IN : nh_index 21942 * IN : Egress forwarding destination. 21943 * Returns: 21944 * BCM_E_XXX 21945 */ 21946 21947 int 21948 bcm_tr_mpls_egress_entry_mac_replace(int unit, int nh_index, bcm_l3_egress_t *egr) 21949 { 21950 egr_l3_next_hop_entry_t egr_nh; 21951 uint32 new_macda_index=-1, old_macda_index=-1; 21952 void *entries[1]; 21953 int rv = BCM_E_NONE; 21954 int entry_type; 21955 egr_mac_da_profile_entry_t macda; 21956 21957 BCM_IF_ERROR_RETURN 21958 (soc_mem_read(unit, EGR_L3_NEXT_HOPm, MEM_BLOCK_ALL, nh_index, &egr_nh)); 21959 21960 entry_type = soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_nh, nh_entry_type_field[unit]); 21961 21962 /* 21963 * If entry_type is 0, then the MAC address is in EGR_L3_NEXT_HOPm 21964 */ 21965 if (entry_type == 1) { 21966 sal_memset(&macda, 0, sizeof(egr_mac_da_profile_entry_t)); 21967 soc_mem_mac_addr_set(unit, EGR_MAC_DA_PROFILEm, &macda, MAC_ADDRESSf, egr->mac_addr); 21968 entries[0] = &macda; 21969 BCM_IF_ERROR_RETURN 21970 (_bcm_mac_da_profile_entry_add(unit, entries, 1, (uint32 *) &new_macda_index)); 21971 21972 if (soc_feature(unit, soc_feature_mpls_enhanced)) { 21973 old_macda_index = soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, 21974 &egr_nh, MPLS__MAC_DA_PROFILE_INDEXf); 21975 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 21976 &egr_nh, MPLS__MAC_DA_PROFILE_INDEXf, new_macda_index); 21977 } else { 21978 old_macda_index = soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, 21979 &egr_nh, MAC_DA_PROFILE_INDEXf); 21980 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 21981 &egr_nh, MAC_DA_PROFILE_INDEXf, new_macda_index); 21982 } 21983 21984 rv = soc_mem_write(unit, EGR_L3_NEXT_HOPm, MEM_BLOCK_ALL, nh_index, &egr_nh); 21985 if (BCM_SUCCESS(rv)) { 21986 if (old_macda_index != -1) { 21987 _bcm_mac_da_profile_entry_delete(unit, old_macda_index); 21988 } 21989 } else { 21990 _bcm_mac_da_profile_entry_delete(unit, new_macda_index); 21991 } 21992 } else if (soc_feature(unit, soc_feature_egress_object_mac_da_replace) && (entry_type == 0)) { 21993 if (soc_mem_field_valid(unit, EGR_L3_NEXT_HOPm, MAC_ADDRESSf)) { 21994 /* Set next hop mac address. */ 21995 soc_mem_mac_addr_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, MAC_ADDRESSf, egr->mac_addr); 21996 rv = soc_mem_write(unit, EGR_L3_NEXT_HOPm, MEM_BLOCK_ALL, nh_index, &egr_nh); 21997 } 21998 } 21999 return rv; 22000 } 22001 22002 /* 22003 * Function: 22004 * bcm_tr_mpls_l3_label_add 22005 * Purpose: 22006 * Updates Inner_LABEL within VC_AND_SWAP_TABLE for a specific EGR_NH Index 22007 * Parameters: 22008 * IN : Unit 22009 * IN : mpls_label 22010 * IN : nh_index 22011 * Returns: 22012 * BCM_E_XXX 22013 */ 22014 22015 int 22016 bcm_tr_mpls_l3_label_add (int unit, bcm_l3_egress_t *egr, int nh_index, uint32 flags) 22017 { 22018 int rv=BCM_E_NONE; 22019 egr_mpls_vc_and_swap_label_table_entry_t vc_entry; 22020 int vc_swap_index=-1; 22021 egr_l3_next_hop_entry_t egr_nh; 22022 uint32 entry_type; 22023 int hw_map_idx, num_mpls_map; 22024 int bkt_idx; 22025 bcm_tr_mpls_vc_swap_table_hash_t *hash_input; 22026 int ref_count = 0; 22027 22028 22029 if (soc_feature(unit, soc_feature_th3_style_simple_mpls)) { 22030 /* NOT supported in TH3 */ 22031 return BCM_E_CONFIG; 22032 } 22033 22034 /* Retrieve EGR L3 NHOP Entry */ 22035 BCM_IF_ERROR_RETURN (soc_mem_read(unit, EGR_L3_NEXT_HOPm, MEM_BLOCK_ANY, 22036 nh_index, &egr_nh)); 22037 22038 sal_memset(&vc_entry, 0, 22039 sizeof(egr_mpls_vc_and_swap_label_table_entry_t)); 22040 22041 BCM_IF_ERROR_RETURN(bcm_tr_mpls_get_entry_type(unit, nh_index, &entry_type)); 22042 if ((entry_type == 1) && (egr->mpls_label != BCM_MPLS_LABEL_INVALID) && (flags & BCM_L3_REPLACE)) { 22043 /* Be sure that the existing entry is already setup to 22044 * egress into an MPLS tunnel. If not, return BCM_E_PARAM. 22045 */ 22046 entry_type = 22047 soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, nh_entry_type_field[unit]); 22048 22049 if (entry_type != 0x1) { /* != MPLS_MACDA_PROFILE */ 22050 return BCM_E_PARAM; 22051 } 22052 22053 /* Retrieve VC_AND_SWAP_INDEX */ 22054 if (soc_feature(unit, soc_feature_mpls_enhanced)) { 22055 vc_swap_index = soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, 22056 MPLS__VC_AND_SWAP_INDEXf); 22057 } else { 22058 vc_swap_index = soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, 22059 VC_AND_SWAP_INDEXf); 22060 } 22061 22062 if (vc_swap_index == 0) { 22063 22064 BCM_IF_ERROR_RETURN( 22065 _bcm_tr_mpls_get_vc_and_swap_table_index(unit, 0, 22066 NULL, NULL, egr, NULL, _BCM_MPLS_ACTION_PUSH, 22067 &vc_swap_index)); 22068 } else { 22069 /* Retrieve VC_AND_SWAP_TABLE entry */ 22070 BCM_IF_ERROR_RETURN( 22071 soc_mem_read(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 22072 MEM_BLOCK_ALL, vc_swap_index, &vc_entry)); 22073 #if defined(BCM_TRIUMPH3_SUPPORT) 22074 if (soc_feature(unit, soc_feature_vc_and_swap_table_overlaid)) { 22075 BCM_IF_ERROR_RETURN( 22076 _bcm_tr_mpls_vc_and_swap_hash_nhop_delete(unit, 22077 vc_swap_index, 22078 nh_index)); 22079 } 22080 #endif 22081 /* Check if any VC_AND_SWAP_LABEL related info has changed */ 22082 if (BCM_FAILURE(_bcm_tr_mpls_vc_swap_compare 22083 (unit, NULL, NULL, egr, NULL,_BCM_MPLS_ACTION_PUSH, &vc_entry))) { 22084 22085 _bcm_tr_mpls_vc_and_swap_ref_count_get(unit, vc_swap_index, &ref_count); 22086 22087 /* Check if any other Egress objects shares the same vc_swap_index */ 22088 if (ref_count > 1) { 22089 _bcm_tr_mpls_vc_and_swap_ref_count_adjust (unit, vc_swap_index, -1); 22090 22091 /* Entry sharing can't be possible, create a new index */ 22092 BCM_IF_ERROR_RETURN( 22093 _bcm_tr_mpls_get_vc_and_swap_table_index(unit, 0, 22094 NULL, NULL, egr, NULL, _BCM_MPLS_ACTION_PUSH, 22095 &vc_swap_index)); 22096 } else { 22097 int tmp_action = 0; 22098 22099 #ifdef BCM_TRIDENT3_SUPPORT 22100 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 22101 tmp_action = MPLS_INFO(unit)->egr_vc_swap_lbl_action[vc_swap_index]; 22102 } 22103 #endif 22104 /* delete the sw state for old entry */ 22105 BCM_IF_ERROR_RETURN(bcmi_tr_mpls_vc_swap_hash_index_get( 22106 unit, NULL, tmp_action, NULL, NULL, &vc_entry, &bkt_idx)); 22107 22108 hash_input = &(bcmi_vc_swap_label_hash[unit][bkt_idx]); 22109 BCM_IF_ERROR_RETURN(bcmi_tr_mpls_vc_swap_hash_delete( 22110 unit, hash_input, vc_swap_index)); 22111 22112 /* Create the sw state for new entry */ 22113 BCM_IF_ERROR_RETURN(bcmi_tr_mpls_vc_swap_hash_index_get( 22114 unit, NULL, _BCM_MPLS_ACTION_PUSH, NULL, egr, NULL, &bkt_idx)); 22115 22116 hash_input = &(bcmi_vc_swap_label_hash[unit][bkt_idx]); 22117 BCM_IF_ERROR_RETURN(bcmi_tr_mpls_vc_swap_hash_insert(unit, hash_input, 22118 vc_swap_index, NULL, NULL, egr, NULL, _BCM_MPLS_ACTION_PUSH, 22119 &vc_swap_index, FALSE)); 22120 } 22121 } 22122 } 22123 }else if ((entry_type == 1) && (egr->mpls_label == BCM_MPLS_LABEL_INVALID) && (flags & BCM_L3_REPLACE)) { 22124 rv = bcm_tr_mpls_l3_label_delete (unit, nh_index); 22125 return rv; 22126 } else { 22127 22128 BCM_IF_ERROR_RETURN( 22129 _bcm_tr_mpls_get_vc_and_swap_table_index(unit, 0, 22130 NULL, NULL, egr, NULL, _BCM_MPLS_ACTION_PUSH, &vc_swap_index)); 22131 } 22132 /* Retrieve hardware index for mapping pointer */ 22133 if ((egr->mpls_flags & BCM_MPLS_EGRESS_LABEL_EXP_SET) || 22134 (egr->mpls_flags & BCM_MPLS_EGRESS_LABEL_PRI_SET)) { 22135 /* Mapping pointer not used */ 22136 hw_map_idx = -1; 22137 } else { 22138 num_mpls_map = soc_mem_index_count(unit, EGR_MPLS_EXP_MAPPING_1m) / 64; 22139 rv = _egr_qos_id2hw_idx(unit,egr->mpls_qos_map_id,&hw_map_idx); 22140 if ((rv != BCM_E_NONE) || hw_map_idx < 0 || hw_map_idx >= num_mpls_map) { 22141 if (egr->mpls_flags & BCM_MPLS_EGRESS_LABEL_EXP_REMARK) { 22142 rv = BCM_E_PARAM; 22143 goto cleanup; 22144 } else { 22145 hw_map_idx = 0; /* use default */ 22146 } 22147 } 22148 } 22149 22150 /* Program the MPLS_VC_AND_SWAP table entry */ 22151 rv = _bcm_tr_mpls_vc_and_swap_table_entry_set(unit, NULL, NULL, egr, 22152 _BCM_MPLS_ACTION_PUSH, &vc_entry, hw_map_idx, 22153 vc_swap_index); 22154 if (rv < 0){ 22155 goto cleanup; 22156 } 22157 #if defined(BCM_TRIUMPH2_SUPPORT) \ 22158 || defined(BCM_ENDURO_SUPPORT) || defined(BCM_TRIDENT_SUPPORT) 22159 if (SOC_IS_TRIUMPH2(unit) 22160 || SOC_IS_ENDURO(unit) || SOC_IS_TRIDENT(unit)) { 22161 /* workaround a hardware issue which is corrected on newer chips 22162 * that the EGR_SD_TAG_CONTROL register influnces L3 MPLS tunnel's 22163 * TPID selection. This shouldn't happen since L3 MPLS 22164 * isn't using SD_TAG. 22165 */ 22166 soc_mem_field32_set(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 22167 &vc_entry, SD_TAG_ACTION_IF_NOT_PRESENTf, 22168 3); 22169 } 22170 #endif 22171 rv = soc_mem_write(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 22172 MEM_BLOCK_ALL, vc_swap_index, 22173 &vc_entry); 22174 if (rv < 0){ 22175 goto cleanup; 22176 } 22177 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 22178 &egr_nh, nh_entry_type_field[unit], 22179 entry_type); 22180 22181 if (soc_feature(unit, soc_feature_mpls_enhanced)) { 22182 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 22183 &egr_nh, MPLS__VC_AND_SWAP_INDEXf, 22184 vc_swap_index); 22185 /* Enable HG.L3_bit */ 22186 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 22187 &egr_nh, MPLS__HG_L3_OVERRIDEf, 0x1); 22188 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 22189 &egr_nh, MPLS__HG_MODIFY_ENABLEf, 0x1); 22190 #if defined(INCLUDE_XFLOW_MACSEC) 22191 if (soc_feature(unit, soc_feature_xflow_macsec) && 22192 ((egr->flags2 & BCM_L3_FLAGS2_XFLOW_MACSEC_ENCRYPT) || 22193 (egr->flags2 & BCM_L3_FLAGS2_XFLOW_MACSEC_DECRYPT))) { 22194 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 22195 &egr_nh, MPLS__MACSEC_ENCRYPTf, 0); 22196 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 22197 &egr_nh, MPLS__MACSEC_DECRYPTf, 0); 22198 if (egr->flags2 & BCM_L3_FLAGS2_XFLOW_MACSEC_ENCRYPT) { 22199 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 22200 &egr_nh, MPLS__MACSEC_ENCRYPTf, 0x1); 22201 } else { 22202 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 22203 &egr_nh, MPLS__MACSEC_DECRYPTf, 0x1); 22204 } 22205 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 22206 &egr_nh, MPLS__HG_MC_DST_MODIDf, egr->module); 22207 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 22208 &egr_nh, MPLS__HG_MC_DST_PORT_NUMf, egr->port); 22209 } 22210 #endif 22211 } else { 22212 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 22213 &egr_nh, VC_AND_SWAP_INDEXf, 22214 vc_swap_index); 22215 /* Enable HG.L3_bit */ 22216 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 22217 &egr_nh, HG_L3_OVERRIDEf, 0x1); 22218 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 22219 &egr_nh, HG_MODIFY_ENABLEf, 0x1); 22220 } 22221 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) 22222 if (soc_feature(unit, soc_feature_mpls_nh_ttl_control)) { 22223 if (egr->flags & BCM_L3_KEEP_TTL) { 22224 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 22225 MPLS__DISABLE_TTL_DECREMENTf, 1); 22226 } else { 22227 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 22228 MPLS__DISABLE_TTL_DECREMENTf, 0); 22229 } 22230 } 22231 #endif 22232 rv = soc_mem_write(unit, EGR_L3_NEXT_HOPm, 22233 MEM_BLOCK_ALL, nh_index, &egr_nh); 22234 22235 if (rv < 0) { 22236 goto cleanup; 22237 } 22238 #if defined(BCM_TRIUMPH3_SUPPORT) 22239 if (soc_feature(unit, soc_feature_vc_and_swap_table_overlaid)) { 22240 rv = _bcm_tr_mpls_vc_and_swap_hash_nhop_add(unit, 22241 vc_swap_index, 22242 nh_index); 22243 if (rv < 0) { 22244 goto cleanup; 22245 } 22246 } 22247 #endif 22248 #ifdef BCM_WARM_BOOT_SUPPORT 22249 SOC_CONTROL_LOCK(unit); 22250 SOC_CONTROL(unit)->scache_dirty = 1; 22251 SOC_CONTROL_UNLOCK(unit); 22252 #endif 22253 22254 return rv; 22255 22256 cleanup: 22257 if (vc_swap_index >= 0) { 22258 if (!(flags & BCM_L3_REPLACE)) { 22259 _bcm_tr_mpls_vc_and_swap_ref_count_adjust (unit, vc_swap_index, -1); 22260 /* Free VC_AND_SWAP_LABEL entry */ 22261 (void)_bcm_tr_mpls_vc_and_swap_table_index_reset (unit, vc_swap_index); 22262 } 22263 } 22264 return rv; 22265 } 22266 22267 /* 22268 * Function: 22269 * bcm_tr_mpls_l3_label_get 22270 * Purpose: 22271 * Retrieves the Inner_LABEL within VC_AND_SWAP_TABLE for a specific EGR_NH Index 22272 * Parameters: 22273 * IN : Unit 22274 * IN : mpls_label 22275 * IN : nh_index 22276 * Returns: 22277 * BCM_E_XXX 22278 */ 22279 22280 int 22281 bcm_tr_mpls_l3_label_get (int unit, int index, bcm_l3_egress_t *egr) 22282 { 22283 int rv=BCM_E_NONE; 22284 int vc_swap_index=-1; 22285 egr_l3_next_hop_entry_t egr_nh; 22286 egr_mpls_vc_and_swap_label_table_entry_t vc_entry; 22287 uint32 entry_type; 22288 uint32 label_action = 0; 22289 22290 /* Retrieve EGR L3 NHOP Entry */ 22291 BCM_IF_ERROR_RETURN (soc_mem_read(unit, EGR_L3_NEXT_HOPm, MEM_BLOCK_ANY, 22292 index, &egr_nh)); 22293 22294 entry_type = 22295 soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, nh_entry_type_field[unit]); 22296 22297 if (entry_type != 0x1) { /* != MPLS_MACDA_PROFILE */ 22298 egr->mpls_label = BCM_MPLS_LABEL_INVALID; 22299 return rv; 22300 } 22301 22302 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) 22303 if (soc_feature(unit, soc_feature_mpls_nh_ttl_control)) { 22304 if (soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_nh, 22305 MPLS__DISABLE_TTL_DECREMENTf)) { 22306 egr->flags |= BCM_L3_KEEP_TTL; 22307 } 22308 } 22309 #endif 22310 22311 #ifdef BCM_TOMAHAWK3_SUPPORT 22312 if (soc_feature(unit, soc_feature_th3_style_simple_mpls)) { 22313 label_action = 22314 soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, 22315 &egr_nh, MPLS__MPLS_LABEL_ACTIONf); 22316 22317 if (label_action == _BCM_MPLS_ACTION_PUSH) { 22318 egr->flags |= BCM_L3_ROUTE_LABEL; 22319 egr->mpls_label = 22320 soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, 22321 &egr_nh, MPLS__MPLS_LABELf); 22322 egr->mpls_ttl = 22323 soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, 22324 &egr_nh, MPLS__MPLS_TTLf); 22325 if (egr->mpls_ttl) { 22326 egr->mpls_flags |= BCM_MPLS_EGRESS_LABEL_TTL_SET; 22327 } 22328 if (soc_feature(unit, soc_feature_mpls_ecn)) { 22329 int ecn_map_id; 22330 int ecn_map_pri; 22331 int ecn_map_hw_idx; 22332 int ret; 22333 ecn_map_hw_idx = soc_mem_field32_get(unit, 22334 EGR_L3_NEXT_HOPm, 22335 &egr_nh, 22336 MPLS__IP_ECN_TO_EXP_MAPPING_PTRf); 22337 ecn_map_pri = soc_mem_field32_get(unit, 22338 EGR_L3_NEXT_HOPm, 22339 &egr_nh, 22340 MPLS__IP_ECN_TO_EXP_PRIORITYf); 22341 ret = bcmi_ecn_map_hw_idx2id(unit, ecn_map_hw_idx, 22342 _BCM_XGS5_MPLS_ECN_MAP_TYPE_ECN2EXP, 22343 &ecn_map_id); 22344 if (BCM_SUCCESS(ret)) { 22345 egr->mpls_flags |= BCM_MPLS_EGRESS_LABEL_ECN_TO_EXP_MAP; 22346 egr->mpls_ecn_map_id = ecn_map_id; 22347 if (ecn_map_pri) { 22348 egr->mpls_flags |= BCM_MPLS_EGRESS_LABEL_ECN_EXP_MAP_TRUST; 22349 } 22350 } 22351 } 22352 } else { 22353 egr->mpls_label = BCM_MPLS_LABEL_INVALID; 22354 } 22355 return rv; 22356 } 22357 #endif 22358 22359 /* Retrieve VC_AND_SWAP_INDEX */ 22360 if (soc_feature(unit, soc_feature_mpls_enhanced)) { 22361 vc_swap_index = soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, 22362 MPLS__VC_AND_SWAP_INDEXf); 22363 } else { 22364 vc_swap_index = soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, 22365 VC_AND_SWAP_INDEXf); 22366 } 22367 if (vc_swap_index != -1) { 22368 /* Retrieve VC_AND_SWAP_TABLE entry */ 22369 BCM_IF_ERROR_RETURN( 22370 soc_mem_read(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 22371 MEM_BLOCK_ALL, vc_swap_index, &vc_entry)); 22372 22373 #if defined(BCM_TRIDENT3_SUPPORT) 22374 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 22375 if (MPLS_INFO(unit)->egr_vc_swap_lbl_action != NULL) { 22376 label_action = MPLS_INFO(unit)->egr_vc_swap_lbl_action[vc_swap_index]; 22377 } 22378 } else 22379 #endif 22380 { 22381 label_action = 22382 soc_mem_field32_get(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 22383 &vc_entry, MPLS_LABEL_ACTIONf); 22384 } 22385 #if defined(BCM_SWAP_TO_SELF_SUPPORT) 22386 if (soc_feature(unit, soc_feature_mpls_swap_label_preserve) && 22387 (label_action == _BCM_MPLS_ACTION_NOOP)) { 22388 return rv; 22389 } 22390 #endif 22391 if (label_action == _BCM_MPLS_ACTION_PUSH) { 22392 egr->flags |= BCM_L3_ROUTE_LABEL; 22393 egr->mpls_label = 22394 soc_mem_field32_get(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 22395 &vc_entry, MPLS_LABELf); 22396 egr->mpls_ttl = 22397 soc_mem_field32_get(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 22398 &vc_entry, MPLS_TTLf); 22399 if (egr->mpls_ttl) { 22400 egr->mpls_flags |= BCM_MPLS_EGRESS_LABEL_TTL_SET; 22401 } 22402 #if defined(BCM_TOMAHAWK2_SUPPORT) || defined(BCM_TRIDENT3_SUPPORT) 22403 if (soc_feature(unit, soc_feature_mpls_ecn)) { 22404 int ecn_map_id; 22405 int ecn_map_pri; 22406 int ecn_map_hw_idx; 22407 int ret; 22408 soc_field_t ipecn_to_exp_ptr; 22409 soc_field_t ipecn_to_exp_priority; 22410 22411 #if defined(BCM_TRIDENT3_SUPPORT) 22412 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 22413 ipecn_to_exp_ptr = PKT_ECN_TO_EXP_MAPPING_PTRf; 22414 ipecn_to_exp_priority = PKT_ECN_TO_EXP_PRIORITYf; 22415 } else 22416 #endif 22417 { 22418 ipecn_to_exp_ptr = IP_ECN_TO_EXP_MAPPING_PTRf; 22419 ipecn_to_exp_priority = IP_ECN_TO_EXP_PRIORITYf; 22420 } 22421 ecn_map_hw_idx = soc_mem_field32_get(unit, 22422 EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 22423 &vc_entry, 22424 ipecn_to_exp_ptr); 22425 ecn_map_pri = soc_mem_field32_get(unit, 22426 EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 22427 &vc_entry, 22428 ipecn_to_exp_priority); 22429 ret = bcmi_ecn_map_hw_idx2id(unit, ecn_map_hw_idx, 22430 _BCM_XGS5_MPLS_ECN_MAP_TYPE_ECN2EXP, 22431 &ecn_map_id); 22432 if (BCM_SUCCESS(ret)) { 22433 egr->mpls_flags |= BCM_MPLS_EGRESS_LABEL_ECN_TO_EXP_MAP; 22434 egr->mpls_ecn_map_id = ecn_map_id; 22435 if (ecn_map_pri) { 22436 egr->mpls_flags |= BCM_MPLS_EGRESS_LABEL_ECN_EXP_MAP_TRUST; 22437 } 22438 } 22439 } 22440 #endif 22441 } else { 22442 egr->mpls_label = BCM_MPLS_LABEL_INVALID; 22443 } 22444 } else { 22445 egr->mpls_label = BCM_MPLS_LABEL_INVALID; 22446 } 22447 22448 return rv; 22449 } 22450 22451 /* 22452 * Function: 22453 * bcm_tr_mpls_l3_label_delete 22454 * Purpose: 22455 * Deletes Inner_LABEL within VC_AND_SWAP_TABLE for a specific EGR_NH Index 22456 * Parameters: 22457 * IN : Unit 22458 * IN : nh_index 22459 * Returns: 22460 * BCM_E_XXX 22461 */ 22462 22463 22464 int 22465 bcm_tr_mpls_l3_label_delete (int unit, int index) 22466 { 22467 int rv=BCM_E_NONE; 22468 int vc_swap_index=-1; 22469 egr_l3_next_hop_entry_t egr_nh; 22470 uint8 entry_type; 22471 int macda_index=-1; 22472 22473 BCM_IF_ERROR_RETURN (soc_mem_read(unit, EGR_L3_NEXT_HOPm, MEM_BLOCK_ANY, 22474 index, &egr_nh)); 22475 22476 /* Retrieve and Verify ENTRY_TYPE */ 22477 entry_type = 22478 soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, nh_entry_type_field[unit]); 22479 22480 if (entry_type != 0x1) { /* != MPLS_MACDA_PROFILE */ 22481 return BCM_E_PARAM; 22482 } 22483 22484 /* Set Entry_Type to Normal */ 22485 entry_type = 0; /* Normal */ 22486 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 22487 nh_entry_type_field[unit], entry_type); 22488 22489 /* Delete MAC_DA_PROFILE_INDEX */ 22490 if (soc_feature(unit, soc_feature_mpls_enhanced)) { 22491 macda_index = 22492 soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, 22493 MPLS__MAC_DA_PROFILE_INDEXf); 22494 } else { 22495 macda_index = 22496 soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, 22497 MAC_DA_PROFILE_INDEXf); 22498 } 22499 22500 if (macda_index != -1) { 22501 _bcm_mac_da_profile_entry_delete(unit, macda_index); 22502 } 22503 22504 if (SOC_MEM_IS_VALID(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm)) { 22505 /* Retrieve VC_AND_SWAP_INDEX */ 22506 if (soc_feature(unit, soc_feature_mpls_enhanced)) { 22507 vc_swap_index = soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, 22508 MPLS__VC_AND_SWAP_INDEXf); 22509 } else { 22510 vc_swap_index = soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, 22511 VC_AND_SWAP_INDEXf); 22512 } 22513 22514 #if defined(BCM_TRIUMPH3_SUPPORT) 22515 if (soc_feature(unit, soc_feature_vc_and_swap_table_overlaid)) { 22516 BCM_IF_ERROR_RETURN( 22517 _bcm_tr_mpls_vc_and_swap_hash_nhop_delete(unit, 22518 vc_swap_index, 22519 index)); 22520 } 22521 #endif 22522 22523 _bcm_tr_mpls_vc_and_swap_ref_count_adjust (unit, vc_swap_index, -1); 22524 22525 BCM_IF_ERROR_RETURN 22526 (_bcm_tr_mpls_vc_and_swap_table_index_reset (unit, vc_swap_index)); 22527 22528 vc_swap_index = 0; 22529 if (soc_feature(unit, soc_feature_mpls_enhanced)) { 22530 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 22531 &egr_nh, MPLS__VC_AND_SWAP_INDEXf, 22532 vc_swap_index); 22533 } else { 22534 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 22535 &egr_nh, VC_AND_SWAP_INDEXf, 22536 vc_swap_index); 22537 } 22538 } 22539 22540 rv = soc_mem_write(unit, EGR_L3_NEXT_HOPm, 22541 MEM_BLOCK_ALL, index, &egr_nh); 22542 22543 #ifdef BCM_WARM_BOOT_SUPPORT 22544 SOC_CONTROL_LOCK(unit); 22545 SOC_CONTROL(unit)->scache_dirty = 1; 22546 SOC_CONTROL_UNLOCK(unit); 22547 #endif 22548 22549 return rv; 22550 } 22551 22552 /* 22553 * Function: 22554 * bcm_tr_mpls_swap_nh_info_add 22555 * Purpose: 22556 * Add SWAP_LABEL within VC_AND_SWAP_TABLE for a specific EGR_NH Index 22557 * Parameters: 22558 * IN : Unit 22559 * IN : Egress object Pointer 22560 * IN : nh_index 22561 * Returns: 22562 * BCM_E_XXX 22563 */ 22564 22565 int 22566 bcm_tr_mpls_swap_nh_info_add (int unit, bcm_l3_egress_t *egr, int nh_index, uint32 flags) 22567 { 22568 ing_l3_next_hop_entry_t ing_nh; 22569 egr_l3_next_hop_entry_t egr_nh; 22570 egr_mpls_vc_and_swap_label_table_entry_t vc_entry, old_vc_entry; 22571 int vc_swap_index = -1; 22572 uint32 old_vc_swap_idx = -1; 22573 int rv, num_vc; 22574 int hw_map_idx, num_mpls_map; 22575 22576 if (!(BCM_XGS3_L3_MPLS_LBL_VALID(egr->mpls_label) || 22577 _BCM_MPLS_EGRESS_LABEL_PRESERVE(unit, egr->mpls_flags))) { 22578 return BCM_E_PARAM; 22579 } 22580 sal_memset(&egr_nh, 0, sizeof(egr_l3_next_hop_entry_t)); 22581 22582 BCM_IF_ERROR_RETURN (soc_mem_read(unit, ING_L3_NEXT_HOPm, MEM_BLOCK_ANY, 22583 nh_index, &ing_nh)); 22584 BCM_IF_ERROR_RETURN (soc_mem_read(unit, EGR_L3_NEXT_HOPm, MEM_BLOCK_ANY, 22585 nh_index, &egr_nh)); 22586 22587 /* Retrieve hardware index for mapping pointer */ 22588 if ((egr->mpls_flags & BCM_MPLS_EGRESS_LABEL_EXP_SET) || 22589 (egr->mpls_flags & BCM_MPLS_EGRESS_LABEL_PRI_SET)) { 22590 /* Mapping pointer not used */ 22591 hw_map_idx = -1; 22592 } else { 22593 rv = _egr_qos_id2hw_idx(unit,egr->mpls_qos_map_id,&hw_map_idx); 22594 num_mpls_map = soc_mem_index_count(unit, EGR_MPLS_EXP_MAPPING_1m) / 64; 22595 if ((rv != BCM_E_NONE) || hw_map_idx < 0 || hw_map_idx >= num_mpls_map) { 22596 if (egr->mpls_flags & BCM_MPLS_EGRESS_LABEL_EXP_REMARK) { 22597 rv = BCM_E_PARAM; 22598 goto cleanup; 22599 } else { 22600 hw_map_idx = 0; /* use default */ 22601 } 22602 } 22603 } 22604 22605 if (!soc_feature(unit, soc_feature_th3_style_simple_mpls)) { 22606 /* 22607 * Indexes in the first half of EGR_MPLS_VC_AND_SWAP_LABEL_TABLE 22608 * also get used as the index into the EGR_PW_INIT_COUNTERS table. 22609 * Set num_vc to half the EGR_MPLS_VC_AND_SWAP_LABEL_TABLE size. 22610 * Choose from the non-counted section (second half) so the counted 22611 * section is available for VPWS. 22612 */ 22613 num_vc = soc_mem_index_count(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm); 22614 num_vc /= 2; 22615 22616 /* Check for egr->flags & BCM_L3_REPLACE */ 22617 if (flags & BCM_L3_REPLACE) { 22618 /* Remember old VC_AND_SWAP_INDEX */ 22619 if (soc_feature(unit, soc_feature_mpls_enhanced)) { 22620 old_vc_swap_idx = soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, 22621 MPLS__VC_AND_SWAP_INDEXf); 22622 } else { 22623 old_vc_swap_idx = soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, 22624 VC_AND_SWAP_INDEXf); 22625 } 22626 BCM_IF_ERROR_RETURN (soc_mem_read(unit, 22627 EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 22628 MEM_BLOCK_ANY, old_vc_swap_idx, &old_vc_entry)); 22629 if (!(egr->mpls_flags & BCM_MPLS_EGRESS_LABEL_TTL_SET)) { 22630 egr->mpls_ttl = soc_mem_field32_get(unit, 22631 EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 22632 &old_vc_entry, MPLS_TTLf); 22633 if (egr->mpls_ttl) { 22634 egr->mpls_flags |= BCM_MPLS_EGRESS_LABEL_TTL_SET; 22635 } 22636 } 22637 } 22638 rv = _bcm_tr_mpls_get_vc_and_swap_table_index (unit, 0, NULL, NULL, 22639 egr, NULL, 22640 _BCM_MPLS_EGRESS_LABEL_PRESERVE(unit, egr->mpls_flags) ? 22641 _BCM_MPLS_ACTION_PRESERVED : _BCM_MPLS_ACTION_SWAP, 22642 &vc_swap_index); 22643 _BCM_MPLS_CLEANUP(rv); 22644 rv = _bcm_tr_mpls_vc_and_swap_table_entry_set(unit, NULL, NULL, egr, 22645 _BCM_MPLS_EGRESS_LABEL_PRESERVE(unit, egr->mpls_flags) ? 22646 _BCM_MPLS_ACTION_PRESERVED : _BCM_MPLS_ACTION_SWAP, 22647 &vc_entry, hw_map_idx, vc_swap_index); 22648 _BCM_MPLS_CLEANUP(rv); 22649 #if defined(BCM_TRIUMPH2_SUPPORT) \ 22650 || defined(BCM_ENDURO_SUPPORT) || defined(BCM_TRIDENT_SUPPORT) 22651 if (SOC_IS_TRIUMPH2(unit) 22652 || SOC_IS_ENDURO(unit) || SOC_IS_TRIDENT(unit)) { 22653 /* workaround a hardware issue which is corrected on newer chips 22654 * that the EGR_SD_TAG_CONTROL register influnces L3 MPLS tunnel's 22655 * TPID selection. This shouldn't happen since L3 MPLS 22656 * isn't using SD_TAG. 22657 */ 22658 soc_mem_field32_set(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 22659 &vc_entry, SD_TAG_ACTION_IF_NOT_PRESENTf, 22660 3); 22661 } 22662 #endif 22663 rv = soc_mem_write(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 22664 MEM_BLOCK_ALL, vc_swap_index, 22665 &vc_entry); 22666 _BCM_MPLS_CLEANUP(rv); 22667 if (soc_feature(unit, soc_feature_mpls_enhanced)) { 22668 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 22669 &egr_nh, MPLS__VC_AND_SWAP_INDEXf, 22670 vc_swap_index); 22671 /* Enable HG.L3_bit */ 22672 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 22673 &egr_nh, MPLS__HG_L3_OVERRIDEf, 0x1); 22674 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 22675 &egr_nh, MPLS__HG_MODIFY_ENABLEf, 0x1); 22676 #if defined(INCLUDE_XFLOW_MACSEC) 22677 if (soc_feature(unit, soc_feature_xflow_macsec) && 22678 ((egr->flags2 & BCM_L3_FLAGS2_XFLOW_MACSEC_ENCRYPT) || 22679 (egr->flags2 & BCM_L3_FLAGS2_XFLOW_MACSEC_DECRYPT))) { 22680 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 22681 &egr_nh, MPLS__MACSEC_ENCRYPTf, 0); 22682 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 22683 &egr_nh, MPLS__MACSEC_DECRYPTf, 0); 22684 if (egr->flags2 & BCM_L3_FLAGS2_XFLOW_MACSEC_ENCRYPT) { 22685 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 22686 &egr_nh, MPLS__MACSEC_ENCRYPTf, 0x1); 22687 } else { 22688 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 22689 &egr_nh, MPLS__MACSEC_DECRYPTf, 0x1); 22690 } 22691 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 22692 &egr_nh, MPLS__HG_MC_DST_MODIDf, egr->module); 22693 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 22694 &egr_nh, MPLS__HG_MC_DST_PORT_NUMf, egr->port); 22695 } 22696 #endif 22697 } else { 22698 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 22699 &egr_nh, VC_AND_SWAP_INDEXf, 22700 vc_swap_index); 22701 /* Enable HG.L3_bit */ 22702 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 22703 &egr_nh, HG_L3_OVERRIDEf, 0x1); 22704 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 22705 &egr_nh, HG_MODIFY_ENABLEf, 0x1); 22706 } 22707 } else { 22708 #ifdef BCM_TOMAHAWK3_SUPPORT 22709 uint32 mpls_flags = 0; 22710 uint8 mpls_exp = 0; 22711 uint8 mpls_pkt_pri = 0; 22712 uint8 mpls_pkt_cfi = 0; 22713 int mpls_ecn_map_id = ECN_MAP_ID_INVALID; 22714 int mpls_int_cn_map_id = ECN_MAP_ID_INVALID; 22715 /* TH3 doesnt support EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm*/ 22716 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 22717 &egr_nh, MPLS__MPLS_LABEL_ACTIONf, 22718 _BCM_MPLS_ACTION_NOOP); 22719 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 22720 &egr_nh, MPLS__MPLS_TTLf, 0x0); 22721 mpls_flags = egr->mpls_flags; 22722 mpls_pkt_pri = egr->mpls_pkt_pri; 22723 mpls_pkt_cfi = egr->mpls_pkt_cfi; 22724 mpls_exp = egr->mpls_exp; 22725 if (soc_feature(unit, soc_feature_mpls_ecn)) { 22726 if (mpls_flags & BCM_MPLS_EGRESS_LABEL_INT_CN_TO_EXP_MAP) { 22727 mpls_int_cn_map_id = egr->mpls_ecn_map_id; 22728 } 22729 if (mpls_flags & BCM_MPLS_EGRESS_LABEL_ECN_TO_EXP_MAP) { 22730 mpls_ecn_map_id = egr->mpls_ecn_map_id; 22731 } 22732 } 22733 22734 if ((mpls_exp > 7) || (mpls_pkt_pri > 7) || 22735 (mpls_pkt_cfi > 1)) { 22736 return BCM_E_PARAM; 22737 } 22738 22739 if ((mpls_flags & BCM_MPLS_EGRESS_LABEL_EXP_SET) || 22740 (mpls_flags & BCM_MPLS_EGRESS_LABEL_PRI_SET)) { 22741 22742 if ((mpls_flags & BCM_MPLS_EGRESS_LABEL_EXP_REMARK) || 22743 (mpls_flags & BCM_MPLS_EGRESS_LABEL_EXP_COPY) || 22744 (mpls_flags & BCM_MPLS_EGRESS_LABEL_PRI_REMARK)) { 22745 return BCM_E_PARAM; 22746 } 22747 /* Use the specified EXP, PRI and CFI */ 22748 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 22749 &egr_nh, MPLS__MPLS_EXP_SELECTf, 22750 0x0); /* USE_FIXED */ 22751 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 22752 &egr_nh, MPLS__MPLS_EXPf, 22753 mpls_exp); 22754 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 22755 &egr_nh, MPLS__NEW_PRIf, 22756 mpls_pkt_pri); 22757 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 22758 &egr_nh, MPLS__NEW_CFIf, 22759 mpls_pkt_cfi); 22760 } else if (mpls_flags & BCM_MPLS_EGRESS_LABEL_EXP_REMARK) { 22761 if (mpls_flags & BCM_MPLS_EGRESS_LABEL_PRI_SET) { 22762 return BCM_E_PARAM; 22763 } 22764 /* Use EXP-map for EXP, PRI and CFI */ 22765 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 22766 &egr_nh, MPLS__MPLS_EXP_SELECTf, 22767 0x1); /* USE_MAPPING */ 22768 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 22769 &egr_nh, MPLS__MPLS_EXP_MAPPING_PTRf, 22770 hw_map_idx); 22771 } else if (/*(label_action != _BCM_MPLS_ACTION_SWAP) && */ 22772 (mpls_flags & BCM_MPLS_EGRESS_LABEL_EXP_COPY) ) { 22773 /* Use EXP from incoming label. If there is no incoming label, 22774 * use the specified EXP value. Use EXP-map for PRI/CFI. 22775 */ 22776 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 22777 &egr_nh, MPLS__MPLS_EXP_SELECTf, 22778 0x2); /* USE_INNER */ 22779 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 22780 &egr_nh, MPLS__MPLS_EXPf, 22781 mpls_exp); 22782 22783 /* Use EXP-PRI-map for PRI/CFI */ 22784 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 22785 &egr_nh, MPLS__MPLS_EXP_MAPPING_PTRf, 22786 hw_map_idx); 22787 } else if (/*(label_action == _BCM_MPLS_ACTION_SWAP) && */ 22788 (mpls_flags & BCM_MPLS_EGRESS_LABEL_EXP_COPY) ) { 22789 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 22790 &egr_nh, MPLS__MPLS_EXP_SELECTf, 22791 0x3); /* USE_SWAP */ 22792 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 22793 &egr_nh, MPLS__MPLS_EXPf, mpls_exp); 22794 /* Use EXP-PRI-map for PRI/CFI */ 22795 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 22796 &egr_nh, MPLS__MPLS_EXP_MAPPING_PTRf, 22797 hw_map_idx); 22798 } 22799 if (soc_feature(unit, soc_feature_mpls_ecn)) { 22800 if ((mpls_flags & BCM_MPLS_EGRESS_LABEL_INT_CN_TO_EXP_MAP) && 22801 (mpls_int_cn_map_id != ECN_MAP_ID_INVALID)) { 22802 int ecn_map_index; 22803 int ecn_map_type; 22804 int ecn_map_num; 22805 int ecn_map_hw_idx; 22806 ecn_map_type = mpls_int_cn_map_id & 22807 _BCM_XGS5_MPLS_ECN_MAP_TYPE_MASK; 22808 ecn_map_index = mpls_int_cn_map_id & 22809 _BCM_XGS5_MPLS_ECN_MAP_NUM_MASK; 22810 ecn_map_num = 22811 soc_mem_index_count(unit, EGR_INT_CN_TO_EXP_MAPPING_TABLEm) / 22812 _BCM_ECN_MAX_ENTRIES_PER_MAP; 22813 if (ecn_map_type != _BCM_XGS5_MPLS_ECN_MAP_TYPE_INTCN2EXP) { 22814 return BCM_E_PARAM; 22815 } 22816 if (ecn_map_index >= ecn_map_num) { 22817 return BCM_E_PARAM; 22818 } 22819 BCM_IF_ERROR_RETURN( 22820 bcmi_ecn_map_id2hw_idx(unit, mpls_int_cn_map_id, &ecn_map_hw_idx)); 22821 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 22822 &egr_nh, MPLS__INT_CN_TO_EXP_MAPPING_PTRf, 22823 ecn_map_hw_idx); 22824 if (mpls_flags & BCM_MPLS_EGRESS_LABEL_ECN_EXP_MAP_TRUST) { 22825 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 22826 &egr_nh, MPLS__INT_CN_TO_EXP_PRIORITYf, 1); 22827 22828 } else { 22829 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 22830 &egr_nh, MPLS__INT_CN_TO_EXP_PRIORITYf, 0); 22831 22832 } 22833 } 22834 if ((mpls_flags & BCM_MPLS_EGRESS_LABEL_ECN_TO_EXP_MAP) && 22835 (mpls_ecn_map_id != ECN_MAP_ID_INVALID)) { 22836 int ecn_map_index; 22837 int ecn_map_type; 22838 int ecn_map_num; 22839 int ecn_map_hw_idx; 22840 ecn_map_type = mpls_ecn_map_id & 22841 _BCM_XGS5_MPLS_ECN_MAP_TYPE_MASK; 22842 ecn_map_index = mpls_ecn_map_id & 22843 _BCM_XGS5_MPLS_ECN_MAP_NUM_MASK; 22844 ecn_map_num = 22845 soc_mem_index_count(unit, EGR_IP_ECN_TO_EXP_MAPPING_TABLEm) / 22846 _BCM_ECN_MAX_ENTRIES_PER_MAP; 22847 if (ecn_map_type != _BCM_XGS5_MPLS_ECN_MAP_TYPE_ECN2EXP) { 22848 return BCM_E_PARAM; 22849 } 22850 if (ecn_map_index >= ecn_map_num) { 22851 return BCM_E_PARAM; 22852 } 22853 BCM_IF_ERROR_RETURN( 22854 bcmi_ecn_map_id2hw_idx(unit, mpls_ecn_map_id, &ecn_map_hw_idx)); 22855 22856 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 22857 &egr_nh, MPLS__IP_ECN_TO_EXP_MAPPING_PTRf, 22858 ecn_map_hw_idx); 22859 if (mpls_flags & BCM_MPLS_EGRESS_LABEL_ECN_EXP_MAP_TRUST) { 22860 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 22861 &egr_nh, MPLS__IP_ECN_TO_EXP_PRIORITYf, 1); 22862 22863 } else { 22864 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 22865 &egr_nh, MPLS__IP_ECN_TO_EXP_PRIORITYf, 0); 22866 22867 } 22868 } 22869 } 22870 #endif 22871 } 22872 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) 22873 if (soc_feature(unit, soc_feature_mpls_nh_ttl_control)) { 22874 if (egr->flags & BCM_L3_KEEP_TTL) { 22875 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 22876 MPLS__DISABLE_TTL_DECREMENTf, 1); 22877 } else { 22878 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 22879 MPLS__DISABLE_TTL_DECREMENTf, 0); 22880 } 22881 } 22882 #endif 22883 22884 /* Write EGR_L3_NEXT_HOP entry */ 22885 rv = soc_mem_write(unit, EGR_L3_NEXT_HOPm, 22886 MEM_BLOCK_ALL, nh_index, &egr_nh); 22887 _BCM_MPLS_CLEANUP(rv); 22888 22889 /* Write ING_L3_NEXT_HOP entry */ 22890 22891 soc_mem_field32_set(unit, ING_L3_NEXT_HOPm, 22892 &ing_nh, ENTRY_TYPEf, 0x1); /* MPLS L3_OIF */ 22893 rv = soc_mem_write (unit, ING_L3_NEXT_HOPm, 22894 MEM_BLOCK_ALL, nh_index, &ing_nh); 22895 _BCM_MPLS_CLEANUP(rv); 22896 22897 /* Handle old VC_SWAP indexes */ 22898 if (old_vc_swap_idx != -1) { 22899 #if defined(BCM_TRIUMPH3_SUPPORT) 22900 if (soc_feature(unit, soc_feature_vc_and_swap_table_overlaid)) { 22901 BCM_IF_ERROR_RETURN( 22902 _bcm_tr_mpls_vc_and_swap_hash_nhop_delete(unit, 22903 old_vc_swap_idx, 22904 nh_index)); 22905 } 22906 #endif 22907 _bcm_tr_mpls_vc_and_swap_ref_count_adjust (unit, old_vc_swap_idx, -1); 22908 BCM_IF_ERROR_RETURN 22909 (_bcm_tr_mpls_vc_and_swap_table_index_reset (unit, old_vc_swap_idx)); 22910 } 22911 #if defined(BCM_TRIUMPH3_SUPPORT) 22912 if (soc_feature(unit, soc_feature_vc_and_swap_table_overlaid)) { 22913 rv = _bcm_tr_mpls_vc_and_swap_hash_nhop_add(unit, 22914 vc_swap_index, 22915 nh_index); 22916 _BCM_MPLS_CLEANUP(rv); 22917 } 22918 #endif 22919 #ifdef BCM_WARM_BOOT_SUPPORT 22920 SOC_CONTROL_LOCK(unit); 22921 SOC_CONTROL(unit)->scache_dirty = 1; 22922 SOC_CONTROL_UNLOCK(unit); 22923 #endif 22924 22925 return rv; 22926 22927 cleanup: 22928 22929 /* coverity[negative_returns : FALSE] */ 22930 if (vc_swap_index != -1) { 22931 _bcm_tr_mpls_vc_and_swap_ref_count_adjust (unit, vc_swap_index, -1); 22932 (void)_bcm_tr_mpls_vc_and_swap_table_index_reset (unit, vc_swap_index); 22933 } 22934 return rv; 22935 } 22936 22937 /* 22938 * Function: 22939 * bcm_tr_mpls_swap_nh_info_delete 22940 * Purpose: 22941 * Delete SWAP_LABEL within VC_AND_SWAP_TABLE for a specific EGR_NH Index 22942 * Parameters: 22943 * IN : Unit 22944 * IN : nh_index 22945 * Returns: 22946 * BCM_E_XXX 22947 */ 22948 22949 int 22950 bcm_tr_mpls_swap_nh_info_delete(int unit, int nh_index) 22951 { 22952 int rv = BCM_E_NONE, old_vc_swap_idx = -1; 22953 ing_l3_next_hop_entry_t ing_nh; 22954 egr_l3_next_hop_entry_t egr_nh; 22955 int intf; 22956 int tunnel_id; 22957 22958 BCM_IF_ERROR_RETURN (soc_mem_read(unit, EGR_L3_NEXT_HOPm, 22959 MEM_BLOCK_ANY, nh_index, &egr_nh)); 22960 BCM_IF_ERROR_RETURN (soc_mem_read(unit, ING_L3_NEXT_HOPm, 22961 MEM_BLOCK_ANY, nh_index, &ing_nh)); 22962 22963 if (soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, nh_entry_type_field[unit]) != 0x1) { 22964 return BCM_E_NONE; 22965 } 22966 22967 if (soc_feature(unit, soc_feature_th3_style_simple_mpls)) { 22968 intf = soc_mem_field32_get(unit, EGR_L3_NEXT_HOP_2m, &egr_nh, 22969 INTF_NUMf); 22970 } else if (soc_feature(unit, soc_feature_mpls_enhanced)) { 22971 old_vc_swap_idx = soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, 22972 MPLS__VC_AND_SWAP_INDEXf); 22973 intf = soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, 22974 MPLS__INTF_NUMf); 22975 } else { 22976 old_vc_swap_idx = soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, 22977 VC_AND_SWAP_INDEXf); 22978 22979 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 22980 intf = soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, 22981 L3__INTF_NUMf); 22982 } else { 22983 intf = soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, 22984 INTF_NUMf); 22985 } 22986 } 22987 22988 if (!soc_feature(unit, soc_feature_th3_style_simple_mpls)) { 22989 if (soc_feature(unit, soc_feature_mpls_enhanced)) { 22990 soc_EGR_L3_NEXT_HOPm_field32_set(unit, &egr_nh, 22991 MPLS__VC_AND_SWAP_INDEXf, 22992 0); 22993 } else { 22994 soc_EGR_L3_NEXT_HOPm_field32_set(unit, &egr_nh, 22995 VC_AND_SWAP_INDEXf, 22996 0); 22997 } 22998 } else { 22999 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 23000 &egr_nh, MPLS__MPLS_LABEL_ACTIONf, 0); 23001 } 23002 BCM_IF_ERROR_RETURN (soc_mem_write(unit, EGR_L3_NEXT_HOPm, 23003 MEM_BLOCK_ALL, nh_index, &egr_nh)); 23004 #if defined(BCM_TRIUMPH3_SUPPORT) 23005 if (soc_feature(unit, soc_feature_vc_and_swap_table_overlaid)) { 23006 BCM_IF_ERROR_RETURN ( 23007 _bcm_tr_mpls_vc_and_swap_hash_nhop_delete(unit, 23008 old_vc_swap_idx, 23009 nh_index)); 23010 } 23011 #endif 23012 23013 if (!soc_feature(unit, soc_feature_th3_style_simple_mpls)) { 23014 /* clear VC_AND_SWAP_LABEL entry */ 23015 _bcm_tr_mpls_vc_and_swap_ref_count_adjust (unit, old_vc_swap_idx, -1); 23016 23017 /* Free VC_AND_SWAP_LABEL entry */ 23018 BCM_IF_ERROR_RETURN 23019 (_bcm_tr_mpls_vc_and_swap_table_index_reset (unit, old_vc_swap_idx)); 23020 } 23021 23022 BCM_IF_ERROR_RETURN 23023 (_bcm_xgs3_l3_get_tunnel_id(unit, intf, &tunnel_id)); 23024 if (!tunnel_id) { 23025 23026 soc_mem_field32_set(unit, ING_L3_NEXT_HOPm, 23027 &ing_nh, ENTRY_TYPEf, 0x0); 23028 rv = soc_mem_write (unit, ING_L3_NEXT_HOPm, 23029 MEM_BLOCK_ALL, nh_index, &ing_nh); 23030 } 23031 23032 #ifdef BCM_WARM_BOOT_SUPPORT 23033 SOC_CONTROL_LOCK(unit); 23034 SOC_CONTROL(unit)->scache_dirty = 1; 23035 SOC_CONTROL_UNLOCK(unit); 23036 #endif 23037 23038 return rv; 23039 } 23040 23041 /* 23042 * Function: 23043 * bcm_tr_mpls_swap_nh_info_get 23044 * Purpose: 23045 * Get Label_Swap info within Egress Object for a specific EGR_NH Index 23046 * Parameters: 23047 * IN : Unit 23048 * OUT : Egress object Pointer 23049 * IN : nh_index 23050 * Returns: 23051 * BCM_E_XXX 23052 */ 23053 23054 int 23055 bcm_tr_mpls_swap_nh_info_get(int unit, bcm_l3_egress_t *egr, int nh_index) 23056 { 23057 egr_l3_next_hop_entry_t egr_nh; 23058 egr_mpls_vc_and_swap_label_table_entry_t vc_entry; 23059 int vc_swap_idx, ix; 23060 uint32 label_action = 0; 23061 uint32 label_select = 0; 23062 int vc_data_type = 0; 23063 #if defined(BCM_TRIDENT3_SUPPORT) 23064 uint32 mpls_format[2]; 23065 #endif 23066 23067 BCM_IF_ERROR_RETURN (soc_mem_read(unit, EGR_L3_NEXT_HOPm, MEM_BLOCK_ANY, 23068 nh_index, &egr_nh)); 23069 23070 #if defined(BCM_TOMAHAWK3_SUPPORT) 23071 if (soc_feature(unit, soc_feature_th3_style_simple_mpls)) { 23072 return bcm_th3_mpls_swap_nh_info_get(unit, egr, nh_index); 23073 } 23074 #endif 23075 23076 if (soc_feature(unit, soc_feature_mpls_enhanced)) { 23077 vc_swap_idx = soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, 23078 MPLS__VC_AND_SWAP_INDEXf); 23079 } else { 23080 vc_swap_idx = soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, 23081 VC_AND_SWAP_INDEXf); 23082 } 23083 23084 BCM_IF_ERROR_RETURN (soc_mem_read(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 23085 MEM_BLOCK_ANY, vc_swap_idx, &vc_entry)); 23086 if (SOC_MEM_FIELD_VALID(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 23087 DATA_TYPEf)) { 23088 vc_data_type = soc_mem_field32_get(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 23089 &vc_entry, DATA_TYPEf); 23090 } 23091 23092 if (vc_data_type == _BCM_VC_SWAP_TBL_FLEX_DATA_TYPE) { 23093 #if defined(BCM_TRIDENT3_SUPPORT) 23094 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 23095 sal_memset(mpls_format, 0, sizeof(mpls_format)); 23096 soc_mem_field_get(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 23097 (uint32 *) &vc_entry, 23098 MPLS_PHP__MPLS_ENTRY_0_ACTION_SETf, 23099 (uint32 *) mpls_format); 23100 } 23101 #endif 23102 } 23103 23104 #if defined(BCM_TRIDENT3_SUPPORT) 23105 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 23106 if (MPLS_INFO(unit)->egr_vc_swap_lbl_action != NULL) { 23107 label_action = 23108 MPLS_INFO(unit)->egr_vc_swap_lbl_action[vc_swap_idx]; 23109 } 23110 } else 23111 #endif 23112 { 23113 label_action = soc_mem_field32_get(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 23114 &vc_entry, MPLS_LABEL_ACTIONf); 23115 } 23116 23117 #if defined(BCM_TRIDENT3_SUPPORT) 23118 if(soc_feature(unit, soc_feature_td3_style_mpls)) { 23119 if (vc_data_type == _BCM_VC_SWAP_TBL_FLEX_DATA_TYPE) { 23120 label_select = soc_format_field32_get(unit, 23121 MPLS_ENTRY_ACTION_SETfmt, 23122 (uint32 *)mpls_format, LABEL_SELECTf); 23123 23124 } else { 23125 label_select = soc_mem_field32_get(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 23126 &vc_entry, LABEL_SELECTf); 23127 } 23128 } 23129 #endif 23130 23131 if (label_action == _BCM_MPLS_ACTION_SWAP || 23132 (soc_feature(unit, soc_feature_mpls_swap_label_preserve) && 23133 ((label_action == _BCM_MPLS_ACTION_PRESERVED) || label_select))) { /* SWAP */ 23134 23135 if (vc_data_type == _BCM_VC_SWAP_TBL_FLEX_DATA_TYPE) { 23136 #if defined(BCM_TRIDENT3_SUPPORT) 23137 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 23138 if ((label_action == _BCM_MPLS_ACTION_PRESERVED) || label_select) { 23139 egr->mpls_flags |= BCM_MPLS_EGRESS_LABEL_PRESERVE; 23140 egr->mpls_label = BCM_MPLS_LABEL_INVALID; 23141 } else { 23142 egr->mpls_label = soc_format_field32_get(unit, 23143 MPLS_ENTRY_ACTION_SETfmt, 23144 (uint32 *)mpls_format, MPLS_LABELf); 23145 } 23146 23147 egr->mpls_ttl = soc_format_field32_get(unit, 23148 MPLS_ENTRY_ACTION_SETfmt, 23149 (uint32 *)mpls_format, MPLS_TTLf); 23150 23151 if (egr->mpls_ttl) { 23152 egr->mpls_flags |= BCM_MPLS_EGRESS_LABEL_TTL_SET; 23153 } else { 23154 egr->mpls_flags |= BCM_MPLS_EGRESS_LABEL_TTL_DECREMENT; 23155 } 23156 if (soc_format_field32_get(unit, MPLS_ENTRY_ACTION_SETfmt, 23157 (uint32 *)mpls_format, MPLS_EXP_SELECTf) == 0x0) { 23158 /* Use the specified EXP, PRI and CFI */ 23159 egr->flags |= BCM_MPLS_EGRESS_LABEL_EXP_SET; 23160 egr->flags |= BCM_MPLS_EGRESS_LABEL_PRI_SET; 23161 egr->mpls_exp = 23162 soc_format_field32_get(unit, MPLS_ENTRY_ACTION_SETfmt, 23163 (uint32 *)mpls_format, MPLS_EXPf); 23164 egr->mpls_pkt_pri = 23165 soc_format_field32_get(unit, MPLS_ENTRY_ACTION_SETfmt, 23166 (uint32 *)mpls_format, NEW_PRIf); 23167 egr->mpls_pkt_cfi = 23168 soc_format_field32_get(unit, MPLS_ENTRY_ACTION_SETfmt, 23169 (uint32 *)mpls_format, NEW_CFIf); 23170 } else if (soc_format_field32_get(unit, MPLS_ENTRY_ACTION_SETfmt, 23171 (uint32 *)mpls_format, MPLS_EXP_SELECTf) == 0x1) { 23172 /* Use EXP-map for EXP, PRI and CFI */ 23173 egr->flags |= BCM_MPLS_EGRESS_LABEL_EXP_REMARK; 23174 egr->flags |= BCM_MPLS_EGRESS_LABEL_PRI_REMARK; 23175 ix = soc_format_field32_get(unit, MPLS_ENTRY_ACTION_SETfmt, 23176 (uint32 *)mpls_format, MPLS_EXP_MAPPING_PTRf); 23177 BCM_IF_ERROR_RETURN( 23178 _egr_qos_hw_idx2id(unit, ix, &egr->mpls_qos_map_id)); 23179 23180 } else if (soc_format_field32_get(unit, MPLS_ENTRY_ACTION_SETfmt, 23181 (uint32 *)mpls_format, MPLS_EXP_SELECTf) == 0x3) { 23182 /* Use EXP from incoming MPLS label. If no incoming label, use the specified 23183 * EXP value. Use EXP-map for PRI/CFI. 23184 */ 23185 egr->flags |= BCM_MPLS_EGRESS_LABEL_EXP_COPY; 23186 egr->flags |= BCM_MPLS_EGRESS_LABEL_PRI_REMARK; 23187 egr->mpls_exp = 23188 soc_format_field32_get(unit, MPLS_ENTRY_ACTION_SETfmt, 23189 (uint32 *)mpls_format, MPLS_EXPf); 23190 ix = soc_format_field32_get(unit, MPLS_ENTRY_ACTION_SETfmt, 23191 (uint32 *)mpls_format, MPLS_EXP_MAPPING_PTRf); 23192 23193 BCM_IF_ERROR_RETURN( 23194 _egr_qos_hw_idx2id(unit, ix, &egr->mpls_qos_map_id)); 23195 } 23196 } 23197 #endif 23198 } else { 23199 23200 if (soc_feature(unit, soc_feature_mpls_swap_label_preserve) && 23201 ((label_action == _BCM_MPLS_ACTION_PRESERVED) || label_select)) { 23202 egr->mpls_flags |= BCM_MPLS_EGRESS_LABEL_PRESERVE; 23203 egr->mpls_label = BCM_MPLS_LABEL_INVALID; 23204 } else { 23205 egr->mpls_label = 23206 soc_mem_field32_get(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 23207 &vc_entry, MPLS_LABELf); 23208 } 23209 egr->mpls_ttl = 23210 soc_mem_field32_get(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 23211 &vc_entry, MPLS_TTLf); 23212 if (egr->mpls_ttl) { 23213 egr->mpls_flags |= BCM_MPLS_EGRESS_LABEL_TTL_SET; 23214 } else { 23215 egr->mpls_flags |= BCM_MPLS_EGRESS_LABEL_TTL_DECREMENT; 23216 } 23217 if (soc_mem_field32_get(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 23218 &vc_entry, MPLS_EXP_SELECTf) == 0x0) { 23219 /* Use the specified EXP, PRI and CFI */ 23220 egr->mpls_flags |= BCM_MPLS_EGRESS_LABEL_EXP_SET; 23221 egr->mpls_flags |= BCM_MPLS_EGRESS_LABEL_PRI_SET; 23222 egr->mpls_exp = 23223 soc_mem_field32_get(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 23224 &vc_entry, MPLS_EXPf); 23225 egr->mpls_pkt_pri = 23226 soc_mem_field32_get(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 23227 &vc_entry, NEW_PRIf); 23228 egr->mpls_pkt_cfi = 23229 soc_mem_field32_get(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 23230 &vc_entry, NEW_CFIf); 23231 } else if (soc_mem_field32_get(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 23232 &vc_entry, MPLS_EXP_SELECTf) == 0x1) { 23233 /* Use EXP-map for EXP, PRI and CFI */ 23234 egr->mpls_flags |= BCM_MPLS_EGRESS_LABEL_EXP_REMARK; 23235 egr->mpls_flags |= BCM_MPLS_EGRESS_LABEL_PRI_REMARK; 23236 ix = soc_mem_field32_get(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 23237 &vc_entry, MPLS_EXP_MAPPING_PTRf); 23238 BCM_IF_ERROR_RETURN( 23239 _egr_qos_hw_idx2id(unit, ix, &egr->mpls_qos_map_id)); 23240 } else if (soc_mem_field32_get(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 23241 &vc_entry, MPLS_EXP_SELECTf) == 0x3) { 23242 /* Use EXP from incoming MPLS label. If no incoming label, use the specified 23243 * EXP value. Use EXP-map for PRI/CFI. 23244 */ 23245 egr->mpls_flags |= BCM_MPLS_EGRESS_LABEL_EXP_COPY; 23246 egr->mpls_flags |= BCM_MPLS_EGRESS_LABEL_PRI_REMARK; 23247 egr->mpls_exp = 23248 soc_mem_field32_get(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 23249 &vc_entry, MPLS_EXPf); 23250 ix = soc_mem_field32_get(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 23251 &vc_entry, MPLS_EXP_MAPPING_PTRf); 23252 BCM_IF_ERROR_RETURN( 23253 _egr_qos_hw_idx2id(unit, ix, &egr->mpls_qos_map_id)); 23254 } 23255 } 23256 #if defined(BCM_TOMAHAWK2_SUPPORT) 23257 if (soc_feature(unit, soc_feature_mpls_ecn) && 23258 !soc_feature(unit, soc_feature_intcn_to_exp_nosupport)) { 23259 int ecn_map_id; 23260 int ecn_map_pri; 23261 int ecn_map_hw_idx; 23262 int rv; 23263 ecn_map_hw_idx = soc_mem_field32_get(unit, 23264 EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, &vc_entry, 23265 INT_CN_TO_EXP_MAPPING_PTRf); 23266 ecn_map_pri = soc_mem_field32_get(unit, 23267 EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, &vc_entry, 23268 INT_CN_TO_EXP_PRIORITYf); 23269 rv = bcmi_ecn_map_hw_idx2id(unit, ecn_map_hw_idx, 23270 _BCM_XGS5_MPLS_ECN_MAP_TYPE_INTCN2EXP, 23271 &ecn_map_id); 23272 if (BCM_SUCCESS(rv)) { 23273 egr->mpls_flags |= BCM_MPLS_EGRESS_LABEL_INT_CN_TO_EXP_MAP; 23274 egr->mpls_ecn_map_id = ecn_map_id; 23275 if (ecn_map_pri) { 23276 egr->mpls_flags |= BCM_MPLS_EGRESS_LABEL_ECN_EXP_MAP_TRUST; 23277 } 23278 } 23279 } 23280 #endif 23281 } else { 23282 egr->mpls_label = BCM_MPLS_LABEL_INVALID; 23283 } 23284 return BCM_E_NONE; 23285 } 23286 23287 /* 23288 * Function: 23289 * bcm_tr_mpls_l3_nh_info_add 23290 * Purpose: 23291 * Add SWAP_LABEL within VC_AND_SWAP_TABLE for a specific EGR_NH Index 23292 * Parameters: 23293 * IN : Unit 23294 * IN/OUT : Tunnel Switch Pointer 23295 * IN : nh_index 23296 * Returns: 23297 * BCM_E_XXX 23298 */ 23299 23300 int 23301 bcm_tr_mpls_l3_nh_info_add(int unit, bcm_mpls_tunnel_switch_t *info, int *nh_index) 23302 { 23303 initial_ing_l3_next_hop_entry_t initial_ing_nh; 23304 ing_l3_next_hop_entry_t ing_nh; 23305 egr_l3_next_hop_entry_t egr_nh; 23306 #if defined(BCM_TOMAHAWK3_SUPPORT) 23307 egr_l3_next_hop_2_entry_t egr_nh_2; 23308 #endif 23309 egr_mac_da_profile_entry_t macda; 23310 egr_mpls_vc_and_swap_label_table_entry_t vc_entry; 23311 _bcm_tr_ing_nh_info_t ing_nh_info; 23312 _bcm_tr_egr_nh_info_t egr_nh_info; 23313 bcm_l3_egress_t nh_info, nh_obj; 23314 bcm_module_t mod_out; 23315 bcm_port_t port_out; 23316 uint32 nh_flags, macda_index; 23317 int rv, temp_nh_index = -1, num_vc=0; 23318 void *entries[1]; 23319 int num_mpls_map, hw_map_idx; 23320 uint32 mpath_flag=0; 23321 23322 /* Initialize values */ 23323 if (info->mtu != 0) { 23324 ing_nh_info.mtu = info->mtu; 23325 } else { 23326 ing_nh_info.mtu = 0x3FFF; 23327 } 23328 23329 ing_nh_info.port = -1; 23330 ing_nh_info.module = -1; 23331 ing_nh_info.trunk = -1; 23332 ing_nh_info.qtag = -1; 23333 ing_nh_info.tag_type = -1; 23334 23335 egr_nh_info.dvp = -1; /* Not applicable */ 23336 egr_nh_info.dvp_is_network = -1; /* Not applicable */ 23337 egr_nh_info.entry_type = -1; 23338 egr_nh_info.sd_tag_action_present = -1; 23339 egr_nh_info.sd_tag_action_not_present = -1; 23340 egr_nh_info.intf_num = -1; 23341 egr_nh_info.sd_tag_vlan = -1; 23342 egr_nh_info.macda_index = -1; 23343 egr_nh_info.vc_swap_index = -1; 23344 egr_nh_info.pw_init_cnt = -1; 23345 23346 23347 /* 23348 * Get egress next-hop index from egress object and 23349 * increment egress object reference count. 23350 */ 23351 rv = bcm_xgs3_get_nh_from_egress_object(unit, info->egress_if, 23352 &mpath_flag, 1, &temp_nh_index); 23353 _BCM_MPLS_CLEANUP(rv); 23354 bcm_l3_egress_t_init(&nh_info); 23355 23356 23357 /* Get egress next-hop info from the egress object */ 23358 rv = bcm_xgs3_nh_get(unit, temp_nh_index, &nh_info); 23359 _BCM_MPLS_CLEANUP(rv); 23360 23361 #if defined(BCM_KATANA_SUPPORT) 23362 if (SOC_IS_KATANAX(unit)) { 23363 ing_l3_next_hop_entry_t in_nh; 23364 23365 rv = soc_mem_read (unit, ING_L3_NEXT_HOPm, 23366 MEM_BLOCK_ALL, temp_nh_index, &in_nh); 23367 _BCM_MPLS_CLEANUP(rv); 23368 ing_nh_info.qtag = soc_ING_L3_NEXT_HOPm_field32_get(unit, &in_nh, 23369 EH_QUEUE_TAGf); 23370 ing_nh_info.tag_type = soc_ING_L3_NEXT_HOPm_field32_get(unit, 23371 &in_nh, 23372 EH_TAG_TYPEf); 23373 } 23374 #endif 23375 23376 /* Check if Egress Object contains a valid SWAP Label */ 23377 if (BCM_XGS3_L3_MPLS_LBL_VALID(nh_info.mpls_label)) { 23378 return BCM_E_CONFIG; 23379 } 23380 23381 /* 23382 * Indexes in the first half of EGR_MPLS_VC_AND_SWAP_LABEL_TABLE 23383 * also get used as the index into the EGR_PW_INIT_COUNTERS table. 23384 * Set num_vc to half the EGR_MPLS_VC_AND_SWAP_LABEL_TABLE size. 23385 * Choose from the non-counted section (second half) so the counted 23386 * section is available for VPWS. 23387 */ 23388 if (SOC_MEM_IS_VALID(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm)) { 23389 num_vc = soc_mem_index_count(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm); 23390 num_vc /= 2; 23391 } 23392 23393 /* 23394 * For SWAP operation, we need to allocate a unique next-hop 23395 * index and populate the swap label info. Copy the destination 23396 * port information from the egress object. 23397 * 23398 * Allocate a next-hop entry. By calling bcm_xgs3_nh_add() 23399 * with _BCM_L3_SHR_WRITE_DISABLE flag, a next-hop index is 23400 * allocated but nothing is written to hardware. The "nh_info" 23401 * in this case is not used, so just set to all zeros. 23402 */ 23403 bcm_l3_egress_t_init(&nh_obj); 23404 23405 nh_flags = _BCM_L3_SHR_MATCH_DISABLE | _BCM_L3_SHR_WRITE_DISABLE; 23406 BCM_IF_ERROR_RETURN(bcm_xgs3_nh_add(unit, nh_flags, &nh_obj, nh_index)); 23407 23408 rv = _bcm_tr_mpls_add_egrNhop (unit, info->egress_if); 23409 _BCM_MPLS_CLEANUP(rv); 23410 23411 rv = _bcm_tr_mpls_add_vp_nh (unit, info->egress_if, *nh_index); 23412 _BCM_MPLS_CLEANUP(rv); 23413 23414 /* Copy the destination port information. */ 23415 if (nh_info.flags & BCM_L3_TGID) { 23416 ing_nh_info.port = -1; 23417 ing_nh_info.module = -1; 23418 ing_nh_info.trunk = nh_info.trunk; 23419 } else { 23420 BCM_IF_ERROR_RETURN 23421 (_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_SET, nh_info.module, nh_info.port, 23422 &mod_out, &port_out)); 23423 ing_nh_info.port = port_out; 23424 ing_nh_info.module = mod_out; 23425 ing_nh_info.trunk = -1; 23426 } 23427 egr_nh_info.intf_num = nh_info.intf; 23428 egr_nh_info.entry_type = 0x1; /* MPLS_MACDA_PROFILE */ 23429 23430 sal_memset(&macda, 0, sizeof(egr_mac_da_profile_entry_t)); 23431 soc_mem_mac_addr_set(unit, EGR_MAC_DA_PROFILEm, 23432 &macda, MAC_ADDRESSf, nh_info.mac_addr); 23433 entries[0] = &macda; 23434 rv = _bcm_mac_da_profile_entry_add(unit, entries, 1, &macda_index); 23435 egr_nh_info.macda_index = macda_index; 23436 _BCM_MPLS_CLEANUP(rv); 23437 23438 if (!soc_feature(unit, soc_feature_th3_style_simple_mpls)) { 23439 rv = _bcm_tr_mpls_get_vc_and_swap_table_index(unit, 0, NULL, info, NULL, 23440 NULL, 23441 _BCM_MPLS_EGRESS_LABEL_PRESERVE(unit,info->egress_label.flags)? 23442 _BCM_MPLS_ACTION_PRESERVED : _BCM_MPLS_ACTION_SWAP, 23443 &egr_nh_info.vc_swap_index); 23444 23445 23446 _BCM_MPLS_CLEANUP(rv); 23447 } 23448 23449 /* Retrieve hardware index for mapping pointer */ 23450 num_mpls_map = soc_mem_index_count(unit, EGR_MPLS_EXP_MAPPING_1m) / 64; 23451 23452 if (info->egress_label.qos_map_id == 0) { 23453 hw_map_idx = 0; /* use default */ 23454 } else { 23455 BCM_IF_ERROR_RETURN(_egr_qos_id2hw_idx(unit, 23456 info->egress_label.qos_map_id,&hw_map_idx)); 23457 } 23458 if (hw_map_idx < 0 || hw_map_idx >= num_mpls_map) { 23459 rv = BCM_E_PARAM; 23460 goto cleanup; 23461 } 23462 23463 23464 23465 /* Write EGR_L3_NEXT_HOP entry */ 23466 sal_memset(&egr_nh, 0, sizeof(egr_l3_next_hop_entry_t)); 23467 23468 /* Program the MPLS_VC_AND_SWAP table entry */ 23469 if (!soc_feature(unit, soc_feature_th3_style_simple_mpls)) { 23470 rv = _bcm_tr_mpls_vc_and_swap_table_entry_set(unit, NULL, info, NULL, 23471 _BCM_MPLS_EGRESS_LABEL_PRESERVE(unit, info->egress_label.flags) ? 23472 _BCM_MPLS_ACTION_PRESERVED : _BCM_MPLS_ACTION_SWAP, 23473 &vc_entry, hw_map_idx, egr_nh_info.vc_swap_index); 23474 _BCM_MPLS_CLEANUP(rv); 23475 23476 rv = soc_mem_write(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 23477 MEM_BLOCK_ALL, egr_nh_info.vc_swap_index, 23478 &vc_entry); 23479 _BCM_MPLS_CLEANUP(rv); 23480 } 23481 #if defined(BCM_TOMAHAWK3_SUPPORT) 23482 else { 23483 if ((info->egress_label.flags & BCM_MPLS_EGRESS_LABEL_INT_CN_TO_EXP_MAP) && 23484 (info->egress_label.int_cn_map_id != ECN_MAP_ID_INVALID) && 23485 (!soc_feature(unit, soc_feature_intcn_to_exp_nosupport))) { 23486 int ecn_map_index; 23487 int ecn_map_type; 23488 int ecn_map_num; 23489 int ecn_map_hw_idx; 23490 ecn_map_type = info->egress_label.int_cn_map_id & 23491 _BCM_XGS5_MPLS_ECN_MAP_TYPE_MASK; 23492 ecn_map_index = info->egress_label.int_cn_map_id & 23493 _BCM_XGS5_MPLS_ECN_MAP_NUM_MASK; 23494 ecn_map_num = 23495 soc_mem_index_count(unit, EGR_INT_CN_TO_EXP_MAPPING_TABLEm) / 23496 _BCM_ECN_MAX_ENTRIES_PER_MAP; 23497 if (ecn_map_type != _BCM_XGS5_MPLS_ECN_MAP_TYPE_INTCN2EXP) { 23498 return BCM_E_PARAM; 23499 } 23500 if (ecn_map_index >= ecn_map_num) { 23501 return BCM_E_PARAM; 23502 } 23503 BCM_IF_ERROR_RETURN( 23504 bcmi_ecn_map_id2hw_idx(unit, info->egress_label.int_cn_map_id, &ecn_map_hw_idx)); 23505 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 23506 &egr_nh, MPLS__INT_CN_TO_EXP_MAPPING_PTRf, 23507 ecn_map_hw_idx); 23508 if (info->egress_label.flags & BCM_MPLS_EGRESS_LABEL_ECN_EXP_MAP_TRUST) { 23509 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 23510 &egr_nh, MPLS__INT_CN_TO_EXP_PRIORITYf, 1); 23511 23512 } else { 23513 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 23514 &egr_nh, MPLS__INT_CN_TO_EXP_PRIORITYf, 0); 23515 23516 } 23517 } 23518 if ((info->egress_label.flags & BCM_MPLS_EGRESS_LABEL_ECN_TO_EXP_MAP) && 23519 (info->egress_label.ecn_map_id != ECN_MAP_ID_INVALID)) { 23520 int ecn_map_index; 23521 int ecn_map_type; 23522 int ecn_map_num; 23523 int ecn_map_hw_idx; 23524 soc_mem_t mem; 23525 soc_field_t ipecn_to_exp_ptr; 23526 soc_field_t ipecn_to_exp_priority; 23527 ecn_map_type = info->egress_label.ecn_map_id & 23528 _BCM_XGS5_MPLS_ECN_MAP_TYPE_MASK; 23529 ecn_map_index = info->egress_label.ecn_map_id & 23530 _BCM_XGS5_MPLS_ECN_MAP_NUM_MASK; 23531 { 23532 mem = EGR_IP_ECN_TO_EXP_MAPPING_TABLEm; 23533 } 23534 ecn_map_num = 23535 soc_mem_index_count(unit, mem) / 23536 _BCM_ECN_MAX_ENTRIES_PER_MAP; 23537 if (ecn_map_type != _BCM_XGS5_MPLS_ECN_MAP_TYPE_ECN2EXP) { 23538 return BCM_E_PARAM; 23539 } 23540 if (ecn_map_index >= ecn_map_num) { 23541 return BCM_E_PARAM; 23542 } 23543 23544 BCM_IF_ERROR_RETURN( 23545 bcmi_ecn_map_id2hw_idx(unit, info->egress_label.ecn_map_id, &ecn_map_hw_idx)); 23546 23547 ipecn_to_exp_ptr = MPLS__IP_ECN_TO_EXP_MAPPING_PTRf; 23548 ipecn_to_exp_priority = MPLS__IP_ECN_TO_EXP_PRIORITYf; 23549 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 23550 &egr_nh, ipecn_to_exp_ptr, 23551 ecn_map_hw_idx); 23552 if (info->egress_label.flags & BCM_MPLS_EGRESS_LABEL_ECN_EXP_MAP_TRUST) { 23553 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 23554 &egr_nh, ipecn_to_exp_priority, 1); 23555 23556 } else { 23557 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 23558 &egr_nh, ipecn_to_exp_priority, 0); 23559 } 23560 } 23561 } 23562 #endif 23563 if (egr_nh_info.entry_type == 0x1) { 23564 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 23565 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 23566 &egr_nh, L3__INTF_NUMf, egr_nh_info.intf_num); 23567 } else 23568 #if defined(BCM_TOMAHAWK3_SUPPORT) 23569 if (SOC_MEM_IS_VALID(unit, EGR_L3_NEXT_HOP_2m)) { 23570 sal_memset(&egr_nh_2, 0, sizeof(egr_l3_next_hop_2_entry_t)); 23571 soc_mem_field32_set(unit, EGR_L3_NEXT_HOP_2m, 23572 &egr_nh_2, INTF_NUMf, egr_nh_info.intf_num); 23573 } else 23574 #endif 23575 { 23576 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 23577 &egr_nh, INTF_NUMf, egr_nh_info.intf_num); 23578 } 23579 23580 if (egr_nh_info.vc_swap_index != -1) { 23581 if (soc_feature(unit, soc_feature_mpls_enhanced)) { 23582 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 23583 &egr_nh, MPLS__VC_AND_SWAP_INDEXf, 23584 egr_nh_info.vc_swap_index); 23585 } else { 23586 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 23587 &egr_nh, VC_AND_SWAP_INDEXf, 23588 egr_nh_info.vc_swap_index); 23589 } 23590 } 23591 23592 if (egr_nh_info.macda_index != -1) { 23593 if (soc_feature(unit, soc_feature_mpls_enhanced) || 23594 soc_feature(unit, soc_feature_th3_style_simple_mpls)) { 23595 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 23596 &egr_nh, MPLS__MAC_DA_PROFILE_INDEXf, 23597 egr_nh_info.macda_index); 23598 } else { 23599 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 23600 &egr_nh, MAC_DA_PROFILE_INDEXf, 23601 egr_nh_info.macda_index); 23602 } 23603 } 23604 23605 if (SOC_MEM_FIELD_VALID(unit, EGR_L3_NEXT_HOPm,MPLS__HG_MODIFY_ENABLEf)) { 23606 if (soc_feature(unit, soc_feature_mpls_enhanced)) { 23607 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 23608 &egr_nh, MPLS__HG_MODIFY_ENABLEf, 0x1); 23609 /* Enable HG.L3_bit */ 23610 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 23611 &egr_nh, MPLS__HG_L3_OVERRIDEf, 0x1); 23612 23613 } else { 23614 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 23615 &egr_nh, HG_MODIFY_ENABLEf, 0x1); 23616 /* Enable HG.L3_bit */ 23617 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 23618 &egr_nh, HG_L3_OVERRIDEf, 0x1); 23619 } 23620 } 23621 23622 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) 23623 if (soc_feature(unit, soc_feature_mpls_nh_ttl_control)) { 23624 if (info->flags & BCM_MPLS_SWITCH_KEEP_TTL) { 23625 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 23626 MPLS__DISABLE_TTL_DECREMENTf, 1); 23627 } 23628 } 23629 23630 if (soc_mem_field_valid(unit, EGR_L3_NEXT_HOPm, 23631 MPLS__DO_EVXLT_AFTER_TUNNEL_ENCAPf)) { 23632 if (info->flags2 & 23633 BCM_MPLS_SWITCH2_TUNNEL_HEADER_EGRESS_VLAN_TRANSLATION) { 23634 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 23635 MPLS__DO_EVXLT_AFTER_TUNNEL_ENCAPf, 1); 23636 } 23637 } 23638 #endif 23639 #if defined(BCM_TOMAHAWK3_SUPPORT) 23640 if (soc_feature(unit, soc_feature_th3_style_simple_mpls)) { 23641 bcm_l3_egress_t egr; 23642 /* 23643 * Get egress object information. 23644 */ 23645 BCM_IF_ERROR_RETURN(bcm_xgs3_nh_get(unit, *nh_index, &egr)); 23646 23647 rv = _bcm_th3_mpls_egr_nh_label_set(unit, info, &egr, 23648 _BCM_MPLS_EGRESS_LABEL_PRESERVE(unit, 23649 info->egress_label.flags) ? _BCM_MPLS_ACTION_PRESERVED : 23650 _BCM_MPLS_ACTION_SWAP, hw_map_idx, &egr_nh); 23651 } 23652 #endif 23653 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 23654 nh_entry_type_field[unit], egr_nh_info.entry_type); 23655 23656 rv = soc_mem_write(unit, EGR_L3_NEXT_HOPm, 23657 MEM_BLOCK_ALL, *nh_index, &egr_nh); 23658 _BCM_MPLS_CLEANUP(rv); 23659 #if defined(BCM_TOMAHAWK3_SUPPORT) 23660 if (SOC_MEM_IS_VALID(unit, EGR_L3_NEXT_HOP_2m)) { 23661 rv = soc_mem_write(unit, EGR_L3_NEXT_HOP_2m, 23662 MEM_BLOCK_ALL, *nh_index, &egr_nh_2); 23663 _BCM_MPLS_CLEANUP(rv); 23664 } 23665 #endif 23666 } 23667 23668 /* Write ING_L3_NEXT_HOP entry */ 23669 sal_memset(&ing_nh, 0, sizeof(ing_l3_next_hop_entry_t)); 23670 if (ing_nh_info.trunk == -1) { 23671 if (soc_feature(unit, soc_feature_generic_dest)) { 23672 soc_mem_field32_dest_set(unit, ING_L3_NEXT_HOPm, &ing_nh, 23673 DESTINATIONf, SOC_MEM_FIF_DEST_DGPP, 23674 ing_nh_info.module << SOC_MEM_FIF_DGPP_MOD_ID_SHIFT_BITS | ing_nh_info.port); 23675 } else { 23676 soc_mem_field32_set(unit, ING_L3_NEXT_HOPm, 23677 &ing_nh, PORT_NUMf, ing_nh_info.port); 23678 if (SOC_MEM_FIELD_VALID(unit, ING_L3_NEXT_HOPm, MODULE_IDf)) { 23679 soc_mem_field32_set(unit, ING_L3_NEXT_HOPm, 23680 &ing_nh, MODULE_IDf, ing_nh_info.module); 23681 } 23682 } 23683 } else { 23684 if (soc_feature(unit, soc_feature_generic_dest)) { 23685 soc_mem_field32_dest_set(unit, ING_L3_NEXT_HOPm, &ing_nh, 23686 DESTINATIONf, SOC_MEM_FIF_DEST_LAG, ing_nh_info.trunk); 23687 } else { 23688 soc_mem_field32_set(unit, ING_L3_NEXT_HOPm, 23689 &ing_nh, Tf, 1); 23690 soc_mem_field32_set(unit, ING_L3_NEXT_HOPm, 23691 &ing_nh, TGIDf, ing_nh_info.trunk); 23692 } 23693 } 23694 23695 if ((ing_nh_info.qtag != -1) && 23696 SOC_MEM_FIELD_VALID(unit, ING_L3_NEXT_HOPm,EH_QUEUE_TAGf)) { 23697 soc_mem_field32_set(unit, ING_L3_NEXT_HOPm, &ing_nh, 23698 EH_QUEUE_TAGf, ing_nh_info.qtag); 23699 } 23700 if ((ing_nh_info.tag_type != -1) && 23701 SOC_MEM_FIELD_VALID(unit, ING_L3_NEXT_HOPm,EH_TAG_TYPEf)) { 23702 soc_mem_field32_set(unit, ING_L3_NEXT_HOPm, &ing_nh, 23703 EH_TAG_TYPEf, ing_nh_info.tag_type); 23704 } 23705 23706 23707 soc_mem_field32_set(unit, ING_L3_NEXT_HOPm, 23708 &ing_nh, ENTRY_TYPEf, 0x1); /* MPLS L3_OIF */ 23709 rv = soc_mem_write (unit, ING_L3_NEXT_HOPm, 23710 MEM_BLOCK_ALL, *nh_index, &ing_nh); 23711 _BCM_MPLS_CLEANUP(rv); 23712 23713 if (SOC_MEM_IS_VALID(unit, INITIAL_ING_L3_NEXT_HOPm)) { 23714 /* Write INITIAL_ING_L3_NEXT_HOP entry */ 23715 sal_memset(&initial_ing_nh, 0, sizeof(initial_ing_l3_next_hop_entry_t)); 23716 if (ing_nh_info.trunk == -1) { 23717 if (soc_feature(unit, soc_feature_generic_dest)) { 23718 soc_mem_field32_dest_set(unit, INITIAL_ING_L3_NEXT_HOPm, &initial_ing_nh, 23719 DESTINATIONf, SOC_MEM_FIF_DEST_DGPP, 23720 ing_nh_info.module << SOC_MEM_FIF_DGPP_MOD_ID_SHIFT_BITS | ing_nh_info.port); 23721 } else { 23722 soc_mem_field32_set(unit, INITIAL_ING_L3_NEXT_HOPm, 23723 &initial_ing_nh, PORT_NUMf, ing_nh_info.port); 23724 if (SOC_MEM_FIELD_VALID(unit, INITIAL_ING_L3_NEXT_HOPm, MODULE_IDf)) { 23725 soc_mem_field32_set(unit, INITIAL_ING_L3_NEXT_HOPm, 23726 &initial_ing_nh, MODULE_IDf, ing_nh_info.module); 23727 } 23728 } 23729 } else { 23730 if (soc_feature(unit, soc_feature_generic_dest)) { 23731 soc_mem_field32_dest_set(unit, INITIAL_ING_L3_NEXT_HOPm, &initial_ing_nh, 23732 DESTINATIONf, SOC_MEM_FIF_DEST_LAG, ing_nh_info.trunk); 23733 } else { 23734 soc_mem_field32_set(unit, INITIAL_ING_L3_NEXT_HOPm, 23735 &initial_ing_nh, Tf, 1); 23736 soc_mem_field32_set(unit, INITIAL_ING_L3_NEXT_HOPm, 23737 &initial_ing_nh, TGIDf, ing_nh_info.trunk); 23738 } 23739 } 23740 rv = soc_mem_write(unit, INITIAL_ING_L3_NEXT_HOPm, 23741 MEM_BLOCK_ALL, *nh_index, &initial_ing_nh); 23742 _BCM_MPLS_CLEANUP(rv); 23743 } 23744 #if defined(BCM_TRIUMPH3_SUPPORT) 23745 if (soc_feature(unit, soc_feature_vc_and_swap_table_overlaid)) { 23746 rv = _bcm_tr_mpls_vc_and_swap_hash_nhop_add(unit, 23747 egr_nh_info.vc_swap_index, 23748 *nh_index); 23749 _BCM_MPLS_CLEANUP(rv); 23750 } 23751 #endif 23752 return rv; 23753 23754 cleanup: 23755 (void) bcm_xgs3_nh_del(unit, _BCM_L3_SHR_WRITE_DISABLE, *nh_index); 23756 23757 if (temp_nh_index != -1) { 23758 (void) bcm_xgs3_nh_del(unit, 0, temp_nh_index); 23759 } 23760 if (egr_nh_info.macda_index != -1) { 23761 _bcm_mac_da_profile_entry_delete(unit, egr_nh_info.macda_index); 23762 } 23763 23764 if (egr_nh_info.vc_swap_index >= 0) { 23765 _bcm_tr_mpls_vc_and_swap_ref_count_adjust (unit, 23766 egr_nh_info.vc_swap_index, -1); 23767 /* Free VC_AND_SWAP_LABEL entry */ 23768 (void)_bcm_tr_mpls_vc_and_swap_table_index_reset (unit, 23769 egr_nh_info.vc_swap_index); 23770 } 23771 return rv; 23772 } 23773 23774 /* 23775 * Function: 23776 * bcm_tr_mpls_l3_nh_info_delete 23777 * Purpose: 23778 * Delete SWAP_LABEL within VC_AND_SWAP_TABLE for a specific EGR_NH Index 23779 * Parameters: 23780 * IN : Unit 23781 * IN : nh_index 23782 * Returns: 23783 * BCM_E_XXX 23784 */ 23785 23786 int 23787 bcm_tr_mpls_l3_nh_info_delete(int unit, int nh_index) 23788 { 23789 int rv, old_macda_idx = -1, old_vc_swap_idx = -1; 23790 bcm_if_t old_egress_if = 0; 23791 initial_ing_l3_next_hop_entry_t initial_ing_nh; 23792 ing_l3_next_hop_entry_t ing_nh; 23793 egr_l3_next_hop_entry_t egr_nh; 23794 23795 BCM_IF_ERROR_RETURN (soc_mem_read(unit, EGR_L3_NEXT_HOPm, 23796 MEM_BLOCK_ANY, nh_index, &egr_nh)); 23797 BCM_IF_ERROR_RETURN (soc_mem_read(unit, ING_L3_NEXT_HOPm, 23798 MEM_BLOCK_ANY, nh_index, &ing_nh)); 23799 if (SOC_MEM_IS_VALID(unit, INITIAL_ING_L3_NEXT_HOPm)) { 23800 BCM_IF_ERROR_RETURN (soc_mem_read(unit, INITIAL_ING_L3_NEXT_HOPm, 23801 MEM_BLOCK_ANY, nh_index, &initial_ing_nh)); 23802 } 23803 23804 if (soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, nh_entry_type_field[unit]) != 0x1) { 23805 return BCM_E_NOT_FOUND; 23806 } 23807 23808 if (soc_feature(unit, soc_feature_mpls_enhanced)) { 23809 old_macda_idx = soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, 23810 MPLS__MAC_DA_PROFILE_INDEXf); 23811 } else { 23812 old_macda_idx = soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, 23813 MAC_DA_PROFILE_INDEXf); 23814 } 23815 23816 if (!soc_feature(unit, soc_feature_th3_style_simple_mpls)) { 23817 if (soc_feature(unit, soc_feature_mpls_enhanced)) { 23818 old_vc_swap_idx = soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, 23819 MPLS__VC_AND_SWAP_INDEXf); 23820 } else { 23821 old_vc_swap_idx = soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, 23822 VC_AND_SWAP_INDEXf); 23823 } 23824 } 23825 /* Find the tunnel_if */ 23826 rv = bcm_tr_mpls_get_vp_nh (unit, (bcm_if_t) nh_index, &old_egress_if); 23827 BCM_IF_ERROR_RETURN (rv); 23828 23829 /* Clear EGR_L3_NEXT_HOP entry */ 23830 sal_memset(&egr_nh, 0, sizeof(egr_l3_next_hop_entry_t)); 23831 BCM_IF_ERROR_RETURN (soc_mem_write(unit, EGR_L3_NEXT_HOPm, 23832 MEM_BLOCK_ALL, nh_index, &egr_nh)); 23833 23834 /* Clear ING_L3_NEXT_HOP entry */ 23835 sal_memset(&ing_nh, 0, sizeof(ing_l3_next_hop_entry_t)); 23836 BCM_IF_ERROR_RETURN (soc_mem_write (unit, ING_L3_NEXT_HOPm, 23837 MEM_BLOCK_ALL, nh_index, &ing_nh)); 23838 23839 /* Clear INITIAL_ING_L3_NEXT_HOP entry */ 23840 if (SOC_MEM_IS_VALID(unit, INITIAL_ING_L3_NEXT_HOPm)) { 23841 sal_memset(&initial_ing_nh, 0, sizeof(initial_ing_l3_next_hop_entry_t)); 23842 BCM_IF_ERROR_RETURN (soc_mem_write(unit, INITIAL_ING_L3_NEXT_HOPm, 23843 MEM_BLOCK_ALL, nh_index, &initial_ing_nh)); 23844 } 23845 23846 #if defined(BCM_TRIUMPH3_SUPPORT) 23847 if (soc_feature(unit, soc_feature_vc_and_swap_table_overlaid)) { 23848 BCM_IF_ERROR_RETURN( 23849 _bcm_tr_mpls_vc_and_swap_hash_nhop_delete(unit, 23850 old_vc_swap_idx, 23851 nh_index)); 23852 } 23853 #endif 23854 23855 if (!soc_feature(unit, soc_feature_th3_style_simple_mpls)) { 23856 /* clear VC_AND_SWAP_LABEL entry */ 23857 _bcm_tr_mpls_vc_and_swap_ref_count_adjust (unit, old_vc_swap_idx, -1); 23858 23859 /* Free VC_AND_SWAP_LABEL entry */ 23860 BCM_IF_ERROR_RETURN 23861 (_bcm_tr_mpls_vc_and_swap_table_index_reset (unit, old_vc_swap_idx)); 23862 } 23863 23864 /* Delete old MAC profile reference */ 23865 rv = _bcm_mac_da_profile_entry_delete(unit, old_macda_idx); 23866 BCM_IF_ERROR_RETURN(rv); 23867 23868 /* Delete egress_if next-hop reference */ 23869 rv = bcm_xgs3_nh_del(unit, 0, (old_egress_if - BCM_XGS3_EGRESS_IDX_MIN(unit))); 23870 BCM_IF_ERROR_RETURN(rv); 23871 23872 if (!soc_feature(unit, soc_feature_th3_style_simple_mpls)) { 23873 BCM_IF_ERROR_RETURN(_bcm_tr_mpls_delete_vp_nh ( unit, nh_index, old_egress_if )); 23874 } 23875 23876 /* Free the next-hop entry. */ 23877 rv = bcm_xgs3_nh_del(unit, _BCM_L3_SHR_WRITE_DISABLE, nh_index); 23878 return rv; 23879 } 23880 23881 /* 23882 * Function: 23883 * bcm_tr_mpls_l3_nh_info_get 23884 * Purpose: 23885 * Get Tunnel_switch info for a specific EGR_NH Index 23886 * Parameters: 23887 * IN : Unit 23888 * OUT : Tunnel switch object pointer 23889 * IN : nh_index 23890 * Returns: 23891 * BCM_E_XXX 23892 */ 23893 23894 int 23895 bcm_tr_mpls_l3_nh_info_get(int unit, bcm_mpls_tunnel_switch_t *info, int nh_index) 23896 { 23897 egr_l3_next_hop_entry_t egr_nh; 23898 egr_mpls_vc_and_swap_label_table_entry_t vc_entry; 23899 int vc_swap_idx, ix; 23900 int vc_data_type = 0; 23901 #if defined(BCM_TOMAHAWK2_SUPPORT) || defined(BCM_TRIDENT3_SUPPORT) 23902 int ecn_map_index; 23903 int ecn_map_pri; 23904 #endif 23905 #ifdef BCM_TRIDENT3_SUPPORT 23906 uint32 mpls_format[2]; 23907 int label_action = 0; 23908 #endif 23909 23910 info->egress_if = nh_index + BCM_XGS3_EGRESS_IDX_MIN(unit); 23911 23912 BCM_IF_ERROR_RETURN (soc_mem_read(unit, EGR_L3_NEXT_HOPm, MEM_BLOCK_ANY, 23913 nh_index, &egr_nh)); 23914 23915 #if defined(BCM_TOMAHAWK3_SUPPORT) 23916 if (soc_feature(unit, soc_feature_th3_style_simple_mpls)) { 23917 return bcm_th3_mpls_l3_nh_info_get(unit, info, nh_index); 23918 } 23919 #endif 23920 if (soc_feature(unit, soc_feature_mpls_enhanced)) { 23921 vc_swap_idx = soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, 23922 MPLS__VC_AND_SWAP_INDEXf); 23923 } else { 23924 vc_swap_idx = soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, 23925 VC_AND_SWAP_INDEXf); 23926 } 23927 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) 23928 if (soc_feature(unit, soc_feature_mpls_nh_ttl_control)) { 23929 if (soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_nh, 23930 MPLS__DISABLE_TTL_DECREMENTf)) { 23931 info->flags |= BCM_MPLS_SWITCH_KEEP_TTL; 23932 } 23933 } 23934 if (soc_mem_field_valid(unit, EGR_L3_NEXT_HOPm, 23935 MPLS__DO_EVXLT_AFTER_TUNNEL_ENCAPf)) { 23936 if (soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_nh, 23937 MPLS__DO_EVXLT_AFTER_TUNNEL_ENCAPf)) { 23938 info->flags2 |= 23939 BCM_MPLS_SWITCH2_TUNNEL_HEADER_EGRESS_VLAN_TRANSLATION; 23940 } 23941 } 23942 #endif 23943 23944 BCM_IF_ERROR_RETURN (soc_mem_read(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 23945 MEM_BLOCK_ANY, vc_swap_idx, &vc_entry)); 23946 if (SOC_MEM_FIELD_VALID(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 23947 DATA_TYPEf)) { 23948 vc_data_type = soc_mem_field32_get(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 23949 &vc_entry, DATA_TYPEf); 23950 } 23951 23952 if (vc_data_type == _BCM_VC_SWAP_TBL_FLEX_DATA_TYPE) { 23953 #if defined(BCM_TRIDENT3_SUPPORT) 23954 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 23955 sal_memset(mpls_format, 0, sizeof(mpls_format)); 23956 soc_mem_field_get(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 23957 (uint32 *) &vc_entry, 23958 MPLS_PHP__MPLS_ENTRY_0_ACTION_SETf, 23959 (uint32 *) mpls_format); 23960 23961 if (MPLS_INFO(unit)->egr_vc_swap_lbl_action != NULL) { 23962 label_action = MPLS_INFO(unit)->egr_vc_swap_lbl_action[vc_swap_idx]; 23963 } 23964 if (_BCM_MPLS_ACTION_PRESERVED == label_action) { 23965 info->egress_label.flags |= BCM_MPLS_EGRESS_LABEL_PRESERVE; 23966 info->egress_label.label = BCM_MPLS_LABEL_INVALID; 23967 } else { 23968 info->egress_label.label = soc_format_field32_get(unit, 23969 MPLS_ENTRY_ACTION_SETfmt, 23970 (uint32 *)mpls_format, MPLS_LABELf); 23971 } 23972 23973 info->egress_label.label = soc_format_field32_get(unit, 23974 MPLS_ENTRY_ACTION_SETfmt, 23975 (uint32 *)mpls_format, MPLS_LABELf); 23976 23977 info->egress_label.ttl = soc_format_field32_get(unit, 23978 MPLS_ENTRY_ACTION_SETfmt, 23979 (uint32 *)mpls_format, MPLS_TTLf); 23980 23981 if (soc_format_field32_get(unit, MPLS_ENTRY_ACTION_SETfmt, 23982 (uint32 *)mpls_format, MPLS_EXP_SELECTf) == 0x0) { 23983 /* Use the specified EXP, PRI and CFI */ 23984 info->egress_label.flags |= BCM_MPLS_EGRESS_LABEL_EXP_SET; 23985 info->egress_label.flags |= BCM_MPLS_EGRESS_LABEL_PRI_SET; 23986 info->egress_label.exp = 23987 soc_format_field32_get(unit, MPLS_ENTRY_ACTION_SETfmt, 23988 (uint32 *)mpls_format, MPLS_EXPf); 23989 info->egress_label.pkt_pri = 23990 soc_format_field32_get(unit, MPLS_ENTRY_ACTION_SETfmt, 23991 (uint32 *)mpls_format, NEW_PRIf); 23992 info->egress_label.pkt_cfi = 23993 soc_format_field32_get(unit, MPLS_ENTRY_ACTION_SETfmt, 23994 (uint32 *)mpls_format, NEW_CFIf); 23995 } else if (soc_format_field32_get(unit, MPLS_ENTRY_ACTION_SETfmt, 23996 (uint32 *)mpls_format, MPLS_EXP_SELECTf) == 0x1) { 23997 /* Use EXP-map for EXP, PRI and CFI */ 23998 info->egress_label.flags |= BCM_MPLS_EGRESS_LABEL_EXP_REMARK; 23999 info->egress_label.flags |= BCM_MPLS_EGRESS_LABEL_PRI_REMARK; 24000 ix = soc_format_field32_get(unit, MPLS_ENTRY_ACTION_SETfmt, 24001 (uint32 *)mpls_format, MPLS_EXP_MAPPING_PTRf); 24002 BCM_IF_ERROR_RETURN( 24003 _egr_qos_hw_idx2id(unit, ix, &info->egress_label.qos_map_id)); 24004 24005 } else if (soc_format_field32_get(unit, MPLS_ENTRY_ACTION_SETfmt, 24006 (uint32 *)mpls_format, MPLS_EXP_SELECTf) == 0x2) { 24007 /* Use EXP from incoming MPLS label. If no incoming label, use the specified 24008 * EXP value. Use EXP-map for PRI/CFI. 24009 */ 24010 info->egress_label.flags |= BCM_MPLS_EGRESS_LABEL_EXP_COPY; 24011 info->egress_label.flags |= BCM_MPLS_EGRESS_LABEL_PRI_REMARK; 24012 info->egress_label.exp = 24013 soc_format_field32_get(unit, MPLS_ENTRY_ACTION_SETfmt, 24014 (uint32 *)mpls_format, MPLS_EXPf); 24015 ix = soc_format_field32_get(unit, MPLS_ENTRY_ACTION_SETfmt, 24016 (uint32 *)mpls_format, MPLS_EXP_MAPPING_PTRf); 24017 24018 BCM_IF_ERROR_RETURN( 24019 _egr_qos_hw_idx2id(unit, ix, &info->egress_label.qos_map_id)); 24020 } 24021 } 24022 #endif 24023 } else { 24024 if (_BCM_MPLS_ACTION_PRESERVED == soc_mem_field32_get(unit, 24025 EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, &vc_entry, MPLS_LABEL_ACTIONf)) { 24026 info->egress_label.flags |= BCM_MPLS_EGRESS_LABEL_PRESERVE; 24027 info->egress_label.label = BCM_MPLS_LABEL_INVALID; 24028 } else { 24029 info->egress_label.label = 24030 soc_mem_field32_get(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 24031 &vc_entry, MPLS_LABELf); 24032 } 24033 24034 info->egress_label.ttl = 24035 soc_mem_field32_get(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 24036 &vc_entry, MPLS_TTLf); 24037 if (info->egress_label.ttl) { 24038 info->egress_label.flags |= BCM_MPLS_EGRESS_LABEL_TTL_SET; 24039 } else { 24040 info->egress_label.flags |= BCM_MPLS_EGRESS_LABEL_TTL_DECREMENT; 24041 } 24042 if (soc_mem_field32_get(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 24043 &vc_entry, MPLS_EXP_SELECTf) == 0x0) { 24044 /* Use the specified EXP, PRI and CFI */ 24045 info->egress_label.flags |= BCM_MPLS_EGRESS_LABEL_EXP_SET; 24046 info->egress_label.flags |= BCM_MPLS_EGRESS_LABEL_PRI_SET; 24047 info->egress_label.exp = 24048 soc_mem_field32_get(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 24049 &vc_entry, MPLS_EXPf); 24050 info->egress_label.pkt_pri = 24051 soc_mem_field32_get(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 24052 &vc_entry, NEW_PRIf); 24053 info->egress_label.pkt_cfi = 24054 soc_mem_field32_get(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 24055 &vc_entry, NEW_CFIf); 24056 } else if (soc_mem_field32_get(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 24057 &vc_entry, MPLS_EXP_SELECTf) == 0x1) { 24058 /* Use EXP-map for EXP, PRI and CFI */ 24059 info->egress_label.flags |= BCM_MPLS_EGRESS_LABEL_EXP_REMARK; 24060 info->egress_label.flags |= BCM_MPLS_EGRESS_LABEL_PRI_REMARK; 24061 ix = soc_mem_field32_get(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 24062 &vc_entry, MPLS_EXP_MAPPING_PTRf); 24063 BCM_IF_ERROR_RETURN( 24064 _egr_qos_hw_idx2id(unit, ix, &info->egress_label.qos_map_id)); 24065 } else if (soc_mem_field32_get(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 24066 &vc_entry, MPLS_EXP_SELECTf) == 0x3) { 24067 /* Use EXP from incoming MPLS label. If no incoming label, use the specified 24068 * EXP value. Use EXP-map for PRI/CFI. 24069 */ 24070 info->egress_label.flags |= BCM_MPLS_EGRESS_LABEL_EXP_COPY; 24071 info->egress_label.flags |= BCM_MPLS_EGRESS_LABEL_PRI_REMARK; 24072 info->egress_label.exp = 24073 soc_mem_field32_get(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 24074 &vc_entry, MPLS_EXPf); 24075 ix = soc_mem_field32_get(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 24076 &vc_entry, MPLS_EXP_MAPPING_PTRf); 24077 BCM_IF_ERROR_RETURN( 24078 _egr_qos_hw_idx2id(unit, ix, &info->egress_label.qos_map_id)); 24079 } 24080 } 24081 #if defined(BCM_SWAP_TO_SELF_SUPPORT) 24082 if (soc_feature(unit, soc_feature_mpls_swap_label_preserve)) { 24083 uint32 mpls_label_action = 0, label_select = 0; 24084 #if defined(BCM_TRIDENT3_SUPPORT) 24085 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 24086 if (vc_data_type == _BCM_VC_SWAP_TBL_FLEX_DATA_TYPE) { 24087 label_select = soc_format_field32_get(unit, 24088 MPLS_ENTRY_ACTION_SETfmt, 24089 (uint32 *)mpls_format, LABEL_SELECTf); 24090 } else { 24091 label_select = soc_mem_field32_get(unit, 24092 EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 24093 &vc_entry, LABEL_SELECTf); 24094 } 24095 24096 if (MPLS_INFO(unit)->egr_vc_swap_lbl_action != NULL) { 24097 mpls_label_action = 24098 MPLS_INFO(unit)->egr_vc_swap_lbl_action[vc_swap_idx]; 24099 } 24100 } else 24101 #endif 24102 { 24103 mpls_label_action = soc_mem_field32_get(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 24104 &vc_entry, MPLS_LABEL_ACTIONf); 24105 } 24106 24107 if (label_select || (mpls_label_action == _BCM_MPLS_ACTION_PRESERVED)) { 24108 info->egress_label.flags |= BCM_MPLS_EGRESS_LABEL_PRESERVE; 24109 } 24110 } 24111 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 24112 info->egress_label.spl_label_push_type = soc_mem_field32_get(unit, 24113 EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, &vc_entry, 24114 SPECIAL_LABEL_PUSH_TYPEf); 24115 } 24116 #endif 24117 24118 #ifdef BCM_TOMAHAWK2_SUPPORT 24119 if (soc_feature(unit, soc_feature_mpls_ecn) && 24120 !soc_feature(unit, soc_feature_intcn_to_exp_nosupport)) { 24121 ecn_map_index = soc_mem_field32_get(unit, 24122 EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 24123 &vc_entry, 24124 INT_CN_TO_EXP_MAPPING_PTRf); 24125 if (bcmi_xgs5_ecn_map_used_get(unit, ecn_map_index, 24126 _bcmEcnmapTypeIntcn2Exp)) { 24127 info->egress_label.int_cn_map_id = 24128 _BCM_XGS5_MPLS_ECN_MAP_TYPE_INTCN2EXP | ecn_map_index; 24129 ecn_map_pri = soc_mem_field32_get(unit, 24130 EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 24131 &vc_entry, 24132 INT_CN_TO_EXP_PRIORITYf); 24133 if (ecn_map_pri) { 24134 info->egress_label.flags |= 24135 BCM_MPLS_EGRESS_LABEL_ECN_EXP_MAP_TRUST; 24136 } 24137 info->egress_label.flags |= 24138 BCM_MPLS_EGRESS_LABEL_INT_CN_TO_EXP_MAP; 24139 } 24140 } 24141 #endif /* BCM_TOMAHAWK2_SUPPORT */ 24142 #if defined(BCM_TRIDENT3_SUPPORT) 24143 if (soc_feature(unit, soc_feature_mpls_ecn)) { 24144 ecn_map_index = soc_mem_field32_get(unit, 24145 EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 24146 &vc_entry, 24147 PKT_ECN_TO_EXP_MAPPING_PTRf); 24148 24149 if (bcmi_xgs5_ecn_map_used_get(unit, ecn_map_index, 24150 _bcmEcnmapTypeIpEcn2Exp)) { 24151 info->egress_label.ecn_map_id = 24152 _BCM_XGS5_MPLS_ECN_MAP_TYPE_ECN2EXP | ecn_map_index; 24153 ecn_map_pri = soc_mem_field32_get(unit, 24154 EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 24155 &vc_entry, 24156 PKT_ECN_TO_EXP_PRIORITYf); 24157 if (ecn_map_pri) { 24158 info->egress_label.flags |= 24159 BCM_MPLS_EGRESS_LABEL_ECN_EXP_MAP_TRUST; 24160 } 24161 info->egress_label.flags |= 24162 BCM_MPLS_EGRESS_LABEL_ECN_TO_EXP_MAP; 24163 } 24164 } 24165 #endif /* BCM_TRIDENT3_SUPPORT */ 24166 return BCM_E_NONE; 24167 } 24168 24169 /* Convert key part of application format to HW entry. */ 24170 STATIC int 24171 _bcm_tr_mpls_entry_set_key(int unit, bcm_mpls_tunnel_switch_t *info, 24172 mpls_entry_entry_t *ment) 24173 { 24174 bcm_module_t mod_out; 24175 bcm_port_t port_out; 24176 bcm_trunk_t trunk_id; 24177 int rv, gport_id; 24178 soc_mem_t mem = MPLS_ENTRYm; 24179 24180 if (soc_feature(unit, soc_feature_th3_style_simple_mpls)) { 24181 mem = MPLS_ENTRY_SINGLEm; 24182 } 24183 24184 sal_memset(ment, 0, sizeof(mpls_entry_entry_t)); 24185 24186 if (info->port == BCM_GPORT_INVALID) { 24187 /* Global label, mod/port not part of lookup key */ 24188 if (SOC_MEM_FIELD_VALID(unit, mem, MODULE_IDf)) { 24189 soc_mem_field32_set(unit, mem, ment, MODULE_IDf, 0); 24190 } 24191 soc_mem_field32_set(unit, mem, ment, PORT_NUMf, 0); 24192 if (BCM_XGS3_L3_MPLS_LBL_VALID(info->label)) { 24193 soc_mem_field32_set(unit, mem, ment, MPLS_LABELf, info->label); 24194 } else { 24195 return BCM_E_PARAM; 24196 } 24197 soc_mem_field32_set(unit, mem, ment, VALIDf, 1); 24198 return BCM_E_NONE; 24199 } 24200 24201 rv = _bcm_esw_gport_resolve(unit, info->port, &mod_out, 24202 &port_out, &trunk_id, &gport_id); 24203 BCM_IF_ERROR_RETURN(rv); 24204 24205 if (BCM_GPORT_IS_TRUNK(info->port)) { 24206 soc_mem_field32_set(unit, mem, ment, Tf, 1); 24207 soc_mem_field32_set(unit, mem, ment, TGIDf, trunk_id); 24208 } else { 24209 if (SOC_MEM_FIELD_VALID(unit, mem, MODULE_IDf)) { 24210 soc_mem_field32_set(unit, mem, ment, MODULE_IDf, mod_out); 24211 } 24212 soc_mem_field32_set(unit, mem, ment, PORT_NUMf, port_out); 24213 } 24214 if (BCM_XGS3_L3_MPLS_LBL_VALID(info->label)) { 24215 soc_mem_field32_set(unit, mem, ment, MPLS_LABELf, info->label); 24216 } else { 24217 return BCM_E_PARAM; 24218 } 24219 soc_mem_field32_set(unit, mem, ment, VALIDf, 1); 24220 24221 return BCM_E_NONE; 24222 } 24223 24224 /* Convert key part of HW entry to application format. */ 24225 STATIC int 24226 _bcm_tr_mpls_entry_get_key(int unit, mpls_entry_entry_t *ment, 24227 bcm_mpls_tunnel_switch_t *info) 24228 { 24229 bcm_port_t port_in, port_out; 24230 bcm_module_t mod_in, mod_out; 24231 bcm_trunk_t trunk_id; 24232 24233 port_in = soc_MPLS_ENTRYm_field32_get(unit, ment, PORT_NUMf); 24234 mod_in = soc_MPLS_ENTRYm_field32_get(unit, ment, MODULE_IDf); 24235 if (soc_MPLS_ENTRYm_field32_get(unit, ment, Tf)) { 24236 trunk_id = soc_MPLS_ENTRYm_field32_get(unit, ment, TGIDf); 24237 BCM_GPORT_TRUNK_SET(info->port, trunk_id); 24238 } else if ((port_in == 0) && (mod_in == 0)) { 24239 /* Global label, mod/port not part of lookup key */ 24240 info->port = BCM_GPORT_INVALID; 24241 } else { 24242 BCM_IF_ERROR_RETURN 24243 (_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET, 24244 mod_in, port_in, &mod_out, &port_out)); 24245 BCM_GPORT_MODPORT_SET(info->port, mod_out, port_out); 24246 } 24247 info->label = soc_MPLS_ENTRYm_field32_get(unit, ment, MPLS_LABELf); 24248 24249 return BCM_E_NONE; 24250 } 24251 24252 /* Convert data part of HW entry to application format. */ 24253 STATIC int 24254 _bcm_tr_mpls_entry_get_data(int unit, mpls_entry_entry_t *ment, 24255 bcm_mpls_tunnel_switch_t *info) 24256 { 24257 int rv, action, nh_index, vrf; 24258 bcm_if_t egress_if=0; 24259 int mode = 0; 24260 soc_mem_t mem = MPLS_ENTRYm; 24261 24262 if (soc_feature(unit, soc_feature_th3_style_simple_mpls)) { 24263 mem = MPLS_ENTRY_SINGLEm; 24264 } 24265 24266 BCM_IF_ERROR_RETURN(bcm_xgs3_l3_ingress_mode_get(unit, &mode)); 24267 24268 action = soc_mem_field32_get(unit, mem, ment, MPLS_ACTION_IF_BOSf); 24269 switch(action) { 24270 case 0x2: 24271 info->action = BCM_MPLS_SWITCH_ACTION_POP; 24272 if (!mode) { 24273 vrf = soc_mem_field32_get(unit, mem, ment, L3_IIFf); 24274 vrf -= _BCM_TR_MPLS_L3_IIF_BASE; 24275 _BCM_MPLS_VPN_SET(info->vpn, _BCM_MPLS_VPN_TYPE_L3, vrf); 24276 } else { 24277 info->ingress_if = soc_mem_field32_get(unit, mem, ment, L3_IIFf); 24278 } 24279 break; 24280 case 0x3: 24281 info->action = BCM_MPLS_SWITCH_ACTION_SWAP; 24282 nh_index = soc_mem_field32_get(unit, mem, ment, 24283 NEXT_HOP_INDEXf); 24284 rv = bcm_tr_mpls_get_vp_nh (unit, nh_index,&egress_if); 24285 if (rv == BCM_E_NONE) { 24286 rv = bcm_tr_mpls_l3_nh_info_get(unit, info, nh_index); 24287 info->egress_if = egress_if; 24288 } else { 24289 info->egress_if = nh_index + BCM_XGS3_EGRESS_IDX_MIN(unit); 24290 info->egress_label.label = BCM_MPLS_LABEL_INVALID; 24291 rv = BCM_E_NONE; 24292 } 24293 BCM_IF_ERROR_RETURN(rv); 24294 break; 24295 case 0x4: 24296 info->action = BCM_MPLS_SWITCH_ACTION_PHP; 24297 nh_index = soc_mem_field32_get(unit, mem, ment, 24298 NEXT_HOP_INDEXf); 24299 info->egress_if = nh_index + BCM_XGS3_EGRESS_IDX_MIN(unit); 24300 break; 24301 case 0x5: 24302 info->action = BCM_MPLS_SWITCH_ACTION_PHP; 24303 nh_index = soc_mem_field32_get(unit, mem, ment, 24304 ECMP_PTRf); 24305 info->egress_if = nh_index + BCM_XGS3_MPATH_EGRESS_IDX_MIN(unit); 24306 break; 24307 default: 24308 return BCM_E_INTERNAL; 24309 break; 24310 } 24311 if (soc_mem_field32_get(unit, mem, ment, PW_TERM_NUM_VALIDf)) { 24312 info->flags |= BCM_MPLS_SWITCH_COUNTED; 24313 } 24314 24315 if (!soc_mem_field32_get(unit, mem, ment, DECAP_USE_TTLf)) { 24316 info->flags |= BCM_MPLS_SWITCH_INNER_TTL; 24317 } 24318 if (soc_mem_field32_get(unit, mem, ment, DECAP_USE_EXP_FOR_INNERf)) { 24319 if (info->action != BCM_MPLS_SWITCH_ACTION_SWAP) { 24320 info->flags |= BCM_MPLS_SWITCH_INNER_EXP; 24321 } 24322 } 24323 if (soc_mem_field32_get(unit, mem, ment, 24324 DECAP_USE_EXP_FOR_PRIf) == 0x1) { 24325 24326 /* Use specified EXP-map to determine internal prio/color */ 24327 info->flags |= BCM_MPLS_SWITCH_INT_PRI_MAP; 24328 info->exp_map = 24329 soc_mem_field32_get(unit, mem, ment, EXP_MAPPING_PTRf); 24330 info->exp_map |= _BCM_TR_MPLS_EXP_MAP_TABLE_TYPE_INGRESS; 24331 } else if (soc_mem_field32_get(unit, mem, ment, 24332 DECAP_USE_EXP_FOR_PRIf) == 0x2) { 24333 24334 /* Use the specified internal priority value */ 24335 info->flags |= BCM_MPLS_SWITCH_INT_PRI_SET; 24336 info->int_pri = 24337 soc_mem_field32_get(unit, mem, ment, NEW_PRIf); 24338 24339 /* Use specified EXP-map to determine internal color */ 24340 info->flags |= BCM_MPLS_SWITCH_COLOR_MAP; 24341 info->exp_map = 24342 soc_mem_field32_get(unit, mem, ment, EXP_MAPPING_PTRf); 24343 info->exp_map |= _BCM_TR_MPLS_EXP_MAP_TABLE_TYPE_INGRESS; 24344 } 24345 if (SOC_MEM_FIELD_VALID(unit,MPLS_ENTRYm, 24346 DO_NOT_CHANGE_PAYLOAD_DSCPf)) { 24347 if (soc_mem_field32_get(unit, mem, ment, 24348 DO_NOT_CHANGE_PAYLOAD_DSCPf) == 0) { 24349 if ((info->action == BCM_MPLS_SWITCH_ACTION_PHP) || 24350 (info->action == BCM_MPLS_SWITCH_ACTION_POP)) { 24351 info->flags |= 24352 (BCM_MPLS_SWITCH_OUTER_EXP | BCM_MPLS_SWITCH_OUTER_TTL); 24353 } 24354 } 24355 } 24356 return BCM_E_NONE; 24357 } 24358 24359 /* 24360 * Function: 24361 * bcm_tr_mpls_egress_object_modify 24362 * Purpose: 24363 * Modify Egress NH entry 24364 * Parameters: 24365 * unit - Device Number 24366 * nh_index - Next Hop Index/ECMP index 24367 * new_entry_type - New Entry type 24368 * Returns: 24369 * BCM_E_XXX 24370 */ 24371 24372 int 24373 bcm_tr_mpls_egress_object_modify(int unit, int nh_index, int new_entry_type) 24374 { 24375 bcm_l3_egress_t nh_info; 24376 egr_l3_next_hop_entry_t new_egr_nh; 24377 uint32 macda_index=-1; 24378 void *entries[1]; 24379 int rv = BCM_E_NONE; 24380 int old_entry_type; 24381 egr_mac_da_profile_entry_t macda; 24382 24383 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) 24384 uint32 flex_ctr_offset_mode, flex_ctr_pool_number, flex_ctr_base_idx; 24385 #endif 24386 BCM_IF_ERROR_RETURN(soc_mem_read(unit, EGR_L3_NEXT_HOPm, MEM_BLOCK_ALL, 24387 nh_index, &new_egr_nh)); 24388 24389 old_entry_type = 24390 soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &new_egr_nh, 24391 nh_entry_type_field[unit]); 24392 24393 if ((old_entry_type == 0) && (new_entry_type == 1)) { 24394 BCM_IF_ERROR_RETURN(bcm_xgs3_nh_get(unit, nh_index, &nh_info)); 24395 24396 sal_memset(&macda, 0, sizeof(egr_mac_da_profile_entry_t)); 24397 soc_mem_mac_addr_set(unit, EGR_MAC_DA_PROFILEm, 24398 &macda, MAC_ADDRESSf, nh_info.mac_addr); 24399 entries[0] = &macda; 24400 BCM_IF_ERROR_RETURN(_bcm_mac_da_profile_entry_add(unit, entries, 1, 24401 (uint32 *) &macda_index)); 24402 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) 24403 if (soc_feature(unit,soc_feature_advanced_flex_counter)) { 24404 /* 1 Store the old flex counter */ 24405 BCM_IF_ERROR_RETURN( 24406 _bcm_esw_get_flex_counter_fields_values(unit, nh_index, 24407 EGR_L3_NEXT_HOPm, 24408 &new_egr_nh, 24409 0, 24410 &flex_ctr_offset_mode, 24411 &flex_ctr_pool_number, 24412 &flex_ctr_base_idx)); 24413 /* 2 Clear flex counter in old entry view */ 24414 BCM_IF_ERROR_RETURN( 24415 _bcm_esw_set_flex_counter_fields_values(unit, nh_index, 24416 EGR_L3_NEXT_HOPm, 24417 &new_egr_nh, 24418 0, 24419 0, 24420 0, 24421 0)); 24422 } 24423 #endif 24424 24425 #if defined(BCM_TOMAHAWK3_SUPPORT) 24426 if (soc_feature(unit, soc_feature_th3_style_simple_mpls)) { 24427 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 24428 &new_egr_nh, MPLS__MPLS_LABELf, 0); 24429 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 24430 &new_egr_nh, MPLS__MPLS_LABEL_ACTIONf, 0); 24431 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 24432 &new_egr_nh, MPLS__MPLS_TTLf, 0); 24433 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 24434 &new_egr_nh, MPLS__MPLS_EXPf, 0); 24435 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 24436 &new_egr_nh, MPLS__MPLS_EXP_SELECTf, 0); 24437 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 24438 &new_egr_nh, MPLS__MPLS_EXP_MAPPING_PTRf, 0); 24439 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 24440 &new_egr_nh, MPLS__IP_ECN_TO_EXP_MAPPING_PTRf, 0); 24441 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 24442 &new_egr_nh, MPLS__INT_CN_TO_EXP_PRIORITYf, 0); 24443 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 24444 &new_egr_nh, MPLS__INT_CN_TO_EXP_MAPPING_PTRf, 0); 24445 } 24446 #endif 24447 if (soc_feature(unit, soc_feature_mpls_enhanced)) { 24448 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 24449 &new_egr_nh, MPLS__MAC_DA_PROFILE_INDEXf, 24450 macda_index); 24451 24452 if (soc_mem_field_valid(unit, EGR_L3_NEXT_HOPm, MPLS__DVPf)) { 24453 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 24454 &new_egr_nh, MPLS__DVPf, 0); 24455 } 24456 if (soc_feature(unit, 24457 soc_feature_multiple_split_horizon_group)) { 24458 if (!(soc_feature(unit, soc_feature_td3_style_mpls))) { 24459 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 24460 &new_egr_nh, MPLS__DVP_NETWORK_GROUPf, 0); 24461 } 24462 } else if (soc_mem_field_valid(unit, EGR_L3_NEXT_HOPm, MPLS__DVP_IS_NETWORK_PORTf)) { 24463 24464 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 24465 &new_egr_nh, MPLS__DVP_IS_NETWORK_PORTf, 0); 24466 } 24467 24468 if (!soc_feature(unit, soc_feature_th3_style_simple_mpls)) { 24469 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 24470 &new_egr_nh, MPLS__HG_MODIFY_ENABLEf, 0x1); 24471 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 24472 &new_egr_nh, MPLS__HG_HDR_SELf, 0); 24473 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 24474 &new_egr_nh, MPLS__HG_MC_DST_MODIDf, 0); 24475 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 24476 &new_egr_nh, MPLS__HG_MC_DST_PORT_NUMf, 0); 24477 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 24478 &new_egr_nh, MPLS__HG_ADD_SYS_RSVD_VIDf, 0); 24479 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 24480 &new_egr_nh, MPLS__HG_LEARN_OVERRIDEf, 0); 24481 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 24482 &new_egr_nh, MPLS__HG_L3_OVERRIDEf, 0); 24483 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 24484 &new_egr_nh, MPLS__PW_INIT_NUMf, 0); 24485 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 24486 &new_egr_nh, MPLS__VC_AND_SWAP_INDEXf, 0); 24487 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 24488 &new_egr_nh, MPLS__UMC_DROPf, 0); 24489 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 24490 &new_egr_nh, MPLS__UUC_DROPf, 0); 24491 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 24492 &new_egr_nh, MPLS__BC_DROPf, 0); 24493 } 24494 24495 } else { 24496 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 24497 &new_egr_nh, MAC_DA_PROFILE_INDEXf, 24498 macda_index); 24499 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 24500 &new_egr_nh, DVPf, 0); 24501 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 24502 &new_egr_nh, DVP_IS_NETWORK_PORTf, 0); 24503 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 24504 &new_egr_nh, HG_MODIFY_ENABLEf, 0x1); 24505 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 24506 &new_egr_nh, HG_HDR_SELf, 0); 24507 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 24508 &new_egr_nh, HG_MC_DST_MODIDf, 0); 24509 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 24510 &new_egr_nh, HG_MC_DST_PORT_NUMf, 0); 24511 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 24512 &new_egr_nh, HG_ADD_SYS_RSVD_VIDf, 0); 24513 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 24514 &new_egr_nh, HG_LEARN_OVERRIDEf, 0); 24515 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 24516 &new_egr_nh, HG_L3_OVERRIDEf, 0); 24517 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 24518 &new_egr_nh, PW_INIT_NUMf, 0); 24519 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 24520 &new_egr_nh, VC_AND_SWAP_INDEXf, 0); 24521 } 24522 24523 #ifdef BCM_KATANA_SUPPORT 24524 if (soc_feature(unit, soc_feature_vlan_xlate)) { 24525 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 24526 &new_egr_nh, MPLS__USE_DVP_IN_EVXLT_KEYf, 0); 24527 } 24528 #endif 24529 24530 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &new_egr_nh, 24531 nh_entry_type_field[unit], new_entry_type); 24532 24533 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) 24534 if (soc_feature(unit,soc_feature_advanced_flex_counter)) { 24535 /* Restore flex counter in new entry view */ 24536 BCM_IF_ERROR_RETURN( 24537 _bcm_esw_set_flex_counter_fields_values(unit, nh_index, 24538 EGR_L3_NEXT_HOPm, 24539 &new_egr_nh, 24540 0, 24541 flex_ctr_offset_mode, 24542 flex_ctr_pool_number, 24543 flex_ctr_base_idx)); 24544 } 24545 #endif 24546 24547 rv = soc_mem_write(unit, EGR_L3_NEXT_HOPm, 24548 MEM_BLOCK_ALL, nh_index, &new_egr_nh); 24549 if (rv < 0) { 24550 if (macda_index != (uint32)-1) { 24551 (void) _bcm_mac_da_profile_entry_delete(unit, macda_index); 24552 } 24553 } 24554 }else if ((old_entry_type == 1) && (new_entry_type == 0)) { 24555 /* Delete MAC_DA_PROFILE_INDEX */ 24556 bcm_mac_t mac_addr; 24557 if (soc_feature(unit, soc_feature_mpls_enhanced)) { 24558 macda_index = 24559 soc_EGR_L3_NEXT_HOPm_field32_get(unit, &new_egr_nh, 24560 MPLS__MAC_DA_PROFILE_INDEXf); 24561 } else { 24562 macda_index = 24563 soc_EGR_L3_NEXT_HOPm_field32_get(unit, &new_egr_nh, 24564 MAC_DA_PROFILE_INDEXf); 24565 } 24566 24567 /* Read entry from MAC-DA-PROFILEm */ 24568 BCM_IF_ERROR_RETURN (soc_mem_read(unit, EGR_MAC_DA_PROFILEm, 24569 MEM_BLOCK_ANY, macda_index, &macda)); 24570 /* Obtain Mac-Address */ 24571 soc_mem_mac_addr_get(unit, EGR_MAC_DA_PROFILEm, 24572 &macda, MAC_ADDRESSf, mac_addr); 24573 if (soc_mem_field_valid(unit, EGR_L3_NEXT_HOPm, L3__MAC_ADDRESSf)) { 24574 soc_mem_mac_addr_set(unit, EGR_L3_NEXT_HOPm, &new_egr_nh, 24575 L3__MAC_ADDRESSf, mac_addr); 24576 } else { 24577 soc_mem_mac_addr_set(unit, EGR_L3_NEXT_HOPm, &new_egr_nh, 24578 MAC_ADDRESSf, mac_addr); 24579 } 24580 if (macda_index != (uint32)-1) { 24581 (void) _bcm_mac_da_profile_entry_delete(unit, macda_index); 24582 } 24583 24584 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) 24585 if (soc_feature(unit,soc_feature_advanced_flex_counter)) { 24586 /* 1 Store the old flex counter */ 24587 BCM_IF_ERROR_RETURN( 24588 _bcm_esw_get_flex_counter_fields_values(unit, nh_index, 24589 EGR_L3_NEXT_HOPm, 24590 &new_egr_nh, 24591 0, 24592 &flex_ctr_offset_mode, 24593 &flex_ctr_pool_number, 24594 &flex_ctr_base_idx)); 24595 /* 2 Clear flex counter in old entry view */ 24596 BCM_IF_ERROR_RETURN( 24597 _bcm_esw_set_flex_counter_fields_values(unit, nh_index, 24598 EGR_L3_NEXT_HOPm, 24599 &new_egr_nh, 24600 0, 24601 0, 24602 0, 24603 0)); 24604 } 24605 #endif 24606 24607 if (soc_feature(unit, soc_feature_mpls_enhanced)) { 24608 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 24609 &new_egr_nh, MPLS__MAC_DA_PROFILE_INDEXf, 0); 24610 } else { 24611 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 24612 &new_egr_nh, MAC_DA_PROFILE_INDEXf, 0); 24613 } 24614 24615 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &new_egr_nh, 24616 nh_entry_type_field[unit], new_entry_type); 24617 24618 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) 24619 if (soc_feature(unit,soc_feature_advanced_flex_counter)) { 24620 /* Restore flex counter in new entry view */ 24621 BCM_IF_ERROR_RETURN( 24622 _bcm_esw_set_flex_counter_fields_values(unit, nh_index, 24623 EGR_L3_NEXT_HOPm, 24624 &new_egr_nh, 24625 0, 24626 flex_ctr_offset_mode, 24627 flex_ctr_pool_number, 24628 flex_ctr_base_idx)); 24629 } 24630 #endif 24631 24632 rv = soc_mem_write(unit, EGR_L3_NEXT_HOPm, 24633 MEM_BLOCK_ALL, nh_index, &new_egr_nh); 24634 24635 } 24636 24637 return rv; 24638 } 24639 24640 /* 24641 * Function: 24642 * bcm_tr_mpls_egress_entry_modify 24643 * Purpose: 24644 * Modify Egress entry 24645 * Parameters: 24646 * unit - Device Number 24647 * nh_index - Next Hop Index/ECMP index 24648 * mpath_flag - Flag to to indicate NH/ECMP 24649 * new_entry_type - New Entry type 24650 * Returns: 24651 * BCM_E_XXX 24652 */ 24653 24654 int 24655 bcm_tr_mpls_egress_entry_modify(int unit, int nh_index, 24656 int mpath_flag, int new_entry_type) 24657 { 24658 int i = 0, ecmp_member_count = 0; 24659 int alloc_size, index; 24660 bcm_l3_egress_ecmp_t ecmp_info; 24661 bcm_l3_ecmp_member_t *ecmp_member_array = NULL; 24662 int rv = BCM_E_NONE; 24663 24664 if (mpath_flag & BCM_L3_MULTIPATH) { 24665 24666 alloc_size = sizeof(bcm_l3_ecmp_member_t) * BCM_XGS3_L3_ECMP_MAX(unit); 24667 ecmp_member_array = sal_alloc(alloc_size, "ecmp member array"); 24668 if (NULL == ecmp_member_array) { 24669 return BCM_E_MEMORY; 24670 } 24671 sal_memset(ecmp_member_array, 0, alloc_size); 24672 24673 ecmp_info.ecmp_intf = nh_index + BCM_XGS3_MPATH_EGRESS_IDX_MIN(unit); 24674 rv = bcm_xgs3_l3_ecmp_get(unit, &ecmp_info, BCM_XGS3_L3_ECMP_MAX(unit), 24675 ecmp_member_array, &ecmp_member_count); 24676 if (BCM_FAILURE(rv)) { 24677 goto clean_up; 24678 } 24679 24680 while (i < ecmp_member_count) { 24681 if (BCM_XGS3_L3_EGRESS_IDX_VALID(unit, 24682 ecmp_member_array[i].egress_if)) { 24683 index = (ecmp_member_array[i].egress_if - 24684 BCM_XGS3_EGRESS_IDX_MIN(unit)); 24685 } 24686 #if defined(BCM_TOMAHAWK3_SUPPORT) 24687 else if ((soc_feature(unit, soc_feature_th3_style_simple_mpls)) && 24688 (BCM_XGS3_L3_MPATH_EGRESS_IDX_VALID(unit, 24689 ecmp_member_array[i].egress_if))) { 24690 index = (ecmp_member_array[i].egress_if - 24691 BCM_XGS3_MPATH_EGRESS_IDX_MIN(unit)); 24692 rv = bcm_tr_mpls_egress_entry_modify(unit, index, mpath_flag, new_entry_type); 24693 if (BCM_FAILURE(rv)) { 24694 goto clean_up; 24695 } 24696 i++; 24697 continue; 24698 } 24699 #endif 24700 else { 24701 index = (ecmp_member_array[i].egress_if - 24702 BCM_XGS3_DVP_EGRESS_IDX_MIN(unit)); 24703 } 24704 24705 rv = bcm_tr_mpls_egress_object_modify(unit, index, new_entry_type); 24706 if (BCM_FAILURE(rv)) { 24707 goto clean_up; 24708 } 24709 i++; 24710 } 24711 } else { 24712 rv = bcm_tr_mpls_egress_object_modify(unit, nh_index, new_entry_type); 24713 } 24714 24715 clean_up: 24716 if (ecmp_member_array) { 24717 sal_free(ecmp_member_array); 24718 ecmp_member_array = NULL; 24719 } 24720 24721 return rv; 24722 } 24723 24724 /* 24725 * Function: 24726 * bcm_mpls_tunnel_switch_add 24727 * Purpose: 24728 * Add an MPLS label entry. 24729 * Parameters: 24730 * unit - Device Number 24731 * info - Label (switch) information 24732 * Returns: 24733 * BCM_E_XXX 24734 */ 24735 int 24736 bcm_tr_mpls_tunnel_switch_add(int unit, bcm_mpls_tunnel_switch_t *info) 24737 { 24738 mpls_entry_entry_t ment; 24739 int mode=0, nh_index = -1, vrf=0, rv, num_pw_term, old_pw_cnt = -1, pw_cnt = -1; 24740 int index, action = -1, old_nh_index = -1, old_ecmp_index = -1; 24741 int tunnel_switch_update=0; 24742 uint32 mpath_flag=0; 24743 int ref_count=0; 24744 bcm_if_t egress_if=0; 24745 24746 rv = bcm_xgs3_l3_egress_mode_get(unit, &mode); 24747 BCM_IF_ERROR_RETURN(rv); 24748 if (!mode) { 24749 LOG_INFO(BSL_LS_BCM_L3, 24750 (BSL_META_U(unit, 24751 "L3 egress mode must be set first\n"))); 24752 return BCM_E_DISABLED; 24753 } 24754 24755 /* Check for Port_independent Label mapping */ 24756 if (!BCM_XGS3_L3_MPLS_LBL_VALID(info->label)) { 24757 return BCM_E_PARAM; 24758 } 24759 24760 rv = bcm_tr_mpls_port_independent_range (unit, info->label, info->port); 24761 if (rv < 0) { 24762 return rv; 24763 } 24764 24765 BCM_IF_ERROR_RETURN(_bcm_tr_mpls_entry_set_key(unit, info, &ment)); 24766 24767 /* See if entry already exists */ 24768 rv = soc_mem_search(unit, MPLS_ENTRYm, MEM_BLOCK_ANY, &index, 24769 &ment, &ment, 0); 24770 24771 /* default not to use DSCP from ING_MPLS_EXP_MAPPING table */ 24772 if (SOC_MEM_FIELD_VALID(unit,MPLS_ENTRYm,DO_NOT_CHANGE_PAYLOAD_DSCPf)) { 24773 soc_MPLS_ENTRYm_field32_set(unit, &ment, 24774 DO_NOT_CHANGE_PAYLOAD_DSCPf, 1); 24775 } 24776 24777 if (rv == SOC_E_NONE) { 24778 /* Entry exists, save old info */ 24779 tunnel_switch_update = 1; 24780 action = soc_MPLS_ENTRYm_field32_get(unit, &ment, MPLS_ACTION_IF_BOSf); 24781 if ((action == 0x3) || (action == 0x4)) { 24782 /* SWAP_NHI or L3_NHI */ 24783 old_nh_index = soc_MPLS_ENTRYm_field32_get(unit, &ment, NEXT_HOP_INDEXf); 24784 } else if (action == 0x5) { 24785 /* L3_ECMP */ 24786 old_ecmp_index = soc_MPLS_ENTRYm_field32_get(unit, &ment, ECMP_PTRf); 24787 } 24788 24789 if (soc_MPLS_ENTRYm_field32_get(unit, &ment, PW_TERM_NUM_VALIDf)) { 24790 old_pw_cnt = soc_MPLS_ENTRYm_field32_get(unit, &ment, PW_TERM_NUMf); 24791 } 24792 } else if (rv != SOC_E_NOT_FOUND) { 24793 return rv; 24794 } 24795 24796 switch(info->action) { 24797 case BCM_MPLS_SWITCH_ACTION_SWAP: 24798 if (!BCM_XGS3_L3_EGRESS_IDX_VALID(unit, info->egress_if)) { 24799 return BCM_E_PARAM; 24800 } 24801 soc_MPLS_ENTRYm_field32_set(unit, &ment, MPLS_ACTION_IF_NOT_BOSf, 24802 0x3); /* SWAP_NHI */ 24803 soc_MPLS_ENTRYm_field32_set(unit, &ment, MPLS_ACTION_IF_BOSf, 24804 0x3); /* SWAP NHI */ 24805 break; 24806 case BCM_MPLS_SWITCH_ACTION_POP: 24807 soc_MPLS_ENTRYm_field32_set(unit, &ment, MPLS_ACTION_IF_NOT_BOSf, 24808 0x1); /* POP */ 24809 soc_MPLS_ENTRYm_field32_set(unit, &ment, MPLS_ACTION_IF_BOSf, 24810 0x2); /* L3_IIF */ 24811 /* uniform qos model if either of these two flags set. 24812 * Only apply to L3 MPLS and BOS 24813 */ 24814 if (info->flags & (BCM_MPLS_SWITCH_OUTER_EXP | 24815 BCM_MPLS_SWITCH_OUTER_TTL) ) { 24816 if (SOC_MEM_FIELD_VALID(unit,MPLS_ENTRYm, 24817 DO_NOT_CHANGE_PAYLOAD_DSCPf)) { 24818 soc_MPLS_ENTRYm_field32_set(unit, &ment, 24819 DO_NOT_CHANGE_PAYLOAD_DSCPf, 0); 24820 } 24821 } 24822 24823 break; 24824 case BCM_MPLS_SWITCH_ACTION_PHP: 24825 soc_MPLS_ENTRYm_field32_set(unit, &ment, MPLS_ACTION_IF_NOT_BOSf, 24826 0x2); /* PHP_NHI */ 24827 if (BCM_XGS3_L3_MPATH_EGRESS_IDX_VALID(unit, info->egress_if)) { 24828 soc_MPLS_ENTRYm_field32_set(unit, &ment, MPLS_ACTION_IF_BOSf, 24829 0x5); /* L3_ECMP */ 24830 } else if (BCM_XGS3_L3_EGRESS_IDX_VALID(unit, info->egress_if)) { 24831 soc_MPLS_ENTRYm_field32_set(unit, &ment, MPLS_ACTION_IF_BOSf, 24832 0x4); /* L3_NHI */ 24833 } else { 24834 return BCM_E_PARAM; 24835 } 24836 /* uniform qos model if either of these two flags set. 24837 * Only apply to L3 MPLS and BOS 24838 */ 24839 if (info->flags & (BCM_MPLS_SWITCH_OUTER_EXP | 24840 BCM_MPLS_SWITCH_OUTER_TTL) ) { 24841 if (SOC_MEM_FIELD_VALID(unit,MPLS_ENTRYm, 24842 DO_NOT_CHANGE_PAYLOAD_DSCPf)) { 24843 soc_MPLS_ENTRYm_field32_set(unit, &ment, 24844 DO_NOT_CHANGE_PAYLOAD_DSCPf, 0); 24845 } 24846 } 24847 break; 24848 default: 24849 return BCM_E_PARAM; 24850 break; 24851 } 24852 if (info->action == BCM_MPLS_SWITCH_ACTION_POP) { 24853 mode = -1; 24854 if (_BCM_MPLS_VPN_IS_L3(info->vpn)) { 24855 _BCM_MPLS_VPN_GET(vrf, _BCM_MPLS_VPN_TYPE_L3, info->vpn); 24856 if (!_BCM_MPLS_VRF_USED_GET(unit, vrf)) { 24857 return BCM_E_PARAM; 24858 } 24859 24860 /* Check L3 Ingress Interface mode. */ 24861 mode = 0; 24862 rv = bcm_xgs3_l3_ingress_mode_get(unit, &mode); 24863 BCM_IF_ERROR_RETURN(rv); 24864 } 24865 if (!mode) { 24866 _bcm_l3_ingress_intf_t iif; 24867 sal_memset(&iif, 0, sizeof(_bcm_l3_ingress_intf_t)); 24868 iif.intf_id = _BCM_TR_MPLS_L3_IIF_BASE + vrf; 24869 rv = _bcm_tr_l3_ingress_interface_get(unit, NULL, &iif); 24870 if (BCM_FAILURE(rv)) { 24871 return rv; 24872 } 24873 iif.vrf = vrf; 24874 rv = _bcm_tr_l3_ingress_interface_set(unit, &iif, NULL, NULL); 24875 if (BCM_FAILURE(rv)) { 24876 return rv; 24877 } 24878 soc_MPLS_ENTRYm_field32_set(unit, &ment, L3_IIFf, 24879 _BCM_TR_MPLS_L3_IIF_BASE + vrf); 24880 } else { 24881 soc_MPLS_ENTRYm_field32_set(unit, &ment, L3_IIFf, info->ingress_if); 24882 } 24883 } else if (info->action == BCM_MPLS_SWITCH_ACTION_PHP) { 24884 24885 /* 24886 * Get egress next-hop index from egress object and 24887 * increment egress object reference count. 24888 */ 24889 24890 BCM_IF_ERROR_RETURN(bcm_xgs3_get_nh_from_egress_object(unit, info->egress_if, 24891 &mpath_flag, 1, &nh_index)); 24892 24893 if (mpath_flag != BCM_L3_MULTIPATH) { 24894 /* Fix: Entry_Type = 1, for PHP Packets with more than 1 Label */ 24895 /* Read the egress next_hop entry pointed by Egress-Object */ 24896 rv = bcm_tr_mpls_egress_entry_modify(unit, nh_index, mpath_flag, 1); 24897 if (rv < 0 ) { 24898 return rv; 24899 } 24900 } 24901 if (mpath_flag == BCM_L3_MULTIPATH) { 24902 soc_MPLS_ENTRYm_field32_set(unit, &ment, ECMP_PTRf, nh_index); 24903 } else { 24904 soc_MPLS_ENTRYm_field32_set(unit, &ment, NEXT_HOP_INDEXf, nh_index); 24905 } 24906 } else if (info->action == BCM_MPLS_SWITCH_ACTION_SWAP) { 24907 if (BCM_XGS3_L3_MPLS_LBL_VALID(info->egress_label.label)) { 24908 rv = bcm_tr_mpls_l3_nh_info_add(unit, info, &nh_index); 24909 if (rv < 0) { 24910 goto cleanup; 24911 } 24912 } else { 24913 rv = bcm_xgs3_get_nh_from_egress_object(unit, info->egress_if, 24914 &mpath_flag, 1, &nh_index); 24915 if (rv < 0) { 24916 return rv; 24917 } 24918 } 24919 soc_MPLS_ENTRYm_field32_set(unit, &ment, NEXT_HOP_INDEXf, nh_index); 24920 }/* BCM_MPLS_SWITCH_ACTION_SWAP */ 24921 24922 24923 soc_MPLS_ENTRYm_field32_set(unit, &ment, V4_ENABLEf, 1); 24924 soc_MPLS_ENTRYm_field32_set(unit, &ment, V6_ENABLEf, 1); 24925 if (info->flags & BCM_MPLS_SWITCH_INNER_TTL) { 24926 if (info->action == BCM_MPLS_SWITCH_ACTION_SWAP) { 24927 rv = BCM_E_PARAM; 24928 goto cleanup; 24929 } 24930 soc_MPLS_ENTRYm_field32_set(unit, &ment, DECAP_USE_TTLf, 0); 24931 } else { 24932 soc_MPLS_ENTRYm_field32_set(unit, &ment, DECAP_USE_TTLf, 1); 24933 } 24934 if (info->flags & BCM_MPLS_SWITCH_INNER_EXP) { 24935 if (info->action == BCM_MPLS_SWITCH_ACTION_SWAP) { 24936 rv = BCM_E_PARAM; 24937 goto cleanup; 24938 } 24939 soc_MPLS_ENTRYm_field32_set(unit, &ment, DECAP_USE_EXP_FOR_INNERf, 0); 24940 } else { 24941 /* For SWAP, Do-not PUSH EXP */ 24942 if (info->action == BCM_MPLS_SWITCH_ACTION_SWAP) { 24943 soc_MPLS_ENTRYm_field32_set(unit, &ment, DECAP_USE_EXP_FOR_INNERf, 0); 24944 } else { 24945 soc_MPLS_ENTRYm_field32_set(unit, &ment, DECAP_USE_EXP_FOR_INNERf, 1); 24946 } 24947 } 24948 24949 (void) bcm_tr_mpls_entry_internal_qos_set(unit, NULL, info, &ment); 24950 24951 if ((info->flags & BCM_MPLS_SWITCH_COUNTED)) { 24952 if (SOC_MEM_IS_VALID(unit, ING_PW_TERM_COUNTERSm)) { 24953 if (old_pw_cnt == -1) { 24954 num_pw_term = soc_mem_index_count(unit, ING_PW_TERM_COUNTERSm); 24955 for (pw_cnt = 0; pw_cnt < num_pw_term; pw_cnt++) { 24956 if (!_BCM_MPLS_PW_TERM_USED_GET(unit, pw_cnt)) { 24957 break; 24958 } 24959 } 24960 if (pw_cnt == num_pw_term) { 24961 rv = BCM_E_RESOURCE; 24962 goto cleanup; 24963 } 24964 _BCM_MPLS_PW_TERM_USED_SET(unit, pw_cnt); 24965 soc_MPLS_ENTRYm_field32_set(unit, &ment, PW_TERM_NUMf, pw_cnt); 24966 soc_MPLS_ENTRYm_field32_set(unit, &ment, PW_TERM_NUM_VALIDf, 1); 24967 } 24968 } 24969 } 24970 #ifdef BCM_TRIUMPH3_SUPPORT 24971 if (SOC_IS_TRIUMPH3(unit)) { 24972 soc_MPLS_ENTRYm_field32_set(unit, &ment, KEY_TYPEf, 0x10); 24973 } 24974 #endif 24975 24976 if (!tunnel_switch_update) { 24977 rv = soc_mem_insert(unit, MPLS_ENTRYm, MEM_BLOCK_ALL, &ment); 24978 } else { 24979 rv = soc_mem_write(unit, MPLS_ENTRYm, 24980 MEM_BLOCK_ALL, index, 24981 &ment); 24982 } 24983 24984 if (rv < 0) { 24985 goto cleanup; 24986 } 24987 24988 if (tunnel_switch_update) { 24989 /* Clean up old next-hop and counter info if entry was replaced */ 24990 if ((old_pw_cnt != -1) && !(info->flags & BCM_MPLS_SWITCH_COUNTED)) { 24991 _BCM_MPLS_PW_TERM_USED_CLR(unit, old_pw_cnt); 24992 } 24993 if (action == 0x3) { /* SWAP_NHI */ 24994 /* Check if tunnel_switch.egress_label mode is being used */ 24995 rv = bcm_tr_mpls_get_vp_nh (unit, (bcm_if_t) old_nh_index, &egress_if); 24996 if (rv == BCM_E_NONE) { 24997 rv = bcm_tr_mpls_l3_nh_info_delete(unit, old_nh_index); 24998 } else { 24999 /* Decrement next-hop Reference count */ 25000 rv = bcm_xgs3_get_ref_count_from_nhi(unit, 0, &ref_count, old_nh_index); 25001 } 25002 } else if (action == 0x4) { 25003 /* L3_NHI */ 25004 rv = bcm_xgs3_nh_del(unit, 0, old_nh_index); 25005 } else if (action == 0x5) { 25006 /* L3_ECMP */ 25007 rv = bcm_xgs3_ecmp_group_del(unit, old_ecmp_index, 0); 25008 } 25009 } 25010 if (rv < 0) { 25011 goto cleanup; 25012 } 25013 25014 #ifdef BCM_WARM_BOOT_SUPPORT 25015 SOC_CONTROL_LOCK(unit); 25016 SOC_CONTROL(unit)->scache_dirty = 1; 25017 SOC_CONTROL_UNLOCK(unit); 25018 #endif 25019 25020 return rv; 25021 25022 cleanup: 25023 if (pw_cnt != -1) { 25024 _BCM_MPLS_PW_TERM_USED_CLR(unit, pw_cnt); 25025 } 25026 if (nh_index != -1) { 25027 if (info->action == BCM_MPLS_SWITCH_ACTION_SWAP) { 25028 if (BCM_XGS3_L3_MPLS_LBL_VALID(info->egress_label.label) || 25029 (info->action == BCM_MPLS_SWITCH_ACTION_PHP)) { 25030 (void) bcm_tr_mpls_l3_nh_info_delete(unit, nh_index); 25031 } else { 25032 /* Decrement next-hop Reference count */ 25033 rv = bcm_xgs3_get_ref_count_from_nhi(unit, 0, &ref_count, nh_index); 25034 } 25035 } else if (info->action == BCM_MPLS_SWITCH_ACTION_PHP) { 25036 (void) bcm_xgs3_nh_del(unit, 0, nh_index); 25037 } 25038 } 25039 return rv; 25040 } 25041 25042 STATIC int 25043 _bcm_tr_mpls_entry_delete(int unit, mpls_entry_entry_t *ment) 25044 { 25045 ing_pw_term_counters_entry_t pw_cnt_entry; 25046 int rv, action, ecmp_index = -1, nh_index = -1, pw_cnt = -1; 25047 bcm_if_t egress_if=0; 25048 int ref_count=0; 25049 25050 if (soc_MPLS_ENTRYm_field32_get(unit, ment, PW_TERM_NUM_VALIDf)) { 25051 pw_cnt = soc_MPLS_ENTRYm_field32_get(unit, ment, PW_TERM_NUMf); 25052 } 25053 25054 action = soc_MPLS_ENTRYm_field32_get(unit, ment, MPLS_ACTION_IF_BOSf); 25055 if ((action == 0x3) || (action == 0x4)) { 25056 /* SWAP_NHI or L3_NHI */ 25057 nh_index = soc_MPLS_ENTRYm_field32_get(unit, ment, NEXT_HOP_INDEXf); 25058 } else if (action == 0x5) { 25059 /* L3_ECMP */ 25060 ecmp_index = soc_MPLS_ENTRYm_field32_get(unit, ment, ECMP_PTRf); 25061 } 25062 25063 /* Delete the entry from HW */ 25064 rv = soc_mem_delete(unit, MPLS_ENTRYm, MEM_BLOCK_ALL, ment); 25065 if ( (rv != BCM_E_NOT_FOUND) && (rv != BCM_E_NONE) ) { 25066 return rv; 25067 } 25068 25069 #if defined(BCM_TRIUMPH2_SUPPORT) 25070 if (soc_feature(unit, soc_feature_gport_service_counters) && 25071 (0 != soc_MPLS_ENTRYm_field32_get(unit, ment, 25072 USE_VINTF_CTR_IDXf)) && 25073 (0 != soc_MPLS_ENTRYm_field32_get(unit, ment, 25074 VINTF_CTR_IDXf))) { 25075 /* Release MPLS label stat use, if any */ 25076 _bcm_flex_stat_handle_t mpls_fsh; 25077 mpls_entry_entry_t fs_ment; 25078 uint32 key[2]; 25079 25080 sal_memset(&fs_ment, 0, sizeof(fs_ment)); 25081 /* Construct key-only entry, copy to FS handle */ 25082 soc_MPLS_ENTRYm_field32_set(unit, &fs_ment, VALIDf, 25083 soc_MPLS_ENTRYm_field32_get(unit, ment, VALIDf)); 25084 soc_mem_field_get(unit, MPLS_ENTRYm, (uint32 *) ment, 25085 KEYf, (uint32 *) key); 25086 soc_mem_field_set(unit, MPLS_ENTRYm, (uint32 *) &fs_ment, 25087 KEYf, (uint32 *) key); 25088 /* Technically, we should copy the KEY_TYPE field here, 25089 * but the rest of the MPLS code appears to abuse the fact that 25090 * the key type value is 0, so it was handled when we 25091 * cleared the entry above. 25092 */ 25093 25094 _BCM_FLEX_STAT_HANDLE_CLEAR(mpls_fsh); 25095 _BCM_FLEX_STAT_HANDLE_COPY(mpls_fsh, fs_ment); 25096 _bcm_esw_flex_stat_ext_handle_free(unit, 25097 _bcmFlexStatTypeMplsLabel, 25098 mpls_fsh); 25099 } 25100 #endif /* BCM_TRIUMPH2_SUPPORT */ 25101 25102 if (pw_cnt != -1) { 25103 sal_memset(&pw_cnt_entry, 0, sizeof(ing_pw_term_counters_entry_t)); 25104 (void) WRITE_ING_PW_TERM_COUNTERSm(unit, MEM_BLOCK_ALL, pw_cnt, 25105 &pw_cnt_entry); 25106 _BCM_MPLS_PW_TERM_USED_CLR(unit, pw_cnt); 25107 } 25108 25109 if (action == 0x3) { 25110 /* SWAP_NHI */ 25111 /* Check if tunnel_switch.egress_label mode is being used */ 25112 rv = bcm_tr_mpls_get_vp_nh (unit, (bcm_if_t) nh_index, &egress_if); 25113 if (rv == BCM_E_NONE) { 25114 rv = bcm_tr_mpls_l3_nh_info_delete(unit, nh_index); 25115 } else { 25116 /* Decrement next-hop Reference count */ 25117 rv = bcm_xgs3_get_ref_count_from_nhi(unit, 0, &ref_count, nh_index); 25118 } 25119 } else if (action == 0x4) { 25120 /* L3_NHI */ 25121 rv = bcm_xgs3_nh_del(unit, 0, nh_index); 25122 } else if (action == 0x5) { 25123 /* L3_ECMP */ 25124 rv = bcm_xgs3_ecmp_group_del(unit, ecmp_index, 0); 25125 } 25126 return rv; 25127 } 25128 25129 /* 25130 * Function: 25131 * bcm_mpls_tunnel_switch_delete 25132 * Purpose: 25133 * Delete an MPLS label entry. 25134 * Parameters: 25135 * unit - Device Number 25136 * info - Label (switch) information 25137 * Returns: 25138 * BCM_E_XXX 25139 */ 25140 int 25141 bcm_tr_mpls_tunnel_switch_delete(int unit, bcm_mpls_tunnel_switch_t *info) 25142 { 25143 int rv, index; 25144 mpls_entry_entry_t ment; 25145 25146 25147 rv = _bcm_tr_mpls_entry_set_key(unit, info, &ment); 25148 BCM_IF_ERROR_RETURN(rv); 25149 25150 rv = soc_mem_search(unit, MPLS_ENTRYm, MEM_BLOCK_ANY, &index, 25151 &ment, &ment, 0); 25152 if (rv < 0) { 25153 return rv; 25154 } 25155 rv = _bcm_tr_mpls_entry_delete(unit, &ment); 25156 25157 #ifdef BCM_WARM_BOOT_SUPPORT 25158 SOC_CONTROL_LOCK(unit); 25159 SOC_CONTROL(unit)->scache_dirty = 1; 25160 SOC_CONTROL_UNLOCK(unit); 25161 #endif 25162 25163 return rv; 25164 } 25165 25166 /* 25167 * Function: 25168 * bcm_mpls_tunnel_switch_delete_all 25169 * Purpose: 25170 * Delete all MPLS label entries. 25171 * Parameters: 25172 * unit - Device Number 25173 * Returns: 25174 * BCM_E_XXX 25175 */ 25176 int 25177 bcm_tr_mpls_tunnel_switch_delete_all(int unit) 25178 { 25179 int rv, i, num_entries; 25180 mpls_entry_entry_t *ment, *mentp; 25181 int imin, imax; 25182 soc_mem_t mem = MPLS_ENTRYm; 25183 soc_field_t validf = VALIDf; 25184 25185 if(soc_feature(unit, soc_feature_th3_style_simple_mpls)) { 25186 mem = MPLS_ENTRY_SINGLEm; 25187 validf = BASE_VALIDf; 25188 } 25189 25190 imin = soc_mem_index_min(unit, mem); 25191 imax = soc_mem_index_max(unit, mem); 25192 num_entries = soc_mem_index_count(unit, mem); 25193 25194 ment = soc_cm_salloc(unit, num_entries * sizeof(*ment), "mpls_entry"); 25195 if (ment == NULL) { 25196 return BCM_E_MEMORY; 25197 } 25198 sal_memset(ment, 0, num_entries * sizeof(*ment)); 25199 25200 rv = soc_mem_read_range(unit, mem, MEM_BLOCK_ANY, 25201 imin, imax, ment); 25202 if (BCM_FAILURE(rv)) { 25203 soc_cm_sfree(unit, ment); 25204 return rv; 25205 } 25206 for (i = 0; i < num_entries; i++) { 25207 mentp = soc_mem_table_idx_to_pointer(unit, mem, 25208 mpls_entry_entry_t *, ment, i); 25209 25210 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 25211 if ((soc_mem_field32_get(unit, mem, mentp, BASE_VALID_0f) == 0) || 25212 (soc_mem_field32_get(unit, mem, mentp, BASE_VALID_1f) == 0)) { 25213 continue; 25214 } 25215 } else { 25216 if (!soc_mem_field32_get(unit, mem, mentp, validf)) { 25217 continue; 25218 } 25219 } 25220 if (soc_mem_field32_get(unit, mem, mentp, 25221 MPLS_ACTION_IF_BOSf) == 0x1) { 25222 /* L2_SVP */ 25223 continue; 25224 } 25225 rv = _bcm_tr_mpls_entry_delete(unit, mentp); 25226 if (rv < 0) { 25227 soc_cm_sfree(unit, ment); 25228 return rv; 25229 } 25230 } 25231 soc_cm_sfree(unit, ment); 25232 25233 return BCM_E_NONE; 25234 } 25235 25236 /* 25237 * Function: 25238 * bcm_mpls_tunnel_switch_get 25239 * Purpose: 25240 * Get an MPLS label entry. 25241 * Parameters: 25242 * unit - Device Number 25243 * info - Label (switch) information 25244 * Returns: 25245 * BCM_E_XXX 25246 */ 25247 int 25248 bcm_tr_mpls_tunnel_switch_get(int unit, bcm_mpls_tunnel_switch_t *info) 25249 { 25250 int rv, index; 25251 mpls_entry_entry_t ment; 25252 25253 rv = _bcm_tr_mpls_entry_set_key(unit, info, &ment); 25254 25255 25256 BCM_IF_ERROR_RETURN(rv); 25257 25258 rv = soc_mem_search(unit, MPLS_ENTRYm, MEM_BLOCK_ANY, &index, 25259 &ment, &ment, 0); 25260 25261 if (rv < 0) { 25262 return rv; 25263 } 25264 rv = _bcm_tr_mpls_entry_get_data(unit, &ment, info); 25265 25266 return rv; 25267 } 25268 25269 /* 25270 * Function: 25271 * bcm_mpls_tunnel_switch_traverse 25272 * Purpose: 25273 * Traverse all valid MPLS label entries an call the 25274 * supplied callback routine. 25275 * Parameters: 25276 * unit - Device Number 25277 * cb - User callback function, called once per MPLS entry. 25278 * user_data - cookie 25279 * Returns: 25280 * BCM_E_XXX 25281 */ 25282 int 25283 bcm_tr_mpls_tunnel_switch_traverse(int unit, 25284 bcm_mpls_tunnel_switch_traverse_cb cb, 25285 void *user_data) 25286 { 25287 int rv, i, num_entries; 25288 mpls_entry_entry_t ment; 25289 bcm_mpls_tunnel_switch_t info; 25290 25291 25292 25293 25294 num_entries = soc_mem_index_count(unit, MPLS_ENTRYm); 25295 for (i = 0; i < num_entries; i++) { 25296 BCM_IF_ERROR_RETURN (READ_MPLS_ENTRYm(unit, MEM_BLOCK_ANY, i, &ment)); 25297 /* Check MPLS Key_type */ 25298 if (soc_feature(unit, soc_feature_mpls_enhanced)) { 25299 if (0x0 != soc_MPLS_ENTRYm_field32_get(unit, &ment, KEY_TYPEf)) { 25300 continue; 25301 } 25302 } 25303 /* Check for valid entry */ 25304 if (!soc_MPLS_ENTRYm_field32_get(unit, &ment, VALIDf)) { 25305 continue; 25306 } 25307 if (soc_MPLS_ENTRYm_field32_get(unit, &ment, 25308 MPLS_ACTION_IF_BOSf) == 0x1) { 25309 /* L2_SVP */ 25310 continue; 25311 } 25312 sal_memset(&info, 0, sizeof(bcm_mpls_tunnel_switch_t)); 25313 rv = _bcm_tr_mpls_entry_get_key(unit, &ment, &info); 25314 if (rv < 0) { 25315 return rv; 25316 } 25317 rv = _bcm_tr_mpls_entry_get_data(unit, &ment, &info); 25318 if (rv < 0) { 25319 return rv; 25320 } 25321 25322 #ifndef BCM_CB_ABORT_ON_ERR 25323 (void) cb(unit, &info, user_data); 25324 #else 25325 rv = cb(unit, &info, user_data); 25326 if (BCM_FAILURE(rv) && SOC_CB_ABORT_ON_ERR(unit)) { 25327 return rv; 25328 } 25329 #endif 25330 } 25331 return BCM_E_NONE; 25332 } 25333 25334 /* 25335 * Function: 25336 * bcm_mpls_exp_map_create 25337 * Purpose: 25338 * Create an MPLS EXP map instance. 25339 * Parameters: 25340 * unit - (IN) SOC unit # 25341 * flags - (IN) MPLS flags 25342 * exp_map_id - (OUT) Allocated EXP map ID 25343 * Returns: 25344 * BCM_E_XXX 25345 */ 25346 int 25347 bcm_tr_mpls_exp_map_create(int unit, uint32 flags, int *exp_map_id) 25348 { 25349 int i, table_num, num_exp_map; 25350 egr_mpls_pri_mapping_entry_t egr_mpls_pri_map[64]; 25351 egr_mpls_exp_mapping_1_entry_t egr_mpls_exp_map[64]; 25352 egr_mpls_exp_mapping_2_entry_t egr_mpls_exp_map2[64]; 25353 int id, index = -1; 25354 void *entries[3]; 25355 25356 /* Check for unsupported Flag */ 25357 if (flags & (~(BCM_MPLS_EXP_MAP_WITH_ID | 25358 BCM_MPLS_EXP_MAP_INGRESS | 25359 BCM_MPLS_EXP_MAP_EGRESS | 25360 BCM_MPLS_EXP_MAP_EGRESS_L2 ))) { 25361 return BCM_E_PARAM; 25362 } 25363 25364 /* Input parameters check. */ 25365 if (NULL == exp_map_id) { 25366 return BCM_E_PARAM; 25367 } 25368 25369 if (flags & BCM_MPLS_EXP_MAP_INGRESS) { 25370 /* ING_MPLS_EXP_MAPPING profiles indexed by EXP */ 25371 num_exp_map = _bcm_tr_get_ing_mpls_index_size(unit); 25372 25373 if (flags & BCM_MPLS_EXP_MAP_WITH_ID) { 25374 table_num = (*exp_map_id & _BCM_TR_MPLS_EXP_MAP_TABLE_NUM_MASK); 25375 if (table_num >= num_exp_map) { 25376 return BCM_E_PARAM; 25377 } 25378 if (_BCM_MPLS_ING_EXP_MAP_USED_GET(unit, table_num)) { 25379 return BCM_E_EXISTS; 25380 } 25381 _BCM_MPLS_ING_EXP_MAP_USED_SET(unit, table_num); 25382 #ifdef BCM_WARM_BOOT_SUPPORT 25383 SOC_CONTROL_LOCK(unit); 25384 SOC_CONTROL(unit)->scache_dirty = 1; 25385 SOC_CONTROL_UNLOCK(unit); 25386 #endif 25387 return BCM_E_NONE; 25388 } 25389 25390 for (i = 0; i < num_exp_map; i++) { 25391 if (!_BCM_MPLS_ING_EXP_MAP_USED_GET(unit, i)) { 25392 _BCM_MPLS_ING_EXP_MAP_USED_SET(unit, i); 25393 *exp_map_id = (i | _BCM_TR_MPLS_EXP_MAP_TABLE_TYPE_INGRESS); 25394 #ifdef BCM_WARM_BOOT_SUPPORT 25395 SOC_CONTROL_LOCK(unit); 25396 SOC_CONTROL(unit)->scache_dirty = 1; 25397 SOC_CONTROL_UNLOCK(unit); 25398 #endif 25399 return BCM_E_NONE; 25400 } 25401 } 25402 25403 } else if (flags & BCM_MPLS_EXP_MAP_EGRESS) { 25404 /* EGR_MPLS_EXP_MAPPING_1 profiles indexed by ((int_pri << 2) + cng) */ 25405 num_exp_map = soc_mem_index_count(unit, EGR_MPLS_EXP_MAPPING_1m) / 64; 25406 25407 if (flags & BCM_MPLS_EXP_MAP_WITH_ID) { 25408 table_num = (*exp_map_id & _BCM_TR_MPLS_EXP_MAP_TABLE_NUM_MASK); 25409 if (table_num >= num_exp_map) { 25410 return BCM_E_PARAM; 25411 } 25412 if (!_BCM_EGR_MPLS_MAP_USED_GET(unit, table_num)) { 25413 /* 25414 * Reserve a chunk in the EGR_MPLS_EXP_MAPPING_1 and 25415 * EGR_MPLS_PRI_MAPPING tables. These two tables always 25416 * done together. 25417 */ 25418 #if defined(BCM_TRIDENT3_SUPPORT) 25419 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 25420 BCM_IF_ERROR_RETURN( 25421 bcm_td3_qos_map_create(unit, (uint32 *)&index, 64)); 25422 } else 25423 #endif 25424 { 25425 sal_memset(egr_mpls_pri_map, 0, sizeof(egr_mpls_pri_map)); 25426 entries[0] = egr_mpls_pri_map; 25427 sal_memset(egr_mpls_exp_map, 0, sizeof(egr_mpls_exp_map)); 25428 entries[1] = egr_mpls_exp_map; 25429 sal_memset(egr_mpls_exp_map2, 0, sizeof(egr_mpls_exp_map2)); 25430 entries[2] = egr_mpls_exp_map2; 25431 BCM_IF_ERROR_RETURN 25432 (_bcm_egr_mpls_combo_map_entry_add(unit, entries, 64, 25433 (uint32 *)&index)); 25434 } 25435 MPLS_INFO(unit)->egr_mpls_hw_idx[table_num] = index / 64; 25436 _BCM_EGR_MPLS_MAP_USED_SET(unit, table_num); 25437 } else { 25438 return BCM_E_EXISTS; 25439 } 25440 #ifdef BCM_WARM_BOOT_SUPPORT 25441 SOC_CONTROL_LOCK(unit); 25442 SOC_CONTROL(unit)->scache_dirty = 1; 25443 SOC_CONTROL_UNLOCK(unit); 25444 #endif 25445 return BCM_E_NONE; 25446 } 25447 25448 for (id = 0; id < num_exp_map; id++) { 25449 if (!_BCM_EGR_MPLS_MAP_USED_GET(unit, id)) { 25450 *exp_map_id = (id | _BCM_TR_MPLS_EXP_MAP_TABLE_TYPE_EGRESS); 25451 /* 25452 * Reserve a chunk in the EGR_MPLS_EXP_MAPPING_1 and 25453 * EGR_MPLS_PRI_MAPPING tables. These two tables always 25454 * done together. 25455 */ 25456 #if defined(BCM_TRIDENT3_SUPPORT) 25457 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 25458 BCM_IF_ERROR_RETURN( 25459 bcm_td3_qos_map_create(unit, (uint32 *)&index, 64)); 25460 } else 25461 #endif 25462 { 25463 sal_memset(egr_mpls_pri_map, 0, sizeof(egr_mpls_pri_map)); 25464 entries[0] = egr_mpls_pri_map; 25465 sal_memset(egr_mpls_exp_map, 0, sizeof(egr_mpls_exp_map)); 25466 entries[1] = egr_mpls_exp_map; 25467 sal_memset(egr_mpls_exp_map2, 0, sizeof(egr_mpls_exp_map2)); 25468 entries[2] = egr_mpls_exp_map2; 25469 BCM_IF_ERROR_RETURN 25470 (_bcm_egr_mpls_combo_map_entry_add(unit, entries, 64, 25471 (uint32 *)&index)); 25472 } 25473 MPLS_INFO(unit)->egr_mpls_hw_idx[id] = index / 64; 25474 _BCM_EGR_MPLS_MAP_USED_SET(unit, id); 25475 #ifdef BCM_WARM_BOOT_SUPPORT 25476 SOC_CONTROL_LOCK(unit); 25477 SOC_CONTROL(unit)->scache_dirty = 1; 25478 SOC_CONTROL_UNLOCK(unit); 25479 #endif 25480 return BCM_E_NONE; 25481 } 25482 } 25483 } else if (flags & BCM_MPLS_EXP_MAP_EGRESS_L2) { 25484 /* EGR_MPLS_EXP_PRI_MAPPINGm profiles indexed by EXP */ 25485 num_exp_map = bcmi_egr_mpls_exp_pri_mapping_num_exp_map_get(unit); 25486 25487 if (flags & BCM_MPLS_EXP_MAP_WITH_ID) { 25488 table_num = (*exp_map_id & _BCM_TR_MPLS_EXP_MAP_TABLE_NUM_MASK); 25489 if (table_num > num_exp_map) { 25490 return BCM_E_PARAM; 25491 } 25492 if (_BCM_MPLS_EGR_EXP_MAP_USED_GET(unit, table_num)) { 25493 return BCM_E_EXISTS; 25494 } 25495 _BCM_MPLS_EGR_EXP_MAP_USED_SET(unit, table_num); 25496 #ifdef BCM_WARM_BOOT_SUPPORT 25497 SOC_CONTROL_LOCK(unit); 25498 SOC_CONTROL(unit)->scache_dirty = 1; 25499 SOC_CONTROL_UNLOCK(unit); 25500 #endif 25501 return BCM_E_NONE; 25502 } 25503 25504 for (i = 0; i < num_exp_map; i++) { 25505 if (!_BCM_MPLS_EGR_EXP_MAP_USED_GET(unit, i)) { 25506 _BCM_MPLS_EGR_EXP_MAP_USED_SET(unit, i); 25507 #ifdef BCM_WARM_BOOT_SUPPORT 25508 SOC_CONTROL_LOCK(unit); 25509 SOC_CONTROL(unit)->scache_dirty = 1; 25510 SOC_CONTROL_UNLOCK(unit); 25511 #endif 25512 *exp_map_id = (i | _BCM_TR_MPLS_EXP_MAP_TABLE_TYPE_EGRESS_L2); 25513 return BCM_E_NONE; 25514 } 25515 } 25516 } else { 25517 return BCM_E_PARAM; 25518 } 25519 return BCM_E_FULL; 25520 } 25521 25522 /* 25523 * Function: 25524 * bcm_mpls_exp_map_destroy 25525 * Purpose: 25526 * Destroy an existing MPLS EXP map instance. 25527 * Parameters: 25528 * unit - (IN) SOC unit # 25529 * exp_map_id - (IN) EXP map ID 25530 * Returns: 25531 * BCM_E_XXX 25532 */ 25533 int 25534 bcm_tr_mpls_exp_map_destroy(int unit, int exp_map_id) 25535 { 25536 int num_exp_map, table_num, base_idx; 25537 25538 if (exp_map_id < 0) { 25539 return BCM_E_PARAM; 25540 } 25541 table_num = exp_map_id & _BCM_TR_MPLS_EXP_MAP_TABLE_NUM_MASK; 25542 25543 if ((exp_map_id & _BCM_TR_MPLS_EXP_MAP_TABLE_TYPE_MASK) == 25544 _BCM_TR_MPLS_EXP_MAP_TABLE_TYPE_INGRESS) { 25545 25546 /* ING_MPLS_EXP_MAPPING profiles indexed by EXP */ 25547 num_exp_map = _bcm_tr_get_ing_mpls_index_size(unit); 25548 if (table_num >= num_exp_map) { 25549 return BCM_E_PARAM; 25550 } 25551 if (!_BCM_MPLS_ING_EXP_MAP_USED_GET(unit, table_num)) { 25552 return BCM_E_NOT_FOUND; 25553 } 25554 _BCM_MPLS_ING_EXP_MAP_USED_CLR(unit, table_num); 25555 #ifdef BCM_WARM_BOOT_SUPPORT 25556 SOC_CONTROL_LOCK(unit); 25557 SOC_CONTROL(unit)->scache_dirty = 1; 25558 SOC_CONTROL_UNLOCK(unit); 25559 #endif 25560 } else if ((exp_map_id & _BCM_TR_MPLS_EXP_MAP_TABLE_TYPE_MASK) == 25561 _BCM_TR_MPLS_EXP_MAP_TABLE_TYPE_EGRESS) { 25562 /* EGR_MPLS_EXP_MAPPING_1 profiles indexed by ((int_pri << 2) + cng) */ 25563 num_exp_map = soc_mem_index_count(unit, EGR_MPLS_EXP_MAPPING_1m) / 64; 25564 25565 if (table_num >= num_exp_map) { 25566 return BCM_E_PARAM; 25567 } 25568 if (!_BCM_EGR_MPLS_MAP_USED_GET(unit, table_num)) { 25569 return BCM_E_NOT_FOUND; 25570 } 25571 base_idx = MPLS_INFO(unit)->egr_mpls_hw_idx[table_num] * 64; 25572 _BCM_EGR_MPLS_MAP_USED_CLR(unit, table_num); 25573 #ifdef BCM_WARM_BOOT_SUPPORT 25574 SOC_CONTROL_LOCK(unit); 25575 SOC_CONTROL(unit)->scache_dirty = 1; 25576 SOC_CONTROL_UNLOCK(unit); 25577 #endif 25578 /* Clear from profile memories */ 25579 BCM_IF_ERROR_RETURN 25580 (_bcm_egr_mpls_combo_map_entry_delete(unit, base_idx)); 25581 } else if ((exp_map_id & _BCM_TR_MPLS_EXP_MAP_TABLE_TYPE_MASK) == 25582 _BCM_TR_MPLS_EXP_MAP_TABLE_TYPE_EGRESS_L2) { 25583 25584 /* EGR_MPLS_EXP_PRI_MAPPINGm profiles indexed by EXP */ 25585 num_exp_map = bcmi_egr_mpls_exp_pri_mapping_num_exp_map_get(unit); 25586 if (table_num >= num_exp_map) { 25587 return BCM_E_PARAM; 25588 } 25589 if (!_BCM_MPLS_EGR_EXP_MAP_USED_GET(unit, table_num)) { 25590 return BCM_E_NOT_FOUND; 25591 } 25592 _BCM_MPLS_EGR_EXP_MAP_USED_CLR(unit, table_num); 25593 #ifdef BCM_WARM_BOOT_SUPPORT 25594 SOC_CONTROL_LOCK(unit); 25595 SOC_CONTROL(unit)->scache_dirty = 1; 25596 SOC_CONTROL_UNLOCK(unit); 25597 #endif 25598 } else { 25599 return BCM_E_PARAM; 25600 } 25601 25602 return BCM_E_NONE; 25603 } 25604 25605 /* 25606 * Function: 25607 * bcm_mpls_exp_map_destroy_all 25608 * Purpose: 25609 * Destroy all existing MPLS EXP map instances. 25610 * Parameters: 25611 * unit - (IN) SOC unit # 25612 * Returns: 25613 * BCM_E_XXX 25614 */ 25615 int 25616 bcm_tr_mpls_exp_map_destroy_all(int unit) 25617 { 25618 int i, num_exp_map, base_idx; 25619 int rv = BCM_E_NONE; 25620 25621 25622 /* ING_MPLS_EXP_MAPPING profiles indexed by EXP */ 25623 num_exp_map = _bcm_tr_get_ing_mpls_index_size(unit); 25624 for (i = 0; i < num_exp_map; i++) { 25625 if (_BCM_MPLS_ING_EXP_MAP_USED_GET(unit, i)) { 25626 _BCM_MPLS_ING_EXP_MAP_USED_CLR(unit, i); 25627 } 25628 } 25629 25630 /* EGR_MPLS_EXP_MAPPING_1 profiles indexed by ((int_pri << 2) + cng) */ 25631 num_exp_map = soc_mem_index_count(unit, EGR_MPLS_EXP_MAPPING_1m) / 64; 25632 25633 for (i = 0; i < num_exp_map; i++) { 25634 if (_BCM_EGR_MPLS_MAP_USED_GET(unit, i)) { 25635 _BCM_EGR_MPLS_MAP_USED_CLR(unit, i); 25636 base_idx = MPLS_INFO(unit)->egr_mpls_hw_idx[i] * 64; 25637 /* Clear from profile memories */ 25638 rv = _bcm_egr_mpls_combo_map_entry_delete(unit, base_idx); 25639 if ((rv != BCM_E_NONE) && (rv != BCM_E_NOT_FOUND)) { 25640 return rv; 25641 } 25642 } 25643 } 25644 25645 /* EGR_MPLS_EXP_PRI_MAPPINGm profiles indexed by EXP */ 25646 num_exp_map = bcmi_egr_mpls_exp_pri_mapping_num_exp_map_get(unit); 25647 for (i = 0; i < num_exp_map; i++) { 25648 if (_BCM_MPLS_EGR_EXP_MAP_USED_GET(unit, i)) { 25649 _BCM_MPLS_EGR_EXP_MAP_USED_CLR(unit, i); 25650 } 25651 } 25652 25653 return BCM_E_NONE; 25654 } 25655 25656 25657 /* 25658 * Function: 25659 * bcm_mpls_exp_map_set 25660 * Purpose: 25661 * Set the mapping of { internal priority, color } 25662 * to a EXP value for MPLS headers 25663 * in the specified EXP map instance. 25664 * Parameters: 25665 * unit - (IN) SOC unit # 25666 * exp_map_id - (IN) EXP map ID 25667 * map - (IN) EXP map config structure 25668 * Returns: 25669 * BCM_E_XXX 25670 */ 25671 int 25672 bcm_tr_mpls_exp_map_set(int unit, int exp_map_id, 25673 bcm_mpls_exp_map_t *map) 25674 { 25675 int table_num, num_exp_map, cng, rv, index; 25676 #if defined(BCM_TRIDENT3_SUPPORT) 25677 egr_mpls_pri_mapping_entry_t exp_mpls_pri_entry; 25678 #endif 25679 egr_mpls_exp_pri_mapping_entry_t exp_pri_entry; 25680 uint32 ing_pri_entry[SOC_MAX_MEM_FIELD_WORDS]; 25681 int max_int_pri = 15; 25682 soc_mem_t mem; 25683 soc_field_t pri_field; 25684 int mode = 0; 25685 25686 /* Check validity of exp_map_id */ 25687 if (exp_map_id < 0) { 25688 return BCM_E_PARAM; 25689 } 25690 25691 if (!map) { 25692 /* invalid pointer to map data */ 25693 return BCM_E_PARAM; 25694 } 25695 25696 table_num = exp_map_id & _BCM_TR_MPLS_EXP_MAP_TABLE_NUM_MASK; 25697 25698 if ((exp_map_id & _BCM_TR_MPLS_EXP_MAP_TABLE_TYPE_MASK) == 25699 _BCM_TR_MPLS_EXP_MAP_TABLE_TYPE_INGRESS) { 25700 25701 /* ING_MPLS_EXP_MAPPING profiles indexed by EXP */ 25702 num_exp_map = _bcm_tr_get_ing_mpls_index_size(unit); 25703 25704 if (!_BCM_MPLS_ING_EXP_MAP_USED_GET(unit, table_num)) { 25705 return BCM_E_NOT_FOUND; 25706 } 25707 25708 if ((map->priority < BCM_PRIO_MIN) || (map->priority > max_int_pri) || 25709 (map->exp > 7)) { 25710 return BCM_E_PARAM; 25711 } 25712 25713 cng = _BCM_COLOR_ENCODING(unit, map->color); 25714 25715 /* Commit to HW */ 25716 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 25717 mem = PHB_MAPPING_TBL_3m; 25718 pri_field = INT_PRIf; 25719 /* 6 bit QOS field and 8-bit profile index 25720 * Max 32 profiles are supported from mpls_entry 25721 * Key is packet exp and profile index from mpls-entry */ 25722 index = (table_num << 6) | map->exp; 25723 } else { 25724 mem = ING_MPLS_EXP_MAPPINGm; 25725 pri_field = PRIf; 25726 /* Get the base index for this EXP map */ 25727 index = (table_num * 8) + map->exp; 25728 } 25729 25730 rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, index, ing_pri_entry); 25731 if (BCM_FAILURE(rv)) { 25732 return rv; 25733 } 25734 soc_mem_field32_set(unit, mem, ing_pri_entry, pri_field, map->priority); 25735 soc_mem_field32_set(unit, mem, ing_pri_entry, CNGf, cng); 25736 25737 if (SOC_MEM_FIELD_VALID(unit, mem, DSCPf)) { 25738 #if defined(BCM_TRIDENT3_SUPPORT) 25739 if(soc_feature(unit, soc_feature_td3_style_mpls) && map->dscp == EXP_MAP_DSCP_INVALID) { 25740 } else 25741 #endif 25742 { 25743 if (map->dscp >= (1 << soc_mem_field_length(unit, mem, DSCPf))) { 25744 return BCM_E_PARAM; 25745 } 25746 soc_mem_field32_set(unit, mem, ing_pri_entry, DSCPf, map->dscp); 25747 } 25748 #if defined(BCM_TRIDENT3_SUPPORT) 25749 if (SOC_MEM_FIELD_VALID(unit, mem, DSCP_VALIDf)) { 25750 if (map->dscp != EXP_MAP_DSCP_INVALID) { 25751 soc_mem_field32_set(unit, mem, ing_pri_entry, DSCP_VALIDf, 1); 25752 } else { 25753 soc_mem_field32_set(unit, mem, ing_pri_entry, DSCP_VALIDf, 0); 25754 } 25755 } 25756 #endif 25757 } 25758 rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, index, ing_pri_entry); 25759 if (BCM_FAILURE(rv)) { 25760 return rv; 25761 } 25762 } else if 25763 ((exp_map_id & _BCM_TR_MPLS_EXP_MAP_TABLE_TYPE_MASK) == 25764 _BCM_TR_MPLS_EXP_MAP_TABLE_TYPE_EGRESS) { 25765 25766 /* EGR_MPLS_EXP_MAPPING_1 profiles indexed by ((int_pri << 2) + cng) */ 25767 num_exp_map = soc_mem_index_count(unit, EGR_MPLS_EXP_MAPPING_1m) / 64; 25768 25769 if ((map == NULL) || (table_num >= num_exp_map) || 25770 (map->priority < BCM_PRIO_MIN) || (map->priority > max_int_pri) || 25771 (map->exp > 7) || (map->pkt_pri > 7) || (map->pkt_cfi > 1)) { 25772 return BCM_E_PARAM; 25773 } 25774 25775 if (!_BCM_EGR_MPLS_MAP_USED_GET(unit, table_num)) { 25776 return BCM_E_NOT_FOUND; 25777 } 25778 25779 #ifdef BCM_TRIDENT3_SUPPORT 25780 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 25781 rv = bcm_td3_mpls_combo_add(unit, BCM_QOS_MAP_EGRESS, map, exp_map_id, 25782 MPLS_INFO(unit)->egr_mpls_hw_idx[table_num], 64); 25783 25784 if (BCM_FAILURE(rv)) { 25785 return (rv); 25786 } 25787 } else 25788 #endif 25789 { 25790 int alloc_size, offset; 25791 egr_mpls_pri_mapping_entry_t *egr_mpls_pri_map; 25792 egr_mpls_exp_mapping_1_entry_t *egr_mpls_exp_map; 25793 egr_mpls_exp_mapping_2_entry_t *egr_mpls_exp_map2; 25794 void *entries[3]; 25795 uint32 *entry; 25796 25797 /* Allocate memory for DMA */ 25798 alloc_size = 64 * sizeof (egr_mpls_pri_mapping_entry_t); 25799 egr_mpls_pri_map = soc_cm_salloc(unit, alloc_size, 25800 "TR2 egr mpls pri map"); 25801 if (NULL == egr_mpls_pri_map) { 25802 return (BCM_E_MEMORY); 25803 } 25804 sal_memset(egr_mpls_pri_map, 0, alloc_size); 25805 25806 alloc_size = 64 * sizeof (egr_mpls_exp_mapping_1_entry_t); 25807 egr_mpls_exp_map = soc_cm_salloc(unit, alloc_size, 25808 "TR2 egr mpls exp map"); 25809 if (NULL == egr_mpls_exp_map) { 25810 sal_free(egr_mpls_pri_map); 25811 return (BCM_E_MEMORY); 25812 } 25813 sal_memset(egr_mpls_exp_map, 0, alloc_size); 25814 25815 alloc_size = 64 * sizeof (egr_mpls_exp_mapping_2_entry_t); 25816 egr_mpls_exp_map2 = soc_cm_salloc(unit, alloc_size, 25817 "TR2 egr mpls exp map2"); 25818 if (NULL == egr_mpls_exp_map2) { 25819 sal_free(egr_mpls_pri_map); 25820 sal_free(egr_mpls_exp_map); 25821 return (BCM_E_MEMORY); 25822 } 25823 sal_memset(egr_mpls_exp_map2, 0, alloc_size); 25824 25825 /* Base index of table in hardware */ 25826 index = MPLS_INFO(unit)->egr_mpls_hw_idx[table_num] * 64; 25827 25828 /* Offset within table */ 25829 cng = _BCM_COLOR_ENCODING(unit, map->color); 25830 offset = (map->priority << 2) | cng; 25831 25832 /* Read the old profile chunk */ 25833 rv = soc_mem_read_range(unit, EGR_MPLS_PRI_MAPPINGm, MEM_BLOCK_ANY, 25834 index, index + 63, egr_mpls_pri_map); 25835 if (BCM_FAILURE(rv)) { 25836 soc_cm_sfree(unit, egr_mpls_pri_map); 25837 soc_cm_sfree(unit, egr_mpls_exp_map); 25838 return (rv); 25839 } 25840 if (SOC_MEM_IS_VALID(unit, EGR_MPLS_EXP_MAPPING_1m)) { 25841 rv = soc_mem_read_range(unit, EGR_MPLS_EXP_MAPPING_1m, MEM_BLOCK_ANY, 25842 index, index + 63, egr_mpls_exp_map); 25843 if (BCM_FAILURE(rv)) { 25844 soc_cm_sfree(unit, egr_mpls_pri_map); 25845 soc_cm_sfree(unit, egr_mpls_exp_map); 25846 return (rv); 25847 } 25848 } 25849 25850 if (SOC_MEM_IS_VALID(unit, EGR_MPLS_EXP_MAPPING_2m)) { 25851 rv = soc_mem_read_range(unit, EGR_MPLS_EXP_MAPPING_2m, MEM_BLOCK_ANY, 25852 index, index + 63, egr_mpls_exp_map2); 25853 if (BCM_FAILURE(rv)) { 25854 soc_cm_sfree(unit, egr_mpls_pri_map); 25855 soc_cm_sfree(unit, egr_mpls_exp_map); 25856 soc_cm_sfree(unit, egr_mpls_exp_map2); 25857 return (rv); 25858 } 25859 } 25860 25861 /* Modify what's needed */ 25862 entry = (uint32 *)&egr_mpls_pri_map[offset]; 25863 sal_memcpy(entry, soc_mem_entry_null(unit, EGR_MPLS_PRI_MAPPINGm), 25864 soc_mem_entry_words(unit, EGR_MPLS_PRI_MAPPINGm) * 4); 25865 soc_mem_field32_set(unit, EGR_MPLS_PRI_MAPPINGm, entry, 25866 NEW_PRIf, map->pkt_pri); 25867 soc_mem_field32_set(unit, EGR_MPLS_PRI_MAPPINGm, entry, 25868 NEW_CFIf, map->pkt_cfi); 25869 if (SOC_MEM_IS_VALID(unit, EGR_MPLS_EXP_MAPPING_1m)) { 25870 entry = (uint32 *)&egr_mpls_exp_map[offset]; 25871 sal_memcpy(entry, soc_mem_entry_null(unit, EGR_MPLS_EXP_MAPPING_1m), 25872 soc_mem_entry_words(unit, EGR_MPLS_EXP_MAPPING_1m) * 4); 25873 soc_mem_field32_set(unit, EGR_MPLS_EXP_MAPPING_1m, entry, 25874 MPLS_EXPf, map->exp); 25875 } 25876 if (SOC_MEM_IS_VALID(unit, EGR_MPLS_EXP_MAPPING_2m)) { 25877 entry = (uint32 *)&egr_mpls_exp_map2[offset]; 25878 sal_memcpy(entry, soc_mem_entry_null(unit, EGR_MPLS_EXP_MAPPING_2m), 25879 soc_mem_entry_words(unit, EGR_MPLS_EXP_MAPPING_2m) * 4); 25880 soc_mem_field32_set(unit, EGR_MPLS_EXP_MAPPING_2m, entry, 25881 MPLS_EXPf, map->exp); 25882 } 25883 25884 /* Update hardware tables */ 25885 entries[0] = egr_mpls_pri_map; 25886 entries[1] = egr_mpls_exp_map; 25887 entries[2] = egr_mpls_exp_map2; 25888 rv = _bcm_egr_mpls_combo_map_entry_update(unit, entries, index); 25889 if (rv == SOC_E_NONE) { 25890 /* reference count increment occurs in entry_update only in dma mode, 25891 * hence deecrease the profile ref_count increased by entry_update */ 25892 rv = _bcm_egr_mpls_combo_map_entry_write_mode_get(unit, index, &mode); 25893 if ((rv == SOC_E_NONE) && (mode == SOC_PROFILE_MEM_WRITE_DMA_MODE)) { 25894 rv = _bcm_egr_mpls_combo_map_entry_delete(unit, index); 25895 } 25896 } 25897 25898 /* Free the DMA memory */ 25899 soc_cm_sfree(unit, egr_mpls_pri_map); 25900 soc_cm_sfree(unit, egr_mpls_exp_map); 25901 soc_cm_sfree(unit, egr_mpls_exp_map2); 25902 } 25903 25904 #ifdef BCM_WARM_BOOT_SUPPORT 25905 SOC_CONTROL_LOCK(unit); 25906 SOC_CONTROL(unit)->scache_dirty = 1; 25907 SOC_CONTROL_UNLOCK(unit); 25908 #endif 25909 } else if 25910 ((exp_map_id & _BCM_TR_MPLS_EXP_MAP_TABLE_TYPE_MASK) == 25911 _BCM_TR_MPLS_EXP_MAP_TABLE_TYPE_EGRESS_L2) { 25912 25913 if ((map->exp > 7) || (map->pkt_pri > 7) || (map->pkt_cfi > 1)) { 25914 return BCM_E_PARAM; 25915 } 25916 25917 /* EGR_MPLS_EXP_PRI_MAPPINGm profiles indexed by EXP */ 25918 num_exp_map = bcmi_egr_mpls_exp_pri_mapping_num_exp_map_get(unit); 25919 25920 /* index = Base index + Offset for this EXP map */ 25921 index = (table_num * 8) + map->exp; 25922 25923 if (!_BCM_MPLS_EGR_EXP_MAP_USED_GET(unit, table_num)) { 25924 return BCM_E_NOT_FOUND; 25925 } 25926 25927 #if defined(BCM_TRIDENT3_SUPPORT) 25928 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 25929 BCM_IF_ERROR_RETURN(READ_EGR_MPLS_PRI_MAPPINGm(unit, MEM_BLOCK_ANY, 25930 index, &exp_mpls_pri_entry)); 25931 soc_EGR_MPLS_PRI_MAPPINGm_field32_set(unit, &exp_mpls_pri_entry, 25932 NEW_PRIf, map->pkt_pri); 25933 soc_EGR_MPLS_PRI_MAPPINGm_field32_set(unit, &exp_mpls_pri_entry, 25934 NEW_CFIf, map->pkt_cfi); 25935 BCM_IF_ERROR_RETURN(WRITE_EGR_MPLS_PRI_MAPPINGm(unit, MEM_BLOCK_ALL, 25936 index, &exp_mpls_pri_entry)); 25937 } else 25938 #endif 25939 { 25940 BCM_IF_ERROR_RETURN(READ_EGR_MPLS_EXP_PRI_MAPPINGm(unit, MEM_BLOCK_ANY, 25941 index, &exp_pri_entry)); 25942 soc_EGR_MPLS_EXP_PRI_MAPPINGm_field32_set(unit, &exp_pri_entry, 25943 NEW_PRIf, map->pkt_pri); 25944 soc_EGR_MPLS_EXP_PRI_MAPPINGm_field32_set(unit, &exp_pri_entry, 25945 NEW_CFIf, map->pkt_cfi); 25946 BCM_IF_ERROR_RETURN(WRITE_EGR_MPLS_EXP_PRI_MAPPINGm(unit, MEM_BLOCK_ALL, 25947 index, &exp_pri_entry)); 25948 } 25949 25950 } else { 25951 return BCM_E_PARAM; 25952 } 25953 25954 return BCM_E_NONE; 25955 } 25956 25957 /* 25958 * Function: 25959 * bcm_mpls_exp_map_get 25960 * Purpose: 25961 * Get the mapping of { internal priority, color } 25962 * to a EXP value for MPLS headers 25963 * in the specified EXP map instance. 25964 * Parameters: 25965 * unit - (IN) SOC unit # 25966 * exp_map_id - (IN) EXP map ID 25967 * map - (OUT) EXP map config structure 25968 * Returns: 25969 * BCM_E_XXX 25970 */ 25971 int 25972 bcm_tr_mpls_exp_map_get(int unit, int exp_map_id, 25973 bcm_mpls_exp_map_t *map) 25974 { 25975 int num_exp_map, cng, index, table_num; 25976 egr_mpls_pri_mapping_entry_t pri_entry; 25977 egr_mpls_exp_mapping_1_entry_t exp_entry; 25978 egr_mpls_exp_pri_mapping_entry_t exp_pri_entry; 25979 int max_int_pri = 15; 25980 int rv=BCM_E_NONE; 25981 uint32 ing_pri_entry[SOC_MAX_MEM_FIELD_WORDS]; 25982 soc_mem_t mem; 25983 soc_field_t pri_field; 25984 #if defined(BCM_TRIDENT3_SUPPORT) 25985 egr_mpls_pri_mapping_entry_t exp_mpls_pri_entry; 25986 #endif 25987 25988 if (exp_map_id < 0) { 25989 return BCM_E_PARAM; 25990 } 25991 25992 table_num = exp_map_id & _BCM_TR_MPLS_EXP_MAP_TABLE_NUM_MASK; 25993 25994 if ((exp_map_id & _BCM_TR_MPLS_EXP_MAP_TABLE_TYPE_MASK) == 25995 _BCM_TR_MPLS_EXP_MAP_TABLE_TYPE_INGRESS) { 25996 25997 /* ING_MPLS_EXP_MAPPING profiles indexed by EXP */ 25998 num_exp_map = _bcm_tr_get_ing_mpls_index_size(unit); 25999 26000 if ((map == NULL) || (table_num >= num_exp_map)) { 26001 return BCM_E_PARAM; 26002 } 26003 if (!_BCM_MPLS_ING_EXP_MAP_USED_GET(unit, table_num)) { 26004 return BCM_E_NOT_FOUND; 26005 } 26006 26007 /* Commit to HW */ 26008 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 26009 mem = PHB_MAPPING_TBL_3m; 26010 pri_field = INT_PRIf; 26011 /* 6 bit QOS field and 8-bit profile index 26012 * Max 32 profiles are supported from mpls_entry 26013 * Key is packet exp and profile index from mpls-entry */ 26014 index = (table_num << 6) | map->exp; 26015 } else { 26016 mem = ING_MPLS_EXP_MAPPINGm; 26017 pri_field = PRIf; 26018 /* Get the base index for this EXP map */ 26019 index = (table_num * 8) + map->exp; 26020 } 26021 26022 rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, index, ing_pri_entry); 26023 if (BCM_FAILURE(rv)) { 26024 return rv; 26025 } 26026 map->priority = soc_mem_field32_get(unit, mem, ing_pri_entry, pri_field); 26027 cng = soc_mem_field32_get(unit, mem, ing_pri_entry, CNGf); 26028 map->color = _BCM_COLOR_DECODING(unit, cng); 26029 if (SOC_MEM_FIELD_VALID(unit,mem,DSCPf)) { 26030 #if defined(BCM_TRIDENT3_SUPPORT) 26031 int valid = 1; 26032 26033 if (SOC_MEM_FIELD_VALID(unit, mem, DSCP_VALIDf)) { 26034 valid = soc_mem_field32_get(unit, mem, ing_pri_entry, DSCP_VALIDf); 26035 } 26036 if (!valid) { 26037 map->dscp = EXP_MAP_DSCP_INVALID; 26038 } else 26039 #endif 26040 { 26041 map->dscp = soc_mem_field32_get(unit, mem, ing_pri_entry, DSCPf); 26042 } 26043 } 26044 } else if 26045 ((exp_map_id & _BCM_TR_MPLS_EXP_MAP_TABLE_TYPE_MASK) == 26046 _BCM_TR_MPLS_EXP_MAP_TABLE_TYPE_EGRESS) { 26047 /* EGR_MPLS_EXP_MAPPING_1 profiles indexed by ((int_pri << 2) + cng) */ 26048 num_exp_map = soc_mem_index_count(unit, EGR_MPLS_EXP_MAPPING_1m) / 64; 26049 26050 if ((map == NULL) || (table_num >= num_exp_map) || 26051 (map->priority < BCM_PRIO_MIN) || (map->priority > max_int_pri)) { 26052 return BCM_E_PARAM; 26053 } 26054 26055 if (!_BCM_EGR_MPLS_MAP_USED_GET(unit, table_num)) { 26056 return BCM_E_NOT_FOUND; 26057 } 26058 cng = _BCM_COLOR_ENCODING(unit, map->color); 26059 26060 /* Base index of table in hardware */ 26061 index = MPLS_INFO(unit)->egr_mpls_hw_idx[table_num] * 64; 26062 26063 /* Add the offset based on priority and color values */ 26064 index += ((map->priority << 2) | (cng & 3)); 26065 26066 /* Get the values from HW */ 26067 BCM_IF_ERROR_RETURN(READ_EGR_MPLS_EXP_MAPPING_1m(unit, MEM_BLOCK_ANY, 26068 index, &exp_entry)); 26069 map->exp = soc_mem_field32_get(unit, EGR_MPLS_EXP_MAPPING_1m, 26070 &exp_entry, MPLS_EXPf); 26071 26072 BCM_IF_ERROR_RETURN(READ_EGR_MPLS_PRI_MAPPINGm(unit, MEM_BLOCK_ANY, 26073 index, &pri_entry)); 26074 map->pkt_pri = soc_mem_field32_get(unit, EGR_MPLS_PRI_MAPPINGm, 26075 &pri_entry, NEW_PRIf); 26076 map->pkt_cfi = soc_mem_field32_get(unit, EGR_MPLS_PRI_MAPPINGm, 26077 &pri_entry, NEW_CFIf); 26078 } else if 26079 ((exp_map_id & _BCM_TR_MPLS_EXP_MAP_TABLE_TYPE_MASK) == 26080 _BCM_TR_MPLS_EXP_MAP_TABLE_TYPE_EGRESS_L2) { 26081 26082 /* EGR_MPLS_EXP_PRI_MAPPINGm profiles indexed by EXP */ 26083 num_exp_map = bcmi_egr_mpls_exp_pri_mapping_num_exp_map_get(unit); 26084 26085 if ((map == NULL) || (table_num >= num_exp_map)) { 26086 return BCM_E_PARAM; 26087 } 26088 26089 if (!_BCM_MPLS_EGR_EXP_MAP_USED_GET(unit, table_num)) { 26090 return BCM_E_NOT_FOUND; 26091 } 26092 26093 /* index = Base index + Offset for this EXP map */ 26094 index = (table_num * 8) + map->exp; 26095 26096 /* Read from HW */ 26097 #if defined(BCM_TRIDENT3_SUPPORT) 26098 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 26099 BCM_IF_ERROR_RETURN(READ_EGR_MPLS_PRI_MAPPINGm(unit, MEM_BLOCK_ANY, 26100 index, &exp_mpls_pri_entry)); 26101 map->pkt_pri = soc_mem_field32_get(unit, EGR_MPLS_PRI_MAPPINGm, 26102 &exp_mpls_pri_entry, NEW_PRIf); 26103 map->pkt_cfi = soc_mem_field32_get(unit, EGR_MPLS_PRI_MAPPINGm, 26104 &exp_mpls_pri_entry, NEW_CFIf); 26105 } else 26106 #endif 26107 { 26108 BCM_IF_ERROR_RETURN(READ_EGR_MPLS_EXP_PRI_MAPPINGm(unit, MEM_BLOCK_ANY, 26109 index, &exp_pri_entry)); 26110 map->pkt_pri = soc_mem_field32_get(unit, EGR_MPLS_EXP_PRI_MAPPINGm, 26111 &exp_pri_entry, NEW_PRIf); 26112 map->pkt_cfi = soc_mem_field32_get(unit, EGR_MPLS_EXP_PRI_MAPPINGm, 26113 &exp_pri_entry, NEW_CFIf); 26114 } 26115 } else { 26116 return BCM_E_PARAM; 26117 } 26118 return BCM_E_NONE; 26119 } 26120 26121 #ifdef BCM_APACHE_SUPPORT 26122 /* 26123 * Function: 26124 * bcm_tr_mpls_exp_to_phb_cng_map_create 26125 * Purpose: 26126 * Create an MPLS EXP to PBH and CNG map instance. 26127 * Parameters: 26128 * unit - (IN) SOC unit # 26129 * flags - (IN) MPLS flags 26130 * exp_map_id - (OUT) Allocated EXP map ID 26131 * Returns: 26132 * BCM_E_XXX 26133 */ 26134 int 26135 bcm_tr_mpls_exp_to_phb_cng_map_create(int unit, uint32 flags, int *exp_map_id) 26136 { 26137 int i, table_num, num_exp_map; 26138 26139 /* Check for unsupported Flag */ 26140 if (flags & (~(BCM_MPLS_EXP_MAP_WITH_ID | 26141 BCM_MPLS_EXP_MAP_INGRESS | 26142 BCM_MPLS_EXP_MAP_EGRESS | 26143 BCM_QOS_MAP_OAM_MPLS_EXP))) { 26144 return BCM_E_PARAM; 26145 } 26146 26147 /* Input parameters check. */ 26148 if (NULL == exp_map_id) { 26149 return BCM_E_PARAM; 26150 } 26151 26152 if (flags & BCM_MPLS_EXP_MAP_INGRESS) { 26153 /* ING_MPLS_EXP_MAPPING_1 profiles indexed by EXP */ 26154 num_exp_map = soc_mem_index_count(unit, ING_MPLS_EXP_MAPPING_1m) / 16; 26155 26156 if (flags & BCM_MPLS_EXP_MAP_WITH_ID) { 26157 table_num = (*exp_map_id & _BCM_TR_MPLS_EXP_MAP_TABLE_NUM_MASK); 26158 if (table_num >= num_exp_map) { 26159 return BCM_E_PARAM; 26160 } 26161 if (_BCM_MPLS_ING_EXP_TO_PHB_CNG_MAP_USED_GET(unit, table_num)) { 26162 return BCM_E_EXISTS; 26163 } 26164 _BCM_MPLS_ING_EXP_TO_PHB_CNG_MAP_USED_SET(unit, table_num); 26165 #ifdef BCM_WARM_BOOT_SUPPORT 26166 SOC_CONTROL_LOCK(unit); 26167 SOC_CONTROL(unit)->scache_dirty = 1; 26168 SOC_CONTROL_UNLOCK(unit); 26169 #endif 26170 26171 *exp_map_id = table_num | (_BCM_QOS_MAP_TYPE_EXP_TO_PHB_CNG_MAP 26172 << _BCM_QOS_MAP_SHIFT); 26173 *exp_map_id = (*exp_map_id | 26174 _BCM_TR_MPLS_EXP_MAP_TABLE_TYPE_INGRESS); 26175 return BCM_E_NONE; 26176 } 26177 26178 for (i = 0; i < num_exp_map; i++) { 26179 if (!_BCM_MPLS_ING_EXP_TO_PHB_CNG_MAP_USED_GET(unit, i)) { 26180 _BCM_MPLS_ING_EXP_TO_PHB_CNG_MAP_USED_SET(unit, i); 26181 *exp_map_id = i | (_BCM_QOS_MAP_TYPE_EXP_TO_PHB_CNG_MAP 26182 << _BCM_QOS_MAP_SHIFT); 26183 *exp_map_id = (*exp_map_id | 26184 _BCM_TR_MPLS_EXP_MAP_TABLE_TYPE_INGRESS); 26185 #ifdef BCM_WARM_BOOT_SUPPORT 26186 SOC_CONTROL_LOCK(unit); 26187 SOC_CONTROL(unit)->scache_dirty = 1; 26188 SOC_CONTROL_UNLOCK(unit); 26189 #endif 26190 return BCM_E_NONE; 26191 } 26192 } 26193 26194 } else if (flags & BCM_MPLS_EXP_MAP_EGRESS) { 26195 /* EGR_MPLS_EXP_MAPPING_3 profiles indexed by MPLS_EXP */ 26196 num_exp_map = soc_mem_index_count(unit, EGR_MPLS_EXP_MAPPING_1m) / 8; 26197 26198 if (flags & BCM_MPLS_EXP_MAP_WITH_ID) { 26199 table_num = (*exp_map_id & _BCM_TR_MPLS_EXP_MAP_TABLE_NUM_MASK); 26200 if (table_num >= num_exp_map) { 26201 return BCM_E_PARAM; 26202 } 26203 if (!_BCM_MPLS_EGR_EXP_TO_PHB_CNG_MAP_USED_GET(unit, table_num)) { 26204 /* Reserve a chunk in the EGR_MPLS_EXP_MAPPING_3 */ 26205 _BCM_MPLS_EGR_EXP_TO_PHB_CNG_MAP_USED_SET(unit, table_num); 26206 } else { 26207 return BCM_E_EXISTS; 26208 } 26209 #ifdef BCM_WARM_BOOT_SUPPORT 26210 SOC_CONTROL_LOCK(unit); 26211 SOC_CONTROL(unit)->scache_dirty = 1; 26212 SOC_CONTROL_UNLOCK(unit); 26213 #endif 26214 *exp_map_id = table_num | (_BCM_QOS_MAP_TYPE_EXP_TO_PHB_CNG_MAP 26215 << _BCM_QOS_MAP_SHIFT); 26216 *exp_map_id = (*exp_map_id | 26217 _BCM_TR_MPLS_EXP_MAP_TABLE_TYPE_EGRESS); 26218 return BCM_E_NONE; 26219 } 26220 26221 for (i = 0; i < num_exp_map; i++) { 26222 if (!_BCM_MPLS_EGR_EXP_TO_PHB_CNG_MAP_USED_GET(unit, i)) { 26223 *exp_map_id = i | (_BCM_QOS_MAP_TYPE_EXP_TO_PHB_CNG_MAP 26224 << _BCM_QOS_MAP_SHIFT); 26225 *exp_map_id = (*exp_map_id | 26226 _BCM_TR_MPLS_EXP_MAP_TABLE_TYPE_EGRESS); 26227 26228 _BCM_MPLS_EGR_EXP_TO_PHB_CNG_MAP_USED_SET(unit, i); 26229 #ifdef BCM_WARM_BOOT_SUPPORT 26230 SOC_CONTROL_LOCK(unit); 26231 SOC_CONTROL(unit)->scache_dirty = 1; 26232 SOC_CONTROL_UNLOCK(unit); 26233 #endif 26234 return BCM_E_NONE; 26235 } 26236 } 26237 } else { 26238 return BCM_E_PARAM; 26239 } 26240 return BCM_E_FULL; 26241 } 26242 26243 /* 26244 * Function: 26245 * bcm_tr_mpls_exp_to_phb_cng_map_destroy 26246 * Purpose: 26247 * Destroy an existing MPLS EXP to PBH and CNG map instance. 26248 * Parameters: 26249 * unit - (IN) SOC unit # 26250 * exp_map_id - (IN) EXP map ID 26251 * Returns: 26252 * BCM_E_XXX 26253 */ 26254 int 26255 bcm_tr_mpls_exp_to_phb_cng_map_destroy(int unit, int exp_map_id) 26256 { 26257 int num_exp_map, table_num; 26258 26259 if (exp_map_id < 0) { 26260 return BCM_E_PARAM; 26261 } 26262 table_num = exp_map_id & _BCM_TR_MPLS_EXP_MAP_TABLE_NUM_MASK; 26263 26264 if ((exp_map_id & _BCM_TR_MPLS_EXP_MAP_TABLE_TYPE_MASK) == 26265 _BCM_TR_MPLS_EXP_MAP_TABLE_TYPE_INGRESS) { 26266 26267 /* ING_MPLS_EXP_MAPPING_1 profiles indexed by EXP */ 26268 num_exp_map = soc_mem_index_count(unit, ING_MPLS_EXP_MAPPING_1m) / 16; 26269 if (table_num >= num_exp_map) { 26270 return BCM_E_PARAM; 26271 } 26272 if (!_BCM_MPLS_ING_EXP_TO_PHB_CNG_MAP_USED_GET(unit, table_num)) { 26273 return BCM_E_NOT_FOUND; 26274 } 26275 _BCM_MPLS_ING_EXP_TO_PHB_CNG_MAP_USED_CLR(unit, table_num); 26276 #ifdef BCM_WARM_BOOT_SUPPORT 26277 SOC_CONTROL_LOCK(unit); 26278 SOC_CONTROL(unit)->scache_dirty = 1; 26279 SOC_CONTROL_UNLOCK(unit); 26280 #endif 26281 } else if ((exp_map_id & _BCM_TR_MPLS_EXP_MAP_TABLE_TYPE_MASK) == 26282 _BCM_TR_MPLS_EXP_MAP_TABLE_TYPE_EGRESS) { 26283 26284 /* EGR_MPLS_EXP_MAPPING_3m profiles indexed by EXP */ 26285 num_exp_map = soc_mem_index_count(unit, EGR_MPLS_EXP_MAPPING_3m) / 8; 26286 if (table_num >= num_exp_map) { 26287 return BCM_E_PARAM; 26288 } 26289 if (!_BCM_MPLS_EGR_EXP_TO_PHB_CNG_MAP_USED_GET(unit, table_num)) { 26290 return BCM_E_NOT_FOUND; 26291 } 26292 _BCM_MPLS_EGR_EXP_TO_PHB_CNG_MAP_USED_CLR(unit, table_num); 26293 #ifdef BCM_WARM_BOOT_SUPPORT 26294 SOC_CONTROL_LOCK(unit); 26295 SOC_CONTROL(unit)->scache_dirty = 1; 26296 SOC_CONTROL_UNLOCK(unit); 26297 #endif 26298 } else { 26299 return BCM_E_PARAM; 26300 } 26301 26302 return BCM_E_NONE; 26303 } 26304 26305 /* 26306 * Function: 26307 * bcm_tr_mpls_exp_to_phb_cng_map_set 26308 * Purpose: 26309 * Set the mapping of { PHB, CNG } 26310 * to a EXP value for MPLS headers 26311 * in the specified EXP map instance. 26312 * Parameters: 26313 * unit - (IN) SOC unit # 26314 * flags - (IN) flags 26315 * exp_map_id - (IN) EXP map ID 26316 * map - (IN) EXP map config structure 26317 * Returns: 26318 * BCM_E_XXX 26319 */ 26320 int 26321 bcm_tr_mpls_exp_to_phb_cng_map_set(int unit, int exp_map_id, 26322 bcm_mpls_exp_map_t *map) 26323 { 26324 int table_num, num_exp_map, cng, index; 26325 egr_mpls_exp_mapping_3_entry_t exp_pri_entry; 26326 ing_mpls_exp_mapping_1_entry_t ing_pri_entry; 26327 26328 /* Check validity of exp_map_id */ 26329 if (exp_map_id < 0) { 26330 return BCM_E_PARAM; 26331 } 26332 26333 if (!map) { 26334 /* invalid pointer to map data */ 26335 return BCM_E_PARAM; 26336 } 26337 26338 table_num = exp_map_id & _BCM_TR_MPLS_EXP_MAP_TABLE_NUM_MASK; 26339 26340 if ((exp_map_id & _BCM_TR_MPLS_EXP_MAP_TABLE_TYPE_MASK) == 26341 _BCM_TR_MPLS_EXP_MAP_TABLE_TYPE_INGRESS) { 26342 26343 /* ING_MPLS_EXP_MAPPING_1 profiles indexed by EXP */ 26344 num_exp_map = soc_mem_index_count(unit, ING_MPLS_EXP_MAPPING_1m) / 16; 26345 if (table_num >= num_exp_map) { 26346 return BCM_E_PARAM; 26347 } 26348 26349 if (!_BCM_MPLS_ING_EXP_TO_PHB_CNG_MAP_USED_GET(unit, table_num)) { 26350 return BCM_E_NOT_FOUND; 26351 } 26352 26353 cng = _BCM_COLOR_ENCODING(unit, map->color); 26354 26355 /* Get the base index for this EXP map */ 26356 index = (table_num * 8) + map->exp; 26357 26358 /* Commit to HW */ 26359 BCM_IF_ERROR_RETURN(READ_ING_MPLS_EXP_MAPPING_1m(unit, MEM_BLOCK_ANY, 26360 index, &ing_pri_entry)); 26361 soc_ING_MPLS_EXP_MAPPING_1m_field32_set(unit, &ing_pri_entry, 26362 PHBf, map->priority); 26363 soc_ING_MPLS_EXP_MAPPING_1m_field32_set(unit, &ing_pri_entry, 26364 CNGf, cng); 26365 BCM_IF_ERROR_RETURN(WRITE_ING_MPLS_EXP_MAPPING_1m(unit, MEM_BLOCK_ALL, 26366 index, &ing_pri_entry)); 26367 } else if 26368 ((exp_map_id & _BCM_TR_MPLS_EXP_MAP_TABLE_TYPE_MASK) == 26369 _BCM_TR_MPLS_EXP_MAP_TABLE_TYPE_EGRESS) { 26370 26371 if ((map->exp > 7) || (map->pkt_pri > 7) || (map->pkt_cfi > 1)) { 26372 return BCM_E_PARAM; 26373 } 26374 26375 /* EGR_MPLS_EXP_MAPPING_3m profiles indexed by EXP */ 26376 num_exp_map = bcmi_egr_mpls_exp_pri_mapping_num_exp_map_get(unit); 26377 if (table_num >= num_exp_map) { 26378 return BCM_E_PARAM; 26379 } 26380 26381 cng = _BCM_COLOR_ENCODING(unit, map->color); 26382 26383 /* index = Base index + Offset for this EXP map */ 26384 index = (table_num * 8) + map->exp; 26385 26386 if (!_BCM_MPLS_EGR_EXP_TO_PHB_CNG_MAP_USED_GET(unit, table_num)) { 26387 return BCM_E_NOT_FOUND; 26388 } 26389 26390 BCM_IF_ERROR_RETURN(READ_EGR_MPLS_EXP_MAPPING_3m(unit, MEM_BLOCK_ANY, 26391 index, &exp_pri_entry)); 26392 soc_EGR_MPLS_EXP_MAPPING_3m_field32_set(unit, &exp_pri_entry, 26393 PHBf, map->priority); 26394 soc_EGR_MPLS_EXP_MAPPING_3m_field32_set(unit, &exp_pri_entry, 26395 CNGf, cng); 26396 BCM_IF_ERROR_RETURN(WRITE_EGR_MPLS_EXP_MAPPING_3m(unit, MEM_BLOCK_ALL, 26397 index, &exp_pri_entry)); 26398 26399 } else { 26400 return BCM_E_PARAM; 26401 } 26402 26403 return BCM_E_NONE; 26404 } 26405 26406 /* 26407 * Function: 26408 * bcm_tr_mpls_exp_to_phb_cng_map_get 26409 * Purpose: 26410 * Get the mapping of { PHB, CNG } 26411 * to a EXP value for MPLS headers 26412 * in the specified EXP map instance. 26413 * Parameters: 26414 * unit - (IN) SOC unit # 26415 * exp_map_id - (IN) EXP map ID 26416 * map - (OUT) EXP map config structure 26417 * Returns: 26418 * BCM_E_XXX 26419 */ 26420 int 26421 bcm_tr_mpls_exp_to_phb_cng_map_get(int unit, int exp_map_id, 26422 bcm_mpls_exp_map_t *map) 26423 { 26424 int num_exp_map, cng, index, table_num; 26425 egr_mpls_exp_mapping_3_entry_t exp_entry; 26426 ing_mpls_exp_mapping_1_entry_t ing_pri_entry; 26427 26428 26429 if (exp_map_id < 0) { 26430 return BCM_E_PARAM; 26431 } 26432 26433 table_num = exp_map_id & _BCM_TR_MPLS_EXP_MAP_TABLE_NUM_MASK; 26434 26435 if ((exp_map_id & _BCM_TR_MPLS_EXP_MAP_TABLE_TYPE_MASK) == 26436 _BCM_TR_MPLS_EXP_MAP_TABLE_TYPE_INGRESS) { 26437 26438 /* ING_MPLS_EXP_MAPPING_1 profiles indexed by EXP */ 26439 num_exp_map = soc_mem_index_count(unit, ING_MPLS_EXP_MAPPING_1m) / 16; 26440 26441 if ((map == NULL) || (table_num >= num_exp_map)) { 26442 return BCM_E_PARAM; 26443 } 26444 if (!_BCM_MPLS_ING_EXP_TO_PHB_CNG_MAP_USED_GET(unit, table_num)) { 26445 return BCM_E_NOT_FOUND; 26446 } 26447 26448 /* Get the base index for this EXP map */ 26449 index = (table_num * 8) + map->exp; 26450 26451 /* Commit to HW */ 26452 BCM_IF_ERROR_RETURN(READ_ING_MPLS_EXP_MAPPING_1m(unit, MEM_BLOCK_ANY, 26453 index, &ing_pri_entry)); 26454 map->priority = soc_mem_field32_get(unit, ING_MPLS_EXP_MAPPING_1m, 26455 &ing_pri_entry, PHBf); 26456 cng = soc_mem_field32_get(unit, ING_MPLS_EXP_MAPPING_1m, 26457 &ing_pri_entry, CNGf); 26458 map->color = _BCM_COLOR_DECODING(unit, cng); 26459 26460 } else if 26461 ((exp_map_id & _BCM_TR_MPLS_EXP_MAP_TABLE_TYPE_MASK) == 26462 _BCM_TR_MPLS_EXP_MAP_TABLE_TYPE_EGRESS) { 26463 /* EGR_MPLS_EXP_MAPPING_1 profiles indexed by EXP*/ 26464 num_exp_map = soc_mem_index_count(unit, EGR_MPLS_EXP_MAPPING_3m) / 8; 26465 26466 if ((map == NULL) || (table_num >= num_exp_map)) { 26467 return BCM_E_PARAM; 26468 } 26469 26470 if (!_BCM_MPLS_EGR_EXP_TO_PHB_CNG_MAP_USED_GET(unit, table_num)) { 26471 return BCM_E_NOT_FOUND; 26472 } 26473 26474 /* Get the base index for this EXP map */ 26475 index = (table_num * 8) + map->exp; 26476 26477 /* Get the values from HW */ 26478 BCM_IF_ERROR_RETURN(READ_EGR_MPLS_EXP_MAPPING_3m(unit, MEM_BLOCK_ANY, 26479 index, &exp_entry)); 26480 map->priority = soc_mem_field32_get(unit, EGR_MPLS_EXP_MAPPING_3m, 26481 &exp_entry, PHBf); 26482 26483 cng = soc_mem_field32_get(unit, EGR_MPLS_EXP_MAPPING_3m, 26484 &exp_entry, CNGf); 26485 map->color = _BCM_COLOR_DECODING(unit, cng); 26486 } else { 26487 return BCM_E_PARAM; 26488 } 26489 return BCM_E_NONE; 26490 } 26491 26492 int 26493 bcm_tr_mpls_exp_to_phb_cng_map_usage_get(int unit, uint32 flags, 26494 int exp_map_id) 26495 { 26496 if((flags & BCM_QOS_MAP_INGRESS) && 26497 (!_BCM_MPLS_ING_EXP_TO_PHB_CNG_MAP_USED_GET(unit, exp_map_id))) { 26498 return BCM_E_NOT_FOUND; 26499 } 26500 else if ((flags & BCM_QOS_MAP_EGRESS) && 26501 (!_BCM_MPLS_EGR_EXP_TO_PHB_CNG_MAP_USED_GET(unit, exp_map_id))) { 26502 return BCM_E_NOT_FOUND; 26503 } 26504 26505 return BCM_E_NONE; 26506 } 26507 26508 int 26509 bcm_tr_mpls_exp_to_phb_cng_map_profile_id_get(int unit, uint32 flags, 26510 int map_id, int *profile_id) 26511 { 26512 if(flags & BCM_QOS_MAP_INGRESS){ 26513 *profile_id = MPLS_INFO(unit)->ing_exp_to_phb_cng_map_bitmap[map_id]; 26514 } else if (flags & BCM_QOS_MAP_EGRESS){ 26515 *profile_id = MPLS_INFO(unit)->egr_exp_to_phb_cng_map_bitmap[map_id]; 26516 } else { 26517 return BCM_E_PARAM; 26518 } 26519 return BCM_E_NONE; 26520 } 26521 26522 int 26523 bcm_tr_mpls_exp_to_phb_cng_map_profile_range_get(int unit, uint32 flags, 26524 int *count) 26525 { 26526 int num_exp_map = 0, value = 0; 26527 26528 if(flags & BCM_QOS_MAP_INGRESS){ 26529 num_exp_map = soc_mem_index_count(unit, ING_MPLS_EXP_MAPPING_1m) / 16; 26530 SHR_BITCOUNT_RANGE(MPLS_INFO(unit)->ing_exp_to_phb_cng_map_bitmap, 26531 value, 0, num_exp_map); 26532 } else if (flags & BCM_QOS_MAP_EGRESS){ 26533 num_exp_map = soc_mem_index_count(unit, EGR_MPLS_EXP_MAPPING_3m) / 8; 26534 SHR_BITCOUNT_RANGE(MPLS_INFO(unit)->egr_exp_to_phb_cng_map_bitmap, 26535 value, 0, num_exp_map); 26536 } 26537 *count = value; 26538 return BCM_E_NONE; 26539 } 26540 26541 26542 #endif 26543 26544 #ifdef BCM_TRIUMPH2_SUPPORT 26545 STATIC int 26546 _bcm_tr2_mpls_label_flex_stat_hw_index_set(int unit, 26547 _bcm_flex_stat_handle_t handle, 26548 int fs_idx, void *cookie) 26549 { 26550 int rv; 26551 mpls_entry_entry_t *ment; 26552 26553 /* The entry was found earlier, so we can use it here */ 26554 ment = (mpls_entry_entry_t *) cookie; 26555 26556 /* Update the entry appropriately */ 26557 soc_mem_field32_set(unit, MPLS_ENTRYm, ment, 26558 VINTF_CTR_IDXf, fs_idx); 26559 soc_mem_field32_set(unit, MPLS_ENTRYm, ment, 26560 USE_VINTF_CTR_IDXf, (fs_idx > 0) ? 1 : 0); 26561 26562 /* Replace the existing entry */ 26563 rv = soc_mem_insert(unit, MPLS_ENTRYm, MEM_BLOCK_ALL, ment); 26564 if (BCM_E_EXISTS == rv) { 26565 return BCM_E_NONE; 26566 } else if (BCM_SUCCESS(rv)) { 26567 rv = BCM_E_NOT_FOUND; 26568 } 26569 26570 return rv; 26571 } 26572 26573 STATIC _bcm_flex_stat_t 26574 _bcm_esw_mpls_label_stat_to_flex_stat(bcm_mpls_stat_t stat) 26575 { 26576 _bcm_flex_stat_t flex_stat; 26577 26578 /* Only ingress stats from the MPLS_ENTRY table. */ 26579 switch (stat) { 26580 case bcmMplsInPkts: 26581 flex_stat = _bcmFlexStatIngressPackets; 26582 break; 26583 case bcmMplsInBytes: 26584 flex_stat = _bcmFlexStatIngressBytes; 26585 break; 26586 default: 26587 flex_stat = _bcmFlexStatNum; 26588 } 26589 26590 return flex_stat; 26591 } 26592 26593 /* 26594 * Function: 26595 * bcm_tr2_mpls_label_stat_enable_set 26596 * Purpose: 26597 * Enable statistics collection for MPLS label or MPLS gport 26598 * Parameters: 26599 * unit - (IN) Unit number. 26600 * label - (IN) MPLS label 26601 * port - (IN) MPLS gport 26602 * enable - (IN) Non-zero to enable counter collection, zero to disable. 26603 * cnt_inx - (IN) counter index. zero means not allocated 26604 * Returns: 26605 * BCM_E_xxx 26606 * Notes: 26607 */ 26608 int 26609 bcm_tr2_mpls_label_stat_enable_set(int unit, bcm_mpls_label_t label, 26610 bcm_gport_t port, int enable,int cnt_inx) 26611 { 26612 /* This enables the flexible statistics gathering for MPLS labels */ 26613 int rv=BCM_E_UNAVAIL; 26614 int index; 26615 bcm_mpls_tunnel_switch_t info; 26616 mpls_entry_entry_t ment; 26617 _bcm_flex_stat_handle_t mpls_fsh; 26618 26619 if (BCM_GPORT_IS_MPLS_PORT(port)) { 26620 /* When the gport is an MPLS port, we'll turn on the 26621 * port-based tracking for backward-compatibility. 26622 */ 26623 return _bcm_esw_flex_stat_enable_set(unit, _bcmFlexStatTypeGport, 26624 _bcm_esw_port_flex_stat_hw_index_set, 26625 cnt_inx? INT_TO_PTR(_BCM_FLEX_STAT_HW_INGRESS): NULL, 26626 port, enable,cnt_inx); 26627 } 26628 26629 sal_memset(&info, 0, sizeof(bcm_mpls_tunnel_switch_t)); 26630 info.port = port; 26631 if (BCM_XGS3_L3_MPLS_LBL_VALID(label)) { 26632 info.label = label; 26633 } else { 26634 return BCM_E_PARAM; 26635 } 26636 26637 rv = _bcm_tr_mpls_entry_set_key(unit, &info, &ment); 26638 BCM_IF_ERROR_RETURN(rv); 26639 26640 /* We don't use the handle retrieval function here because 26641 * we've already found the matching entry from which to extract 26642 * the key. 26643 */ 26644 /* Fill handle for MPLS label info */ 26645 _BCM_FLEX_STAT_HANDLE_CLEAR(mpls_fsh); 26646 /* Handle is key of MPLS entry */ 26647 _BCM_FLEX_STAT_HANDLE_COPY(mpls_fsh, ment); 26648 26649 rv = soc_mem_search(unit, MPLS_ENTRYm, MEM_BLOCK_ANY, &index, 26650 &ment, &ment, 0); 26651 26652 if (rv == SOC_E_NONE) { 26653 /* Entry exists, and we are inside MPLS lock, so proceed with 26654 * attaching the counter. */ 26655 rv = _bcm_esw_flex_stat_ext_enable_set(unit, 26656 _bcmFlexStatTypeMplsLabel, 26657 _bcm_tr2_mpls_label_flex_stat_hw_index_set, 26658 (void *) &ment, mpls_fsh, enable,cnt_inx); 26659 } 26660 26661 return rv; 26662 } 26663 #endif /* BCM_TRIUMPH2_SUPPORT */ 26664 26665 /* 26666 * Function: 26667 * bcm_tr_mpls_label_stat_get 26668 * Purpose: 26669 * Get L2 MPLS PW Stats 26670 * if sync_mode is set, sync the sw accumulated count 26671 * with hw count value first, else return sw count. 26672 * Parameters: 26673 * unit - (IN) SOC unit # 26674 * sync_mode - (IN) hwcount is to be synced to sw count 26675 * label - (IN) MPLS label 26676 * port - (IN) MPLS gport 26677 * stat - (IN) specify the Stat type 26678 * val - (OUT) 64-bit Stats value 26679 * Returns: 26680 * BCM_E_XXX 26681 */ 26682 26683 int 26684 bcm_tr_mpls_label_stat_get(int unit, int sync_mode, bcm_mpls_label_t label, 26685 bcm_gport_t port, bcm_mpls_stat_t stat, uint64 *val) 26686 { 26687 int rv=BCM_E_UNAVAIL, index; 26688 bcm_mpls_tunnel_switch_t info; 26689 mpls_entry_entry_t ment; 26690 ing_pw_term_counters_entry_t cent; 26691 egr_pw_init_counters_entry_t pw_init_entry; 26692 egr_l3_next_hop_entry_t egr_nh; 26693 ing_dvp_table_entry_t dvp; 26694 int vp, nh_index; 26695 uint32 hw_val[2]; 26696 uint32 val_high, val_low; 26697 uint32 pkt_counter; 26698 uint32 pw_term_cnt, pw_init_cnt, num_pw_mask; 26699 26700 /* Based on Switch Type */ 26701 #ifdef BCM_TRIUMPH2_SUPPORT 26702 if (soc_feature(unit, soc_feature_gport_service_counters)) { 26703 _bcm_flex_stat_handle_t mpls_fsh; 26704 26705 COMPILER_64_ZERO(*val); 26706 26707 if (BCM_GPORT_IS_MPLS_PORT(port)) { 26708 bcm_port_stat_t flex_stat=0; 26709 switch (stat) { 26710 case bcmMplsInPkts: 26711 flex_stat = bcmPortStatIngressPackets; 26712 break; 26713 case bcmMplsInBytes: 26714 flex_stat = bcmPortStatIngressBytes; 26715 break; 26716 case bcmMplsOutPkts: 26717 flex_stat = bcmPortStatEgressPackets; 26718 break; 26719 case bcmMplsOutBytes: 26720 flex_stat = bcmPortStatEgressBytes; 26721 break; 26722 } 26723 26724 rv = _bcm_esw_port_stat_get(unit, sync_mode, port, flex_stat, val); 26725 } else { 26726 26727 /* When not an MPLS gport, we use the label-based stats. */ 26728 sal_memset(&info, 0, sizeof(bcm_mpls_tunnel_switch_t)); 26729 info.port = port; 26730 if (BCM_XGS3_L3_MPLS_LBL_VALID(label)) { 26731 info.label = label; 26732 } else { 26733 return BCM_E_PARAM; 26734 } 26735 26736 rv = _bcm_tr_mpls_entry_set_key(unit, &info, &ment); 26737 BCM_IF_ERROR_RETURN(rv); 26738 26739 _BCM_FLEX_STAT_HANDLE_CLEAR(mpls_fsh); 26740 _BCM_FLEX_STAT_HANDLE_COPY(mpls_fsh, ment); 26741 26742 26743 rv = _bcm_esw_flex_stat_ext_get(unit, sync_mode, 26744 _bcmFlexStatTypeMplsLabel, 26745 mpls_fsh, 26746 _bcm_esw_mpls_label_stat_to_flex_stat(stat), 26747 val); 26748 } 26749 } else 26750 #endif /* BCM_TRIUMPH2_SUPPORT */ 26751 if (SOC_IS_TR_VL(unit)) { 26752 26753 if ((stat == bcmMplsInBytes) || (stat == bcmMplsInPkts)) { 26754 sal_memset(&info, 0, sizeof(bcm_mpls_tunnel_switch_t)); 26755 info.port = port; 26756 if (BCM_XGS3_L3_MPLS_LBL_VALID(label)) { 26757 info.label = label; 26758 } else { 26759 return BCM_E_PARAM; 26760 } 26761 26762 rv = _bcm_tr_mpls_entry_set_key(unit, &info, &ment); 26763 BCM_IF_ERROR_RETURN(rv); 26764 26765 rv = soc_mem_search(unit, MPLS_ENTRYm, MEM_BLOCK_ANY, &index, 26766 &ment, &ment, 0); 26767 26768 if (rv == SOC_E_NONE) { 26769 if (!soc_MPLS_ENTRYm_field32_get(unit, &ment, PW_TERM_NUM_VALIDf)) { 26770 return BCM_E_CONFIG; 26771 } 26772 pw_term_cnt = soc_MPLS_ENTRYm_field32_get(unit, &ment, PW_TERM_NUMf); 26773 26774 if (SOC_MEM_IS_VALID(unit, ING_PW_TERM_COUNTERSm)) { 26775 rv = READ_ING_PW_TERM_COUNTERSm(unit, MEM_BLOCK_ANY, pw_term_cnt, ¢); 26776 if (rv < 0) { 26777 return rv; 26778 } 26779 } else { 26780 return BCM_E_UNAVAIL; 26781 } 26782 COMPILER_64_ZERO(*val); 26783 switch (stat) { 26784 case bcmMplsInBytes: 26785 if(SOC_IS_ENDURO(unit)) { 26786 hw_val[0] = hw_val[1] = 0; 26787 soc_mem_field_get(unit, ING_PW_TERM_COUNTERSm, 26788 (uint32 *) ¢, BYTE_COUNTERf, hw_val); 26789 COMPILER_64_SET(*val, hw_val[1],hw_val[0]); 26790 } 26791 else { 26792 val_high = soc_mem_field32_get(unit, ING_PW_TERM_COUNTERSm, 26793 ¢, BYTE_COUNTER_HIf); 26794 val_low = soc_mem_field32_get(unit, ING_PW_TERM_COUNTERSm, 26795 ¢, BYTE_COUNTER_LOf); 26796 COMPILER_64_SET(*val, val_high, val_low); 26797 } 26798 break; 26799 26800 case bcmMplsInPkts: 26801 val_low = soc_mem_field32_get(unit, ING_PW_TERM_COUNTERSm, 26802 ¢, PACKET_COUNTERf); 26803 COMPILER_64_SET(*val, 0, val_low); 26804 break; 26805 /* 26806 * COVERITY 26807 * 26808 * This default is unreachable. It is kept intentionally as a defensive default for future development. 26809 */ 26810 /* coverity[dead_error_begin] */ 26811 default: 26812 break; 26813 } 26814 } 26815 } else if ((stat == bcmMplsOutBytes) || (stat == bcmMplsOutPkts) ) { 26816 26817 /* Get egress next-hop index from MPLS GPORT */ 26818 vp = BCM_GPORT_MPLS_PORT_ID_GET(port); 26819 if (vp == -1) { 26820 return BCM_E_PARAM; 26821 } 26822 26823 rv = READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp, &dvp); 26824 if (rv < 0) { 26825 return rv; 26826 } 26827 nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, 26828 NEXT_HOP_INDEXf); 26829 26830 /* Retrieve EGR L3 NHOP Entry */ 26831 BCM_IF_ERROR_RETURN (soc_mem_read(unit, EGR_L3_NEXT_HOPm, MEM_BLOCK_ANY, 26832 nh_index, &egr_nh)); 26833 26834 /* Retrieve PW_INIT Index from EGR L3 NHOP Entry */ 26835 if (soc_feature(unit, soc_feature_mpls_enhanced)) { 26836 pw_init_cnt = 26837 soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, 26838 MPLS__PW_INIT_NUMf); 26839 } else { 26840 pw_init_cnt = 26841 soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, 26842 PW_INIT_NUMf); 26843 } 26844 26845 num_pw_mask = soc_mem_index_count(0, EGR_PW_INIT_COUNTERSm) - 1; 26846 pw_init_cnt &= num_pw_mask; 26847 26848 /* Retrieve the Counter Value */ 26849 sal_memset(&pw_init_entry, 0, sizeof(egr_pw_init_counters_entry_t)); 26850 if (SOC_MEM_IS_VALID(unit, EGR_PW_INIT_COUNTERSm)) { 26851 rv = READ_EGR_PW_INIT_COUNTERSm(unit, MEM_BLOCK_ANY, pw_init_cnt, &pw_init_entry); 26852 if (rv < 0) { 26853 return rv; 26854 } 26855 } else { 26856 return BCM_E_UNAVAIL; 26857 } 26858 COMPILER_64_ZERO(*val); 26859 switch (stat) { 26860 case bcmMplsOutBytes: 26861 if (SOC_MEM_FIELD_VALID (unit, EGR_PW_INIT_COUNTERSm, BYTE_COUNTERf)) { 26862 hw_val[0] = hw_val[1] = 0; 26863 soc_mem_field_get(unit, EGR_PW_INIT_COUNTERSm, 26864 (uint32 *) &pw_init_entry, BYTE_COUNTERf, hw_val); 26865 COMPILER_64_SET(*val, hw_val[1],hw_val[0]); 26866 } else { 26867 return BCM_E_UNAVAIL; 26868 } 26869 break; 26870 26871 case bcmMplsOutPkts: 26872 if (SOC_MEM_FIELD_VALID (unit, EGR_PW_INIT_COUNTERSm, PACKET_COUNTERf)) { 26873 pkt_counter = soc_mem_field32_get(unit, EGR_PW_INIT_COUNTERSm, 26874 &pw_init_entry, PACKET_COUNTERf); 26875 val_low = (pkt_counter - (pkt_counter/65536)); 26876 COMPILER_64_SET(*val, 0, val_low); 26877 } else { 26878 return BCM_E_UNAVAIL; 26879 } 26880 break; 26881 default: 26882 break; 26883 } 26884 } 26885 } 26886 return rv; 26887 } 26888 26889 int 26890 bcm_tr_mpls_label_stat_get32(int unit, int sync_mode, 26891 bcm_mpls_label_t label, bcm_gport_t port, 26892 bcm_mpls_stat_t stat, uint32 *val) 26893 { 26894 int rv; 26895 uint64 val64; 26896 26897 26898 rv = bcm_tr_mpls_label_stat_get(unit, sync_mode, label, 26899 port, stat, &val64); 26900 if (rv == BCM_E_NONE) { 26901 *val = COMPILER_64_LO(val64); 26902 } 26903 return rv; 26904 } 26905 26906 /* 26907 * Function: 26908 * bcm_tr_mpls_label_stat_clear 26909 * Purpose: 26910 * Clear L2 MPLS PW Stats 26911 * Parameters: 26912 * unit - (IN) SOC unit # 26913 * label - (IN) MPLS label 26914 * port - (IN) MPLS gport 26915 * stat - (IN) specify the Stat type 26916 * Returns: 26917 * BCM_E_XXX 26918 */ 26919 26920 int 26921 bcm_tr_mpls_label_stat_clear(int unit, bcm_mpls_label_t label, bcm_gport_t port, 26922 bcm_mpls_stat_t stat) 26923 { 26924 int rv=BCM_E_UNAVAIL, pw_term_cnt, pw_init_cnt, index; 26925 bcm_mpls_tunnel_switch_t info; 26926 mpls_entry_entry_t ment; 26927 ing_pw_term_counters_entry_t cent; 26928 egr_pw_init_counters_entry_t pw_init_entry; 26929 egr_l3_next_hop_entry_t egr_nh; 26930 ing_dvp_table_entry_t dvp; 26931 int vp, nh_index; 26932 uint32 num_pw_mask; 26933 26934 /* Based on Switch Type */ 26935 #ifdef BCM_TRIUMPH2_SUPPORT 26936 if (soc_feature(unit, soc_feature_gport_service_counters)) { 26937 _bcm_flex_stat_handle_t mpls_fsh; 26938 bcm_port_stat_t flex_stat=0; 26939 uint64 flex_value; 26940 26941 COMPILER_64_ZERO(flex_value); 26942 26943 if (BCM_GPORT_IS_MPLS_PORT(port)) { 26944 switch (stat) { 26945 case bcmMplsInPkts: 26946 flex_stat = bcmPortStatIngressPackets; 26947 break; 26948 case bcmMplsInBytes: 26949 flex_stat = bcmPortStatIngressBytes; 26950 break; 26951 case bcmMplsOutPkts: 26952 flex_stat = bcmPortStatEgressPackets; 26953 break; 26954 case bcmMplsOutBytes: 26955 flex_stat = bcmPortStatEgressBytes; 26956 break; 26957 } 26958 26959 COMPILER_64_ZERO(flex_value); 26960 rv = bcm_esw_port_stat_set(unit, port, flex_stat, flex_value); 26961 } else { 26962 sal_memset(&info, 0, sizeof(bcm_mpls_tunnel_switch_t)); 26963 info.port = port; 26964 if (BCM_XGS3_L3_MPLS_LBL_VALID(label)) { 26965 info.label = label; 26966 } else { 26967 return BCM_E_PARAM; 26968 } 26969 26970 rv = _bcm_tr_mpls_entry_set_key(unit, &info, &ment); 26971 BCM_IF_ERROR_RETURN(rv); 26972 26973 _BCM_FLEX_STAT_HANDLE_CLEAR(mpls_fsh); 26974 _BCM_FLEX_STAT_HANDLE_COPY(mpls_fsh, ment); 26975 26976 rv = _bcm_esw_flex_stat_ext_set(unit, _bcmFlexStatTypeMplsLabel, 26977 mpls_fsh, 26978 _bcm_esw_mpls_label_stat_to_flex_stat(stat), 26979 flex_value); 26980 } 26981 } else 26982 #endif /* BCM_TRIUMPH2_SUPPORT */ 26983 if (SOC_IS_TR_VL(unit)) { 26984 26985 if ((stat == bcmMplsInBytes) || (stat == bcmMplsInPkts)) { 26986 sal_memset(&info, 0, sizeof(bcm_mpls_tunnel_switch_t)); 26987 info.port = port; 26988 if (BCM_XGS3_L3_MPLS_LBL_VALID(label)) { 26989 info.label = label; 26990 } else { 26991 return BCM_E_PARAM; 26992 } 26993 26994 rv = _bcm_tr_mpls_entry_set_key(unit, &info, &ment); 26995 BCM_IF_ERROR_RETURN(rv); 26996 26997 rv = soc_mem_search(unit, MPLS_ENTRYm, MEM_BLOCK_ANY, &index, 26998 &ment, &ment, 0); 26999 if (rv == SOC_E_NONE) { 27000 if (!soc_MPLS_ENTRYm_field32_get(unit, &ment, PW_TERM_NUM_VALIDf)) { 27001 return BCM_E_CONFIG; 27002 } 27003 27004 /* Retrieve PW_TERM Index from MPLS_Entry */ 27005 pw_term_cnt = soc_MPLS_ENTRYm_field32_get(unit, &ment, PW_TERM_NUMf); 27006 27007 /* Clear the Counter Value */ 27008 sal_memset(¢, 0, sizeof(ing_pw_term_counters_entry_t)); 27009 rv = WRITE_ING_PW_TERM_COUNTERSm(unit, MEM_BLOCK_ANY, pw_term_cnt, ¢); 27010 if (rv < 0) { 27011 return rv; 27012 } 27013 } 27014 } else if ((stat == bcmMplsOutBytes) || (stat == bcmMplsOutPkts) ) { 27015 27016 /* Get egress next-hop index from MPLS GPORT */ 27017 vp = BCM_GPORT_MPLS_PORT_ID_GET(port); 27018 if (vp == -1) { 27019 return BCM_E_PARAM; 27020 } 27021 27022 rv = READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp, &dvp); 27023 if (rv < 0) { 27024 return rv; 27025 } 27026 nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, 27027 NEXT_HOP_INDEXf); 27028 27029 /* Retrieve EGR L3 NHOP Entry */ 27030 BCM_IF_ERROR_RETURN (soc_mem_read(unit, EGR_L3_NEXT_HOPm, MEM_BLOCK_ANY, 27031 nh_index, &egr_nh)); 27032 27033 /* Retrieve PW_INIT Index from EGR L3 NHOP Entry */ 27034 pw_init_cnt = soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, PW_INIT_NUMf); 27035 27036 num_pw_mask = soc_mem_index_count(0, EGR_PW_INIT_COUNTERSm) - 1; 27037 pw_init_cnt &= num_pw_mask; 27038 27039 /* Clear the Counter Value */ 27040 sal_memset(&pw_init_entry, 0, sizeof(egr_pw_init_counters_entry_t)); 27041 rv = WRITE_EGR_PW_INIT_COUNTERSm(unit, MEM_BLOCK_ANY, pw_init_cnt, &pw_init_entry); 27042 if (rv < 0) { 27043 return rv; 27044 } 27045 } 27046 } 27047 return rv; 27048 } 27049 27050 /* 27051 * Function: 27052 * bcm_tr_mpls_port_learn_set 27053 * Purpose: 27054 * Set the CML bits for an mpls port. 27055 * Returns: 27056 * BCM_E_XXX 27057 */ 27058 int 27059 bcm_tr_mpls_port_learn_set(int unit, bcm_gport_t mpls_port_id, uint32 flags) 27060 { 27061 int vp, cml = 0, rv = BCM_E_NONE; 27062 source_vp_entry_t svp; 27063 27064 rv = _bcm_tr_mpls_check_init (unit); 27065 if (rv < 0) { 27066 return rv; 27067 } 27068 27069 cml = 0; 27070 if (!(flags & BCM_PORT_LEARN_FWD)) { 27071 cml |= (1 << 0); 27072 } 27073 if (flags & BCM_PORT_LEARN_CPU) { 27074 cml |= (1 << 1); 27075 } 27076 if (flags & BCM_PORT_LEARN_PENDING) { 27077 cml |= (1 << 2); 27078 } 27079 if (flags & BCM_PORT_LEARN_ARL) { 27080 cml |= (1 << 3); 27081 } 27082 27083 /* Get the VP index from the gport */ 27084 vp = BCM_GPORT_MPLS_PORT_ID_GET(mpls_port_id); 27085 if (vp == -1) { 27086 return BCM_E_PARAM; 27087 } 27088 27089 /* Be sure the entry is used and is set for VPLS */ 27090 if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeMpls)) { 27091 return BCM_E_NOT_FOUND; 27092 } 27093 rv = READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp, &svp); 27094 if (rv < 0) { 27095 return rv; 27096 } 27097 if (soc_SOURCE_VPm_field32_get(unit, &svp, ENTRY_TYPEf) != 1) { /* VPLS */ 27098 return BCM_E_NOT_FOUND; 27099 } 27100 soc_SOURCE_VPm_field32_set(unit, &svp, CML_FLAGS_MOVEf, cml); 27101 soc_SOURCE_VPm_field32_set(unit, &svp, CML_FLAGS_NEWf, cml); 27102 rv = WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, vp, &svp); 27103 return rv; 27104 } 27105 27106 /* 27107 * Function: 27108 * bcm_tr_mpls_port_learn_get 27109 * Purpose: 27110 * Get the CML bits for an mpls port 27111 * Returns: 27112 * BCM_E_XXX 27113 */ 27114 int 27115 bcm_tr_mpls_port_learn_get(int unit, bcm_gport_t mpls_port_id, uint32 *flags) 27116 { 27117 int rv, vp, cml = 0; 27118 source_vp_entry_t svp; 27119 27120 rv = _bcm_tr_mpls_check_init (unit); 27121 if (rv < 0) { 27122 return rv; 27123 } 27124 27125 /* Get the VP index from the gport */ 27126 vp = BCM_GPORT_MPLS_PORT_ID_GET(mpls_port_id); 27127 if (vp == -1) { 27128 return BCM_E_PARAM; 27129 } 27130 27131 /* Be sure the entry is used and is set for VPLS */ 27132 if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeMpls)) { 27133 return BCM_E_NOT_FOUND; 27134 } 27135 rv = READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp, &svp); 27136 if (rv < 0) { 27137 return rv; 27138 } 27139 if (soc_SOURCE_VPm_field32_get(unit, &svp, ENTRY_TYPEf) != 1) { /* VPLS */ 27140 return BCM_E_NOT_FOUND; 27141 } 27142 cml = soc_SOURCE_VPm_field32_get(unit, &svp, CML_FLAGS_NEWf); 27143 27144 *flags = 0; 27145 if (!(cml & (1 << 0))) { 27146 *flags |= BCM_PORT_LEARN_FWD; 27147 } 27148 if (cml & (1 << 1)) { 27149 *flags |= BCM_PORT_LEARN_CPU; 27150 } 27151 if (cml & (1 << 2)) { 27152 *flags |= BCM_PORT_LEARN_PENDING; 27153 } 27154 if (cml & (1 << 3)) { 27155 *flags |= BCM_PORT_LEARN_ARL; 27156 } 27157 return BCM_E_NONE; 27158 } 27159 27160 /* 27161 * Function: 27162 * bcm_tr_mpls_mcast_flood_set 27163 * Purpose: 27164 * Set the PFM for a VPLS VFI. 27165 * Returns: 27166 * BCM_E_XXX 27167 */ 27168 int 27169 bcm_tr_mpls_mcast_flood_set(int unit, bcm_vlan_t vlan, 27170 bcm_vlan_mcast_flood_t mode) 27171 { 27172 int vfi, pfm = 0, rv = BCM_E_NONE; 27173 27174 rv = _bcm_tr_mpls_check_init (unit); 27175 if (rv < 0) { 27176 return rv; 27177 } 27178 27179 _BCM_MPLS_VPN_GET(vfi, _BCM_MPLS_VPN_TYPE_VPLS, vlan); 27180 27181 switch (mode) { 27182 case BCM_VLAN_MCAST_FLOOD_ALL: 27183 pfm = 0; 27184 break; 27185 case BCM_VLAN_MCAST_FLOOD_NONE: 27186 pfm = 2; 27187 break; 27188 default: 27189 pfm = 1; 27190 break; 27191 } 27192 27193 if (!_bcm_vfi_used_get(unit, vfi, _bcmVfiTypeMpls)) { 27194 return BCM_E_NOT_FOUND; 27195 } 27196 /* Update the HW entry */ 27197 rv = soc_mem_field32_modify(unit, VFIm, vfi, PFMf, pfm); 27198 return rv; 27199 } 27200 27201 /* 27202 * Function: 27203 * bcm_tr_mpls_mcast_flood_get 27204 * Purpose: 27205 * Get the PFM for a VPLS VFI. 27206 * Returns: 27207 * BCM_E_XXX 27208 */ 27209 int 27210 bcm_tr_mpls_mcast_flood_get(int unit, bcm_vlan_t vlan, 27211 bcm_vlan_mcast_flood_t *mode) 27212 { 27213 int vfi, pfm = 0, rv = BCM_E_NONE; 27214 vfi_entry_t vfi_entry; 27215 27216 rv = _bcm_tr_mpls_check_init (unit); 27217 if (rv < 0) { 27218 return rv; 27219 } 27220 27221 _BCM_MPLS_VPN_GET(vfi, _BCM_MPLS_VPN_TYPE_VPLS, vlan); 27222 27223 if (!_bcm_vfi_used_get(unit, vfi, _bcmVfiTypeMpls)) { 27224 return BCM_E_NOT_FOUND; 27225 } 27226 rv = READ_VFIm(unit, MEM_BLOCK_ANY, vfi, &vfi_entry); 27227 if (rv < 0) { 27228 return rv; 27229 } 27230 pfm = soc_VFIm_field32_get(unit, &vfi_entry, PFMf); 27231 27232 switch (pfm) { 27233 case 0: 27234 *mode = BCM_VLAN_MCAST_FLOOD_ALL; 27235 break; 27236 case 2: 27237 *mode = BCM_VLAN_MCAST_FLOOD_NONE; 27238 break; 27239 default: 27240 *mode = BCM_VLAN_MCAST_FLOOD_UNKNOWN; 27241 break; 27242 } 27243 return rv; 27244 } 27245 27246 /* 27247 * Function: 27248 * bcm_tr_mpls_port_phys_gport_get 27249 * Purpose: 27250 * Get the PFM for a VPLS VFI. 27251 * Returns: 27252 * BCM_E_XXX 27253 */ 27254 27255 int 27256 bcm_tr_mpls_port_phys_gport_get(int unit, int vp, bcm_gport_t *gp) 27257 { 27258 int nh_index; 27259 ing_dvp_table_entry_t dvp; 27260 ing_l3_next_hop_entry_t ing_nh; 27261 bcm_module_t mod_out, mod_in; 27262 bcm_port_t port_out, port_in; 27263 bcm_trunk_t trunk_id; 27264 uint32 dt, dv; 27265 27266 BCM_IF_ERROR_RETURN(READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp, &dvp)); 27267 nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, NEXT_HOP_INDEXf); 27268 BCM_IF_ERROR_RETURN(soc_mem_read(unit, ING_L3_NEXT_HOPm, MEM_BLOCK_ANY, 27269 nh_index, &ing_nh)); 27270 27271 if (soc_feature(unit, soc_feature_generic_dest)) { 27272 dv = soc_mem_field32_dest_get(unit, ING_L3_NEXT_HOPm, 27273 &ing_nh, DESTINATIONf, &dt); 27274 if (dt == SOC_MEM_FIF_DEST_LAG) { 27275 /* Trunk group */ 27276 trunk_id = dv & SOC_MEM_FIF_DGPP_TGID_MASK; 27277 BCM_GPORT_TRUNK_SET(*gp, trunk_id); 27278 27279 } else { 27280 port_in = dv & SOC_MEM_FIF_DGPP_PORT_MASK; 27281 mod_in = (dv & SOC_MEM_FIF_DGPP_MOD_ID_MASK) >> 27282 SOC_MEM_FIF_DGPP_MOD_ID_SHIFT_BITS; 27283 27284 BCM_IF_ERROR_RETURN 27285 (_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET, mod_in, port_in, 27286 &mod_out, &port_out)); 27287 BCM_GPORT_MODPORT_SET(*gp, mod_out, port_out); 27288 } 27289 } else { 27290 if (soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, Tf)) { 27291 trunk_id = soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, TGIDf); 27292 BCM_GPORT_TRUNK_SET(*gp, trunk_id); 27293 } else { 27294 mod_in = soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, MODULE_IDf); 27295 port_in = soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, PORT_NUMf); 27296 BCM_IF_ERROR_RETURN 27297 (_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET, mod_in, port_in, 27298 &mod_out, &port_out)); 27299 BCM_GPORT_MODPORT_SET(*gp, mod_out, port_out); 27300 } 27301 } 27302 return BCM_E_NONE; 27303 } 27304 27305 #ifndef BCM_SW_STATE_DUMP_DISABLE 27306 /* 27307 * Function: 27308 * _bcm_mpls_sw_dump 27309 * Purpose: 27310 * Displays MPLS State information maintained by software. 27311 * Parameters: 27312 * unit - Device unit number 27313 * Returns: 27314 * None 27315 */ 27316 void 27317 _bcm_mpls_sw_dump(int unit) 27318 { 27319 _bcm_tr_mpls_bookkeeping_t *mpls_info = MPLS_INFO(unit); 27320 int i, num_vp = 0, num_vc = 0, num_tnl = 0, num_trunk = 0; 27321 #ifdef BCM_KATANA_SUPPORT 27322 int num_queue = 0; 27323 #endif /* BCM_KATANA_SUPPORT */ 27324 soc_mem_t mem = 0; 27325 27326 if (!mpls_info->initialized) { 27327 LOG_CLI((BSL_META_U(unit, 27328 "\nMPLS data structure is not initialized\n"))); 27329 return; 27330 } 27331 27332 LOG_CLI((BSL_META_U(unit, 27333 "\nSW Information MPLS - Unit %d\n"), unit)); 27334 27335 if (SOC_MEM_IS_VALID(unit, SOURCE_VPm)) { 27336 num_vp = soc_mem_index_count(unit, SOURCE_VPm); 27337 } 27338 27339 LOG_CLI((BSL_META_U(unit, 27340 "\n Match Info : \n"))); 27341 for (i = 0; i < num_vp; i++) { 27342 if ((mpls_info->match_key[i].trunk_id == -1) && 27343 (mpls_info->match_key[i].modid == -1) && 27344 (mpls_info->match_key[i].port == 0)) { 27345 continue; 27346 } 27347 LOG_CLI((BSL_META_U(unit, 27348 "\n MPLS port vp = %d\n"), i)); 27349 LOG_CLI((BSL_META_U(unit, 27350 "Flags = %x\n"), mpls_info->match_key[i].flags)); 27351 LOG_CLI((BSL_META_U(unit, 27352 "Index = %x\n"), mpls_info->match_key[i].index)); 27353 LOG_CLI((BSL_META_U(unit, 27354 "TGID = %d\n"), mpls_info->match_key[i].trunk_id)); 27355 LOG_CLI((BSL_META_U(unit, 27356 "Modid = %d\n"), mpls_info->match_key[i].modid)); 27357 LOG_CLI((BSL_META_U(unit, 27358 "Port = %d\n"), mpls_info->match_key[i].port)); 27359 LOG_CLI((BSL_META_U(unit, 27360 "Match VLAN = %d\n"), 27361 mpls_info->match_key[i].match_vlan)); 27362 LOG_CLI((BSL_META_U(unit, 27363 "Match Inner VLAN = %d\n"), 27364 mpls_info->match_key[i].match_inner_vlan)); 27365 LOG_CLI((BSL_META_U(unit, 27366 "Match Label = %d\n"), 27367 mpls_info->match_key[i].match_label)); 27368 LOG_CLI((BSL_META_U(unit, 27369 "Match Count = %d\n"), 27370 mpls_info->match_key[i].match_count)); 27371 } 27372 27373 if (SOC_MEM_IS_VALID(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm)) { 27374 num_vc = soc_mem_index_count(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm); 27375 } 27376 for (i = 0; i < num_vc; i++) { 27377 if (mpls_info->vc_swap_ref_count[i]) { 27378 LOG_CLI((BSL_META_U(unit, 27379 "Label = %d RefCount=%d\n"), 27380 i, mpls_info->vc_swap_ref_count[i])); 27381 } 27382 } 27383 27384 /* VPWS VPs to VPN mapping */ 27385 27386 LOG_CLI((BSL_META_U(unit, 27387 "\nVPN to VPWS VP mapping:\n"))); 27388 LOG_CLI((BSL_META_U(unit, 27389 "-----------------------\n"))); 27390 LOG_CLI((BSL_META_U(unit, 27391 "VPN VPWS VPs\n"))); 27392 for (i=0; i<(num_vp/2); i++) { 27393 if (mpls_info->vpws_vp_map[i].vp1 != -1 && 27394 mpls_info->vpws_vp_map[i].vp2 != -1) { 27395 LOG_CLI((BSL_META_U(unit, 27396 "%d %d & %d\n"),(0x2000+i), 27397 mpls_info->vpws_vp_map[i].vp1, 27398 mpls_info->vpws_vp_map[i].vp2)); 27399 } 27400 } 27401 #if defined(BCM_TRIDENT3_SUPPORT) 27402 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 27403 mem = EGR_IP_TUNNEL_MPLS_DOUBLE_WIDEm; 27404 } else 27405 #endif 27406 { 27407 mem = EGR_IP_TUNNEL_MPLSm; 27408 } 27409 num_tnl = soc_mem_index_count(unit, mem); 27410 for (i = 0; i < num_tnl * _BCM_MPLS_NUM_MPLS_ENTRIES_PER_INDEX(unit); i++) { 27411 if (mpls_info->egr_tunnel_ref_count[i]) { 27412 LOG_CLI((BSL_META_U(unit, 27413 "Egress MPLS Tunnel = %d RefCount=%d\n"), 27414 i, mpls_info->egr_tunnel_ref_count[i])); 27415 } 27416 } 27417 27418 /* Print VP - NH mapping */ 27419 LOG_CLI((BSL_META_U(unit, 27420 "\n VP to NH mapping:\n"))); 27421 LOG_CLI((BSL_META_U(unit, 27422 "-----------------------\n"))); 27423 _bcm_tr_mpls_dump_egrNhop(unit); 27424 LOG_CLI((BSL_META_U(unit, 27425 "\n"))); 27426 #ifdef BCM_KATANA_SUPPORT 27427 if (soc_feature(unit, soc_feature_extended_queueing)) { 27428 num_queue = soc_mem_index_count(unit, ING_QUEUE_MAPm); 27429 LOG_CLI((BSL_META_U(unit,"\n Ingress Queue map reference count:\n"))); 27430 LOG_CLI((BSL_META_U(unit,"-----------------------\n"))); 27431 for (i = 0; i < num_queue; i++) { 27432 if (mpls_info->ing_qmap_ref_count[i]) { 27433 LOG_CLI((BSL_META_U(unit, 27434 "\n Ingress Queue Map Index = %d RefCount=%d\n"), 27435 i, mpls_info->ing_qmap_ref_count[i])); 27436 } 27437 } 27438 } 27439 #endif /* BCM_KATANA_SUPPORT */ 27440 27441 /* Trunk to VP mapping */ 27442 if (SOC_MEM_IS_VALID(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm)) { 27443 num_trunk = soc_mem_index_count(unit, TRUNK_GROUPm); 27444 } 27445 27446 LOG_CLI((BSL_META_U(unit, 27447 "\nTrunk to VP mapping:\n"))); 27448 LOG_CLI((BSL_META_U(unit, 27449 "-----------------------\n"))); 27450 LOG_CLI((BSL_META_U(unit, 27451 "TRUNK VP\n"))); 27452 for (i = 0; i < num_trunk; i++) { 27453 if (mpls_info->trunk_vp_map[i] != -1) { 27454 LOG_CLI((BSL_META_U(unit, 27455 "%d %d\n"), 27456 i, mpls_info->trunk_vp_map[i])); 27457 } 27458 } 27459 #ifdef BCM_SPECIAL_LABEL_SUPPORT 27460 if (soc_feature(unit, soc_feature_mpls_special_label)) { 27461 int num_entry = 0; 27462 bcmi_mpls_special_label_control_t *ptr; 27463 27464 ptr = bcmi_special_label_precedence_state[unit]; 27465 num_entry = 27466 soc_mem_index_count(unit, SPECIAL_LABEL_CONTROLm); 27467 for (i = 0; i < num_entry; i++) { 27468 if (ptr[i].valid) { 27469 LOG_CLI((BSL_META_U(unit,"Index = %d : Label Value = 0x%x Label Mask= 0x%x Label Type = %s ref_count= %d\n"), 27470 i, ptr[i].label_value, ptr[i].label_mask, label_type_array[ptr[i].label_type], ptr[i].ref_count)); 27471 } 27472 } 27473 } 27474 #endif 27475 27476 #if defined BCM_TRIUMPH2_SUPPORT 27477 if (soc_feature(unit, soc_feature_mpls_failover)) { 27478 for (i = 0; i < num_vp; i++) { 27479 if (mpls_info->failover_vp[i] == 0) { 27480 continue; 27481 } 27482 LOG_CLI((BSL_META_U(unit, 27483 "\n MPLS vp %d failover vp = %d\n"), i, 27484 mpls_info->failover_vp[i])); 27485 } 27486 } 27487 #endif 27488 return; 27489 } 27490 #endif /* BCM_SW_STATE_DUMP_DISABLE */ 27491 27492 27493 #ifdef BCM_TRIUMPH2_SUPPORT 27494 int 27495 _bcm_esw_mpls_flex_stat_index_set(int unit, bcm_gport_t port, int fs_idx,uint32 flags) 27496 { 27497 int rv, vp, nh_index=0; 27498 source_vp_entry_t svp; 27499 ing_dvp_table_entry_t dvp; 27500 egr_l3_next_hop_entry_t egr_nh; 27501 uint32 entry_type=0; 27502 initial_prot_nhi_table_entry_t prot_entry; 27503 int vpless_failover_port = FALSE; 27504 27505 if (_BCM_MPLS_GPORT_FAILOVER_VPLESS_GET(port)) { 27506 vpless_failover_port = TRUE; 27507 port = _BCM_MPLS_GPORT_FAILOVER_VPLESS_CLEAR(port); 27508 } 27509 27510 vp = BCM_GPORT_MPLS_PORT_ID_GET(port); 27511 if (vp == -1) { 27512 return BCM_E_PARAM; 27513 } 27514 27515 rv = bcm_tr_mpls_lock(unit); 27516 if (BCM_FAILURE(rv)) { 27517 return rv; 27518 } 27519 if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeMpls)) { 27520 bcm_tr_mpls_unlock(unit); 27521 return BCM_E_NOT_FOUND; 27522 } else { 27523 /* Ingress side */ 27524 if (flags & _BCM_FLEX_STAT_HW_INGRESS) { 27525 rv = soc_mem_read(unit, SOURCE_VPm, MEM_BLOCK_ANY, vp, &svp); 27526 if (BCM_SUCCESS(rv)) { 27527 if (soc_mem_field_valid(unit, SOURCE_VPm, USE_VINTF_CTR_IDXf)) { 27528 soc_mem_field32_set(unit, SOURCE_VPm, &svp, USE_VINTF_CTR_IDXf, 27529 fs_idx > 0 ? 1 : 0); 27530 } 27531 soc_mem_field32_set(unit, SOURCE_VPm, &svp, VINTF_CTR_IDXf, 27532 fs_idx); 27533 rv = soc_mem_write(unit, SOURCE_VPm, MEM_BLOCK_ALL, vp, &svp); 27534 } 27535 } 27536 /* Egress side */ 27537 if (flags & _BCM_FLEX_STAT_HW_EGRESS) { 27538 if (BCM_SUCCESS(rv)) { 27539 rv = READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp, &dvp); 27540 if (BCM_SUCCESS(rv)) { 27541 nh_index = soc_mem_field32_get(unit, ING_DVP_TABLEm, &dvp, 27542 NEXT_HOP_INDEXf); 27543 if (vpless_failover_port == TRUE) { 27544 rv = READ_INITIAL_PROT_NHI_TABLEm(unit,MEM_BLOCK_ANY, nh_index, &prot_entry); 27545 if (BCM_SUCCESS(rv)) { 27546 nh_index = soc_INITIAL_PROT_NHI_TABLEm_field32_get(unit,&prot_entry, 27547 PROT_NEXT_HOP_INDEXf); 27548 } 27549 } 27550 } 27551 } 27552 if (BCM_SUCCESS(rv)) { 27553 rv = soc_mem_read(unit, EGR_L3_NEXT_HOPm, MEM_BLOCK_ANY, nh_index, 27554 &egr_nh); 27555 } 27556 if (BCM_SUCCESS(rv)) { 27557 entry_type = soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_nh, ENTRY_TYPEf); 27558 if(entry_type == 1) { 27559 if (soc_mem_field_valid(unit, EGR_L3_NEXT_HOPm, 27560 MPLS__USE_VINTF_CTR_IDXf)) { 27561 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 27562 MPLS__USE_VINTF_CTR_IDXf, 27563 fs_idx > 0 ? 1 : 0); 27564 } 27565 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 27566 MPLS__VINTF_CTR_IDXf, fs_idx); 27567 } else if (entry_type == 2) { 27568 if (soc_mem_field_valid(unit, EGR_L3_NEXT_HOPm, 27569 SD_TAG__USE_VINTF_CTR_IDXf)) { 27570 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 27571 SD_TAG__USE_VINTF_CTR_IDXf, 27572 fs_idx > 0 ? 1 : 0); 27573 } 27574 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 27575 SD_TAG__VINTF_CTR_IDXf, fs_idx); 27576 } 27577 rv = soc_mem_write(unit, EGR_L3_NEXT_HOPm, MEM_BLOCK_ALL, nh_index, 27578 &egr_nh); 27579 } 27580 } 27581 } 27582 27583 bcm_tr_mpls_unlock(unit); 27584 return rv; 27585 } 27586 27587 int 27588 _bcm_tr2_mpls_svp_field_set(int unit, bcm_gport_t vp, 27589 soc_field_t field, int value) 27590 { 27591 int rv = BCM_E_NONE; 27592 source_vp_entry_t svp; 27593 27594 rv = bcm_tr_mpls_lock(unit); 27595 if (BCM_FAILURE(rv)) { 27596 return rv; 27597 } 27598 rv = READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp, &svp); 27599 if (rv < 0) { 27600 bcm_tr_mpls_unlock(unit); 27601 return rv; 27602 } 27603 if (SOC_MEM_FIELD_VALID(unit, SOURCE_VPm, field)) { 27604 soc_SOURCE_VPm_field32_set(unit, &svp, field, value); 27605 } else { 27606 bcm_tr_mpls_unlock(unit); 27607 return BCM_E_UNAVAIL; 27608 } 27609 rv = WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, vp, &svp); 27610 bcm_tr_mpls_unlock(unit); 27611 return rv; 27612 } 27613 27614 #endif /* BCM_TRIUMPH2_SUPPORT */ 27615 27616 int _bcm_tr_mpls_vpws_egress_if_get(int unit, bcm_gport_t gport, bcm_if_t *egress_if) 27617 { 27618 int vp = -1; 27619 uint32 nh_index; 27620 ing_dvp_table_entry_t dvp; 27621 27622 vp = BCM_GPORT_MPLS_PORT_ID_GET(gport); 27623 if (vp == -1) { 27624 return BCM_E_PARAM; 27625 } 27626 27627 if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeMpls)) { 27628 return BCM_E_PARAM; 27629 } 27630 27631 BCM_IF_ERROR_RETURN (READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp, &dvp)); 27632 nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, NEXT_HOP_INDEXf); 27633 *egress_if = nh_index + BCM_XGS3_DVP_EGRESS_IDX_MIN(unit); 27634 27635 return BCM_E_NONE; 27636 } 27637 27638 #if defined(BCM_TRIDENT3_SUPPORT) 27639 /* 27640 * Function: 27641 * bcm_td3_mpls_php_info_add 27642 * Purpose: 27643 * Add VC_AND_SWAP_TABLE for a specific EGR_NH Index 27644 * Parameters: 27645 * IN : Unit 27646 * IN/OUT : Tunnel Switch Pointer 27647 * IN : nh_index 27648 * Returns: 27649 * BCM_E_XXX 27650 */ 27651 27652 int 27653 bcmi_td3_mpls_php_vcswap_info_add(int unit, bcm_mpls_tunnel_switch_t *php_info, int *nh_index) 27654 { 27655 bcm_l3_egress_t nh_info; 27656 _bcm_tr_egr_nh_info_t egr_nh_info; 27657 egr_mpls_vc_and_swap_label_table_entry_t vc_entry; 27658 int rv = BCM_E_NONE, temp_nh_index = -1; 27659 uint32 mpath_flag=0; 27660 egr_nh_info.vc_swap_index = -1; 27661 27662 /* 27663 * Get egress next-hop index from egress object and 27664 * increment egress object reference count. 27665 */ 27666 if (BCM_XGS3_L3_EGRESS_IDX_VALID(unit, php_info->egress_if)) { 27667 rv = bcm_xgs3_get_nh_from_egress_object(unit, php_info->egress_if, 27668 &mpath_flag, 1, &temp_nh_index); 27669 27670 bcm_l3_egress_t_init(&nh_info); 27671 27672 /* Get egress next-hop info from the egress object */ 27673 rv = bcm_xgs3_nh_get(unit, temp_nh_index, &nh_info); 27674 27675 BCM_IF_ERROR_RETURN(rv); 27676 } 27677 27678 rv = _bcm_tr_mpls_get_vc_and_swap_table_index(unit, 0, NULL, php_info, NULL, 27679 NULL, _BCM_MPLS_ACTION_PRESERVED, &egr_nh_info.vc_swap_index); 27680 27681 BCM_IF_ERROR_RETURN(rv); 27682 27683 /* Program the MPLS_VC_AND_SWAP table entry */ 27684 rv = _bcm_tr_mpls_vc_and_swap_table_entry_set(unit, NULL, php_info, NULL, 27685 _BCM_MPLS_ACTION_PRESERVED, 27686 &vc_entry, 0, egr_nh_info.vc_swap_index); 27687 _BCM_MPLS_CLEANUP(rv); 27688 27689 /* Write the entry into index, index is derived above successfully. */ 27690 rv = soc_mem_write(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 27691 MEM_BLOCK_ALL, egr_nh_info.vc_swap_index, 27692 &vc_entry); 27693 27694 _BCM_MPLS_CLEANUP(rv); 27695 27696 /* Write EGR_L3_NEXT_HOP entry */ 27697 rv = soc_mem_field32_modify(unit, EGR_L3_NEXT_HOPm, *nh_index, 27698 MPLS__VC_AND_SWAP_INDEXf, egr_nh_info.vc_swap_index); 27699 _BCM_MPLS_CLEANUP(rv); 27700 27701 #if defined(BCM_TRIUMPH3_SUPPORT) 27702 if (soc_feature(unit, soc_feature_vc_and_swap_table_overlaid)) { 27703 rv = _bcm_tr_mpls_vc_and_swap_hash_nhop_add(unit, 27704 egr_nh_info.vc_swap_index, 27705 *nh_index); 27706 _BCM_MPLS_CLEANUP(rv); 27707 } 27708 #endif 27709 27710 return rv; 27711 27712 cleanup: 27713 if (egr_nh_info.vc_swap_index >= 0) { 27714 _bcm_tr_mpls_vc_and_swap_ref_count_adjust (unit, 27715 egr_nh_info.vc_swap_index, -1); 27716 /* Free VC_AND_SWAP_LABEL entry */ 27717 (void)_bcm_tr_mpls_vc_and_swap_table_index_reset (unit, 27718 egr_nh_info.vc_swap_index); 27719 } 27720 return rv; 27721 } 27722 27723 27724 /* 27725 * Function: 27726 * bcmi_td3_mpls_php_vcswap_info_delete 27727 * Purpose: 27728 * Delete VC_AND_SWAP_TABLE for a specific EGR_NH Index 27729 * Parameters: 27730 * IN : Unit 27731 * IN : nh_index 27732 * Returns: 27733 * BCM_E_XXX 27734 */ 27735 27736 int 27737 bcmi_td3_mpls_php_vcswap_info_delete(int unit, int nh_index,int type) 27738 { 27739 int rv = BCM_E_NONE, old_vc_swap_idx = -1; 27740 egr_l3_next_hop_entry_t egr_nh; 27741 27742 BCM_IF_ERROR_RETURN (soc_mem_read(unit, EGR_L3_NEXT_HOPm, 27743 MEM_BLOCK_ANY, nh_index, &egr_nh)); 27744 27745 if (soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, nh_entry_type_field[unit]) != 0x1) { 27746 return BCM_E_NOT_FOUND; 27747 } 27748 27749 if (soc_feature(unit, soc_feature_mpls_enhanced)) { 27750 old_vc_swap_idx = soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, 27751 MPLS__VC_AND_SWAP_INDEXf); 27752 } 27753 27754 /* Clear VC_SWAP_INDEX in EGR_L3_NEXT_HOP entry */ 27755 if (old_vc_swap_idx != -1) { 27756 int vc_and_swap_ref_count = 0; 27757 int nh_ref_count = BCM_XGS3_L3_ENT_REF_CNT(BCM_XGS3_L3_TBL_PTR(unit, next_hop), nh_index); 27758 27759 _bcm_tr_mpls_vc_and_swap_ref_count_get(unit, old_vc_swap_idx, &vc_and_swap_ref_count); 27760 if ((nh_ref_count <= 3) || (vc_and_swap_ref_count <= 1)) { 27761 rv = soc_mem_field32_modify(unit, EGR_L3_NEXT_HOPm, nh_index, 27762 MPLS__VC_AND_SWAP_INDEXf, 0); 27763 } 27764 27765 #if defined(BCM_TRIUMPH3_SUPPORT) 27766 if (soc_feature(unit, soc_feature_vc_and_swap_table_overlaid)) { 27767 BCM_IF_ERROR_RETURN( 27768 _bcm_tr_mpls_vc_and_swap_hash_nhop_delete(unit, 27769 old_vc_swap_idx, 27770 nh_index)); 27771 } 27772 #endif 27773 27774 /* clear VC_AND_SWAP_LABEL entry */ 27775 _bcm_tr_mpls_vc_and_swap_ref_count_adjust (unit, old_vc_swap_idx, -1); 27776 27777 /* Free VC_AND_SWAP_LABEL entry */ 27778 BCM_IF_ERROR_RETURN 27779 (_bcm_tr_mpls_vc_and_swap_table_index_reset (unit, old_vc_swap_idx)); 27780 } 27781 27782 return rv; 27783 } 27784 27785 #endif 27786 #else /* BCM_TRIUMPH_SUPPORT && BCM_MPLS_SUPPORT && INCLUDE_L3 */ 27787 int bcm_tr_mpls_not_empty; 27788 #endif /* BCM_TRIUMPH_SUPPORT && BCM_MPLS_SUPPORT && INCLUDE_L3 */