mpls.c (236611B)
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 Tomahawk, TD2+ MPLS functions 9 */ 10 #include <shared/bsl.h> 11 12 #include <soc/defs.h> 13 #include <sal/core/libc.h> 14 #include <shared/bsl.h> 15 16 #ifdef INCLUDE_L3 17 #ifdef BCM_MPLS_SUPPORT 18 #if (defined(BCM_TOMAHAWK_SUPPORT) || defined(BCM_TRIDENT2PLUS_SUPPORT)) 19 20 #include <soc/drv.h> 21 #include <soc/hash.h> 22 #include <soc/mem.h> 23 #include <soc/util.h> 24 #include <soc/debug.h> 25 #include <soc/triumph.h> 26 #include <soc/format.h> 27 28 #include <bcm/error.h> 29 #include <bcm/mpls.h> 30 31 #include <bcm_int/esw/mbcm.h> 32 #include <bcm_int/esw/l3.h> 33 #include <bcm_int/esw/firebolt.h> 34 #include <bcm_int/esw/tomahawk.h> 35 #include <bcm_int/esw/triumph3.h> 36 #include <bcm_int/esw/trident2plus.h> 37 #include <bcm_int/esw/triumph.h> 38 #include <bcm_int/esw/triumph2.h> 39 #include <bcm_int/esw/trx.h> 40 #include <bcm_int/esw/xgs3.h> 41 #include <bcm_int/esw/xgs5.h> 42 #include <bcm_int/esw/mpls.h> 43 #include <bcm_int/esw/stack.h> 44 #include <bcm_int/common/multicast.h> 45 #include <bcm_int/esw/virtual.h> 46 #include <bcm_int/esw/port.h> 47 #include <bcm_int/esw/ecn.h> 48 #include <bcm_int/esw_dispatch.h> 49 #include <bcm_int/api_xlate_port.h> 50 #include <bcm_int/esw/failover.h> 51 #ifdef BCM_TOMAHAWK2_SUPPORT 52 #include <bcm_int/esw/tomahawk2.h> 53 #endif 54 #ifdef BCM_TOMAHAWK3_SUPPORT 55 #include <bcm_int/esw/tomahawk3.h> 56 #endif 57 #ifdef BCM_TRIDENT3_SUPPORT 58 #include <soc/esw/cancun.h> 59 #include <soc/esw/cancun_enums.h> 60 #endif /* BCM_TRIDENT3_SUPPORT */ 61 62 #define MPLS_INFO(_unit_) (&_bcm_tr_mpls_bk_info[_unit_]) 63 #define L3_INFO(_unit_) (&_bcm_l3_bk_info[_unit_]) 64 65 #define bcmi_mpls_bookkeeping_t _bcm_tr_mpls_bookkeeping_t 66 67 bcmi_egr_ip_tnl_mpls_tunnel_entry_t **egr_mpls_tnl_sw_state[BCM_MAX_NUM_UNITS]; 68 bcmi_egr_ip_tnl_free_indexes_t fi_db[BCM_MAX_NUM_UNITS]; 69 70 STATIC int 71 _bcmi_xgs5_mpls_entry_set_key(int unit, bcm_mpls_tunnel_switch_t *info, 72 mpls_entry_entry_t *ment); 73 74 /* 75 TD3 MPLS_ENTRY_X FORMAT: 76 ---------------------------------------------------------------------------------------------------------- 77 | MPLS_LABEL(0:19) | MPLS_PUSH_ACTION(20:21) | MPLS_EXP_SELECT(22:23) | 78 ----------------------------------------------------------------------------------------------------------| 79 | MPLS_EXP_MAPPING_PTR(24:27) | NEW_CFI(24:24) | NEW_PRI(25:27) | 80 ----------------------------------------------------------------------------------------------------------| 81 | MPLS_EXP(30:28) | LABEL_SELECT(31:31) | MPLS_TTL(32:39) | 82 ----------------------------------------------------------------------------------------------------------| 83 | SPECIAL_LABEL_PUSH_TYPE(40:41) | EXP_MAPPING_TABLE_SELECT(42:43) | PKT_ECN_TO_EXP_MAPPING_PTR(44:45)| 84 ----------------------------------------------------------------------------------------------------------| 85 | PKT_ECN_TO_EXP_PRIORITY(46:46) | EGR_FLEX_CTR_ACTION_SET(47:65) | FLEX_CTR_BASE_COUNTER_IDX(47:59) | 86 ----------------------------------------------------------------------------------------------------------| 87 | FLEX_CTR_POOL_NUMBER(60:61) | RSVD_FLEX_CTR_POOL_NUMBER(62:63) | FLEX_CTR_OFFSET_MODE(61:65) | 88 ----------------------------------------------------------------------------------------------------------| 89 | ECN_MAPPING_ENABLE(66:66) | ECN_MAPPING_TABLE_SELECT(67:68) | RESERVED(69:70) | 90 ---------------------------------------------------------------------------------------------------------- 91 */ 92 #ifdef BCM_TRIDENT3_SUPPORT 93 static soc_field_t _tnl_label_entry_f[] = 94 { MPLS_ENTRY_0f, MPLS_ENTRY_1f, MPLS_ENTRY_2f, MPLS_ENTRY_3f, 95 MPLS_ENTRY_4f, MPLS_ENTRY_5f, MPLS_ENTRY_6f, MPLS_ENTRY_7f }; 96 #endif 97 98 static soc_field_t _tnl_label_f[] = 99 { MPLS_LABEL_0f, MPLS_LABEL_1f, MPLS_LABEL_2f, MPLS_LABEL_3f, 100 MPLS_LABEL_4f, MPLS_LABEL_5f, MPLS_LABEL_6f, MPLS_LABEL_7f }; 101 static soc_field_t _tnl_push_action_f[] = 102 { MPLS_PUSH_ACTION_0f, MPLS_PUSH_ACTION_1f, 103 MPLS_PUSH_ACTION_2f, MPLS_PUSH_ACTION_3f, 104 MPLS_PUSH_ACTION_4f, MPLS_PUSH_ACTION_5f, 105 MPLS_PUSH_ACTION_6f, MPLS_PUSH_ACTION_7f }; 106 static soc_field_t _tnl_exp_select_f[] = 107 { MPLS_EXP_SELECT_0f, MPLS_EXP_SELECT_1f, 108 MPLS_EXP_SELECT_2f, MPLS_EXP_SELECT_3f, 109 MPLS_EXP_SELECT_4f, MPLS_EXP_SELECT_5f, 110 MPLS_EXP_SELECT_6f, MPLS_EXP_SELECT_7f }; 111 static soc_field_t _tnl_exp_ptr_f[] = 112 { MPLS_EXP_MAPPING_PTR_0f, MPLS_EXP_MAPPING_PTR_1f, 113 MPLS_EXP_MAPPING_PTR_2f, MPLS_EXP_MAPPING_PTR_3f, 114 MPLS_EXP_MAPPING_PTR_4f, MPLS_EXP_MAPPING_PTR_5f, 115 MPLS_EXP_MAPPING_PTR_6f, MPLS_EXP_MAPPING_PTR_7f }; 116 static soc_field_t _tnl_exp_f[] = 117 { MPLS_EXP_0f, MPLS_EXP_1f, MPLS_EXP_2f, MPLS_EXP_3f, 118 MPLS_EXP_4f, MPLS_EXP_5f, MPLS_EXP_6f, MPLS_EXP_7f }; 119 static soc_field_t _tnl_ttl_f[] = 120 { MPLS_TTL_0f, MPLS_TTL_1f, MPLS_TTL_2f, MPLS_TTL_3f, 121 MPLS_TTL_4f, MPLS_TTL_5f, MPLS_TTL_6f, MPLS_TTL_7f }; 122 static soc_field_t _tnl_pri_f[] = 123 { NEW_PRI_0f, NEW_PRI_1f, NEW_PRI_2f, NEW_PRI_3f, 124 NEW_PRI_4f, NEW_PRI_5f, NEW_PRI_6f, NEW_PRI_7f }; 125 static soc_field_t _tnl_cfi_f[] = 126 { NEW_CFI_0f, NEW_CFI_1f, NEW_CFI_2f, NEW_CFI_3f, 127 NEW_CFI_4f, NEW_CFI_5f, NEW_CFI_6f, NEW_CFI_7f }; 128 #if defined(BCM_TOMAHAWK2_SUPPORT) || defined(BCM_TRIDENT3_SUPPORT) 129 static soc_field_t _tnl_ecn_ptr_f[] = 130 { IP_ECN_TO_EXP_MAPPING_PTR_0f, IP_ECN_TO_EXP_MAPPING_PTR_1f, 131 IP_ECN_TO_EXP_MAPPING_PTR_2f, IP_ECN_TO_EXP_MAPPING_PTR_3f, 132 IP_ECN_TO_EXP_MAPPING_PTR_4f, IP_ECN_TO_EXP_MAPPING_PTR_5f, 133 IP_ECN_TO_EXP_MAPPING_PTR_6f, IP_ECN_TO_EXP_MAPPING_PTR_7f}; 134 static soc_field_t _tnl_ecn_ptr_pri_f[] = 135 { IP_ECN_TO_EXP_PRIORITY_0f, IP_ECN_TO_EXP_PRIORITY_1f, 136 IP_ECN_TO_EXP_PRIORITY_2f, IP_ECN_TO_EXP_PRIORITY_3f, 137 IP_ECN_TO_EXP_PRIORITY_4f, IP_ECN_TO_EXP_PRIORITY_5f, 138 IP_ECN_TO_EXP_PRIORITY_6f, IP_ECN_TO_EXP_PRIORITY_7f}; 139 static soc_field_t _tnl_int_cn_ptr_f[] = 140 { INT_CN_TO_EXP_MAPPING_PTR_0f, INT_CN_TO_EXP_MAPPING_PTR_1f, 141 INT_CN_TO_EXP_MAPPING_PTR_2f, INT_CN_TO_EXP_MAPPING_PTR_3f, 142 INT_CN_TO_EXP_MAPPING_PTR_4f, INT_CN_TO_EXP_MAPPING_PTR_5f, 143 INT_CN_TO_EXP_MAPPING_PTR_6f, INT_CN_TO_EXP_MAPPING_PTR_7f}; 144 static soc_field_t _tnl_int_cn_ptr_pri_f[] = 145 { INT_CN_TO_EXP_PRIORITY_0f, INT_CN_TO_EXP_PRIORITY_1f, 146 INT_CN_TO_EXP_PRIORITY_2f, INT_CN_TO_EXP_PRIORITY_3f, 147 INT_CN_TO_EXP_PRIORITY_4f, INT_CN_TO_EXP_PRIORITY_5f, 148 INT_CN_TO_EXP_PRIORITY_6f, INT_CN_TO_EXP_PRIORITY_7f}; 149 #endif 150 /************************ FUNCTIONS BOUNDARY **********************/ 151 152 STATIC soc_mem_t 153 bcmi_egr_ip_tnl_mem_name_get(int unit) 154 { 155 soc_mem_t mem; 156 157 #if defined(BCM_TRIDENT3_SUPPORT) 158 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 159 mem = EGR_IP_TUNNEL_MPLS_DOUBLE_WIDEm; 160 } else 161 #endif 162 { 163 mem = EGR_IP_TUNNEL_MPLSm; 164 } 165 return mem; 166 } 167 168 STATIC int 169 bcmi_egr_ip_tnl_mpls_table_write(int unit,int tnl_id,void *tnl_buf) 170 { 171 int rv = BCM_E_NONE; 172 173 #if defined(BCM_TRIDENT3_SUPPORT) 174 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 175 rv = WRITE_EGR_IP_TUNNEL_MPLS_DOUBLE_WIDEm(unit, MEM_BLOCK_ANY, 176 tnl_id, tnl_buf); 177 } else 178 #endif 179 { 180 rv = WRITE_EGR_IP_TUNNEL_MPLSm(unit, MEM_BLOCK_ANY, tnl_id, tnl_buf); 181 } 182 return rv; 183 } 184 185 186 STATIC int 187 bcmi_egr_ip_tnl_mpls_table_read(int unit,int tnl_id,void *tnl_buf) 188 { 189 int rv = BCM_E_NONE; 190 191 #if defined(BCM_TRIDENT3_SUPPORT) 192 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 193 rv = READ_EGR_IP_TUNNEL_MPLS_DOUBLE_WIDEm(unit, 194 MEM_BLOCK_ANY,tnl_id, tnl_buf); 195 } else 196 #endif 197 { 198 rv = READ_EGR_IP_TUNNEL_MPLSm(unit, MEM_BLOCK_ANY, 199 tnl_id,tnl_buf); 200 } 201 return rv; 202 } 203 204 STATIC void 205 bcmi_egr_ip_tnl_mpls_table_memset(int unit,void *tnl_buf) 206 { 207 208 #if defined(BCM_TRIDENT3_SUPPORT) 209 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 210 sal_memset(tnl_buf, 0, 211 sizeof(egr_ip_tunnel_mpls_double_wide_entry_t)); 212 } else 213 #endif 214 { 215 sal_memset(tnl_buf, 0, sizeof(egr_ip_tunnel_mpls_entry_t)); 216 } 217 } 218 219 STATIC int 220 bcmi_egr_ip_tnl_mpls_entry_type_check(int unit,void *tnl_buf) 221 { 222 int rv = BCM_E_NONE; 223 soc_mem_t mem; 224 mem = bcmi_egr_ip_tnl_mem_name_get(unit); 225 226 #if defined(BCM_TRIDENT3_SUPPORT) 227 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 228 if (soc_mem_field32_get(unit, 229 mem, 230 tnl_buf, DATA_TYPEf) != 0x14) { 231 return BCM_E_INTERNAL; 232 } 233 } else 234 #endif 235 { 236 if (soc_mem_field32_get(unit, 237 mem, 238 tnl_buf, ENTRY_TYPEf) != 3) { 239 return BCM_E_INTERNAL; 240 } 241 } 242 return rv; 243 } 244 245 int 246 bcmi_egress_tnl_label_entry_set(int unit, void *tnl_buf, 247 int offset, uint32 *data_buf) 248 { 249 int rv = BCM_E_NONE; 250 251 #if defined(BCM_TRIDENT3_SUPPORT) 252 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 253 soc_mem_field_set(unit, EGR_IP_TUNNEL_MPLS_DOUBLE_WIDEm, 254 (uint32 *)tnl_buf, _tnl_label_entry_f[offset], data_buf); 255 } 256 #endif 257 258 return rv; 259 } 260 261 262 int 263 bcmi_egress_tnl_label_entry_get(int unit, void *tnl_buf, 264 int offset, uint32 *data_buf) 265 { 266 int rv = BCM_E_NONE; 267 268 #if defined(BCM_TRIDENT3_SUPPORT) 269 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 270 soc_mem_field_get(unit, EGR_IP_TUNNEL_MPLS_DOUBLE_WIDEm, 271 (uint32 *)tnl_buf, _tnl_label_entry_f[offset], data_buf); 272 } 273 #endif 274 275 return rv; 276 } 277 278 STATIC int 279 bcmi_validate_field_range(int unit,uint32 set_val,int range) 280 { 281 #ifdef BCM_TRIDENT3_SUPPORT 282 return BCM_E_NONE; 283 #else 284 return BCM_E_NONE; 285 #endif 286 287 } 288 289 STATIC void 290 bcmi_egr_ip_tnl_copy_src_label_info_to_dest(int unit, void *src_entry , 291 void *dst_entry, int src_offset, int dst_offset, int no_of_elements) 292 { 293 int i = 0; 294 int src_value; 295 296 for (; i < no_of_elements; i++) { 297 src_value = soc_mem_field32_get(unit, EGR_IP_TUNNEL_MPLSm, src_entry, 298 _tnl_push_action_f[src_offset+i]); 299 soc_mem_field32_set(unit, EGR_IP_TUNNEL_MPLSm, dst_entry, 300 _tnl_push_action_f[dst_offset+i], src_value); 301 src_value = soc_mem_field32_get(unit, EGR_IP_TUNNEL_MPLSm, src_entry, 302 _tnl_label_f[src_offset+i]); 303 soc_mem_field32_set(unit, EGR_IP_TUNNEL_MPLSm, dst_entry, 304 _tnl_label_f[dst_offset+i], src_value); 305 src_value = soc_mem_field32_get(unit, EGR_IP_TUNNEL_MPLSm, src_entry, 306 _tnl_exp_select_f[src_offset+i]); 307 soc_mem_field32_set(unit, EGR_IP_TUNNEL_MPLSm, dst_entry, 308 _tnl_exp_select_f[dst_offset+i], src_value); 309 src_value = soc_mem_field32_get(unit, EGR_IP_TUNNEL_MPLSm, src_entry, 310 _tnl_exp_f[src_offset+i]); 311 soc_mem_field32_set(unit, EGR_IP_TUNNEL_MPLSm, dst_entry, 312 _tnl_exp_f[dst_offset+i], src_value); 313 src_value = soc_mem_field32_get(unit, EGR_IP_TUNNEL_MPLSm, src_entry, 314 _tnl_pri_f[src_offset+i]); 315 soc_mem_field32_set(unit, EGR_IP_TUNNEL_MPLSm, dst_entry, 316 _tnl_pri_f[dst_offset+i], src_value); 317 src_value = soc_mem_field32_get(unit, EGR_IP_TUNNEL_MPLSm, src_entry, 318 _tnl_cfi_f[src_offset+i]); 319 soc_mem_field32_set(unit, EGR_IP_TUNNEL_MPLSm, dst_entry, 320 _tnl_cfi_f[dst_offset+i], src_value); 321 src_value = soc_mem_field32_get(unit, EGR_IP_TUNNEL_MPLSm, src_entry, 322 _tnl_exp_ptr_f[src_offset+i]); 323 soc_mem_field32_set(unit, EGR_IP_TUNNEL_MPLSm, dst_entry, 324 _tnl_exp_ptr_f[dst_offset+i], src_value); 325 src_value = soc_mem_field32_get(unit, EGR_IP_TUNNEL_MPLSm, src_entry, 326 _tnl_ttl_f[src_offset+i]); 327 soc_mem_field32_set(unit, EGR_IP_TUNNEL_MPLSm, dst_entry, 328 _tnl_ttl_f[dst_offset+i], src_value); 329 } 330 } 331 332 STATIC int 333 bcmi_td3_destination_format_set(int unit, mpls_entry_entry_t *mpls_entry, 334 int dest_type, int value) 335 { 336 if (mpls_entry == NULL) { 337 return BCM_E_PARAM; 338 } 339 340 switch (dest_type) { 341 case SOC_MEM_FIF_DEST_NEXTHOP: 342 soc_mem_field32_dest_set(unit, MPLS_ENTRYm, mpls_entry, 343 DESTINATIONf, 344 SOC_MEM_FIF_DEST_NEXTHOP, value); 345 break; 346 case SOC_MEM_FIF_DEST_ECMP: 347 soc_mem_field32_dest_set(unit, MPLS_ENTRYm, mpls_entry, 348 DESTINATIONf, 349 SOC_MEM_FIF_DEST_ECMP, value); 350 break; 351 default: 352 break; 353 } 354 355 return BCM_E_NONE; 356 } 357 358 STATIC int 359 _bcmi_xgs5_mpls_entry_get_key(int unit, mpls_entry_entry_t *ment, 360 bcm_mpls_tunnel_switch_t *info) 361 { 362 bcm_port_t port_in = 0, port_out = 0; 363 bcm_module_t mod_in = 0, mod_out = 0; 364 bcm_trunk_t trunk_id; 365 soc_mem_t mem = MPLS_ENTRYm; 366 367 if (soc_feature(unit, soc_feature_th3_style_simple_mpls)) { 368 mem = MPLS_ENTRY_SINGLEm; 369 } else { 370 mod_in = soc_mem_field32_get(unit, mem, ment, MODULE_IDf); 371 } 372 port_in = soc_mem_field32_get(unit, mem, ment, PORT_NUMf); 373 if (soc_mem_field32_get(unit, mem, ment, Tf)) { 374 trunk_id = soc_mem_field32_get(unit, mem, ment, TGIDf); 375 BCM_GPORT_TRUNK_SET(info->port, trunk_id); 376 } else if ((port_in == 0) && (mod_in == 0)) { 377 /* Global label, mod/port not part of lookup key */ 378 info->port = BCM_GPORT_INVALID; 379 } else { 380 BCM_IF_ERROR_RETURN 381 (_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET, 382 mod_in, port_in, &mod_out, &port_out)); 383 BCM_GPORT_MODPORT_SET(info->port, mod_out, port_out); 384 } 385 info->label = soc_mem_field32_get(unit, mem, ment, MPLS_LABELf); 386 387 return BCM_E_NONE; 388 } 389 390 /* Convert data part of HW entry to application format. */ 391 STATIC int 392 _bcmi_xgs5_mpls_entry_get_data(int unit, mpls_entry_entry_t *ment, 393 bcm_mpls_tunnel_switch_t *info) 394 { 395 int rv, nh_index, vrf; 396 int action_if_bos, action_if_not_bos; 397 bcm_if_t egress_if=0; 398 int mode = 0; 399 soc_mem_t mem = MPLS_ENTRYm; 400 #ifdef BCM_MONTEREY_SUPPORT 401 uint32 roe_type = 0; 402 uint32 bit_num = 0; 403 #endif 404 405 if (soc_feature(unit, soc_feature_th3_style_simple_mpls)) { 406 mem = MPLS_ENTRY_SINGLEm; 407 } 408 409 BCM_IF_ERROR_RETURN(bcm_xgs3_l3_ingress_mode_get(unit, &mode)); 410 action_if_bos = soc_mem_field32_get(unit, mem, ment, MPLS_ACTION_IF_BOSf); 411 action_if_not_bos = soc_mem_field32_get(unit, mem, ment, 412 MPLS_ACTION_IF_NOT_BOSf); 413 414 if (action_if_bos == _BCM_MPLS_XGS5_MPLS_ACTION_IF_BOS_L3_IIF || 415 action_if_not_bos == _BCM_MPLS_XGS5_MPLS_ACTION_IF_NOT_BOS_POP) { 416 if (!mode) { 417 _bcm_l3_ingress_intf_t iif; 418 #ifdef BCM_TOMAHAWK_SUPPORT 419 int tunnel_term_ecn_map_id; 420 #endif 421 vrf = soc_mem_field32_get(unit, mem, ment, L3_IIFf); 422 /* 423 * If the ingress mode is not set, then L3_IIF is added 424 * above the intreface of _BCM_TR_MPLS_L3_IIF_BASE. 425 * If this is 0 then 0 vpn index was set. 426 */ 427 if (vrf != 0) { 428 iif.intf_id = vrf; 429 vrf -= _BCM_TR_MPLS_L3_IIF_BASE; 430 _BCM_MPLS_VPN_SET(info->vpn, _BCM_MPLS_VPN_TYPE_L3, vrf); 431 rv = _bcm_tr_l3_ingress_interface_get(unit, NULL, &iif); 432 BCM_IF_ERROR_RETURN(rv); 433 #ifdef BCM_TOMAHAWK_SUPPORT 434 if (soc_feature(unit, soc_feature_mpls_ecn)) { 435 tunnel_term_ecn_map_id = iif.tunnel_term_ecn_map_id; 436 if (bcmi_xgs5_ecn_map_used_get(unit, tunnel_term_ecn_map_id, 437 _bcmEcnmapTypeTunnelTerm)) { 438 info->tunnel_term_ecn_map_id = tunnel_term_ecn_map_id | 439 _BCM_XGS5_ECN_MAP_TYPE_TUNNEL_TERM; 440 info->flags |= BCM_MPLS_SWITCH_TUNNEL_TERM_ECN_MAP; 441 } 442 } 443 #endif 444 } 445 } else { 446 info->ingress_if = soc_mem_field32_get(unit, mem, ment, L3_IIFf); 447 } 448 } 449 450 if (action_if_bos == _BCM_MPLS_XGS5_MPLS_ACTION_IF_BOS_SWAP_NHI || 451 action_if_not_bos == _BCM_MPLS_XGS5_MPLS_ACTION_IF_NOT_BOS_SWAP_NHI) { 452 nh_index = soc_mem_field32_get(unit, mem, ment, 453 NEXT_HOP_INDEXf); 454 rv = bcm_tr_mpls_get_vp_nh (unit, nh_index,&egress_if); 455 if (rv == BCM_E_NONE) { 456 rv = bcm_tr_mpls_l3_nh_info_get(unit, info, nh_index); 457 } else 458 #ifdef BCM_TOMAHAWK3_SUPPORT 459 if (soc_feature(unit, soc_feature_th3_style_simple_mpls)) { 460 rv = bcm_th3_mpls_l3_nh_info_get(unit, info, nh_index); 461 } else 462 #endif 463 { 464 info->egress_if = nh_index + BCM_XGS3_EGRESS_IDX_MIN(unit); 465 info->egress_label.label = BCM_MPLS_LABEL_INVALID; 466 rv = BCM_E_NONE; 467 } 468 BCM_IF_ERROR_RETURN(rv); 469 } 470 471 if (action_if_bos == _BCM_MPLS_XGS5_MPLS_ACTION_IF_BOS_L3_NHI || 472 action_if_bos == _BCM_MPLS_XGS5_MPLS_ACTION_IF_BOS_ROE_NHI || 473 action_if_not_bos == _BCM_MPLS_XGS5_MPLS_ACTION_IF_NOT_BOS_PHP_NHI) { 474 info->action = BCM_MPLS_SWITCH_ACTION_PHP; 475 nh_index = soc_mem_field32_get(unit, mem, ment, 476 NEXT_HOP_INDEXf); 477 info->egress_if = nh_index + BCM_XGS3_EGRESS_IDX_MIN(unit); 478 } 479 480 if (action_if_bos == _BCM_MPLS_XGS5_MPLS_ACTION_IF_BOS_L3_ECMP || 481 action_if_not_bos == _BCM_MPLS_XGS5_MPLS_ACTION_IF_NOT_BOS_PHP_ECMP || 482 action_if_bos == _BCM_MPLS_XGS5_MPLS_ACTION_IF_BOS_SWAP_ECMP || 483 action_if_not_bos == _BCM_MPLS_XGS5_MPLS_ACTION_IF_NOT_BOS_SWAP_ECMP) { 484 info->action = BCM_MPLS_SWITCH_ACTION_SWAP; 485 nh_index = soc_mem_field32_get(unit, mem, ment, 486 ECMP_PTRf); 487 info->egress_if = nh_index + BCM_XGS3_MPATH_EGRESS_IDX_MIN(unit); 488 } 489 490 491 switch(action_if_bos) { 492 case _BCM_MPLS_XGS5_MPLS_ACTION_IF_BOS_L3_IIF: 493 info->action_if_bos = BCM_MPLS_SWITCH_ACTION_POP; 494 break; 495 case _BCM_MPLS_XGS5_MPLS_ACTION_IF_BOS_SWAP_NHI: 496 case _BCM_MPLS_XGS5_MPLS_ACTION_IF_BOS_SWAP_ECMP: 497 info->action_if_bos = BCM_MPLS_SWITCH_ACTION_SWAP; 498 break; 499 case _BCM_MPLS_XGS5_MPLS_ACTION_IF_BOS_L3_NHI: 500 case _BCM_MPLS_XGS5_MPLS_ACTION_IF_BOS_ROE_NHI: 501 case _BCM_MPLS_XGS5_MPLS_ACTION_IF_BOS_L3_ECMP: 502 info->action_if_bos = BCM_MPLS_SWITCH_ACTION_PHP; 503 break; 504 case _BCM_MPLS_XGS5_MPLS_ACTION_IF_BOS_INVALID: 505 info->action_if_bos = BCM_MPLS_SWITCH_ACTION_INVALID; 506 break; 507 default: 508 return BCM_E_INTERNAL; 509 break; 510 } 511 512 switch(action_if_not_bos) { 513 case _BCM_MPLS_XGS5_MPLS_ACTION_IF_NOT_BOS_POP: 514 info->action_if_not_bos = BCM_MPLS_SWITCH_ACTION_POP; 515 break; 516 case _BCM_MPLS_XGS5_MPLS_ACTION_IF_NOT_BOS_SWAP_NHI: 517 case _BCM_MPLS_XGS5_MPLS_ACTION_IF_NOT_BOS_SWAP_ECMP: 518 info->action_if_not_bos = BCM_MPLS_SWITCH_ACTION_SWAP; 519 break; 520 case _BCM_MPLS_XGS5_MPLS_ACTION_IF_NOT_BOS_PHP_NHI: 521 case _BCM_MPLS_XGS5_MPLS_ACTION_IF_NOT_BOS_PHP_ECMP: 522 info->action_if_not_bos = BCM_MPLS_SWITCH_ACTION_PHP; 523 break; 524 case _BCM_MPLS_XGS5_MPLS_ACTION_IF_NOT_BOS_INVALID: 525 info->action_if_not_bos = BCM_MPLS_SWITCH_ACTION_INVALID; 526 break; 527 default: 528 return BCM_E_INTERNAL; 529 break; 530 } 531 532 if (info->action_if_bos == info->action_if_not_bos) { 533 info->action = info->action_if_bos; 534 if (info->action == BCM_MPLS_SWITCH_ACTION_INVALID) { 535 /* Both actions are invalid in the HW entry 536 * Error out. 537 */ 538 return BCM_E_INTERNAL; 539 } 540 } else { 541 info->action = BCM_MPLS_SWITCH_ACTION_INVALID; 542 } 543 544 if (SOC_MEM_FIELD_VALID(unit, mem, PW_TERM_NUM_VALIDf) && 545 soc_mem_field32_get(unit, mem, ment, PW_TERM_NUM_VALIDf)) { 546 info->flags |= BCM_MPLS_SWITCH_COUNTED; 547 } 548 549 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 550 else if (SOC_MEM_FIELD_VALID(unit, MPLS_ENTRYm, CLASS_IDf)) { 551 info->class_id = soc_mem_field32_get(unit, mem, ment, CLASS_IDf); 552 #if defined(BCM_MONTEREY_SUPPORT) 553 if (soc_feature(unit,soc_feature_mont_roe_classid_sw_war)) { 554 if ((bit_num = soc_mem_field_length(unit, mem, CLASS_IDf)) > 0) { 555 bit_num -= 1; 556 info->class_id = info->class_id & (( 1 << bit_num ) - 1); 557 } 558 } 559 #endif 560 } 561 #endif 562 563 #ifdef BCM_MONTEREY_SUPPORT 564 if (SOC_MEM_FIELD_VALID(unit, MPLS_ENTRYm, ROE_TYPEf)) { 565 roe_type = soc_MPLS_ENTRYm_field32_get(unit, ment, ROE_TYPEf); 566 if (roe_type == _BCM_MPLS_XGS5_MPLS_ROE_TUNNEL) { 567 info->flags2 |= BCM_MPLS_SWITCH2_ENABLE_ROE; 568 } else if (roe_type == _BCM_MPLS_XGS5_MPLS_ROE_CUSTOM_TUNNEL) { 569 info->flags2 |= BCM_MPLS_SWITCH2_ENABLE_ROE_CUSTOM; 570 } else { 571 /* Do nothing */ 572 } 573 } 574 #endif 575 576 if (!soc_mem_field32_get(unit, mem, ment, DECAP_USE_TTLf)) { 577 info->flags |= BCM_MPLS_SWITCH_INNER_TTL; 578 } 579 if (soc_mem_field32_get(unit, mem, ment, DECAP_USE_EXP_FOR_INNERf)) { 580 if ((info->action_if_bos == BCM_MPLS_SWITCH_ACTION_PHP) || 581 (info->action_if_bos == BCM_MPLS_SWITCH_ACTION_POP) || 582 (info->action_if_not_bos == BCM_MPLS_SWITCH_ACTION_PHP) || 583 (info->action_if_not_bos == BCM_MPLS_SWITCH_ACTION_POP)) { 584 info->flags |= BCM_MPLS_SWITCH_INNER_EXP; 585 } 586 } 587 if (soc_mem_field32_get(unit, mem, ment, 588 DECAP_USE_EXP_FOR_PRIf) == 0x1) { 589 590 /* Use specified EXP-map to determine internal prio/color */ 591 info->flags |= BCM_MPLS_SWITCH_INT_PRI_MAP; 592 info->exp_map = 593 soc_mem_field32_get(unit, mem, ment, EXP_MAPPING_PTRf); 594 info->exp_map |= _BCM_TR_MPLS_EXP_MAP_TABLE_TYPE_INGRESS; 595 } else if (soc_mem_field32_get(unit, mem, ment, 596 DECAP_USE_EXP_FOR_PRIf) == 0x2) { 597 598 /* Use the specified internal priority value */ 599 info->flags |= BCM_MPLS_SWITCH_INT_PRI_SET; 600 info->int_pri = 601 soc_mem_field32_get(unit, mem, ment, NEW_PRIf); 602 603 /* Use specified EXP-map to determine internal color */ 604 info->flags |= BCM_MPLS_SWITCH_COLOR_MAP; 605 info->exp_map = 606 soc_mem_field32_get(unit, mem, ment, EXP_MAPPING_PTRf); 607 info->exp_map |= _BCM_TR_MPLS_EXP_MAP_TABLE_TYPE_INGRESS; 608 } 609 if (SOC_MEM_FIELD_VALID(unit,mem, 610 DO_NOT_CHANGE_PAYLOAD_DSCPf)) { 611 if (soc_mem_field32_get(unit, mem, ment, 612 DO_NOT_CHANGE_PAYLOAD_DSCPf) == 0) { 613 if ((info->action_if_bos == BCM_MPLS_SWITCH_ACTION_PHP) || 614 (info->action_if_bos == BCM_MPLS_SWITCH_ACTION_POP) || 615 (info->action_if_not_bos == BCM_MPLS_SWITCH_ACTION_PHP) || 616 (info->action_if_not_bos == BCM_MPLS_SWITCH_ACTION_POP)) { 617 info->flags |= 618 (BCM_MPLS_SWITCH_OUTER_EXP | BCM_MPLS_SWITCH_OUTER_TTL); 619 } 620 } 621 } 622 #if defined(BCM_TOMAHAWK2_SUPPORT) 623 if (soc_feature(unit, soc_feature_mpls_ecn)) { 624 int ecn_map_id; 625 int ecn_map_hw_idx; 626 int rv; 627 ecn_map_hw_idx = soc_mem_field32_get(unit, mem, ment, 628 EXP_TO_IP_ECN_MAPPING_PTRf); 629 rv = bcmi_ecn_map_hw_idx2id(unit, ecn_map_hw_idx, 630 _BCM_XGS5_MPLS_ECN_MAP_TYPE_EXP2ECN, 631 &ecn_map_id); 632 if (BCM_SUCCESS(rv)) { 633 info->flags |= BCM_MPLS_SWITCH_INGRESS_ECN_MAP; 634 info->ecn_map_id = ecn_map_id; 635 } 636 } 637 #endif /* BCM_TOMAHAWK2_SUPPORT */ 638 #if defined(BCM_TRIDENT2PLUS_SUPPORT) || defined(BCM_TOMAHAWK2_SUPPORT) 639 if (soc_feature(unit, soc_feature_td2p_mpls_linear_protection) || 640 SOC_IS_TOMAHAWK2(unit)) { 641 642 if (soc_mem_field32_get(unit, mem, ment, 643 MPLS__DROP_DATA_ENABLEf)) { 644 info->flags |= BCM_MPLS_SWITCH_DROP; 645 } 646 info->failover_id = 647 soc_mem_field32_get(unit, mem, ment, 648 MPLS__RX_PROT_GROUPf); 649 if (info->failover_id != 0) { 650 _BCM_ENCAP_TYPE_IN_FAILOVER_ID(info->failover_id, 651 _BCM_FAILOVER_INGRESS); 652 } 653 } 654 #endif /*BCM_TRIDENT2PLUS_SUPPORT || BCM_TOMAHAWK2_SUPPORT */ 655 return BCM_E_NONE; 656 } 657 658 /* 659 * Function: 660 * bcm_td3_mpls_l3_nh_info_get 661 * Purpose: 662 * Get Tunnel_switch info for a specific EGR_NH Index 663 * Parameters: 664 * unit - unit 665 * info - Tunnel switch info 666 * nh_index - next hop index 667 * Returns: 668 * BCM_E_XXX 669 */ 670 STATIC int 671 bcm_td3_mpls_l3_nh_info_get(int unit, bcm_mpls_tunnel_switch_t *info, int nh_index) 672 { 673 int vc_swap_idx = 0; 674 int vc_data_type = 0; 675 int pri_cfi_sel = 0; 676 int mapping_ptr = 0; 677 uint32 mpls_format[2]; 678 egr_l3_next_hop_entry_t egr_nh; 679 egr_mpls_vc_and_swap_label_table_entry_t vc_entry; 680 681 SOC_IF_ERROR_RETURN(soc_mem_read(unit, 682 EGR_L3_NEXT_HOPm, MEM_BLOCK_ANY, nh_index, &egr_nh)); 683 vc_swap_idx = soc_EGR_L3_NEXT_HOPm_field32_get( 684 unit, &egr_nh, MPLS__VC_AND_SWAP_INDEXf); 685 SOC_IF_ERROR_RETURN(soc_mem_read(unit, 686 EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 687 MEM_BLOCK_ANY, vc_swap_idx, &vc_entry)); 688 vc_data_type = soc_mem_field32_get(unit, 689 EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 690 &vc_entry, DATA_TYPEf); 691 692 if (vc_data_type == _BCM_VC_SWAP_TBL_FLEX_DATA_TYPE) { 693 sal_memset(mpls_format, 0, sizeof(mpls_format)); 694 soc_mem_field_get(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 695 (uint32*)&vc_entry, 696 MPLS_PHP__MPLS_ENTRY_0_ACTION_SETf, 697 (uint32*)mpls_format); 698 pri_cfi_sel = soc_format_field32_get(unit, 699 MPLS_ENTRY_ACTION_SETfmt, 700 (uint32*)mpls_format, PRI_CFI_SELf); 701 mapping_ptr = soc_format_field32_get(unit, 702 MPLS_ENTRY_ACTION_SETfmt, 703 (uint32*)mpls_format, DOT1P_MAPPING_PTRf); 704 705 if (pri_cfi_sel == 1) { 706 info->flags2 |= BCM_MPLS_SWITCH2_VLAN_PRI_PHB_REMARK; 707 BCM_IF_ERROR_RETURN( 708 _bcm_tr2_qos_idx2id(unit, mapping_ptr, 709 _BCM_QOS_MAP_TYPE_EGR_MPLS_MAPS, &info->qos_map_id)); 710 } else if (pri_cfi_sel == 0 && mapping_ptr > 0) { 711 info->flags2 |= BCM_MPLS_SWITCH2_VLAN_PRI_SET; 712 info->pkt_cfi = mapping_ptr & 1; 713 info->pkt_pri = (mapping_ptr >> 1) & 0x7; 714 } 715 } 716 717 return BCM_E_NONE; 718 } 719 720 STATIC int 721 bcmi_td3_mpls_entry_get_data(int unit, mpls_entry_entry_t *ment, 722 bcm_mpls_tunnel_switch_t *info) 723 { 724 int rv = BCM_E_NONE, nh_index, vrf; 725 int action_if_bos, action_if_not_bos; 726 bcm_if_t egress_if=0; 727 int mode = 0; 728 uint32 dest_type; 729 uint32 value = 0; 730 soc_mem_t mem = MPLS_ENTRYm; 731 732 BCM_IF_ERROR_RETURN(bcm_xgs3_l3_ingress_mode_get(unit, &mode)); 733 action_if_bos = soc_mem_field32_get(unit, mem, ment, MPLS_ACTION_IF_BOSf); 734 action_if_not_bos = soc_mem_field32_get(unit, mem, ment, 735 MPLS_ACTION_IF_NOT_BOSf); 736 737 if (action_if_bos == _BCM_MPLS_TD3_MPLS_ACTION_POP_SVP_ENTROPY) { 738 739 } 740 741 /*POP OR L3_IIF*/ 742 if (action_if_bos == _BCM_MPLS_TD3_MPLS_ACTION_L3_IIF || 743 action_if_not_bos == _BCM_MPLS_TD3_MPLS_ACTION_POP) { 744 if (!mode) { 745 _bcm_l3_ingress_intf_t iif; 746 #ifdef BCM_TOMAHAWK_SUPPORT 747 int tunnel_term_ecn_map_id; 748 #endif 749 vrf = soc_mem_field32_get(unit, mem, ment, L3_IIFf); 750 iif.intf_id = vrf; 751 vrf -= _BCM_TR_MPLS_L3_IIF_BASE; 752 _BCM_MPLS_VPN_SET(info->vpn, _BCM_MPLS_VPN_TYPE_L3, vrf); 753 rv = _bcm_tr_l3_ingress_interface_get(unit, NULL, &iif); 754 BCM_IF_ERROR_RETURN(rv); 755 #ifdef BCM_TOMAHAWK_SUPPORT 756 if (soc_feature(unit, soc_feature_mpls_ecn)) { 757 tunnel_term_ecn_map_id = iif.tunnel_term_ecn_map_id; 758 if (bcmi_xgs5_ecn_map_used_get(unit, tunnel_term_ecn_map_id, 759 _bcmEcnmapTypeTunnelTerm)) { 760 info->tunnel_term_ecn_map_id = tunnel_term_ecn_map_id | 761 _BCM_XGS5_ECN_MAP_TYPE_TUNNEL_TERM; 762 info->flags |= BCM_MPLS_SWITCH_TUNNEL_TERM_ECN_MAP; 763 } 764 } 765 #endif 766 } else { 767 info->ingress_if = soc_mem_field32_get(unit, mem, ment, L3_IIFf); 768 } 769 } 770 771 if (action_if_bos == _BCM_MPLS_TD3_MPLS_ACTION_SWAP || 772 action_if_not_bos == _BCM_MPLS_TD3_MPLS_ACTION_SWAP) { 773 value = soc_mem_field32_dest_get(unit, MPLS_ENTRYm, ment, 774 DESTINATIONf, &dest_type); 775 776 if (dest_type == SOC_MEM_FIF_DEST_NEXTHOP) { 777 nh_index = value; 778 779 rv = bcm_tr_mpls_get_vp_nh (unit, nh_index,&egress_if); 780 if (rv == BCM_E_NONE) { 781 rv = bcm_tr_mpls_l3_nh_info_get(unit, info, nh_index); 782 } else { 783 info->egress_if = nh_index + BCM_XGS3_EGRESS_IDX_MIN(unit); 784 info->egress_label.label = BCM_MPLS_LABEL_INVALID; 785 rv = BCM_E_NONE; 786 } 787 } 788 BCM_IF_ERROR_RETURN(rv); 789 } 790 791 if (action_if_bos == _BCM_MPLS_TD3_MPLS_ACTION_PHP || 792 action_if_not_bos == _BCM_MPLS_TD3_MPLS_ACTION_PHP) { 793 info->action = BCM_MPLS_SWITCH_ACTION_PHP; 794 value = soc_mem_field32_dest_get(unit, MPLS_ENTRYm, ment, 795 DESTINATIONf, &dest_type); 796 797 if (dest_type == SOC_MEM_FIF_DEST_NEXTHOP) { 798 nh_index = value; 799 info->egress_if = nh_index + BCM_XGS3_EGRESS_IDX_MIN(unit); 800 BCM_IF_ERROR_RETURN( 801 bcm_td3_mpls_l3_nh_info_get(unit, info, nh_index)); 802 } 803 } 804 805 if (action_if_bos == _BCM_MPLS_TD3_MPLS_ACTION_PHP || 806 action_if_not_bos == _BCM_MPLS_TD3_MPLS_ACTION_PHP || 807 action_if_bos == _BCM_MPLS_TD3_MPLS_ACTION_SWAP || 808 action_if_not_bos == _BCM_MPLS_TD3_MPLS_ACTION_SWAP) { 809 info->action = BCM_MPLS_SWITCH_ACTION_SWAP; 810 value = soc_mem_field32_dest_get(unit, MPLS_ENTRYm, ment, 811 DESTINATIONf, &dest_type); 812 813 if (dest_type == SOC_MEM_FIF_DEST_ECMP) { 814 nh_index = value; 815 info->egress_if = nh_index + BCM_XGS3_MPATH_EGRESS_IDX_MIN(unit); 816 } 817 } 818 819 switch(action_if_bos) { 820 case _BCM_MPLS_TD3_MPLS_ACTION_L3_IIF: 821 info->action_if_bos = BCM_MPLS_SWITCH_ACTION_POP; 822 break; 823 case _BCM_MPLS_TD3_MPLS_ACTION_SWAP: 824 info->action_if_bos = BCM_MPLS_SWITCH_ACTION_SWAP; 825 break; 826 case _BCM_MPLS_TD3_MPLS_ACTION_PHP: 827 info->action_if_bos = BCM_MPLS_SWITCH_ACTION_PHP; 828 break; 829 case _BCM_MPLS_TD3_MPLS_ACTION_INVALID: 830 info->action_if_bos = BCM_MPLS_SWITCH_ACTION_INVALID; 831 break; 832 default: 833 return BCM_E_INTERNAL; 834 break; 835 } 836 837 switch(action_if_not_bos) { 838 case _BCM_MPLS_TD3_MPLS_ACTION_POP: 839 info->action_if_not_bos = BCM_MPLS_SWITCH_ACTION_POP; 840 break; 841 case _BCM_MPLS_TD3_MPLS_ACTION_SWAP: 842 info->action_if_not_bos = BCM_MPLS_SWITCH_ACTION_SWAP; 843 break; 844 case _BCM_MPLS_TD3_MPLS_ACTION_PHP: 845 info->action_if_not_bos = BCM_MPLS_SWITCH_ACTION_PHP; 846 break; 847 case _BCM_MPLS_TD3_MPLS_ACTION_INVALID: 848 info->action_if_not_bos = BCM_MPLS_SWITCH_ACTION_INVALID; 849 break; 850 default: 851 return BCM_E_INTERNAL; 852 break; 853 } 854 855 if (info->action_if_bos == info->action_if_not_bos) { 856 info->action = info->action_if_bos; 857 if (info->action == BCM_MPLS_SWITCH_ACTION_INVALID) { 858 /* Both actions are invalid in the HW entry 859 * Error out. 860 */ 861 return BCM_E_INTERNAL; 862 } 863 } else { 864 info->action = BCM_MPLS_SWITCH_ACTION_INVALID; 865 } 866 867 if (soc_mem_field32_get(unit, mem, ment, PW_TERM_NUM_VALIDf)) { 868 info->flags |= BCM_MPLS_SWITCH_COUNTED; 869 } 870 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 871 else if (SOC_MEM_FIELD_VALID(unit, MPLS_ENTRYm, CLASS_IDf)) { 872 info->class_id = soc_mem_field32_get(unit, mem, ment, CLASS_IDf); 873 } 874 #endif 875 876 if (!soc_mem_field32_get(unit, mem, ment, DECAP_USE_TTLf)) { 877 info->flags |= BCM_MPLS_SWITCH_INNER_TTL; 878 } 879 if (soc_mem_field32_get(unit, mem, ment, DECAP_USE_EXP_FOR_INNERf)) { 880 if ((info->action_if_bos == BCM_MPLS_SWITCH_ACTION_PHP) || 881 (info->action_if_bos == BCM_MPLS_SWITCH_ACTION_POP) || 882 (info->action_if_not_bos == BCM_MPLS_SWITCH_ACTION_PHP) || 883 (info->action_if_not_bos == BCM_MPLS_SWITCH_ACTION_POP)) { 884 info->flags |= BCM_MPLS_SWITCH_INNER_EXP; 885 } 886 } 887 if (soc_mem_field32_get(unit, mem, ment, 888 DECAP_USE_EXP_FOR_PRIf) == 0x1) { 889 890 /* Use specified EXP-map to determine internal prio/color */ 891 info->flags |= BCM_MPLS_SWITCH_INT_PRI_MAP; 892 info->exp_map = 893 soc_mem_field32_get(unit, mem, ment, EXP_MAPPING_PTRf); 894 info->exp_map |= _BCM_TR_MPLS_EXP_MAP_TABLE_TYPE_INGRESS; 895 } else if (soc_mem_field32_get(unit, mem, ment, 896 DECAP_USE_EXP_FOR_PRIf) == 0x2) { 897 898 /* Use the specified internal priority value */ 899 info->flags |= BCM_MPLS_SWITCH_INT_PRI_SET; 900 info->int_pri = 901 soc_mem_field32_get(unit, mem, ment, NEW_PRIf); 902 903 /* Use specified EXP-map to determine internal color */ 904 info->flags |= BCM_MPLS_SWITCH_COLOR_MAP; 905 info->exp_map = 906 soc_mem_field32_get(unit, mem, ment, EXP_MAPPING_PTRf); 907 info->exp_map |= _BCM_TR_MPLS_EXP_MAP_TABLE_TYPE_INGRESS; 908 } 909 if (SOC_MEM_FIELD_VALID(unit,MPLS_ENTRYm, 910 DO_NOT_CHANGE_PAYLOAD_DSCPf)) { 911 if (soc_mem_field32_get(unit, mem, ment, 912 DO_NOT_CHANGE_PAYLOAD_DSCPf) == 0) { 913 if ((info->action_if_bos == BCM_MPLS_SWITCH_ACTION_PHP) || 914 (info->action_if_bos == BCM_MPLS_SWITCH_ACTION_POP) || 915 (info->action_if_not_bos == BCM_MPLS_SWITCH_ACTION_PHP) || 916 (info->action_if_not_bos == BCM_MPLS_SWITCH_ACTION_POP)) { 917 info->flags |= 918 (BCM_MPLS_SWITCH_OUTER_EXP | BCM_MPLS_SWITCH_OUTER_TTL); 919 } 920 } 921 } 922 923 #if defined(BCM_TOMAHAWK2_SUPPORT) || defined(BCM_TRIDENT3_SUPPORT) 924 if (soc_feature(unit, soc_feature_mpls_ecn)) { 925 int ecn_map_id; 926 int ecn_map_hw_idx = 0; 927 int rv; 928 929 if(soc_feature(unit, soc_feature_td3_style_mpls)) { 930 ecn_map_hw_idx = soc_MPLS_ENTRYm_field32_get(unit, ment, 931 EXP_TO_ECN_MAPPING_PTRf); 932 } 933 934 rv = bcmi_ecn_map_hw_idx2id(unit, ecn_map_hw_idx, 935 _BCM_XGS5_MPLS_ECN_MAP_TYPE_EXP2ECN, 936 &ecn_map_id); 937 if (BCM_SUCCESS(rv)) { 938 info->flags |= BCM_MPLS_SWITCH_INGRESS_ECN_MAP; 939 info->ecn_map_id = ecn_map_id; 940 } 941 } 942 #endif 943 return rv; 944 } 945 946 /* Convert key part of application format to HW entry. */ 947 STATIC int 948 _bcmi_xgs5_mpls_entry_set_key(int unit, bcm_mpls_tunnel_switch_t *info, 949 mpls_entry_entry_t *ment) 950 { 951 bcm_module_t mod_out; 952 bcm_port_t port_out; 953 bcm_trunk_t trunk_id; 954 int rv, gport_id; 955 soc_mem_t mem = MPLS_ENTRYm; 956 soc_field_t validf = VALIDf; 957 958 if (soc_feature(unit, soc_feature_th3_style_simple_mpls)) { 959 mem = MPLS_ENTRY_SINGLEm; 960 validf = BASE_VALIDf; 961 } 962 963 sal_memset(ment, 0, sizeof(mpls_entry_entry_t)); 964 965 if (info->port == BCM_GPORT_INVALID) { 966 /* Global label, mod/port not part of lookup key */ 967 if (SOC_MEM_FIELD_VALID(unit, mem, MODULE_IDf)) { 968 soc_mem_field32_set(unit, mem, ment, MODULE_IDf, 0); 969 } 970 soc_mem_field32_set(unit, mem, ment, PORT_NUMf, 0); 971 if (BCM_XGS3_L3_MPLS_LBL_VALID(info->label)) { 972 soc_mem_field32_set(unit, mem, ment, MPLS_LABELf, info->label); 973 } else { 974 return BCM_E_PARAM; 975 } 976 977 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 978 soc_mem_field32_set(unit, mem, ment, BASE_VALID_0f, 3); 979 soc_mem_field32_set(unit, mem, ment, BASE_VALID_1f, 7); 980 } else if (SOC_MEM_FIELD_VALID(unit, mem, BASE_VALIDf)) { 981 soc_mem_field32_set(unit, mem, ment, BASE_VALIDf, 1); 982 } else { 983 soc_mem_field32_set(unit, mem, ment, validf, 1); 984 } 985 return BCM_E_NONE; 986 } 987 988 rv = _bcm_esw_gport_resolve(unit, info->port, &mod_out, 989 &port_out, &trunk_id, &gport_id); 990 BCM_IF_ERROR_RETURN(rv); 991 992 if (BCM_GPORT_IS_TRUNK(info->port)) { 993 soc_mem_field32_set(unit, mem, ment, Tf, 1); 994 soc_mem_field32_set(unit, mem, ment, TGIDf, trunk_id); 995 } else { 996 if (SOC_MEM_FIELD_VALID(unit, mem, MODULE_IDf)) { 997 soc_mem_field32_set(unit, mem, ment, MODULE_IDf, mod_out); 998 } 999 soc_mem_field32_set(unit, mem, ment, PORT_NUMf, port_out); 1000 } 1001 if (BCM_XGS3_L3_MPLS_LBL_VALID(info->label)) { 1002 soc_mem_field32_set(unit, mem, ment, MPLS_LABELf, info->label); 1003 } else { 1004 return BCM_E_PARAM; 1005 } 1006 1007 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 1008 soc_mem_field32_set(unit, mem, ment, BASE_VALID_0f, 3); 1009 soc_mem_field32_set(unit, mem, ment, BASE_VALID_1f, 7); 1010 } else if (SOC_MEM_FIELD_VALID(unit, mem, BASE_VALIDf)){ 1011 soc_mem_field32_set(unit, mem, ment, BASE_VALIDf, 1); 1012 } else { 1013 soc_mem_field32_set(unit, mem, ment, validf, 1); 1014 } 1015 1016 return BCM_E_NONE; 1017 } 1018 1019 #if defined(BCM_TRIDENT3_SUPPORT) 1020 STATIC int 1021 bcmi_td3_php_ecmp_nhop_vcswap_add(int unit,bcm_mpls_tunnel_switch_t *php_info, 1022 int nh_index, int mpath_flag) 1023 { 1024 int i = 0, ecmp_member_count = 0; 1025 int alloc_size, index; 1026 bcm_l3_egress_ecmp_t ecmp_info; 1027 bcm_l3_ecmp_member_t *ecmp_member_array = NULL; 1028 int rv = BCM_E_NONE; 1029 1030 if (mpath_flag & BCM_L3_MULTIPATH) { 1031 1032 alloc_size = sizeof(bcm_l3_ecmp_member_t) * BCM_XGS3_L3_ECMP_MAX(unit); 1033 ecmp_member_array = sal_alloc(alloc_size, "ecmp member array"); 1034 if (NULL == ecmp_member_array) { 1035 return BCM_E_MEMORY; 1036 } 1037 sal_memset(ecmp_member_array, 0, alloc_size); 1038 1039 ecmp_info.ecmp_intf = nh_index + BCM_XGS3_MPATH_EGRESS_IDX_MIN(unit); 1040 rv = bcm_xgs3_l3_ecmp_get(unit, &ecmp_info, BCM_XGS3_L3_ECMP_MAX(unit), 1041 ecmp_member_array, &ecmp_member_count); 1042 if (BCM_FAILURE(rv)) { 1043 goto clean_up; 1044 } 1045 1046 while (i < ecmp_member_count) { 1047 if (BCM_XGS3_L3_EGRESS_IDX_VALID(unit, 1048 ecmp_member_array[i].egress_if)) { 1049 index = (ecmp_member_array[i].egress_if - 1050 BCM_XGS3_EGRESS_IDX_MIN(unit)); 1051 } else { 1052 index = (ecmp_member_array[i].egress_if - 1053 BCM_XGS3_DVP_EGRESS_IDX_MIN(unit)); 1054 } 1055 1056 rv = bcmi_td3_mpls_php_vcswap_info_add(unit, php_info, &index); 1057 if (BCM_FAILURE(rv)) { 1058 goto clean_up; 1059 } 1060 i++; 1061 } 1062 } 1063 1064 clean_up: 1065 if (ecmp_member_array) { 1066 sal_free(ecmp_member_array); 1067 ecmp_member_array = NULL; 1068 } 1069 1070 return rv; 1071 } 1072 1073 STATIC int 1074 bcmi_td3_php_ecmp_nhop_vcswap_delete(int unit, int nh_index, int dest_type, int mpath_flag) 1075 { 1076 int i = 0, ecmp_member_count = 0; 1077 int alloc_size, index; 1078 bcm_l3_egress_ecmp_t ecmp_info; 1079 bcm_l3_ecmp_member_t *ecmp_member_array = NULL; 1080 int rv = BCM_E_NONE; 1081 1082 if (mpath_flag & BCM_L3_MULTIPATH) { 1083 1084 alloc_size = sizeof(bcm_l3_ecmp_member_t) * BCM_XGS3_L3_ECMP_MAX(unit); 1085 ecmp_member_array = sal_alloc(alloc_size, "ecmp member array"); 1086 if (NULL == ecmp_member_array) { 1087 return BCM_E_MEMORY; 1088 } 1089 sal_memset(ecmp_member_array, 0, alloc_size); 1090 1091 ecmp_info.ecmp_intf = nh_index + BCM_XGS3_MPATH_EGRESS_IDX_MIN(unit); 1092 rv = bcm_xgs3_l3_ecmp_get(unit, &ecmp_info, BCM_XGS3_L3_ECMP_MAX(unit), 1093 ecmp_member_array, &ecmp_member_count); 1094 if (BCM_FAILURE(rv)) { 1095 goto clean_up; 1096 } 1097 1098 while (i < ecmp_member_count) { 1099 if (BCM_XGS3_L3_EGRESS_IDX_VALID(unit, 1100 ecmp_member_array[i].egress_if)) { 1101 index = (ecmp_member_array[i].egress_if - 1102 BCM_XGS3_EGRESS_IDX_MIN(unit)); 1103 } else { 1104 index = (ecmp_member_array[i].egress_if - 1105 BCM_XGS3_DVP_EGRESS_IDX_MIN(unit)); 1106 } 1107 1108 rv = bcmi_td3_mpls_php_vcswap_info_delete(unit, index, dest_type); 1109 if (BCM_FAILURE(rv)) { 1110 goto clean_up; 1111 } 1112 i++; 1113 } 1114 } 1115 1116 clean_up: 1117 if (ecmp_member_array) { 1118 sal_free(ecmp_member_array); 1119 ecmp_member_array = NULL; 1120 } 1121 1122 return rv; 1123 } 1124 #endif 1125 1126 STATIC int 1127 bcmi_xgs5_mpls_entry_label_actions_set(int unit, int action_if_bos, 1128 int action_if_not_bos, bcm_mpls_tunnel_switch_t *info, 1129 mpls_entry_entry_t *ment, int *nh_index, int *nh_index_alloc_failed) 1130 { 1131 int rv = BCM_E_NONE; 1132 int mode,vrf=0; 1133 uint32 mpath_flag=0; 1134 soc_mem_t mem = MPLS_ENTRYm; 1135 #if defined(BCM_TRIDENT3_SUPPORT) 1136 uint32 cancun_ver; 1137 #endif 1138 1139 if (soc_feature(unit, soc_feature_th3_style_simple_mpls)) { 1140 mem = MPLS_ENTRY_SINGLEm; 1141 } 1142 1143 if ((ment == NULL) || (info == NULL)) { 1144 return BCM_E_INTERNAL; 1145 } 1146 1147 #if defined(BCM_TRIDENT3_SUPPORT) 1148 if (SOC_IS_TRIDENT3X(unit)) { 1149 SOC_IF_ERROR_RETURN(soc_cancun_version_get(unit, &cancun_ver)); 1150 } 1151 #endif 1152 1153 /*POP ACTION*/ 1154 if (BCM_MPLS_SWITCH_ACTION_POP == action_if_bos || 1155 BCM_MPLS_SWITCH_ACTION_POP == action_if_not_bos) { 1156 1157 /* uniform qos model if either of these two flags set. 1158 * Only apply to L3 MPLS and BOS 1159 */ 1160 if (info->flags & (BCM_MPLS_SWITCH_OUTER_EXP | 1161 BCM_MPLS_SWITCH_OUTER_TTL) ) { 1162 if (SOC_MEM_FIELD_VALID(unit,mem, 1163 DO_NOT_CHANGE_PAYLOAD_DSCPf)) { 1164 soc_mem_field32_set(unit, mem, ment, 1165 DO_NOT_CHANGE_PAYLOAD_DSCPf, 0); 1166 } 1167 } 1168 1169 mode = -1; 1170 if (_BCM_MPLS_VPN_IS_L3(info->vpn)) { 1171 _BCM_MPLS_VPN_GET(vrf, _BCM_MPLS_VPN_TYPE_L3, info->vpn); 1172 if (!_BCM_MPLS_VRF_USED_GET(unit, vrf)) { 1173 return BCM_E_PARAM; 1174 } 1175 1176 /* Check L3 Ingress Interface mode. */ 1177 mode = 0; 1178 rv = bcm_xgs3_l3_ingress_mode_get(unit, &mode); 1179 BCM_IF_ERROR_RETURN(rv); 1180 } 1181 if (!mode) { 1182 _bcm_l3_ingress_intf_t iif; 1183 sal_memset(&iif, 0, sizeof(_bcm_l3_ingress_intf_t)); 1184 iif.intf_id = _BCM_TR_MPLS_L3_IIF_BASE + vrf; 1185 rv = _bcm_tr_l3_ingress_interface_get(unit, NULL, &iif); 1186 BCM_IF_ERROR_RETURN(rv); 1187 1188 iif.vrf = vrf; 1189 #ifdef BCM_TOMAHAWK_SUPPORT 1190 if (soc_feature(unit, soc_feature_ecn_wred) && 1191 (info->flags & BCM_MPLS_SWITCH_TUNNEL_TERM_ECN_MAP)) { 1192 int ecn_map_index; 1193 int ecn_map_type; 1194 int ecn_map_num; 1195 ecn_map_type = info->tunnel_term_ecn_map_id & 1196 _BCM_XGS5_ECN_MAP_TYPE_MASK; 1197 ecn_map_index = info->tunnel_term_ecn_map_id & 1198 _BCM_XGS5_ECN_MAP_NUM_MASK; 1199 ecn_map_num = 1200 soc_mem_index_count(unit, ING_TUNNEL_ECN_DECAPm) / 1201 _BCM_ECN_MAX_ENTRIES_PER_TUNNEL_TERM_MAP; 1202 if (ecn_map_type != _BCM_XGS5_ECN_MAP_TYPE_TUNNEL_TERM) { 1203 return BCM_E_PARAM; 1204 } 1205 if (ecn_map_index >= ecn_map_num) { 1206 return BCM_E_PARAM; 1207 } 1208 if (!bcmi_xgs5_ecn_map_used_get(unit, ecn_map_index, 1209 _bcmEcnmapTypeTunnelTerm)) { 1210 return BCM_E_PARAM; 1211 } 1212 iif.tunnel_term_ecn_map_id = ecn_map_index; 1213 iif.flags |= BCM_L3_INGRESS_TUNNEL_TERM_ECN_MAP; 1214 } 1215 #endif 1216 1217 rv = _bcm_tr_l3_ingress_interface_set(unit, &iif, NULL, NULL); 1218 BCM_IF_ERROR_RETURN(rv); 1219 1220 soc_mem_field32_set(unit, mem, ment, L3_IIFf, 1221 _BCM_TR_MPLS_L3_IIF_BASE + vrf); 1222 } else { 1223 soc_mem_field32_set(unit, mem, ment, L3_IIFf, info->ingress_if); 1224 } 1225 1226 if (BCM_MPLS_SWITCH_ACTION_POP == action_if_not_bos) { 1227 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 1228 soc_mem_field32_set(unit, mem, ment, 1229 MPLS_ACTION_IF_NOT_BOSf, 1230 _BCM_MPLS_TD3_MPLS_ACTION_POP); 1231 } else { 1232 soc_mem_field32_set(unit, mem, ment, 1233 MPLS_ACTION_IF_NOT_BOSf, 1234 _BCM_MPLS_XGS5_MPLS_ACTION_IF_NOT_BOS_POP); 1235 } 1236 } 1237 1238 if (BCM_MPLS_SWITCH_ACTION_POP == action_if_bos) { 1239 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 1240 soc_mem_field32_set(unit, mem, ment, 1241 MPLS_ACTION_IF_BOSf, 1242 _BCM_MPLS_TD3_MPLS_ACTION_L3_IIF); 1243 } else { 1244 soc_mem_field32_set(unit, mem, ment, MPLS_ACTION_IF_BOSf, 1245 _BCM_MPLS_XGS5_MPLS_ACTION_IF_BOS_L3_IIF); 1246 } 1247 } 1248 }/*BCM_MPLS_SWITCH_ACTION_POP*/ 1249 1250 /*PHP ACTION*/ 1251 if (BCM_MPLS_SWITCH_ACTION_PHP == action_if_bos || 1252 BCM_MPLS_SWITCH_ACTION_PHP == action_if_not_bos) { 1253 1254 if (BCM_XGS3_L3_MPATH_EGRESS_IDX_VALID(unit, info->egress_if)) { 1255 if (BCM_MPLS_SWITCH_ACTION_PHP == action_if_bos) { 1256 1257 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 1258 soc_mem_field32_set(unit, mem, ment, MPLS_ACTION_IF_BOSf, 1259 _BCM_MPLS_TD3_MPLS_ACTION_PHP); 1260 } else { 1261 soc_mem_field32_set(unit, mem, ment, MPLS_ACTION_IF_BOSf, 1262 _BCM_MPLS_XGS5_MPLS_ACTION_IF_BOS_L3_ECMP); 1263 } 1264 1265 } 1266 1267 if (BCM_MPLS_SWITCH_ACTION_PHP == action_if_not_bos) { 1268 if (soc_feature(unit, soc_feature_mpls_lsr_ecmp)) { 1269 1270 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 1271 soc_mem_field32_set(unit, mem, ment, MPLS_ACTION_IF_NOT_BOSf, 1272 _BCM_MPLS_TD3_MPLS_ACTION_PHP); 1273 } else { 1274 soc_mem_field32_set(unit, mem, ment, MPLS_ACTION_IF_NOT_BOSf, 1275 _BCM_MPLS_XGS5_MPLS_ACTION_IF_NOT_BOS_PHP_ECMP); 1276 } 1277 } 1278 } 1279 } else if (BCM_XGS3_L3_EGRESS_IDX_VALID(unit, info->egress_if)) { 1280 if (BCM_MPLS_SWITCH_ACTION_PHP == action_if_bos) { 1281 1282 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 1283 soc_mem_field32_set(unit, mem, ment, MPLS_ACTION_IF_BOSf, 1284 _BCM_MPLS_TD3_MPLS_ACTION_PHP); 1285 } else { 1286 #ifdef BCM_MONTEREY_SUPPORT 1287 if ((info->flags2 & BCM_MPLS_SWITCH2_ENABLE_ROE) || 1288 (info->flags2 & BCM_MPLS_SWITCH2_ENABLE_ROE_CUSTOM)){ 1289 soc_mem_field32_set(unit, mem, ment, MPLS_ACTION_IF_BOSf, 1290 _BCM_MPLS_XGS5_MPLS_ACTION_IF_BOS_ROE_NHI); 1291 } else 1292 #endif 1293 { 1294 soc_mem_field32_set(unit, mem, ment, MPLS_ACTION_IF_BOSf, 1295 _BCM_MPLS_XGS5_MPLS_ACTION_IF_BOS_L3_NHI); 1296 } 1297 } 1298 } 1299 1300 if (BCM_MPLS_SWITCH_ACTION_PHP == action_if_not_bos) { 1301 1302 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 1303 soc_mem_field32_set(unit, mem, ment, MPLS_ACTION_IF_NOT_BOSf, 1304 _BCM_MPLS_TD3_MPLS_ACTION_PHP); 1305 } else { 1306 soc_mem_field32_set(unit, mem, ment, MPLS_ACTION_IF_NOT_BOSf, 1307 _BCM_MPLS_XGS5_MPLS_ACTION_IF_NOT_BOS_PHP_NHI); 1308 } 1309 } 1310 } else { 1311 return BCM_E_PARAM; 1312 } 1313 1314 /* uniform qos model if either of these two flags set. 1315 * Only apply to L3 MPLS and BOS 1316 */ 1317 if (info->flags & (BCM_MPLS_SWITCH_OUTER_EXP | 1318 BCM_MPLS_SWITCH_OUTER_TTL) ) { 1319 if (SOC_MEM_FIELD_VALID(unit,mem, 1320 DO_NOT_CHANGE_PAYLOAD_DSCPf)) { 1321 soc_mem_field32_set(unit, mem, ment, 1322 DO_NOT_CHANGE_PAYLOAD_DSCPf, 0); 1323 } 1324 } 1325 1326 /* 1327 * Get egress next-hop index from egress object and 1328 * increment egress object reference count. 1329 */ 1330 1331 BCM_IF_ERROR_RETURN(bcm_xgs3_get_nh_from_egress_object(unit, 1332 info->egress_if, &mpath_flag, 1, nh_index)); 1333 1334 /* Fix: Entry_Type = 1, for PHP Packets with more than 1 Label */ 1335 /* Read the egress next_hop entry pointed by Egress-Object */ 1336 if (!((info->flags2 & BCM_MPLS_SWITCH2_ENABLE_ROE) || 1337 (info->flags2 & BCM_MPLS_SWITCH2_ENABLE_ROE_CUSTOM))) { 1338 rv = bcm_tr_mpls_egress_entry_modify(unit, *nh_index, mpath_flag, 1); 1339 if (rv < 0 ) { 1340 return rv; 1341 } 1342 } 1343 1344 if (mpath_flag == BCM_L3_MULTIPATH) { 1345 if (soc_feature(unit, soc_feature_generic_dest)) { 1346 bcmi_td3_destination_format_set(unit, ment, 1347 SOC_MEM_FIF_DEST_ECMP, *nh_index); 1348 } else { 1349 soc_mem_field32_set(unit, mem, ment, ECMP_PTRf, 1350 *nh_index); 1351 } 1352 1353 /* Swap to ECMP Type PHP_ECMP or L3_ECMP flag is set up earlier */ 1354 } else { 1355 if (soc_feature(unit, soc_feature_generic_dest)) { 1356 bcmi_td3_destination_format_set(unit, ment, 1357 SOC_MEM_FIF_DEST_NEXTHOP, *nh_index); 1358 } else { 1359 soc_mem_field32_set(unit, mem, ment, NEXT_HOP_INDEXf, 1360 *nh_index); 1361 } 1362 } 1363 1364 #if defined(BCM_TRIDENT3_SUPPORT) 1365 /*PHP is similar to swap-to-self*/ 1366 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 1367 if (((SOC_IS_TRIDENT3(unit) && (cancun_ver < SOC_CANCUN_VERSION_DEF_6_0_0)) || 1368 (SOC_IS_MAVERICK2(unit) && (cancun_ver < SOC_CANCUN_VERSION_DEF_4_0_0)) || 1369 (SOC_IS_HELIX5(unit) && (cancun_ver < SOC_CANCUN_VERSION_DEF_4_0_0))) || 1370 (BCM_MPLS_SWITCH_ACTION_PHP != action_if_not_bos)) { 1371 soc_mem_field32_set(unit, mem, ment, 1372 DECAP_NEXT_FWD_LABELf, 1); 1373 1374 soc_mem_field32_set(unit, mem, ment, 1375 NEXT_FWD_LABEL_INHERITf, 1); 1376 1377 soc_mem_field32_set(unit, mem, ment, 1378 INHERITANCE_TYPEf, 1); 1379 } 1380 1381 if (BCM_MPLS_SWITCH_ACTION_PHP == action_if_bos || 1382 BCM_MPLS_SWITCH_ACTION_PHP == action_if_not_bos) { 1383 if (info->action == BCM_MPLS_SWITCH_ACTION_INVALID) { 1384 info->action = BCM_MPLS_SWITCH_ACTION_PHP; 1385 } 1386 } 1387 1388 if (mpath_flag == BCM_L3_MULTIPATH) { 1389 rv = bcmi_td3_php_ecmp_nhop_vcswap_add(unit, info, *nh_index, mpath_flag); 1390 } else { 1391 rv = bcmi_td3_mpls_php_vcswap_info_add(unit, info, nh_index); 1392 } 1393 1394 if (rv < 0) { 1395 return rv; 1396 } 1397 } 1398 #endif 1399 } /*BCM_MPLS_SWITCH_ACTION_PHP*/ 1400 1401 /*SWAP ACTION*/ 1402 if (BCM_MPLS_SWITCH_ACTION_SWAP == action_if_bos || 1403 BCM_MPLS_SWITCH_ACTION_SWAP == action_if_not_bos) { 1404 1405 if (!BCM_XGS3_L3_EGRESS_IDX_VALID(unit, info->egress_if)) { 1406 if ((!soc_feature(unit, soc_feature_mpls_lsr_ecmp)) || 1407 (!BCM_XGS3_L3_MPATH_EGRESS_IDX_VALID(unit, info->egress_if))) { 1408 return BCM_E_PARAM; 1409 } 1410 } 1411 if (BCM_XGS3_L3_MPLS_LBL_VALID(info->egress_label.label) || 1412 _BCM_MPLS_EGRESS_LABEL_PRESERVE(unit, info->egress_label.flags)) { 1413 rv = bcm_tr_mpls_l3_nh_info_add(unit, info, nh_index); 1414 if (rv < 0) { 1415 *nh_index_alloc_failed = 1; 1416 return rv; 1417 } 1418 if (soc_feature(unit, soc_feature_generic_dest)) { 1419 bcmi_td3_destination_format_set(unit, ment, 1420 SOC_MEM_FIF_DEST_NEXTHOP, *nh_index); 1421 } else { 1422 soc_mem_field32_set(unit, mem, ment, NEXT_HOP_INDEXf, 1423 *nh_index); 1424 } 1425 1426 if (BCM_MPLS_SWITCH_ACTION_SWAP == action_if_bos) { 1427 1428 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 1429 soc_mem_field32_set(unit, mem, ment, MPLS_ACTION_IF_BOSf, 1430 _BCM_MPLS_TD3_MPLS_ACTION_SWAP); 1431 } else { 1432 soc_mem_field32_set(unit, mem, ment, MPLS_ACTION_IF_BOSf, 1433 _BCM_MPLS_XGS5_MPLS_ACTION_IF_BOS_SWAP_NHI); 1434 } 1435 } 1436 1437 if (BCM_MPLS_SWITCH_ACTION_SWAP == action_if_not_bos) { 1438 1439 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 1440 soc_mem_field32_set(unit, mem, ment, MPLS_ACTION_IF_NOT_BOSf, 1441 _BCM_MPLS_TD3_MPLS_ACTION_SWAP); 1442 } else { 1443 soc_mem_field32_set(unit, mem, ment, MPLS_ACTION_IF_NOT_BOSf, 1444 _BCM_MPLS_XGS5_MPLS_ACTION_IF_NOT_BOS_SWAP_NHI); 1445 } 1446 } 1447 1448 #if defined(BCM_TRIDENT3_SUPPORT) || defined(BCM_TOMAHAWK3_SUPPORT) 1449 if (_BCM_MPLS_EGRESS_LABEL_PRESERVE(unit, info->egress_label.flags)) { 1450 /*Decap and add swap label to achieve swap-to-self.*/ 1451 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 1452 soc_mem_field32_set(unit, mem, ment, 1453 CURR_FWD_LABEL_INHERITf, 1); 1454 1455 soc_mem_field32_set(unit, mem, ment, 1456 INHERITANCE_TYPEf, 1); 1457 } 1458 } 1459 #endif 1460 } else { 1461 /* 1462 * Get egress next-hop index from egress object and 1463 * increment egress object reference count. 1464 */ 1465 BCM_IF_ERROR_RETURN(bcm_xgs3_get_nh_from_egress_object(unit, info->egress_if, 1466 &mpath_flag, 1, nh_index)); 1467 1468 if (soc_feature(unit, soc_feature_mpls_lsr_ecmp) && (mpath_flag == BCM_L3_MULTIPATH)) { 1469 if (soc_feature(unit, soc_feature_generic_dest)) { 1470 bcmi_td3_destination_format_set(unit, ment, 1471 SOC_MEM_FIF_DEST_ECMP, *nh_index); 1472 } else { 1473 soc_mem_field32_set(unit, mem, ment, ECMP_PTRf, 1474 *nh_index); 1475 } 1476 1477 /* Swap to ECMP Type */ 1478 if (BCM_MPLS_SWITCH_ACTION_SWAP == action_if_not_bos) { 1479 1480 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 1481 soc_mem_field32_set(unit, mem, ment, MPLS_ACTION_IF_NOT_BOSf, 1482 _BCM_MPLS_TD3_MPLS_ACTION_SWAP); 1483 } else { 1484 soc_mem_field32_set(unit, mem, ment, MPLS__MPLS_ACTION_IF_NOT_BOSf, 1485 _BCM_MPLS_XGS5_MPLS_ACTION_IF_NOT_BOS_SWAP_ECMP); 1486 } 1487 } 1488 1489 if (BCM_MPLS_SWITCH_ACTION_SWAP == action_if_bos) { 1490 1491 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 1492 soc_mem_field32_set(unit, mem, ment, MPLS_ACTION_IF_BOSf, 1493 _BCM_MPLS_TD3_MPLS_ACTION_SWAP); 1494 } else { 1495 soc_mem_field32_set(unit, mem, ment, MPLS__MPLS_ACTION_IF_BOSf, 1496 _BCM_MPLS_XGS5_MPLS_ACTION_IF_BOS_SWAP_ECMP); 1497 } 1498 } 1499 } else { 1500 if (soc_feature(unit, soc_feature_generic_dest)) { 1501 bcmi_td3_destination_format_set(unit, ment, 1502 SOC_MEM_FIF_DEST_NEXTHOP, *nh_index); 1503 } else { 1504 soc_mem_field32_set(unit, mem, ment, NEXT_HOP_INDEXf, 1505 *nh_index); 1506 } 1507 if (BCM_MPLS_SWITCH_ACTION_SWAP == action_if_not_bos) { 1508 1509 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 1510 soc_mem_field32_set(unit, mem, ment, MPLS_ACTION_IF_NOT_BOSf, 1511 _BCM_MPLS_TD3_MPLS_ACTION_SWAP); 1512 } else { 1513 soc_mem_field32_set(unit, mem, ment, MPLS_ACTION_IF_NOT_BOSf, 1514 _BCM_MPLS_XGS5_MPLS_ACTION_IF_NOT_BOS_SWAP_NHI); 1515 } 1516 } 1517 1518 if (BCM_MPLS_SWITCH_ACTION_SWAP == action_if_bos) { 1519 1520 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 1521 soc_mem_field32_set(unit, mem, ment, MPLS_ACTION_IF_BOSf, 1522 _BCM_MPLS_TD3_MPLS_ACTION_SWAP); 1523 } else { 1524 soc_mem_field32_set(unit, mem, ment, MPLS_ACTION_IF_BOSf, 1525 _BCM_MPLS_XGS5_MPLS_ACTION_IF_BOS_SWAP_NHI); 1526 } 1527 } 1528 } 1529 } 1530 }/* BCM_MPLS_SWITCH_ACTION_SWAP */ 1531 1532 /*INVALID ACTION*/ 1533 if (BCM_MPLS_SWITCH_ACTION_INVALID == action_if_bos) { 1534 1535 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 1536 soc_mem_field32_set(unit, mem, ment, MPLS_ACTION_IF_BOSf, 1537 _BCM_MPLS_TD3_MPLS_ACTION_INVALID); 1538 } else { 1539 soc_mem_field32_set(unit, mem, ment, MPLS_ACTION_IF_BOSf, 1540 _BCM_MPLS_XGS5_MPLS_ACTION_IF_BOS_INVALID); 1541 } 1542 } else if (BCM_MPLS_SWITCH_ACTION_INVALID == action_if_not_bos) { 1543 1544 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 1545 soc_mem_field32_set(unit, mem, ment, MPLS_ACTION_IF_NOT_BOSf, 1546 _BCM_MPLS_TD3_MPLS_ACTION_INVALID); 1547 } else { 1548 soc_mem_field32_set(unit, mem, ment, MPLS_ACTION_IF_NOT_BOSf, 1549 _BCM_MPLS_XGS5_MPLS_ACTION_IF_NOT_BOS_INVALID); 1550 } 1551 } 1552 1553 return rv; 1554 } 1555 1556 /* 1557 * Function: 1558 * bcm_mpls_tunnel_switch_add 1559 * Purpose: 1560 * Add an MPLS label entry. 1561 * Parameters: 1562 * unit - Device Number 1563 * info - Label (switch) information 1564 * Returns: 1565 * BCM_E_XXX 1566 */ 1567 int 1568 bcmi_xgs5_mpls_tunnel_switch_add(int unit, bcm_mpls_tunnel_switch_t *info) 1569 { 1570 mpls_entry_entry_t ment, ment_lkup, ment_old; 1571 int mode=0, nh_index = -1, rv, num_pw_term, old_pw_cnt = -1, pw_cnt = -1; 1572 int idx_l3_tunnel_mem, idx_mpls_mem; 1573 int old_nh_index = -1, old_ecmp_index = -1; 1574 int action, action_if_bos, action_if_not_bos; 1575 int old_action_if_bos = -1, old_action_if_not_bos = -1; 1576 int tunnel_switch_update=0; 1577 int ref_count=0; 1578 bcm_if_t egress_if=0; 1579 uint32 retval = 0, dest_type = SOC_MEM_FIF_DEST_INVALID; 1580 int nh_index_alloc_failed = 0; 1581 soc_mem_t mem = MPLS_ENTRYm; 1582 1583 if (soc_feature(unit, soc_feature_th3_style_simple_mpls)) { 1584 mem = MPLS_ENTRY_SINGLEm; 1585 } 1586 1587 rv = bcm_xgs3_l3_egress_mode_get(unit, &mode); 1588 BCM_IF_ERROR_RETURN(rv); 1589 if (!mode) { 1590 LOG_INFO(BSL_LS_BCM_L3, 1591 (BSL_META_U(unit, 1592 "L3 egress mode must be set first\n"))); 1593 return BCM_E_DISABLED; 1594 } 1595 1596 /* Check for Port_independent Label mapping */ 1597 if (!BCM_XGS3_L3_MPLS_LBL_VALID(info->label)) { 1598 return BCM_E_PARAM; 1599 } 1600 1601 /*INT_CN TO EXP MAP is Deprecated in TD3*/ 1602 if (soc_feature(unit, soc_feature_td3_style_mpls) && 1603 (info->flags & BCM_MPLS_EGRESS_LABEL_INT_CN_TO_EXP_MAP)) { 1604 return BCM_E_UNAVAIL; 1605 } 1606 1607 rv = bcm_tr_mpls_port_independent_range (unit, info->label, info->port); 1608 if (rv < 0) { 1609 return rv; 1610 } 1611 1612 #if defined(BCM_TOMAHAWK2_SUPPORT) || defined(BCM_APACHE_SUPPORT) 1613 if (soc_feature(unit, soc_feature_mpls_frr_lookup)) { 1614 if (info->flags & BCM_MPLS_SWITCH_FRR) { 1615 rv = _bcm_tr3_mpls_tunnel_switch_frr_set(unit, info); 1616 return rv; 1617 } 1618 } 1619 #endif /* BCM_TOMAHAWK2_SUPPORT || BCM_APACHE_SUPPORT */ 1620 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 1621 if((soc_feature(unit, soc_feature_fp_based_oam) || 1622 soc_feature(unit, soc_feature_td3_style_fp)) && 1623 SOC_MEM_FIELD_VALID(unit, MPLS_ENTRYm, CLASS_IDf)) { 1624 /*Ensure that class_id doesnt overcross CLASS_IDf*/ 1625 int bit_num = 0; 1626 if((info->flags & BCM_MPLS_SWITCH_COUNTED) && (info->class_id)) { 1627 return BCM_E_PARAM; 1628 } 1629 if(info->class_id) { 1630 if ((bit_num = soc_mem_field_length(unit, mem, CLASS_IDf)) > 0) { 1631 #if defined(BCM_MONTEREY_SUPPORT) 1632 if (soc_feature(unit,soc_feature_mont_roe_classid_sw_war)) { 1633 bit_num -= 1; 1634 } 1635 #endif 1636 } 1637 if(info->class_id > (( 1 << bit_num ) - 1)) { 1638 return BCM_E_PARAM; 1639 } 1640 } 1641 } 1642 #endif 1643 1644 action = info->action; 1645 if (info->action_if_bos != info->action_if_not_bos) { 1646 action = BCM_MPLS_SWITCH_ACTION_INVALID; 1647 action_if_bos = info->action_if_bos; 1648 action_if_not_bos = info->action_if_not_bos; 1649 } else { 1650 /* 1651 * Same action specified in if_bos and if_not_bos. 1652 * If this action is of valid type, it will override 1653 * the action specified in info->action 1654 */ 1655 if (info->action_if_bos != BCM_MPLS_SWITCH_ACTION_INVALID) { 1656 action = info->action_if_bos; 1657 } 1658 action_if_bos = action_if_not_bos = action; 1659 } 1660 1661 if (!(BCM_MPLS_SWITCH_ACTION_SWAP == action_if_bos || 1662 BCM_MPLS_SWITCH_ACTION_SWAP == action_if_not_bos || 1663 BCM_MPLS_SWITCH_ACTION_POP == action_if_bos || 1664 BCM_MPLS_SWITCH_ACTION_POP == action_if_not_bos || 1665 BCM_MPLS_SWITCH_ACTION_PHP == action_if_bos || 1666 BCM_MPLS_SWITCH_ACTION_PHP == action_if_not_bos)) { 1667 return BCM_E_PARAM; 1668 } 1669 if ((info->egress_label.flags & BCM_MPLS_EGRESS_LABEL_PRESERVE) && 1670 (BCM_MPLS_SWITCH_ACTION_SWAP != action_if_bos || 1671 BCM_MPLS_SWITCH_ACTION_SWAP != action_if_not_bos)) { 1672 return BCM_E_PARAM; 1673 } 1674 1675 #ifdef BCM_MONTEREY_SUPPORT 1676 if (!soc_feature(unit,soc_feature_roe)) { 1677 if (info->flags2 & BCM_MPLS_SWITCH2_ENABLE_ROE) { 1678 return BCM_E_UNAVAIL; 1679 } 1680 } 1681 if (!soc_feature(unit,soc_feature_roe_custom)) { 1682 if (info->flags2 & BCM_MPLS_SWITCH2_ENABLE_ROE_CUSTOM) { 1683 return BCM_E_UNAVAIL; 1684 } 1685 } 1686 if ((info->flags2 & BCM_MPLS_SWITCH2_ENABLE_ROE) && 1687 (info->flags2 & BCM_MPLS_SWITCH2_ENABLE_ROE_CUSTOM)) { 1688 return BCM_E_PARAM; 1689 } 1690 #endif 1691 1692 BCM_IF_ERROR_RETURN(_bcmi_xgs5_mpls_entry_set_key(unit, info, &ment)); 1693 1694 /* See if entry already exists */ 1695 rv = soc_mem_search(unit, mem, MEM_BLOCK_ANY, &idx_mpls_mem, 1696 &ment, &ment, 0); 1697 1698 if ((SOC_E_NONE == rv) && 1699 soc_feature(unit, soc_feature_th3_style_simple_mpls)) { 1700 /* For TH3, if there exists an entry in MPLS_ENTRY_SINGLE table then 1701 * cache it, as at later stage the cached copy can be used to revert 1702 * the MPLS_ENTRY_SINGLE entry to its original format if the insertion 1703 * fails in L3_TUNNEL_SINGLEm 1704 */ 1705 sal_memcpy(&ment_old, &ment, sizeof(mpls_entry_entry_t)); 1706 } 1707 1708 /* default not to use DSCP from ING_MPLS_EXP_MAPPING table */ 1709 if (SOC_MEM_FIELD_VALID(unit,mem,DO_NOT_CHANGE_PAYLOAD_DSCPf)) { 1710 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 1711 soc_mem_field32_set(unit, mem, &ment, 1712 DO_NOT_CHANGE_PAYLOAD_DSCPf, 0); 1713 } else { 1714 soc_mem_field32_set(unit, mem, &ment, 1715 DO_NOT_CHANGE_PAYLOAD_DSCPf, 1); 1716 } 1717 } 1718 1719 if (rv == SOC_E_NONE) { 1720 /* Entry exists, save old info */ 1721 tunnel_switch_update = 1; 1722 old_action_if_bos = soc_mem_field32_get(unit, mem, &ment, 1723 MPLS_ACTION_IF_BOSf); 1724 old_action_if_not_bos = soc_mem_field32_get(unit, mem, &ment, 1725 MPLS_ACTION_IF_NOT_BOSf); 1726 1727 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 1728 /*TD3 old mpls actions*/ 1729 if ((old_action_if_bos == _BCM_MPLS_TD3_MPLS_ACTION_SWAP) || 1730 (old_action_if_not_bos == _BCM_MPLS_TD3_MPLS_ACTION_SWAP) || 1731 (old_action_if_bos == _BCM_MPLS_TD3_MPLS_ACTION_PHP) || 1732 (old_action_if_not_bos == _BCM_MPLS_TD3_MPLS_ACTION_PHP)) { 1733 1734 retval = soc_mem_field32_dest_get(unit, MPLS_ENTRYm, &ment, 1735 DESTINATIONf, &dest_type); 1736 if (dest_type == SOC_MEM_FIF_DEST_ECMP) { 1737 old_ecmp_index = retval; 1738 } 1739 1740 if (dest_type == SOC_MEM_FIF_DEST_NEXTHOP) { 1741 old_nh_index = retval; 1742 } 1743 } 1744 1745 if (((old_action_if_bos == _BCM_MPLS_XGS5_MPLS_ACTION_IF_BOS_SWAP_ECMP) || 1746 (old_action_if_not_bos == _BCM_MPLS_XGS5_MPLS_ACTION_IF_NOT_BOS_SWAP_ECMP)) && 1747 soc_feature(unit, soc_feature_mpls_lsr_ecmp)) { 1748 1749 retval = soc_mem_field32_dest_get(unit, mem, &ment, 1750 DESTINATIONf, &dest_type); 1751 1752 if (dest_type == SOC_MEM_FIF_DEST_ECMP) { 1753 old_ecmp_index = retval; 1754 } 1755 } 1756 1757 } else { 1758 1759 if ((old_action_if_bos == _BCM_MPLS_XGS5_MPLS_ACTION_IF_BOS_SWAP_NHI) || 1760 (old_action_if_not_bos == _BCM_MPLS_XGS5_MPLS_ACTION_IF_NOT_BOS_SWAP_NHI) || 1761 (old_action_if_bos == _BCM_MPLS_XGS5_MPLS_ACTION_IF_BOS_L3_NHI) || 1762 (old_action_if_not_bos == _BCM_MPLS_XGS5_MPLS_ACTION_IF_NOT_BOS_PHP_NHI) || 1763 (old_action_if_bos == _BCM_MPLS_XGS5_MPLS_ACTION_IF_BOS_ROE_NHI)) { 1764 old_nh_index = soc_mem_field32_get(unit, mem, &ment, NEXT_HOP_INDEXf); 1765 } 1766 if ((old_action_if_bos == _BCM_MPLS_XGS5_MPLS_ACTION_IF_BOS_L3_ECMP) || 1767 (old_action_if_not_bos == _BCM_MPLS_XGS5_MPLS_ACTION_IF_NOT_BOS_PHP_ECMP)) { 1768 old_ecmp_index = soc_mem_field32_get(unit, mem, &ment, ECMP_PTRf); 1769 } 1770 if (((old_action_if_bos == _BCM_MPLS_XGS5_MPLS_ACTION_IF_BOS_SWAP_ECMP) || 1771 (old_action_if_not_bos == _BCM_MPLS_XGS5_MPLS_ACTION_IF_NOT_BOS_SWAP_ECMP)) && 1772 soc_feature(unit, soc_feature_mpls_lsr_ecmp)) { 1773 old_ecmp_index = soc_mem_field32_get(unit, mem, &ment, ECMP_PTRf); 1774 } 1775 } 1776 if (SOC_MEM_FIELD_VALID(unit, mem, PW_TERM_NUM_VALIDf)) { 1777 if (soc_mem_field32_get(unit, mem, &ment, PW_TERM_NUM_VALIDf)) { 1778 old_pw_cnt = soc_mem_field32_get(unit, mem, &ment, PW_TERM_NUMf); 1779 } 1780 } 1781 } else if (rv != SOC_E_NOT_FOUND) { 1782 return rv; 1783 } 1784 1785 rv = bcmi_xgs5_mpls_entry_label_actions_set(unit, action_if_bos, 1786 action_if_not_bos, info, &ment, &nh_index, &nh_index_alloc_failed); 1787 1788 if (rv < 0) { 1789 goto cleanup; 1790 } 1791 1792 soc_mem_field32_set(unit, mem, &ment, V4_ENABLEf, 1); 1793 soc_mem_field32_set(unit, mem, &ment, V6_ENABLEf, 1); 1794 1795 if (info->flags & BCM_MPLS_SWITCH_INNER_TTL) { 1796 if (BCM_MPLS_SWITCH_ACTION_SWAP == action_if_bos && 1797 BCM_MPLS_SWITCH_ACTION_SWAP == action_if_not_bos) { 1798 rv = BCM_E_PARAM; 1799 goto cleanup; 1800 } 1801 soc_mem_field32_set(unit, mem, &ment, DECAP_USE_TTLf, 0); 1802 } else { 1803 soc_mem_field32_set(unit, mem, &ment, DECAP_USE_TTLf, 1); 1804 } 1805 1806 if (info->flags & BCM_MPLS_SWITCH_INNER_EXP) { 1807 if (BCM_MPLS_SWITCH_ACTION_SWAP == action_if_bos && 1808 BCM_MPLS_SWITCH_ACTION_SWAP == action_if_not_bos) { 1809 rv = BCM_E_PARAM; 1810 goto cleanup; 1811 } 1812 soc_mem_field32_set(unit, mem, &ment, DECAP_USE_EXP_FOR_INNERf, 0); 1813 } else { 1814 /* For SWAP, Do-not PUSH EXP */ 1815 if (BCM_MPLS_SWITCH_ACTION_SWAP == action_if_bos && 1816 BCM_MPLS_SWITCH_ACTION_SWAP == action_if_not_bos) { 1817 soc_mem_field32_set(unit, mem, &ment, DECAP_USE_EXP_FOR_INNERf, 0); 1818 } else { 1819 soc_mem_field32_set(unit, mem, &ment, DECAP_USE_EXP_FOR_INNERf, 1); 1820 } 1821 } 1822 1823 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 1824 if (soc_feature(unit, soc_feature_td2p_mpls_linear_protection)){ 1825 int local_failover_id = 0; 1826 int prot_type = 0; 1827 if (info->flags & BCM_MPLS_SWITCH_DROP) { 1828 soc_mem_field32_set(unit, mem, &ment, 1829 MPLS__DROP_DATA_ENABLEf, 1); 1830 } else { 1831 soc_mem_field32_set(unit, mem, &ment, 1832 MPLS__DROP_DATA_ENABLEf, 0); 1833 } 1834 1835 if (info->failover_id != 0) { 1836 local_failover_id = info->failover_id; 1837 _BCM_GET_FAILOVER_TYPE(local_failover_id, prot_type); 1838 _BCM_GET_FAILOVER_ID(local_failover_id); 1839 if ((prot_type & _BCM_FAILOVER_INGRESS) && 1840 (BCM_SUCCESS(_bcm_td2p_failover_ingress_id_validate( 1841 unit, local_failover_id)))) { 1842 soc_mem_field32_set(unit, mem, &ment, 1843 MPLS__RX_PROT_GROUPf, 1844 local_failover_id); 1845 } 1846 } else { 1847 soc_mem_field32_set(unit, mem, &ment, 1848 MPLS__RX_PROT_GROUPf, 0); 1849 } 1850 } 1851 #endif 1852 1853 #if defined(BCM_TOMAHAWK2_SUPPORT) 1854 if (SOC_IS_TOMAHAWK2(unit)){ 1855 int local_failover_id = 0; 1856 int prot_type = 0; 1857 if (info->flags & BCM_MPLS_SWITCH_DROP) { 1858 soc_mem_field32_set(unit, mem, &ment, 1859 MPLS__DROP_DATA_ENABLEf, 1); 1860 } else { 1861 soc_mem_field32_set(unit, mem, &ment, 1862 MPLS__DROP_DATA_ENABLEf, 0); 1863 } 1864 1865 if (info->failover_id != 0) { 1866 local_failover_id = info->failover_id; 1867 _BCM_GET_FAILOVER_TYPE(local_failover_id, prot_type); 1868 _BCM_GET_FAILOVER_ID(local_failover_id); 1869 if ((prot_type & _BCM_FAILOVER_INGRESS) && 1870 (BCM_SUCCESS(_bcm_th2_failover_ingress_id_validate( 1871 unit, local_failover_id)))) { 1872 soc_mem_field32_set(unit, mem, &ment, 1873 MPLS__RX_PROT_GROUPf, 1874 local_failover_id); 1875 } 1876 } else { 1877 soc_mem_field32_set(unit, mem, &ment, 1878 MPLS__RX_PROT_GROUPf, 0); 1879 } 1880 } 1881 #endif 1882 1883 1884 1885 (void) bcm_tr_mpls_entry_internal_qos_set(unit, NULL, info, &ment); 1886 1887 if ((info->flags & BCM_MPLS_SWITCH_COUNTED)) { 1888 if (SOC_MEM_IS_VALID(unit, ING_PW_TERM_COUNTERSm)) { 1889 if (old_pw_cnt == -1) { 1890 num_pw_term = soc_mem_index_count(unit, ING_PW_TERM_COUNTERSm); 1891 for (pw_cnt = 0; pw_cnt < num_pw_term; pw_cnt++) { 1892 if (!_BCM_MPLS_PW_TERM_USED_GET(unit, pw_cnt)) { 1893 break; 1894 } 1895 } 1896 if (pw_cnt == num_pw_term) { 1897 rv = BCM_E_RESOURCE; 1898 goto cleanup; 1899 } 1900 _BCM_MPLS_PW_TERM_USED_SET(unit, pw_cnt); 1901 soc_mem_field32_set(unit, mem, &ment, PW_TERM_NUMf, pw_cnt); 1902 soc_mem_field32_set(unit, mem, &ment, PW_TERM_NUM_VALIDf, 1); 1903 } 1904 } else if (SOC_MEM_IS_VALID(unit, ING_PW_TERM_SEQ_NUMm)) { 1905 if (old_pw_cnt == -1) { 1906 num_pw_term = soc_mem_index_count(unit, ING_PW_TERM_SEQ_NUMm); 1907 for (pw_cnt = 0; pw_cnt < num_pw_term; pw_cnt++) { 1908 if (!_BCM_MPLS_PW_TERM_USED_GET(unit, pw_cnt)) { 1909 break; 1910 } 1911 } 1912 if (pw_cnt == num_pw_term) { 1913 rv = BCM_E_RESOURCE; 1914 goto cleanup; 1915 } 1916 _BCM_MPLS_PW_TERM_USED_SET(unit, pw_cnt); 1917 soc_mem_field32_set(unit, mem, &ment, PW_TERM_NUMf, pw_cnt); 1918 soc_mem_field32_set(unit, mem, &ment, PW_TERM_NUM_VALIDf, 1); 1919 } 1920 } 1921 } 1922 1923 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 1924 else if ((soc_feature(unit, soc_feature_fp_based_oam) || 1925 soc_feature(unit, soc_feature_td3_style_fp)) && 1926 SOC_MEM_FIELD_VALID(unit, MPLS_ENTRYm, CLASS_IDf)) { 1927 soc_mem_field32_set(unit, mem, &ment, CLASS_IDf, info->class_id); 1928 } 1929 #endif 1930 1931 #ifdef BCM_MONTEREY_SUPPORT 1932 /* Enable ROE or ROE Custom frame handling */ 1933 if (SOC_MEM_FIELD_VALID(unit,MPLS_ENTRYm,ROE_TYPEf)) { 1934 if (info->flags2 & BCM_MPLS_SWITCH2_ENABLE_ROE) { 1935 soc_mem_field32_set(unit, mem, &ment, 1936 ROE_TYPEf, _BCM_MPLS_XGS5_MPLS_ROE_TUNNEL); 1937 } else if (info->flags2 & BCM_MPLS_SWITCH2_ENABLE_ROE_CUSTOM) { 1938 soc_mem_field32_set(unit, mem, &ment, 1939 ROE_TYPEf, _BCM_MPLS_XGS5_MPLS_ROE_CUSTOM_TUNNEL); 1940 } else { 1941 soc_mem_field32_set(unit, mem, &ment, ROE_TYPEf, 0); 1942 } 1943 } 1944 #endif 1945 1946 #if defined(BCM_TOMAHAWK2_SUPPORT) || defined(BCM_TRIDENT3_SUPPORT) 1947 if (soc_feature(unit, soc_feature_mpls_ecn)) { 1948 if (info->flags & BCM_MPLS_SWITCH_INGRESS_ECN_MAP) { 1949 int ecn_map_index; 1950 int ecn_map_type; 1951 int ecn_map_num; 1952 int ecn_map_hw_idx; 1953 soc_mem_t mem_map; 1954 1955 ecn_map_type = info->ecn_map_id & _BCM_XGS5_MPLS_ECN_MAP_TYPE_MASK; 1956 ecn_map_index = info->ecn_map_id & _BCM_XGS5_MPLS_ECN_MAP_NUM_MASK; 1957 1958 #if defined(BCM_TRIDENT3_SUPPORT) 1959 if(soc_feature(unit, soc_feature_td3_style_mpls)) { 1960 mem_map = ING_EXP_TO_ECN_MAPPING_1m; 1961 } else 1962 #endif 1963 { 1964 mem_map = ING_EXP_TO_IP_ECN_MAPPINGm; 1965 } 1966 1967 ecn_map_num = 1968 soc_mem_index_count(unit, mem_map) / 1969 _BCM_ECN_MAX_ENTRIES_PER_MAP; 1970 if (ecn_map_type != _BCM_XGS5_MPLS_ECN_MAP_TYPE_EXP2ECN) { 1971 rv = BCM_E_PARAM; 1972 goto cleanup; 1973 } 1974 if (ecn_map_index >= ecn_map_num) { 1975 rv = BCM_E_PARAM; 1976 goto cleanup; 1977 } 1978 if (!bcmi_xgs5_ecn_map_used_get(unit, ecn_map_index, 1979 _bcmEcnmapTypeExp2Ecn)) { 1980 rv = BCM_E_PARAM; 1981 goto cleanup; 1982 } 1983 if (bcmi_ecn_map_id2hw_idx(unit, info->ecn_map_id, &ecn_map_hw_idx)) { 1984 rv = BCM_E_PARAM; 1985 goto cleanup; 1986 } 1987 #if defined(BCM_TRIDENT3_SUPPORT) 1988 if(soc_feature(unit, soc_feature_td3_style_mpls)) { 1989 soc_MPLS_ENTRYm_field32_set(unit, &ment, 1990 EXP_TO_ECN_MAPPING_PTRf, 1991 ecn_map_hw_idx); 1992 } else 1993 #endif 1994 { 1995 soc_mem_field32_set(unit, mem, &ment, 1996 EXP_TO_IP_ECN_MAPPING_PTRf, 1997 ecn_map_hw_idx); 1998 } 1999 } 2000 } 2001 #endif 2002 2003 #if defined(BCM_TRIDENT3_SUPPORT) 2004 if (BCM_MPLS_SWITCH_ACTION_SWAP == action_if_bos || 2005 BCM_MPLS_SWITCH_ACTION_SWAP == action_if_not_bos) { 2006 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 2007 /*It is needed for SWAPTOSELF scenarios*/ 2008 soc_mem_field32_set(unit, mem, &ment, 2009 CURR_FWD_LABEL_INHERITf, 1); 2010 2011 soc_mem_field32_set(unit, mem, &ment, 2012 INHERITANCE_TYPEf, 1); 2013 } 2014 } 2015 #endif 2016 2017 if (!tunnel_switch_update) { 2018 rv = soc_mem_insert(unit, mem, MEM_BLOCK_ALL, &ment); 2019 if (BCM_SUCCESS(rv) && 2020 soc_feature(unit, soc_feature_th3_style_simple_mpls)) { 2021 rv = soc_mem_insert(unit, L3_TUNNEL_SINGLEm, MEM_BLOCK_ALL, &ment); 2022 if (rv < 0) { 2023 /* Revert the insertion into MPLS_ENTRY_SINGLEm */ 2024 (void)soc_mem_delete(unit, mem, MEM_BLOCK_ALL, &ment); 2025 } 2026 } 2027 } else { 2028 rv = soc_mem_write(unit, mem, 2029 MEM_BLOCK_ALL, idx_mpls_mem, 2030 &ment); 2031 if (BCM_SUCCESS(rv) && 2032 soc_feature(unit, soc_feature_th3_style_simple_mpls)) { 2033 rv = _bcmi_xgs5_mpls_entry_set_key(unit, info, &ment_lkup); 2034 if (BCM_SUCCESS(rv)) { 2035 rv = soc_mem_search(unit, L3_TUNNEL_SINGLEm, MEM_BLOCK_ANY, 2036 &idx_l3_tunnel_mem, &ment_lkup, &ment_lkup, 0); 2037 if (BCM_SUCCESS(rv)) { 2038 rv = soc_mem_write(unit, L3_TUNNEL_SINGLEm, 2039 MEM_BLOCK_ALL, idx_l3_tunnel_mem, 2040 &ment); 2041 } 2042 } 2043 2044 if (rv < 0) { 2045 /* Revert the write into MPLS_ENTRY_SINGLEm */ 2046 (void)soc_mem_write( 2047 unit, mem, MEM_BLOCK_ALL, idx_mpls_mem, &ment_old); 2048 } 2049 } 2050 } 2051 2052 if (rv < 0) { 2053 goto cleanup; 2054 } 2055 2056 if (tunnel_switch_update) { 2057 /* Clean up old next-hop and counter info if entry was replaced */ 2058 if ((old_pw_cnt != -1) && !(info->flags & BCM_MPLS_SWITCH_COUNTED)) { 2059 _BCM_MPLS_PW_TERM_USED_CLR(unit, old_pw_cnt); 2060 } 2061 2062 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 2063 2064 if ((old_action_if_bos == _BCM_MPLS_TD3_MPLS_ACTION_SWAP) || 2065 (old_action_if_not_bos == _BCM_MPLS_TD3_MPLS_ACTION_SWAP)) { 2066 /* Check if tunnel_switch.egress_label mode is being used */ 2067 if (dest_type == SOC_MEM_FIF_DEST_NEXTHOP) { 2068 2069 rv = bcm_tr_mpls_get_vp_nh (unit, (bcm_if_t) old_nh_index, &egress_if); 2070 if (rv == BCM_E_NONE) { 2071 rv = bcm_tr_mpls_l3_nh_info_delete(unit, old_nh_index); 2072 } else { 2073 /* Decrement next-hop Reference count */ 2074 rv = bcm_xgs3_get_ref_count_from_nhi(unit, 0, &ref_count, old_nh_index); 2075 } 2076 } 2077 } 2078 2079 if ((old_action_if_bos == _BCM_MPLS_TD3_MPLS_ACTION_PHP) || 2080 (old_action_if_not_bos == _BCM_MPLS_TD3_MPLS_ACTION_PHP)) { 2081 2082 if (dest_type == SOC_MEM_FIF_DEST_NEXTHOP) { 2083 rv = bcm_xgs3_nh_del(unit, 0, old_nh_index); 2084 } 2085 2086 if (dest_type == SOC_MEM_FIF_DEST_ECMP) { 2087 rv = bcm_xgs3_ecmp_group_del(unit, old_ecmp_index, 0); 2088 } 2089 } 2090 2091 if (soc_feature(unit, soc_feature_mpls_lsr_ecmp) && 2092 ((old_action_if_bos == _BCM_MPLS_TD3_MPLS_ACTION_SWAP) || 2093 (old_action_if_not_bos == _BCM_MPLS_TD3_MPLS_ACTION_SWAP))) { 2094 2095 if (dest_type == SOC_MEM_FIF_DEST_ECMP) { 2096 rv = bcm_xgs3_ecmp_group_del(unit, old_ecmp_index, 0); 2097 } 2098 } 2099 2100 } else { 2101 if ((old_action_if_bos == _BCM_MPLS_XGS5_MPLS_ACTION_IF_BOS_SWAP_NHI) || 2102 (old_action_if_not_bos == _BCM_MPLS_XGS5_MPLS_ACTION_IF_NOT_BOS_SWAP_NHI)) { 2103 /* Check if tunnel_switch.egress_label mode is being used */ 2104 rv = bcm_tr_mpls_get_vp_nh (unit, (bcm_if_t) old_nh_index, &egress_if); 2105 if (rv == BCM_E_NONE) { 2106 rv = bcm_tr_mpls_l3_nh_info_delete(unit, old_nh_index); 2107 } else { 2108 /* Decrement next-hop Reference count */ 2109 rv = bcm_xgs3_get_ref_count_from_nhi(unit, 0, &ref_count, old_nh_index); 2110 } 2111 } 2112 if ((old_action_if_bos == _BCM_MPLS_XGS5_MPLS_ACTION_IF_BOS_L3_NHI) || 2113 (old_action_if_bos == _BCM_MPLS_XGS5_MPLS_ACTION_IF_BOS_ROE_NHI) || 2114 (old_action_if_not_bos == _BCM_MPLS_XGS5_MPLS_ACTION_IF_NOT_BOS_PHP_NHI)) { 2115 rv = bcm_xgs3_nh_del(unit, 0, old_nh_index); 2116 } 2117 if ((old_action_if_bos == _BCM_MPLS_XGS5_MPLS_ACTION_IF_BOS_L3_ECMP) || 2118 (old_action_if_not_bos == _BCM_MPLS_XGS5_MPLS_ACTION_IF_NOT_BOS_PHP_ECMP)) { 2119 rv = bcm_xgs3_ecmp_group_del(unit, old_ecmp_index, 0); 2120 } 2121 if (soc_feature(unit, soc_feature_mpls_lsr_ecmp) && 2122 ((old_action_if_bos == _BCM_MPLS_XGS5_MPLS_ACTION_IF_BOS_SWAP_ECMP) || 2123 (old_action_if_not_bos == _BCM_MPLS_XGS5_MPLS_ACTION_IF_NOT_BOS_SWAP_ECMP))) { 2124 rv = bcm_xgs3_ecmp_group_del(unit, old_ecmp_index, 0); 2125 } 2126 } 2127 } 2128 2129 if (rv < 0) { 2130 goto cleanup; 2131 } 2132 2133 #ifdef BCM_WARM_BOOT_SUPPORT 2134 SOC_CONTROL_LOCK(unit); 2135 SOC_CONTROL(unit)->scache_dirty = 1; 2136 SOC_CONTROL_UNLOCK(unit); 2137 #endif 2138 2139 return rv; 2140 2141 cleanup: 2142 if (nh_index_alloc_failed) { 2143 return rv; 2144 } 2145 if (pw_cnt != -1) { 2146 _BCM_MPLS_PW_TERM_USED_CLR(unit, pw_cnt); 2147 } 2148 /* coverity[check_after_sink : FALSE] */ 2149 if (nh_index != -1) { 2150 if ((action_if_bos == BCM_MPLS_SWITCH_ACTION_SWAP) || 2151 (action_if_not_bos == BCM_MPLS_SWITCH_ACTION_SWAP)) { 2152 if (BCM_XGS3_L3_MPLS_LBL_VALID(info->egress_label.label) || 2153 (info->action == BCM_MPLS_SWITCH_ACTION_PHP)) { 2154 (void) bcm_tr_mpls_l3_nh_info_delete(unit, nh_index); 2155 } 2156 } else if ((action_if_bos == BCM_MPLS_SWITCH_ACTION_PHP) || 2157 (action_if_not_bos == BCM_MPLS_SWITCH_ACTION_PHP)) { 2158 (void) bcm_xgs3_nh_del(unit, 0, nh_index); 2159 } 2160 } 2161 return rv; 2162 } 2163 2164 STATIC int 2165 _bcmi_xgs5_mpls_entry_delete(int unit, mpls_entry_entry_t *ment) 2166 { 2167 ing_pw_term_counters_entry_t pw_cnt_entry; 2168 int rv, ecmp_index = -1, nh_index = -1, pw_cnt = -1; 2169 int action_if_bos, action_if_not_bos; 2170 bcm_if_t egress_if=0; 2171 int ref_count=0; 2172 uint32 dest_type = SOC_MEM_FIF_DEST_INVALID; 2173 uint32 value=0; 2174 soc_mem_t mem = MPLS_ENTRYm; 2175 2176 if (soc_feature(unit, soc_feature_th3_style_simple_mpls)) { 2177 mem = MPLS_ENTRY_SINGLEm; 2178 } 2179 2180 if (SOC_MEM_FIELD_VALID(unit, mem, PW_TERM_NUM_VALIDf)) { 2181 if (soc_mem_field32_get(unit, mem, ment, PW_TERM_NUM_VALIDf)) { 2182 pw_cnt = soc_mem_field32_get(unit, mem, ment, PW_TERM_NUMf); 2183 } 2184 } 2185 2186 action_if_bos = soc_mem_field32_get(unit, mem, ment, MPLS_ACTION_IF_BOSf); 2187 action_if_not_bos = soc_mem_field32_get(unit, mem, ment, 2188 MPLS_ACTION_IF_NOT_BOSf); 2189 2190 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 2191 if ((action_if_bos == _BCM_MPLS_TD3_MPLS_ACTION_SWAP) || 2192 (action_if_not_bos == _BCM_MPLS_TD3_MPLS_ACTION_SWAP) || 2193 (action_if_bos == _BCM_MPLS_TD3_MPLS_ACTION_PHP) || 2194 (action_if_not_bos == _BCM_MPLS_TD3_MPLS_ACTION_PHP)) { 2195 2196 value = soc_mem_field32_dest_get(unit, MPLS_ENTRYm, ment, 2197 DESTINATIONf, &dest_type); 2198 2199 if (dest_type == SOC_MEM_FIF_DEST_NEXTHOP) { 2200 nh_index = value; 2201 } 2202 if (dest_type == SOC_MEM_FIF_DEST_ECMP) { 2203 ecmp_index = value; 2204 } 2205 } 2206 #if 0 2207 if ((action_if_bos == _BCM_MPLS_TD3_MPLS_ACTION_PHP) || 2208 (action_if_not_bos == _BCM_MPLS_TD3_MPLS_ACTION_PHP)) { 2209 ecmp_index = soc_mem_field32_get(unit, mem, ment, ECMP_PTRf); 2210 } 2211 #endif 2212 2213 if (((action_if_bos == _BCM_MPLS_TD3_MPLS_ACTION_SWAP) || 2214 (action_if_not_bos == _BCM_MPLS_TD3_MPLS_ACTION_SWAP)) && 2215 soc_feature(unit, soc_feature_mpls_lsr_ecmp)) { 2216 2217 value = soc_mem_field32_dest_get(unit, mem, ment, 2218 DESTINATIONf, &dest_type); 2219 2220 if (dest_type == SOC_MEM_FIF_DEST_ECMP) { 2221 ecmp_index = value; 2222 } 2223 } 2224 } else { 2225 if ((action_if_bos == _BCM_MPLS_XGS5_MPLS_ACTION_IF_BOS_SWAP_NHI) || 2226 (action_if_not_bos == _BCM_MPLS_XGS5_MPLS_ACTION_IF_NOT_BOS_SWAP_NHI) || 2227 (action_if_bos == _BCM_MPLS_XGS5_MPLS_ACTION_IF_BOS_L3_NHI) || 2228 (action_if_bos == _BCM_MPLS_XGS5_MPLS_ACTION_IF_BOS_ROE_NHI) || 2229 (action_if_not_bos == _BCM_MPLS_XGS5_MPLS_ACTION_IF_NOT_BOS_PHP_NHI)) { 2230 nh_index = soc_mem_field32_get(unit, mem, ment, NEXT_HOP_INDEXf); 2231 } 2232 if ((action_if_bos == _BCM_MPLS_XGS5_MPLS_ACTION_IF_BOS_L3_ECMP) || 2233 (action_if_not_bos == _BCM_MPLS_XGS5_MPLS_ACTION_IF_NOT_BOS_PHP_ECMP)) { 2234 ecmp_index = soc_mem_field32_get(unit, mem, ment, ECMP_PTRf); 2235 } 2236 if (((action_if_bos == _BCM_MPLS_XGS5_MPLS_ACTION_IF_BOS_SWAP_ECMP) || 2237 (action_if_not_bos == _BCM_MPLS_XGS5_MPLS_ACTION_IF_NOT_BOS_SWAP_ECMP)) && 2238 soc_feature(unit, soc_feature_mpls_lsr_ecmp)) { 2239 ecmp_index = soc_mem_field32_get(unit, mem, ment, ECMP_PTRf); 2240 } 2241 } 2242 /* Delete the entry from HW */ 2243 rv = soc_mem_delete(unit, mem, MEM_BLOCK_ALL, ment); 2244 if ( (rv != BCM_E_NOT_FOUND) && (rv != BCM_E_NONE) ) { 2245 return rv; 2246 } 2247 2248 if (soc_feature(unit, soc_feature_th3_style_simple_mpls)) { 2249 rv = soc_mem_delete(unit, L3_TUNNEL_SINGLEm, MEM_BLOCK_ALL, ment); 2250 if ( (rv != BCM_E_NOT_FOUND) && (rv != BCM_E_NONE) ) { 2251 return rv; 2252 } 2253 } 2254 2255 if (pw_cnt != -1) { 2256 if (SOC_MEM_IS_VALID(unit, ING_PW_TERM_SEQ_NUMm)) { 2257 ing_pw_term_seq_num_entry_t pw_seq_num_entry; 2258 2259 sal_memset(&pw_seq_num_entry, 0, sizeof(ing_pw_term_seq_num_entry_t)); 2260 (void) WRITE_ING_PW_TERM_SEQ_NUMm(unit, MEM_BLOCK_ALL, pw_cnt, 2261 &pw_seq_num_entry); 2262 } else { 2263 sal_memset(&pw_cnt_entry, 0, sizeof(ing_pw_term_counters_entry_t)); 2264 (void) WRITE_ING_PW_TERM_COUNTERSm(unit, MEM_BLOCK_ALL, pw_cnt, 2265 &pw_cnt_entry); 2266 } 2267 2268 _BCM_MPLS_PW_TERM_USED_CLR(unit, pw_cnt); 2269 } 2270 2271 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 2272 if ((action_if_bos == _BCM_MPLS_TD3_MPLS_ACTION_SWAP) || 2273 (action_if_not_bos == _BCM_MPLS_TD3_MPLS_ACTION_SWAP)) { 2274 /* Check if tunnel_switch.egress_label mode is being used */ 2275 if (dest_type == SOC_MEM_FIF_DEST_NEXTHOP) { 2276 rv = bcm_tr_mpls_get_vp_nh (unit, (bcm_if_t) nh_index, &egress_if); 2277 if (rv == BCM_E_NONE) { 2278 rv = bcm_tr_mpls_l3_nh_info_delete(unit, nh_index); 2279 } else { 2280 /* Decrement next-hop Reference count */ 2281 rv = bcm_xgs3_get_ref_count_from_nhi(unit, 0, &ref_count, nh_index); 2282 } 2283 } 2284 } 2285 2286 if ((action_if_bos == _BCM_MPLS_TD3_MPLS_ACTION_PHP) || 2287 (action_if_not_bos == _BCM_MPLS_TD3_MPLS_ACTION_PHP)) { 2288 2289 if (dest_type == SOC_MEM_FIF_DEST_NEXTHOP) { 2290 #if defined(BCM_TRIDENT3_SUPPORT) 2291 rv = bcmi_td3_mpls_php_vcswap_info_delete(unit, 2292 nh_index, dest_type); 2293 /* Decrement next-hop Reference count */ 2294 rv = bcm_xgs3_get_ref_count_from_nhi(unit, 0, 2295 &ref_count, nh_index); 2296 #endif 2297 rv = bcm_xgs3_nh_del(unit, 0, nh_index); 2298 } 2299 2300 if (dest_type == SOC_MEM_FIF_DEST_ECMP) { 2301 #if defined(BCM_TRIDENT3_SUPPORT) 2302 rv = bcmi_td3_php_ecmp_nhop_vcswap_delete(unit, 2303 ecmp_index, dest_type,BCM_L3_MULTIPATH); 2304 /* Decrement next-hop Reference count */ 2305 rv = bcm_xgs3_get_ref_count_from_nhi(unit, 0, 2306 &ref_count, ecmp_index); 2307 #endif 2308 rv = bcm_xgs3_ecmp_group_del(unit, ecmp_index, 0); 2309 } 2310 } 2311 2312 if (soc_feature(unit, soc_feature_mpls_lsr_ecmp) && 2313 ((action_if_bos == _BCM_MPLS_TD3_MPLS_ACTION_SWAP) || 2314 (action_if_not_bos == _BCM_MPLS_TD3_MPLS_ACTION_SWAP))) { 2315 2316 if (dest_type == SOC_MEM_FIF_DEST_ECMP) { 2317 rv = bcm_xgs3_ecmp_group_del(unit, ecmp_index, 0); 2318 } 2319 } 2320 } else { 2321 if ((action_if_bos == _BCM_MPLS_XGS5_MPLS_ACTION_IF_BOS_SWAP_NHI) || 2322 (action_if_not_bos == _BCM_MPLS_XGS5_MPLS_ACTION_IF_NOT_BOS_SWAP_NHI)) { 2323 /* Check if tunnel_switch.egress_label mode is being used */ 2324 rv = bcm_tr_mpls_get_vp_nh (unit, (bcm_if_t) nh_index, &egress_if); 2325 if (rv == BCM_E_NONE) { 2326 rv = bcm_tr_mpls_l3_nh_info_delete(unit, nh_index); 2327 } else { 2328 /* Decrement next-hop Reference count */ 2329 rv = bcm_xgs3_get_ref_count_from_nhi(unit, 0, &ref_count, nh_index); 2330 } 2331 } 2332 if ((action_if_bos == _BCM_MPLS_XGS5_MPLS_ACTION_IF_BOS_L3_NHI) || 2333 (action_if_bos == _BCM_MPLS_XGS5_MPLS_ACTION_IF_BOS_ROE_NHI) || 2334 (action_if_not_bos == _BCM_MPLS_XGS5_MPLS_ACTION_IF_NOT_BOS_PHP_NHI)) { 2335 rv = bcm_xgs3_nh_del(unit, 0, nh_index); 2336 } 2337 if ((action_if_bos == _BCM_MPLS_XGS5_MPLS_ACTION_IF_BOS_L3_ECMP) || 2338 (action_if_not_bos == _BCM_MPLS_XGS5_MPLS_ACTION_IF_NOT_BOS_PHP_ECMP)) { 2339 rv = bcm_xgs3_ecmp_group_del(unit, ecmp_index, 0); 2340 } 2341 if (soc_feature(unit, soc_feature_mpls_lsr_ecmp) && 2342 ((action_if_bos == _BCM_MPLS_XGS5_MPLS_ACTION_IF_BOS_SWAP_ECMP) || 2343 (action_if_not_bos == _BCM_MPLS_XGS5_MPLS_ACTION_IF_NOT_BOS_SWAP_ECMP))) { 2344 rv = bcm_xgs3_ecmp_group_del(unit, ecmp_index, 0); 2345 } 2346 } 2347 2348 return rv; 2349 } 2350 2351 /* 2352 * Function: 2353 * bcm_mpls_tunnel_switch_delete 2354 * Purpose: 2355 * Delete an MPLS label entry. 2356 * Parameters: 2357 * unit - Device Number 2358 * info - Label (switch) information 2359 * Returns: 2360 * BCM_E_XXX 2361 */ 2362 int 2363 bcmi_xgs5_mpls_tunnel_switch_delete(int unit, bcm_mpls_tunnel_switch_t *info) 2364 { 2365 int rv, index; 2366 mpls_entry_entry_t ment; 2367 soc_mem_t mem = MPLS_ENTRYm; 2368 2369 if (soc_feature(unit, soc_feature_th3_style_simple_mpls)) { 2370 mem = MPLS_ENTRY_SINGLEm; 2371 } 2372 #if defined(BCM_TOMAHAWK2_SUPPORT) || defined(BCM_APACHE_SUPPORT) 2373 if (soc_feature(unit, soc_feature_mpls_frr_lookup) && 2374 (info->flags & BCM_MPLS_SWITCH_FRR)) { 2375 rv = _bcm_tr3_mpls_tunnel_switch_frr_delete(unit, info); 2376 } else 2377 #endif /* BCM_TOMAHAWK2_SUPPORT || BCM_APACHE_SUPPORT */ 2378 { 2379 rv = _bcmi_xgs5_mpls_entry_set_key(unit, info, &ment); 2380 BCM_IF_ERROR_RETURN(rv); 2381 2382 rv = soc_mem_search(unit, mem, MEM_BLOCK_ANY, &index, 2383 &ment, &ment, 0); 2384 if (rv < 0) { 2385 return rv; 2386 } 2387 rv = _bcmi_xgs5_mpls_entry_delete(unit, &ment); 2388 } 2389 2390 #ifdef BCM_WARM_BOOT_SUPPORT 2391 SOC_CONTROL_LOCK(unit); 2392 SOC_CONTROL(unit)->scache_dirty = 1; 2393 SOC_CONTROL_UNLOCK(unit); 2394 #endif 2395 2396 return rv; 2397 } 2398 2399 /* 2400 * Function: 2401 * bcm_mpls_tunnel_switch_delete_all 2402 * Purpose: 2403 * Delete all MPLS label entries. 2404 * Parameters: 2405 * unit - Device Number 2406 * Returns: 2407 * BCM_E_XXX 2408 */ 2409 int 2410 bcmi_xgs5_mpls_tunnel_switch_delete_all(int unit) 2411 { 2412 int rv = BCM_E_NONE, i; 2413 mpls_entry_entry_t *ment = NULL; 2414 int index_min, index_max; 2415 uint8 *mpls_entry_buf = NULL; 2416 #if defined(BCM_TOMAHAWK2_SUPPORT) || defined(BCM_APACHE_SUPPORT) 2417 int num_entries; 2418 soc_tunnel_term_t tnl_entry; 2419 #endif 2420 soc_mem_t mem = MPLS_ENTRYm; 2421 soc_field_t validf = VALIDf; 2422 2423 if (soc_feature(unit, soc_feature_th3_style_simple_mpls)) { 2424 mem = MPLS_ENTRY_SINGLEm; 2425 validf = BASE_VALIDf; 2426 } 2427 2428 mpls_entry_buf = soc_cm_salloc(unit, 2429 SOC_MEM_TABLE_BYTES(unit, mem), "MPLS_ENTRY buffer"); 2430 if (NULL == mpls_entry_buf) { 2431 return BCM_E_MEMORY; 2432 } 2433 2434 index_min = soc_mem_index_min(unit, mem); 2435 index_max = soc_mem_index_max(unit, mem); 2436 rv = soc_mem_read_range(unit, mem, MEM_BLOCK_ANY, 2437 index_min, index_max, mpls_entry_buf); 2438 if (SOC_FAILURE(rv)) { 2439 if (mpls_entry_buf) { 2440 soc_cm_sfree(unit, mpls_entry_buf); 2441 } 2442 return rv; 2443 } 2444 2445 for (i = index_min; i <= index_max; i++) { 2446 ment = soc_mem_table_idx_to_pointer 2447 (unit, mem, mpls_entry_entry_t *, mpls_entry_buf, i); 2448 2449 /* Check for valid entry */ 2450 if (soc_feature(unit, soc_feature_td3_style_mpls)){ 2451 if (soc_mem_field32_get(unit, mem, ment, BASE_VALID_0f) != 3) { 2452 continue; 2453 } 2454 if (soc_mem_field32_get(unit, mem, ment, BASE_VALID_1f) != 7) { 2455 continue; 2456 } 2457 } else { 2458 if (!soc_mem_field32_get(unit, mem, ment, validf)) { 2459 continue; 2460 } 2461 } 2462 if (soc_mem_field32_get(unit, mem, ment, MPLS_ACTION_IF_BOSf) == 2463 _BCM_MPLS_XGS5_MPLS_ACTION_IF_BOS_L2_SVP) { 2464 /* L2_SVP */ 2465 continue; 2466 } 2467 2468 rv = _bcmi_xgs5_mpls_entry_delete(unit, ment); 2469 if (BCM_FAILURE(rv)) { 2470 if (mpls_entry_buf) { 2471 soc_cm_sfree(unit, mpls_entry_buf); 2472 } 2473 return rv; 2474 } 2475 } 2476 2477 if (mpls_entry_buf) { 2478 soc_cm_sfree(unit, mpls_entry_buf); 2479 } 2480 #if defined(BCM_TOMAHAWK2_SUPPORT) || defined(BCM_APACHE_SUPPORT) 2481 if (soc_feature(unit, soc_feature_mpls_frr_lookup)) { 2482 num_entries = soc_mem_index_count(unit, L3_TUNNELm); 2483 for (i = 0; i < num_entries; i++) { 2484 sal_memset(&tnl_entry, 0, sizeof(tnl_entry)); 2485 rv = READ_L3_TUNNELm(unit, MEM_BLOCK_ANY, i, 2486 (uint32 *)&tnl_entry.entry_arr[0]); 2487 if (rv < 0) { 2488 return rv; 2489 } 2490 if (!soc_L3_TUNNELm_field32_get(unit, &tnl_entry, VALIDf)) { 2491 continue; 2492 } 2493 if (0x2 != soc_L3_TUNNELm_field32_get(unit, &tnl_entry, MODEf)) { 2494 continue; 2495 } 2496 2497 rv = soc_tunnel_term_delete(unit, &tnl_entry); 2498 if (rv < 0) { 2499 return rv; 2500 } 2501 2502 /*_soc_tunnel_term_slot_free() api moves last entry to 2503 *deleted entry position using _soc_tunnel_term_entry_shift(). 2504 *Therefore adding this index change to support delete all*/ 2505 i--; 2506 } 2507 } 2508 #endif 2509 2510 return BCM_E_NONE; 2511 } 2512 2513 /* 2514 * Function: 2515 * bcm_mpls_tunnel_switch_get 2516 * Purpose: 2517 * Get an MPLS label entry. 2518 * Parameters: 2519 * unit - Device Number 2520 * info - Label (switch) information 2521 * Returns: 2522 * BCM_E_XXX 2523 */ 2524 int 2525 bcmi_xgs5_mpls_tunnel_switch_get(int unit, bcm_mpls_tunnel_switch_t *info) 2526 { 2527 int rv, index; 2528 mpls_entry_entry_t ment; 2529 soc_mem_t mem = MPLS_ENTRYm; 2530 2531 if (soc_feature(unit, soc_feature_th3_style_simple_mpls)) { 2532 mem = MPLS_ENTRY_SINGLEm; 2533 } 2534 #if defined(BCM_TOMAHAWK2_SUPPORT) || defined(BCM_APACHE_SUPPORT) 2535 if (soc_feature(unit, soc_feature_mpls_frr_lookup) && 2536 (info->flags & BCM_MPLS_SWITCH_FRR)) { 2537 rv = _bcm_tr3_mpls_tunnel_switch_frr_get(unit, info, &index); 2538 } else 2539 #endif /* BCM_TOMAHAWK2_SUPPORT || BCM_APACHE_SUPPORT */ 2540 { 2541 2542 rv = _bcmi_xgs5_mpls_entry_set_key(unit, info, &ment); 2543 2544 BCM_IF_ERROR_RETURN(rv); 2545 2546 rv = soc_mem_search(unit, mem, MEM_BLOCK_ANY, &index, 2547 &ment, &ment, 0); 2548 2549 if (rv < 0) { 2550 return rv; 2551 } 2552 2553 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 2554 rv = bcmi_td3_mpls_entry_get_data(unit, &ment, info); 2555 } else { 2556 rv = _bcmi_xgs5_mpls_entry_get_data(unit, &ment, info); 2557 } 2558 } 2559 return rv; 2560 } 2561 2562 /* 2563 * Function: 2564 * bcm_mpls_tunnel_switch_traverse 2565 * Purpose: 2566 * Traverse all valid MPLS label entries an call the 2567 * supplied callback routine. 2568 * Parameters: 2569 * unit - Device Number 2570 * cb - User callback function, called once per MPLS entry. 2571 * user_data - cookie 2572 * Returns: 2573 * BCM_E_XXX 2574 */ 2575 int 2576 bcmi_xgs5_mpls_tunnel_switch_traverse(int unit, 2577 bcm_mpls_tunnel_switch_traverse_cb cb, 2578 void *user_data) 2579 { 2580 int rv, i; 2581 mpls_entry_entry_t *ment = NULL; 2582 bcm_mpls_tunnel_switch_t info; 2583 #if defined(BCM_TOMAHAWK2_SUPPORT) || defined(BCM_APACHE_SUPPORT) 2584 soc_tunnel_term_t *tnl_entry = NULL; 2585 uint32 key_type=0; 2586 uint8 *tnl_entry_buf = NULL; 2587 #endif 2588 int index_min, index_max; 2589 uint8 *mpls_entry_buf = NULL; 2590 soc_mem_t mem = MPLS_ENTRYm; 2591 soc_field_t validf = VALIDf; 2592 2593 if (soc_feature(unit, soc_feature_th3_style_simple_mpls)) { 2594 mem = MPLS_ENTRY_SINGLEm; 2595 validf = BASE_VALIDf; 2596 } 2597 2598 mpls_entry_buf = soc_cm_salloc(unit, 2599 SOC_MEM_TABLE_BYTES(unit, mem), "MPLS_ENTRY buffer"); 2600 if (NULL == mpls_entry_buf) { 2601 rv = BCM_E_MEMORY; 2602 goto cleanup; 2603 } 2604 2605 index_min = soc_mem_index_min(unit, mem); 2606 index_max = soc_mem_index_max(unit, mem); 2607 rv = soc_mem_read_range(unit, mem, MEM_BLOCK_ANY, 2608 index_min, index_max, mpls_entry_buf); 2609 if (SOC_FAILURE(rv)) { 2610 goto cleanup; 2611 } 2612 2613 for (i = index_min; i <= index_max; i++) { 2614 ment = soc_mem_table_idx_to_pointer 2615 (unit, mem, mpls_entry_entry_t *, mpls_entry_buf, i); 2616 2617 /* Check for valid entry */ 2618 if (SOC_IS_TRIDENT3X(unit)) { 2619 if (soc_mem_field32_get(unit, mem, ment, BASE_VALID_0f) != 3) { 2620 continue; 2621 } 2622 if (soc_mem_field32_get(unit, mem, ment, BASE_VALID_1f) != 7) { 2623 continue; 2624 } 2625 } else { 2626 if (!soc_mem_field32_get(unit, mem, ment, validf)) { 2627 continue; 2628 } 2629 } 2630 /* Check MPLS Key_type */ 2631 if (soc_feature(unit, soc_feature_mpls_enhanced)) { 2632 if (0x0 != soc_mem_field32_get(unit, mem, ment, KEY_TYPEf)) { 2633 continue; 2634 } 2635 } 2636 if (soc_mem_field32_get(unit, mem, ment, MPLS_ACTION_IF_BOSf) == 2637 _BCM_MPLS_XGS5_MPLS_ACTION_IF_BOS_L2_SVP) { 2638 continue; 2639 } 2640 sal_memset(&info, 0, sizeof(bcm_mpls_tunnel_switch_t)); 2641 rv = _bcmi_xgs5_mpls_entry_get_key(unit, ment, &info); 2642 if (rv < 0) { 2643 goto cleanup; 2644 } 2645 2646 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 2647 rv = bcmi_td3_mpls_entry_get_data(unit, ment, &info); 2648 } else { 2649 rv = _bcmi_xgs5_mpls_entry_get_data(unit, ment, &info); 2650 } 2651 if (rv < 0) { 2652 goto cleanup; 2653 } 2654 rv = cb(unit, &info, user_data); 2655 #ifdef BCM_CB_ABORT_ON_ERR 2656 if (BCM_FAILURE(rv) && SOC_CB_ABORT_ON_ERR(unit)) { 2657 goto cleanup; 2658 } 2659 #endif 2660 } 2661 2662 #if defined(BCM_TOMAHAWK2_SUPPORT) || defined(BCM_APACHE_SUPPORT) 2663 if (soc_feature(unit, soc_feature_mpls_frr_lookup)) { 2664 2665 /* traverse L3_TUNNEL entries */ 2666 tnl_entry_buf = soc_cm_salloc(unit, 2667 SOC_MEM_TABLE_BYTES(unit, L3_TUNNELm), "L3_TUNNEL buffer"); 2668 if (NULL == tnl_entry_buf) { 2669 rv = BCM_E_MEMORY; 2670 goto cleanup; 2671 } 2672 2673 index_min = soc_mem_index_min(unit, L3_TUNNELm); 2674 index_max = soc_mem_index_max(unit, L3_TUNNELm); 2675 rv = soc_mem_read_range(unit, L3_TUNNELm, MEM_BLOCK_ANY, 2676 index_min, index_max, tnl_entry_buf); 2677 if (SOC_FAILURE(rv)) { 2678 goto cleanup; 2679 } 2680 2681 for (i = index_min; i <= index_max; i++) { 2682 tnl_entry = soc_mem_table_idx_to_pointer 2683 (unit, L3_TUNNELm, soc_tunnel_term_t *, tnl_entry_buf, i); 2684 2685 if (!soc_L3_TUNNELm_field32_get (unit, tnl_entry, VALIDf)) { 2686 continue; 2687 } 2688 2689 /* Check for MPLS entry key */ 2690 key_type = soc_L3_TUNNELm_field32_get(unit, tnl_entry, MODEf); 2691 if (key_type != 0x2) { 2692 continue; 2693 } 2694 2695 sal_memset(&info, 0, sizeof(bcm_mpls_tunnel_switch_t)); 2696 rv = _bcm_tr3_mpls_tunnel_switch_frr_entry_key_get (unit, tnl_entry, &info); 2697 if (rv < 0) { 2698 goto cleanup; 2699 } 2700 2701 (void) _bcm_tr3_mpls_tunnel_switch_frr_parse(unit, tnl_entry, &info); 2702 2703 rv = cb(unit, &info, user_data); 2704 #ifdef BCM_CB_ABORT_ON_ERR 2705 if (BCM_FAILURE(rv) && SOC_CB_ABORT_ON_ERR(unit)) { 2706 goto cleanup; 2707 } 2708 #endif 2709 } 2710 } 2711 #endif /* BCM_TOMAHAWK2_SUPPORT || BCM_APACHE_SUPPORT */ 2712 2713 cleanup: 2714 if (mpls_entry_buf) { 2715 soc_cm_sfree(unit, mpls_entry_buf); 2716 } 2717 #if defined(BCM_TOMAHAWK2_SUPPORT) || defined(BCM_APACHE_SUPPORT) 2718 if (tnl_entry_buf) { 2719 soc_cm_sfree(unit, tnl_entry_buf); 2720 } 2721 #endif /* BCM_TOMAHAWK2_SUPPORT || BCM_APACHE_SUPPORT */ 2722 return rv; 2723 } 2724 2725 /*************************************************** 2726 *************************************************** 2727 ****** ****** 2728 ****** Segment Routing Feature Development. ****** 2729 */ 2730 2731 /* 2732 * Function: 2733 * bcmi_egr_ip_tnl_mpls_free_indexes_init 2734 * Purpose: 2735 * Initilize the free indexes. 2736 * Parameters: 2737 * unit - Device Number 2738 * fi - Pointer to free index structure. 2739 * Returns: 2740 * None. 2741 */ 2742 void 2743 bcmi_egr_ip_tnl_mpls_free_indexes_init(int unit, 2744 bcmi_egr_ip_tnl_free_indexes_t *fi) 2745 { 2746 2747 int idx = 0,free_idx = 0; 2748 2749 /* MAX_FREE_ENTRY = */ 2750 for (;idx < MAX_ENTRY_INDEXES; idx++) { 2751 /* MAX FREE ENTRY COUNTING = 8 */ 2752 free_idx=0; 2753 fi->free_index_count[idx]=0; 2754 for (; free_idx<MAX_FREE_ENTRY_INDEXES; free_idx++) { 2755 fi->free_entry_indexes[idx][free_idx] = -1; 2756 } 2757 2758 } 2759 } 2760 2761 /* 2762 * Function: 2763 * bcmi_egr_ip_tnl_mpls_free_indexes_clear 2764 * Purpose: 2765 * clear free indexes structure in tunnel. 2766 * When cleaning the full tunnel entry, 2767 * we also need to free any free entry 2768 * associated with this tunnel. 2769 * Parameters: 2770 * unit - Device Number 2771 * tnl_id - (IN)Tunnel index. 2772 * fi - (IN)Pointer to free index structure. 2773 * Returns: 2774 * None. 2775 */ 2776 2777 void 2778 bcmi_egr_ip_tnl_mpls_free_indexes_clear(int unit, int tnl_id, 2779 bcmi_egr_ip_tnl_free_indexes_t *fi) 2780 { 2781 int idx = 0,free_idx = 0; 2782 int idx_min = tnl_id * _BCM_MPLS_NUM_MPLS_ENTRIES_PER_INDEX(unit); 2783 int idx_max = idx_min + _BCM_MPLS_NUM_MPLS_ENTRIES_PER_INDEX(unit); 2784 int entry_count = 0; 2785 2786 for (idx=0;idx < MAX_ENTRY_INDEXES; idx++) { 2787 /* MAX FREE ENTRY COUNTING = 8 */ 2788 entry_count = fi->free_index_count[idx]; 2789 if (entry_count) { 2790 for (free_idx=0; free_idx<MAX_FREE_ENTRY_INDEXES; free_idx++) { 2791 2792 entry_count = fi->free_index_count[idx]; 2793 if (fi->free_entry_indexes[idx][free_idx] == -1) { 2794 continue; 2795 } 2796 2797 if ((fi->free_entry_indexes[idx][free_idx] >= idx_min) && 2798 (fi->free_entry_indexes[idx][free_idx] < idx_max)) { 2799 2800 2801 if (free_idx == (entry_count - 1)) { 2802 /* This is the last entry in free list. just clean it.*/ 2803 fi->free_entry_indexes[idx][free_idx] = -1; 2804 } else { 2805 fi->free_entry_indexes[idx][free_idx] = 2806 fi->free_entry_indexes[idx][entry_count -1]; 2807 2808 fi->free_entry_indexes[idx][entry_count -1] = -1; 2809 } 2810 fi->free_index_count[idx]--; 2811 free_idx = -1; 2812 } 2813 } 2814 } 2815 } 2816 } 2817 2818 /* 2819 * Function: 2820 * bcmi_egr_ip_tnl_mpls_free_indexes_dump 2821 * Purpose: 2822 * Dump free indexes. 2823 * Parameters: 2824 * unit - Device Number 2825 * fi - Pointer to free index structure. 2826 * Returns: 2827 * None. 2828 */ 2829 void 2830 bcmi_egr_ip_tnl_mpls_free_indexes_dump(int unit, 2831 bcmi_egr_ip_tnl_free_indexes_t *fi) 2832 { 2833 2834 int idx = 0,free_idx = 0; 2835 2836 /* MAX_FREE_ENTRY = */ 2837 for (;idx < MAX_ENTRY_INDEXES; idx++) { 2838 /* MAX FREE ENTRY COUNTING = 8 */ 2839 free_idx=0; 2840 LOG_ERROR(BSL_LS_BCM_L3, 2841 (BSL_META_U(unit, "%s:%d: tnl idx = %d, count = %d \n"), 2842 __FUNCTION__, __LINE__, idx, fi->free_index_count[idx])); 2843 2844 for (; free_idx<MAX_FREE_ENTRY_INDEXES; free_idx++) { 2845 if (fi->free_entry_indexes[idx][free_idx] == -1) { 2846 continue; 2847 } 2848 2849 LOG_CLI((BSL_META_U(unit, "start idx[%d] = %d "), 2850 free_idx, fi->free_entry_indexes[idx][free_idx])); 2851 } 2852 2853 LOG_CLI((BSL_META_U(unit, "\n"))); 2854 } 2855 } 2856 2857 /* 2858 * Function: 2859 * bcmi_egr_ip_tunnel_mpls_sw_cleanup 2860 * Purpose: 2861 * cleanup and deallocate sw state for mpls tunnel. 2862 * Parameters: 2863 * unit - Device Number 2864 * Returns: 2865 * BCM_E_NONE. 2866 */ 2867 int 2868 bcmi_egr_ip_tunnel_mpls_sw_cleanup(int unit) 2869 { 2870 bcmi_egr_ip_tnl_mpls_tunnel_entry_t **tnl_sw_entry; 2871 int num_ip_tnl_mpls; 2872 int i,j; 2873 soc_mem_t mem; 2874 2875 mem = bcmi_egr_ip_tnl_mem_name_get(unit); 2876 2877 num_ip_tnl_mpls = soc_mem_index_count(unit, mem); 2878 2879 tnl_sw_entry = egr_mpls_tnl_sw_state[unit]; 2880 2881 if (tnl_sw_entry == NULL) { 2882 return BCM_E_NONE; 2883 } 2884 2885 for (i=0; i<num_ip_tnl_mpls; i++) { 2886 2887 if (tnl_sw_entry[i] == NULL) { 2888 continue; 2889 } 2890 2891 if (tnl_sw_entry[i]->label_entry == NULL) { 2892 continue; 2893 } 2894 2895 for (j=0; j<_BCM_MPLS_NUM_MPLS_ENTRIES_PER_INDEX(unit); j++) { 2896 2897 if (tnl_sw_entry[i]->label_entry[j] == NULL) { 2898 continue; 2899 } 2900 2901 sal_free(tnl_sw_entry[i]->label_entry[j]); 2902 tnl_sw_entry[i]->label_entry[j] = NULL; 2903 } 2904 2905 sal_free(tnl_sw_entry[i]->label_entry); 2906 tnl_sw_entry[i]->label_entry = NULL; 2907 2908 sal_free(tnl_sw_entry[i]); 2909 tnl_sw_entry[i] = NULL; 2910 } 2911 2912 sal_free(tnl_sw_entry); 2913 tnl_sw_entry = NULL; 2914 2915 return BCM_E_NONE; 2916 } 2917 2918 /* 2919 * Function: 2920 * bcmi_egr_ip_tunnel_mpls_sw_init 2921 * Purpose: 2922 * initialize s/w state for egress mpls tunnel. 2923 * Parameters: 2924 * unit - Device Number 2925 * Returns: 2926 * BCME_XXX. 2927 */ 2928 int 2929 bcmi_egr_ip_tunnel_mpls_sw_init(int unit) 2930 { 2931 int num_ip_tnl_mpls; 2932 int i,j; 2933 int ent_per_tnl = _BCM_MPLS_NUM_MPLS_ENTRIES_PER_INDEX(unit); 2934 soc_mem_t mem; 2935 2936 mem = bcmi_egr_ip_tnl_mem_name_get(unit); 2937 2938 num_ip_tnl_mpls = soc_mem_index_count(unit, mem); 2939 2940 egr_mpls_tnl_sw_state[unit] = (bcmi_egr_ip_tnl_mpls_tunnel_entry_t **) 2941 sal_alloc((num_ip_tnl_mpls * 2942 sizeof(bcmi_egr_ip_tnl_mpls_tunnel_entry_t *)), 2943 "egress mpls tunnel sw state"); 2944 2945 if (egr_mpls_tnl_sw_state[unit] == NULL) { 2946 return BCM_E_MEMORY; 2947 } 2948 sal_memset(egr_mpls_tnl_sw_state[unit], 0, 2949 (num_ip_tnl_mpls * sizeof(bcmi_egr_ip_tnl_mpls_tunnel_entry_t *))); 2950 2951 for (i=0; i<num_ip_tnl_mpls; i++) { 2952 egr_mpls_tnl_sw_state[unit][i] = (bcmi_egr_ip_tnl_mpls_tunnel_entry_t *) 2953 sal_alloc((sizeof(bcmi_egr_ip_tnl_mpls_tunnel_entry_t)), 2954 "egress mpls tunnel entry"); 2955 2956 sal_memset(egr_mpls_tnl_sw_state[unit][i], 0, 2957 sizeof(bcmi_egr_ip_tnl_mpls_tunnel_entry_t)); 2958 2959 if (egr_mpls_tnl_sw_state[unit][i] == NULL) { 2960 bcmi_egr_ip_tunnel_mpls_sw_cleanup(unit); 2961 return BCM_E_MEMORY; 2962 } 2963 2964 egr_mpls_tnl_sw_state[unit][i]->label_entry = 2965 (bcmi_egr_ip_tnl_mpls_label_entry_t **) 2966 sal_alloc((ent_per_tnl * 2967 sizeof(bcmi_egr_ip_tnl_mpls_label_entry_t *)), 2968 "egress mpls tunnel label bucket"); 2969 2970 if (egr_mpls_tnl_sw_state[unit][i]->label_entry == NULL) { 2971 bcmi_egr_ip_tunnel_mpls_sw_cleanup(unit); 2972 return BCM_E_MEMORY; 2973 } 2974 2975 for (j=0; j<_BCM_MPLS_NUM_MPLS_ENTRIES_PER_INDEX(unit); j++) { 2976 egr_mpls_tnl_sw_state[unit][i]->label_entry[j] = 2977 (bcmi_egr_ip_tnl_mpls_label_entry_t *) 2978 sal_alloc((sizeof(bcmi_egr_ip_tnl_mpls_label_entry_t)), 2979 "egress mpls tunnel label entry"); 2980 2981 if (egr_mpls_tnl_sw_state[unit][i]->label_entry[j] == NULL) { 2982 bcmi_egr_ip_tunnel_mpls_sw_cleanup(unit); 2983 return BCM_E_MEMORY; 2984 } 2985 2986 egr_mpls_tnl_sw_state[unit][i]->label_entry[j]->intf_list = NULL; 2987 egr_mpls_tnl_sw_state[unit][i]->label_entry[j]->flags = 0; 2988 egr_mpls_tnl_sw_state[unit][i]->label_entry[j]->num_elements = 0; 2989 } 2990 } 2991 bcmi_egr_ip_tnl_mpls_free_indexes_init(unit, &(fi_db[unit])); 2992 return 0; 2993 } 2994 2995 /* 2996 * Function: 2997 * bcmi_egr_ip_tnl_mpls_tunnel_ref_count_get 2998 * Purpose: 2999 * get the current reference Count 3000 * Parameters: 3001 * unit Unit number 3002 * index (IN) Entry Index 3003 */ 3004 3005 STATIC void 3006 bcmi_egr_ip_tnl_mpls_tunnel_ref_count_get(int unit, int index, int *cnt_value) 3007 { 3008 bcmi_mpls_bookkeeping_t *mpls_info = MPLS_INFO(unit); 3009 3010 *cnt_value = mpls_info->egr_tunnel_ref_count[index]; 3011 } 3012 3013 /* 3014 * Function: 3015 * bcmi_egr_ip_tnl_mpls_ref_count_adjust 3016 * Purpose: 3017 * Increment / Decrement Reference Count for Egress Tunnel 3018 * Parameters: 3019 * unit Unit number 3020 * index (IN) Entry Index 3021 * step (IN) no of references 3022 */ 3023 3024 STATIC void 3025 bcmi_egr_ip_tnl_mpls_ref_count_adjust (int unit, int index, int step) 3026 { 3027 bcmi_mpls_bookkeeping_t *mpls_info = MPLS_INFO(unit); 3028 3029 if (( mpls_info->egr_tunnel_ref_count[index] == 0 ) && (step < 0)) { 3030 mpls_info->egr_tunnel_ref_count[index] = 0; 3031 } else { 3032 mpls_info->egr_tunnel_ref_count[index] += step; 3033 } 3034 3035 } 3036 3037 /* 3038 * Function: 3039 * bcmi_egr_ip_tnl_mpls_ref_count_reset 3040 * Purpose: 3041 * reset the reference Count 3042 * Parameters: 3043 * unit Unit number 3044 * index (IN) Entry Index 3045 */ 3046 3047 STATIC void 3048 bcmi_egr_ip_tnl_mpls_ref_count_reset (int unit, int index) 3049 { 3050 bcmi_mpls_bookkeeping_t *mpls_info = MPLS_INFO(unit); 3051 3052 mpls_info->egr_tunnel_ref_count[index] = 0; 3053 } 3054 3055 /* 3056 * Function: 3057 * bcmi_egr_ip_tnl_mpls_check_dup_free_index 3058 * Purpose: 3059 * check for duplicate free index. 3060 * Parameters: 3061 * unit Unit number 3062 * fi (IN) free index structure. 3063 * free_entry_idx (IN) free index where we should look. 3064 * mpls_tnl_idx (IN) original mpls tnl idx. 3065 * Return 3066 * TRUE/FALSE; 3067 */ 3068 int 3069 bcmi_egr_ip_tnl_mpls_check_dup_free_index(int unit, 3070 bcmi_egr_ip_tnl_free_indexes_t *fi, 3071 int free_entry_num, int mpls_tnl_idx) 3072 { 3073 3074 int free_idx=0; 3075 int ent_idx = free_entry_num - 1; 3076 3077 for (; free_idx < 8; free_idx++) { 3078 if (fi->free_index_count[ent_idx]) { 3079 if (fi->free_entry_indexes[ent_idx][free_idx] == -1) { 3080 break; 3081 } 3082 if (fi->free_entry_indexes[ent_idx][free_idx] == mpls_tnl_idx) { 3083 return TRUE; 3084 } 3085 3086 } 3087 } 3088 return FALSE; 3089 } 3090 3091 /* 3092 * Function: 3093 * bcmi_egr_ip_tnl_mpls_free_idx_update 3094 * Purpose: 3095 * check for duplicate free index. 3096 * Parameters: 3097 * unit Unit number 3098 * fi (IN) free index structure. 3099 * free_entries (IN) no of free entries. 3100 * start_index (IN) start index. 3101 * Return 3102 * TRUE/FALSE; 3103 */ 3104 void 3105 bcmi_egr_ip_tnl_mpls_free_idx_update(int unit, int free_entries, 3106 int start_index, bcmi_egr_ip_tnl_free_indexes_t *fi) 3107 { 3108 int free_entry_count; 3109 3110 if (!(bcmi_egr_ip_tnl_mpls_check_dup_free_index(unit, 3111 fi, free_entries, start_index))) { 3112 3113 if (fi->free_index_count[free_entries-1] < MAX_FREE_ENTRY_INDEXES) { 3114 free_entry_count = fi->free_index_count[free_entries-1]; 3115 fi->free_entry_indexes[free_entries-1][free_entry_count] = start_index; 3116 fi->free_index_count[free_entries-1]++; 3117 } 3118 } 3119 } 3120 3121 /* 3122 * Function: 3123 * bcm_egr_ip_tnl_mpls_remark_free_indexes 3124 * Purpose: 3125 * Mark correct free indexes for mpls tunnel entries. 3126 * Parameters: 3127 * unit - Device Number 3128 * free_entries - number of free entries 3129 * start_index - Start index of tunnel entry 3130 * fi - free indexes database pointer. 3131 * Returns: 3132 * BCM_E_XXX 3133 */ 3134 bcm_error_t 3135 bcm_egr_ip_tnl_mpls_remark_free_indexes(int unit, int free_entries, 3136 int start_index, bcmi_egr_ip_tnl_free_indexes_t *fi) 3137 { 3138 int temp_free_entries; 3139 int ent_per_tnl = _BCM_MPLS_NUM_MPLS_ENTRIES_PER_INDEX(unit); 3140 3141 if (free_entries == 0) { 3142 return BCM_E_NONE; 3143 } 3144 if (start_index == -1) { 3145 return BCM_E_NONE; 3146 } 3147 3148 /* 3149 * if start index is 0, then any entry can be put there. 3150 * if start index is 4, then only 3 and 4 number of entries 3151 * can be put there. 3152 */ 3153 if (((start_index % ent_per_tnl) == 0) || 3154 (((start_index % 3155 (ent_per_tnl / 2)) == 0) && 3156 ((free_entries > 2) && free_entries < 5))) { 3157 3158 bcmi_egr_ip_tnl_mpls_free_idx_update(unit, free_entries, 3159 start_index, fi); 3160 } else { 3161 if ((free_entries >= 4) 3162 && ((((start_index + free_entries) % ent_per_tnl) == 0))) { 3163 3164 /* 3165 * the entry is free till end and has more 3166 * than 4 consecutive spaces then 3167 * break them into smaller and take 3168 * 4 spaces into single big entry. 3169 */ 3170 temp_free_entries = free_entries - 4; 3171 while(temp_free_entries > 0) { 3172 if (temp_free_entries == 1) { 3173 bcmi_egr_ip_tnl_mpls_free_idx_update(unit, 1, 3174 start_index, fi); 3175 3176 start_index++; 3177 temp_free_entries--; 3178 } else if (temp_free_entries >= 2) { 3179 3180 bcmi_egr_ip_tnl_mpls_free_idx_update(unit, 2, 3181 start_index, fi); 3182 3183 start_index +=2; 3184 temp_free_entries-=2; 3185 } 3186 } 3187 if (!(bcmi_egr_ip_tnl_mpls_check_dup_free_index(unit, 3188 fi, 4, start_index))) { 3189 3190 bcmi_egr_ip_tnl_mpls_free_idx_update(unit, 4, start_index, fi); 3191 start_index +=4; 3192 temp_free_entries-=4; 3193 } 3194 } else if ((free_entries >= 3) && 3195 ((((start_index + free_entries) % ent_per_tnl) == 7))) { 3196 /* 3197 * the entry is free till second last and has more 3198 * than 3 consecutive spaces then break them into smaller 3199 * and take 3 spaces into single big entry. 3200 */ 3201 temp_free_entries = free_entries - 3; 3202 while(temp_free_entries > 0) { 3203 if (temp_free_entries == 1) { 3204 bcmi_egr_ip_tnl_mpls_free_idx_update(unit, 1, 3205 start_index, fi); 3206 3207 start_index++; 3208 temp_free_entries--; 3209 } else if (temp_free_entries >= 2) { 3210 bcmi_egr_ip_tnl_mpls_free_idx_update(unit, 2, 3211 start_index, fi); 3212 3213 start_index +=2; 3214 temp_free_entries-=2; 3215 } 3216 } 3217 bcmi_egr_ip_tnl_mpls_free_idx_update(unit, 3, start_index, fi); 3218 start_index +=3; 3219 temp_free_entries-=3; 3220 } else { 3221 temp_free_entries = free_entries; 3222 while(temp_free_entries > 0) { 3223 if (temp_free_entries == 1) { 3224 bcmi_egr_ip_tnl_mpls_free_idx_update(unit, 1, 3225 start_index, fi); 3226 3227 start_index++; 3228 temp_free_entries--; 3229 } else if (temp_free_entries >= 2) { 3230 bcmi_egr_ip_tnl_mpls_free_idx_update(unit, 2, 3231 start_index, fi); 3232 3233 start_index +=2; 3234 temp_free_entries-=2; 3235 } 3236 } 3237 } 3238 } 3239 return BCM_E_NONE; 3240 } 3241 3242 /* 3243 * Function: 3244 * bcm_egr_ip_tnl_mpls_move_entries 3245 * Purpose: 3246 * Move enties to create space for other entry. 3247 * Parameters: 3248 * unit - Device Number 3249 * src_tnl_index - Tunnel start index. 3250 * src_entry_offset - Mpls entry offset. 3251 * dst_free_mpls_idx - Dest mpls tunnel entry index. 3252 * no_of_elements - Number of elements to move. 3253 * Returns: 3254 * BCM_E_XXX 3255 */ 3256 bcm_error_t 3257 bcm_egr_ip_tnl_mpls_move_entries(int unit, 3258 bcmi_egr_ip_tnl_mpls_tunnel_entry_t **tnl_sw_entry, 3259 int src_tnl_index, int src_entry_offset, 3260 int dst_free_mpls_idx, int no_of_elements) 3261 { 3262 3263 int dst_offset; 3264 int src_offset; 3265 int i = 0; 3266 int ent_per_tnl = _BCM_MPLS_NUM_MPLS_ENTRIES_PER_INDEX(unit); 3267 int src_tnl_mpls_idx, dst_tnl_index; 3268 int ref_count; 3269 int rv; 3270 uint32 l3_max_entry[SOC_MAX_MEM_WORDS]; /* Buffer to write interface info. */ 3271 uint32 *l3_if_entry_p; /* Write buffer address. */ 3272 soc_mem_t mem; /* Interface table memory. */ 3273 intf_list_t *intf_list = NULL; 3274 uint32 src_tnl_entry[SOC_MAX_MEM_WORDS]; 3275 uint32 dst_tnl_entry[SOC_MAX_MEM_WORDS]; 3276 uint32 src_buf[3] = {0}; 3277 3278 bcmi_egr_ip_tnl_mpls_table_memset(unit, src_tnl_entry); 3279 bcmi_egr_ip_tnl_mpls_table_memset(unit, dst_tnl_entry); 3280 3281 /* Get interface table memory. */ 3282 mem = BCM_XGS3_L3_MEM(unit, intf); 3283 3284 /* Zero the buffer. */ 3285 l3_if_entry_p = (uint32 *)&l3_max_entry; 3286 3287 /* Compute offsets */ 3288 src_offset = src_entry_offset; 3289 dst_offset = dst_free_mpls_idx % ent_per_tnl; 3290 dst_tnl_index = dst_free_mpls_idx / ent_per_tnl; 3291 3292 /*Read src_tnl_entry*/ 3293 bcmi_egr_ip_tnl_mpls_table_read(unit, src_tnl_index, src_tnl_entry); 3294 3295 /*Read dst_entry*/ 3296 bcmi_egr_ip_tnl_mpls_table_read(unit, dst_tnl_index, dst_tnl_entry); 3297 3298 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 3299 for (; i < no_of_elements; i++) { 3300 /*Get Label,Pushaction,expselect,exp,pri,cfi,expptr,ttl into src_buf 3301 *and write src_buf into dst_entry_double.*/ 3302 bcmi_egress_tnl_label_entry_get(unit , src_tnl_entry, 3303 src_offset+i, src_buf); 3304 bcmi_egress_tnl_label_entry_set(unit , dst_tnl_entry, 3305 dst_offset+i, src_buf); 3306 } 3307 } else { 3308 bcmi_egr_ip_tnl_copy_src_label_info_to_dest(unit, src_tnl_entry, 3309 dst_tnl_entry, src_offset, dst_offset, no_of_elements); 3310 } 3311 3312 rv = bcmi_egr_ip_tnl_mpls_table_write(unit, dst_tnl_index, dst_tnl_entry); 3313 3314 if (rv == BCM_E_NONE) { 3315 src_tnl_mpls_idx = (src_tnl_index * ent_per_tnl) + src_entry_offset; 3316 for (i=0; i < no_of_elements; i++) { 3317 _BCM_MPLS_TNL_USED_SET(unit, dst_free_mpls_idx + i); 3318 _BCM_MPLS_TNL_USED_CLR(unit, src_tnl_mpls_idx + i); 3319 } 3320 /* get the moved entry's original ref counter number */ 3321 bcmi_egr_ip_tnl_mpls_tunnel_ref_count_get (unit, 3322 src_tnl_mpls_idx, &ref_count); 3323 bcmi_egr_ip_tnl_mpls_ref_count_reset (unit, src_tnl_mpls_idx); 3324 bcmi_egr_ip_tnl_mpls_ref_count_adjust (unit, 3325 dst_free_mpls_idx, ref_count); 3326 3327 /* 3328 * Now change tunnel index in L3 interface entry. 3329 */ 3330 intf_list = tnl_sw_entry[src_tnl_index]->label_entry[src_entry_offset]->intf_list; 3331 3332 while (intf_list) { 3333 sal_memset(l3_if_entry_p, 0, BCM_XGS3_L3_ENT_SZ(unit, intf)); 3334 BCM_IF_ERROR_RETURN( 3335 BCM_XGS3_MEM_READ(unit, mem, intf_list->intf_num, l3_if_entry_p)); 3336 3337 soc_mem_field32_set(unit, mem, l3_if_entry_p, 3338 MPLS_TUNNEL_INDEXf, dst_free_mpls_idx); 3339 3340 rv = soc_mem_write(unit, mem, MEM_BLOCK_ANY, intf_list->intf_num, l3_if_entry_p); 3341 3342 if (BCM_FAILURE(rv)) { 3343 return rv; 3344 } 3345 intf_list = intf_list->next; 3346 } 3347 3348 } 3349 3350 return BCM_E_NONE; 3351 } 3352 3353 /* 3354 * Function: 3355 * bcmi_egr_ip_tnl_mpls_intf_list_alloc 3356 * Purpose: 3357 * Allocates link memory and sets interface chain. 3358 * Parameters: 3359 * intf_num - interface number 3360 * Returns: 3361 * pointer to allocated link memory 3362 */ 3363 intf_list_t * 3364 bcmi_egr_ip_tnl_mpls_intf_list_alloc(bcm_if_t intf_num) 3365 { 3366 intf_list_t *ptr; 3367 3368 ptr = (intf_list_t *) sal_alloc(sizeof(intf_list_t), "egr mpls tnl sw intf list"); 3369 sal_memset(ptr, 0, sizeof(intf_list_t)); 3370 3371 ptr->intf_num = intf_num; 3372 ptr->next = NULL; 3373 3374 return ptr; 3375 } 3376 3377 /* 3378 * Function: 3379 * bcmi_egr_ip_tnl_mpls_intf_list_dump 3380 * Purpose: 3381 * Dumps interface chain. 3382 * Parameters: 3383 * unit - device number 3384 * tnl_sw_entry - pointer to tunnel database. 3385 * intf_num - interface number 3386 * tnl_idx - Tunnel Index 3387 * mpls_offset - mpls entry offset in tunnel 3388 * Returns: 3389 * None. 3390 */ 3391 void 3392 bcmi_egr_ip_tnl_mpls_intf_list_dump(int unit, 3393 bcmi_egr_ip_tnl_mpls_tunnel_entry_t **tnl_sw_entry, 3394 bcm_if_t intf_num, int tnl_idx, int mpls_offset) 3395 { 3396 3397 intf_list_t *temp; 3398 3399 temp = tnl_sw_entry[tnl_idx]->label_entry[mpls_offset]->intf_list; 3400 3401 while (temp) { 3402 LOG_ERROR(BSL_LS_BCM_L3, 3403 (BSL_META_U(unit, "intf index = %d, tnl_idx = %d, mpls_off = %d\n"), 3404 temp->intf_num, tnl_idx, mpls_offset)); 3405 3406 temp = temp->next; 3407 } 3408 } 3409 3410 /* 3411 * Function: 3412 * bcmi_egr_ip_tnl_mpls_intf_list_add 3413 * Purpose: 3414 * Adds interface chain at a mpls entry index. 3415 * Parameters: 3416 * unit - device number 3417 * tnl_sw_entry - pointer to tunnel database. 3418 * intf_id - interface number 3419 * tnl_idx - Tunnel Index 3420 * mpls_offset - mpls entry offset in tunnel 3421 * Returns: 3422 * bcm_error_t 3423 */ 3424 bcm_error_t 3425 bcmi_egr_ip_tnl_mpls_intf_list_add(int unit, 3426 bcmi_egr_ip_tnl_mpls_tunnel_entry_t **tnl_sw_entry, 3427 bcm_if_t intf_id, int tnl_idx, int mpls_offset) 3428 { 3429 3430 intf_list_t *ptr, *temp, *prev; 3431 3432 temp = tnl_sw_entry[tnl_idx]->label_entry[mpls_offset]->intf_list; 3433 prev = temp; 3434 while (temp) { 3435 if (temp->intf_num == intf_id) { 3436 /* 3437 * We already have this interface at this index. 3438 * this is just a negative case test if 3439 * someone tries to send same entry at same intf. 3440 */ 3441 return BCM_E_NONE; 3442 } 3443 prev = temp; 3444 temp = temp->next; 3445 } 3446 3447 ptr = bcmi_egr_ip_tnl_mpls_intf_list_alloc(intf_id); 3448 3449 if (ptr == NULL) { 3450 return BCM_E_MEMORY; 3451 } 3452 3453 if(temp == prev) { 3454 tnl_sw_entry[tnl_idx]->label_entry[mpls_offset]->intf_list = ptr; 3455 } else { 3456 prev->next = ptr; 3457 } 3458 return BCM_E_NONE; 3459 } 3460 3461 /* 3462 * Function: 3463 * bcmi_egr_ip_tnl_mpls_intf_list_delete 3464 * Purpose: 3465 * Deletes interface chain matching to a 3466 * particular interface number. 3467 * Parameters: 3468 * unit - device number 3469 * tnl_sw_entry - pointer to tunnel database. 3470 * intf_num - interface number 3471 * tnl_idx - Tunnel Index 3472 * mpls_offset - mpls entry offset in tunnel 3473 * Returns: 3474 * bcm_error_t 3475 */ 3476 bcm_error_t 3477 bcmi_egr_ip_tnl_mpls_intf_list_delete(int unit, bcmi_egr_ip_tnl_mpls_tunnel_entry_t **tnl_sw_entry, 3478 bcm_if_t intf_num, int tnl_idx, int mpls_offset) 3479 { 3480 3481 intf_list_t *temp_ptr, *prev_ptr; 3482 3483 if(tnl_sw_entry[tnl_idx]->label_entry[mpls_offset]->intf_list == NULL) { 3484 /* why we are here. this is not possible */ 3485 return BCM_E_INTERNAL; 3486 } 3487 3488 temp_ptr = tnl_sw_entry[tnl_idx]->label_entry[mpls_offset]->intf_list; 3489 prev_ptr = temp_ptr; 3490 3491 while ((temp_ptr) && ((temp_ptr->intf_num) != intf_num)) { 3492 prev_ptr = temp_ptr; 3493 temp_ptr = temp_ptr->next; 3494 } 3495 3496 if (temp_ptr) { 3497 if (temp_ptr == prev_ptr) { 3498 tnl_sw_entry[tnl_idx]->label_entry[mpls_offset]->intf_list = temp_ptr->next; 3499 } else { 3500 prev_ptr->next = temp_ptr->next; 3501 } 3502 3503 sal_free(temp_ptr); 3504 } else { 3505 return BCM_E_NOT_FOUND; 3506 } 3507 return BCM_E_NONE; 3508 } 3509 3510 /* 3511 * Function: 3512 * bcmi_egr_ip_tnl_mpls_intf_list_delete_all 3513 * Purpose: 3514 * Deletes all nodex of Interface chain at that mpls 3515 * entry index. 3516 * Parameters: 3517 * unit - device number 3518 * tnl_sw_entry - pointer to tunnel database. 3519 * intf_num - interface number 3520 * tnl_idx - Tunnel Index 3521 * mpls_offset - mpls entry offset in tunnel 3522 * Returns: 3523 * bcm_error_t 3524 */ 3525 3526 void 3527 bcmi_egr_ip_tnl_mpls_intf_list_delete_all(int unit, 3528 bcmi_egr_ip_tnl_mpls_tunnel_entry_t **tnl_sw_entry, 3529 int tnl_idx, int mpls_offset) 3530 { 3531 3532 intf_list_t *temp_ptr; 3533 3534 temp_ptr = tnl_sw_entry[tnl_idx]->label_entry[mpls_offset]->intf_list; 3535 3536 while (temp_ptr) { 3537 tnl_sw_entry[tnl_idx]->label_entry[mpls_offset]->intf_list = 3538 temp_ptr->next; 3539 3540 sal_free(temp_ptr); 3541 temp_ptr = tnl_sw_entry[tnl_idx]->label_entry[mpls_offset]->intf_list; 3542 } 3543 } 3544 3545 #if 0 3546 void 3547 bcmi_egr_ip_tnl_mpls_intf_list_copy(int unit, 3548 bcmi_egr_ip_tnl_mpls_tunnel_entry_t **tnl_sw_entry, 3549 int dst_tnl_idx, int dst_mpls_offset, 3550 int tnl_idx, int mpls_offset) 3551 { 3552 3553 3554 /* we can just change the pointer and whole list can be picked from there */ 3555 tnl_sw_entry[dst_tnl_idx]->label_entry[dst_mpls_offset]->intf_list = 3556 tnl_sw_entry[tnl_idx]->label_entry[mpls_offset]->intf_list; 3557 3558 tnl_sw_entry[tnl_idx]->label_entry[mpls_offset]->intf_list = NULL; 3559 } 3560 #endif 3561 3562 /* 3563 * Function: 3564 * bcm_egr_ip_tnl_mpls_sw_entry_reset 3565 * Purpose: 3566 * Dumps interface chain. 3567 * Parameters: 3568 * unit - device number 3569 * tnl_sw_entry - pointer to tunnel database. 3570 * tnl_idx - Tunnel Index 3571 * mpls_offset - mpls entry offset in tunnel 3572 * clean_list _ flag to decide whether to clean interface list. 3573 * Returns: 3574 * bcm_error_t 3575 */ 3576 3577 3578 void bcm_egr_ip_tnl_mpls_sw_entry_reset(int unit, 3579 bcmi_egr_ip_tnl_mpls_tunnel_entry_t **tnl_sw_entry, 3580 int tnl_idx, int mpls_offset, int clean_list) 3581 { 3582 3583 if (clean_list) { 3584 tnl_sw_entry[tnl_idx]->label_entry[mpls_offset]->intf_list = NULL; 3585 } 3586 tnl_sw_entry[tnl_idx]->label_entry[mpls_offset]->flags = 0; 3587 tnl_sw_entry[tnl_idx]->label_entry[mpls_offset]->num_elements = 0; 3588 } 3589 3590 /* 3591 * Function: 3592 * bcmi_mpls_egr_tunnel_delete_free_indexes 3593 * Purpose: 3594 * Delete free index entry from free indexes if the entry is used up. 3595 * Parameters: 3596 * unit - device number 3597 * fi - Pointer to free indexes database. 3598 * num_labels - Number of labels that entry contains. 3599 * mpls_entry_idx - index to mpls entry index that is used up. 3600 * Returns: 3601 * None. 3602 */ 3603 void 3604 bcmi_mpls_egr_tunnel_delete_free_indexes(int unit, 3605 bcmi_egr_ip_tnl_free_indexes_t *fi, 3606 int num_labels, int mpls_entry_idx) 3607 { 3608 int idx=0,free_idx=0; 3609 int entry_count = 0; 3610 int idx_min=0, idx_max=0; 3611 3612 3613 idx_min = mpls_entry_idx; 3614 idx_max = mpls_entry_idx + num_labels; 3615 3616 if ((num_labels <= 0) || (num_labels > 8)) { 3617 return; 3618 } 3619 3620 for (; idx<MAX_ENTRY_INDEXES; idx++) { 3621 3622 if (!(fi->free_index_count[idx])) { 3623 continue; 3624 } 3625 3626 for (free_idx=0; free_idx<MAX_FREE_ENTRY_INDEXES; free_idx++) { 3627 /* need to keep it here as we are chaning counts for next run. */ 3628 entry_count = fi->free_index_count[idx]; 3629 3630 if (fi->free_entry_indexes[idx][free_idx] == -1) { 3631 break; 3632 } 3633 3634 if ((fi->free_entry_indexes[idx][free_idx] >= idx_min) && 3635 (fi->free_entry_indexes[idx][free_idx] < idx_max)) { 3636 /* free this space */ 3637 if (free_idx == (entry_count - 1)) { 3638 fi->free_entry_indexes[idx][free_idx] = -1; 3639 } else { 3640 fi->free_entry_indexes[idx][free_idx] = 3641 fi->free_entry_indexes[idx][entry_count-1]; 3642 fi->free_entry_indexes[idx][entry_count-1] = -1; 3643 /* 3644 * We should check free_idx from start again here. 3645 * as some matching index may have come to this slot. 3646 */ 3647 free_idx = -1; 3648 } 3649 fi->free_index_count[idx]--; 3650 } 3651 } 3652 } 3653 } 3654 3655 /* 3656 * Function: 3657 * bcmi_egr_ip_tnl_mpls_move_tunnel_entries 3658 * Purpose: 3659 * Once we identify that this is the tunnel index that can create 3660 * space for our new entry, we try to move the mple tunnel entries 3661 * from that tunnel index. 3662 * Parameters: 3663 * unit - (IN)device number 3664 * fi - (IN)Pointer to free indexes database. 3665 * tunnel_entry - (IN)Number of labels that entry contains. 3666 * idx - (IN)index to mpls entry index that is used up. 3667 * num_labels - (IN)Number of labels for which free space is made. 3668 * mpls_tnl_idx - (IN)mpls offset from where entry needs to be moved. 3669 * Returns: 3670 * None. 3671 */ 3672 int 3673 bcmi_egr_ip_tnl_mpls_move_tunnel_entries(int unit, 3674 bcmi_egr_ip_tnl_free_indexes_t *fi, 3675 bcmi_egr_ip_tnl_mpls_tunnel_entry_t **tunnel_entry, 3676 int src_tnl_idx, int src_mpls_tnl_off, int num_labels) 3677 { 3678 int ent_per_idx = _BCM_MPLS_NUM_MPLS_ENTRIES_PER_INDEX(unit); 3679 int temp_num_labels = num_labels; 3680 int left_free_entries = 0; 3681 int found = 0; 3682 int rv = BCM_E_NONE; 3683 int mpls_index = 0; 3684 int mpls_off = 0; 3685 int no_of_elements = 0; 3686 int f_idx, free_idx; 3687 int new_start_index; 3688 int chk_tnl_idx, chk_mpls_idx; 3689 bcmi_egr_ip_tnl_mpls_label_entry_t *label_entry; 3690 bcmi_egr_ip_tnl_mpls_label_entry_t *src_label_entry; 3691 int free_db_entries = 0; 3692 int total_free_entries = 0; 3693 3694 3695 mpls_index = (src_tnl_idx * _BCM_MPLS_NUM_MPLS_ENTRIES_PER_INDEX(unit)); 3696 /* check for entry free */ 3697 for(mpls_off=src_mpls_tnl_off; mpls_off < ent_per_idx; mpls_off++) { 3698 found = 0; 3699 3700 if (!_BCM_MPLS_TNL_USED_GET(unit, (mpls_index + mpls_off))) { 3701 temp_num_labels--; 3702 free_db_entries++; 3703 total_free_entries++; 3704 continue; 3705 } 3706 3707 /* If we are looking at same index as free index. then continue. */ 3708 if (free_db_entries) { 3709 bcmi_mpls_egr_tunnel_delete_free_indexes(unit, 3710 fi, free_db_entries, (mpls_index + mpls_off - free_db_entries)); 3711 } 3712 free_db_entries = 0; 3713 src_label_entry = tunnel_entry[src_tnl_idx]->label_entry[mpls_off]; 3714 if(src_label_entry->flags 3715 & BCMI_EGR_IP_TUNNEL_MPLS_START_OF_ENTRY) { 3716 /* this is the start of this entry, 3717 * we should check if we have some free space for this entry 3718 */ 3719 no_of_elements = src_label_entry->num_elements; 3720 3721 /* we also should check if there are some bigger entries in this 3722 * tunnel entry, big entries can be adjusted to other big entries 3723 * if exists. 3724 * else we might have to move smaller entries to bigger entries. 3725 */ 3726 for (f_idx=no_of_elements-1; f_idx < 8; f_idx++) { 3727 3728 if (fi->free_index_count[f_idx] == 0) { 3729 continue; 3730 } 3731 3732 for (free_idx=0; free_idx<8; free_idx++) { 3733 /* There is some empty place here. 3734 * lets use the same size entry or bigger. 3735 * returning the first free entry in that block. 3736 */ 3737 if (fi->free_entry_indexes[f_idx][free_idx] == -1) { 3738 break; 3739 } 3740 chk_tnl_idx = fi->free_entry_indexes[f_idx][free_idx] / 3741 _BCM_MPLS_NUM_MPLS_ENTRIES_PER_INDEX(unit); 3742 3743 chk_mpls_idx = fi->free_entry_indexes[f_idx][free_idx] % 3744 _BCM_MPLS_NUM_MPLS_ENTRIES_PER_INDEX(unit); 3745 3746 label_entry = 3747 tunnel_entry[chk_tnl_idx]->label_entry[chk_mpls_idx]; 3748 if (!(label_entry->flags & 3749 BCMI_EGR_IP_TUNNEL_MPLS_ENTRY_CHECKED)) { 3750 3751 /* 3752 * we can use free_entry_indexes[idx][free_idx]; 3753 * mark this entry used so that next lookup should 3754 * not use this. 3755 */ 3756 label_entry->flags |= 3757 BCMI_EGR_IP_TUNNEL_MPLS_ENTRY_CHECKED; 3758 found = 1; 3759 rv = bcm_egr_ip_tnl_mpls_move_entries(unit, 3760 tunnel_entry, src_tnl_idx, mpls_off, 3761 fi->free_entry_indexes[f_idx][free_idx], 3762 no_of_elements); 3763 3764 if (rv == BCM_E_NONE) { 3765 /* movement is successful */ 3766 label_entry->flags |= 3767 BCMI_EGR_IP_TUNNEL_MPLS_START_OF_ENTRY; 3768 label_entry->num_elements = no_of_elements; 3769 /* now copy interfaces. 3770 * even if we are keeping pointer here for linked list, 3771 * we can assign the same pointer to the new list. 3772 */ 3773 label_entry->intf_list = src_label_entry->intf_list; 3774 bcm_egr_ip_tnl_mpls_sw_entry_reset(unit, tunnel_entry, 3775 src_tnl_idx, mpls_off, 1); 3776 } else { 3777 return rv; 3778 } 3779 3780 temp_num_labels -= no_of_elements; 3781 /* mpls_off will also get incremented in this loop. */ 3782 mpls_off += (no_of_elements - 1); 3783 new_start_index = 3784 fi->free_entry_indexes[f_idx][free_idx] + 3785 no_of_elements; 3786 3787 bcmi_mpls_egr_tunnel_delete_free_indexes(unit, fi, 3788 no_of_elements, 3789 fi->free_entry_indexes[f_idx][free_idx]); 3790 3791 left_free_entries = (f_idx+1)-no_of_elements; 3792 total_free_entries += no_of_elements; 3793 bcm_egr_ip_tnl_mpls_remark_free_indexes(unit, 3794 left_free_entries, new_start_index, fi); 3795 3796 break; 3797 } 3798 } 3799 if (found) { 3800 /*break from loop so that we can check next entry*/ 3801 break; 3802 } 3803 } 3804 if (!found) { 3805 temp_num_labels = num_labels; 3806 } 3807 } 3808 if (temp_num_labels <= 0) { 3809 3810 /* we have moved all the entries to some other space. 3811 * we have this space free now. 3812 */ 3813 bcm_egr_ip_tnl_mpls_remark_free_indexes(unit, 3814 (total_free_entries - num_labels), 3815 ((src_tnl_idx*ent_per_idx) + src_mpls_tnl_off + num_labels), fi); 3816 3817 return BCM_E_NONE; 3818 } 3819 } 3820 /* We cant not free any entry here. so return BCM_E_FULL */ 3821 return BCM_E_FULL; 3822 } 3823 3824 /* 3825 * Function: 3826 * bcmi_xgs5_mpls_egr_tunnel_lookup 3827 * Purpose: 3828 * loopup matching entry into EGR_IP_TUNNEL_MPLS 3829 * Parameters: 3830 * IN : Unit 3831 * IN : push_action 3832 * IN : label_array 3833 * OUT : match_mpls_tunnel_index 3834 * Returns: 3835 * BCM_E_XXX 3836 */ 3837 3838 STATIC int 3839 bcmi_xgs5_mpls_egr_tunnel_lookup (int unit, int push_action, 3840 bcmi_egr_ip_tnl_mpls_tunnel_entry_t **tunnel_entry, 3841 bcm_mpls_egress_label_t *label_array, 3842 int *match_mpls_tunnel_index) 3843 { 3844 int rv = BCM_E_NONE; 3845 uint32 label_value; 3846 uint32 entry_ttl, entry_exp, entry_push_action; 3847 int num_ip_tnl_mpls; 3848 int i = 0, j = 0, tnl_index = -1, mpls_index = -1; 3849 int temp_push_action = 0; 3850 int offset; 3851 soc_mem_t mem; 3852 uint32 tnl_entry[SOC_MAX_MEM_WORDS]; 3853 uint32 iptun_mpls_entry_format[3] = {0}; 3854 3855 mem = bcmi_egr_ip_tnl_mem_name_get(unit); 3856 num_ip_tnl_mpls = soc_mem_index_count(unit, mem); 3857 3858 /* parameter checking */ 3859 if (push_action != 0 && label_array == NULL) { 3860 return BCM_E_PARAM; 3861 } 3862 3863 for (tnl_index = 0; tnl_index < num_ip_tnl_mpls; tnl_index++) { 3864 if (!_BCM_MPLS_IP_TNL_USED_GET(unit, tnl_index)) { 3865 continue; 3866 } 3867 3868 mpls_index = tnl_index * _BCM_MPLS_NUM_MPLS_ENTRIES_PER_INDEX(unit); 3869 3870 for (i = 0; i < _BCM_MPLS_NUM_MPLS_ENTRIES_PER_INDEX(unit); i++) { 3871 if (!(tunnel_entry[tnl_index]->label_entry[i]->flags & 3872 BCMI_EGR_IP_TUNNEL_MPLS_START_OF_ENTRY)) { 3873 continue; 3874 } 3875 if (!push_action) { 3876 if ((tunnel_entry[tnl_index]->label_entry[i]->flags & 3877 BCMI_EGR_IP_TUNNEL_MPLS_ENTRY_ZERO)) { 3878 *match_mpls_tunnel_index = (tnl_index * 3879 _BCM_MPLS_NUM_MPLS_ENTRIES_PER_INDEX(unit)) + i; 3880 } 3881 return BCM_E_NONE; 3882 } 3883 3884 if (!(tunnel_entry[tnl_index]->label_entry[i]->num_elements == 3885 push_action)) { 3886 continue; 3887 } 3888 3889 rv = bcmi_egr_ip_tnl_mpls_table_read(unit, tnl_index, tnl_entry); 3890 if (rv < 0) { 3891 return rv; 3892 } 3893 3894 if (push_action > 1) { 3895 j = 0; 3896 temp_push_action = push_action; 3897 3898 while (temp_push_action > 1) { 3899 if (!(_BCM_MPLS_TNL_USED_GET(unit, mpls_index + i + j))) { 3900 break; 3901 } 3902 3903 3904 offset = (i+j); 3905 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 3906 bcmi_egress_tnl_label_entry_get(unit, tnl_entry, 3907 offset, iptun_mpls_entry_format); 3908 } 3909 3910 bcmi_egr_ip_tnl_mpls_entry_format_get(unit, 3911 tnl_entry, offset, 3912 iptun_mpls_entry_format, bcmiMplsLabel, 3913 &label_value); 3914 3915 bcmi_egr_ip_tnl_mpls_entry_format_get(unit, 3916 tnl_entry, offset, 3917 iptun_mpls_entry_format, bcmiMplsTtl, 3918 &entry_ttl); 3919 3920 bcmi_egr_ip_tnl_mpls_entry_format_get(unit, 3921 tnl_entry, offset, 3922 iptun_mpls_entry_format, bcmiMplsExp, 3923 &entry_exp); 3924 3925 bcmi_egr_ip_tnl_mpls_entry_format_get(unit, 3926 tnl_entry, offset, 3927 iptun_mpls_entry_format, bcmiMplsPushAction, 3928 &entry_push_action); 3929 /* 3930 * entry_push_action should be 2 as next entry will also 3931 * be checked with this entry. 3932 */ 3933 if ((label_array[j].label == label_value) && 3934 (label_array[j].ttl == entry_ttl) && 3935 (label_array[j].exp == entry_exp) && 3936 (entry_push_action == 2)) { 3937 /* Do nothing. This is good case so continue */ 3938 temp_push_action--; 3939 } else { 3940 /* we are not getting matching entry here */ 3941 break; 3942 } 3943 j++; 3944 } 3945 3946 offset = (i+j); 3947 3948 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 3949 sal_memset(&iptun_mpls_entry_format, 0, 3950 sizeof(iptun_mpls_entry_format)); 3951 3952 bcmi_egress_tnl_label_entry_get(unit, tnl_entry, 3953 offset, iptun_mpls_entry_format); 3954 } 3955 3956 bcmi_egr_ip_tnl_mpls_entry_format_get(unit, 3957 tnl_entry, offset, 3958 iptun_mpls_entry_format, bcmiMplsLabel, 3959 &label_value); 3960 3961 bcmi_egr_ip_tnl_mpls_entry_format_get(unit, 3962 tnl_entry, offset, 3963 iptun_mpls_entry_format, bcmiMplsTtl, 3964 &entry_ttl); 3965 3966 bcmi_egr_ip_tnl_mpls_entry_format_get(unit, 3967 tnl_entry, offset, 3968 iptun_mpls_entry_format, bcmiMplsExp, 3969 &entry_exp); 3970 3971 bcmi_egr_ip_tnl_mpls_entry_format_get(unit, 3972 tnl_entry, offset, 3973 iptun_mpls_entry_format, bcmiMplsPushAction, 3974 &entry_push_action); 3975 /* 3976 * This is the last entry in the chain, therefore 3977 * entry push actions should be 1. 3978 */ 3979 if ((label_array[j].label == label_value) && 3980 (label_array[j].ttl == entry_ttl) && 3981 (label_array[j].exp == entry_exp) && 3982 (entry_push_action == 1)) { 3983 3984 *match_mpls_tunnel_index = (tnl_index * 3985 _BCM_MPLS_NUM_MPLS_ENTRIES_PER_INDEX(unit)) + i; 3986 return BCM_E_NONE; 3987 } 3988 3989 } else if (push_action == 0x1) { 3990 3991 offset = i; 3992 3993 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 3994 bcmi_egress_tnl_label_entry_get(unit, tnl_entry, 3995 offset, iptun_mpls_entry_format); 3996 } 3997 3998 bcmi_egr_ip_tnl_mpls_entry_format_get(unit, 3999 tnl_entry, offset, 4000 iptun_mpls_entry_format, bcmiMplsLabel, 4001 &label_value); 4002 4003 bcmi_egr_ip_tnl_mpls_entry_format_get(unit, 4004 tnl_entry, offset, 4005 iptun_mpls_entry_format, bcmiMplsTtl, 4006 &entry_ttl); 4007 4008 bcmi_egr_ip_tnl_mpls_entry_format_get(unit, 4009 tnl_entry, offset, 4010 iptun_mpls_entry_format, bcmiMplsExp, 4011 &entry_exp); 4012 4013 offset = (i+j); 4014 4015 sal_memset(&iptun_mpls_entry_format, 0, 4016 sizeof(iptun_mpls_entry_format)); 4017 4018 bcmi_egress_tnl_label_entry_get(unit, tnl_entry, 4019 offset, iptun_mpls_entry_format); 4020 4021 bcmi_egr_ip_tnl_mpls_entry_format_get(unit, 4022 tnl_entry, offset, 4023 iptun_mpls_entry_format, bcmiMplsPushAction, 4024 &entry_push_action); 4025 4026 if ((label_array[0].label == label_value) && 4027 (label_array[0].ttl == entry_ttl) && 4028 (label_array[0].exp == entry_exp) && 4029 (push_action == entry_push_action)) { 4030 4031 *match_mpls_tunnel_index = (tnl_index * 4032 _BCM_MPLS_NUM_MPLS_ENTRIES_PER_INDEX(unit)) + i; 4033 return BCM_E_NONE; 4034 } 4035 } else if (push_action == 0x0) { 4036 4037 offset = i; 4038 bcmi_egress_tnl_label_entry_get(unit, tnl_entry, 4039 offset, iptun_mpls_entry_format); 4040 4041 bcmi_egr_ip_tnl_mpls_entry_format_get(unit, 4042 tnl_entry, offset, 4043 iptun_mpls_entry_format, bcmiMplsLabel, 4044 &label_value); 4045 4046 bcmi_egr_ip_tnl_mpls_entry_format_get(unit, 4047 tnl_entry, offset, 4048 iptun_mpls_entry_format, bcmiMplsTtl, 4049 &entry_ttl); 4050 4051 bcmi_egr_ip_tnl_mpls_entry_format_get(unit, 4052 tnl_entry, offset, 4053 iptun_mpls_entry_format, bcmiMplsExp, 4054 &entry_exp); 4055 4056 offset = (i+j); 4057 sal_memset(&iptun_mpls_entry_format, 0, 4058 sizeof(iptun_mpls_entry_format)); 4059 4060 bcmi_egress_tnl_label_entry_get(unit, tnl_entry, 4061 offset, iptun_mpls_entry_format); 4062 bcmi_egr_ip_tnl_mpls_entry_format_get(unit, 4063 tnl_entry, offset, 4064 iptun_mpls_entry_format, bcmiMplsPushAction, 4065 &entry_push_action); 4066 4067 /* Case of Dummy entry */ 4068 if ((0 == label_value) && 4069 (0 == entry_ttl) && 4070 (0 == entry_exp) && 4071 (0 == entry_push_action)) { 4072 4073 *match_mpls_tunnel_index = (tnl_index * 4074 _BCM_MPLS_NUM_MPLS_ENTRIES_PER_INDEX(unit)) + i; 4075 return BCM_E_NONE; 4076 } 4077 } 4078 } 4079 } 4080 return BCM_E_NONE; 4081 } 4082 4083 /* 4084 * Function: 4085 * bcmi_egr_ip_tnl_mpls_check_availability 4086 * Purpose: 4087 * Checks availability for incoming mpls tunnel 4088 * entry into the existing free entries. 4089 * Parameters: 4090 * unit - (IN)device number 4091 * fi - (IN)Pointer to free indexes database. 4092 * num_labels - (IN)Number of labels that entry contains. 4093 * Returns: 4094 * (INT) 4095 */ 4096 int 4097 bcmi_egr_ip_tnl_mpls_check_availability(int unit, 4098 bcmi_egr_ip_tnl_free_indexes_t *fi, 4099 int num_labels) 4100 { 4101 int idx,free_idx; 4102 int mpls_entry_index; 4103 4104 if (num_labels == 0) { 4105 return -1; 4106 } 4107 /* MAX_FREE_ENTRY = */ 4108 for (idx=num_labels-1; idx < MAX_ENTRY_INDEXES; idx++) { 4109 /* MAX FREE ENTRY COUNTING = 8 */ 4110 if (fi->free_index_count[idx]) { 4111 /* entry array starts from 0 but count is from 1 */ 4112 free_idx=fi->free_index_count[idx] - 1; 4113 for (; free_idx>=0; free_idx--) { 4114 /* There is some empty place here. 4115 * lets use the same size ehtry or bigger. 4116 * returning the first free entry in that block. 4117 */ 4118 if (fi->free_entry_indexes[idx][free_idx] == -1) { 4119 /* 4120 * count is set but no free index here. 4121 * please reduce the count 4122 */ 4123 fi->free_index_count[idx]--; 4124 continue; 4125 } 4126 /* 4127 * if we have reached here that means we have got the space 4128 */ 4129 mpls_entry_index = fi->free_entry_indexes[idx][free_idx]; 4130 fi->free_entry_indexes[idx][free_idx] = -1; 4131 fi->free_index_count[idx]--; 4132 bcm_egr_ip_tnl_mpls_remark_free_indexes(unit, 4133 (idx+1)-num_labels, mpls_entry_index+num_labels, fi); 4134 4135 return mpls_entry_index; 4136 } 4137 } 4138 } 4139 return -1; 4140 } 4141 4142 /* 4143 * Function: 4144 * bcmi_egr_ip_tnl_mpls_get_free_index 4145 * Purpose: 4146 * fills the free entry index database with after 4147 * reading all the tunnel entries. 4148 * Parameters: 4149 * unit - (IN)device number 4150 * num_labels - (IN)Number of labels that entry contains. 4151 * tunnel_entry - (IN)Pointer to mpls tunnel s/w state. 4152 * fi - (IN/OUT)Pointer to free indexes database. 4153 * Returns: 4154 * (INT) 4155 */ 4156 int 4157 bcmi_egr_ip_tnl_mpls_get_free_index(int unit, int num_labels, 4158 bcmi_egr_ip_tnl_mpls_tunnel_entry_t **tunnel_entry, 4159 bcmi_egr_ip_tnl_free_indexes_t *fi) 4160 { 4161 int idx=0, mpls_off=0; 4162 int mpls_index; 4163 int start_index = -1; 4164 int number_of_free_entries = 0; 4165 int free_tunnel_index = -1; 4166 int num_ip_tnl; 4167 bcmi_egr_ip_tnl_mpls_label_entry_t *label_entry; 4168 soc_mem_t mem; 4169 4170 if (num_labels == 0) { 4171 return -1; 4172 } 4173 4174 mem = bcmi_egr_ip_tnl_mem_name_get(unit); 4175 4176 num_ip_tnl = soc_mem_index_count(unit, mem); 4177 4178 for (;idx < num_ip_tnl; idx++) { 4179 4180 if (!_BCM_MPLS_IP_TNL_USED_GET(unit, idx)) { 4181 continue; 4182 } 4183 4184 mpls_index = idx * _BCM_MPLS_NUM_MPLS_ENTRIES_PER_INDEX(unit); 4185 start_index = -1; 4186 mpls_off = 0; 4187 number_of_free_entries = 0; 4188 for(;mpls_off < _BCM_MPLS_NUM_MPLS_ENTRIES_PER_INDEX(unit); mpls_off++) { 4189 4190 if (_BCM_MPLS_TNL_USED_GET(unit, (mpls_index + mpls_off))) { 4191 4192 label_entry = tunnel_entry[idx]->label_entry[mpls_off]; 4193 4194 if (label_entry->flags & 4195 BCMI_EGR_IP_TUNNEL_MPLS_START_OF_ENTRY) { 4196 4197 mpls_off += 4198 label_entry->num_elements - 1; 4199 } 4200 if (!(bcmi_egr_ip_tnl_mpls_check_dup_free_index(unit, 4201 fi,number_of_free_entries, start_index))) { 4202 4203 bcm_egr_ip_tnl_mpls_remark_free_indexes(unit, 4204 number_of_free_entries, start_index, fi); 4205 } 4206 start_index = -1; 4207 number_of_free_entries = 0; 4208 4209 } else { 4210 4211 number_of_free_entries++; 4212 if (start_index == -1) { 4213 start_index = mpls_index + mpls_off; 4214 } 4215 if (mpls_off == 7) { 4216 /* 4217 * this is the last tunnel index and therefore we 4218 * should just update free entries 4219 */ 4220 if (!(bcmi_egr_ip_tnl_mpls_check_dup_free_index(unit, 4221 fi,number_of_free_entries, start_index))) { 4222 4223 bcm_egr_ip_tnl_mpls_remark_free_indexes(unit, 4224 number_of_free_entries, start_index, fi); 4225 } 4226 start_index= -1; 4227 number_of_free_entries = 0; 4228 4229 } 4230 } 4231 } 4232 if (idx % num_labels == 0) { 4233 /* just checking after getting data of five labels */ 4234 free_tunnel_index = bcmi_egr_ip_tnl_mpls_check_availability(unit, 4235 fi, num_labels); 4236 } 4237 if (free_tunnel_index != -1) { 4238 return free_tunnel_index; 4239 } 4240 } 4241 return -1; 4242 } 4243 4244 /* 4245 * Function: 4246 * bcmi_egr_ip_tnl_mpls_create_local_free_indexes 4247 * Purpose: 4248 * Create duplicate free indexes for local arithmatic. 4249 * Parameters: 4250 * unit - (IN)device number 4251 * free_entry_structures - (IN)Pointer to free indexes database. 4252 * local_free_indexes_structure - (IN)Pointer to free indexes database. 4253 * Returns: 4254 * None. 4255 */ 4256 void 4257 bcmi_egr_ip_tnl_mpls_create_local_free_indexes(int unit, 4258 bcmi_egr_ip_tnl_free_indexes_t *free_entry_structures, 4259 bcmi_egr_ip_tnl_free_indexes_t *local_free_indexes_structure) 4260 { 4261 int i, j; 4262 4263 sal_memset(local_free_indexes_structure, 0, 4264 sizeof(bcmi_egr_ip_tnl_free_indexes_t)); 4265 for (i=0; i<MAX_ENTRY_INDEXES;i++) { 4266 for (j=0;j<MAX_FREE_ENTRY_INDEXES; j++) { 4267 local_free_indexes_structure->free_entry_indexes[i][j] = 4268 free_entry_structures->free_entry_indexes[i][j]; 4269 } 4270 local_free_indexes_structure->free_index_count[i] = 4271 free_entry_structures->free_index_count[i]; 4272 } 4273 } 4274 4275 /* 4276 * Function: 4277 * bcmi_egr_ip_tnl_mpls_uncheck_free_indexes 4278 * Purpose: 4279 * while looking for entries, we mark some entries as checkes 4280 * already so that we do not try to use the same entry 4281 * while looking for multiple entries.. 4282 * Parameters: 4283 * unit - (IN)device number 4284 * fi - (IN)Pointer to free indexes database. 4285 * tunnel_entry - (IN)Pointer to tunnel database 4286 * Returns: 4287 * None. 4288 */ 4289 void 4290 bcmi_egr_ip_tnl_mpls_uncheck_free_indexes(int unit, 4291 bcmi_egr_ip_tnl_free_indexes_t *fi, 4292 bcmi_egr_ip_tnl_mpls_tunnel_entry_t **tunnel_entry) 4293 { 4294 int i, j; 4295 int tnl_idx, tnl_mpls_idx; 4296 4297 for (i=0; i<MAX_ENTRY_INDEXES;i++) { 4298 for (j=0;j<MAX_FREE_ENTRY_INDEXES; j++) { 4299 4300 if (fi->free_entry_indexes[i][j] == -1) { 4301 continue; 4302 } 4303 tnl_idx = fi->free_entry_indexes[i][j] / 4304 _BCM_MPLS_NUM_MPLS_ENTRIES_PER_INDEX(unit); 4305 tnl_mpls_idx = fi->free_entry_indexes[i][j] % 4306 _BCM_MPLS_NUM_MPLS_ENTRIES_PER_INDEX(unit); 4307 4308 tunnel_entry[tnl_idx]->label_entry[tnl_mpls_idx]->flags &= 4309 (~BCMI_EGR_IP_TUNNEL_MPLS_ENTRY_CHECKED); 4310 } 4311 4312 } 4313 } 4314 4315 /* 4316 * Function: 4317 * bcmi_egr_ip_tnl_mpls_adjust_entry 4318 * Purpose: 4319 * Reshuffle the entries if we are not able to fit 4320 * the incoming entry. 4321 * Parameters: 4322 * unit - (IN)device number 4323 * num_labels - (IN)Number of labels that entry contains. 4324 * tunnel_entry - (IN_Pointer to mpls tunnel s/w state. 4325 * fi - (IN)Pointer to free indexes database. 4326 * tnl_idx - (OUT)Pointer to index of freed entry if possible. 4327 * Returns: 4328 * bcm_error_t 4329 */ 4330 bcm_error_t 4331 bcmi_egr_ip_tnl_mpls_adjust_entry(int unit, 4332 int num_labels, 4333 bcmi_egr_ip_tnl_mpls_tunnel_entry_t **tunnel_entry, 4334 bcmi_egr_ip_tnl_free_indexes_t *fi, 4335 int *tnl_idx) 4336 { 4337 int idx=0; 4338 bcmi_egr_ip_tnl_free_indexes_t local_fi; /* locan free indexes */ 4339 int num_ip_tnl; 4340 int mpls_off; 4341 int no_of_elements; 4342 int temp_num_labels; 4343 int found = 0; 4344 int free_indexes_changed = 1; 4345 int f_idx, free_idx; 4346 int mpls_index; 4347 int left_free_entries; 4348 int new_start_index; 4349 int chk_tnl_idx, chk_mpls_idx; 4350 int rv; 4351 int src_mpls_index = 0; 4352 int ent_per_tunnel = _BCM_MPLS_NUM_MPLS_ENTRIES_PER_INDEX(unit); 4353 bcmi_egr_ip_tnl_mpls_label_entry_t *label_entry; 4354 soc_mem_t mem; 4355 int free_db_entries=0; 4356 4357 mem = bcmi_egr_ip_tnl_mem_name_get(unit); 4358 4359 num_ip_tnl = soc_mem_index_count(unit, mem); 4360 4361 for (;idx < num_ip_tnl; idx++) { 4362 mpls_off = 0; 4363 temp_num_labels = num_labels; 4364 4365 bcmi_egr_ip_tnl_mpls_uncheck_free_indexes(unit, fi, tunnel_entry); 4366 4367 if (!_BCM_MPLS_IP_TNL_USED_GET(unit, idx)) { 4368 continue; 4369 } 4370 if (free_indexes_changed) { 4371 bcmi_egr_ip_tnl_mpls_create_local_free_indexes(unit, fi, &local_fi); 4372 } 4373 free_indexes_changed=0; 4374 mpls_index = idx * ent_per_tunnel; 4375 /* check for quad entry free */ 4376 for(;mpls_off < ent_per_tunnel; mpls_off++) { 4377 found = 0; 4378 /* 4379 * if we have just started for entry, then do basic index checking. 4380 * if number of labels are 3 or 4 then only index 0 or index 4 are 4381 * valid indexes. 4382 * if number of labels are bigger than 4 then entry can start only 4383 * at index 0. 4384 * based on above rules, move the index to the next valid index. 4385 */ 4386 if (temp_num_labels == num_labels) { 4387 src_mpls_index = mpls_index + mpls_off; 4388 if ((num_labels < 5) && (num_labels > 2)) { 4389 if (mpls_off < 4 && mpls_off > 0) { 4390 mpls_off = 4; 4391 } else if (mpls_off > 4) { 4392 mpls_off = 7; 4393 continue; 4394 } 4395 } 4396 if ((num_labels > 4) && (mpls_off > 0)) { 4397 mpls_off = 7; 4398 continue; 4399 } 4400 } 4401 4402 /* If this is free index then continue until you get free space. */ 4403 if (!_BCM_MPLS_TNL_USED_GET(unit, (mpls_index + mpls_off))) { 4404 temp_num_labels--; 4405 free_db_entries++; 4406 if (temp_num_labels) { 4407 continue; 4408 } 4409 } 4410 4411 /* If we are looking at same index as free index. then continue. */ 4412 if (free_db_entries) { 4413 bcmi_mpls_egr_tunnel_delete_free_indexes(unit, 4414 &local_fi, free_db_entries, (mpls_index + mpls_off - free_db_entries)); 4415 free_indexes_changed = 1; 4416 } 4417 4418 free_db_entries = 0; 4419 if(tunnel_entry[idx]->label_entry[mpls_off]->flags & 4420 BCMI_EGR_IP_TUNNEL_MPLS_START_OF_ENTRY) { 4421 /* this is the start of this entry, 4422 * we should check if we have some free space for this entry 4423 */ 4424 no_of_elements = 4425 tunnel_entry[idx]->label_entry[mpls_off]->num_elements; 4426 /* we also should check if there are some bigger entries 4427 * in this tunnel entry, 4428 * big entries can be adjusted to other big entries if exists. 4429 * else we might have to move smaller entries to bigger entries 4430 */ 4431 if (no_of_elements >= num_labels) { 4432 /* 4433 * no need to look for bigger entry as this is already 4434 * checked above. 4435 * if we could move bigger entry then we could have moved 4436 * incoming entry itself 4437 * so please return back with update to indexes. 4438 */ 4439 mpls_off += no_of_elements; 4440 temp_num_labels = num_labels; 4441 if (free_indexes_changed) { 4442 bcmi_egr_ip_tnl_mpls_create_local_free_indexes(unit, 4443 fi, &local_fi); 4444 } 4445 4446 /* 4447 * we are doing continue here because we may like to 4448 * check further entries also. 4449 */ 4450 bcmi_egr_ip_tnl_mpls_uncheck_free_indexes(unit, 4451 fi, tunnel_entry); 4452 continue; 4453 } 4454 4455 for (f_idx=no_of_elements-1; f_idx < 8; f_idx++) { 4456 if (!(local_fi.free_index_count[f_idx])) { 4457 continue; 4458 } 4459 for (free_idx=0; free_idx<8; free_idx++) { 4460 /* There is some empty place here. 4461 * lets use the same size entry or bigger. 4462 * returning the first free entry in that block. 4463 */ 4464 if (local_fi.free_entry_indexes[f_idx][free_idx] 4465 == -1) { 4466 4467 break; 4468 } 4469 4470 chk_tnl_idx = 4471 local_fi.free_entry_indexes[f_idx][free_idx] / 4472 ent_per_tunnel; 4473 chk_mpls_idx = 4474 local_fi.free_entry_indexes[f_idx][free_idx] % 4475 ent_per_tunnel; 4476 4477 label_entry = 4478 tunnel_entry[chk_tnl_idx]->label_entry[chk_mpls_idx]; 4479 4480 if (!(label_entry->flags & 4481 BCMI_EGR_IP_TUNNEL_MPLS_ENTRY_CHECKED)) { 4482 /* 4483 * we can use free_entry_indexes[idx][free_idx]; 4484 * mark this entry used so that next lookup should 4485 * not use this. 4486 */ 4487 label_entry->flags |= 4488 BCMI_EGR_IP_TUNNEL_MPLS_ENTRY_CHECKED; 4489 4490 found = 1; 4491 free_indexes_changed = 1; 4492 4493 temp_num_labels -= no_of_elements; 4494 /* mpls_off is loop incrementing value. so reduce it. */ 4495 mpls_off += (no_of_elements - 1); 4496 new_start_index = 4497 local_fi.free_entry_indexes[f_idx][free_idx] + 4498 no_of_elements; 4499 bcmi_mpls_egr_tunnel_delete_free_indexes(unit, 4500 &local_fi, no_of_elements, 4501 fi->free_entry_indexes[f_idx][free_idx]); 4502 4503 left_free_entries = (f_idx+1)-no_of_elements; 4504 bcm_egr_ip_tnl_mpls_remark_free_indexes(unit, 4505 left_free_entries, new_start_index, &local_fi); 4506 break; 4507 } 4508 } 4509 if (found) { 4510 break; 4511 } 4512 } 4513 if (!found) { 4514 temp_num_labels = num_labels; 4515 } 4516 } 4517 if (temp_num_labels <= 0) { 4518 4519 /* if we are here that means we have got required space. 4520 * get ready to move the entries. 4521 */ 4522 int mpls_tnl_off = src_mpls_index % ent_per_tunnel; 4523 4524 bcmi_egr_ip_tnl_mpls_uncheck_free_indexes(unit, fi, 4525 tunnel_entry); 4526 rv = bcmi_egr_ip_tnl_mpls_move_tunnel_entries(unit, fi, 4527 tunnel_entry, idx, mpls_tnl_off, num_labels); 4528 4529 if (rv == BCM_E_NONE) { 4530 *tnl_idx = src_mpls_index; 4531 /* we have got the index where we can fill this entry 4532 * But we can have some free entries beneath it. 4533 * so return those free entries to free indexes. 4534 */ 4535 /* 4536 bcm_egr_ip_tnl_mpls_remark_free_indexes(unit, 4537 (ent_per_tunnel - num_labels - mpls_tnl_off), 4538 src_mpls_index, &(fi_db[unit])); 4539 */ 4540 return rv; 4541 } 4542 } 4543 } 4544 } 4545 /* 4546 * if we are here then we have not got the space. 4547 * Currently return BCM_E_FULLL. 4548 */ 4549 return BCM_E_FULL; 4550 } 4551 4552 /* 4553 * Function: 4554 * bcmi_xgs5_mpls_tunnel_initiator_set 4555 * Purpose: 4556 * Set MPLS Tunnel initiator 4557 * Parameters: 4558 * unit - Device Number 4559 * intf - The egress L3 interface 4560 * num_labels - Number of labels in the array 4561 * label_array - Array of MPLS label and header information 4562 * Returns: 4563 * BCM_E_XXX 4564 */ 4565 int 4566 bcmi_xgs5_mpls_tunnel_initiator_set(int unit, bcm_if_t intf, int num_labels, 4567 bcm_mpls_egress_label_t *label_array) 4568 { 4569 egr_l3_intf_entry_t if_entry; 4570 int rv, num_mpls_map, i, push_action=0, offset = 0; 4571 int found = 0, tnl_index = 0, mpls_index = 0; 4572 int hw_map_idx; 4573 bcm_tunnel_initiator_t tnl_init; 4574 uint32 tnl_flags = 0; 4575 int match_mpls_tunnel_index=-1; 4576 int ent_per_tnl = 0; 4577 int tnl_id = 0; 4578 int mpls_offset = 0; 4579 int mpls_tunnel_update = 0; 4580 bcmi_egr_ip_tnl_mpls_tunnel_entry_t **tunnel_entry; 4581 soc_mem_t mem; 4582 uint32 tnl_entry[SOC_MAX_MEM_WORDS]; 4583 uint32 iptun_mpls_entry_format[3] = {0}; 4584 4585 mem = bcmi_egr_ip_tnl_mem_name_get(unit); 4586 ent_per_tnl = _BCM_MPLS_NUM_MPLS_ENTRIES_PER_INDEX(unit); 4587 tunnel_entry = egr_mpls_tnl_sw_state[unit]; 4588 4589 if ((num_labels < 0) || (num_labels > ent_per_tnl) || 4590 (intf < 0) || (intf >= L3_INFO(unit)->l3_intf_table_size)) { 4591 return BCM_E_PARAM; 4592 } 4593 4594 if ((num_labels > 2) && 4595 !(soc_feature(unit, soc_feature_mpls_segment_routing)) && 4596 !(soc_feature(unit, soc_feature_th3_style_simple_mpls))) { 4597 return BCM_E_UNAVAIL; 4598 } 4599 4600 /* Derive action from labels. 4601 * based on number of labels, we can set multiple entries to add 4602 * desired number of labels into the tunnel. 4603 * Therefore push action is directly derived from num labels. 4604 */ 4605 push_action = num_labels; 4606 4607 /* Param checking */ 4608 num_mpls_map = soc_mem_index_count(unit, EGR_MPLS_EXP_MAPPING_1m) / 64; 4609 for (i = 0; i < num_labels; i++) { 4610 if (label_array[i].qos_map_id == 0) { /* treat it as using default */ 4611 hw_map_idx = 0; 4612 } else { 4613 BCM_IF_ERROR_RETURN(_egr_qos_id2hw_idx(unit, 4614 label_array[i].qos_map_id,&hw_map_idx)); 4615 } 4616 if ((label_array[i].label > 0xfffff) || 4617 (hw_map_idx < 0) || 4618 (hw_map_idx >= num_mpls_map) || 4619 (label_array[i].exp > 7) || (label_array[i].pkt_pri > 7) || 4620 (label_array[i].pkt_cfi > 1)) { 4621 return BCM_E_PARAM; 4622 } 4623 } 4624 if (!BCM_L3_INTF_USED_GET(unit, intf)) { 4625 LOG_INFO(BSL_LS_BCM_L3, 4626 (BSL_META_U(unit, 4627 "L3 interface not created\n"))); 4628 return BCM_E_NOT_FOUND; 4629 } 4630 4631 /* L3 interface info */ 4632 rv = READ_EGR_L3_INTFm(unit, MEM_BLOCK_ANY, intf, &if_entry); 4633 if (rv < 0) { 4634 return rv; 4635 } 4636 /* init the allocated entry */ 4637 bcmi_egr_ip_tnl_mpls_table_memset(unit,tnl_entry); 4638 4639 /* Case of Dummy Tunnel entry sharing by multiple L3_INTF */ 4640 if (num_labels == 0) { 4641 /* Lookup if Tunnel Entry with Tunnel Label exists? */ 4642 rv = bcmi_xgs5_mpls_egr_tunnel_lookup (unit, push_action, tunnel_entry, 4643 NULL, &match_mpls_tunnel_index); 4644 if (rv < 0) { 4645 return rv; 4646 } 4647 4648 if (match_mpls_tunnel_index != -1) { 4649 /* L3_Interface to point to mpls_tunnel */ 4650 soc_EGR_L3_INTFm_field32_set(unit, &if_entry, 4651 MPLS_TUNNEL_INDEXf, match_mpls_tunnel_index); 4652 /* Increment Ref count */ 4653 bcmi_egr_ip_tnl_mpls_ref_count_adjust (unit, 4654 match_mpls_tunnel_index, 1); 4655 rv = WRITE_EGR_L3_INTFm(unit, MEM_BLOCK_ANY, intf, &if_entry); 4656 4657 if (rv == BCM_E_NONE) { 4658 tnl_id = match_mpls_tunnel_index/ent_per_tnl; 4659 mpls_offset = match_mpls_tunnel_index % ent_per_tnl; 4660 rv = bcmi_egr_ip_tnl_mpls_intf_list_add 4661 (unit, tunnel_entry, intf, tnl_id, mpls_offset); 4662 4663 } 4664 return rv; 4665 } 4666 } 4667 4668 for (i = 0; i < num_labels; i++) { 4669 /* Check for Port_independent Label mapping */ 4670 rv = bcm_tr_mpls_port_independent_range (unit, label_array[i].label, 4671 BCM_GPORT_INVALID); 4672 /* Either Port-scope-label or Explicit-Null-label */ 4673 if ((rv == BCM_E_CONFIG) || (label_array[i].label == 0)) { 4674 /* Tunnel-label is Port-based */ 4675 /* Lookup if Tunnel Entry with Tunnel Label exists? */ 4676 rv = bcmi_xgs5_mpls_egr_tunnel_lookup (unit, push_action, 4677 tunnel_entry, label_array, &match_mpls_tunnel_index); 4678 if (rv < 0) { 4679 return rv; 4680 } 4681 4682 if (match_mpls_tunnel_index != -1) { 4683 /* L3_Interface to point to mpls_tunnel */ 4684 soc_EGR_L3_INTFm_field32_set(unit, &if_entry, 4685 MPLS_TUNNEL_INDEXf, match_mpls_tunnel_index); 4686 /* Increment Ref count */ 4687 bcmi_egr_ip_tnl_mpls_ref_count_adjust (unit, 4688 match_mpls_tunnel_index, 1); 4689 /* we also need to add this entry into sw state linked list */ 4690 rv = WRITE_EGR_L3_INTFm(unit, MEM_BLOCK_ANY, intf, &if_entry); 4691 if (rv == BCM_E_NONE) { 4692 tnl_id = match_mpls_tunnel_index/ent_per_tnl; 4693 offset = match_mpls_tunnel_index % ent_per_tnl; 4694 rv = bcmi_egr_ip_tnl_mpls_intf_list_add(unit, tunnel_entry, 4695 intf, tnl_id, offset); 4696 } 4697 return rv; 4698 } 4699 } 4700 } 4701 mpls_index = soc_EGR_L3_INTFm_field32_get(unit, &if_entry, 4702 MPLS_TUNNEL_INDEXf); 4703 tnl_index = mpls_index / ent_per_tnl; 4704 4705 if ((mpls_index != 0) && (_BCM_MPLS_TNL_USED_GET(unit, mpls_index))) { 4706 /* Obtain referenced Tunnel entry */ 4707 /* try using existing entry in tunnel */ 4708 rv = bcmi_egr_ip_tnl_mpls_table_read(unit,tnl_index,tnl_entry); 4709 4710 if (rv < 0) { 4711 return rv; 4712 } 4713 4714 rv = bcmi_egr_ip_tnl_mpls_entry_type_check(unit, tnl_entry); 4715 4716 if (rv < 0) { 4717 return rv; 4718 } 4719 4720 /* we need to check here if at least number of labels is same.*/ 4721 offset = mpls_index % ent_per_tnl; 4722 if (tunnel_entry[tnl_index]->label_entry[offset]->flags & 4723 BCMI_EGR_IP_TUNNEL_MPLS_START_OF_ENTRY) { 4724 if (tunnel_entry[tnl_index]->label_entry[offset]->num_elements != 4725 num_labels) { 4726 /* Changing push action/ num labels is not permitted, 4727 * need to clear/set 4728 */ 4729 return BCM_E_PARAM; 4730 } 4731 } else { 4732 return BCM_E_PARAM; 4733 } 4734 mpls_tunnel_update = 1; 4735 4736 } else { 4737 /* allocate an unused EGR_IP_TUNNEL_MPLS_ENTRY */ 4738 /* 4739 * First try finding an allocated tunnel entry with 4740 * unused MPLS entries. 4741 */ 4742 mpls_index = bcmi_egr_ip_tnl_mpls_check_availability(unit, 4743 &(fi_db[unit]), num_labels); 4744 4745 if (mpls_index == -1) { 4746 /* 4747 * we have not got corresponding free indexes. 4748 * lets try to create some more free indexes 4749 * and then try again. 4750 */ 4751 mpls_index = bcmi_egr_ip_tnl_mpls_get_free_index(unit, num_labels, 4752 tunnel_entry, &(fi_db[unit])); 4753 } 4754 if (mpls_index != -1) { 4755 found = 1; 4756 tnl_index = mpls_index / 4757 (_BCM_MPLS_EGR_L3_INTF_MPLS_INDEX_OFFSET_MASK(unit) + 1); 4758 4759 rv = bcmi_egr_ip_tnl_mpls_table_read(unit,tnl_index,tnl_entry); 4760 if (rv < 0) { 4761 return rv; 4762 } 4763 4764 } else { 4765 /* 4766 * Alloc an egr_ip_tunnel entry. By calling bcm_xgs3_tnl_init_add 4767 * with _BCM_L3_SHR_WRITE_DISABLE flag, a tunnel index is 4768 * allocated but nothing is written to hardware. The "tnl_init" 4769 * information is not used, set to all zero. 4770 */ 4771 sal_memset(&tnl_init, 0, sizeof(bcm_tunnel_initiator_t)); 4772 tnl_flags = _BCM_L3_SHR_MATCH_DISABLE | _BCM_L3_SHR_WRITE_DISABLE | 4773 _BCM_L3_SHR_SKIP_INDEX_ZERO; 4774 tnl_init.type = bcmTunnelTypeMpls; 4775 rv = bcm_xgs3_tnl_init_add(unit, tnl_flags, &tnl_init, &tnl_index); 4776 if (rv == BCM_E_FULL) { 4777 4778 /* There is no entry left unused. 4779 * now see if we can move some entries and make space 4780 */ 4781 4782 rv = bcmi_egr_ip_tnl_mpls_adjust_entry(unit, num_labels, 4783 tunnel_entry, &(fi_db[unit]), &mpls_index); 4784 if (rv < 0) { 4785 return rv; 4786 } 4787 4788 } else { 4789 found = 1; 4790 /* we have got full entry here. start at 0 index. 4791 * we will get double entry from l3_tbl_add as it 4792 * works on common resorce of egr_ip_tunnel. 4793 * But egr_ip_tunnel_mpls uses double entries. 4794 */ 4795 tnl_index = (tnl_index + 1)/2; 4796 mpls_index = tnl_index * 4797 (_BCM_MPLS_EGR_L3_INTF_MPLS_INDEX_OFFSET_MASK(unit) + 1); 4798 /* we are using two tunnel entries at same time.*/ 4799 _BCM_MPLS_IP_TNL_USED_SET(unit, tnl_index); 4800 _BCM_MPLS_TNL_USED_SET(unit, mpls_index); 4801 4802 bcmi_egr_ip_tnl_mpls_table_memset(unit,tnl_entry); 4803 if (num_labels < ent_per_tnl) { 4804 bcm_egr_ip_tnl_mpls_remark_free_indexes(unit, 4805 (ent_per_tnl - ((num_labels) ? num_labels : 1)), 4806 mpls_index+((num_labels) ? num_labels : 1), 4807 &(fi_db[unit])); 4808 } 4809 } 4810 } 4811 } 4812 4813 offset = mpls_index & _BCM_MPLS_EGR_L3_INTF_MPLS_INDEX_OFFSET_MASK(unit); 4814 tnl_id = mpls_index / 4815 (_BCM_MPLS_EGR_L3_INTF_MPLS_INDEX_OFFSET_MASK(unit) + 1); 4816 4817 tunnel_entry[tnl_id]->label_entry[offset]->flags |= 4818 BCMI_EGR_IP_TUNNEL_MPLS_START_OF_ENTRY; 4819 tunnel_entry[tnl_id]->label_entry[offset]->num_elements = 4820 ((num_labels) ? num_labels : 1); 4821 4822 if (!num_labels) { 4823 tunnel_entry[tnl_id]->label_entry[offset]->flags |= 4824 BCMI_EGR_IP_TUNNEL_MPLS_ENTRY_ZERO; 4825 } 4826 4827 rv = bcmi_egr_ip_tnl_mpls_table_read(unit, tnl_id,tnl_entry); 4828 if (rv < 0) { 4829 return rv; 4830 } 4831 4832 for (i = 0; i < num_labels; i++) { 4833 if (label_array[i].qos_map_id == 0) { /* treat it as using default */ 4834 hw_map_idx = 0; 4835 } else { 4836 rv = _egr_qos_id2hw_idx(unit, 4837 label_array[i].qos_map_id,&hw_map_idx); 4838 if (rv < 0) { 4839 goto cleanup; 4840 } 4841 } 4842 4843 bcmi_egr_ip_tnl_mpls_entry_format_set(unit, bcmiMplsPushAction, 4844 tnl_entry, offset, 4845 iptun_mpls_entry_format, 4846 ((i == (num_labels - 1)) ? 1 : 2)); 4847 if (num_labels > 0) { 4848 bcmi_egr_ip_tnl_mpls_entry_format_set(unit, bcmiMplsLabel, 4849 tnl_entry, offset, 4850 iptun_mpls_entry_format, label_array[i].label); 4851 } 4852 4853 #if defined(BCM_TRIDENT3_SUPPORT) 4854 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 4855 bcmi_egr_ip_tnl_mpls_entry_format_set(unit, bcmiSpecialLabelPushType, 4856 tnl_entry, offset, 4857 iptun_mpls_entry_format, label_array[i].spl_label_push_type); 4858 } 4859 #endif 4860 4861 if ((label_array[i].flags & BCM_MPLS_EGRESS_LABEL_EXP_SET) || 4862 (label_array[i].flags & BCM_MPLS_EGRESS_LABEL_PRI_SET)) { 4863 4864 /* Use the specified EXP, PRI and CFI */ 4865 if ((label_array[i].flags & BCM_MPLS_EGRESS_LABEL_EXP_REMARK) || 4866 (label_array[i].flags & BCM_MPLS_EGRESS_LABEL_EXP_COPY) || 4867 (label_array[i].flags & BCM_MPLS_EGRESS_LABEL_PRI_REMARK)) { 4868 rv = BCM_E_PARAM; 4869 goto cleanup; 4870 } 4871 4872 bcmi_egr_ip_tnl_mpls_entry_format_set(unit, 4873 bcmiMplsExpSelect, 4874 tnl_entry, offset, 4875 iptun_mpls_entry_format, 0); 4876 4877 bcmi_egr_ip_tnl_mpls_entry_format_set(unit, 4878 bcmiMplsExp, 4879 tnl_entry, offset, 4880 iptun_mpls_entry_format, 4881 label_array[i].exp); 4882 4883 bcmi_egr_ip_tnl_mpls_entry_format_set(unit, 4884 bcmiNewPri, 4885 tnl_entry, offset, 4886 iptun_mpls_entry_format, 4887 label_array[i].pkt_pri); 4888 4889 bcmi_egr_ip_tnl_mpls_entry_format_set(unit, 4890 bcmiNewCfi, 4891 tnl_entry, offset, 4892 iptun_mpls_entry_format, 4893 label_array[i].pkt_cfi); 4894 } else if (label_array[i].flags & BCM_MPLS_EGRESS_LABEL_EXP_REMARK) { 4895 if (label_array[i].flags & BCM_MPLS_EGRESS_LABEL_PRI_SET) { 4896 rv = BCM_E_PARAM; 4897 goto cleanup; 4898 } 4899 /* Use EXP-map for EXP, PRI and CFI */ 4900 bcmi_egr_ip_tnl_mpls_entry_format_set(unit, 4901 bcmiMplsExpSelect, 4902 tnl_entry, offset, 4903 iptun_mpls_entry_format, 0x1); 4904 4905 bcmi_egr_ip_tnl_mpls_entry_format_set(unit, 4906 bcmiMplsExpMappingPtr, 4907 tnl_entry, offset, 4908 iptun_mpls_entry_format, 4909 hw_map_idx); 4910 4911 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 4912 if(i == 1) { 4913 /*EGR_MPLS_EXP_MAPPING_3 for Tunnel label 2*/ 4914 bcmi_egr_ip_tnl_mpls_entry_format_set(unit, 4915 bcmiExpMappingTableSelect, 4916 tnl_entry, offset, 4917 iptun_mpls_entry_format, 0x2); 4918 } 4919 4920 if(i == 0) { 4921 /*EGR_MPLS_EXP_MAPPING_2 for Tunnel label 1*/ 4922 bcmi_egr_ip_tnl_mpls_entry_format_set(unit, 4923 bcmiExpMappingTableSelect, 4924 tnl_entry, offset, 4925 iptun_mpls_entry_format, 0x1); 4926 } 4927 } 4928 4929 } else { /* BCM_MPLS_EGRESS_LABEL_EXP_COPY */ 4930 /* Use EXP from inner label. If there is no inner label, 4931 * use the specified EXP value. Use EXP-map for PRI/CFI. 4932 */ 4933 bcmi_egr_ip_tnl_mpls_entry_format_set(unit, 4934 bcmiMplsExpSelect, 4935 tnl_entry, offset, 4936 iptun_mpls_entry_format, 0x2); /* USE_INNER */ 4937 4938 bcmi_egr_ip_tnl_mpls_entry_format_set(unit, 4939 bcmiMplsExp, 4940 tnl_entry, offset, 4941 iptun_mpls_entry_format, 4942 label_array[i].exp); 4943 4944 bcmi_egr_ip_tnl_mpls_entry_format_set(unit, 4945 bcmiMplsExpMappingPtr, 4946 tnl_entry, offset, 4947 iptun_mpls_entry_format, 4948 hw_map_idx); 4949 4950 } 4951 4952 if (label_array[i].flags & BCM_MPLS_EGRESS_LABEL_TTL_SET) { 4953 bcmi_egr_ip_tnl_mpls_entry_format_set(unit, 4954 bcmiMplsTtl, 4955 tnl_entry, offset, 4956 iptun_mpls_entry_format, 4957 label_array[i].ttl); 4958 } else { 4959 bcmi_egr_ip_tnl_mpls_entry_format_set(unit, 4960 bcmiMplsTtl, 4961 tnl_entry, offset, 4962 iptun_mpls_entry_format, 4963 0); 4964 } 4965 4966 #if defined(BCM_TOMAHAWK2_SUPPORT) || defined(BCM_TRIDENT3_SUPPORT) 4967 if (soc_feature(unit, soc_feature_mpls_ecn)) { 4968 if (label_array[i].flags & BCM_MPLS_EGRESS_LABEL_ECN_TO_EXP_MAP) { 4969 int ecn_map_index; 4970 int ecn_map_type; 4971 int ecn_map_num; 4972 int ecn_map_hw_idx; 4973 soc_mem_t mem; 4974 4975 ecn_map_type = label_array[i].ecn_map_id & 4976 _BCM_XGS5_MPLS_ECN_MAP_TYPE_MASK; 4977 ecn_map_index = label_array[i].ecn_map_id & 4978 _BCM_XGS5_MPLS_ECN_MAP_NUM_MASK; 4979 4980 #if defined(BCM_TRIDENT3_SUPPORT) 4981 if(soc_feature(unit, soc_feature_td3_style_mpls)) { 4982 mem = EGR_PKT_ECN_TO_EXP_MAPPING_1m; 4983 } else 4984 #endif 4985 { 4986 mem = EGR_IP_ECN_TO_EXP_MAPPING_TABLEm; 4987 } 4988 4989 ecn_map_num = soc_mem_index_count(unit, mem) / 4990 _BCM_ECN_MAX_ENTRIES_PER_MAP; 4991 if (ecn_map_type != _BCM_XGS5_MPLS_ECN_MAP_TYPE_ECN2EXP) { 4992 rv = BCM_E_PARAM; 4993 goto cleanup; 4994 } 4995 if (ecn_map_index >= ecn_map_num) { 4996 rv = BCM_E_PARAM; 4997 goto cleanup; 4998 } 4999 if (!bcmi_xgs5_ecn_map_used_get(unit, ecn_map_index, 5000 _bcmEcnmapTypeIpEcn2Exp)) { 5001 rv = BCM_E_PARAM; 5002 goto cleanup; 5003 } 5004 rv = bcmi_ecn_map_id2hw_idx(unit, label_array[i].ecn_map_id, 5005 &ecn_map_hw_idx); 5006 if (BCM_FAILURE(rv)) { 5007 goto cleanup; 5008 } 5009 #if defined(BCM_TRIDENT3_SUPPORT) 5010 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 5011 bcmi_egr_ip_tnl_mpls_entry_format_set(unit, 5012 bcmiPktEcnToExpMappingPtr, 5013 tnl_entry, offset, 5014 iptun_mpls_entry_format, 5015 ecn_map_hw_idx); 5016 5017 /*ECN_MAPPING_ENABLE Remap EXP to encode ECN.*/ 5018 bcmi_egr_ip_tnl_mpls_entry_format_set(unit, 5019 bcmiEcnMappingEnable, 5020 tnl_entry, offset, 5021 iptun_mpls_entry_format, 1); 5022 5023 bcmi_egr_ip_tnl_mpls_entry_format_set(unit, 5024 bcmiEcnMappingTableSelect, 5025 tnl_entry, offset, 5026 iptun_mpls_entry_format, 2); 5027 5028 if (label_array[i].flags & 5029 BCM_MPLS_EGRESS_LABEL_ECN_EXP_MAP_TRUST) { 5030 bcmi_egr_ip_tnl_mpls_entry_format_set(unit, 5031 bcmiPktEcnToExpPriority, 5032 tnl_entry, offset, 5033 iptun_mpls_entry_format, 1); 5034 } else { 5035 bcmi_egr_ip_tnl_mpls_entry_format_set(unit, 5036 bcmiPktEcnToExpPriority, 5037 tnl_entry, offset, 5038 iptun_mpls_entry_format, 0); 5039 } 5040 } else 5041 #endif 5042 { 5043 /* Coverity issue ignored: 5044 * It cannot overrun size by 8 since the macro 5045 * _BCM_MPLS_NUM_MPLS_ENTRIES_PER_INDEX is 8 or 4 5046 * hence, the scenario does not arise */ 5047 /* coverity[overrun-local : FALSE] */ 5048 soc_mem_field32_set(unit, EGR_IP_TUNNEL_MPLSm, &tnl_entry, 5049 _tnl_ecn_ptr_f[offset], 5050 ecn_map_hw_idx); 5051 if (label_array[i].flags & 5052 BCM_MPLS_EGRESS_LABEL_ECN_EXP_MAP_TRUST) { 5053 /* coverity[overrun-local : FALSE] */ 5054 soc_mem_field32_set(unit, EGR_IP_TUNNEL_MPLSm, &tnl_entry, 5055 _tnl_ecn_ptr_pri_f[offset], 1); 5056 } else { 5057 /* coverity[overrun-local : FALSE] */ 5058 soc_mem_field32_set(unit, EGR_IP_TUNNEL_MPLSm, &tnl_entry, 5059 _tnl_ecn_ptr_pri_f[offset], 0); 5060 5061 } 5062 } 5063 } 5064 if (label_array[i].flags & BCM_MPLS_EGRESS_LABEL_INT_CN_TO_EXP_MAP) { 5065 int ecn_map_index; 5066 int ecn_map_type; 5067 int ecn_map_num; 5068 int ecn_map_hw_idx; 5069 soc_mem_t mem; 5070 ecn_map_type = label_array[i].int_cn_map_id & 5071 _BCM_XGS5_MPLS_ECN_MAP_TYPE_MASK; 5072 ecn_map_index = label_array[i].int_cn_map_id & 5073 _BCM_XGS5_MPLS_ECN_MAP_NUM_MASK; 5074 5075 #if defined(BCM_TRIDENT3_SUPPORT) 5076 if(soc_feature(unit, soc_feature_td3_style_mpls)) { 5077 mem = EGR_PKT_ECN_TO_EXP_MAPPING_1m; 5078 } else 5079 #endif 5080 { 5081 mem = EGR_IP_ECN_TO_EXP_MAPPING_TABLEm; 5082 } 5083 5084 ecn_map_num = soc_mem_index_count(unit, mem) / 5085 _BCM_ECN_MAX_ENTRIES_PER_MAP; 5086 5087 if (ecn_map_type != _BCM_XGS5_MPLS_ECN_MAP_TYPE_INTCN2EXP) { 5088 rv = BCM_E_PARAM; 5089 goto cleanup; 5090 5091 } 5092 if (ecn_map_index >= ecn_map_num) { 5093 rv = BCM_E_PARAM; 5094 goto cleanup; 5095 } 5096 if (!bcmi_xgs5_ecn_map_used_get(unit, ecn_map_index, 5097 _bcmEcnmapTypeIntcn2Exp)) { 5098 rv = BCM_E_PARAM; 5099 goto cleanup; 5100 } 5101 rv = bcmi_ecn_map_id2hw_idx(unit, label_array[i].int_cn_map_id, 5102 &ecn_map_hw_idx); 5103 if (BCM_FAILURE(rv)) { 5104 goto cleanup; 5105 } 5106 /* Coverity issue ignored: 5107 * It cannot overrun size by 8 since the macro 5108 * _BCM_MPLS_NUM_MPLS_ENTRIES_PER_INDEX is 8 or 4 5109 * hence, the scenario does not arise */ 5110 /* coverity[overrun-local : FALSE] */ 5111 soc_mem_field32_set(unit, EGR_IP_TUNNEL_MPLSm, &tnl_entry, 5112 _tnl_int_cn_ptr_f[offset], 5113 ecn_map_hw_idx); 5114 if (label_array[i].flags & 5115 BCM_MPLS_EGRESS_LABEL_ECN_EXP_MAP_TRUST) { 5116 /* coverity[overrun-local : FALSE] */ 5117 soc_mem_field32_set(unit, EGR_IP_TUNNEL_MPLSm, &tnl_entry, 5118 _tnl_int_cn_ptr_pri_f[offset], 1); 5119 } else { 5120 /* coverity[overrun-local : FALSE] */ 5121 soc_mem_field32_set(unit, EGR_IP_TUNNEL_MPLSm, &tnl_entry, 5122 _tnl_int_cn_ptr_pri_f[offset], 0); 5123 5124 } 5125 } 5126 } 5127 #endif 5128 5129 /*After filling all fields in EGR_IP_TUNNEL_MPLS_ENTRY_FORMAT 5130 *set MPLS_ENTRY_Xf*/ 5131 /* Coverity issue ignored: 5132 * It cannot overrun size by 8 since the macro 5133 * _BCM_MPLS_NUM_MPLS_ENTRIES_PER_INDEX is 8 or 4 5134 * hence, the scenario does not arise */ 5135 /* coverity[overrun-local : FALSE] */ 5136 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 5137 bcmi_egress_tnl_label_entry_set(unit, tnl_entry, 5138 offset, iptun_mpls_entry_format); 5139 } 5140 5141 offset++; 5142 _BCM_MPLS_TNL_USED_SET(unit, mpls_index + i); 5143 } 5144 bcmi_egr_ip_tnl_mpls_ref_count_adjust (unit, 5145 mpls_index, 1); 5146 5147 #if defined(BCM_TRIDENT3_SUPPORT) 5148 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 5149 soc_mem_field32_set(unit, mem, 5150 &tnl_entry, DATA_TYPEf, 0x14); 5151 soc_mem_field32_set(unit, mem, 5152 &tnl_entry, DATA_TYPE_COPYf, 0x14); 5153 } else 5154 #endif 5155 { 5156 soc_mem_field32_set(unit, mem, &tnl_entry, 5157 ENTRY_TYPEf, 0x3); 5158 soc_mem_field32_set(unit, mem, &tnl_entry, 5159 ENTRY_TYPE_COPYf, 0x3); 5160 } 5161 5162 /* Commit the values to HW */ 5163 rv = bcmi_egr_ip_tnl_mpls_table_write(unit, tnl_id, tnl_entry); 5164 if (rv < 0) { 5165 goto cleanup; 5166 } 5167 5168 /* Update the EGR_L3_INTF to point to the MPLS tunnel entry */ 5169 rv = soc_mem_field32_modify(unit, EGR_L3_INTFm, intf, 5170 MPLS_TUNNEL_INDEXf, mpls_index); 5171 if (rv < 0) { 5172 goto cleanup; 5173 } 5174 5175 5176 offset = mpls_index & _BCM_MPLS_EGR_L3_INTF_MPLS_INDEX_OFFSET_MASK(unit); 5177 tnl_id = mpls_index / (_BCM_MPLS_EGR_L3_INTF_MPLS_INDEX_OFFSET_MASK(unit) + 1); 5178 5179 rv = bcmi_egr_ip_tnl_mpls_intf_list_add(unit, tunnel_entry, intf, tnl_id, offset); 5180 if (rv < 0) { 5181 goto cleanup; 5182 } 5183 5184 #ifdef BCM_WARM_BOOT_SUPPORT 5185 SOC_CONTROL_LOCK(unit); 5186 SOC_CONTROL(unit)->scache_dirty = 1; 5187 SOC_CONTROL_UNLOCK(unit); 5188 #endif 5189 5190 return rv; 5191 5192 cleanup: 5193 if (mpls_tunnel_update) { 5194 return rv; 5195 } 5196 if (!found) { 5197 /* Free the tunnel entry */ 5198 (void) bcm_xgs3_tnl_init_del(unit, tnl_flags, tnl_index * 2); 5199 5200 /* Clear "in-use" for the IP tunnel entry */ 5201 _BCM_MPLS_IP_TNL_USED_CLR(unit, tnl_index); 5202 } 5203 /* Clear "in-use" for the MPLS tunnel entry(s) */ 5204 for (i = 0; i < num_labels; i++) { 5205 _BCM_MPLS_TNL_USED_CLR(unit, mpls_index + i); 5206 } 5207 return rv; 5208 } 5209 5210 /* 5211 * Function: 5212 * bcmi_mpls_egr_tunnel_add_free_indexes 5213 * Purpose: 5214 * Adds free index entry into free indexes if the entry is freed. 5215 * Parameters: 5216 * unit - device number 5217 * fi - Pointer to free indexes database. 5218 * num_labels - Number of labels that entry contains. 5219 * mpls_entry_idx - index to mpls entry index that is used up. 5220 * Returns: 5221 * None. 5222 */ 5223 5224 void 5225 bcmi_mpls_egr_tunnel_add_free_indexes(int unit, 5226 bcmi_egr_ip_tnl_free_indexes_t *fi, 5227 int num_labels, int mpls_entry_idx) 5228 { 5229 int tnl_index, mpls_index, offset; 5230 int new_mpls_entry_idx, new_num_elements; 5231 int i=0, j=0; 5232 int ent_per_tnl = _BCM_MPLS_NUM_MPLS_ENTRIES_PER_INDEX(unit); 5233 5234 tnl_index = mpls_entry_idx/ent_per_tnl; 5235 mpls_index = tnl_index * ent_per_tnl; 5236 5237 new_mpls_entry_idx = mpls_entry_idx; 5238 new_num_elements = num_labels; 5239 /* check from the start of an entry */ 5240 for(; i<ent_per_tnl; i++) { 5241 if (_BCM_MPLS_TNL_USED_GET(unit, mpls_index + i)) { 5242 continue; 5243 } 5244 while ((mpls_index + i + j) < mpls_entry_idx) { 5245 5246 if (_BCM_MPLS_TNL_USED_GET(unit, mpls_index + i + j)) { 5247 i += j; 5248 j = 0; 5249 break; 5250 } 5251 j++; 5252 } 5253 } 5254 5255 /* delete this free entry from the free entry db */ 5256 if (j > 0) { 5257 new_mpls_entry_idx = mpls_entry_idx - j; 5258 new_num_elements = num_labels+j; 5259 bcmi_mpls_egr_tunnel_delete_free_indexes(unit, fi, j, 5260 new_mpls_entry_idx); 5261 } 5262 5263 offset = mpls_entry_idx % ent_per_tnl; 5264 offset += num_labels; 5265 5266 j = 0; 5267 /* now check towards end of the entry */ 5268 for(i=offset; i<ent_per_tnl; i++) { 5269 if (_BCM_MPLS_TNL_USED_GET(unit, mpls_index + i)) { 5270 break; 5271 } 5272 5273 j++; 5274 } 5275 if (j > 0) { 5276 /* delete this free entries from free entry db */ 5277 bcmi_mpls_egr_tunnel_delete_free_indexes(unit, fi, j, 5278 mpls_index + offset); 5279 new_num_elements += j; 5280 } 5281 /* Now we can remark this new entry into the database. */ 5282 bcm_egr_ip_tnl_mpls_remark_free_indexes(unit, new_num_elements, 5283 new_mpls_entry_idx, fi); 5284 } 5285 5286 /* 5287 * Function: 5288 * _bcm_tr_mpls_tunnel_initiator_clear 5289 * Purpose: 5290 * Clear MPLS Tunnel initiator 5291 * Parameters: 5292 * unit - (IN)Device Number 5293 * intf - (IN)Egress L3 interface 5294 * Returns: 5295 * BCM_E_XXX 5296 */ 5297 bcm_error_t 5298 bcmi_xgs5_mpls_tunnel_initiator_clear(int unit, int intf_id) 5299 { 5300 egr_l3_intf_entry_t if_entry; 5301 int rv, mpls_offset, mpls_entry_used, i; 5302 int tnl_idx = 0, mpls_index = 0; 5303 uint32 tnl_flags; 5304 _bcm_tr_mpls_bookkeeping_t *mpls_info = MPLS_INFO(unit); 5305 bcmi_egr_ip_tnl_mpls_tunnel_entry_t **tunnel_entry; 5306 bcmi_egr_ip_tnl_free_indexes_t *fi = &(fi_db[unit]); 5307 int mpls_tnl_start_index = 0; 5308 int no_of_elements; 5309 uint32 tnl_entry[SOC_MAX_MEM_WORDS]; 5310 uint32 data_buf[3] = {0}; 5311 5312 tunnel_entry = egr_mpls_tnl_sw_state[unit]; 5313 5314 if (tunnel_entry == NULL) { 5315 return BCM_E_INIT; 5316 } 5317 5318 bcmi_egr_ip_tnl_mpls_table_memset(unit, tnl_entry); 5319 5320 /* L3 interface info */ 5321 rv = READ_EGR_L3_INTFm(unit, MEM_BLOCK_ANY, intf_id, &if_entry); 5322 if (rv < 0) { 5323 return rv; 5324 } 5325 mpls_index = soc_EGR_L3_INTFm_field32_get(unit, &if_entry, 5326 MPLS_TUNNEL_INDEXf); 5327 tnl_idx = mpls_index / _BCM_MPLS_NUM_MPLS_ENTRIES_PER_INDEX(unit); 5328 mpls_tnl_start_index = tnl_idx * _BCM_MPLS_NUM_MPLS_ENTRIES_PER_INDEX(unit); 5329 5330 if (!_BCM_MPLS_TNL_USED_GET(unit, mpls_index)) { 5331 return BCM_E_NOT_FOUND; 5332 } 5333 5334 rv = bcmi_egr_ip_tnl_mpls_table_read(unit, tnl_idx, tnl_entry); 5335 if (rv < 0) { 5336 return rv; 5337 } 5338 5339 rv = bcmi_egr_ip_tnl_mpls_entry_type_check(unit, tnl_entry); 5340 if (rv < 0) { 5341 return BCM_E_NOT_FOUND; 5342 } 5343 5344 mpls_offset = mpls_index & _BCM_MPLS_EGR_L3_INTF_MPLS_INDEX_OFFSET_MASK(unit); 5345 5346 5347 if (tunnel_entry[tnl_idx]->label_entry[mpls_offset]->flags 5348 & BCMI_EGR_IP_TUNNEL_MPLS_START_OF_ENTRY) { 5349 5350 no_of_elements = 5351 tunnel_entry[tnl_idx]->label_entry[mpls_offset]->num_elements; 5352 5353 bcmi_egr_ip_tnl_mpls_ref_count_adjust (unit, mpls_index, -1); 5354 } else { 5355 return BCM_E_NOT_FOUND; 5356 } 5357 5358 rv = bcmi_egr_ip_tnl_mpls_intf_list_delete(unit, tunnel_entry, intf_id, 5359 tnl_idx, mpls_offset); 5360 5361 5362 if (rv < 0) { 5363 return rv; 5364 } 5365 5366 /* Update the EGR_L3_INTF to no longer point to the MPLS tunnel entry */ 5367 rv = soc_mem_field32_modify(unit, EGR_L3_INTFm, intf_id, 5368 MPLS_TUNNEL_INDEXf, 0); 5369 if (rv < 0) { 5370 return rv; 5371 } 5372 5373 if ( mpls_info->egr_tunnel_ref_count[mpls_index] != 0x0 ) { 5374 return BCM_E_NONE; 5375 } 5376 5377 bcm_egr_ip_tnl_mpls_sw_entry_reset(unit, tunnel_entry, tnl_idx, 5378 mpls_offset, 0); 5379 5380 /* Clear the MPLS tunnel entry(s) */ 5381 rv = bcmi_egr_ip_tnl_mpls_table_read(unit,tnl_idx,tnl_entry); 5382 if (rv < 0) { 5383 return rv; 5384 } 5385 5386 for (i=0; i < no_of_elements; i++) { 5387 5388 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 5389 bcmi_egress_tnl_label_entry_set(unit, tnl_entry, 5390 mpls_offset + i, data_buf); 5391 } else { 5392 /*data_buf is dontcare in non TD3*/ 5393 /*label*/ 5394 bcmi_egr_ip_tnl_mpls_entry_format_set(unit, 5395 bcmiMplsLabel, 5396 tnl_entry, mpls_offset + i, 5397 data_buf, 5398 0); 5399 /*Pushaction*/ 5400 bcmi_egr_ip_tnl_mpls_entry_format_set(unit, 5401 bcmiMplsPushAction, 5402 tnl_entry, mpls_offset + i, 5403 data_buf, 5404 0); 5405 /*Expselect*/ 5406 bcmi_egr_ip_tnl_mpls_entry_format_set(unit, 5407 bcmiMplsExpSelect, 5408 tnl_entry, mpls_offset + i, 5409 data_buf, 5410 0); 5411 /*Expptr*/ 5412 bcmi_egr_ip_tnl_mpls_entry_format_set(unit, 5413 bcmiMplsExpMappingPtr, 5414 tnl_entry, mpls_offset + i, 5415 data_buf, 5416 0); 5417 /*Exp*/ 5418 bcmi_egr_ip_tnl_mpls_entry_format_set(unit, 5419 bcmiMplsExp, 5420 tnl_entry, mpls_offset + i, 5421 data_buf, 5422 0); 5423 /*TTl*/ 5424 bcmi_egr_ip_tnl_mpls_entry_format_set(unit, 5425 bcmiMplsTtl, 5426 tnl_entry, mpls_offset + i, 5427 data_buf, 5428 0); 5429 } 5430 #if defined(BCM_TOMAHAWK2_SUPPORT) || defined(BCM_TRIDENT3_SUPPORT) 5431 if (soc_feature(unit, soc_feature_mpls_ecn)) { 5432 if(soc_feature(unit, soc_feature_td3_style_mpls)) { 5433 bcmi_egr_ip_tnl_mpls_entry_format_set(unit, 5434 bcmiPktEcnToExpMappingPtr, 5435 tnl_entry, mpls_offset + i, 5436 data_buf, 5437 0); 5438 5439 bcmi_egr_ip_tnl_mpls_entry_format_set(unit, 5440 bcmiPktEcnToExpPriority, 5441 tnl_entry, mpls_offset + i, 5442 data_buf, 5443 0); 5444 5445 bcmi_egr_ip_tnl_mpls_entry_format_set(unit, 5446 bcmiEcnMappingEnable, 5447 tnl_entry, mpls_offset + i, 5448 data_buf, 5449 0); 5450 5451 bcmi_egr_ip_tnl_mpls_entry_format_set(unit, 5452 bcmiEcnMappingTableSelect, 5453 tnl_entry, mpls_offset + i, 5454 data_buf, 5455 0); 5456 } else { 5457 soc_mem_field32_set(unit, EGR_IP_TUNNEL_MPLSm, &tnl_entry, 5458 _tnl_ecn_ptr_f[mpls_offset + i], 0); 5459 soc_mem_field32_set(unit, EGR_IP_TUNNEL_MPLSm, &tnl_entry, 5460 _tnl_ecn_ptr_pri_f[mpls_offset + i], 0); 5461 soc_mem_field32_set(unit, EGR_IP_TUNNEL_MPLSm, &tnl_entry, 5462 _tnl_int_cn_ptr_f[mpls_offset + i], 0); 5463 soc_mem_field32_set(unit, EGR_IP_TUNNEL_MPLSm, &tnl_entry, 5464 _tnl_int_cn_ptr_pri_f[mpls_offset + i], 0); 5465 } 5466 } 5467 #endif 5468 _BCM_MPLS_TNL_USED_CLR(unit, mpls_index + i); 5469 } 5470 5471 /* See if we can free the IP tunnel base entry */ 5472 _BCM_MPLS_TNL_USED_RANGE_GET(unit, mpls_tnl_start_index, 5473 _BCM_MPLS_NUM_MPLS_ENTRIES_PER_INDEX(unit), mpls_entry_used); 5474 5475 if (!mpls_entry_used) { 5476 /* None of the 4 or 8 entries are used, free base entry */ 5477 tnl_flags = 0; 5478 (void) bcm_xgs3_tnl_init_del(unit, tnl_flags, tnl_idx * 2); 5479 5480 /* Clear "in-use" for the IP tunnel entry */ 5481 _BCM_MPLS_IP_TNL_USED_CLR(unit, tnl_idx); 5482 5483 /* Clear HW Entry-Type */ 5484 #if defined(BCM_TRIDENT3_SUPPORT) 5485 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 5486 soc_mem_field32_set(unit, EGR_IP_TUNNEL_MPLS_DOUBLE_WIDEm, 5487 tnl_entry, DATA_TYPE_COPYf, 0x0); 5488 soc_mem_field32_set(unit, EGR_IP_TUNNEL_MPLS_DOUBLE_WIDEm, 5489 tnl_entry, DATA_TYPEf, 0x0); 5490 } else 5491 #endif 5492 { 5493 soc_mem_field32_set(unit, EGR_IP_TUNNEL_MPLSm, tnl_entry, 5494 ENTRY_TYPEf, 0); 5495 soc_mem_field32_set(unit, EGR_IP_TUNNEL_MPLSm, tnl_entry, 5496 ENTRY_TYPE_COPYf, 0); 5497 } 5498 bcmi_egr_ip_tnl_mpls_free_indexes_clear(unit, tnl_idx, fi); 5499 } else { 5500 bcmi_mpls_egr_tunnel_add_free_indexes(unit, fi, no_of_elements, 5501 mpls_index); 5502 } 5503 5504 rv = bcmi_egr_ip_tnl_mpls_table_write(unit, tnl_idx, tnl_entry); 5505 if (rv < 0) { 5506 return rv; 5507 } 5508 5509 #ifdef BCM_WARM_BOOT_SUPPORT 5510 SOC_CONTROL_LOCK(unit); 5511 SOC_CONTROL(unit)->scache_dirty = 1; 5512 SOC_CONTROL_UNLOCK(unit); 5513 #endif 5514 5515 return BCM_E_NONE; 5516 } 5517 5518 /* 5519 * Function: 5520 * bcmi_xgs5_mpls_tunnel_initiator_clear_all 5521 * Purpose: 5522 * Clear all MPLS Tunnel Initiators 5523 * Parameters: 5524 * unit - (IN)Device Number 5525 * Returns: 5526 * BCM_E_XXX 5527 */ 5528 int 5529 bcmi_xgs5_mpls_tunnel_initiator_clear_all(int unit) 5530 { 5531 egr_l3_intf_entry_t if_entry; 5532 int mpls_index; 5533 int rv=BCM_E_NONE; 5534 int num_ip_tnl_mpls; 5535 int i,j; 5536 soc_mem_t mem; 5537 5538 for (i = 0; i < L3_INFO(unit)->l3_intf_table_size; i++) { 5539 if (!BCM_L3_INTF_USED_GET(unit, i)) { 5540 continue; 5541 } 5542 5543 rv = READ_EGR_L3_INTFm(unit, MEM_BLOCK_ANY, i, &if_entry); 5544 if (rv < 0) { 5545 return rv; 5546 } 5547 mpls_index = soc_EGR_L3_INTFm_field32_get(unit, &if_entry, 5548 MPLS_TUNNEL_INDEXf); 5549 if (!_BCM_MPLS_TNL_USED_GET(unit, mpls_index)) { 5550 continue; 5551 } 5552 rv = bcmi_xgs5_mpls_tunnel_initiator_clear(unit, i); 5553 if (rv < 0) { 5554 return rv; 5555 } 5556 } 5557 5558 /* cleanup the s/w state for tunnel table. */ 5559 mem = bcmi_egr_ip_tnl_mem_name_get(unit); 5560 5561 num_ip_tnl_mpls = soc_mem_index_count(unit, mem); 5562 for (i=0; i<num_ip_tnl_mpls; i++) { 5563 for (j=0; j<_BCM_MPLS_NUM_MPLS_ENTRIES_PER_INDEX(unit); j++) { 5564 bcmi_egr_ip_tnl_mpls_intf_list_delete_all(unit, 5565 egr_mpls_tnl_sw_state[unit], i, j); 5566 5567 egr_mpls_tnl_sw_state[unit][i]->label_entry[j]->intf_list = NULL; 5568 egr_mpls_tnl_sw_state[unit][i]->label_entry[j]->flags = 0; 5569 egr_mpls_tnl_sw_state[unit][i]->label_entry[j]->num_elements = 0; 5570 5571 } 5572 } 5573 5574 /* cleanup the free indexes */ 5575 bcmi_egr_ip_tnl_mpls_free_indexes_init(unit, &(fi_db[unit])); 5576 5577 return rv; 5578 } 5579 5580 5581 /* 5582 * Function: 5583 * bcmi_xgs5_mpls_tunnel_initiator_reinit 5584 * Purpose: 5585 * set s/w state of MPLS tunnel during warmboot. 5586 * Parameters: 5587 * unit - (IN) Device Number 5588 * Returns: 5589 * BCM_E_XXX 5590 */ 5591 bcm_error_t 5592 bcmi_xgs5_mpls_tunnel_initiator_reinit(int unit) 5593 { 5594 int tnl_idx=0, mpls_off = 0; 5595 int start_of_entry = 0; 5596 bcmi_egr_ip_tnl_mpls_tunnel_entry_t **tunnel_entry; 5597 /* Indexes to iterate over memories, chunks and entries */ 5598 int chnk_idx, ent_idx, chnk_idx_max, mem_idx_max; 5599 int buf_size, chunksize, chnk_end; 5600 uint32 *tbl_chnk; 5601 uint32 *el3inf_entry; 5602 int rv = BCM_E_NONE; 5603 soc_mem_t mem; 5604 int last_push_action = 0; 5605 int num_labels = 0; 5606 int push_action = 0; 5607 int mpls_offset = 0; 5608 int mpls_index = 0; 5609 int index_min, index_max; 5610 uint8 *tunnel_entry_buf = NULL; 5611 #if defined(BCM_TRIDENT3_SUPPORT) 5612 egr_ip_tunnel_mpls_double_wide_entry_t *tnl_entry_double = NULL; 5613 uint32 iptun_mpls_entry_format[3] = {0}; 5614 #endif 5615 egr_ip_tunnel_mpls_entry_t *tnl_entry = NULL; 5616 5617 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 5618 mem = EGR_IP_TUNNEL_MPLS_DOUBLE_WIDEm; 5619 } else { 5620 mem = EGR_IP_TUNNEL_MPLSm; 5621 } 5622 5623 tunnel_entry = egr_mpls_tnl_sw_state[unit]; 5624 5625 tunnel_entry_buf = soc_cm_salloc(unit, 5626 SOC_MEM_TABLE_BYTES(unit, mem), "MPLS TUNNEL ENTRY buffer"); 5627 if (NULL == tunnel_entry_buf) { 5628 return BCM_E_MEMORY; 5629 } 5630 5631 index_min = soc_mem_index_min(unit, mem); 5632 index_max = soc_mem_index_max(unit, mem); 5633 rv = soc_mem_read_range(unit, mem, MEM_BLOCK_ANY, 5634 index_min, index_max, tunnel_entry_buf); 5635 if (SOC_FAILURE(rv)) { 5636 soc_cm_sfree(unit, tunnel_entry_buf); 5637 return rv; 5638 } 5639 5640 for (tnl_idx = index_min; tnl_idx <= index_max; tnl_idx++) { 5641 5642 if (!_BCM_MPLS_IP_TNL_USED_GET(unit, tnl_idx)) { 5643 continue; 5644 } 5645 5646 last_push_action = 0; 5647 start_of_entry = 0; 5648 num_labels = 0; 5649 5650 #if defined(BCM_TRIDENT3_SUPPORT) 5651 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 5652 tnl_entry_double = soc_mem_table_idx_to_pointer 5653 (unit, EGR_IP_TUNNEL_MPLS_DOUBLE_WIDEm, 5654 egr_ip_tunnel_mpls_double_wide_entry_t *, 5655 tunnel_entry_buf, tnl_idx); 5656 } else 5657 #endif 5658 { 5659 tnl_entry = soc_mem_table_idx_to_pointer 5660 (unit, EGR_IP_TUNNEL_MPLSm, egr_ip_tunnel_mpls_entry_t *, tunnel_entry_buf, tnl_idx); 5661 } 5662 5663 /* Check for valid entry */ 5664 5665 for(mpls_off = 0; mpls_off<_BCM_MPLS_NUM_MPLS_ENTRIES_PER_INDEX(unit); mpls_off++) { 5666 mpls_index = tnl_idx * _BCM_MPLS_NUM_MPLS_ENTRIES_PER_INDEX(unit) + mpls_off; 5667 5668 if (!_BCM_MPLS_TNL_USED_GET(unit, mpls_index)) { 5669 start_of_entry = 0; 5670 last_push_action = 0; 5671 num_labels = 0; 5672 continue; 5673 } 5674 5675 if (last_push_action == 2) { 5676 start_of_entry = 0; 5677 } else { 5678 start_of_entry = 1; 5679 } 5680 5681 if (start_of_entry) { 5682 tunnel_entry[tnl_idx]->label_entry[mpls_off]->flags |= 5683 BCMI_EGR_IP_TUNNEL_MPLS_START_OF_ENTRY; 5684 } 5685 5686 #if defined(BCM_TRIDENT3_SUPPORT) 5687 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 5688 soc_mem_field_get(unit, mem, 5689 (uint32 *)tnl_entry_double, 5690 _tnl_label_entry_f[mpls_off], 5691 iptun_mpls_entry_format); 5692 5693 bcmi_egr_ip_tnl_mpls_entry_format_get(unit, 5694 tnl_entry_double, mpls_off, 5695 iptun_mpls_entry_format, bcmiMplsPushAction, 5696 (uint32 *)&push_action); 5697 } else 5698 #endif 5699 { 5700 push_action = soc_mem_field32_get(unit, mem, 5701 tnl_entry, _tnl_push_action_f[mpls_off]); 5702 } 5703 5704 if (push_action == 2) { 5705 num_labels++; 5706 } else { 5707 if (last_push_action == 2) { 5708 mpls_offset = mpls_off-num_labels; 5709 } else { 5710 mpls_offset = mpls_off; 5711 } 5712 num_labels++; 5713 tunnel_entry[tnl_idx]->label_entry[mpls_offset]->num_elements = 5714 num_labels; 5715 start_of_entry = 0; 5716 num_labels = 0; 5717 } 5718 last_push_action = push_action; 5719 } 5720 } 5721 5722 soc_cm_sfree(unit, tunnel_entry_buf); 5723 5724 /* need to look into EGR_L3_INTF table to get interface entry */ 5725 mem = EGR_L3_INTFm; 5726 5727 chunksize = 0x400; /* 1k */ 5728 buf_size = sizeof(egr_l3_intf_entry_t) * chunksize; 5729 tbl_chnk = soc_cm_salloc(unit, buf_size, "egr_l3_intf traverse"); 5730 if (NULL == tbl_chnk) { 5731 return BCM_E_MEMORY; 5732 } 5733 5734 mem_idx_max = soc_mem_index_max(unit, mem); 5735 for (chnk_idx = soc_mem_index_min(unit, mem); 5736 chnk_idx <= mem_idx_max; 5737 chnk_idx += chunksize) { 5738 sal_memset((void *)tbl_chnk, 0, buf_size); 5739 5740 chnk_idx_max = 5741 ((chnk_idx + chunksize) <= mem_idx_max) ? 5742 chnk_idx + chunksize - 1: mem_idx_max; 5743 5744 soc_mem_lock(unit, mem); 5745 rv = soc_mem_read_range(unit, mem, MEM_BLOCK_ANY, 5746 chnk_idx, chnk_idx_max, tbl_chnk); 5747 if (SOC_FAILURE(rv)) { 5748 soc_mem_unlock(unit, mem); 5749 break; 5750 } 5751 chnk_end = (chnk_idx_max - chnk_idx); 5752 for (ent_idx = 0 ; ent_idx <= chnk_end; ent_idx ++) { 5753 el3inf_entry = 5754 soc_mem_table_idx_to_pointer(unit, mem, uint32 *, 5755 tbl_chnk, ent_idx); 5756 5757 mpls_index = soc_mem_field32_get(unit, mem, el3inf_entry, 5758 MPLS_TUNNEL_INDEXf); 5759 5760 if (!mpls_index) { 5761 continue; 5762 } 5763 5764 tnl_idx = mpls_index / 5765 _BCM_MPLS_NUM_MPLS_ENTRIES_PER_INDEX(unit); 5766 mpls_off = mpls_index % 5767 _BCM_MPLS_NUM_MPLS_ENTRIES_PER_INDEX(unit); 5768 5769 rv = bcmi_egr_ip_tnl_mpls_intf_list_add(unit, tunnel_entry, 5770 chnk_idx + ent_idx, tnl_idx, mpls_off); 5771 if (BCM_FAILURE(rv)) { 5772 break; 5773 } 5774 } 5775 soc_mem_unlock(unit, mem); 5776 if (BCM_FAILURE(rv)) { 5777 break; 5778 } 5779 } 5780 5781 soc_cm_sfree(unit, tbl_chnk); 5782 return BCM_E_NONE; 5783 } 5784 5785 /* 5786 * Function: 5787 * bcmi_xgs5_mpls_tunnel_initiator_get 5788 * Purpose: 5789 * Get MPLS Tunnel Initiator info 5790 * Parameters: 5791 * unit - (IN) Device Number 5792 * intf - (IN) The egress L3 interface 5793 * label_max - (IN) Number of entries in label_array 5794 * label_array - (OUT) MPLS header information 5795 * label_count - (OUT) Actual number of labels returned 5796 * Returns: 5797 * BCM_E_XXX 5798 */ 5799 int 5800 bcmi_xgs5_mpls_tunnel_initiator_get(int unit, bcm_if_t intf, int label_max, 5801 bcm_mpls_egress_label_t *label_array, 5802 int *label_count) 5803 { 5804 egr_l3_intf_entry_t if_entry; 5805 int rv, i, ix, offset; 5806 int tnl_index = 0, mpls_index = 0; 5807 bcmi_egr_ip_tnl_mpls_tunnel_entry_t **tunnel_entry = egr_mpls_tnl_sw_state[unit]; 5808 int no_of_elements; 5809 int mpls_exp_select=0,mpls_tnl_ttl=0; 5810 uint32 iptun_mpls_entry_format[3]; 5811 uint32 tnl_lbl=0, tnl_exp=0, tnl_exp_ptr=0; 5812 uint32 tnl_pri=0, tnl_cfi=0; 5813 uint32 tnl_entry[SOC_MAX_MEM_WORDS]; 5814 5815 bcmi_egr_ip_tnl_mpls_table_memset(unit, tnl_entry); 5816 5817 if ((label_array == NULL) || 5818 (intf < 0) || (intf >= L3_INFO(unit)->l3_intf_table_size)) { 5819 return BCM_E_PARAM; 5820 } 5821 5822 if (!BCM_L3_INTF_USED_GET(unit, intf)) { 5823 LOG_INFO(BSL_LS_BCM_L3, 5824 (BSL_META_U(unit, 5825 "L3 interface not created\n"))); 5826 return BCM_E_NOT_FOUND; 5827 } 5828 5829 /* L3 interface info */ 5830 rv = READ_EGR_L3_INTFm(unit, MEM_BLOCK_ANY, intf, &if_entry); 5831 if (rv < 0) { 5832 return rv; 5833 } 5834 mpls_index = soc_EGR_L3_INTFm_field32_get(unit, &if_entry, 5835 MPLS_TUNNEL_INDEXf); 5836 tnl_index = mpls_index / _BCM_MPLS_NUM_MPLS_ENTRIES_PER_INDEX(unit); 5837 5838 if (!_BCM_MPLS_TNL_USED_GET(unit, mpls_index)) { 5839 return BCM_E_NOT_FOUND; 5840 } 5841 5842 rv = bcmi_egr_ip_tnl_mpls_table_read(unit, tnl_index, tnl_entry); 5843 5844 if (rv < 0) { 5845 return rv; 5846 } 5847 5848 5849 rv = bcmi_egr_ip_tnl_mpls_entry_type_check(unit, tnl_entry); 5850 5851 if (rv < 0) { 5852 return BCM_E_NOT_FOUND; 5853 } 5854 5855 *label_count = 0; 5856 sal_memset(label_array, 0, sizeof(bcm_mpls_egress_label_t) * label_max); 5857 offset = mpls_index & _BCM_MPLS_EGR_L3_INTF_MPLS_INDEX_OFFSET_MASK(unit); 5858 if (tunnel_entry[tnl_index]->label_entry[offset]->flags 5859 & BCMI_EGR_IP_TUNNEL_MPLS_START_OF_ENTRY) { 5860 5861 if (tunnel_entry[tnl_index]->label_entry[offset]->flags 5862 & BCMI_EGR_IP_TUNNEL_MPLS_ENTRY_ZERO) { 5863 no_of_elements = 0; 5864 } else { 5865 no_of_elements = 5866 tunnel_entry[tnl_index]->label_entry[offset]->num_elements; 5867 } 5868 5869 } else { 5870 return BCM_E_NOT_FOUND; 5871 } 5872 5873 if (label_max < no_of_elements) { 5874 *label_count = label_max; 5875 } else { 5876 *label_count = no_of_elements; 5877 } 5878 5879 5880 for (i = 0; i < *label_count; i++) { 5881 bcmi_egress_tnl_label_entry_get(unit, tnl_entry, 5882 offset + i,iptun_mpls_entry_format); 5883 5884 bcmi_egr_ip_tnl_mpls_entry_format_get(unit, 5885 tnl_entry, offset + i, 5886 iptun_mpls_entry_format, bcmiSpecialLabelPushType, 5887 ((uint32 *)(&(label_array[i].spl_label_push_type)))); 5888 5889 bcmi_egr_ip_tnl_mpls_entry_format_get(unit, 5890 tnl_entry, offset + i, 5891 iptun_mpls_entry_format, bcmiMplsLabel, 5892 &tnl_lbl); 5893 5894 label_array[i].label = tnl_lbl; 5895 bcmi_egr_ip_tnl_mpls_entry_format_get(unit, 5896 tnl_entry, offset + i, 5897 iptun_mpls_entry_format, bcmiMplsTtl, 5898 (uint32 *)&mpls_tnl_ttl); 5899 5900 bcmi_egr_ip_tnl_mpls_entry_format_get(unit, 5901 tnl_entry, offset + i, 5902 iptun_mpls_entry_format, bcmiMplsExpSelect, 5903 (uint32 *)&mpls_exp_select); 5904 5905 if (mpls_exp_select == 0x0) { 5906 /* Use the specified EXP, PRI and CFI */ 5907 label_array[i].flags |= BCM_MPLS_EGRESS_LABEL_EXP_SET; 5908 label_array[i].flags |= BCM_MPLS_EGRESS_LABEL_PRI_SET; 5909 5910 bcmi_egr_ip_tnl_mpls_entry_format_get(unit, 5911 tnl_entry, offset + i, 5912 iptun_mpls_entry_format, bcmiMplsExp, 5913 &tnl_exp); 5914 5915 label_array[i].exp = tnl_exp; 5916 bcmi_egr_ip_tnl_mpls_entry_format_get(unit, 5917 tnl_entry, offset + i, 5918 iptun_mpls_entry_format, bcmiNewPri, 5919 &tnl_pri); 5920 5921 label_array[i].pkt_pri = tnl_pri; 5922 bcmi_egr_ip_tnl_mpls_entry_format_get(unit, 5923 tnl_entry, offset + i, 5924 iptun_mpls_entry_format, bcmiNewCfi, 5925 &tnl_cfi); 5926 5927 label_array[i].pkt_cfi = tnl_cfi; 5928 5929 } else if (mpls_exp_select == 0x1) { 5930 /* Use EXP-map for EXP, PRI and CFI */ 5931 label_array[i].flags |= BCM_MPLS_EGRESS_LABEL_EXP_REMARK; 5932 label_array[i].flags |= BCM_MPLS_EGRESS_LABEL_PRI_REMARK; 5933 5934 bcmi_egr_ip_tnl_mpls_entry_format_get(unit, 5935 tnl_entry, offset + i, 5936 iptun_mpls_entry_format, bcmiMplsExpMappingPtr, 5937 &tnl_exp_ptr); 5938 5939 ix = tnl_exp_ptr; 5940 5941 BCM_IF_ERROR_RETURN( 5942 _egr_qos_hw_idx2id(unit, ix, &label_array[i].qos_map_id)); 5943 } else { 5944 /* Use EXP from incoming label. If there is no incoming label, 5945 * use the specified EXP value. 5946 */ 5947 label_array[i].flags |= BCM_MPLS_EGRESS_LABEL_EXP_COPY; 5948 label_array[i].flags |= BCM_MPLS_EGRESS_LABEL_PRI_REMARK; 5949 5950 bcmi_egr_ip_tnl_mpls_entry_format_get(unit, 5951 tnl_entry, offset + i, 5952 iptun_mpls_entry_format, bcmiMplsExp, 5953 &tnl_exp); 5954 5955 label_array[i].exp = tnl_exp; 5956 bcmi_egr_ip_tnl_mpls_entry_format_get(unit, 5957 tnl_entry, offset + i, 5958 iptun_mpls_entry_format, bcmiMplsExpMappingPtr, 5959 &tnl_exp_ptr); 5960 5961 ix = tnl_exp_ptr; 5962 BCM_IF_ERROR_RETURN( 5963 _egr_qos_hw_idx2id(unit, ix, &label_array[i].qos_map_id)); 5964 } 5965 5966 if (mpls_tnl_ttl){ 5967 /* Use specified TTL value */ 5968 label_array[i].flags |= BCM_MPLS_EGRESS_LABEL_TTL_SET; 5969 label_array[i].ttl = mpls_tnl_ttl; 5970 } else { 5971 label_array[i].flags |= BCM_MPLS_EGRESS_LABEL_TTL_DECREMENT; 5972 } 5973 #if defined(BCM_TOMAHAWK2_SUPPORT) || defined(BCM_TRIDENT3_SUPPORT) 5974 if (soc_feature(unit, soc_feature_mpls_ecn)) { 5975 int ecn_map_trust; 5976 int ecn_map_hw_idx; 5977 int ecn_map_id; 5978 int rv; 5979 5980 if(soc_feature(unit, soc_feature_td3_style_mpls)) { 5981 bcmi_egr_ip_tnl_mpls_entry_format_get(unit, 5982 tnl_entry, offset + i, 5983 iptun_mpls_entry_format, bcmiPktEcnToExpMappingPtr, 5984 (uint32 *)&ecn_map_hw_idx); 5985 } else { 5986 ecn_map_hw_idx = soc_mem_field32_get(unit, EGR_IP_TUNNEL_MPLSm, 5987 &tnl_entry, 5988 _tnl_ecn_ptr_f[offset + i]); 5989 } 5990 5991 rv = bcmi_ecn_map_hw_idx2id(unit, ecn_map_hw_idx, 5992 _BCM_XGS5_MPLS_ECN_MAP_TYPE_ECN2EXP, 5993 &ecn_map_id); 5994 if (BCM_SUCCESS(rv)) { 5995 label_array[i].flags |= BCM_MPLS_EGRESS_LABEL_ECN_TO_EXP_MAP; 5996 label_array[i].ecn_map_id = ecn_map_id; 5997 5998 if(soc_feature(unit, soc_feature_td3_style_mpls)) { 5999 bcmi_egr_ip_tnl_mpls_entry_format_get(unit, 6000 tnl_entry, offset + i, 6001 iptun_mpls_entry_format, bcmiPktEcnToExpPriority, 6002 (uint32 *)&ecn_map_trust); 6003 } else { 6004 ecn_map_trust = soc_mem_field32_get(unit, EGR_IP_TUNNEL_MPLSm, 6005 &tnl_entry, 6006 _tnl_ecn_ptr_pri_f[offset + i]); 6007 } 6008 if (ecn_map_trust) { 6009 label_array[i].flags |= BCM_MPLS_EGRESS_LABEL_ECN_EXP_MAP_TRUST; 6010 } 6011 } 6012 6013 if (!soc_feature(unit, soc_feature_intcn_to_exp_nosupport)) { 6014 ecn_map_hw_idx = soc_mem_field32_get(unit, EGR_IP_TUNNEL_MPLSm, 6015 &tnl_entry, 6016 _tnl_int_cn_ptr_f[offset + i]); 6017 rv = bcmi_ecn_map_hw_idx2id(unit, ecn_map_hw_idx, 6018 _BCM_XGS5_MPLS_ECN_MAP_TYPE_INTCN2EXP, 6019 &ecn_map_id); 6020 if (BCM_SUCCESS(rv)) { 6021 label_array[i].flags |= BCM_MPLS_EGRESS_LABEL_INT_CN_TO_EXP_MAP; 6022 label_array[i].int_cn_map_id = ecn_map_id; 6023 ecn_map_trust = soc_mem_field32_get(unit, EGR_IP_TUNNEL_MPLSm, 6024 &tnl_entry, 6025 _tnl_int_cn_ptr_pri_f[offset + i]); 6026 if (ecn_map_trust) { 6027 label_array[i].flags |= BCM_MPLS_EGRESS_LABEL_ECN_EXP_MAP_TRUST; 6028 } 6029 } 6030 } 6031 } 6032 #endif 6033 } 6034 6035 return BCM_E_NONE; 6036 } 6037 /* 6038 * Function: 6039 * bcmi_xgs5_mpls_failover_nw_port_match_get 6040 * Purpose: 6041 * Get match criteria of an MPLS port 6042 * Parameters: 6043 * unit - (IN) Device Number 6044 * mpls_port - (IN) mpls port information 6045 * vp - (IN) Source Virtual Port 6046 * return_ment - (OUT) matched entry 6047 * Returns: 6048 * BCM_E_XXX 6049 */ 6050 int 6051 bcmi_xgs5_mpls_failover_nw_port_match_get(int unit, bcm_mpls_port_t *mpls_port, 6052 int vp, mpls_entry_entry_t *return_ment) 6053 { 6054 _bcm_tr_mpls_bookkeeping_t *mpls_info = MPLS_INFO(unit); 6055 mpls_entry_entry_t ment; 6056 int entry_index = -1; 6057 int key_type = 0x00; /* mpls_key_type */ 6058 int rv = BCM_E_NONE; 6059 bcm_module_t mod_out; 6060 bcm_port_t port_out; 6061 bcm_trunk_t trunk_id; 6062 bcm_gport_t gport_id; 6063 soc_mem_t mem = MPLS_ENTRYm; 6064 soc_field_t validf = VALIDf; 6065 6066 if (soc_feature(unit, soc_feature_th3_style_simple_mpls)) { 6067 mem = MPLS_ENTRY_SINGLEm; 6068 validf = BASE_VALIDf; 6069 } 6070 6071 /* return not found if both inputs are invalid. */ 6072 if ((mpls_port == NULL) && (vp == -1)) { 6073 return BCM_E_NOT_FOUND; 6074 } 6075 6076 sal_memset(&ment, 0, sizeof(mpls_entry_entry_t)); 6077 if (mpls_port != NULL) { 6078 if (mpls_port->criteria == BCM_MPLS_PORT_MATCH_LABEL_PORT) { 6079 /* Check for Port_independent Label mapping */ 6080 rv = bcm_tr_mpls_port_independent_range (unit, mpls_port->match_label, mpls_port->port); 6081 if (rv < 0) { 6082 return rv; 6083 } 6084 6085 rv = _bcm_esw_gport_resolve(unit, mpls_port->port, &mod_out, 6086 &port_out, &trunk_id, &gport_id); 6087 BCM_IF_ERROR_RETURN(rv); 6088 6089 if (BCM_GPORT_IS_TRUNK(mpls_port->port)) { 6090 soc_mem_field32_set(unit, mem, &ment, MPLS__Tf, 1); 6091 soc_mem_field32_set(unit, mem, &ment, MPLS__TGIDf, mpls_port->port); 6092 } else { 6093 if (SOC_MEM_FIELD_VALID(unit, mem, MPLS__MODULE_IDf)) { 6094 soc_mem_field32_set(unit, mem, &ment, MPLS__MODULE_IDf, mod_out); 6095 } 6096 soc_mem_field32_set(unit, mem, &ment, MPLS__PORT_NUMf, port_out); 6097 } 6098 } else if (mpls_port->criteria == BCM_MPLS_PORT_MATCH_LABEL) { 6099 if (SOC_MEM_FIELD_VALID(unit, mem, MPLS__MODULE_IDf)) { 6100 soc_mem_field32_set(unit, mem, &ment, MPLS__MODULE_IDf, 0); 6101 } 6102 soc_mem_field32_set(unit, mem, &ment, MPLS__PORT_NUMf, 0); 6103 } else { 6104 return BCM_E_NOT_FOUND; 6105 } 6106 6107 /* Use old label to get old mpls entry for replace operation */ 6108 soc_mem_field32_set(unit, mem, &ment, MPLS__MPLS_LABELf, 6109 mpls_port->match_label); 6110 6111 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 6112 soc_mem_field32_set(unit, mem, &ment, BASE_VALID_0f, 3); 6113 soc_mem_field32_set(unit, mem, &ment, BASE_VALID_1f, 7); 6114 } else { 6115 soc_mem_field32_set(unit, mem, &ment, validf, 1); 6116 } 6117 6118 soc_mem_field32_set(unit, mem, &ment, KEY_TYPEf, key_type); 6119 } else { 6120 6121 if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeMpls)) { 6122 return BCM_E_NOT_FOUND; 6123 } 6124 6125 if ((mpls_info->match_key[vp].flags & 6126 _BCM_MPLS_PORT_MATCH_TYPE_LABEL) || 6127 (mpls_info->match_key[vp].flags == 6128 _BCM_MPLS_PORT_MATCH_TYPE_LABEL_PORT)) { 6129 6130 if (mpls_info->match_key[vp].flags & 6131 _BCM_MPLS_PORT_MATCH_TYPE_LABEL_PORT) { 6132 6133 if (mpls_info->match_key[vp].trunk_id != -1) { 6134 soc_mem_field32_set(unit, mem, &ment, MPLS__Tf, 1); 6135 soc_mem_field32_set(unit, mem, &ment, MPLS__TGIDf, 6136 mpls_info->match_key[vp].trunk_id); 6137 } else { 6138 if (SOC_MEM_FIELD_VALID(unit, mem, MPLS__MODULE_IDf)) { 6139 soc_mem_field32_set(unit, mem, &ment, MPLS__MODULE_IDf, 6140 mpls_info->match_key[vp].modid); 6141 } 6142 soc_mem_field32_set(unit, mem, &ment, MPLS__PORT_NUMf, 6143 mpls_info->match_key[vp].port); 6144 } 6145 } 6146 6147 soc_mem_field32_set(unit, mem, &ment, MPLS__MPLS_LABELf, 6148 mpls_info->match_key[vp].match_label); 6149 soc_mem_field32_set(unit, mem, &ment, KEY_TYPEf, key_type); 6150 6151 } else { 6152 return BCM_E_NOT_FOUND; 6153 } 6154 } 6155 6156 rv = soc_mem_search(unit, mem, MEM_BLOCK_ANY, &entry_index, 6157 &ment, return_ment, 0); 6158 6159 return rv; 6160 } 6161 6162 STATIC int 6163 _bcmi_mpls_entry_field_val_set(int unit, void *tnl_buf, soc_field_t field, 6164 uint32 *p_fn_data, uint32 *set_val, 6165 uint32 offset, uint32 width) 6166 { 6167 int rv = BCM_E_NONE; 6168 6169 #if defined(BCM_TRIDENT3_SUPPORT) 6170 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 6171 uint32 u32_mask; 6172 int idx, wp, bp, len; 6173 6174 if (NULL == p_fn_data || NULL == set_val) { 6175 LOG_VERBOSE(BSL_LS_BCM_MPLS, (BSL_META("Invalid Parameters\n"))); 6176 return BCM_E_PARAM; 6177 } 6178 6179 wp = offset / 32; 6180 bp = offset & (32 - 1); 6181 idx = 0; 6182 6183 for (len = width; len > 0; len -= 32) { 6184 if (bp) { 6185 if (len < 32) { 6186 u32_mask = (1 << len) - 1; 6187 if ((set_val[idx] & ~u32_mask) != 0) { 6188 return (BCM_E_PARAM); 6189 } 6190 } else { 6191 u32_mask = 0xffffffff; 6192 } 6193 6194 p_fn_data[wp] &= ~(u32_mask << bp); 6195 p_fn_data[wp++] |= set_val[idx] << bp; 6196 p_fn_data[wp] &= ~(u32_mask >> (32 - bp)); 6197 p_fn_data[wp] |= set_val[idx] >> (32 - bp) & ((1 << bp) - 1); 6198 6199 } else { 6200 if (len < 32) { 6201 u32_mask = (1 << len) - 1; 6202 if ((set_val[idx] & ~u32_mask) != 0) { 6203 return (BCM_E_PARAM); 6204 } 6205 p_fn_data[wp] &= ~u32_mask; 6206 p_fn_data[wp++] |= set_val[idx]; 6207 } else { 6208 p_fn_data[wp++] = set_val[idx]; 6209 } 6210 } 6211 6212 idx++; 6213 } 6214 } else 6215 #endif 6216 { 6217 soc_mem_field32_set(unit, EGR_IP_TUNNEL_MPLSm, tnl_buf, 6218 field, *set_val); 6219 } 6220 6221 return rv; 6222 } 6223 6224 STATIC int 6225 _bcmi_mpls_entry_field_val_get(int unit, void *tnl_buf, soc_field_t field, 6226 uint32 *p_fn_data, uint32 *p_data, 6227 uint32 offset, uint32 width) 6228 { 6229 6230 int rv = BCM_E_NONE; 6231 6232 #if defined(BCM_TRIDENT3_SUPPORT) 6233 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 6234 int idx, wp, bp, len; 6235 6236 /* Input parameters check. */ 6237 if (NULL == p_fn_data || NULL == p_data) { 6238 LOG_VERBOSE(BSL_LS_BCM_MPLS, (BSL_META("Invalid Parameters\n"))); 6239 return (BCM_E_PARAM); 6240 } 6241 6242 wp = offset / 32; 6243 bp = offset & (32 - 1); 6244 idx = 0; 6245 6246 for (len = width; len > 0; len -= 32) { 6247 if (bp) { 6248 p_data[idx] = (p_fn_data[wp++] >> bp) & ((1 << (32 - bp)) - 1); 6249 p_data[idx] |= p_fn_data[wp] << (32 - bp); 6250 } else { 6251 p_data[idx] = p_fn_data[wp++]; 6252 } 6253 6254 if (len < 32) { 6255 p_data[idx] &= ((1 << len) - 1); 6256 } 6257 6258 idx++; 6259 } 6260 } else 6261 #endif 6262 { 6263 soc_mem_t mem; 6264 uint32 value; 6265 mem = bcmi_egr_ip_tnl_mem_name_get(unit); 6266 value = soc_mem_field32_get(unit, mem, tnl_buf, field); 6267 *p_data = value; 6268 } 6269 return rv; 6270 } 6271 6272 6273 /* 6274 * Function: 6275 * bcmi_egr_ip_tnl_mpls_entry_format_set 6276 * Purpose: 6277 * Set egress ip tunnel mpls entry format fields 6278 * Parameters: 6279 * unit - (IN) Device Number 6280 * field_type - (IN) Field type 6281 * tnl_buf - (IN) tnl entry buffer 6282 * lbl_offset - (OUT) offset 6283 * rebuf - (OUT) return buffer 6284 * value - (IN) value 6285 * Returns: 6286 * BCM_E_XXX 6287 */ 6288 int 6289 bcmi_egr_ip_tnl_mpls_entry_format_set(int unit,int field_type, 6290 void *tnl_buf, int lbl_offset, 6291 uint32 *retbuf, int value) 6292 { 6293 int rv = BCM_E_NONE; 6294 uint32 set_val = 0; 6295 set_val = value; 6296 6297 /*use tnl_buf,lbl_offset is non TD3 chips, 6298 *retbuf,offset,width is dont care. 6299 *use retbuf in TD3 tnl_buf,lbl_offset is dontcare. 6300 *Yet to set few fields in non TD3 chips*/ 6301 switch (field_type) { 6302 case bcmiMplsLabel: 6303 6304 rv = bcmi_validate_field_range(unit, set_val, 20); 6305 _bcmi_mpls_entry_field_val_set(unit, tnl_buf, 6306 _tnl_label_f[lbl_offset], retbuf, &set_val, 0, 20); 6307 break; 6308 case bcmiMplsPushAction: 6309 6310 rv = bcmi_validate_field_range(unit, set_val, 2); 6311 _bcmi_mpls_entry_field_val_set(unit, tnl_buf, 6312 _tnl_push_action_f[lbl_offset], retbuf, &set_val, 20, 2); 6313 break; 6314 case bcmiMplsExpSelect: 6315 6316 rv = bcmi_validate_field_range(unit, set_val, 2); 6317 _bcmi_mpls_entry_field_val_set(unit, tnl_buf, 6318 _tnl_exp_select_f[lbl_offset], retbuf, &set_val, 22, 2); 6319 break; 6320 case bcmiMplsExpMappingPtr: 6321 6322 rv = bcmi_validate_field_range(unit, set_val, 4); 6323 _bcmi_mpls_entry_field_val_set(unit, tnl_buf, 6324 _tnl_exp_ptr_f[lbl_offset], retbuf, &set_val, 24, 4); 6325 break; 6326 case bcmiNewCfi: 6327 6328 rv = bcmi_validate_field_range(unit, set_val, 1); 6329 _bcmi_mpls_entry_field_val_set(unit, tnl_buf, 6330 _tnl_cfi_f[lbl_offset], retbuf, &set_val, 24, 1); 6331 break; 6332 case bcmiNewPri: 6333 6334 rv = bcmi_validate_field_range(unit, set_val, 3); 6335 _bcmi_mpls_entry_field_val_set(unit, tnl_buf, 6336 _tnl_pri_f[lbl_offset], retbuf, &set_val, 25, 3); 6337 break; 6338 case bcmiMplsExp: 6339 6340 rv = bcmi_validate_field_range(unit, set_val, 3); 6341 _bcmi_mpls_entry_field_val_set(unit, tnl_buf, 6342 _tnl_exp_f[lbl_offset], retbuf, &set_val, 28, 3); 6343 break; 6344 case bcmiLabelSelect: 6345 6346 rv = bcmi_validate_field_range(unit, set_val, 1); 6347 _bcmi_mpls_entry_field_val_set(unit, tnl_buf, 6348 _tnl_label_f[lbl_offset], retbuf, &set_val, 31, 1); 6349 break; 6350 case bcmiMplsTtl: 6351 6352 rv = bcmi_validate_field_range(unit, set_val, 8); 6353 _bcmi_mpls_entry_field_val_set(unit, tnl_buf, 6354 _tnl_ttl_f[lbl_offset], retbuf, &set_val, 32, 8); 6355 break; 6356 case bcmiSpecialLabelPushType: 6357 6358 rv = bcmi_validate_field_range(unit, set_val, 2); 6359 _bcmi_mpls_entry_field_val_set(unit, tnl_buf, 6360 _tnl_label_f[lbl_offset], retbuf, &set_val, 40, 2); 6361 break; 6362 case bcmiExpMappingTableSelect: 6363 6364 rv = bcmi_validate_field_range(unit, set_val, 2); 6365 _bcmi_mpls_entry_field_val_set(unit, tnl_buf, 6366 _tnl_label_f[lbl_offset], retbuf, &set_val, 42, 2); 6367 break; 6368 case bcmiPktEcnToExpMappingPtr: 6369 6370 rv = bcmi_validate_field_range(unit, set_val, 2); 6371 _bcmi_mpls_entry_field_val_set(unit, tnl_buf, 6372 _tnl_label_f[lbl_offset], retbuf, &set_val, 44, 2); 6373 break; 6374 case bcmiPktEcnToExpPriority: 6375 6376 rv = bcmi_validate_field_range(unit, set_val, 1); 6377 _bcmi_mpls_entry_field_val_set(unit, tnl_buf, 6378 _tnl_label_f[lbl_offset], retbuf, &set_val, 46, 1); 6379 break; 6380 case bcmiEgrFlexCtrActionSet: 6381 6382 rv = bcmi_validate_field_range(unit, set_val, 19); 6383 _bcmi_mpls_entry_field_val_set(unit, tnl_buf, 6384 _tnl_label_f[lbl_offset], retbuf, &set_val, 47, 19); 6385 break; 6386 case bcmiFlexCtrBaseCounterIdx: 6387 6388 rv = bcmi_validate_field_range(unit, set_val, 13); 6389 _bcmi_mpls_entry_field_val_set(unit, tnl_buf, 6390 _tnl_label_f[lbl_offset], retbuf, &set_val, 47, 13); 6391 break; 6392 case bcmiFlexCtrPoolNumber: 6393 6394 rv = bcmi_validate_field_range(unit, set_val, 2); 6395 _bcmi_mpls_entry_field_val_set(unit, tnl_buf, 6396 _tnl_label_f[lbl_offset], retbuf, &set_val, 61, 2); 6397 break; 6398 case bcmiRsvdFlexCtrPoolNumber: 6399 6400 rv = bcmi_validate_field_range(unit, set_val, 2); 6401 _bcmi_mpls_entry_field_val_set(unit, tnl_buf, 6402 _tnl_label_f[lbl_offset], retbuf, &set_val, 63, 1); 6403 break; 6404 case bcmiFlexCtrOffsetMode: 6405 6406 rv = bcmi_validate_field_range(unit, set_val, 5); 6407 _bcmi_mpls_entry_field_val_set(unit, tnl_buf, 6408 _tnl_label_f[lbl_offset], retbuf, &set_val, 64, 2); 6409 break; 6410 case bcmiEcnMappingEnable: 6411 6412 rv = bcmi_validate_field_range(unit, set_val, 1); 6413 _bcmi_mpls_entry_field_val_set(unit, tnl_buf, 6414 _tnl_label_f[lbl_offset], retbuf, &set_val, 66, 1); 6415 break; 6416 case bcmiEcnMappingTableSelect: 6417 6418 rv = bcmi_validate_field_range(unit, set_val, 2); 6419 _bcmi_mpls_entry_field_val_set(unit, tnl_buf, 6420 _tnl_label_f[lbl_offset], retbuf, &set_val, 67, 2); 6421 break; 6422 case bcmiMplsEntryFormatReserved: 6423 6424 rv = bcmi_validate_field_range(unit, set_val, 2); 6425 _bcmi_mpls_entry_field_val_set(unit, tnl_buf, 6426 _tnl_label_f[lbl_offset], retbuf, &set_val, 69, 2); 6427 break; 6428 default: 6429 rv = BCM_E_PARAM; 6430 break; 6431 } 6432 6433 return rv; 6434 } 6435 6436 /* 6437 * Function: 6438 * bcmi_egr_ip_tnl_mpls_entry_format_get 6439 * Purpose: 6440 * get egress ip tunnel mpls entry format field value 6441 * Parameters: 6442 * unit - (IN) Device Number 6443 * tnl_buf - (IN) tnl entry buffer 6444 * lbl_offset - (IN) offset 6445 * inbuf - (IN) input buffer 6446 * field_type - (IN) field type 6447 * value - (OUT) return value 6448 * Returns: 6449 * BCM_E_XXX 6450 */ 6451 int 6452 bcmi_egr_ip_tnl_mpls_entry_format_get(int unit, void *tnl_buf, int lbl_offset, 6453 uint32 *inbuf, int field_type, uint32 *retval) 6454 { 6455 int rv = BCM_E_NONE; 6456 6457 switch (field_type) { 6458 case bcmiMplsLabel: 6459 _bcmi_mpls_entry_field_val_get(unit, tnl_buf, 6460 _tnl_label_f[lbl_offset], inbuf, retval, 0, 20); 6461 break; 6462 case bcmiMplsPushAction: 6463 _bcmi_mpls_entry_field_val_get(unit, tnl_buf, 6464 _tnl_push_action_f[lbl_offset], inbuf, retval, 20, 2); 6465 break; 6466 case bcmiMplsExpSelect: 6467 _bcmi_mpls_entry_field_val_get(unit, tnl_buf, 6468 _tnl_exp_select_f[lbl_offset], inbuf, retval, 22, 2); 6469 break; 6470 case bcmiMplsExpMappingPtr: 6471 _bcmi_mpls_entry_field_val_get(unit, tnl_buf, 6472 _tnl_exp_ptr_f[lbl_offset], inbuf, retval, 24, 4); 6473 break; 6474 case bcmiNewCfi: 6475 _bcmi_mpls_entry_field_val_get(unit, tnl_buf, 6476 _tnl_cfi_f[lbl_offset], inbuf, retval, 24, 1); 6477 break; 6478 case bcmiNewPri: 6479 _bcmi_mpls_entry_field_val_get(unit, tnl_buf, 6480 _tnl_pri_f[lbl_offset], inbuf, retval, 25, 3); 6481 break; 6482 case bcmiMplsExp: 6483 _bcmi_mpls_entry_field_val_get(unit, tnl_buf, 6484 _tnl_exp_f[lbl_offset], inbuf, retval, 28, 3); 6485 break; 6486 case bcmiLabelSelect: 6487 _bcmi_mpls_entry_field_val_get(unit, tnl_buf, 6488 _tnl_label_f[lbl_offset], inbuf, retval, 31, 1); 6489 break; 6490 case bcmiMplsTtl: 6491 _bcmi_mpls_entry_field_val_get(unit, tnl_buf, 6492 _tnl_ttl_f[lbl_offset], inbuf, retval, 32, 8); 6493 break; 6494 case bcmiSpecialLabelPushType: 6495 _bcmi_mpls_entry_field_val_get(unit, tnl_buf, 6496 _tnl_label_f[lbl_offset], inbuf, retval, 40, 2); 6497 break; 6498 case bcmiExpMappingTableSelect: 6499 _bcmi_mpls_entry_field_val_get(unit, tnl_buf, 6500 _tnl_label_f[lbl_offset], inbuf, retval, 42, 2); 6501 break; 6502 case bcmiPktEcnToExpMappingPtr: 6503 _bcmi_mpls_entry_field_val_get(unit, tnl_buf, 6504 _tnl_label_f[lbl_offset], inbuf, retval, 44, 2); 6505 break; 6506 case bcmiPktEcnToExpPriority: 6507 _bcmi_mpls_entry_field_val_get(unit, tnl_buf, 6508 _tnl_label_f[lbl_offset], inbuf, retval, 46, 1); 6509 break; 6510 case bcmiEgrFlexCtrActionSet: 6511 _bcmi_mpls_entry_field_val_get(unit, tnl_buf, 6512 _tnl_label_f[lbl_offset], inbuf, retval, 47, 19); 6513 break; 6514 case bcmiFlexCtrBaseCounterIdx: 6515 _bcmi_mpls_entry_field_val_get(unit, tnl_buf, 6516 _tnl_label_f[lbl_offset], inbuf, retval, 47, 13); 6517 break; 6518 case bcmiFlexCtrPoolNumber: 6519 _bcmi_mpls_entry_field_val_get(unit, tnl_buf, 6520 _tnl_label_f[lbl_offset], inbuf, retval, 61, 2); 6521 break; 6522 case bcmiRsvdFlexCtrPoolNumber: 6523 _bcmi_mpls_entry_field_val_get(unit, tnl_buf, 6524 _tnl_label_f[lbl_offset], inbuf, retval, 63, 1); 6525 break; 6526 case bcmiFlexCtrOffsetMode: 6527 _bcmi_mpls_entry_field_val_get(unit, tnl_buf, 6528 _tnl_label_f[lbl_offset], inbuf, retval, 64, 2); 6529 break; 6530 case bcmiEcnMappingEnable: 6531 _bcmi_mpls_entry_field_val_get(unit, tnl_buf, 6532 _tnl_label_f[lbl_offset], inbuf, retval, 66, 1); 6533 break; 6534 case bcmiEcnMappingTableSelect: 6535 _bcmi_mpls_entry_field_val_get(unit, tnl_buf, 6536 _tnl_label_f[lbl_offset], inbuf, retval, 67, 2); 6537 break; 6538 case bcmiMplsEntryFormatReserved: 6539 _bcmi_mpls_entry_field_val_get(unit, tnl_buf, 6540 _tnl_label_f[lbl_offset], inbuf, retval, 69, 2); 6541 break; 6542 default: 6543 rv = BCM_E_PARAM; 6544 break; 6545 } 6546 6547 return rv; 6548 } 6549 6550 void 6551 bcm_td3_ip_tnl_mpls_label_info_get(int unit, void *tnl_entry, int field_type, 6552 int offset, int *retval) 6553 { 6554 uint32 iptun_mpls_entry_format[3] = {0}; 6555 6556 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 6557 bcmi_egress_tnl_label_entry_get(unit, tnl_entry, 6558 offset, iptun_mpls_entry_format); 6559 6560 6561 bcmi_egr_ip_tnl_mpls_entry_format_get(unit, 6562 tnl_entry, offset, 6563 iptun_mpls_entry_format, field_type, 6564 (uint32 *)retval); 6565 } 6566 } 6567 6568 #endif /* (BCM_TOMAHAWK_SUPPORT) || defined(BCM_TRIDENT2PLUS_SUPPORT) */ 6569 #endif /* BCM_MPLS_SUPPORT */ 6570 #endif /* INCLUDE_L3 */ 6571