switch.c (67744B)
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 8 #include <shared/bsl.h> 9 #include <soc/debug.h> 10 #include <soc/drv.h> 11 #include <soc/scache.h> 12 #include <soc/mem.h> 13 #include <bcm/switch.h> 14 #include <bcm/error.h> 15 #include <bcm_int/esw/trx.h> 16 #include <bcm_int/esw/switch.h> 17 #include <bcm_int/esw/hurricane3.h> 18 #include <bcm_int/esw/triumph2.h> 19 #include <bcm_int/esw/xgs3.h> 20 #include <bcm_int/esw/stack.h> 21 22 #ifdef BCM_HURRICANE3_SUPPORT 23 24 /* 25 * Software book keeping for Switch Encap related information 26 */ 27 typedef struct _bcm_hr3_switch_encap_bookkeeping_s { 28 #ifdef INCLUDE_L3 29 SHR_BITDCL *intf_bitmap; /* L3 interfaces used */ 30 uint32 *miml_encap; /* MiML encap id */ 31 #endif /* INCLUDE_L3 */ 32 uint32 *custom_header_encap; /* Custom Header encap id */ 33 } _bcm_hr3_switch_encap_bookkeeping_t; 34 35 _bcm_hr3_switch_encap_bookkeeping_t 36 _bcm_hr3_switch_encap_bk_info[BCM_MAX_NUM_UNITS]; 37 38 /* Flag to check initialized status */ 39 STATIC int _bcm_hr3_encap_initialized[BCM_MAX_NUM_UNITS]; 40 41 STATIC sal_mutex_t _hr3_encap_mutex[BCM_MAX_NUM_UNITS] = {NULL}; 42 43 #define HR3_ENCAP_INFO(_unit_) (&_bcm_hr3_switch_encap_bk_info[_unit_]) 44 45 #define HR3_ENCAP_CONTINUOUS_ENTRIES_MAX 128 46 47 #define HR3_ENCAP_INIT(unit) \ 48 do { \ 49 if ((unit < 0) || (unit >= BCM_MAX_NUM_UNITS)) { \ 50 return BCM_E_UNIT; \ 51 } \ 52 if (!_bcm_hr3_encap_initialized[unit]) { \ 53 return BCM_E_INIT; \ 54 } \ 55 } while (0) 56 57 /* Function Enter/Leave Tracing */ 58 #define HR3_ENCAP_FUNCTION_TRACE(_u_, _str_) \ 59 do { \ 60 LOG_VERBOSE(BSL_LS_BCM_SWITCH, \ 61 (BSL_META_U((_u_), \ 62 "%s: " _str_ "\n"), __FUNCTION__)); \ 63 } while (0) 64 65 /* 66 * Switch Encap lock 67 */ 68 #define HR3_ENCAP_LOCK(unit) \ 69 sal_mutex_take(_hr3_encap_mutex[unit], sal_mutex_FOREVER); 70 71 #define HR3_ENCAP_UNLOCK(unit) \ 72 sal_mutex_give(_hr3_encap_mutex[unit]); 73 74 #ifdef INCLUDE_L3 75 #define HR3_L3_INFO(unit) (&_bcm_l3_bk_info[unit]) 76 /* 77 * L3 interface usage bitmap operations 78 */ 79 #define HR3_MIML_INTF_USED_GET(_u_, _intf_) \ 80 SHR_BITGET(HR3_ENCAP_INFO(_u_)->intf_bitmap, (_intf_)) 81 #define HR3_MIML_INTF_USED_SET(_u_, _intf_) \ 82 SHR_BITSET(HR3_ENCAP_INFO((_u_))->intf_bitmap, (_intf_)) 83 #define HR3_MIML_INTF_USED_CLR(_u_, _intf_) \ 84 SHR_BITCLR(HR3_ENCAP_INFO((_u_))->intf_bitmap, (_intf_)) 85 86 typedef struct _bcm_hr3_ing_nh_info_s { 87 int port; 88 int module; 89 int trunk; 90 } _bcm_hr3_ing_nh_info_t; 91 92 typedef struct _bcm_hr3_egr_nh_info_s { 93 uint8 entry_type; 94 int intf_num; 95 int macda_index; 96 int pri; 97 int cfi; 98 } _bcm_hr3_egr_nh_info_t; 99 #endif /* INCLUDE_L3 */ 100 101 /* Function: 102 * _bcm_hr3_switch_encap_idx2id 103 * Purpose: 104 * Translate hardware table index into encap ID used by API 105 * Parameters: 106 * Returns: 107 * BCM_E_XXX 108 */ 109 int 110 _bcm_hr3_switch_encap_idx2id 111 (int unit, int type, int index_count, int *index_array, bcm_if_t *encap_id) 112 { 113 int idx, id = 0; 114 115 HR3_ENCAP_FUNCTION_TRACE(unit, "IN"); 116 117 if (index_array == NULL) { 118 return BCM_E_PARAM; 119 } 120 121 if (encap_id == NULL) { 122 return BCM_E_PARAM; 123 } 124 125 switch (type) { 126 case _BCM_SWITCH_ENCAP_TYPE_MIML: 127 if (index_count < 2) { 128 return BCM_E_PARAM; 129 } 130 131 for (idx = 0; idx < index_count; idx++) { 132 if (idx == 0) { 133 id = index_array[idx]; 134 } else if (idx == 1) { 135 id |= (index_array[idx] << 136 _BCM_SWITCH_ENCAP_MIML_EGR_HEADER_ENCAP_SHIFT); 137 } 138 } 139 break; 140 case _BCM_SWITCH_ENCAP_TYPE_CUSTOM_HEADER: 141 if (index_count < 1) { 142 return BCM_E_PARAM; 143 } 144 145 for (idx = 0; idx < index_count; idx++) { 146 if (idx == 0) { 147 id = index_array[idx]; 148 } 149 } 150 break; 151 default: 152 return BCM_E_NOT_FOUND; 153 } 154 155 *encap_id = id | (type << _BCM_SWITCH_ENCAP_SHIFT); 156 157 HR3_ENCAP_FUNCTION_TRACE(unit, "OUT"); 158 return BCM_E_NONE; 159 } 160 161 /* Function: 162 * _bcm_hr3_switch_encap_id2idx 163 * Purpose: 164 * Translate encap ID into hardware table index used by API 165 * Parameters: 166 * Returns: 167 * BCM_E_XXX 168 */ 169 int 170 _bcm_hr3_switch_encap_id2idx 171 (int unit, bcm_if_t encap_id, int index_count, int *index_array) 172 { 173 int idx, id = 0; 174 175 HR3_ENCAP_FUNCTION_TRACE(unit, "IN"); 176 if (index_array == NULL) { 177 return BCM_E_PARAM; 178 } 179 180 id = encap_id & _BCM_SWITCH_ENCAP_TYPE_MASK; 181 182 switch (encap_id >> _BCM_SWITCH_ENCAP_SHIFT) { 183 case _BCM_SWITCH_ENCAP_TYPE_MIML: 184 if (index_count < 2) { 185 return BCM_E_PARAM; 186 } 187 188 for (idx = 0; idx < index_count; idx++) { 189 if (idx == 0) { 190 index_array[idx] = id & _BCM_SWITCH_ENCAP_MIML_NHI_MASK; 191 } else if (idx == 1) { 192 index_array[idx] = 193 (id >> _BCM_SWITCH_ENCAP_MIML_EGR_HEADER_ENCAP_SHIFT) & 194 _BCM_SWITCH_ENCAP_MIML_EGR_HEADER_ENCAP_MASK; 195 } else { 196 index_array[idx] = 0; 197 } 198 } 199 break; 200 case _BCM_SWITCH_ENCAP_TYPE_CUSTOM_HEADER: 201 if (index_count < 1) { 202 return BCM_E_PARAM; 203 } 204 205 for (idx = 0; idx < index_count; idx++) { 206 if (idx == 0) { 207 index_array[idx] = 208 (id & _BCM_SWITCH_ENCAP_CUSTOM_HEADER_EGR_HEADER_ENCAP_MASK); 209 } else { 210 index_array[idx] = 0; 211 } 212 } 213 break; 214 default: 215 return BCM_E_NOT_FOUND; 216 } 217 218 HR3_ENCAP_FUNCTION_TRACE(unit, "OUT"); 219 return BCM_E_NONE; 220 } 221 222 #ifdef INCLUDE_L3 223 STATIC int 224 _bcm_hr3_miml_l3_intf_add(int unit, _bcm_l3_intf_cfg_t *if_info) 225 { 226 int idx, num_intf; 227 egr_l3_intf_entry_t egr_intf; 228 bcm_mac_t hw_mac; 229 bcm_vlan_t hw_ivid; 230 num_intf = soc_mem_index_count(unit, EGR_L3_INTFm); 231 for (idx = 0; idx < num_intf; idx++) { 232 if (HR3_MIML_INTF_USED_GET(unit, idx)) { 233 BCM_IF_ERROR_RETURN(soc_mem_read(unit, EGR_L3_INTFm, 234 MEM_BLOCK_ANY, idx, &egr_intf)); 235 soc_mem_mac_addr_get(unit, EGR_L3_INTFm, 236 &egr_intf, MAC_ADDRESSf, hw_mac); 237 hw_ivid = soc_mem_field32_get(unit, EGR_L3_INTFm, &egr_intf, IVIDf); 238 if ((SAL_MAC_ADDR_EQUAL(hw_mac, if_info->l3i_mac_addr)) && 239 (hw_ivid == if_info->l3i_inner_vlan)) { 240 if_info->l3i_index = idx; 241 return BCM_E_NONE; 242 } 243 } 244 } 245 /* Create an interface */ 246 BCM_IF_ERROR_RETURN(bcm_xgs3_l3_intf_create(unit, if_info)); 247 HR3_MIML_INTF_USED_SET(unit, if_info->l3i_index); 248 249 return BCM_E_NONE; 250 } 251 252 STATIC int 253 _bcm_hr3_miml_l3_nh_info_add(int unit, 254 bcm_switch_encap_info_t *encap_info, int *nh_index, int replace) 255 { 256 int rv = BCM_E_NONE; 257 int hw_idx = 0; 258 egr_l3_next_hop_entry_t egr_nh_entry; 259 ing_l3_next_hop_entry_t ing_nh_entry; 260 egr_mac_da_profile_entry_t macda; 261 _bcm_hr3_ing_nh_info_t ing_nh_info; 262 _bcm_hr3_egr_nh_info_t egr_nh_info; 263 bcm_l3_egress_t nh_info; 264 _bcm_l3_intf_cfg_t if_info; 265 uint32 nh_flags; 266 int gport_id, is_local; 267 bcm_module_t mod_out; 268 bcm_port_t port_out; 269 bcm_trunk_t trunk_id; 270 int old_macda_idx = -1; 271 uint64 temp_mac; 272 void *entries[1]; 273 274 /* Initialize values */ 275 is_local = -1; 276 ing_nh_info.port = -1; 277 ing_nh_info.module = -1; 278 ing_nh_info.trunk = -1; 279 280 /* Parameter checking */ 281 if (encap_info->encap_service != BCM_SWITCH_ENCAP_SERVICE_MIML) { 282 return BCM_E_PARAM; 283 } 284 285 /* Resolve the gport */ 286 rv = _bcm_esw_gport_resolve(unit, encap_info->port, &mod_out, 287 &port_out, &trunk_id, &gport_id); 288 BCM_IF_ERROR_RETURN(rv); 289 290 /* Note: encap_info->port is must set for MiML to indicate the destination port */ 291 if (BCM_GPORT_IS_TRUNK(encap_info->port)) { 292 ing_nh_info.module = -1; 293 ing_nh_info.port = -1; 294 ing_nh_info.trunk = trunk_id; 295 } else { 296 ing_nh_info.module = mod_out; 297 ing_nh_info.port = port_out; 298 ing_nh_info.trunk = -1; 299 BCM_IF_ERROR_RETURN( 300 _bcm_esw_modid_is_local(unit, mod_out, &is_local)); 301 } 302 303 if (replace) { 304 if ((*nh_index > soc_mem_index_max(unit, EGR_L3_NEXT_HOPm)) || 305 (*nh_index < soc_mem_index_min(unit, EGR_L3_NEXT_HOPm))) { 306 return BCM_E_PARAM; 307 } 308 /* Read the existing egress next_hop entry */ 309 rv = soc_mem_read(unit, EGR_L3_NEXT_HOPm, 310 MEM_BLOCK_ANY, *nh_index, &egr_nh_entry); 311 BCM_IF_ERROR_RETURN(rv); 312 } else { 313 /* 314 * Allocate a next-hop entry. By calling bcm_xgs3_nh_add() 315 * with _BCM_L3_SHR_WRITE_DISABLE flag, a next-hop index is 316 * allocated but nothing is written to hardware. The "nh_info" 317 * in this case is not used, so just set to all zeros. 318 */ 319 bcm_l3_egress_t_init(&nh_info); 320 321 nh_flags = _BCM_L3_SHR_MATCH_DISABLE | _BCM_L3_SHR_WRITE_DISABLE; 322 rv = bcm_xgs3_nh_add(unit, nh_flags, &nh_info, nh_index); 323 BCM_IF_ERROR_RETURN(rv); 324 } 325 326 /* ENTRY_TYPE is MiML */ 327 if (replace) { 328 /* Be sure that the existing entry is programmed to MiML */ 329 egr_nh_info.entry_type = 330 soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh_entry, ENTRY_TYPEf); 331 if (egr_nh_info.entry_type != 0x3) { /* != MiML */ 332 return BCM_E_PARAM; 333 } 334 /* Remember old MAC DA profile index */ 335 old_macda_idx = soc_EGR_L3_NEXT_HOPm_field32_get(unit, 336 &egr_nh_entry, MIML__MAC_DA_PROFILE_INDEXf); 337 } 338 egr_nh_info.entry_type = 0x3; 339 340 /* MIML-DA: Add MAC DA profile */ 341 sal_memset(&macda, 0, sizeof(egr_mac_da_profile_entry_t)); 342 soc_mem_mac_addr_set(unit, EGR_MAC_DA_PROFILEm, 343 &macda, MAC_ADDRESSf, encap_info->egress_dstmac); 344 entries[0] = &macda; 345 rv = _bcm_mac_da_profile_entry_add(unit, 346 entries, 1, (uint32 *) &egr_nh_info.macda_index); 347 if (BCM_FAILURE(rv)) { 348 goto cleanup; 349 } 350 351 /* MIML-SA: Add MAC SA to an L3 interface entry - ref count if exists */ 352 if (!BCM_VLAN_VALID(encap_info->egress_vlan)) { 353 rv = BCM_E_PARAM; 354 goto cleanup; 355 } 356 sal_memset(&if_info, 0, sizeof(_bcm_l3_intf_cfg_t)); 357 SAL_MAC_ADDR_TO_UINT64(encap_info->egress_srcmac, temp_mac); 358 SAL_MAC_ADDR_FROM_UINT64(if_info.l3i_mac_addr, temp_mac); 359 360 /* MIML-VID */ 361 if_info.l3i_inner_vlan = encap_info->egress_vlan; 362 363 /* HiGig Header OVID */ 364 if (encap_info->flags & BCM_SWITCH_ENCAP_MIML_OVERRIDE_HG_HEADER_VID) { 365 if (!BCM_VLAN_VALID(encap_info->higig_vlan)) { 366 rv = BCM_E_PARAM; 367 goto cleanup; 368 } 369 if (is_local && !IS_HG_PORT(unit, port_out)) { 370 rv = BCM_E_PARAM; 371 goto cleanup; 372 } 373 if_info.l3i_vid = encap_info->higig_vlan; 374 } else { 375 /* For non-HiGig port, the OVID must be dropped by configuring VLAN as untagged set */ 376 if_info.l3i_vid = encap_info->egress_vlan; 377 } 378 379 rv = _bcm_hr3_miml_l3_intf_add(unit, &if_info); 380 if (BCM_FAILURE(rv)) { 381 goto cleanup; 382 } 383 384 /* Populate the fields of MIML::EGR_l3_NEXT_HOP */ 385 if (!replace) { 386 sal_memset(&egr_nh_entry, 0, sizeof(egr_l3_next_hop_entry_t)); 387 } 388 389 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 390 &egr_nh_entry, ENTRY_TYPEf, egr_nh_info.entry_type); 391 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 392 &egr_nh_entry, MIML__INTF_NUMf, if_info.l3i_index); 393 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 394 &egr_nh_entry, MIML__HG_HDR_SELf, 1); /* HG 2 */ 395 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 396 &egr_nh_entry, MIML__MAC_DA_PROFILE_INDEXf, egr_nh_info.macda_index); 397 398 /* encap priority selection */ 399 if (encap_info->flags & BCM_SWITCH_ENCAP_MIML_QOS_MAP_INT_PRI) { 400 /* USE_MAPPING */ 401 rv = _bcm_tr2_qos_id2idx(unit, encap_info->qos_map_id, &hw_idx); 402 if (BCM_FAILURE(rv)) { 403 goto cleanup; 404 } 405 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 406 &egr_nh_entry, MIML__DOT1P_PRI_SELECTf, 0x1); 407 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 408 &egr_nh_entry, MIML__DOT1P_MAPPING_PTRf, hw_idx); 409 } else { 410 /* USE_FIXED */ 411 if ((encap_info->pkt_pri > 7) || (encap_info->pkt_cfi > 1)) { 412 rv = BCM_E_PARAM; 413 goto cleanup; 414 } 415 416 /* MIML-NEW_PCP/NEW_CFI */ 417 egr_nh_info.pri = encap_info->pkt_pri; 418 egr_nh_info.cfi = encap_info->pkt_cfi; 419 420 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 421 &egr_nh_entry, MIML__DOT1P_PRI_SELECTf, 0x0); 422 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 423 &egr_nh_entry, MIML__NEW_PCPf, egr_nh_info.pri); 424 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 425 &egr_nh_entry, MIML__NEW_CFIf, egr_nh_info.cfi); 426 } 427 428 /* Write EGR_L3_NEXT_HOP entry */ 429 rv = soc_mem_write(unit, EGR_L3_NEXT_HOPm, 430 MEM_BLOCK_ALL, *nh_index, &egr_nh_entry); 431 if (rv < 0) { 432 goto cleanup; 433 } 434 435 /* Write ING_L3_NEXT_HOP entry */ 436 sal_memset(&ing_nh_entry, 0, sizeof(ing_l3_next_hop_entry_t)); 437 if (ing_nh_info.trunk == -1) { 438 soc_mem_field32_set(unit, ING_L3_NEXT_HOPm, 439 &ing_nh_entry, PORT_NUMf, ing_nh_info.port); 440 soc_mem_field32_set(unit, ING_L3_NEXT_HOPm, 441 &ing_nh_entry, MODULE_IDf, ing_nh_info.module); 442 } else { 443 soc_mem_field32_set(unit, ING_L3_NEXT_HOPm, 444 &ing_nh_entry, Tf, 1); 445 soc_mem_field32_set(unit, ING_L3_NEXT_HOPm, 446 &ing_nh_entry, TGIDf, ing_nh_info.trunk); 447 } 448 rv = soc_mem_write (unit, ING_L3_NEXT_HOPm, 449 MEM_BLOCK_ALL, *nh_index, &ing_nh_entry); 450 if (rv < 0) { 451 goto cleanup; 452 } 453 454 /* Delete MAC_DA indexes */ 455 if (old_macda_idx != -1) { 456 rv = _bcm_mac_da_profile_entry_delete(unit, old_macda_idx); 457 BCM_IF_ERROR_RETURN(rv); 458 } 459 460 return rv; 461 462 cleanup: 463 if (!replace) { 464 (void) bcm_xgs3_nh_del(unit, _BCM_L3_SHR_WRITE_DISABLE, *nh_index); 465 } 466 if (egr_nh_info.macda_index != -1) { 467 (void) _bcm_mac_da_profile_entry_delete(unit, egr_nh_info.macda_index); 468 } 469 470 return rv; 471 } 472 473 STATIC int 474 _bcm_hr3_miml_l3_nh_info_delete(int unit, int nh_index) 475 { 476 int rv, old_macda_idx = -1; 477 egr_l3_next_hop_entry_t egr_nh_entry; 478 ing_l3_next_hop_entry_t ing_nh_entry; 479 480 BCM_IF_ERROR_RETURN (soc_mem_read(unit, EGR_L3_NEXT_HOPm, 481 MEM_BLOCK_ANY, nh_index, &egr_nh_entry)); 482 BCM_IF_ERROR_RETURN (soc_mem_read(unit, ING_L3_NEXT_HOPm, 483 MEM_BLOCK_ANY, nh_index, &ing_nh_entry)); 484 485 if (soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh_entry, ENTRY_TYPEf) == 0x3) { 486 old_macda_idx = soc_EGR_L3_NEXT_HOPm_field32_get(unit, 487 &egr_nh_entry, MIML__MAC_DA_PROFILE_INDEXf); 488 } else { 489 return BCM_E_NOT_FOUND; 490 } 491 492 /* Clear EGR_L3_NEXT_HOP entry */ 493 sal_memset(&egr_nh_entry, 0, sizeof(egr_l3_next_hop_entry_t)); 494 BCM_IF_ERROR_RETURN (soc_mem_write(unit, EGR_L3_NEXT_HOPm, 495 MEM_BLOCK_ALL, nh_index, &egr_nh_entry)); 496 497 /* Clear ING_L3_NEXT_HOP entry */ 498 sal_memset(&ing_nh_entry, 0, sizeof(ing_l3_next_hop_entry_t)); 499 BCM_IF_ERROR_RETURN (soc_mem_write (unit, ING_L3_NEXT_HOPm, 500 MEM_BLOCK_ALL, nh_index, &ing_nh_entry)); 501 502 /* Delete old MAC profile reference */ 503 if (old_macda_idx != -1) { 504 rv = _bcm_mac_da_profile_entry_delete(unit, old_macda_idx); 505 if (BCM_FAILURE(rv)) { 506 return rv; 507 } 508 } 509 510 /* Free the next-hop entry. */ 511 rv = bcm_xgs3_nh_del(unit, _BCM_L3_SHR_WRITE_DISABLE, nh_index); 512 513 return rv; 514 } 515 516 STATIC int 517 _bcm_hr3_miml_l3_nh_info_get(int unit, 518 int nh_index, bcm_switch_encap_info_t *encap_info) 519 { 520 int rv = BCM_E_NONE; 521 egr_l3_next_hop_entry_t egr_nh_entry; 522 ing_l3_next_hop_entry_t ing_nh_entry; 523 egr_l3_intf_entry_t egr_intf; 524 egr_mac_da_profile_entry_t macda; 525 int intf_num = -1, macda_idx = -1; 526 int hw_idx = 0; 527 bcm_module_t mod_out, mod_in; 528 bcm_port_t port_out, port_in; 529 bcm_trunk_t trunk_id; 530 int is_local = 0; 531 532 /* Read the HW entries */ 533 BCM_IF_ERROR_RETURN (soc_mem_read(unit, EGR_L3_NEXT_HOPm, 534 MEM_BLOCK_ANY, nh_index, &egr_nh_entry)); 535 BCM_IF_ERROR_RETURN (soc_mem_read(unit, ING_L3_NEXT_HOPm, 536 MEM_BLOCK_ANY, nh_index, &ing_nh_entry)); 537 538 if (soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh_entry, Tf)) { 539 trunk_id = soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh_entry, TGIDf); 540 BCM_GPORT_TRUNK_SET(encap_info->port, trunk_id); 541 } else { 542 mod_in = soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh_entry, MODULE_IDf); 543 port_in = soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh_entry, PORT_NUMf); 544 SOC_IF_ERROR_RETURN(_bcm_esw_stk_modmap_map(unit, 545 BCM_STK_MODMAP_GET, mod_in, port_in, &mod_out, &port_out)); 546 BCM_GPORT_MODPORT_SET(encap_info->port, mod_out, port_out); 547 548 BCM_IF_ERROR_RETURN( 549 _bcm_esw_modid_is_local(unit, mod_out, &is_local)); 550 } 551 552 if (soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh_entry, ENTRY_TYPEf) == 0x3) { 553 /* Get the MiML encap attributes */ 554 intf_num = soc_EGR_L3_NEXT_HOPm_field32_get(unit, 555 &egr_nh_entry, MIML__INTF_NUMf); 556 macda_idx = soc_EGR_L3_NEXT_HOPm_field32_get(unit, 557 &egr_nh_entry, MIML__MAC_DA_PROFILE_INDEXf); 558 559 BCM_IF_ERROR_RETURN(soc_mem_read(unit, EGR_L3_INTFm, 560 MEM_BLOCK_ANY, intf_num, &egr_intf)); 561 BCM_IF_ERROR_RETURN(soc_mem_read(unit, EGR_MAC_DA_PROFILEm, 562 MEM_BLOCK_ANY, macda_idx, &macda)); 563 564 soc_mem_mac_addr_get(unit, EGR_L3_INTFm, 565 &egr_intf, MAC_ADDRESSf, encap_info->egress_srcmac); 566 encap_info->egress_vlan = 567 soc_mem_field32_get(unit, EGR_L3_INTFm, &egr_intf, IVIDf); 568 569 encap_info->higig_vlan = 570 soc_mem_field32_get(unit, EGR_L3_INTFm, &egr_intf, OVIDf); 571 /* HiGig Header OVID */ 572 if (!is_local || (is_local && IS_HG_PORT(unit, port_out))) { 573 encap_info->flags |= BCM_SWITCH_ENCAP_MIML_OVERRIDE_HG_HEADER_VID; 574 } 575 576 soc_mem_mac_addr_get(unit, EGR_MAC_DA_PROFILEm, 577 &macda, MAC_ADDRESSf, encap_info->egress_dstmac); 578 579 if (soc_EGR_L3_NEXT_HOPm_field32_get(unit, 580 &egr_nh_entry, MIML__DOT1P_PRI_SELECTf) == 0x1) { 581 /* USE_MAPPING */ 582 hw_idx = soc_EGR_L3_NEXT_HOPm_field32_get(unit, 583 &egr_nh_entry, MIML__DOT1P_MAPPING_PTRf); 584 585 rv = _bcm_tr2_qos_idx2id(unit, hw_idx, 586 _BCM_QOS_MAP_TYPE_EGR_MPLS_MAPS, &encap_info->qos_map_id); 587 if (BCM_FAILURE(rv)) { 588 return rv; 589 } 590 591 encap_info->flags |= BCM_SWITCH_ENCAP_MIML_QOS_MAP_INT_PRI; 592 } else { 593 /* USE_FIXED */ 594 encap_info->pkt_pri = soc_EGR_L3_NEXT_HOPm_field32_get(unit, 595 &egr_nh_entry, MIML__NEW_PCPf); 596 encap_info->pkt_cfi = soc_EGR_L3_NEXT_HOPm_field32_get(unit, 597 &egr_nh_entry, MIML__NEW_CFIf); 598 } 599 600 } else { 601 return BCM_E_NOT_FOUND; 602 } 603 604 return rv; 605 } 606 #endif /* INCLUDE_L3 */ 607 608 STATIC int 609 bcmi_hr3_egr_header_encap_data_fill_content( 610 int unit, 611 bcm_switch_encap_info_t *encap_info, 612 int value_offset, 613 egr_header_encap_data_entry_t *egr_header_encap_data) 614 { 615 int rv = BCM_E_NONE; 616 uint32 value32; 617 int hw_idx = 0; 618 619 /* Parameter checking */ 620 if (encap_info == NULL) { 621 return BCM_E_PARAM; 622 } 623 if (egr_header_encap_data == NULL) { 624 return BCM_E_PARAM; 625 } 626 627 if (encap_info->encap_service == BCM_SWITCH_ENCAP_SERVICE_MIML) { 628 value32 = 629 (encap_info->length & _BCM_SWITCH_ENCAP_MIML_LENGTH_MASK) 630 << _BCM_SWITCH_ENCAP_MIML_LENGTH_SHIFT; 631 value32 |= 632 (encap_info->iid & _BCM_SWITCH_ENCAP_MIML_IID_MASK) 633 << _BCM_SWITCH_ENCAP_MIML_IID_SHIFT; 634 value32 |= 635 (encap_info->pkt_type & 636 _BCM_SWITCH_ENCAP_MIML_PKT_TYPE_MASK) 637 << _BCM_SWITCH_ENCAP_MIML_PKT_TYPE_SHIFT; 638 639 soc_mem_field32_set(unit, EGR_HEADER_ENCAP_DATAm, 640 egr_header_encap_data, CUSTOM_PACKET_HEADERf, value32); 641 } else if (encap_info->encap_service == 642 BCM_SWITCH_ENCAP_SERVICE_CUSTOM_HEADER) { 643 /* Set 32-bit data value for encapsulation */ 644 value32 = encap_info->value32 + value_offset; 645 646 soc_mem_field32_set(unit, EGR_HEADER_ENCAP_DATAm, 647 egr_header_encap_data, CUSTOM_PACKET_HEADERf, value32); 648 649 /* encap priority selection */ 650 if (encap_info->flags & 651 BCM_SWITCH_ENCAP_CUSTOM_HEADER_QOS_MAP_INT_PRI) { 652 /* USE_MAPPING */ 653 rv = _bcm_tr2_qos_id2idx( 654 unit, encap_info->qos_map_id, &hw_idx); 655 if (BCM_FAILURE(rv)) { 656 return rv; 657 } 658 soc_mem_field32_set(unit, EGR_HEADER_ENCAP_DATAm, 659 egr_header_encap_data, CUSTOM_PRI_SELECTf, 0x1); 660 soc_mem_field32_set(unit, EGR_HEADER_ENCAP_DATAm, 661 egr_header_encap_data, CUSTOM_PRI_MAPPING_PTRf, 662 hw_idx); 663 } else { 664 /* USE_FIXED */ 665 soc_mem_field32_set(unit, EGR_HEADER_ENCAP_DATAm, 666 egr_header_encap_data, CUSTOM_PRI_SELECTf, 0x0); 667 } 668 } else { 669 return BCM_E_PARAM; 670 } 671 672 return BCM_E_NONE; 673 } 674 675 STATIC int 676 bcmi_hr3_egr_header_encap_data_add_one_entry( 677 int unit, 678 bcm_switch_encap_info_t *encap_info, 679 int value_offset_base, 680 uint32 *eh_idx) 681 { 682 int rv = BCM_E_NONE; 683 684 void *entries[1]; 685 int entries_per_set; 686 int value_offset = value_offset_base; 687 egr_header_encap_data_entry_t egr_header_encap_data; 688 egr_header_encap_data_entry_t egr_header_encap_data_war[4]; 689 690 /* Parameter checking */ 691 if (encap_info == NULL) { 692 return BCM_E_PARAM; 693 } 694 if (eh_idx == NULL) { 695 return BCM_E_PARAM; 696 } 697 698 while (1) { 699 sal_memset(&egr_header_encap_data, 0, 700 sizeof(egr_header_encap_data_entry_t)); 701 sal_memset(egr_header_encap_data_war, 0, 702 sizeof(egr_header_encap_data_war)); 703 BCM_IF_ERROR_RETURN( 704 bcmi_hr3_egr_header_encap_data_fill_content( 705 unit, encap_info, value_offset, &egr_header_encap_data)); 706 707 /* Add EGR_HEADER_ENCAP_DATA profile */ 708 if (soc_feature(unit, 709 soc_feature_hr3_switch_encap_index_shift2_war)) { 710 /* WAR for A0: The index of */ 711 /* EGR_HEADER_ENCAP_DATA is shifted << 2 bits. */ 712 sal_memcpy(&egr_header_encap_data_war[0], 713 &egr_header_encap_data, sizeof(egr_header_encap_data)); 714 entries[0] = &egr_header_encap_data_war; 715 entries_per_set = 4; 716 } else { 717 entries[0] = &egr_header_encap_data; 718 entries_per_set = 1; 719 } 720 721 rv = _bcm_egr_header_encap_data_entry_search( 722 unit, entries, entries_per_set, eh_idx); 723 if (value_offset == 0 && rv == BCM_E_EXISTS) { 724 /* First entry value already existed */ 725 return BCM_E_EXISTS; 726 } else if (rv == BCM_E_EXISTS) { 727 value_offset++; 728 continue; 729 } 730 BCM_IF_ERROR_RETURN(rv); 731 732 rv = _bcm_egr_header_encap_data_entry_add( 733 unit, entries, entries_per_set, eh_idx); 734 BCM_IF_ERROR_RETURN(rv); 735 break; 736 } 737 return BCM_E_NONE; 738 } 739 740 STATIC int 741 bcmi_hr3_egr_header_encap_data_update_one_entry( 742 int unit, 743 bcm_switch_encap_info_t *encap_info, 744 int value_offset, 745 uint32 eh_idx) 746 { 747 int rv = BCM_E_NONE; 748 749 void *entries[1]; 750 egr_header_encap_data_entry_t egr_header_encap_data; 751 egr_header_encap_data_entry_t egr_header_encap_data_war[4]; 752 753 /* Parameter checking */ 754 if (encap_info == NULL) { 755 return BCM_E_PARAM; 756 } 757 sal_memset(&egr_header_encap_data, 0, 758 sizeof(egr_header_encap_data_entry_t)); 759 sal_memset(egr_header_encap_data_war, 0, 760 sizeof(egr_header_encap_data_war)); 761 BCM_IF_ERROR_RETURN( 762 bcmi_hr3_egr_header_encap_data_fill_content( 763 unit, encap_info, value_offset, &egr_header_encap_data)); 764 765 /* Add EGR_HEADER_ENCAP_DATA profile */ 766 if (soc_feature(unit, 767 soc_feature_hr3_switch_encap_index_shift2_war)) { 768 /* WAR for A0: The index of */ 769 /* EGR_HEADER_ENCAP_DATA is shifted << 2 bits. */ 770 sal_memcpy(&egr_header_encap_data_war[0], 771 &egr_header_encap_data, sizeof(egr_header_encap_data)); 772 entries[0] = &egr_header_encap_data_war; 773 } else { 774 entries[0] = &egr_header_encap_data; 775 } 776 rv = _bcm_egr_header_encap_data_entry_update( 777 unit, entries, eh_idx); 778 BCM_IF_ERROR_RETURN(rv); 779 return BCM_E_NONE; 780 } 781 782 STATIC int 783 _bcm_hr3_egr_header_encap_data_add(int unit, 784 bcm_switch_encap_info_t *encap_info, 785 uint32 count, 786 int *eh_index) 787 { 788 int rv = BCM_E_NONE; 789 uint32 eh_idx = 0; 790 uint32 continue_cnt = 0; 791 uint32 eh_idx_arry[HR3_ENCAP_CONTINUOUS_ENTRIES_MAX]; 792 int idx_first, idx_next, idx; 793 794 HR3_ENCAP_FUNCTION_TRACE(unit, "IN"); 795 796 /* MIML doesn't support continued N encap entries */ 797 if (count != 1 && 798 encap_info->encap_service == BCM_SWITCH_ENCAP_SERVICE_MIML) { 799 return BCM_E_UNAVAIL; 800 } 801 802 assert(count <= HR3_ENCAP_CONTINUOUS_ENTRIES_MAX); 803 804 /* 805 * Since the utility soc_profile_mem_add cannot add the same entry data content 806 * , for loop here is to create continuous encap custom data by increase 807 * CUSTOM_PACKET_HEADERf 808 * i.e 809 * CUSTOM_PACKET_HEADER=0x99990000 810 * CUSTOM_PACKET_HEADER=0x99990001 811 * ... 812 * CUSTOM_PACKET_HEADER=0x99990000 + count -1 813 */ 814 815 /* 1. Add 1st entry */ 816 rv = bcmi_hr3_egr_header_encap_data_add_one_entry 817 (unit, encap_info, 0, &eh_idx); 818 if (BCM_FAILURE(rv)) { 819 if (rv == BCM_E_EXISTS) { 820 *eh_index = eh_idx; 821 } 822 return rv; 823 } 824 continue_cnt = 1; 825 idx_first = 0; 826 idx_next = idx_first + 1; 827 eh_idx_arry[idx_first] = eh_idx; 828 829 /* 2. keep adding 1 entry until reaching continues "count" entries */ 830 while (1) { 831 if (continue_cnt == count) { 832 break; 833 } 834 BCM_IF_ERROR_RETURN( 835 bcmi_hr3_egr_header_encap_data_add_one_entry( 836 unit, encap_info, 1, &eh_idx)); 837 eh_idx_arry[idx_next] = eh_idx; 838 if (eh_idx_arry[idx_next - 1] == eh_idx_arry[idx_next] - 1) { 839 continue_cnt++; 840 } else { 841 continue_cnt = 1; 842 idx_first = idx_next; 843 } 844 idx_next++; 845 if (idx_next >= HR3_ENCAP_CONTINUOUS_ENTRIES_MAX) { 846 return BCM_E_RESOURCE; 847 } 848 } 849 850 /* 3. Delete entries from 0 to idx_first -1 */ 851 for (idx = 0; idx < idx_first; idx++) { 852 rv = _bcm_egr_header_encap_data_entry_delete(unit, eh_idx_arry[idx]); 853 BCM_IF_ERROR_RETURN(rv); 854 } 855 856 /* 4. refill value for 1st entry */ 857 BCM_IF_ERROR_RETURN( 858 bcmi_hr3_egr_header_encap_data_update_one_entry( 859 unit, encap_info, 0, eh_idx_arry[idx_first])); 860 861 /* Add EGR_HEADER_ENCAP_DATA profile */ 862 if (soc_feature(unit, soc_feature_hr3_switch_encap_index_shift2_war)) { 863 /* Shift >> 2 bits for software index */ 864 *eh_index = (eh_idx_arry[idx_first] >> 2); 865 } else { 866 *eh_index = eh_idx_arry[idx_first]; 867 } 868 869 HR3_ENCAP_FUNCTION_TRACE(unit, "OUT"); 870 return rv; 871 } 872 873 STATIC int 874 _bcm_hr3_egr_header_encap_data_delete(int unit, int eh_index) 875 { 876 int rv = BCM_E_NONE; 877 878 HR3_ENCAP_FUNCTION_TRACE(unit, "IN"); 879 if (soc_feature(unit, soc_feature_hr3_switch_encap_index_shift2_war)) { 880 /* WAR for A0: The index of EGR_HEADER_ENCAP_DATA is shifted << 2 bits. */ 881 /* Shift << 2 bits for hardware index */ 882 eh_index = (eh_index << 2); 883 } 884 885 /* Delete existing EGR_HEADER_ENCAP_DATA profile reference */ 886 rv = _bcm_egr_header_encap_data_entry_delete(unit, eh_index); 887 BCM_IF_ERROR_RETURN(rv); 888 889 HR3_ENCAP_FUNCTION_TRACE(unit, "OUT"); 890 return rv; 891 } 892 893 STATIC int 894 _bcm_hr3_egr_header_encap_data_update(int unit, bcm_if_t encap_id, 895 int eh_index, bcm_switch_encap_info_t *encap_info) 896 { 897 int rv = BCM_E_NONE; 898 int hw_idx; 899 uint32 value32; 900 egr_header_encap_data_entry_t egr_header_encap_data; 901 egr_header_encap_data_entry_t egr_header_encap_data_war[4]; 902 void *entries[1]; 903 904 HR3_ENCAP_FUNCTION_TRACE(unit, "IN"); 905 906 if (soc_feature(unit, soc_feature_hr3_switch_encap_index_shift2_war)) { 907 /* WAR for A0: The index of EGR_HEADER_ENCAP_DATA is shifted << 2 bits. */ 908 /* Shift << 2 bits for hardware index */ 909 eh_index = (eh_index << 2); 910 } 911 912 if ((eh_index > soc_mem_index_max(unit, EGR_HEADER_ENCAP_DATAm)) || 913 (eh_index < soc_mem_index_min(unit, EGR_HEADER_ENCAP_DATAm))) { 914 return BCM_E_PARAM; 915 } 916 917 sal_memset(&egr_header_encap_data, 0, sizeof(egr_header_encap_data_entry_t)); 918 sal_memset(egr_header_encap_data_war, 0, sizeof(egr_header_encap_data_war)); 919 920 if ((encap_id >> _BCM_SWITCH_ENCAP_SHIFT) == _BCM_SWITCH_ENCAP_TYPE_MIML) { 921 /* Set MiML Packet Type, IID and Length: use the same field as Custom Header */ 922 value32 = 923 (encap_info->length & _BCM_SWITCH_ENCAP_MIML_LENGTH_MASK) << 924 _BCM_SWITCH_ENCAP_MIML_LENGTH_SHIFT; 925 value32 |= 926 (encap_info->iid & _BCM_SWITCH_ENCAP_MIML_IID_MASK) << 927 _BCM_SWITCH_ENCAP_MIML_IID_SHIFT; 928 value32 |= 929 (encap_info->pkt_type & _BCM_SWITCH_ENCAP_MIML_PKT_TYPE_MASK) << 930 _BCM_SWITCH_ENCAP_MIML_PKT_TYPE_SHIFT ; 931 932 soc_mem_field32_set(unit, EGR_HEADER_ENCAP_DATAm, 933 &egr_header_encap_data, CUSTOM_PACKET_HEADERf, value32); 934 } else if ((encap_id >> _BCM_SWITCH_ENCAP_SHIFT) == 935 _BCM_SWITCH_ENCAP_TYPE_CUSTOM_HEADER) { 936 /* Set 32-bit data value for encapsulation */ 937 value32 = encap_info->value32; 938 939 soc_mem_field32_set(unit, EGR_HEADER_ENCAP_DATAm, 940 &egr_header_encap_data, CUSTOM_PACKET_HEADERf, value32); 941 942 /* encap priority selection */ 943 if (encap_info->flags & BCM_SWITCH_ENCAP_CUSTOM_HEADER_QOS_MAP_INT_PRI) { 944 /* USE_MAPPING */ 945 rv = _bcm_tr2_qos_id2idx(unit, encap_info->qos_map_id, &hw_idx); 946 if (BCM_FAILURE(rv)) { 947 return rv; 948 } 949 soc_mem_field32_set(unit, EGR_HEADER_ENCAP_DATAm, 950 &egr_header_encap_data, CUSTOM_PRI_SELECTf, 0x1); 951 soc_mem_field32_set(unit, EGR_HEADER_ENCAP_DATAm, 952 &egr_header_encap_data, CUSTOM_PRI_MAPPING_PTRf, hw_idx); 953 } else { 954 /* USE_FIXED */ 955 soc_mem_field32_set(unit, EGR_HEADER_ENCAP_DATAm, 956 &egr_header_encap_data, CUSTOM_PRI_SELECTf, 0x0); 957 } 958 } else { 959 return BCM_E_PARAM; 960 } 961 962 /* Update EGR_HEADER_ENCAP_DATA profile */ 963 if (soc_feature(unit, soc_feature_hr3_switch_encap_index_shift2_war)) { 964 /* WAR for A0: The index of EGR_HEADER_ENCAP_DATA is shifted << 2 bits. */ 965 sal_memcpy(&egr_header_encap_data_war[0], 966 &egr_header_encap_data, sizeof(egr_header_encap_data)); 967 /* entries_per_set = 4 */ 968 entries[0] = &egr_header_encap_data_war; 969 } else { 970 entries[0] = &egr_header_encap_data; 971 } 972 973 rv = _bcm_egr_header_encap_data_entry_update(unit, entries, (uint32)eh_index); 974 BCM_IF_ERROR_RETURN(rv); 975 976 HR3_ENCAP_FUNCTION_TRACE(unit, "OUT"); 977 return rv; 978 } 979 980 STATIC int 981 _bcm_hr3_egr_header_encap_data_get(int unit, bcm_if_t encap_id, 982 int eh_index, bcm_switch_encap_info_t *encap_info) 983 { 984 int rv = BCM_E_NONE; 985 int hw_idx = 0; 986 uint32 value32; 987 egr_header_encap_data_entry_t egr_header_encap_data; 988 989 if (soc_feature(unit, soc_feature_hr3_switch_encap_index_shift2_war)) { 990 /* WAR for A0: The index of EGR_HEADER_ENCAP_DATA is shifted << 2 bits. */ 991 /* Shift << 2 bits for hardware index */ 992 eh_index = (eh_index << 2); 993 } 994 995 if ((eh_index > soc_mem_index_max(unit, EGR_HEADER_ENCAP_DATAm)) || 996 (eh_index < soc_mem_index_min(unit, EGR_HEADER_ENCAP_DATAm))) { 997 return BCM_E_PARAM; 998 } 999 1000 /* Read the existing egress next_hop entry */ 1001 rv = soc_mem_read(unit, EGR_HEADER_ENCAP_DATAm, 1002 MEM_BLOCK_ANY, eh_index, &egr_header_encap_data); 1003 1004 if ((encap_id >> _BCM_SWITCH_ENCAP_SHIFT) == _BCM_SWITCH_ENCAP_TYPE_MIML) { 1005 /* Get MiML Packet Type, IID and Length: use the same field as Custom Header */ 1006 value32 = soc_mem_field32_get(unit, EGR_HEADER_ENCAP_DATAm, 1007 &egr_header_encap_data, CUSTOM_PACKET_HEADERf); 1008 1009 encap_info->length = 1010 (value32 >> _BCM_SWITCH_ENCAP_MIML_LENGTH_SHIFT) & 1011 _BCM_SWITCH_ENCAP_MIML_LENGTH_MASK; 1012 encap_info->iid = 1013 (value32 >> _BCM_SWITCH_ENCAP_MIML_IID_SHIFT) & 1014 _BCM_SWITCH_ENCAP_MIML_IID_MASK; 1015 encap_info->pkt_type = 1016 (value32 >> _BCM_SWITCH_ENCAP_MIML_PKT_TYPE_SHIFT) & 1017 _BCM_SWITCH_ENCAP_MIML_PKT_TYPE_MASK; 1018 } else if ((encap_id >> _BCM_SWITCH_ENCAP_SHIFT) == 1019 _BCM_SWITCH_ENCAP_TYPE_CUSTOM_HEADER) { 1020 /* Get 32-bit data value for encapsulation */ 1021 value32 = soc_mem_field32_get(unit, EGR_HEADER_ENCAP_DATAm, 1022 &egr_header_encap_data, CUSTOM_PACKET_HEADERf); 1023 encap_info->value32 = value32; 1024 1025 encap_info->flags = 0; 1026 /* encap priority selection */ 1027 if (soc_EGR_HEADER_ENCAP_DATAm_field32_get(unit, 1028 &egr_header_encap_data, CUSTOM_PRI_SELECTf) == 0x1) { 1029 /* USE_MAPPING */ 1030 hw_idx = soc_mem_field32_get(unit, EGR_HEADER_ENCAP_DATAm, 1031 &egr_header_encap_data, CUSTOM_PRI_MAPPING_PTRf); 1032 1033 rv = _bcm_tr2_qos_idx2id(unit, hw_idx, 1034 _BCM_QOS_MAP_TYPE_EGR_MPLS_MAPS, &encap_info->qos_map_id); 1035 if (BCM_FAILURE(rv)) { 1036 return rv; 1037 } 1038 1039 encap_info->flags |= BCM_SWITCH_ENCAP_CUSTOM_HEADER_QOS_MAP_INT_PRI; 1040 } 1041 } else { 1042 return BCM_E_PARAM; 1043 } 1044 1045 return rv; 1046 } 1047 1048 #ifdef INCLUDE_L3 1049 STATIC int 1050 _bcm_hr3_miml_switch_encap_delete(int unit, int nh_index, int eh_index) 1051 { 1052 int rv = BCM_E_NONE; 1053 1054 rv = _bcm_hr3_miml_l3_nh_info_delete(unit, nh_index); 1055 if (BCM_FAILURE(rv)) { 1056 return rv; 1057 } 1058 1059 rv = _bcm_hr3_egr_header_encap_data_delete(unit, eh_index); 1060 if (BCM_FAILURE(rv)) { 1061 return rv; 1062 } 1063 1064 return rv; 1065 } 1066 1067 STATIC int 1068 _bcm_hr3_miml_switch_encap_create(int unit, 1069 bcm_switch_encap_info_t *encap_info, bcm_if_t *encap_id) 1070 { 1071 int rv = BCM_E_NONE; 1072 int nh_index, eh_index, index_array[2]; 1073 int idx, num_miml, free_set; 1074 1075 num_miml = soc_mem_index_count(unit, FP_POLICY_TABLEm); /* Depend on IFP */ 1076 1077 /* Parameter checking */ 1078 if (encap_info == NULL) { 1079 return BCM_E_PARAM; 1080 } 1081 if (encap_id == NULL) { 1082 return BCM_E_PARAM; 1083 } 1084 if (encap_info->encap_service != BCM_SWITCH_ENCAP_SERVICE_MIML) { 1085 return BCM_E_PARAM; 1086 } 1087 1088 rv = _bcm_hr3_miml_l3_nh_info_add(unit, encap_info, &nh_index, FALSE); 1089 if (BCM_FAILURE(rv)) { 1090 return rv; 1091 } 1092 1093 rv = _bcm_hr3_egr_header_encap_data_add(unit, encap_info, 1, &eh_index); 1094 if (BCM_FAILURE(rv)) { 1095 return rv; 1096 } 1097 1098 index_array[0] = nh_index; 1099 index_array[1] = eh_index; 1100 rv = _bcm_hr3_switch_encap_idx2id(unit, 1101 _BCM_SWITCH_ENCAP_TYPE_MIML, 2, index_array, encap_id); 1102 if (BCM_FAILURE(rv)) { 1103 return rv; 1104 } 1105 1106 /* Check if created encap entry is already existed */ 1107 free_set = -1; 1108 for (idx = 0; idx < num_miml; idx++) { 1109 if (HR3_ENCAP_INFO(unit)->miml_encap[idx] == 0x0) { 1110 if (free_set == -1) { 1111 free_set = idx; 1112 } 1113 } 1114 1115 if (HR3_ENCAP_INFO(unit)->miml_encap[idx] == *encap_id) { 1116 rv = _bcm_hr3_miml_switch_encap_delete(unit, nh_index, eh_index); 1117 if (BCM_FAILURE(rv)) { 1118 return rv; 1119 } 1120 return BCM_E_EXISTS; 1121 } 1122 } 1123 1124 if (free_set != -1) { 1125 HR3_ENCAP_INFO(unit)->miml_encap[free_set] = *encap_id; 1126 } else { 1127 /* Delete previous added nh_info and egr_header_encap_data */ 1128 rv = _bcm_hr3_miml_switch_encap_delete(unit, nh_index, eh_index); 1129 if (BCM_FAILURE(rv)) { 1130 return rv; 1131 } 1132 rv = BCM_E_FULL; 1133 } 1134 1135 return rv; 1136 } 1137 1138 STATIC int 1139 _bcm_hr3_miml_switch_encap_set(int unit, 1140 bcm_if_t encap_id, bcm_switch_encap_info_t *encap_info) 1141 { 1142 int rv = BCM_E_NONE; 1143 int nh_index, eh_index, index_array[2]; 1144 1145 /* Parameter checking */ 1146 if (encap_info == NULL) { 1147 return BCM_E_PARAM; 1148 } 1149 1150 if ((encap_id >> _BCM_SWITCH_ENCAP_SHIFT) != _BCM_SWITCH_ENCAP_TYPE_MIML) { 1151 return BCM_E_PARAM; 1152 } 1153 1154 rv = _bcm_hr3_switch_encap_id2idx(unit, encap_id, 2, index_array); 1155 if (BCM_FAILURE(rv)) { 1156 return rv; 1157 } 1158 nh_index = index_array[0]; 1159 eh_index = index_array[1]; 1160 1161 rv = _bcm_hr3_miml_l3_nh_info_add(unit, encap_info, &nh_index, TRUE); 1162 if (BCM_FAILURE(rv)) { 1163 return rv; 1164 } 1165 1166 rv = _bcm_hr3_egr_header_encap_data_update(unit, 1167 encap_id, eh_index, encap_info); 1168 1169 return rv; 1170 } 1171 1172 STATIC int 1173 _bcm_hr3_miml_switch_encap_get(int unit, 1174 bcm_if_t encap_id, bcm_switch_encap_info_t *encap_info) 1175 { 1176 int rv = BCM_E_NONE; 1177 int nh_index, eh_index, index_array[2]; 1178 1179 /* Parameter checking */ 1180 if (encap_info == NULL) { 1181 return BCM_E_PARAM; 1182 } 1183 1184 if ((encap_id >> _BCM_SWITCH_ENCAP_SHIFT) != _BCM_SWITCH_ENCAP_TYPE_MIML) { 1185 return BCM_E_PARAM; 1186 } 1187 1188 rv = _bcm_hr3_switch_encap_id2idx(unit, encap_id, 2, index_array); 1189 if (BCM_FAILURE(rv)) { 1190 return rv; 1191 } 1192 nh_index = index_array[0]; 1193 eh_index = index_array[1]; 1194 1195 rv = _bcm_hr3_miml_l3_nh_info_get(unit, nh_index, encap_info); 1196 if (BCM_FAILURE(rv)) { 1197 return rv; 1198 } 1199 1200 rv = _bcm_hr3_egr_header_encap_data_get(unit, encap_id, eh_index, encap_info); 1201 if (BCM_FAILURE(rv)) { 1202 return rv; 1203 } 1204 1205 encap_info->encap_service = BCM_SWITCH_ENCAP_SERVICE_MIML; 1206 1207 return rv; 1208 } 1209 #endif /* INCLUDE_L3 */ 1210 1211 /* create N Customer header encap objects */ 1212 STATIC int 1213 _bcm_hr3_custom_header_switch_encap_create(int unit, 1214 bcm_switch_encap_info_t *encap_info, 1215 uint32 count, 1216 bcm_if_t *encap_id) 1217 { 1218 int rv = BCM_E_NONE; 1219 int eh_index, base_eh_index, index_array[1]; 1220 int ref_count = 0; 1221 int i; 1222 1223 HR3_ENCAP_FUNCTION_TRACE(unit, "IN"); 1224 /* Parameter checking */ 1225 if (encap_info == NULL) { 1226 return BCM_E_PARAM; 1227 } 1228 if (encap_id == NULL) { 1229 return BCM_E_PARAM; 1230 } 1231 if (encap_info->encap_service != BCM_SWITCH_ENCAP_SERVICE_CUSTOM_HEADER) { 1232 return BCM_E_PARAM; 1233 } 1234 1235 rv = _bcm_hr3_egr_header_encap_data_add(unit, 1236 encap_info, count, &base_eh_index); 1237 if (BCM_FAILURE(rv)) { 1238 if (rv == BCM_E_EXISTS) { 1239 index_array[0] = base_eh_index; 1240 rv = _bcm_hr3_switch_encap_idx2id 1241 (unit, _BCM_SWITCH_ENCAP_TYPE_CUSTOM_HEADER, 1, 1242 index_array, encap_id); 1243 BCM_IF_ERROR_RETURN(rv); 1244 return BCM_E_EXISTS; 1245 } else { 1246 return rv; 1247 } 1248 } 1249 1250 for (i = count - 1; i >= 0; i--) { 1251 eh_index = base_eh_index + i; 1252 /* Check if created encap entry is existed */ 1253 if (soc_feature(unit, soc_feature_hr3_switch_encap_index_shift2_war)) { 1254 /* WAR for A0: The index of EGR_HEADER_ENCAP_DATA is shifted << 2 bits. */ 1255 rv = _bcm_egr_header_encap_data_entry_ref_count_get(unit, 1256 ((uint32)eh_index << 2), &ref_count); 1257 } else { 1258 rv = _bcm_egr_header_encap_data_entry_ref_count_get(unit, 1259 (uint32)eh_index, &ref_count); 1260 } 1261 BCM_IF_ERROR_RETURN(rv); 1262 1263 if (ref_count >= 2) { 1264 /* Delete previous added egr_header_encap_data entry */ 1265 rv = _bcm_hr3_egr_header_encap_data_delete(unit, eh_index); 1266 if (BCM_FAILURE(rv)) { 1267 return rv; 1268 } 1269 return BCM_E_EXISTS; 1270 } 1271 1272 index_array[0] = eh_index; 1273 rv = _bcm_hr3_switch_encap_idx2id(unit, 1274 _BCM_SWITCH_ENCAP_TYPE_CUSTOM_HEADER, 1, index_array, encap_id); 1275 BCM_IF_ERROR_RETURN(rv); 1276 1277 HR3_ENCAP_INFO(unit)->custom_header_encap[eh_index] = *encap_id; 1278 } 1279 1280 return rv; 1281 } 1282 1283 STATIC int 1284 _bcm_hr3_custom_header_switch_encap_set(int unit, 1285 bcm_if_t encap_id, bcm_switch_encap_info_t *encap_info) 1286 { 1287 int rv = BCM_E_NONE; 1288 int eh_index, index_array[1]; 1289 1290 HR3_ENCAP_FUNCTION_TRACE(unit, "IN"); 1291 /* Parameter checking */ 1292 if (encap_info == NULL) { 1293 return BCM_E_PARAM; 1294 } 1295 1296 if ((encap_id >> _BCM_SWITCH_ENCAP_SHIFT) != 1297 _BCM_SWITCH_ENCAP_TYPE_CUSTOM_HEADER) { 1298 return BCM_E_PARAM; 1299 } 1300 1301 rv = _bcm_hr3_switch_encap_id2idx(unit, encap_id, 1, index_array); 1302 if (BCM_FAILURE(rv)) { 1303 return rv; 1304 } 1305 eh_index = index_array[0]; 1306 1307 rv = _bcm_hr3_egr_header_encap_data_update(unit, 1308 encap_id, eh_index, encap_info); 1309 BCM_IF_ERROR_RETURN(rv); 1310 1311 HR3_ENCAP_FUNCTION_TRACE(unit, "OUT"); 1312 return rv; 1313 } 1314 1315 STATIC int 1316 _bcm_hr3_custom_header_switch_encap_get(int unit, 1317 bcm_if_t encap_id, bcm_switch_encap_info_t *encap_info) 1318 { 1319 int rv = BCM_E_NONE; 1320 int eh_index, index_array[1]; 1321 1322 HR3_ENCAP_FUNCTION_TRACE(unit, "IN"); 1323 /* Parameter checking */ 1324 if (encap_info == NULL) { 1325 return BCM_E_PARAM; 1326 } 1327 1328 if ((encap_id >> _BCM_SWITCH_ENCAP_SHIFT) != 1329 _BCM_SWITCH_ENCAP_TYPE_CUSTOM_HEADER) { 1330 return BCM_E_PARAM; 1331 } 1332 1333 rv = _bcm_hr3_switch_encap_id2idx(unit, encap_id, 1, index_array); 1334 if (BCM_FAILURE(rv)) { 1335 return rv; 1336 } 1337 eh_index = index_array[0]; 1338 1339 rv = _bcm_hr3_egr_header_encap_data_get(unit, 1340 encap_id, eh_index, encap_info); 1341 BCM_IF_ERROR_RETURN(rv); 1342 1343 encap_info->encap_service = BCM_SWITCH_ENCAP_SERVICE_CUSTOM_HEADER; 1344 1345 HR3_ENCAP_FUNCTION_TRACE(unit, "OUT"); 1346 return rv; 1347 } 1348 1349 /* 1350 * Function: 1351 * _bcm_hr3_switch_encap_free_resources 1352 * Purpose: 1353 * Free all allocated tables and memory 1354 * Parameters: 1355 * unit - SOC unit number 1356 * Returns: 1357 * Nothing 1358 */ 1359 STATIC void 1360 _bcm_hr3_switch_encap_free_resources(int unit) 1361 { 1362 _bcm_hr3_switch_encap_bookkeeping_t *sw_encap_info = HR3_ENCAP_INFO(unit); 1363 1364 if (_hr3_encap_mutex[unit]) { 1365 sal_mutex_destroy(_hr3_encap_mutex[unit]); 1366 _hr3_encap_mutex[unit] = NULL; 1367 } 1368 #ifdef INCLUDE_L3 1369 if (sw_encap_info->intf_bitmap) { 1370 sal_free(sw_encap_info->intf_bitmap); 1371 sw_encap_info->intf_bitmap = NULL; 1372 } 1373 1374 if (sw_encap_info->miml_encap) { 1375 sal_free(sw_encap_info->miml_encap); 1376 sw_encap_info->miml_encap = NULL; 1377 } 1378 #endif /* INCLUDE_L3 */ 1379 if (sw_encap_info->custom_header_encap) { 1380 sal_free(sw_encap_info->custom_header_encap); 1381 sw_encap_info->custom_header_encap = NULL; 1382 } 1383 } 1384 1385 #ifdef BCM_WARM_BOOT_SUPPORT 1386 /* 1387 * Function: 1388 * _bcm_hr3_switch_encap_wb_scache_size_get 1389 * Purpose: 1390 * Helper utility to determine scache details. 1391 * Parameters: 1392 * unit : (IN) Device Unit Number 1393 * scache_len : (OUT) Total required scache length 1394 * Returns: 1395 * BCM_E_XXX 1396 */ 1397 int 1398 _bcm_hr3_switch_encap_wb_scache_size_get(int unit, 1399 int *req_scache_size) 1400 { 1401 int alloc_size = 0; 1402 #ifdef INCLUDE_L3 1403 int num_miml = 0; 1404 #endif /* INCLUDE_L3 */ 1405 int num_custom_header = 0; 1406 1407 #ifdef INCLUDE_L3 1408 /* Depend on IFP */ 1409 num_miml = soc_mem_index_count(unit, FP_POLICY_TABLEm); 1410 alloc_size += (num_miml * sizeof(uint32)); 1411 #endif /* INCLUDE_L3 */ 1412 num_custom_header = soc_mem_index_count(unit, EGR_HEADER_ENCAP_DATAm); 1413 alloc_size += (num_custom_header * sizeof(uint32)); 1414 1415 *req_scache_size = alloc_size; 1416 1417 return BCM_E_NONE; 1418 } 1419 1420 STATIC int 1421 _bcm_hr3_switch_encap_associated_data_recover(int unit, 1422 bcm_if_t encap_id) 1423 { 1424 int rv = BCM_E_NONE; 1425 int index_array[2]; 1426 int eh_index; 1427 #ifdef INCLUDE_L3 1428 int nh_index, macda_idx, intf_num; 1429 uint32 nh_flags; 1430 egr_l3_next_hop_entry_t egr_nh_entry; 1431 bcm_l3_egress_t nh_info; 1432 #endif /* INCLUDE_L3 */ 1433 1434 rv = _bcm_hr3_switch_encap_id2idx(unit, encap_id, 2, index_array); 1435 if (BCM_FAILURE(rv)) { 1436 return rv; 1437 } 1438 1439 if ((encap_id >> _BCM_SWITCH_ENCAP_SHIFT) == 1440 _BCM_SWITCH_ENCAP_TYPE_MIML) { 1441 #ifdef INCLUDE_L3 1442 nh_index = index_array[0]; 1443 eh_index = index_array[1]; 1444 1445 BCM_IF_ERROR_RETURN(soc_mem_read(unit, EGR_L3_NEXT_HOPm, 1446 MEM_BLOCK_ANY, nh_index, &egr_nh_entry)); 1447 1448 bcm_l3_egress_t_init(&nh_info); 1449 1450 nh_flags = _BCM_L3_SHR_UPDATE | _BCM_L3_SHR_WRITE_DISABLE | 1451 _BCM_L3_SHR_WITH_ID; 1452 rv = bcm_xgs3_nh_add(unit, nh_flags, &nh_info, &nh_index); 1453 BCM_IF_ERROR_RETURN(rv); 1454 1455 if (soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh_entry, ENTRY_TYPEf) == 0x3) { 1456 /* MIML view - recover MACDA profile and interface reference counts */ 1457 macda_idx = soc_EGR_L3_NEXT_HOPm_field32_get(unit, 1458 &egr_nh_entry, MIML__MAC_DA_PROFILE_INDEXf); 1459 _bcm_common_profile_mem_ref_cnt_update(unit, 1460 EGR_MAC_DA_PROFILEm, macda_idx, 1); 1461 intf_num = soc_EGR_L3_NEXT_HOPm_field32_get(unit, 1462 &egr_nh_entry, MIML__INTF_NUMf); 1463 1464 HR3_MIML_INTF_USED_SET(unit, intf_num); 1465 BCM_L3_INTF_USED_SET(unit, intf_num); 1466 1467 if (soc_feature(unit, soc_feature_hr3_switch_encap_index_shift2_war)) { 1468 /* WAR for A0: The index of EGR_HEADER_ENCAP_DATA is shifted << 2 bits. */ 1469 _bcm_common_profile_mem_ref_cnt_update(unit, 1470 EGR_HEADER_ENCAP_DATAm, (eh_index << 2), 1); 1471 } else { 1472 _bcm_common_profile_mem_ref_cnt_update(unit, 1473 EGR_HEADER_ENCAP_DATAm, eh_index, 1); 1474 } 1475 } 1476 #else 1477 rv = BCM_E_UNAVAIL; 1478 #endif /* INCLUDE_L3 */ 1479 } else if ((encap_id >> _BCM_SWITCH_ENCAP_SHIFT) == 1480 _BCM_SWITCH_ENCAP_TYPE_CUSTOM_HEADER) { 1481 eh_index = index_array[0]; 1482 1483 if (soc_feature(unit, soc_feature_hr3_switch_encap_index_shift2_war)) { 1484 /* WAR for A0: The index of EGR_HEADER_ENCAP_DATA is shifted << 2 bits. */ 1485 _bcm_common_profile_mem_ref_cnt_update(unit, 1486 EGR_HEADER_ENCAP_DATAm, (eh_index << 2), 1); 1487 } else { 1488 _bcm_common_profile_mem_ref_cnt_update(unit, 1489 EGR_HEADER_ENCAP_DATAm, eh_index, 1); 1490 } 1491 } 1492 1493 return rv; 1494 } 1495 1496 /* 1497 * Function: 1498 * _bcm_hr3_switch_encap_reinit 1499 * Purpose: 1500 * Warm boot recovery for the Switch Encap software module 1501 * Parameters: 1502 * unit - Device Number 1503 * Returns: 1504 * BCM_E_XXX 1505 */ 1506 int 1507 _bcm_hr3_switch_encap_reinit(int unit, uint8 **scache_ptr) 1508 { 1509 uint32 *u32_scache_p; 1510 uint32 encap_id; 1511 int idx, num_custom_header = 0; 1512 #ifdef INCLUDE_L3 1513 int num_miml = 0; 1514 #endif /* INCLUDE_L3 */ 1515 1516 #ifdef INCLUDE_L3 1517 num_miml = soc_mem_index_count(unit, FP_POLICY_TABLEm); /* Depend on IFP */ 1518 #endif /* INCLUDE_L3 */ 1519 num_custom_header = soc_mem_index_count(unit, EGR_HEADER_ENCAP_DATAm); 1520 1521 u32_scache_p = (uint32 *)(*scache_ptr); 1522 1523 /* recover from scache into book-keeping structs */ 1524 #ifdef INCLUDE_L3 1525 for (idx = 0; idx < num_miml; idx++) { 1526 encap_id = *u32_scache_p; 1527 u32_scache_p++; 1528 if ((encap_id >> _BCM_SWITCH_ENCAP_SHIFT) == 1529 _BCM_SWITCH_ENCAP_TYPE_MIML) { 1530 HR3_ENCAP_INFO(unit)->miml_encap[idx] = encap_id; 1531 1532 BCM_IF_ERROR_RETURN( 1533 _bcm_hr3_switch_encap_associated_data_recover(unit, encap_id)); 1534 } 1535 } 1536 #endif /* INCLUDE_L3 */ 1537 for (idx = 0; idx < num_custom_header; idx++) { 1538 encap_id = *u32_scache_p; 1539 u32_scache_p++; 1540 if ((encap_id >> _BCM_SWITCH_ENCAP_SHIFT) == 1541 _BCM_SWITCH_ENCAP_TYPE_CUSTOM_HEADER) { 1542 HR3_ENCAP_INFO(unit)->custom_header_encap[idx] = encap_id; 1543 1544 BCM_IF_ERROR_RETURN( 1545 _bcm_hr3_switch_encap_associated_data_recover(unit, encap_id)); 1546 } 1547 } 1548 1549 return BCM_E_NONE; 1550 } 1551 1552 /* 1553 * Function: 1554 * _bcm_hr3_switch_encap_sync 1555 * Purpose: 1556 * This routine extracts the state that needs to be stored from the 1557 * book-keeping structs and stores it in the allocated scache location 1558 * Parameters: 1559 * unit : (IN) Device Unit Number 1560 * Returns: 1561 * BCM_E_XXX 1562 */ 1563 int 1564 _bcm_hr3_switch_encap_sync(int unit, uint8 **scache_ptr) 1565 { 1566 uint32 *u32_scache_p; 1567 uint32 encap_id; 1568 int idx, num_custom_header = 0; 1569 #ifdef INCLUDE_L3 1570 int num_miml = 0; 1571 #endif /* INCLUDE_L3 */ 1572 1573 #ifdef INCLUDE_L3 1574 num_miml = soc_mem_index_count(unit, FP_POLICY_TABLEm); /* Depend on IFP */ 1575 #endif /* INCLUDE_L3 */ 1576 num_custom_header = soc_mem_index_count(unit, EGR_HEADER_ENCAP_DATAm); 1577 1578 u32_scache_p = (uint32 *)(*scache_ptr); 1579 1580 /* now store the state into the compressed format */ 1581 #ifdef INCLUDE_L3 1582 for (idx = 0; idx < num_miml; idx++) { 1583 if ((HR3_ENCAP_INFO(unit)->miml_encap[idx] >> 1584 _BCM_SWITCH_ENCAP_SHIFT) == _BCM_SWITCH_ENCAP_TYPE_MIML) { 1585 encap_id = HR3_ENCAP_INFO(unit)->miml_encap[idx]; 1586 } else { 1587 encap_id = 0x0; 1588 } 1589 *u32_scache_p = encap_id; 1590 u32_scache_p++; 1591 } 1592 #endif /* INCLUDE_L3 */ 1593 for (idx = 0; idx < num_custom_header; idx++) { 1594 if ((HR3_ENCAP_INFO(unit)->custom_header_encap[idx] >> 1595 _BCM_SWITCH_ENCAP_SHIFT) == _BCM_SWITCH_ENCAP_TYPE_CUSTOM_HEADER) { 1596 encap_id = HR3_ENCAP_INFO(unit)->custom_header_encap[idx]; 1597 } else { 1598 encap_id = 0x0; 1599 } 1600 *u32_scache_p = encap_id; 1601 u32_scache_p++; 1602 } 1603 1604 return BCM_E_NONE; 1605 } 1606 1607 #endif /* BCM_WARM_BOOT_SUPPORT */ 1608 1609 /* 1610 * Function: 1611 * bcm_hr3_switch_encap_detach 1612 * Purpose: 1613 * Detach the Switch Encap software module 1614 * Parameters: 1615 * unit - Device Number 1616 * Returns: 1617 * BCM_E_XXX 1618 */ 1619 int 1620 bcm_hr3_switch_encap_detach(int unit) 1621 { 1622 int rv = BCM_E_NONE; 1623 1624 HR3_ENCAP_FUNCTION_TRACE(unit, "IN"); 1625 if (_bcm_hr3_encap_initialized[unit] == FALSE) { 1626 return BCM_E_NONE; 1627 } 1628 1629 _bcm_hr3_switch_encap_free_resources(unit); 1630 _bcm_hr3_encap_initialized[unit] = FALSE; 1631 HR3_ENCAP_FUNCTION_TRACE(unit, "OUT"); 1632 return rv; 1633 } 1634 1635 /* 1636 * Function: 1637 * bcm_hr3_switch_encap_init 1638 * Description: 1639 * Initialize switch encap. 1640 * Parameters: 1641 * unit - Device unit number 1642 * Returns: 1643 * BCM_E_xxx 1644 */ 1645 int 1646 bcm_hr3_switch_encap_init(int unit) 1647 { 1648 int rv = BCM_E_NONE; 1649 #ifdef INCLUDE_L3 1650 int num_intf = 0, num_miml = 0; 1651 #endif /* INCLUDE_L3 */ 1652 int num_custom_header = 0; 1653 _bcm_hr3_switch_encap_bookkeeping_t *sw_encap_info = HR3_ENCAP_INFO(unit); 1654 1655 HR3_ENCAP_FUNCTION_TRACE(unit, "IN"); 1656 1657 if (!(soc_feature(unit, soc_feature_miml) || 1658 soc_feature(unit, soc_feature_custom_header))) { 1659 return BCM_E_UNAVAIL; 1660 } 1661 1662 #ifdef INCLUDE_L3 1663 if (soc_feature(unit, soc_feature_miml) && !HR3_L3_INFO(unit)->l3_initialized) { 1664 LOG_INFO(BSL_LS_BCM_L3, 1665 (BSL_META_U(unit, 1666 "L3 module must be initialized first\n"))); 1667 return BCM_E_NONE; 1668 } 1669 #endif /* INCLUDE_L3 */ 1670 1671 if (_bcm_hr3_encap_initialized[unit]) { 1672 BCM_IF_ERROR_RETURN(bcm_hr3_switch_encap_detach(unit)); 1673 } 1674 #ifdef INCLUDE_L3 1675 num_intf = soc_mem_index_count(unit, EGR_L3_INTFm); 1676 num_miml = soc_mem_index_count(unit, FP_POLICY_TABLEm); /* Depend on IFP */ 1677 #endif /* INCLUDE_L3 */ 1678 num_custom_header = soc_mem_index_count(unit, EGR_HEADER_ENCAP_DATAm); 1679 1680 sal_memset(sw_encap_info, 0, sizeof(_bcm_hr3_switch_encap_bookkeeping_t)); 1681 1682 #ifdef INCLUDE_L3 1683 /* Allocate MiML encap L3 intf usage bitmap */ 1684 if (sw_encap_info->intf_bitmap == NULL) { 1685 sw_encap_info->intf_bitmap = 1686 sal_alloc(SHR_BITALLOCSIZE(num_intf), "intf_bitmap"); 1687 if (sw_encap_info->intf_bitmap == NULL) { 1688 _bcm_hr3_switch_encap_free_resources(unit); 1689 return BCM_E_MEMORY; 1690 } 1691 } 1692 sal_memset(sw_encap_info->intf_bitmap, 0, SHR_BITALLOCSIZE(num_intf)); 1693 1694 /* Allocate MiML encap id */ 1695 if (sw_encap_info->miml_encap == NULL) { 1696 sw_encap_info->miml_encap = 1697 sal_alloc((sizeof(uint32) * num_miml), "miml_encap"); 1698 if (sw_encap_info->miml_encap == NULL) { 1699 _bcm_hr3_switch_encap_free_resources(unit); 1700 return BCM_E_MEMORY; 1701 } 1702 } 1703 sal_memset(sw_encap_info->miml_encap, 0, (sizeof(uint32) * num_miml)); 1704 #endif /* INCLUDE_L3 */ 1705 1706 /* Allocate Custom Header encap id */ 1707 if (sw_encap_info->custom_header_encap == NULL) { 1708 sw_encap_info->custom_header_encap = 1709 sal_alloc((sizeof(uint32) * num_custom_header), "custom_header_encap"); 1710 if (sw_encap_info->custom_header_encap == NULL) { 1711 _bcm_hr3_switch_encap_free_resources(unit); 1712 return BCM_E_MEMORY; 1713 } 1714 } 1715 sal_memset(sw_encap_info->custom_header_encap, 0, 1716 (sizeof(uint32) * num_custom_header)); 1717 1718 if (_hr3_encap_mutex[unit] == NULL) { 1719 _hr3_encap_mutex[unit] = sal_mutex_create("sw_encap mutex"); 1720 if (_hr3_encap_mutex[unit] == NULL) { 1721 _bcm_hr3_switch_encap_free_resources(unit); 1722 return BCM_E_MEMORY; 1723 } 1724 } 1725 1726 _bcm_hr3_encap_initialized[unit] = TRUE; 1727 HR3_ENCAP_FUNCTION_TRACE(unit, "OUT"); 1728 return rv; 1729 } 1730 1731 /* 1732 * Function: 1733 * _bcm_hr3_switch_encap_create 1734 * Purpose: 1735 * Create N continuous encapsulation objects, base_encap_id will be returned 1736 * after the N (base_encap_id ~ base_encap_id + count - 1) encapsulation 1737 * objects are created. 1738 * Parameters: 1739 * unit - (IN) Unit number. 1740 * encap_info - (IN) Encapsulation info data structure. 1741 * count - (IN) Number of encapsulation objects to create 1742 * base_encap_id - (OUT) Encapsulation object id. 1743 * Returns: 1744 * BCM_E_xxx 1745 * Notes: 1746 */ 1747 int 1748 _bcm_hr3_switch_encap_create(int unit, 1749 bcm_switch_encap_info_t *encap_info, 1750 uint32 count, 1751 bcm_if_t *base_encap_id) 1752 { 1753 int rv = BCM_E_UNAVAIL; 1754 1755 HR3_ENCAP_FUNCTION_TRACE(unit, "IN"); 1756 HR3_ENCAP_INIT(unit); 1757 1758 if (encap_info == NULL) { 1759 return BCM_E_PARAM; 1760 } 1761 if (base_encap_id == NULL) { 1762 return BCM_E_PARAM; 1763 } 1764 1765 switch (encap_info->encap_service) { 1766 case BCM_SWITCH_ENCAP_SERVICE_MIML: 1767 if (!soc_feature(unit, soc_feature_miml)) { 1768 return BCM_E_UNAVAIL; 1769 } 1770 if (count != 1) { 1771 return BCM_E_PARAM; 1772 } 1773 #ifdef INCLUDE_L3 1774 HR3_ENCAP_LOCK(unit); 1775 rv = _bcm_hr3_miml_switch_encap_create(unit, 1776 encap_info, base_encap_id); 1777 HR3_ENCAP_UNLOCK(unit); 1778 #endif /* INCLUDE_L3 */ 1779 break; 1780 case BCM_SWITCH_ENCAP_SERVICE_CUSTOM_HEADER: 1781 if (!soc_feature(unit, soc_feature_custom_header)) { 1782 return BCM_E_UNAVAIL; 1783 } 1784 HR3_ENCAP_LOCK(unit); 1785 rv = _bcm_hr3_custom_header_switch_encap_create(unit, 1786 encap_info, count, base_encap_id); 1787 HR3_ENCAP_UNLOCK(unit); 1788 break; 1789 default: 1790 return BCM_E_UNAVAIL; 1791 } 1792 BCM_IF_ERROR_RETURN(rv); 1793 1794 HR3_ENCAP_FUNCTION_TRACE(unit, "OUT"); 1795 return rv; 1796 } 1797 1798 /* 1799 * Function: 1800 * bcm_hr3_switch_encap_create 1801 * Purpose: 1802 * Create an encapuslation object, encap_id will be returned after the 1803 * encapsulation object created. The encap_id will be used by FP. 1804 * Parameters: 1805 * unit - (IN) Unit number. 1806 * encap_info - (IN) Encapsulation info data structure. 1807 * encap_id - (OUT) Encapsulation object id. 1808 * Returns: 1809 * BCM_E_xxx 1810 * Notes: 1811 */ 1812 int 1813 bcm_hr3_switch_encap_create(int unit, 1814 bcm_switch_encap_info_t *encap_info, bcm_if_t *encap_id) 1815 { 1816 int rv; 1817 1818 HR3_ENCAP_FUNCTION_TRACE(unit, "IN"); 1819 if (encap_info == NULL) { 1820 return BCM_E_PARAM; 1821 } 1822 1823 if (encap_id == NULL) { 1824 return BCM_E_PARAM; 1825 } 1826 1827 /* create 1 encap_id */ 1828 rv = _bcm_hr3_switch_encap_create(unit, encap_info, 1, encap_id); 1829 BCM_IF_ERROR_RETURN(rv); 1830 1831 HR3_ENCAP_FUNCTION_TRACE(unit, "OUT"); 1832 return rv; 1833 } 1834 1835 /* 1836 * Function: 1837 * bcm_hr3_switch_encap_destroy 1838 * Purpose: 1839 * Destroy the encap object with the given encap_id. 1840 * Parameters: 1841 * unit - (IN) Unit number. 1842 * encap_id - (IN) Encapsulation object id. 1843 * Returns: 1844 * BCM_E_xxx 1845 * Notes: 1846 */ 1847 int 1848 bcm_hr3_switch_encap_destroy(int unit, bcm_if_t encap_id) 1849 { 1850 int rv = BCM_E_UNAVAIL; 1851 int idx, index_count, index_array[2]; 1852 #ifdef INCLUDE_L3 1853 int num_miml; 1854 #endif /* INCLUDE_L3 */ 1855 1856 HR3_ENCAP_FUNCTION_TRACE(unit, "IN"); 1857 HR3_ENCAP_INIT(unit); 1858 1859 switch (encap_id >> _BCM_SWITCH_ENCAP_SHIFT) { 1860 case _BCM_SWITCH_ENCAP_TYPE_MIML: 1861 if (!soc_feature(unit, soc_feature_miml)) { 1862 return BCM_E_UNAVAIL; 1863 } 1864 #ifdef INCLUDE_L3 1865 HR3_ENCAP_LOCK(unit); 1866 index_count = 2; 1867 rv = _bcm_hr3_switch_encap_id2idx(unit, encap_id, index_count, index_array); 1868 if (BCM_FAILURE(rv)) { 1869 HR3_ENCAP_UNLOCK(unit); 1870 return rv; 1871 } 1872 1873 rv = _bcm_hr3_miml_switch_encap_delete(unit, 1874 index_array[0], index_array[1]); 1875 if (BCM_FAILURE(rv)) { 1876 HR3_ENCAP_UNLOCK(unit); 1877 return rv; 1878 } 1879 1880 num_miml = soc_mem_index_count(unit, FP_POLICY_TABLEm); /* Depend on IFP */ 1881 for (idx = 0; idx < num_miml; idx++) { 1882 if (HR3_ENCAP_INFO(unit)->miml_encap[idx] == encap_id) { 1883 HR3_ENCAP_INFO(unit)->miml_encap[idx] = 0x0; 1884 } 1885 } 1886 HR3_ENCAP_UNLOCK(unit); 1887 #endif /* INCLUDE_L3 */ 1888 break; 1889 case _BCM_SWITCH_ENCAP_TYPE_CUSTOM_HEADER: 1890 if (!soc_feature(unit, soc_feature_custom_header)) { 1891 return BCM_E_UNAVAIL; 1892 } 1893 1894 HR3_ENCAP_LOCK(unit); 1895 index_count = 1; 1896 rv = _bcm_hr3_switch_encap_id2idx(unit, encap_id, index_count, index_array); 1897 if (BCM_FAILURE(rv)) { 1898 HR3_ENCAP_UNLOCK(unit); 1899 return rv; 1900 } 1901 1902 idx = index_count - 1; 1903 rv = _bcm_hr3_egr_header_encap_data_delete(unit, index_array[idx]); 1904 if (BCM_FAILURE(rv)) { 1905 HR3_ENCAP_UNLOCK(unit); 1906 return rv; 1907 } 1908 1909 HR3_ENCAP_INFO(unit)->custom_header_encap[index_array[idx]] = 0x0; 1910 1911 HR3_ENCAP_UNLOCK(unit); 1912 break; 1913 default: 1914 return BCM_E_NOT_FOUND; 1915 } 1916 1917 HR3_ENCAP_FUNCTION_TRACE(unit, "OUT"); 1918 return rv; 1919 } 1920 1921 /* 1922 * Function: 1923 * bcm_hr3_switch_encap_destroy_all 1924 * Purpose: 1925 * Destroy all encap objects. 1926 * Parameters: 1927 * unit - (IN) Unit number. 1928 * Returns: 1929 * BCM_E_xxx 1930 * Notes: 1931 */ 1932 int 1933 bcm_hr3_switch_encap_destroy_all(int unit) 1934 { 1935 int rv = BCM_E_NONE; 1936 int idx, num_custom_header = 0; 1937 #ifdef INCLUDE_L3 1938 int num_miml = 0; 1939 #endif /* INCLUDE_L3 */ 1940 bcm_if_t encap_id; 1941 1942 HR3_ENCAP_FUNCTION_TRACE(unit, "IN"); 1943 HR3_ENCAP_INIT(unit); 1944 1945 #ifdef INCLUDE_L3 1946 if (soc_feature(unit, soc_feature_miml)) { 1947 /* Depend on IFP */ 1948 num_miml = soc_mem_index_count(unit, FP_POLICY_TABLEm); 1949 } 1950 #endif /* INCLUDE_L3 */ 1951 if (soc_feature(unit, soc_feature_custom_header)) { 1952 num_custom_header = soc_mem_index_count(unit, EGR_HEADER_ENCAP_DATAm); 1953 } 1954 1955 #ifdef INCLUDE_L3 1956 /* Destroy all created encap id for MiML */ 1957 for (idx = 0; idx < num_miml; idx++) { 1958 encap_id = HR3_ENCAP_INFO(unit)->miml_encap[idx]; 1959 if (encap_id != 0x0) { 1960 rv = bcm_hr3_switch_encap_destroy(unit, encap_id); 1961 if (BCM_FAILURE(rv)) { 1962 return rv; 1963 } 1964 } 1965 } 1966 #endif /* INCLUDE_L3 */ 1967 1968 /* Destroy all created encap id for Custom Header */ 1969 for (idx = 0; idx < num_custom_header; idx++) { 1970 encap_id = HR3_ENCAP_INFO(unit)->custom_header_encap[idx]; 1971 if (encap_id != 0x0) { 1972 rv = bcm_hr3_switch_encap_destroy(unit, encap_id); 1973 if (BCM_FAILURE(rv)) { 1974 return rv; 1975 } 1976 } 1977 } 1978 1979 HR3_ENCAP_FUNCTION_TRACE(unit, "OUT"); 1980 return rv; 1981 } 1982 1983 /* 1984 * Function: 1985 * bcm_hr3_switch_encap_set 1986 * Purpose: 1987 * Modify the configuration of the encap object with the given encap_id. 1988 * Parameters: 1989 * unit - (IN) Unit number. 1990 * encap_id - (IN) Encapsulation object id. 1991 * encap_info - (IN) Encapsulation info data structure. 1992 * Returns: 1993 * BCM_E_xxx 1994 * Notes: 1995 */ 1996 int 1997 bcm_hr3_switch_encap_set(int unit, 1998 bcm_if_t encap_id, bcm_switch_encap_info_t *encap_info) 1999 { 2000 int rv = BCM_E_UNAVAIL; 2001 2002 HR3_ENCAP_FUNCTION_TRACE(unit, "IN"); 2003 HR3_ENCAP_INIT(unit); 2004 2005 if (encap_info == NULL) { 2006 return BCM_E_PARAM; 2007 } 2008 2009 switch (encap_id >> _BCM_SWITCH_ENCAP_SHIFT) { 2010 case _BCM_SWITCH_ENCAP_TYPE_MIML: 2011 if (!soc_feature(unit, soc_feature_miml)) { 2012 return BCM_E_UNAVAIL; 2013 } 2014 #ifdef INCLUDE_L3 2015 HR3_ENCAP_LOCK(unit); 2016 rv = _bcm_hr3_miml_switch_encap_set(unit, 2017 encap_id, encap_info); 2018 HR3_ENCAP_UNLOCK(unit); 2019 #endif /* INCLUDE_L3 */ 2020 break; 2021 case _BCM_SWITCH_ENCAP_TYPE_CUSTOM_HEADER: 2022 if (!soc_feature(unit, soc_feature_custom_header)) { 2023 return BCM_E_UNAVAIL; 2024 } 2025 HR3_ENCAP_LOCK(unit); 2026 rv = _bcm_hr3_custom_header_switch_encap_set(unit, 2027 encap_id, encap_info); 2028 HR3_ENCAP_UNLOCK(unit); 2029 break; 2030 default: 2031 return BCM_E_NOT_FOUND; 2032 } 2033 BCM_IF_ERROR_RETURN(rv); 2034 2035 HR3_ENCAP_FUNCTION_TRACE(unit, "OUT"); 2036 return rv; 2037 } 2038 2039 /* 2040 * Function: 2041 * bcm_hr3_switch_encap_get 2042 * Purpose: 2043 * Get the configuration of the encap object with the given encap_id. 2044 * Parameters: 2045 * unit - (IN) Unit number. 2046 * encap_id - (IN) Encapsulation object id. 2047 * encap_info - (OUT) Encapsulation info data structure. 2048 * Returns: 2049 * BCM_E_xxx 2050 * Notes: 2051 */ 2052 int 2053 bcm_hr3_switch_encap_get(int unit, 2054 bcm_if_t encap_id, bcm_switch_encap_info_t *encap_info) 2055 { 2056 int rv = BCM_E_UNAVAIL; 2057 2058 HR3_ENCAP_FUNCTION_TRACE(unit, "IN"); 2059 HR3_ENCAP_INIT(unit); 2060 2061 if (encap_info == NULL) { 2062 return BCM_E_PARAM; 2063 } 2064 2065 bcm_switch_encap_info_t_init(encap_info); 2066 2067 switch (encap_id >> _BCM_SWITCH_ENCAP_SHIFT) { 2068 case _BCM_SWITCH_ENCAP_TYPE_MIML: 2069 if (!soc_feature(unit, soc_feature_miml)) { 2070 return BCM_E_UNAVAIL; 2071 } 2072 #ifdef INCLUDE_L3 2073 HR3_ENCAP_LOCK(unit); 2074 rv = _bcm_hr3_miml_switch_encap_get(unit, 2075 encap_id, encap_info); 2076 HR3_ENCAP_UNLOCK(unit); 2077 #endif /* INCLUDE_L3 */ 2078 break; 2079 case _BCM_SWITCH_ENCAP_TYPE_CUSTOM_HEADER: 2080 if (!soc_feature(unit, soc_feature_custom_header)) { 2081 return BCM_E_UNAVAIL; 2082 } 2083 HR3_ENCAP_LOCK(unit); 2084 rv = _bcm_hr3_custom_header_switch_encap_get(unit, 2085 encap_id, encap_info); 2086 HR3_ENCAP_UNLOCK(unit); 2087 break; 2088 default: 2089 return BCM_E_NOT_FOUND; 2090 } 2091 BCM_IF_ERROR_RETURN(rv); 2092 2093 HR3_ENCAP_FUNCTION_TRACE(unit, "OUT"); 2094 return rv; 2095 } 2096 2097 /* 2098 * Function: 2099 * bcm_hr3_switch_encap_traverse 2100 * Purpose: 2101 * To traverse all created encapsulation entries and call provided callback function 2102 * with matched entry. 2103 * Parameters: 2104 * unit - (IN) Unit number. 2105 * cb_fn - (IN) User specified callback function. 2106 * user_data - (IN) User specified cookie. 2107 * Returns: 2108 * BCM_E_xxx 2109 * Notes: 2110 */ 2111 int 2112 bcm_hr3_switch_encap_traverse(int unit, 2113 bcm_switch_encap_traverse_cb cb_fn, void *user_data) 2114 { 2115 int rv = BCM_E_NONE; 2116 int idx, num_custom_header = 0; 2117 #ifdef INCLUDE_L3 2118 int num_miml = 0; 2119 #endif /* INCLUDE_L3 */ 2120 bcm_if_t encap_id; 2121 bcm_switch_encap_info_t encap_info; 2122 2123 HR3_ENCAP_FUNCTION_TRACE(unit, "IN"); 2124 HR3_ENCAP_INIT(unit); 2125 2126 #ifdef INCLUDE_L3 2127 if (soc_feature(unit, soc_feature_miml)) { 2128 /* Depend on IFP */ 2129 num_miml = soc_mem_index_count(unit, FP_POLICY_TABLEm); 2130 } 2131 #endif /* INCLUDE_L3 */ 2132 if (soc_feature(unit, soc_feature_custom_header)) { 2133 num_custom_header = soc_mem_index_count(unit, EGR_HEADER_ENCAP_DATAm); 2134 } 2135 2136 bcm_switch_encap_info_t_init(&encap_info); 2137 2138 HR3_ENCAP_LOCK(unit); 2139 #ifdef INCLUDE_L3 2140 /* Traverse all created encap id for MiML */ 2141 for (idx = 0; idx < num_miml; idx++) { 2142 encap_id = HR3_ENCAP_INFO(unit)->miml_encap[idx]; 2143 if (encap_id != 0x0) { 2144 /* Get the configuration of the encap info */ 2145 rv = bcm_hr3_switch_encap_get(unit, encap_id, &encap_info); 2146 if (BCM_FAILURE(rv)) { 2147 HR3_ENCAP_UNLOCK(unit); 2148 return rv; 2149 } 2150 2151 /* Call application call-back */ 2152 rv = cb_fn(unit, encap_id, &encap_info, user_data); 2153 if (BCM_FAILURE(rv)) { 2154 #ifdef BCM_CB_ABORT_ON_ERR 2155 if (SOC_CB_ABORT_ON_ERR(unit)) { 2156 HR3_ENCAP_UNLOCK(unit); 2157 return rv; 2158 } 2159 #endif 2160 } 2161 } 2162 } 2163 #endif /* INCLUDE_L3 */ 2164 2165 /* Traverse all created encap id for Custom Header */ 2166 for (idx = 0; idx < num_custom_header; idx++) { 2167 encap_id = HR3_ENCAP_INFO(unit)->custom_header_encap[idx]; 2168 if (encap_id != 0x0) { 2169 /* Get the configuration of the encap info */ 2170 rv = bcm_hr3_switch_encap_get(unit, encap_id, &encap_info); 2171 if (BCM_FAILURE(rv)) { 2172 HR3_ENCAP_UNLOCK(unit); 2173 return rv; 2174 } 2175 /* Call application call-back */ 2176 rv = cb_fn(unit, encap_id, &encap_info, user_data); 2177 if (BCM_FAILURE(rv)) { 2178 #ifdef BCM_CB_ABORT_ON_ERR 2179 if (SOC_CB_ABORT_ON_ERR(unit)) { 2180 HR3_ENCAP_UNLOCK(unit); 2181 return rv; 2182 } 2183 #endif 2184 } 2185 } 2186 } 2187 2188 HR3_ENCAP_UNLOCK(unit); 2189 2190 HR3_ENCAP_FUNCTION_TRACE(unit, "OUT"); 2191 return rv; 2192 } 2193 #endif /* BCM_HURRICANE3_SUPPORT */ 2194