mpls.c (225118B)
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: TR3 MPLS enhancements 9 */ 10 #include <soc/defs.h> 11 #include <shared/bsl.h> 12 #include <assert.h> 13 14 #include <sal/core/libc.h> 15 #if defined(BCM_TRIUMPH3_SUPPORT) && defined(BCM_MPLS_SUPPORT) && \ 16 defined(INCLUDE_L3) 17 18 #include <shared/util.h> 19 #include <soc/mem.h> 20 #include <soc/cm.h> 21 #include <soc/drv.h> 22 #include <soc/register.h> 23 #include <soc/memory.h> 24 #include <bcm/qos.h> 25 #include <bcm/error.h> 26 #include <bcm_int/esw/triumph3.h> 27 #include <bcm_int/esw/triumph.h> 28 #include <bcm_int/esw/port.h> 29 #include <bcm_int/esw/firebolt.h> 30 #include <bcm_int/esw/trx.h> 31 #include <bcm_int/esw/virtual.h> 32 #include <bcm_int/esw/xgs3.h> 33 #include <bcm_int/esw_dispatch.h> 34 #include <bcm_int/esw/switch.h> 35 #include <bcm_int/esw/mpls.h> 36 #include <bcm_int/esw/katana.h> 37 #include <bcm_int/esw/flex_ctr.h> 38 #include <bcm_int/esw/multicast.h> 39 #include <bcm_int/common/multicast.h> 40 #include <bcm_int/api_xlate_port.h> 41 #include <bcm_int/esw/ecn.h> 42 43 #define MPLS_INFO(_unit_) (&_bcm_tr_mpls_bk_info[_unit_]) 44 #define ECN_INFO(_unit_) (&_bcm_xgs5_ecn_bk_info[_unit_]) 45 46 int 47 _bcm_tr3_mpls_entry_convert_to_extd_entry_key( 48 int unit, 49 mpls_entry_entry_t *mpls_entry_entry, 50 mpls_entry_extd_entry_t *mpls_entry_extd_entry); 51 52 /* 53 * Function: 54 * _bcm_tr3_mpls_p2mp_loopback_enable 55 * Purpose: 56 * Enable loopback for MPLS P2MP 57 * Parameters: 58 * IN : unit 59 * Returns: 60 * BCM_E_XXX 61 */ 62 63 STATIC int 64 _bcm_tr3_mpls_p2mp_loopback_enable(int unit) 65 { 66 soc_field_t lport_fields[] = { 67 PORT_TYPEf, 68 MPLS_ENABLEf, 69 V4L3_ENABLEf, 70 V6L3_ENABLEf 71 }; 72 uint32 lport_values[] = { 73 0x2, /* PORT_TYPEf */ 74 0x1, /* MPLS_ENABLEf */ 75 0x1, /* V4L3_ENABLEf */ 76 0x1 /* V6L3_ENABLEf */ 77 }; 78 79 /* Update LPORT Profile Table */ 80 return _bcm_lport_profile_fields32_modify(unit, LPORT_PROFILE_LPORT_TAB, 81 COUNTOF(lport_fields), 82 lport_fields, lport_values); 83 } 84 85 /* 86 * Function: 87 * _bcm_tr3_mpls_p2mp_loopback_disable 88 * Purpose: 89 * Disable loopback for MPLS P2MP 90 * Parameters: 91 * IN : unit 92 * Returns: 93 * BCM_E_XXX 94 */ 95 96 STATIC int 97 _bcm_tr3_mpls_p2mp_loopback_disable(int unit) 98 { 99 soc_field_t lport_fields[] = { 100 PORT_TYPEf, 101 MPLS_ENABLEf, 102 V4L3_ENABLEf, 103 V6L3_ENABLEf 104 }; 105 uint32 lport_values[] = { 106 0x0, /* PORT_TYPEf */ 107 0x0, /* MPLS_ENABLEf */ 108 0x0, /* V4L3_ENABLEf */ 109 0x0 /* V6L3_ENABLEf */ 110 }; 111 112 /* Update LPORT Profile Table */ 113 return _bcm_lport_profile_fields32_modify(unit, LPORT_PROFILE_LPORT_TAB, 114 COUNTOF(lport_fields), 115 lport_fields, lport_values); 116 } 117 118 /* 119 * Function: 120 * _bcm_tr3_mpls_entry_set_key 121 * Purpose: 122 * Convert key part of application format to HW entry. 123 * Parameters: 124 * unit - Device Number 125 * info - Label (switch) information 126 * ment - MPLS entry 127 * Returns: 128 * BCM_E_XXX 129 */ 130 131 STATIC int 132 _bcm_tr3_mpls_entry_set_key(int unit, bcm_mpls_tunnel_switch_t *info, 133 uint32 *hw_buf, 134 soc_mem_t hw_mem, uint8 key_type) 135 { 136 bcm_module_t mod_out; 137 bcm_port_t port_out; 138 bcm_trunk_t trunk_id; 139 int gport_id; 140 int rv = BCM_E_NONE; 141 142 if (info->port == BCM_GPORT_INVALID) { 143 /* Global label, mod/port not part of lookup key */ 144 soc_mem_field32_set(unit, hw_mem, hw_buf, MPLS__MODULE_IDf, 0); 145 soc_mem_field32_set(unit, hw_mem, hw_buf, MPLS__PORT_NUMf, 0); 146 if (BCM_XGS3_L3_MPLS_LBL_VALID( info->label)) { 147 soc_mem_field32_set(unit, hw_mem, hw_buf, MPLS__MPLS_LABELf, info->label); 148 } else { 149 return BCM_E_PARAM; 150 } 151 152 if (hw_mem == MPLS_ENTRYm) { 153 soc_mem_field32_set(unit, hw_mem, hw_buf, KEY_TYPEf, key_type); 154 soc_mem_field32_set(unit, hw_mem, hw_buf, VALIDf, 1); 155 } else if (hw_mem == MPLS_ENTRY_EXTDm) { 156 soc_mem_field32_set(unit, hw_mem, hw_buf, KEY_TYPE_0f, key_type); 157 soc_mem_field32_set(unit, hw_mem, hw_buf, KEY_TYPE_1f, key_type); 158 soc_mem_field32_set(unit, hw_mem, hw_buf, VALID_0f, 1); 159 soc_mem_field32_set(unit, hw_mem, hw_buf, VALID_1f, 1); 160 } 161 return BCM_E_NONE; 162 } 163 164 rv = _bcm_esw_gport_resolve(unit, info->port, &mod_out, 165 &port_out, &trunk_id, &gport_id); 166 BCM_IF_ERROR_RETURN(rv); 167 168 if (BCM_GPORT_IS_TRUNK(info->port)) { 169 soc_mem_field32_set(unit, hw_mem, hw_buf, MPLS__Tf, 1); 170 soc_mem_field32_set(unit, hw_mem, hw_buf, MPLS__TGIDf, trunk_id); 171 } else { 172 soc_mem_field32_set(unit, hw_mem, hw_buf, MPLS__MODULE_IDf, mod_out); 173 soc_mem_field32_set(unit, hw_mem, hw_buf, MPLS__PORT_NUMf, port_out); 174 } 175 if (BCM_XGS3_L3_MPLS_LBL_VALID( info->label)) { 176 soc_mem_field32_set(unit, hw_mem, hw_buf, MPLS__MPLS_LABELf, info->label); 177 } else { 178 return BCM_E_PARAM; 179 } 180 if (hw_mem == MPLS_ENTRYm) { 181 soc_mem_field32_set(unit, hw_mem, hw_buf, KEY_TYPEf, key_type); 182 soc_mem_field32_set(unit, hw_mem, hw_buf, VALIDf, 1); 183 } else if (hw_mem == MPLS_ENTRY_EXTDm) { 184 soc_mem_field32_set(unit, hw_mem, hw_buf, KEY_TYPE_0f, key_type); 185 soc_mem_field32_set(unit, hw_mem, hw_buf, KEY_TYPE_1f, key_type); 186 soc_mem_field32_set(unit, hw_mem, hw_buf, VALID_0f, 1); 187 soc_mem_field32_set(unit, hw_mem, hw_buf, VALID_1f, 1); 188 } 189 return BCM_E_NONE; 190 } 191 192 /* 193 * Function: 194 * _bcm_tr3_mpls_entry_get_key 195 * Purpose: 196 * Convert key part of HW entry to application format. 197 * Parameters: 198 * unit - Device Number 199 * hw_buf - mpls entry 200 * hw_mem - MPLS Memory 201 * info - Label (switch) information 202 * Returns: 203 * BCM_E_XXX 204 */ 205 206 STATIC int 207 _bcm_tr3_mpls_entry_get_key(int unit, uint32 *hw_buf, 208 soc_mem_t hw_mem, bcm_mpls_tunnel_switch_t *info) 209 { 210 bcm_port_t port_in, port_out; 211 bcm_module_t mod_in, mod_out; 212 bcm_trunk_t trunk_id; 213 214 port_in = soc_mem_field32_get(unit, hw_mem, hw_buf, MPLS__PORT_NUMf); 215 mod_in = soc_mem_field32_get(unit, hw_mem, hw_buf, MPLS__MODULE_IDf); 216 if (soc_mem_field32_get(unit, hw_mem, hw_buf, MPLS__Tf)) { 217 trunk_id = soc_mem_field32_get(unit, hw_mem, hw_buf, MPLS__TGIDf); 218 BCM_GPORT_TRUNK_SET(info->port, trunk_id); 219 } else if ((port_in == 0) && (mod_in == 0)) { 220 /* Global label, mod/port not part of lookup key */ 221 info->port = BCM_GPORT_INVALID; 222 } else { 223 BCM_IF_ERROR_RETURN 224 (_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET, 225 mod_in, port_in, &mod_out, &port_out)); 226 BCM_GPORT_MODPORT_SET(info->port, mod_out, port_out); 227 } 228 info->label = soc_mem_field32_get(unit, hw_mem, hw_buf, MPLS__MPLS_LABELf); 229 230 return BCM_E_NONE; 231 } 232 233 /* 234 * Function: 235 * _bcm_tr3_mpls_bud_entry_find 236 * Purpose: 237 * Search for Bud entry 238 * Returns: 239 * BCM_E_XXX 240 */ 241 242 STATIC int 243 _bcm_tr3_mpls_bud_entry_find(int unit, int action, 244 bcm_mpls_tunnel_switch_t *info, uint32 *bud_ment, 245 soc_mem_t *bud_mem, int *bud_node_index, 246 uint8 *key_type) 247 { 248 int rv = BCM_E_NONE; 249 250 if (action == 0x2) { 251 *key_type = 0x10; 252 *bud_mem = MPLS_ENTRYm; 253 BCM_IF_ERROR_RETURN( 254 _bcm_tr3_mpls_entry_set_key(unit, info, bud_ment, *bud_mem, *key_type)); 255 } else { 256 *key_type = 0x12; 257 *bud_mem = MPLS_ENTRYm; 258 BCM_IF_ERROR_RETURN( 259 _bcm_tr3_mpls_entry_set_key(unit, info, bud_ment, *bud_mem, *key_type)); 260 } 261 262 /* See if entry already exists */ 263 rv = soc_mem_search(unit, *bud_mem, MEM_BLOCK_ANY, bud_node_index, 264 bud_ment, bud_ment, 0); 265 266 /* If not found, then search in EXTD memory */ 267 if (BCM_FAILURE(rv)) { 268 if (action == 0x2) { 269 *key_type = 0x11; 270 *bud_mem = MPLS_ENTRY_EXTDm; 271 BCM_IF_ERROR_RETURN( 272 _bcm_tr3_mpls_entry_set_key(unit, info, bud_ment, *bud_mem, *key_type)); 273 } else { 274 *key_type = 0x13; 275 *bud_mem = MPLS_ENTRY_EXTDm; 276 BCM_IF_ERROR_RETURN( 277 _bcm_tr3_mpls_entry_set_key(unit, info, bud_ment, *bud_mem, *key_type)); 278 } 279 /* See if entry already exists */ 280 rv = soc_mem_search(unit, *bud_mem, MEM_BLOCK_ANY, bud_node_index, 281 bud_ment, bud_ment, 0); 282 } 283 return rv; 284 } 285 286 /* 287 * Function: 288 * _bcm_tr3_mpls_entry_find 289 * Purpose: 290 * Search for MPLS entry 291 * Returns: 292 * BCM_E_XXX 293 */ 294 295 STATIC int 296 _bcm_tr3_mpls_entry_find(int unit, 297 bcm_mpls_tunnel_switch_t *info, uint32 *hw_buf, 298 soc_mem_t *hw_mem, int *index) 299 { 300 int rv = BCM_E_NONE; 301 uint8 key_type=0; 302 303 /* Type-1, First-Pass */ 304 sal_memset (hw_buf, 0, SOC_MAX_MEM_FIELD_WORDS * sizeof(uint32)); 305 *hw_mem = MPLS_ENTRYm; 306 key_type = 0x10; 307 rv = _bcm_tr3_mpls_entry_set_key(unit, info, hw_buf, 308 *hw_mem, key_type); 309 BCM_IF_ERROR_RETURN(rv); 310 311 rv = soc_mem_search(unit, *hw_mem, MEM_BLOCK_ANY, index, 312 hw_buf, hw_buf, 0); 313 314 if (BCM_FAILURE(rv)) { 315 /* Type-1, Second-Pass */ 316 sal_memset (hw_buf, 0, SOC_MAX_MEM_FIELD_WORDS * sizeof(uint32)); 317 *hw_mem = MPLS_ENTRYm; 318 key_type = 0x12; 319 rv = _bcm_tr3_mpls_entry_set_key(unit, info, hw_buf, 320 *hw_mem, key_type); 321 BCM_IF_ERROR_RETURN(rv); 322 323 rv = soc_mem_search(unit, *hw_mem, MEM_BLOCK_ANY, index, 324 hw_buf, hw_buf, 0); 325 326 if (BCM_FAILURE(rv)) { 327 /* Type-2, First-Pass */ 328 sal_memset (hw_buf, 0, SOC_MAX_MEM_FIELD_WORDS * sizeof(uint32)); 329 *hw_mem = MPLS_ENTRY_EXTDm; 330 key_type = 0x11; 331 rv = _bcm_tr3_mpls_entry_set_key(unit, info, hw_buf, 332 *hw_mem, key_type); 333 BCM_IF_ERROR_RETURN(rv); 334 335 rv = soc_mem_search(unit, *hw_mem, MEM_BLOCK_ANY, index, 336 hw_buf, hw_buf, 0); 337 338 if (BCM_FAILURE(rv)) { 339 /* Type-2, Second-)Pass */ 340 sal_memset (hw_buf, 0, SOC_MAX_MEM_FIELD_WORDS * sizeof(uint32)); 341 *hw_mem = MPLS_ENTRY_EXTDm; 342 key_type = 0x13; 343 rv = _bcm_tr3_mpls_entry_set_key(unit, info, hw_buf, 344 *hw_mem, key_type); 345 BCM_IF_ERROR_RETURN(rv); 346 347 rv = soc_mem_search(unit, *hw_mem, MEM_BLOCK_ANY, index, 348 hw_buf, hw_buf, 0); 349 } 350 } 351 } 352 return rv; 353 } 354 355 /* 356 * Function: 357 * _bcm_tr3_mpls_entry_delete 358 * Purpose: 359 * Delete entry from MPLS_ENTRY table 360 * Parameters: 361 * unit - Device Number 362 * ment - MPLS Label entry to delete 363 * Returns: 364 * BCM_E_XXX 365 */ 366 367 STATIC int 368 _bcm_tr3_mpls_entry_delete(int unit, uint32 *hw_buf, 369 soc_mem_t hw_mem, 370 bcm_mpls_tunnel_switch_t *info, int index) 371 { 372 int action, ecmp_index = -1, nh_index = -1; 373 bcm_if_t egress_if=0; 374 int ref_count=0, forwarding_field_type=-1, ipmc_index=-1; 375 int bud_node_trigger=-1, is_set=0; 376 uint32 bud_ment[SOC_MAX_MEM_FIELD_WORDS]; 377 soc_mem_t bud_mem; 378 uint8 key_type=0; 379 int bud_node_index=-1; 380 int rv = BCM_E_NONE; 381 382 sal_memset (bud_ment, 0, SOC_MAX_MEM_FIELD_WORDS * sizeof(uint32)); 383 384 action = soc_mem_field32_get(unit, hw_mem, hw_buf, 385 MPLS__MPLS_ACTION_IF_BOSf); 386 switch (action) { 387 case 2: /* POP */ 388 if (hw_mem == MPLS_ENTRYm) { 389 key_type = 0x12; 390 if (key_type == soc_mem_field32_get(unit, hw_mem, hw_buf, 391 KEY_TYPEf)) { 392 forwarding_field_type = _BCM_MPLS_FORWARD_MULTICAST_GROUP; 393 } 394 } else if (hw_mem == MPLS_ENTRY_EXTDm) { 395 key_type = 0x13; 396 if (key_type == soc_mem_field32_get(unit, hw_mem, hw_buf, 397 KEY_TYPE_0f)) { 398 forwarding_field_type = _BCM_MPLS_FORWARD_MULTICAST_GROUP; 399 } 400 } 401 break; 402 case 3: /* SWAP_NHI */ 403 case 6: /* PHP_NHI */ 404 forwarding_field_type = _BCM_MPLS_FORWARD_NEXT_HOP; 405 break; 406 case 4: /* SWAP_ECMP */ 407 case 7: /* PHP_ECMP */ 408 forwarding_field_type = _BCM_MPLS_FORWARD_ECMP_GROUP; 409 break; 410 case 5: /* SWAP_L3MC_INDEX */ 411 forwarding_field_type = _BCM_MPLS_FORWARD_MULTICAST_GROUP; 412 break; 413 default: 414 break; 415 } 416 417 if (forwarding_field_type == _BCM_MPLS_FORWARD_MULTICAST_GROUP) { 418 if (action == 0x2) { 419 bud_node_trigger = 1; 420 } else { 421 ipmc_index = soc_mem_field32_get(unit, hw_mem, hw_buf, 422 MPLS__L3MC_INDEXf); 423 bud_node_trigger = soc_mem_field32_get(unit, hw_mem, hw_buf, 424 MPLS__P2MP_LOCAL_RECEIVERS_PRESENTf); 425 rv = bcm_xgs3_ipmc_id_is_set(unit, ipmc_index, &is_set); 426 if (BCM_SUCCESS(rv)) { 427 if (is_set) { 428 /* First Delete IPMC_entry, then delete P2MP Label entry */ 429 return BCM_E_BUSY; 430 } 431 } 432 } 433 if ((bud_node_trigger) && (info->action != -1)) { 434 /* Search for Bud_Node entry */ 435 rv = _bcm_tr3_mpls_bud_entry_find(unit, action, info, bud_ment, 436 &bud_mem, &bud_node_index, &key_type); 437 /* If Not found in both Memory, then return error */ 438 if (BCM_FAILURE(rv)) { 439 return (rv); 440 } 441 if ((info->action == BCM_MPLS_SWITCH_ACTION_SWAP)) { 442 /* Change key_type of POP Entry to key_type_1; Disable loopback of POP Entry */ 443 if (bud_mem == MPLS_ENTRY_EXTDm) { 444 soc_mem_field32_set(unit, bud_mem, bud_ment, KEY_TYPE_0f, 0x11); 445 } else if (bud_mem == MPLS_ENTRYm) { 446 soc_mem_field32_set(unit, bud_mem, bud_ment, KEY_TYPEf, 0x10); 447 } 448 soc_mem_field32_set(unit, bud_mem, bud_ment, 449 MPLS__P2MP_LOCAL_RECEIVERS_PRESENTf, 0x0); 450 (void) _bcm_tr3_mpls_p2mp_loopback_disable(unit); 451 /* Update POP Entry */ 452 rv = soc_mem_write(unit, bud_mem, 453 MEM_BLOCK_ALL, bud_node_index, bud_ment); 454 if (BCM_SUCCESS(rv)) { 455 /* Delete SWAP Entry from HW */ 456 rv = soc_mem_delete(unit, hw_mem, MEM_BLOCK_ALL, hw_buf); 457 if ( (rv != BCM_E_NOT_FOUND) && (rv != BCM_E_NONE) ) { 458 return rv; 459 } 460 } 461 } else if ((info->action == BCM_MPLS_SWITCH_ACTION_POP)) { 462 /* Disable Loopback of SWAP Entry */ 463 soc_mem_field32_set(unit, bud_mem, bud_ment, 464 MPLS__P2MP_LOCAL_RECEIVERS_PRESENTf, 0x0); 465 (void) _bcm_tr3_mpls_p2mp_loopback_disable(unit); 466 /* Update SWAP Entry */ 467 rv = soc_mem_write(unit, bud_mem, 468 MEM_BLOCK_ALL, bud_node_index, bud_ment); 469 if (BCM_SUCCESS(rv)) { 470 /* Delete POP Entry from HW */ 471 rv = soc_mem_delete(unit, hw_mem, MEM_BLOCK_ALL, hw_buf); 472 return rv; 473 } 474 } 475 }else if (info->action == BCM_MPLS_SWITCH_ACTION_SWAP) { 476 /* Delete SWAP Entry from HW */ 477 rv = soc_mem_delete(unit, hw_mem, MEM_BLOCK_ALL, hw_buf); 478 if ( (rv != BCM_E_NOT_FOUND) && (rv != BCM_E_NONE) ) { 479 return rv; 480 } 481 } 482 return rv; 483 } else if (forwarding_field_type == _BCM_MPLS_FORWARD_NEXT_HOP) { 484 nh_index = soc_mem_field32_get(unit, hw_mem, hw_buf, MPLS__NEXT_HOP_INDEXf); 485 } else if (forwarding_field_type == _BCM_MPLS_FORWARD_ECMP_GROUP) { 486 ecmp_index = soc_mem_field32_get(unit, hw_mem, hw_buf, MPLS__ECMP_PTRf); 487 } 488 489 /* Delete the entry from HW */ 490 rv = soc_mem_delete(unit, hw_mem, MEM_BLOCK_ALL, hw_buf); 491 if ( (rv != BCM_E_NOT_FOUND) && (rv != BCM_E_NONE) ) { 492 return rv; 493 } 494 495 if (forwarding_field_type != _BCM_MPLS_FORWARD_MULTICAST_GROUP) { 496 if (action == 0x3) { /* SWAP_NHI */ 497 /* Check if tunnel_switch.egress_label mode is being used */ 498 rv = bcm_tr_mpls_get_vp_nh (unit, (bcm_if_t) nh_index, &egress_if); 499 if (rv == BCM_E_NONE) { 500 rv = bcm_tr_mpls_l3_nh_info_delete(unit, nh_index); 501 } else { 502 /* Decrement next-hop Reference count */ 503 rv = bcm_xgs3_get_ref_count_from_nhi(unit, 0, &ref_count, nh_index); 504 } 505 } else if (action == 0x6) { /* PHP_NHI */ 506 rv = bcm_xgs3_nh_del(unit, 0, nh_index); 507 } else if (forwarding_field_type == _BCM_MPLS_FORWARD_ECMP_GROUP) { 508 rv = bcm_xgs3_ecmp_group_del(unit, ecmp_index, 0); 509 if (rv == BCM_E_NONE) { 510 rv = bcm_xgs3_get_ref_count_from_nhi(unit, BCM_L3_MULTIPATH, 511 &ref_count, ecmp_index); 512 } 513 } 514 } 515 return rv; 516 } 517 518 519 /* 520 * Function: 521 * _bcm_tr3_mpls_entry_get_data 522 * Purpose: 523 * Convert data part of HW entry to application format. 524 * Parameters: 525 * unit - Device Number 526 * ment - mpls entry 527 * info - Label (switch) information 528 * Returns: 529 * BCM_E_XXX 530 */ 531 532 STATIC int 533 _bcm_tr3_mpls_entry_get_data(int unit, uint32 *hw_buf, 534 soc_mem_t hw_mem, 535 bcm_mpls_tunnel_switch_t *info) 536 { 537 int action, nh_index, ecmp_group, vrf, ipmc_index; 538 bcm_if_t egress_if=0; 539 int rv=BCM_E_NONE; 540 int mode = 0; 541 int v4_v6_override; 542 543 BCM_IF_ERROR_RETURN(bcm_xgs3_l3_ingress_mode_get(unit, &mode)); 544 545 action = soc_mem_field32_get(unit, hw_mem, hw_buf, MPLS__MPLS_ACTION_IF_BOSf); 546 switch(action) { 547 case 0x2: 548 info->action = BCM_MPLS_SWITCH_ACTION_POP; 549 if (mode == 0) { 550 vrf = soc_mem_field32_get(unit, hw_mem, hw_buf, MPLS__L3_IIFf); 551 vrf -= _BCM_TR_MPLS_L3_IIF_BASE; 552 _BCM_MPLS_VPN_SET(info->vpn, _BCM_MPLS_VPN_TYPE_L3, vrf); 553 } else { 554 info->ingress_if = soc_mem_field32_get(unit, hw_mem, hw_buf, MPLS__L3_IIFf); 555 } 556 break; 557 case 0x3: 558 info->action = BCM_MPLS_SWITCH_ACTION_SWAP; 559 nh_index = soc_mem_field32_get(unit, hw_mem, hw_buf, 560 MPLS__NEXT_HOP_INDEXf); 561 rv = bcm_tr_mpls_get_vp_nh (unit, nh_index, &egress_if); 562 if (rv == BCM_E_NONE) { 563 rv = bcm_tr_mpls_l3_nh_info_get(unit, info, nh_index); 564 BCM_IF_ERROR_RETURN(rv); 565 } else { 566 info->egress_if = nh_index + BCM_XGS3_EGRESS_IDX_MIN(unit); 567 info->egress_label.label = 0; 568 } 569 break; 570 case 0x4: 571 info->action = BCM_MPLS_SWITCH_ACTION_SWAP; 572 ecmp_group = soc_mem_field32_get(unit, hw_mem, hw_buf, 573 MPLS__ECMP_PTRf); 574 info->egress_if = ecmp_group + BCM_XGS3_MPATH_EGRESS_IDX_MIN(unit); 575 break; 576 case 0x5: 577 ipmc_index = soc_mem_field32_get(unit, hw_mem, hw_buf, 578 MPLS__L3MC_INDEXf); 579 info->flags |= BCM_MPLS_SWITCH_P2MP; 580 _BCM_MULTICAST_GROUP_SET(info->mc_group, 581 _BCM_MULTICAST_TYPE_EGRESS_OBJECT, ipmc_index); 582 info->egress_label.label = 0; 583 break; 584 case 0x6: 585 info->action = BCM_MPLS_SWITCH_ACTION_PHP; 586 nh_index = soc_mem_field32_get(unit, hw_mem, hw_buf, 587 MPLS__NEXT_HOP_INDEXf); 588 info->egress_if = nh_index + BCM_XGS3_EGRESS_IDX_MIN(unit); 589 break; 590 case 0x7: 591 info->action = BCM_MPLS_SWITCH_ACTION_PHP; 592 ecmp_group = soc_mem_field32_get(unit, hw_mem, hw_buf, 593 MPLS__ECMP_PTRf); 594 info->egress_if = ecmp_group + BCM_XGS3_MPATH_EGRESS_IDX_MIN(unit); 595 break; 596 default: 597 return BCM_E_INTERNAL; 598 break; 599 } 600 v4_v6_override = soc_property_get(unit, spn_MPLS_SWITCH_IPV4_IPV6_INDEPENDENT_CONTROL, 0); 601 if (v4_v6_override) { 602 if (soc_mem_field32_get(unit, hw_mem, hw_buf, MPLS__V4_ENABLEf)) { 603 info->flags2 |= BCM_MPLS_SWITCH2_ENABLE_IPV4; 604 } 605 if (soc_mem_field32_get(unit, hw_mem, hw_buf, MPLS__V6_ENABLEf)) { 606 info->flags2 |= BCM_MPLS_SWITCH2_ENABLE_IPV6; 607 } 608 } 609 if (!soc_mem_field32_get(unit, hw_mem, hw_buf, MPLS__DECAP_USE_TTLf)) { 610 info->flags |= BCM_MPLS_SWITCH_INNER_TTL; 611 } 612 if (soc_mem_field32_get(unit, hw_mem, hw_buf, MPLS__DECAP_USE_EXP_FOR_INNERf)) { 613 info->flags |= BCM_MPLS_SWITCH_INNER_EXP; 614 } 615 if (soc_mem_field32_get(unit, hw_mem, hw_buf, 616 MPLS__DECAP_USE_EXP_FOR_PRIf) == 0x1) { 617 618 /* Use specified EXP-map to determine internal prio/color */ 619 info->flags |= BCM_MPLS_SWITCH_INT_PRI_MAP; 620 info->exp_map = 621 soc_mem_field32_get(unit, hw_mem, hw_buf, MPLS__EXP_MAPPING_PTRf); 622 info->exp_map |= _BCM_TR_MPLS_EXP_MAP_TABLE_TYPE_INGRESS; 623 } else if (soc_mem_field32_get(unit, hw_mem, hw_buf, 624 MPLS__DECAP_USE_EXP_FOR_PRIf) == 0x2) { 625 626 /* Use the specified internal priority value */ 627 info->flags |= BCM_MPLS_SWITCH_INT_PRI_SET; 628 info->int_pri = 629 soc_mem_field32_get(unit, hw_mem, hw_buf, MPLS__NEW_PRIf); 630 631 /* Use specified EXP-map to determine internal color */ 632 info->flags |= BCM_MPLS_SWITCH_COLOR_MAP; 633 info->exp_map = 634 soc_mem_field32_get(unit, hw_mem, hw_buf, MPLS__EXP_MAPPING_PTRf); 635 info->exp_map |= _BCM_TR_MPLS_EXP_MAP_TABLE_TYPE_INGRESS; 636 } 637 return BCM_E_NONE; 638 } 639 640 /* 641 * Function: 642 * _bcm_tr3_mpls_port_stat_get_table_info 643 * Description: 644 * Provides relevant flex table information(table-name,index with 645 * direction) for specific vpn and gport 646 * 647 * Parameters: 648 * unit - (IN) unit number 649 * vpn - (IN) VPN Id 650 * port - (IN) MPLS GPORT ID 651 * num_of_tables - (OUT) Number of flex counter tables 652 * table_info - (OUT) Flex counter tables information 653 * 654 * Return Value: 655 * BCM_E_XXX 656 * Notes: 657 */ 658 STATIC 659 bcm_error_t _bcm_tr3_mpls_port_stat_get_table_info( 660 int unit, 661 bcm_vpn_t vpn, 662 bcm_gport_t port, 663 uint32 *num_of_tables, 664 bcm_stat_flex_table_info_t *table_info) 665 { 666 int vp=0; 667 ing_dvp_table_entry_t dvp={{0}}; 668 int nh_index=0; 669 initial_prot_nhi_table_entry_t prot_entry; 670 int vpless_failover_port = FALSE; 671 int rv; 672 673 if (_BCM_MPLS_GPORT_FAILOVER_VPLESS_GET(port)) { 674 vpless_failover_port = TRUE; 675 port = _BCM_MPLS_GPORT_FAILOVER_VPLESS_CLEAR(port); 676 } 677 678 (*num_of_tables)=0; 679 if (!soc_feature(unit,soc_feature_advanced_flex_counter)) { 680 return BCM_E_UNAVAIL; 681 } 682 if (soc_feature(unit, soc_feature_mpls)) { 683 BCM_IF_ERROR_RETURN(bcm_tr_mpls_lock(unit)); 684 if (!_BCM_MPLS_VPN_IS_VPLS(vpn) && 685 !_BCM_MPLS_VPN_IS_VPWS(vpn)) { 686 bcm_tr_mpls_unlock (unit); 687 return BCM_E_PARAM; 688 } 689 vp = BCM_GPORT_MPLS_PORT_ID_GET(port); 690 if (vp == -1) { 691 bcm_tr_mpls_unlock (unit); 692 return BCM_E_PARAM; 693 } 694 if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeMpls)) { 695 bcm_tr_mpls_unlock (unit); 696 return BCM_E_NOT_FOUND; 697 } 698 table_info[*num_of_tables].table= SOURCE_VPm; 699 table_info[*num_of_tables].index=vp; 700 table_info[*num_of_tables].direction=bcmStatFlexDirectionIngress; 701 (*num_of_tables)++; 702 if(READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp, &dvp) == BCM_E_NONE) { 703 nh_index=soc_ING_DVP_TABLEm_field32_get(unit, &dvp, NEXT_HOP_INDEXf); 704 rv = BCM_E_NONE; 705 if (vpless_failover_port == TRUE) { 706 rv = READ_INITIAL_PROT_NHI_TABLEm(unit,MEM_BLOCK_ANY, nh_index, &prot_entry); 707 if (BCM_SUCCESS(rv)) { 708 nh_index = soc_INITIAL_PROT_NHI_TABLEm_field32_get(unit,&prot_entry, 709 REPLACEMENT_DATAf); 710 } 711 } 712 if (BCM_SUCCESS(rv)) { 713 table_info[*num_of_tables].table= EGR_L3_NEXT_HOPm; 714 table_info[*num_of_tables].index=nh_index; 715 table_info[*num_of_tables].direction=bcmStatFlexDirectionEgress; 716 (*num_of_tables)++; 717 } 718 } 719 bcm_tr_mpls_unlock (unit); 720 return BCM_E_NONE; 721 } 722 return BCM_E_UNAVAIL; 723 } 724 725 /* 726 * Function: 727 * _bcm_esw_mpls_entry_convert_common_fields 728 * Description: 729 * convert/copies commons fields in two mpls tables i.e 730 * MPLS_ENTRYm and MPLS_ENTRY_EXTDm 731 * (Generic routine) 732 * 733 * Parameters: 734 * unit - (IN) unit number 735 * from_table - (IN) Source Table 736 * to_table - (IN) Destination Table 737 * view_field - (IN) Common view field(KEY_TYPE) deciding view 738 * view_name - (IN) Common view name 739 * from_entry - (IN) Source table entry 740 * to_entry - (OUT) Destination table entry 741 * 742 * Return Value: 743 * BCM_E_XXX 744 * Notes: 745 */ 746 STATIC 747 bcm_error_t _bcm_esw_mpls_entry_convert_common_fields( 748 int unit, 749 soc_mem_t from_table, 750 soc_mem_t to_table, 751 soc_field_t view_field, 752 char *view_name, 753 void *from_entry, 754 void *to_entry) 755 { 756 soc_mem_info_t *memp_from; 757 uint32 key_type=0; 758 int f=0; 759 #if !defined(SOC_NO_NAMES) 760 soc_mem_info_t *memp_to; 761 soc_field_info_t *fieldp_from; 762 uint32 fval[SOC_MAX_MEM_FIELD_WORDS]={0}; 763 soc_field_info_t *fieldp_to; 764 #endif 765 char view_name_with_colon[64]; 766 767 /* sal_memset(to_entry, 0, sizeof(mpls_entry_extd_entry_t)); */ 768 memp_from = &SOC_MEM_INFO(unit, from_table); 769 key_type= soc_mem_field32_get(unit, from_table, 770 (uint32 *)from_entry , view_field); 771 if (sal_strcmp(memp_from->views[key_type],view_name) != 0) { 772 return BCM_E_PARAM; 773 } 774 sal_memset(to_entry, 0, soc_mem_entry_bytes(unit,to_table)); 775 sal_sprintf(view_name_with_colon,"%s:",view_name); 776 for (f = memp_from->nFields - 1; f >= 0; f--) { 777 #if !defined(SOC_NO_NAMES) 778 memp_to = &SOC_MEM_INFO(unit, to_table); 779 fieldp_from = &memp_from->fields[f]; 780 /* LOG_CLI((BSL_META_U(unit, 781 ":%d:%s: ==>"), 782 f,soc_fieldnames[fieldp_from->field])); */ 783 if ((sal_strstr(soc_fieldnames[fieldp_from->field], 784 view_name_with_colon) != NULL) /* || 785 (sal_strstr(soc_fieldnames[fieldp_from->field], ":") == NULL) */) { 786 if (soc_mem_field_valid(unit, 787 to_table,fieldp_from->field)) { 788 SOC_FIND_FIELD(fieldp_from->field, 789 memp_to->fields, 790 memp_to->nFields, 791 fieldp_to); 792 if (fieldp_to->len < fieldp_from->len) { 793 LOG_CLI((BSL_META_U(unit, 794 "Warning:%d:%s: Mismatch in length %d:%d ==>"), 795 f,soc_fieldnames[fieldp_from->field], 796 fieldp_from->len,fieldp_to->len)); 797 } else if (fieldp_to->len > fieldp_from->len) { 798 sal_memset(fval,0,((fieldp_to->len-1) >> 5)+1); 799 LOG_CLI((BSL_META_U(unit, 800 "Warning:%d:%s: More lengthy field %d:%d==>"), 801 f,soc_fieldnames[fieldp_from->field], 802 fieldp_from->len,fieldp_to->len)); 803 } 804 fval[0]=fval[1]=0; 805 soc_mem_field_get(unit, from_table, 806 (uint32 *)from_entry , 807 fieldp_from->field,fval); 808 soc_mem_field_set(unit,to_table, 809 (uint32 *)to_entry , 810 fieldp_from->field, fval); 811 /* LOG_CLI((BSL_META_U(unit, 812 "Matched \n"))); */ 813 } else { 814 /* LOG_CLI((BSL_META_U(unit, 815 "Not Matched \n"))); */ 816 } 817 } else { 818 /* LOG_CLI((BSL_META_U(unit, 819 "Skipped \n"))); */ 820 } 821 #endif 822 } 823 return BCM_E_NONE; 824 } 825 /* 826 * Function: 827 * _bcm_esw_mpls_entry_convert_to_extd_entry 828 * Description: 829 * convert regular source mpls tables entry to extended destination mpls 830 * table entry(MPLS_ENTRYm and MPLS_ENTRY_EXTDm) 831 * 832 * Parameters: 833 * unit - (IN) unit number 834 * mpls_entry_entry - (IN) Source table entry 835 * mpls_entry_extd_entry - (OUT) Destination table entry 836 * 837 * Return Value: 838 * BCM_E_XXX 839 * Notes: 840 */ 841 STATIC 842 bcm_error_t _bcm_esw_mpls_entry_convert_to_extd_entry( 843 int unit, 844 mpls_entry_entry_t *mpls_entry_entry, 845 mpls_entry_extd_entry_t *mpls_entry_extd_entry) 846 { 847 uint32 key_type=0; 848 uint32 fval[SOC_MAX_MEM_FIELD_WORDS]={0}; 849 uint32 new_key_type=0; 850 851 BCM_IF_ERROR_RETURN(_bcm_esw_mpls_entry_convert_common_fields( 852 unit, 853 MPLS_ENTRYm, MPLS_ENTRY_EXTDm,KEY_TYPEf,"MPLS", 854 (void *)mpls_entry_entry, 855 (void *)mpls_entry_extd_entry)); 856 857 /* Take care about special fields */ 858 soc_mem_field_get(unit, MPLS_ENTRYm, 859 (uint32 *)mpls_entry_entry , VALIDf,fval); 860 soc_mem_field_set(unit, MPLS_ENTRY_EXTDm, 861 (uint32 *)mpls_entry_extd_entry, VALID_0f, fval); 862 soc_mem_field_set(unit, MPLS_ENTRY_EXTDm, 863 (uint32 *)mpls_entry_extd_entry, VALID_1f, fval); 864 fval[0] = 0; 865 fval[1] = 0; 866 soc_mem_field_get(unit,MPLS_ENTRYm,(uint32 *)mpls_entry_entry,MPLS__KEYf,fval); 867 soc_mem_field_set(unit,MPLS_ENTRY_EXTDm,(uint32 *)mpls_entry_extd_entry, 868 MPLS__KEY_0f, fval); /* Default KEY_0f */ 869 870 soc_mem_field_get(unit, MPLS_ENTRYm, (uint32 *)mpls_entry_entry , 871 KEY_TYPEf,&key_type); 872 new_key_type=key_type+1; 873 soc_mem_field_set(unit,MPLS_ENTRY_EXTDm,(uint32 *)mpls_entry_extd_entry, 874 KEY_TYPE_0f, &new_key_type); 875 soc_mem_field_set(unit,MPLS_ENTRY_EXTDm,(uint32 *)mpls_entry_extd_entry, 876 KEY_TYPE_1f, &new_key_type); 877 878 fval[0] = 0; 879 fval[1] = 0; 880 soc_mem_field_get(unit, MPLS_ENTRYm,(uint32 *)mpls_entry_entry, MPLS__DATAf,fval); 881 soc_mem_field_set(unit, MPLS_ENTRY_EXTDm, 882 (uint32 *)mpls_entry_extd_entry, MPLS__DATA_0f, fval); 883 return BCM_E_NONE; 884 } 885 /* 886 * Function: 887 * _bcm_esw_mpls_entry_convert_to_regular_entry 888 * Description: 889 * convert extended source mpls tables entry to regular destination mpls 890 * table entry(MPLS_ENTRY_EXTDm and MPLS_ENTRYm) 891 * 892 * Parameters: 893 * unit - (IN) unit number 894 * mpls_entry_extd_entry - (IN) Source table entry 895 * mpls_entry_entry - (OUT) Destination table entry 896 * 897 * Return Value: 898 * BCM_E_XXX 899 * Notes: 900 */ 901 STATIC 902 bcm_error_t _bcm_esw_mpls_entry_convert_to_regular_entry( 903 int unit, 904 mpls_entry_extd_entry_t *mpls_entry_extd_entry, 905 mpls_entry_entry_t *mpls_entry_entry) 906 { 907 uint32 key_type=0; 908 uint32 fval[SOC_MAX_MEM_FIELD_WORDS]; 909 uint32 new_key_type=0; 910 911 BCM_IF_ERROR_RETURN(_bcm_esw_mpls_entry_convert_common_fields( 912 unit, 913 MPLS_ENTRY_EXTDm, MPLS_ENTRYm,KEY_TYPE_0f,"MPLS", 914 (void *)mpls_entry_extd_entry, 915 (void *)mpls_entry_entry)); 916 /* Take care about special fields */ 917 918 fval[0] = 0; 919 fval[1] = 0; 920 soc_mem_field_get(unit, MPLS_ENTRY_EXTDm, 921 (uint32 *)mpls_entry_extd_entry , VALID_0f,fval); 922 soc_mem_field_set(unit, MPLS_ENTRYm,(uint32 *)mpls_entry_entry, 923 VALIDf, fval); 924 925 fval[0] = 0; 926 fval[1] = 0; 927 soc_mem_field_get(unit, MPLS_ENTRY_EXTDm, 928 (uint32 *)mpls_entry_extd_entry , MPLS__KEY_0f,fval); 929 soc_mem_field_set(unit, MPLS_ENTRYm,(uint32 *)mpls_entry_entry, 930 MPLS__KEYf, fval); 931 932 soc_mem_field_get(unit,MPLS_ENTRY_EXTDm, (uint32 *)mpls_entry_extd_entry, 933 KEY_TYPE_0f, &key_type); 934 new_key_type = key_type - 1; 935 soc_mem_field_set(unit, MPLS_ENTRYm, (uint32 *)mpls_entry_entry , 936 KEY_TYPEf, &new_key_type); 937 938 fval[0] = 0; 939 fval[1] = 0; 940 soc_mem_field_get(unit, MPLS_ENTRY_EXTDm, (uint32 *)mpls_entry_extd_entry, 941 MPLS__DATA_0f,fval); 942 /* fval[1] &= 0x3f; */ 943 soc_mem_field_set(unit, MPLS_ENTRYm, (uint32 *)mpls_entry_entry, MPLS__DATAf,fval); 944 945 return BCM_E_NONE; 946 } 947 /* 948 * Function: 949 * _bcm_tr3_mpls_label_stat_get_table_info 950 * Description: 951 * Provides relevant flex table information(table-name,index with 952 * direction) for given mpls label and gport 953 * 954 * Parameters: 955 * unit - (IN) unit number 956 * label - (IN) MPLS Label 957 * port - (IN) MPLS Gport 958 * object - (IN) STAT object 959 * num_of_tables - (OUT) Number of flex counter tables 960 * table_info - (OUT) Flex counter tables information 961 * 962 * Return Value: 963 * BCM_E_XXX 964 * Notes: 965 */ 966 967 STATIC 968 bcm_error_t _bcm_tr3_mpls_label_stat_get_table_info( 969 int unit, 970 bcm_mpls_label_t label, 971 bcm_gport_t port, 972 bcm_stat_object_t object, 973 uint32 *num_of_tables, 974 bcm_stat_flex_table_info_t *table_info) 975 { 976 bcm_error_t rv=BCM_E_NOT_FOUND; 977 bcm_mpls_tunnel_switch_t mpls_tunnel_switch={0}; 978 mpls_entry_entry_t mpls_entry_entry={{0}}; 979 int index[2] = {0, 0}; 980 soc_mem_t mem[2] = {MPLS_ENTRY_EXTDm, L3_TUNNELm}; 981 mpls_entry_extd_entry_t mpls_entry_extd_entry={{0}}; 982 int i, num_found = 0; 983 984 (*num_of_tables)=0; 985 if (!soc_feature(unit,soc_feature_advanced_flex_counter)) { 986 return BCM_E_UNAVAIL; 987 } 988 if (!soc_feature(unit, soc_feature_mpls)) { 989 return BCM_E_UNAVAIL; 990 } 991 if (!SOC_IS_TRIUMPH3(unit)) { 992 return BCM_E_UNAVAIL; 993 } 994 sal_memset(&mpls_entry_entry, 0, sizeof(mpls_entry_entry_t)); 995 sal_memset(&mpls_entry_extd_entry, 0, sizeof(mpls_entry_extd_entry_t)); 996 997 mpls_tunnel_switch.port = port; 998 if (BCM_XGS3_L3_MPLS_LBL_VALID(label)) { 999 mpls_tunnel_switch.label = label; 1000 } else { 1001 return BCM_E_PARAM; 1002 } 1003 1004 if (object != bcmStatObjectIngMplsFrrLabel) { 1005 BCM_IF_ERROR_RETURN(_bcm_tr3_mpls_entry_set_key(unit, 1006 &mpls_tunnel_switch,(uint32 *) &mpls_entry_entry, MPLS_ENTRYm, 0x10)); 1007 rv = soc_mem_search(unit, MPLS_ENTRYm, MEM_BLOCK_ANY, &index[num_found], 1008 &mpls_entry_entry, &mpls_entry_entry, 0); 1009 if (BCM_SUCCESS(rv)) { 1010 BCM_IF_ERROR_RETURN(_bcm_esw_mpls_entry_convert_to_extd_entry( 1011 unit,&mpls_entry_entry,&mpls_entry_extd_entry)); 1012 BCM_IF_ERROR_RETURN(soc_mem_delete( 1013 unit, MPLS_ENTRYm, MEM_BLOCK_ANY, 1014 (void *)&mpls_entry_entry)); 1015 BCM_IF_ERROR_RETURN(soc_mem_insert( 1016 unit, MPLS_ENTRY_EXTDm, MEM_BLOCK_ALL, 1017 (void *)&mpls_entry_extd_entry)); 1018 } else { 1019 /* Possibly entry has already been moved to MPLS_ENTRY_EXTD table */ 1020 BCM_IF_ERROR_RETURN(_bcm_esw_mpls_entry_convert_to_extd_entry( 1021 unit,&mpls_entry_entry,&mpls_entry_extd_entry)); 1022 } 1023 BCM_IF_ERROR_RETURN(soc_mem_search(unit, MPLS_ENTRY_EXTDm, 1024 MEM_BLOCK_ALL,&index[num_found], 1025 (void *)&mpls_entry_extd_entry, 1026 (void *)&mpls_entry_extd_entry,0)); 1027 mem[num_found] = MPLS_ENTRY_EXTDm; 1028 num_found++; 1029 } 1030 if (soc_feature(unit, soc_feature_mpls_frr_lookup)) { 1031 if ((!num_found && (object == bcmStatObjectIngMplsFrrLabel)) || 1032 (object == bcmStatObjectMaxValue)) { 1033 rv = _bcm_tr3_mpls_tunnel_switch_frr_get(unit, 1034 &mpls_tunnel_switch, &index[num_found]); 1035 if (rv == BCM_E_NONE) { 1036 mem[num_found] = L3_TUNNELm; 1037 num_found++; 1038 } 1039 } 1040 } 1041 if (num_found && (rv == BCM_E_NOT_FOUND)) { 1042 rv = BCM_E_NONE; 1043 } 1044 1045 for (i = 0; i < num_found; i++) { 1046 table_info[*num_of_tables].table=mem[i]; 1047 table_info[*num_of_tables].index=index[i]; 1048 table_info[*num_of_tables].direction=bcmStatFlexDirectionIngress; 1049 (*num_of_tables)++; 1050 } 1051 return BCM_E_NONE; 1052 } 1053 1054 /* 1055 * Function: 1056 * _bcm_tr3_egress_object_p2mp_set 1057 * Purpose: 1058 * Set P2MP entry type within Egress Object entry 1059 * Parameters: 1060 * unit - Device Number 1061 * nh_index - Next Hop Index 1062 * flag - Indicates SWAP or PHP 1063 * Returns: 1064 * BCM_E_XXX 1065 */ 1066 1067 STATIC int 1068 _bcm_tr3_egress_object_p2mp_set(int unit, bcm_multicast_t mc_group, int flag) 1069 { 1070 int rv=BCM_E_UNAVAIL; 1071 egr_l3_next_hop_entry_t egr_nh; 1072 int num_encap_id=0; 1073 bcm_if_t *encap_id_array = NULL; 1074 int i; 1075 int nh_index; 1076 1077 1078 /* Get the number of encap IDs of the multicast group */ 1079 rv = bcm_esw_multicast_egress_get(unit, mc_group, 0, 1080 NULL, NULL, &num_encap_id); 1081 if (rv < 0) { 1082 return rv; 1083 } 1084 1085 /* Get all the encap IDs of the multicast group */ 1086 1087 encap_id_array = sal_alloc(sizeof(bcm_if_t) * num_encap_id, 1088 "encap_id_array"); 1089 if (NULL == encap_id_array) { 1090 return BCM_E_MEMORY; 1091 } 1092 sal_memset(encap_id_array, 0, sizeof(bcm_if_t) * num_encap_id); 1093 1094 rv = bcm_esw_multicast_egress_get(unit, mc_group, num_encap_id, 1095 NULL, encap_id_array, &num_encap_id); 1096 if (rv < 0) { 1097 sal_free(encap_id_array); 1098 return rv; 1099 } 1100 1101 /* Convert encap IDs to next hop indices */ 1102 1103 for (i = 0; i < num_encap_id; i++) { 1104 if (BCM_IF_INVALID != (uint32)encap_id_array[i]) { 1105 nh_index = encap_id_array[i] - BCM_XGS3_DVP_EGRESS_IDX_MIN(unit); 1106 BCM_IF_ERROR_RETURN(soc_mem_read(unit, EGR_L3_NEXT_HOPm, 1107 MEM_BLOCK_ANY, nh_index, &egr_nh)); 1108 1109 switch (flag) { 1110 case BCM_MPLS_SWITCH_ACTION_SWAP: 1111 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 1112 MPLS__LABEL_ACTIONf, 0x1); /* SWAP action */ 1113 break; 1114 1115 case BCM_MPLS_SWITCH_ACTION_PHP: 1116 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 1117 MPLS__LABEL_ACTIONf, 0x2); /* PHP action */ 1118 break; 1119 1120 default: 1121 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 1122 MPLS__LABEL_ACTIONf, 0x0); /* NOOP action */ 1123 break; 1124 } 1125 rv = soc_mem_write(unit, EGR_L3_NEXT_HOPm, 1126 MEM_BLOCK_ALL, nh_index, &egr_nh); 1127 if (rv < 0) { 1128 sal_free(encap_id_array); 1129 return rv; 1130 } 1131 } 1132 } 1133 1134 sal_free(encap_id_array); 1135 return rv; 1136 } 1137 1138 /* 1139 * Function: 1140 * _bcm_tr3_mpls_p2mp_bud_entry_set 1141 * Purpose: 1142 * Create P2MP Bud Entry for POP Action 1143 * Parameters: 1144 * unit - Device Number 1145 * mpls_entry 1146 * Returns: 1147 * BCM_E_XXX 1148 */ 1149 1150 STATIC int 1151 _bcm_tr3_mpls_p2mp_bud_entry_set(int unit, bcm_mpls_tunnel_switch_t *info, 1152 mpls_entry_entry_t *ment_entry ) 1153 { 1154 mpls_entry_entry_t ment; 1155 uint8 key_type_2 = 0x12; 1156 int rv = BCM_E_NONE; 1157 int vrf=-1, mode=-1; 1158 uint32 value; 1159 1160 sal_memset(&ment, 0, sizeof(mpls_entry_entry_t)); 1161 1162 if ((info != NULL) && (ment_entry == NULL)) { 1163 if (_BCM_MPLS_VPN_IS_L3(info->vpn)) { 1164 _BCM_MPLS_VPN_GET(vrf, _BCM_MPLS_VPN_TYPE_L3, info->vpn); 1165 if (!bcm_tr_mpls_vrf_used_get(unit, vrf)) { 1166 return BCM_E_PARAM; 1167 } 1168 /* Check L3 Ingress Interface mode. */ 1169 mode = 0; 1170 rv = bcm_xgs3_l3_ingress_mode_get(unit, &mode); 1171 BCM_IF_ERROR_RETURN(rv); 1172 } 1173 BCM_IF_ERROR_RETURN( 1174 _bcm_tr3_mpls_entry_set_key(unit, info, (uint32 *) &ment, MPLS_ENTRYm, key_type_2)); 1175 1176 soc_MPLS_ENTRYm_field32_set(unit, &ment, MPLS__MPLS_ACTION_IF_NOT_BOSf, 1177 0x0); /* INVALID */ 1178 soc_MPLS_ENTRYm_field32_set(unit, &ment, MPLS__MPLS_ACTION_IF_BOSf, 1179 0x2); /* L3_IIF */ 1180 if (!mode) { 1181 soc_MPLS_ENTRYm_field32_set(unit, &ment, MPLS__L3_IIFf, 1182 _BCM_TR_MPLS_L3_IIF_BASE + vrf); 1183 } else { 1184 soc_MPLS_ENTRYm_field32_set(unit, &ment, MPLS__L3_IIFf, info->ingress_if); 1185 } 1186 1187 soc_MPLS_ENTRYm_field32_set(unit, &ment, MPLS__V4_ENABLEf, 1); 1188 soc_MPLS_ENTRYm_field32_set(unit, &ment, MPLS__V6_ENABLEf, 1); 1189 if (info->flags & BCM_MPLS_SWITCH_INNER_TTL) { 1190 soc_MPLS_ENTRYm_field32_set(unit, &ment, MPLS__DECAP_USE_TTLf, 0); 1191 } else { 1192 soc_MPLS_ENTRYm_field32_set(unit, &ment, MPLS__DECAP_USE_TTLf, 1); 1193 } 1194 if (info->flags & BCM_MPLS_SWITCH_INNER_EXP) { 1195 soc_MPLS_ENTRYm_field32_set(unit, &ment, MPLS__DECAP_USE_EXP_FOR_INNERf, 0); 1196 } else { 1197 soc_MPLS_ENTRYm_field32_set(unit, &ment, MPLS__DECAP_USE_EXP_FOR_INNERf, 1); 1198 } 1199 if (info->flags & BCM_MPLS_SWITCH_INT_PRI_MAP) { 1200 soc_MPLS_ENTRYm_field32_set(unit, &ment, MPLS__DECAP_USE_EXP_FOR_PRIf, 1201 0x1); /* MAP_PRI_AND_CNG */ 1202 /* Use specified EXP-map to determine internal prio/color */ 1203 soc_MPLS_ENTRYm_field32_set(unit, &ment, MPLS__EXP_MAPPING_PTRf, 1204 info->exp_map & _BCM_TR_MPLS_EXP_MAP_TABLE_NUM_MASK); 1205 } else if (info->flags & BCM_MPLS_SWITCH_INT_PRI_SET) { 1206 soc_MPLS_ENTRYm_field32_set(unit, &ment, MPLS__DECAP_USE_EXP_FOR_PRIf, 1207 0x2); /* NEW_PRI_MAP_CNG */ 1208 /* Use the specified internal priority value */ 1209 soc_MPLS_ENTRYm_field32_set(unit, &ment, MPLS__NEW_PRIf, 1210 info->int_pri); 1211 /* Use specified EXP-map to determine internal color */ 1212 soc_MPLS_ENTRYm_field32_set(unit, &ment, MPLS__EXP_MAPPING_PTRf, 1213 info->exp_map & _BCM_TR_MPLS_EXP_MAP_TABLE_NUM_MASK); 1214 } 1215 1216 rv = soc_mem_insert(unit, MPLS_ENTRYm, MEM_BLOCK_ALL, &ment); 1217 } else if ((info != NULL) && (ment_entry != NULL)) { 1218 BCM_IF_ERROR_RETURN( 1219 _bcm_tr3_mpls_entry_set_key(unit, info, (uint32 *) &ment, MPLS_ENTRYm, key_type_2)); 1220 1221 soc_MPLS_ENTRYm_field32_set(unit, &ment, MPLS__MPLS_ACTION_IF_NOT_BOSf, 1222 0x0); /* INVALID */ 1223 soc_MPLS_ENTRYm_field32_set(unit, &ment, MPLS__MPLS_ACTION_IF_BOSf, 1224 0x2); /* L3_IIF */ 1225 soc_MPLS_ENTRYm_field32_set(unit, &ment, MPLS__V4_ENABLEf, 1); 1226 soc_MPLS_ENTRYm_field32_set(unit, &ment, MPLS__V6_ENABLEf, 1); 1227 1228 value = soc_MPLS_ENTRYm_field32_get(unit, ment_entry, MPLS__L3_IIFf); 1229 soc_MPLS_ENTRYm_field32_set(unit, &ment, MPLS__L3_IIFf, value); 1230 1231 value = soc_MPLS_ENTRYm_field32_get(unit, ment_entry, MPLS__DECAP_USE_TTLf); 1232 soc_MPLS_ENTRYm_field32_set(unit, &ment, MPLS__DECAP_USE_TTLf, value); 1233 1234 value = soc_MPLS_ENTRYm_field32_get(unit, ment_entry, MPLS__DECAP_USE_EXP_FOR_INNERf); 1235 soc_MPLS_ENTRYm_field32_set(unit, &ment, MPLS__DECAP_USE_EXP_FOR_INNERf, value); 1236 1237 value = soc_MPLS_ENTRYm_field32_get(unit, ment_entry, MPLS__DECAP_USE_EXP_FOR_PRIf); 1238 soc_MPLS_ENTRYm_field32_set(unit, &ment, MPLS__DECAP_USE_EXP_FOR_PRIf, value); 1239 1240 value = soc_MPLS_ENTRYm_field32_get(unit, ment_entry, MPLS__EXP_MAPPING_PTRf); 1241 soc_MPLS_ENTRYm_field32_set(unit, &ment, MPLS__EXP_MAPPING_PTRf, value); 1242 1243 value = soc_MPLS_ENTRYm_field32_get(unit, ment_entry, MPLS__DECAP_USE_EXP_FOR_PRIf); 1244 soc_MPLS_ENTRYm_field32_set(unit, &ment, MPLS__DECAP_USE_EXP_FOR_PRIf, value); 1245 1246 value = soc_MPLS_ENTRYm_field32_get(unit, ment_entry, MPLS__NEW_PRIf); 1247 soc_MPLS_ENTRYm_field32_set(unit, &ment, MPLS__NEW_PRIf, value); 1248 1249 value = soc_MPLS_ENTRYm_field32_get(unit, ment_entry, MPLS__EXP_MAPPING_PTRf); 1250 soc_MPLS_ENTRYm_field32_set(unit, &ment, MPLS__EXP_MAPPING_PTRf, value); 1251 1252 rv = soc_mem_insert(unit, MPLS_ENTRYm, MEM_BLOCK_ALL, &ment); 1253 1254 } else if (info == NULL) { 1255 return BCM_E_PARAM; 1256 } 1257 1258 return rv; 1259 } 1260 1261 /* 1262 * Function: 1263 * _bcm_tr3_mpls_process_swap_label_action 1264 * Purpose: 1265 * Process tunnel_switch.action = SWAP 1266 * Parameters: 1267 * unit - Device Number 1268 * info - Label (switch) information 1269 * Returns: 1270 * BCM_E_XXX 1271 */ 1272 1273 STATIC int 1274 _bcm_tr3_mpls_process_swap_label_action(int unit, bcm_mpls_tunnel_switch_t *info, 1275 int bud_node_trigger, 1276 int *nh_index, 1277 mpls_entry_entry_t *ment ) 1278 { 1279 int rv = BCM_E_NONE; 1280 uint32 mpath_flag=0; 1281 int mc_index = -1; 1282 1283 if (info->flags & BCM_MPLS_SWITCH_P2MP) { 1284 if ( bud_node_trigger ) { 1285 /* Case of Leaf_LSR + Branch_LSR => BUD_LSR */ 1286 1287 /* Insert Second-pass POP entry */ 1288 rv = _bcm_tr3_mpls_p2mp_bud_entry_set(unit, info, ment); 1289 BCM_IF_ERROR_RETURN(rv); 1290 1291 /* Update First-pass SWAP entry, First-pass POP to First-pass SWAP entry */ 1292 soc_MPLS_ENTRYm_field32_set(unit, ment, 1293 MPLS__P2MP_LOCAL_RECEIVERS_PRESENTf, 0x1); 1294 soc_MPLS_ENTRYm_field32_set(unit, ment, MPLS__MPLS_ACTION_IF_NOT_BOSf, 1295 0x0); /* INVALID */ 1296 soc_MPLS_ENTRYm_field32_set(unit, ment, MPLS__MPLS_ACTION_IF_BOSf, 1297 0x5); /* SWAP_L3MC_INDEX */ 1298 soc_MPLS_ENTRYm_field32_set(unit, ment, KEY_TYPEf, 0x10); 1299 1300 if (_BCM_MULTICAST_IS_SET(info->mc_group)) { 1301 mc_index = _BCM_MULTICAST_ID_GET(info->mc_group); 1302 soc_MPLS_ENTRYm_field32_set(unit, ment, MPLS__L3MC_INDEXf, 1303 mc_index); 1304 } else { 1305 return BCM_E_PARAM; 1306 } 1307 1308 rv = _bcm_tr3_mpls_p2mp_loopback_enable(unit); 1309 if (rv < 0) { 1310 return rv; 1311 } 1312 } else { 1313 /* Case of P2MP BRANCH_LSR */ 1314 soc_MPLS_ENTRYm_field32_set(unit, ment, MPLS__MPLS_ACTION_IF_NOT_BOSf, 1315 0x0); /* INVALID */ 1316 soc_MPLS_ENTRYm_field32_set(unit, ment, MPLS__MPLS_ACTION_IF_BOSf, 1317 0x5); /* SWAP_L3MC_INDEX */ 1318 if (_BCM_MULTICAST_IS_SET(info->mc_group)) { 1319 mc_index = _BCM_MULTICAST_ID_GET(info->mc_group); 1320 soc_MPLS_ENTRYm_field32_set(unit, ment, MPLS__L3MC_INDEXf, 1321 mc_index); 1322 } else { 1323 return BCM_E_PARAM; 1324 } 1325 soc_MPLS_ENTRYm_field32_set(unit, ment, KEY_TYPEf, 0x10); 1326 soc_MPLS_ENTRYm_field32_set(unit, ment, VALIDf, 0x1); 1327 } 1328 rv = _bcm_tr3_egress_object_p2mp_set(unit, info->mc_group, 1329 BCM_MPLS_SWITCH_ACTION_SWAP); 1330 } else { 1331 1332 if (!BCM_XGS3_L3_EGRESS_IDX_VALID(unit, info->egress_if)) { 1333 if (!BCM_XGS3_L3_MPATH_EGRESS_IDX_VALID(unit, info->egress_if)) { 1334 return BCM_E_PARAM; 1335 } 1336 } 1337 1338 /* Case of LSR */ 1339 if (BCM_XGS3_L3_MPLS_LBL_VALID(info->egress_label.label)) { 1340 rv = bcm_tr_mpls_l3_nh_info_add(unit, info, nh_index); 1341 if (rv < 0) { 1342 return rv; 1343 } 1344 soc_MPLS_ENTRYm_field32_set(unit, ment, MPLS__NEXT_HOP_INDEXf, *nh_index); 1345 /* Swap to Next_Hop Type */ 1346 soc_MPLS_ENTRYm_field32_set(unit, ment, MPLS__MPLS_ACTION_IF_NOT_BOSf, 1347 0x3); /* SWAP_NHI */ 1348 soc_MPLS_ENTRYm_field32_set(unit, ment, MPLS__MPLS_ACTION_IF_BOSf, 1349 0x3); /* SWAP NHI */ 1350 } else { 1351 rv = bcm_xgs3_get_nh_from_egress_object(unit, info->egress_if, 1352 &mpath_flag, 1, nh_index); 1353 if (rv < 0) { 1354 return rv; 1355 } 1356 if (mpath_flag == BCM_L3_MULTIPATH) { 1357 soc_MPLS_ENTRYm_field32_set(unit, ment, MPLS__ECMP_PTRf, *nh_index); 1358 /* Swap to ECMP Type */ 1359 soc_MPLS_ENTRYm_field32_set(unit, ment, MPLS__MPLS_ACTION_IF_NOT_BOSf, 1360 0x4); /* SWAP_ECMP */ 1361 soc_MPLS_ENTRYm_field32_set(unit, ment, MPLS__MPLS_ACTION_IF_BOSf, 1362 0x4); /* SWAP_ECMP */ 1363 1364 } else { 1365 soc_MPLS_ENTRYm_field32_set(unit, ment, MPLS__NEXT_HOP_INDEXf, *nh_index); 1366 /* Swap to Next_Hop Type */ 1367 soc_MPLS_ENTRYm_field32_set(unit, ment, MPLS__MPLS_ACTION_IF_NOT_BOSf, 1368 0x3); /* SWAP_NHI */ 1369 soc_MPLS_ENTRYm_field32_set(unit, ment, MPLS__MPLS_ACTION_IF_BOSf, 1370 0x3); /* SWAP NHI */ 1371 } 1372 } 1373 } 1374 return rv; 1375 } 1376 1377 1378 /* 1379 * Function: 1380 * _bcm_kt_mpls_process_pop_label_action 1381 * Purpose: 1382 * Process tunnel_switch.action = SWAP 1383 * Parameters: 1384 * unit - Device Number 1385 * info - Label (switch) information 1386 * Returns: 1387 * BCM_E_XXX 1388 */ 1389 1390 STATIC int 1391 _bcm_tr3_mpls_process_pop_label_action(int unit, bcm_mpls_tunnel_switch_t *info, 1392 int bud_node_trigger, 1393 int old_action, 1394 mpls_entry_entry_t *ment ) 1395 { 1396 int rv = BCM_E_NONE; 1397 int vrf=-1, mode=-1; 1398 int mc_index = -1; 1399 uint8 key_type_1 = 0x10; 1400 1401 if (_BCM_MPLS_VPN_IS_L3(info->vpn)) { 1402 _BCM_MPLS_VPN_GET(vrf, _BCM_MPLS_VPN_TYPE_L3, info->vpn); 1403 1404 if (!bcm_tr_mpls_vrf_used_get(unit, vrf)) { 1405 return BCM_E_PARAM; 1406 } 1407 1408 /* Check L3 Ingress Interface mode. */ 1409 mode = 0; 1410 rv = bcm_xgs3_l3_ingress_mode_get(unit, &mode); 1411 BCM_IF_ERROR_RETURN(rv); 1412 } 1413 1414 if (info->flags & BCM_MPLS_SWITCH_P2MP) { 1415 if (bud_node_trigger == 1) { 1416 /* Case of Branch_LSR + Leaf_LSR => BUD_LSR */ 1417 1418 /* Insert Second-pass POP entry */ 1419 rv = _bcm_tr3_mpls_p2mp_bud_entry_set(unit, info, NULL); 1420 BCM_IF_ERROR_RETURN (rv); 1421 1422 /* Update First-pass SWAP to SWAP-BUD entry */ 1423 soc_MPLS_ENTRYm_field32_set(unit, ment, 1424 MPLS__P2MP_LOCAL_RECEIVERS_PRESENTf, 0x1); 1425 soc_MPLS_ENTRYm_field32_set(unit, ment, MPLS__MPLS_ACTION_IF_NOT_BOSf, 1426 0x0); /* INVALID */ 1427 soc_MPLS_ENTRYm_field32_set(unit, ment, MPLS__MPLS_ACTION_IF_BOSf, 1428 0x5); /* SWAP_L3MC_INDEX */ 1429 soc_MPLS_ENTRYm_field32_set(unit, ment, KEY_TYPEf, key_type_1); 1430 1431 if (_BCM_MULTICAST_IS_SET(info->mc_group)) { 1432 mc_index = _BCM_MULTICAST_ID_GET(info->mc_group); 1433 soc_MPLS_ENTRYm_field32_set(unit, ment, MPLS__L3MC_INDEXf, 1434 mc_index); 1435 } else { 1436 return BCM_E_PARAM; 1437 } 1438 1439 rv = _bcm_tr3_mpls_p2mp_loopback_enable(unit); 1440 } else { 1441 /* Case of LEAF_LSR */ 1442 soc_MPLS_ENTRYm_field32_set(unit, ment, MPLS__MPLS_ACTION_IF_NOT_BOSf, 1443 0x0); /* INVALID */ 1444 soc_MPLS_ENTRYm_field32_set(unit, ment, MPLS__MPLS_ACTION_IF_BOSf, 1445 0x2); /* L3_IIF */ 1446 if (!mode) { 1447 soc_MPLS_ENTRYm_field32_set(unit, ment, MPLS__L3_IIFf, 1448 _BCM_TR_MPLS_L3_IIF_BASE + vrf); 1449 } else { 1450 soc_MPLS_ENTRYm_field32_set(unit, ment, MPLS__L3_IIFf, info->ingress_if); 1451 } 1452 } 1453 } else { 1454 /* Case of LSR */ 1455 soc_MPLS_ENTRYm_field32_set(unit, ment, MPLS__MPLS_ACTION_IF_NOT_BOSf, 1456 0x1); /* POP */ 1457 soc_MPLS_ENTRYm_field32_set(unit, ment, MPLS__MPLS_ACTION_IF_BOSf, 1458 0x2); /* L3_IIF */ 1459 if (!mode) { 1460 _bcm_l3_ingress_intf_t iif; 1461 sal_memset(&iif, 0, sizeof(_bcm_l3_ingress_intf_t)); 1462 iif.intf_id = _BCM_TR_MPLS_L3_IIF_BASE + vrf; 1463 rv = _bcm_tr_l3_ingress_interface_get(unit, NULL, &iif); 1464 if (BCM_FAILURE(rv)) { 1465 return rv; 1466 } 1467 iif.vrf = vrf; 1468 rv = _bcm_tr_l3_ingress_interface_set(unit, &iif, NULL, NULL); 1469 if (BCM_FAILURE(rv)) { 1470 return rv; 1471 } 1472 1473 soc_MPLS_ENTRYm_field32_set(unit, ment, MPLS__L3_IIFf, 1474 _BCM_TR_MPLS_L3_IIF_BASE + vrf); 1475 } else { 1476 soc_MPLS_ENTRYm_field32_set(unit, ment, MPLS__L3_IIFf, info->ingress_if); 1477 } 1478 } 1479 return rv; 1480 } 1481 1482 1483 /* 1484 * Function: 1485 * _bcm_kt_mpls_process_php_label_action 1486 * Purpose: 1487 * Process tunnel_switch.action = PHP 1488 * Parameters: 1489 * unit - Device Number 1490 * info - Label (switch) information 1491 * Returns: 1492 * BCM_E_XXX 1493 */ 1494 1495 STATIC int 1496 _bcm_tr3_mpls_process_php_label_action(int unit, bcm_mpls_tunnel_switch_t *info, 1497 int *nh_index, 1498 mpls_entry_entry_t *ment ) 1499 { 1500 int rv = BCM_E_NONE; 1501 uint32 mpath_flag=0; 1502 1503 /* Case of LSR */ 1504 if (!BCM_XGS3_L3_EGRESS_IDX_VALID(unit, info->egress_if)) { 1505 if (!BCM_XGS3_L3_MPATH_EGRESS_IDX_VALID(unit, info->egress_if)) { 1506 return BCM_E_PARAM; 1507 } 1508 } 1509 /* 1510 * Get egress next-hop index from egress object and 1511 * increment egress object reference count. 1512 */ 1513 1514 BCM_IF_ERROR_RETURN(bcm_xgs3_get_nh_from_egress_object(unit, info->egress_if, 1515 &mpath_flag, 1, nh_index)); 1516 1517 /* Fix: Entry_Type = 1, for PHP Packets with more than 1 Label */ 1518 /* Read the egress next_hop entry pointed by Egress-Object */ 1519 rv = bcm_tr_mpls_egress_entry_modify(unit, *nh_index, mpath_flag, 1); 1520 if (rv < 0 ) { 1521 return rv; 1522 } 1523 if (mpath_flag == BCM_L3_MULTIPATH) { 1524 soc_MPLS_ENTRYm_field32_set(unit, ment, MPLS__ECMP_PTRf, *nh_index); 1525 /* Swap to ECMP Type */ 1526 soc_MPLS_ENTRYm_field32_set(unit, ment, MPLS__MPLS_ACTION_IF_NOT_BOSf, 1527 0x7); /* PHP_ECMP */ 1528 soc_MPLS_ENTRYm_field32_set(unit, ment, MPLS__MPLS_ACTION_IF_BOSf, 1529 0x7); /* PHP_ECMP */ 1530 } else { 1531 soc_MPLS_ENTRYm_field32_set(unit, ment, MPLS__NEXT_HOP_INDEXf, *nh_index); 1532 /* Swap to Next_Hop Type */ 1533 soc_MPLS_ENTRYm_field32_set(unit, ment, MPLS__MPLS_ACTION_IF_NOT_BOSf, 1534 0x6); /* PHP_NHI */ 1535 soc_MPLS_ENTRYm_field32_set(unit, ment, MPLS__MPLS_ACTION_IF_BOSf, 1536 0x6); /* PHP_NHI */ 1537 } 1538 return rv; 1539 } 1540 1541 /* 1542 * Function: 1543 * bcm_tr3_mpls_entry_internal_qos_set 1544 * Purpose: 1545 * Set MPLS Entry QoS parameters 1546 * Parameters: 1547 * IN : Unit 1548 * IN : mpls_port 1549 * IN : mpls_entry 1550 * Returns: 1551 * BCM_E_XXX 1552 */ 1553 1554 void 1555 bcm_tr3_mpls_entry_internal_qos_set(int unit, bcm_mpls_port_t *mpls_port, 1556 bcm_mpls_tunnel_switch_t *info, mpls_entry_entry_t *ment) 1557 { 1558 if (mpls_port != NULL ) { 1559 if (mpls_port->flags & BCM_MPLS_PORT_INT_PRI_MAP) { 1560 soc_MPLS_ENTRYm_field32_set(unit, ment, MPLS__DECAP_USE_EXP_FOR_PRIf, 1561 0x1); /* MAP_PRI_AND_CNG */ 1562 /* Use specified EXP-map to determine internal prio/color */ 1563 soc_MPLS_ENTRYm_field32_set(unit, ment, MPLS__EXP_MAPPING_PTRf, 1564 mpls_port->exp_map & _BCM_TR_MPLS_EXP_MAP_TABLE_NUM_MASK); 1565 } else if ((mpls_port->flags & BCM_MPLS_PORT_INT_PRI_SET) && 1566 (mpls_port->flags & BCM_MPLS_PORT_COLOR_MAP)) { 1567 soc_MPLS_ENTRYm_field32_set(unit, ment, MPLS__DECAP_USE_EXP_FOR_PRIf, 1568 0x2); /* NEW_PRI_MAP_CNG */ 1569 /* Use the specified internal priority value */ 1570 soc_MPLS_ENTRYm_field32_set(unit, ment, MPLS__NEW_PRIf, 1571 mpls_port->int_pri); 1572 /* Use specified EXP-map to determine internal color */ 1573 soc_MPLS_ENTRYm_field32_set(unit, ment, MPLS__EXP_MAPPING_PTRf, 1574 mpls_port->exp_map & _BCM_TR_MPLS_EXP_MAP_TABLE_NUM_MASK); 1575 } else if (mpls_port->flags & BCM_MPLS_PORT_INT_PRI_SET) { 1576 soc_MPLS_ENTRYm_field32_set(unit, ment, MPLS__DECAP_USE_EXP_FOR_PRIf, 0x2); 1577 if (soc_mem_field_valid(unit, MPLS_ENTRYm, 1578 MPLS__TRUST_OUTER_DOT1P_PTRf)) { 1579 soc_MPLS_ENTRYm_field32_set(unit, ment, 1580 MPLS__TRUST_OUTER_DOT1P_PTRf, 1581 _BCM_TR_MPLS_PRI_CNG_MAP_NONE); 1582 } 1583 soc_MPLS_ENTRYm_field32_set(unit, ment, MPLS__NEW_PRIf, 1584 mpls_port->int_pri); 1585 } else { 1586 /* Trust the encapsulated packet's 802.1p pri/cfi, 1587 * and use the incoming ports mapping. 1588 */ 1589 soc_MPLS_ENTRYm_field32_set(unit, ment, MPLS__DECAP_USE_EXP_FOR_PRIf, 1590 0x0); /* NONE */ 1591 if (soc_mem_field_valid(unit, MPLS_ENTRYm, 1592 MPLS__TRUST_OUTER_DOT1P_PTRf)) { 1593 soc_MPLS_ENTRYm_field32_set(unit, ment, 1594 MPLS__TRUST_OUTER_DOT1P_PTRf, 1595 _BCM_TR_MPLS_PRI_CNG_MAP_IDENTITY); 1596 } 1597 } 1598 }else if ( info != NULL ) { 1599 if (info->flags & BCM_MPLS_SWITCH_INT_PRI_MAP) { 1600 soc_MPLS_ENTRYm_field32_set(unit, ment, MPLS__DECAP_USE_EXP_FOR_PRIf, 1601 0x1); /* MAP_PRI_AND_CNG */ 1602 /* Use specified EXP-map to determine internal prio/color */ 1603 soc_MPLS_ENTRYm_field32_set(unit, ment, MPLS__EXP_MAPPING_PTRf, 1604 info->exp_map & _BCM_TR_MPLS_EXP_MAP_TABLE_NUM_MASK); 1605 } else if ((info->flags & BCM_MPLS_SWITCH_INT_PRI_SET) && 1606 (info->flags & BCM_MPLS_SWITCH_COLOR_MAP)) { 1607 soc_MPLS_ENTRYm_field32_set(unit, ment, MPLS__DECAP_USE_EXP_FOR_PRIf, 1608 0x2); /* NEW_PRI_MAP_CNG */ 1609 /* Use the specified internal priority value */ 1610 soc_MPLS_ENTRYm_field32_set(unit, ment, MPLS__NEW_PRIf, 1611 info->int_pri); 1612 /* Use specified EXP-map to determine internal color */ 1613 soc_MPLS_ENTRYm_field32_set(unit, ment, MPLS__EXP_MAPPING_PTRf, 1614 info->exp_map & _BCM_TR_MPLS_EXP_MAP_TABLE_NUM_MASK); 1615 } else if (info->flags & BCM_MPLS_SWITCH_INT_PRI_SET) { 1616 soc_MPLS_ENTRYm_field32_set(unit, ment, MPLS__DECAP_USE_EXP_FOR_PRIf, 0x2); 1617 if (soc_mem_field_valid(unit, MPLS_ENTRYm, 1618 MPLS__TRUST_OUTER_DOT1P_PTRf)) { 1619 soc_MPLS_ENTRYm_field32_set(unit, ment, 1620 MPLS__TRUST_OUTER_DOT1P_PTRf, 1621 _BCM_TR_MPLS_PRI_CNG_MAP_NONE); 1622 } 1623 soc_MPLS_ENTRYm_field32_set(unit, ment, MPLS__NEW_PRIf, 1624 info->int_pri); 1625 } else { 1626 /* Trust the encapsulated packet's 802.1p pri/cfi, 1627 * and use the incoming ports mapping. 1628 */ 1629 soc_MPLS_ENTRYm_field32_set(unit, ment, MPLS__DECAP_USE_EXP_FOR_PRIf, 1630 0x0); /* NONE */ 1631 if (soc_mem_field_valid(unit, MPLS_ENTRYm, 1632 MPLS__TRUST_OUTER_DOT1P_PTRf)) { 1633 soc_MPLS_ENTRYm_field32_set(unit, ment, 1634 MPLS__TRUST_OUTER_DOT1P_PTRf, 1635 _BCM_TR_MPLS_PRI_CNG_MAP_IDENTITY); 1636 } 1637 } 1638 } 1639 } 1640 1641 /* 1642 * Function: 1643 * _bcm_tr3_mpls_tunnel_switch_frr_entry_key_get 1644 * Purpose: 1645 * Populate key part from tunnel terminator entry 1646 * Parameters: 1647 * unit - Device Number 1648 * tnl_entry - (IN)Tunnel terminator entry. 1649 * info - Label (switch) information 1650 * Returns: 1651 * BCM_E_XXX 1652 */ 1653 int 1654 _bcm_tr3_mpls_tunnel_switch_frr_entry_key_get(int unit, soc_tunnel_term_t *tnl_entry, 1655 bcm_mpls_tunnel_switch_t *info) 1656 { 1657 bcm_port_t port_in, port_out; 1658 bcm_module_t mod_in, mod_out; 1659 bcm_trunk_t trunk_id; 1660 1661 port_in = soc_L3_TUNNELm_field32_get(unit, tnl_entry, MPLS__PORT_NUMf); 1662 mod_in = soc_L3_TUNNELm_field32_get(unit, tnl_entry, MPLS__MODULE_IDf); 1663 if (soc_L3_TUNNELm_field32_get(unit, tnl_entry, MPLS__Tf)) { 1664 trunk_id = soc_L3_TUNNELm_field32_get(unit, tnl_entry, MPLS__TGIDf); 1665 BCM_GPORT_TRUNK_SET(info->port, trunk_id); 1666 } else if ((port_in == 0) && (mod_in == 0)) { 1667 /* Global label, mod/port not part of lookup key */ 1668 info->port = BCM_GPORT_INVALID; 1669 } else { 1670 BCM_IF_ERROR_RETURN 1671 (_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET, 1672 mod_in, port_in, &mod_out, &port_out)); 1673 BCM_GPORT_MODPORT_SET(info->port, mod_out, port_out); 1674 } 1675 info->label = soc_L3_TUNNELm_field32_get(unit, tnl_entry, MPLS__MPLS_LABELf); 1676 1677 return BCM_E_NONE; 1678 } 1679 1680 /* 1681 * Function: 1682 * _bcm_tr3_mpls_tunnel_switch_frr_entry_key_init 1683 * Purpose: 1684 * Set MPLS Tunnel-switch entry key for Fast Reroute 1685 * Parameters: 1686 * unit - (IN)SOC unit number. 1687 * tnl_info - (IN)MPLS Tunnel terminator parameters. 1688 * Returns: 1689 * BCM_E_XXX 1690 */ 1691 int 1692 _bcm_tr3_mpls_tunnel_switch_frr_entry_key_init(int unit, bcm_mpls_tunnel_switch_t *info, soc_tunnel_term_t *tnl_entry) 1693 { 1694 soc_mem_t tunnel_mem; 1695 bcm_module_t mod_out=-1; 1696 bcm_port_t port_out=-1; 1697 bcm_trunk_t trunk_id=-1; 1698 int gport_id=-1; 1699 int rv=BCM_E_NONE; 1700 1701 tunnel_mem = L3_TUNNELm; 1702 1703 if (info->port == BCM_GPORT_INVALID) { 1704 /* Global label, mod/port not part of lookup key */ 1705 soc_mem_field32_set(unit, tunnel_mem, tnl_entry, MPLS__MODULE_IDf, 0); 1706 soc_mem_field32_set(unit, tunnel_mem, tnl_entry, MPLS__PORT_NUMf, 0); 1707 if (BCM_XGS3_L3_MPLS_LBL_VALID(info->label)) { 1708 soc_mem_field32_set(unit, tunnel_mem, tnl_entry, MPLS__MPLS_LABELf, info->label); 1709 } else { 1710 return BCM_E_PARAM; 1711 } 1712 soc_mem_field32_set(unit, tunnel_mem, tnl_entry, VALIDf, 1713 (1 << soc_mem_field_length(unit, tunnel_mem, VALIDf)) - 1); 1714 1715 #ifdef BCM_APACHE_SUPPORT 1716 if (soc_feature(unit, soc_feature_l3_tunnel_mode_fld_is_keytype)) { 1717 soc_mem_field32_set(unit, tunnel_mem, tnl_entry, MODEf, 0x2); 1718 } else 1719 #endif 1720 { 1721 soc_mem_field32_set(unit, tunnel_mem, tnl_entry, KEY_TYPEf, 0x2); 1722 } 1723 1724 } else { 1725 1726 rv = _bcm_esw_gport_resolve(unit, info->port, &mod_out, 1727 &port_out, &trunk_id, &gport_id); 1728 BCM_IF_ERROR_RETURN(rv); 1729 1730 if (BCM_GPORT_IS_TRUNK(info->port)) { 1731 soc_mem_field32_set(unit, tunnel_mem, tnl_entry, MPLS__Tf, 1); 1732 soc_mem_field32_set(unit, tunnel_mem, tnl_entry, MPLS__TGIDf, trunk_id); 1733 } else { 1734 soc_mem_field32_set(unit, tunnel_mem, tnl_entry, MPLS__MODULE_IDf, mod_out); 1735 soc_mem_field32_set(unit, tunnel_mem, tnl_entry, MPLS__PORT_NUMf, port_out); 1736 } 1737 if (BCM_XGS3_L3_MPLS_LBL_VALID(info->label)) { 1738 soc_mem_field32_set(unit, tunnel_mem, tnl_entry, MPLS__MPLS_LABELf, info->label); 1739 } else { 1740 return BCM_E_PARAM; 1741 } 1742 soc_mem_field32_set(unit, tunnel_mem, tnl_entry, VALIDf, 1743 (1 << soc_mem_field_length(unit, tunnel_mem, VALIDf)) - 1); 1744 1745 #ifdef BCM_APACHE_SUPPORT 1746 if (soc_feature(unit, soc_feature_l3_tunnel_mode_fld_is_keytype)) { 1747 soc_mem_field32_set(unit, tunnel_mem, tnl_entry, MODEf, 0x2); 1748 } else 1749 #endif 1750 { 1751 soc_mem_field32_set(unit, tunnel_mem, tnl_entry, KEY_TYPEf, 0x2); 1752 } 1753 1754 } 1755 1756 soc_mem_field32_set(unit, tunnel_mem, 1757 tnl_entry, MPLS__MPLS_LABEL_MASKf, 0xfffff); 1758 soc_mem_field32_set(unit, tunnel_mem, 1759 tnl_entry, MPLS__T_MASKf, 0x1); 1760 if (SOC_IS_KATANA2(unit) || 1761 (soc_feature(unit, soc_feature_l3_tunnel_expanded_mod_mask))) { 1762 soc_mem_field32_set(unit, tunnel_mem, 1763 tnl_entry, MPLS__MODULE_ID_MASKf, 0xff); 1764 } else { 1765 soc_mem_field32_set(unit, tunnel_mem, 1766 tnl_entry, MPLS__MODULE_ID_MASKf, 0xf); 1767 } 1768 soc_mem_field32_set(unit, tunnel_mem, 1769 tnl_entry, MPLS__PORT_NUM_MASKf, 0x7f); 1770 soc_mem_field32_set(unit, tunnel_mem, 1771 tnl_entry, MPLS__TGID_MASKf, 0x3ff); 1772 #ifdef BCM_APACHE_SUPPORT 1773 if (soc_feature(unit, soc_feature_l3_tunnel_mode_fld_is_keytype)) { 1774 soc_mem_field32_set(unit, tunnel_mem, 1775 tnl_entry, MPLS__MODE_MASKf, 0x3); 1776 } else 1777 #endif 1778 { 1779 soc_mem_field32_set(unit, tunnel_mem, 1780 tnl_entry, MPLS__KEY_TYPE_MASKf, 0x3); 1781 } 1782 return BCM_E_NONE; 1783 } 1784 1785 /* 1786 * Function: 1787 * _bcm_tr3_mpls_frr_entry_set 1788 * Purpose: 1789 * Set MPLS Tunnel-switch entry for Fast Reroute 1790 * Parameters: 1791 * IN : Unit 1792 * IN : info 1793 * Returns: 1794 * BCM_E_XXX 1795 */ 1796 1797 int 1798 _bcm_tr3_mpls_tunnel_switch_frr_set(int unit, bcm_mpls_tunnel_switch_t *info) 1799 { 1800 soc_mem_t tunnel_mem; 1801 soc_tunnel_term_t tnl_entry; 1802 uint32 index; 1803 int rv = BCM_E_NONE; 1804 int max_int_pri = 15; 1805 1806 sal_memset(&tnl_entry, 0, sizeof(tnl_entry)); 1807 tunnel_mem = L3_TUNNELm; 1808 1809 /* Setup TCAM key */ 1810 rv = _bcm_tr3_mpls_tunnel_switch_frr_entry_key_init(unit, info, &tnl_entry); 1811 BCM_IF_ERROR_RETURN(rv); 1812 1813 if (info->flags & BCM_MPLS_SWITCH_INT_PRI_SET) { 1814 if ((info->int_pri < BCM_PRIO_MIN) || (info->int_pri > max_int_pri)) { 1815 return BCM_E_PARAM; 1816 } 1817 } 1818 1819 soc_mem_field32_set(unit, tunnel_mem, &tnl_entry, 1820 MPLS__MPLS_ACTION_IF_NOT_BOSf, 1821 0x1); /* POP */ 1822 1823 if (info->flags & BCM_MPLS_SWITCH_INT_PRI_MAP) { 1824 soc_mem_field32_set(unit, tunnel_mem, &tnl_entry, 1825 MPLS__DECAP_USE_EXP_FOR_PRIf, 1826 0x1); /* MAP_PRI_AND_CNG */ 1827 /* Use specified EXP-map to determine internal prio/color */ 1828 soc_mem_field32_set(unit, tunnel_mem, &tnl_entry, 1829 MPLS__EXP_MAPPING_PTRf, 1830 info->exp_map & _BCM_TR_MPLS_EXP_MAP_TABLE_NUM_MASK); 1831 } else if ((info->flags & BCM_MPLS_SWITCH_INT_PRI_SET) && 1832 (info->flags & BCM_MPLS_SWITCH_COLOR_MAP)) { 1833 soc_mem_field32_set(unit, tunnel_mem, &tnl_entry, 1834 MPLS__DECAP_USE_EXP_FOR_PRIf, 1835 0x2); /* NEW_PRI_MAP_CNG */ 1836 /* Use the specified internal priority value */ 1837 soc_mem_field32_set(unit, tunnel_mem, &tnl_entry, 1838 MPLS__NEW_PRIf, 1839 info->int_pri); 1840 /* Use specified EXP-map to determine internal color */ 1841 soc_mem_field32_set(unit, tunnel_mem, &tnl_entry, 1842 MPLS__EXP_MAPPING_PTRf, 1843 info->exp_map & _BCM_TR_MPLS_EXP_MAP_TABLE_NUM_MASK); 1844 } else if (info->flags & BCM_MPLS_SWITCH_INT_PRI_SET) { 1845 soc_mem_field32_set(unit, tunnel_mem, &tnl_entry, 1846 MPLS__DECAP_USE_EXP_FOR_PRIf, 0x2); 1847 soc_mem_field32_set(unit, tunnel_mem, &tnl_entry, 1848 MPLS__NEW_PRIf, info->int_pri); 1849 } else { 1850 /* Trust the encapsulated packet's 802.1p pri/cfi, 1851 * and use the incoming ports mapping. 1852 */ 1853 soc_mem_field32_set(unit, tunnel_mem, &tnl_entry, 1854 MPLS__DECAP_USE_EXP_FOR_PRIf, 0x0); /* NONE */ 1855 } 1856 1857 if (info->flags & BCM_MPLS_SWITCH_INNER_TTL) { 1858 soc_mem_field32_set(unit, tunnel_mem, &tnl_entry, 1859 MPLS__DECAP_USE_TTLf, 0); 1860 } else { 1861 soc_mem_field32_set(unit, tunnel_mem, &tnl_entry, 1862 MPLS__DECAP_USE_TTLf, 1); 1863 } 1864 1865 if (info->flags & BCM_MPLS_SWITCH_INNER_EXP) { 1866 soc_mem_field32_set(unit, tunnel_mem, &tnl_entry, 1867 MPLS__DECAP_USE_EXP_FOR_INNERf, 0); 1868 } else { 1869 soc_mem_field32_set(unit, tunnel_mem, &tnl_entry, 1870 MPLS__DECAP_USE_EXP_FOR_INNERf, 1); 1871 } 1872 1873 if (info->flags & BCM_MPLS_SWITCH_DROP) { 1874 soc_mem_field32_set(unit, tunnel_mem, &tnl_entry, 1875 MPLS__DROP_DATA_ENABLEf, 1); 1876 } else { 1877 soc_mem_field32_set(unit, tunnel_mem, &tnl_entry, 1878 MPLS__DROP_DATA_ENABLEf, 0); 1879 } 1880 #ifdef BCM_TOMAHAWK2_SUPPORT 1881 if (soc_feature(unit, soc_feature_mpls_ecn) && 1882 (info->flags & BCM_MPLS_SWITCH_INGRESS_ECN_MAP)) { 1883 int ecn_map_index; 1884 int ecn_map_type; 1885 int ecn_map_num; 1886 int ecn_map_hw_idx; 1887 ecn_map_type = info->ecn_map_id & 1888 _BCM_XGS5_MPLS_ECN_MAP_TYPE_MASK; 1889 ecn_map_index = info->ecn_map_id & 1890 _BCM_XGS5_MPLS_ECN_MAP_NUM_MASK; 1891 ecn_map_num = 1892 soc_mem_index_count(unit, ING_EXP_TO_IP_ECN_MAPPINGm) / 1893 _BCM_ECN_MAX_ENTRIES_PER_MAP; 1894 if (ecn_map_type != _BCM_XGS5_MPLS_ECN_MAP_TYPE_EXP2ECN) { 1895 return BCM_E_PARAM; 1896 } 1897 if (ecn_map_index >= ecn_map_num) { 1898 return BCM_E_PARAM; 1899 } 1900 if (!bcmi_xgs5_ecn_map_used_get(unit, ecn_map_index, 1901 _bcmEcnmapTypeExp2Ecn)) { 1902 return BCM_E_PARAM; 1903 } 1904 BCM_IF_ERROR_RETURN( 1905 bcmi_ecn_map_id2hw_idx(unit, info->ecn_map_id, &ecn_map_hw_idx)); 1906 soc_mem_field32_set(unit, tunnel_mem, &tnl_entry, 1907 MPLS__EXP_TO_IP_ECN_MAPPING_PTRf, ecn_map_hw_idx); 1908 } 1909 #endif 1910 1911 #ifdef BCM_APACHE_SUPPORT 1912 /*CLASS_ID used for OAM applications*/ 1913 if (SOC_MEM_FIELD_VALID(unit, tunnel_mem, MPLS__CLASS_IDf)) { 1914 if (info->class_id) { 1915 int bit_num = 0; 1916 bit_num = soc_mem_field_length(unit, tunnel_mem, MPLS__CLASS_IDf); 1917 if (info->class_id > (( 1 << bit_num ) - 1)) { 1918 return BCM_E_PARAM; 1919 } 1920 soc_mem_field32_set(unit, tunnel_mem, &tnl_entry, 1921 MPLS__CLASS_IDf, info->class_id); 1922 } 1923 } 1924 #endif 1925 1926 /* Add tunnel terminator in TCAM. */ 1927 rv = soc_tunnel_term_insert(unit, &tnl_entry, &index); 1928 return rv; 1929 } 1930 1931 /* 1932 * Function: 1933 * _bcm_tr3_mpls_tunnel_switch_frr_parse 1934 * Purpose: 1935 * Parse MPLS Tunnel-switch entry for Fast Reroute 1936 * Parameters: 1937 * IN : Unit 1938 * IN : info 1939 * Returns: 1940 */ 1941 1942 void 1943 _bcm_tr3_mpls_tunnel_switch_frr_parse(int unit, soc_tunnel_term_t *tnl_entry, bcm_mpls_tunnel_switch_t *tnl_info) 1944 { 1945 1946 if ( 0x1 == soc_L3_TUNNELm_field32_get (unit, tnl_entry, MPLS__MPLS_ACTION_IF_NOT_BOSf)) { 1947 tnl_info->action = BCM_MPLS_SWITCH_ACTION_POP; 1948 } 1949 1950 if (soc_L3_TUNNELm_field32_get(unit, tnl_entry, MPLS__DROP_DATA_ENABLEf)) { 1951 tnl_info->flags |= BCM_MPLS_SWITCH_DROP; 1952 } 1953 if (!soc_L3_TUNNELm_field32_get(unit, tnl_entry, MPLS__DECAP_USE_TTLf)) { 1954 tnl_info->flags |= BCM_MPLS_SWITCH_INNER_TTL; 1955 } 1956 if (!soc_L3_TUNNELm_field32_get(unit, tnl_entry, MPLS__DECAP_USE_EXP_FOR_INNERf)) { 1957 tnl_info->flags |= BCM_MPLS_SWITCH_INNER_EXP; 1958 } 1959 if (soc_L3_TUNNELm_field32_get(unit, tnl_entry, 1960 MPLS__DECAP_USE_EXP_FOR_PRIf) == 0x1) { 1961 1962 /* Use specified EXP-map to determine internal prio/color */ 1963 tnl_info->flags |= BCM_MPLS_SWITCH_INT_PRI_MAP; 1964 tnl_info->exp_map = 1965 soc_L3_TUNNELm_field32_get(unit, tnl_entry, MPLS__EXP_MAPPING_PTRf); 1966 tnl_info->exp_map |= _BCM_TR_MPLS_EXP_MAP_TABLE_TYPE_INGRESS; 1967 } else if (soc_L3_TUNNELm_field32_get(unit, tnl_entry, 1968 MPLS__DECAP_USE_EXP_FOR_PRIf) == 0x2) { 1969 1970 /* Use the specified internal priority value */ 1971 tnl_info->flags |= BCM_MPLS_SWITCH_INT_PRI_SET; 1972 tnl_info->int_pri = 1973 soc_L3_TUNNELm_field32_get(unit, tnl_entry, MPLS__NEW_PRIf); 1974 1975 /* Use specified EXP-map to determine internal color */ 1976 tnl_info->flags |= BCM_MPLS_SWITCH_COLOR_MAP; 1977 tnl_info->exp_map = 1978 soc_L3_TUNNELm_field32_get(unit, tnl_entry, MPLS__EXP_MAPPING_PTRf); 1979 tnl_info->exp_map |= _BCM_TR_MPLS_EXP_MAP_TABLE_TYPE_INGRESS; 1980 } 1981 #ifdef BCM_TOMAHAWK2_SUPPORT 1982 if (soc_feature(unit, soc_feature_mpls_ecn)) { 1983 int ecn_map_id; 1984 int ecn_map_hw_idx; 1985 int rv; 1986 ecn_map_hw_idx = soc_L3_TUNNELm_field32_get(unit, tnl_entry, 1987 MPLS__EXP_TO_IP_ECN_MAPPING_PTRf); 1988 rv = bcmi_ecn_map_hw_idx2id(unit, ecn_map_hw_idx, 1989 _BCM_XGS5_MPLS_ECN_MAP_TYPE_EXP2ECN, 1990 &ecn_map_id); 1991 if (BCM_SUCCESS(rv)) { 1992 tnl_info->flags |= BCM_MPLS_SWITCH_INGRESS_ECN_MAP; 1993 tnl_info->ecn_map_id = ecn_map_id; 1994 } 1995 } 1996 #endif 1997 1998 #ifdef BCM_APACHE_SUPPORT 1999 if (SOC_MEM_FIELD_VALID(unit, L3_TUNNELm, MPLS__CLASS_IDf)) { 2000 tnl_info->class_id = 2001 soc_L3_TUNNELm_field32_get(unit, tnl_entry, MPLS__CLASS_IDf); 2002 } 2003 #endif 2004 2005 /* Set FRR flag */ 2006 tnl_info->flags |= BCM_MPLS_SWITCH_FRR; 2007 2008 return; 2009 } 2010 2011 /* 2012 * Function: 2013 * _bcm_tr3_mpls_tunnel_switch_frr_delete 2014 * Purpose: 2015 * Delete MPLS Tunnel-switch entry for Fast Reroute 2016 * Parameters: 2017 * unit - (IN)SOC unit number. 2018 * tnl_info - (IN)MPLS Tunnel terminator parameters. 2019 * Returns: 2020 * BCM_E_XXX 2021 */ 2022 int 2023 _bcm_tr3_mpls_tunnel_switch_frr_delete(int unit, bcm_mpls_tunnel_switch_t *tnl_info) 2024 { 2025 soc_tunnel_term_t tnl_entry; 2026 int rv = BCM_E_NONE; 2027 2028 sal_memset(&tnl_entry, 0, sizeof(tnl_entry)); 2029 2030 /* Setup TCAM key */ 2031 rv = _bcm_tr3_mpls_tunnel_switch_frr_entry_key_init(unit, tnl_info, &tnl_entry); 2032 BCM_IF_ERROR_RETURN(rv); 2033 2034 /* Delete tunnel terminator in TCAM. */ 2035 return soc_tunnel_term_delete(unit, &tnl_entry); 2036 } 2037 2038 2039 /* 2040 * Function: 2041 * _bcm_tr3_mpls_tunnel_switch_frr_get 2042 * Purpose: 2043 * Get MPLS Tunnel-switch entry for Fast Reroute 2044 * Parameters: 2045 * unit -(IN)SOC unit number. 2046 * tnl_info -(IN)Buffer to fill tunnel info. 2047 * Returns: 2048 * BCM_E_XXX 2049 */ 2050 int 2051 _bcm_tr3_mpls_tunnel_switch_frr_get(int unit, bcm_mpls_tunnel_switch_t *tnl_info, int *index) 2052 { 2053 soc_tunnel_term_t tnl_entry; 2054 soc_tunnel_term_t tnl_key; 2055 int rv = BCM_E_NONE; 2056 int entry_index; 2057 2058 sal_memset(&tnl_key, 0, sizeof(tnl_key)); 2059 sal_memset(&tnl_entry, 0, sizeof(tnl_entry)); 2060 2061 /* Setup TCAM key */ 2062 rv = _bcm_tr3_mpls_tunnel_switch_frr_entry_key_init(unit, tnl_info, &tnl_key); 2063 BCM_IF_ERROR_RETURN(rv); 2064 2065 /* Find tunnel terminator in TCAM. */ 2066 BCM_IF_ERROR_RETURN(soc_tunnel_term_match(unit, &tnl_key, &tnl_entry, &entry_index)); 2067 *index = entry_index; 2068 2069 /* Parse HW entry to User Information */ 2070 (void) _bcm_tr3_mpls_tunnel_switch_frr_parse(unit, &tnl_entry, tnl_info); 2071 return BCM_E_NONE; 2072 } 2073 2074 /* 2075 * Function: 2076 * bcm_mpls_tunnel_switch_add 2077 * Purpose: 2078 * Add an MPLS label entry. 2079 * Parameters: 2080 * unit - Device Number 2081 * info - Label (switch) information 2082 * Returns: 2083 * BCM_E_XXX 2084 */ 2085 int 2086 bcm_tr3_mpls_tunnel_switch_add(int unit, bcm_mpls_tunnel_switch_t *info) 2087 { 2088 int rv = BCM_E_NONE; 2089 mpls_entry_entry_t ment; 2090 mpls_entry_extd_entry_t ment_extd; 2091 int mode=0, nh_index = -1; 2092 int index, forwarding_field_type=-1, old_action = -1; 2093 int old_nh_index = -1, old_ecmp_index = -1; 2094 int tunnel_switch_update=-1; 2095 int ref_count=0, bud_node_trigger=0; 2096 bcm_if_t egress_if=0; 2097 uint8 key_type_1 = 0x10; 2098 uint8 key_type_2 = 0x12; 2099 soc_mem_t mem = MPLS_ENTRYm; 2100 void *entry_buffer = &ment; 2101 int v4_v6_override; 2102 2103 rv = bcm_xgs3_l3_egress_mode_get(unit, &mode); 2104 BCM_IF_ERROR_RETURN(rv); 2105 if (!mode) { 2106 LOG_INFO(BSL_LS_BCM_L3, 2107 (BSL_META_U(unit, 2108 "L3 egress mode must be set first\n"))); 2109 return BCM_E_DISABLED; 2110 } 2111 2112 /* Check for Port_independent Label mapping */ 2113 if (!BCM_XGS3_L3_MPLS_LBL_VALID(info->label)) { 2114 return BCM_E_PARAM; 2115 } 2116 2117 /* BCM_MPLS_SWITCH_KEEP_TTL flag will work only for swap action and 2118 * it is ineffective for other actions. 2119 */ 2120 if ((info->flags & BCM_MPLS_SWITCH_KEEP_TTL) && 2121 (info->action != BCM_MPLS_SWITCH_ACTION_SWAP)) { 2122 return BCM_E_PARAM; 2123 } 2124 2125 rv = bcm_tr_mpls_port_independent_range (unit, info->label, info->port); 2126 if (rv < 0) { 2127 return rv; 2128 } 2129 2130 sal_memset(&ment, 0, sizeof(mpls_entry_entry_t)); 2131 sal_memset(&ment_extd, 0, sizeof(mpls_entry_extd_entry_t)); 2132 2133 if (info->flags & BCM_MPLS_SWITCH_P2MP) { 2134 BCM_IF_ERROR_RETURN( 2135 _bcm_tr3_mpls_entry_set_key(unit, info, (uint32 *) &ment, MPLS_ENTRYm, key_type_1)); 2136 2137 /* See if entry already exists */ 2138 rv = soc_mem_search(unit, MPLS_ENTRYm, MEM_BLOCK_ANY, &index, 2139 &ment, &ment, 0); 2140 if (BCM_FAILURE(rv)) { 2141 BCM_IF_ERROR_RETURN( 2142 _bcm_tr3_mpls_entry_convert_to_extd_entry_key(unit, &ment, &ment_extd)); 2143 rv = soc_mem_search(unit, MPLS_ENTRY_EXTDm, MEM_BLOCK_ANY, &index, 2144 &ment_extd, &ment_extd, 0); 2145 if(rv == SOC_E_NONE) { 2146 mem = MPLS_ENTRY_EXTDm; 2147 entry_buffer = &ment_extd; 2148 } 2149 } else { 2150 mem = MPLS_ENTRYm; 2151 entry_buffer = &ment; 2152 } 2153 2154 if (rv == SOC_E_NONE) { 2155 /* Entry exists */ 2156 old_action = 2157 soc_mem_field32_get(unit, mem, entry_buffer, MPLS__MPLS_ACTION_IF_BOSf); 2158 if (old_action == 5) { /* SWAP_L3MC */ 2159 if (info->action == BCM_MPLS_SWITCH_ACTION_SWAP) { 2160 /* Update existing SWAP entry */ 2161 tunnel_switch_update = 1; 2162 } else if (info->action == BCM_MPLS_SWITCH_ACTION_POP) { 2163 /* Create New POP Entry */ 2164 tunnel_switch_update = 0; 2165 bud_node_trigger = 1; 2166 } 2167 } else if (old_action == 2) { /* POP L3_IIF */ 2168 if (info->action == BCM_MPLS_SWITCH_ACTION_SWAP) { 2169 /* Create New SWAP entry */ 2170 tunnel_switch_update = 0; 2171 bud_node_trigger = 1; 2172 } else if (info->action == BCM_MPLS_SWITCH_ACTION_POP) { 2173 /* Update POP Entry */ 2174 tunnel_switch_update = 1; 2175 } 2176 } 2177 2178 if ((soc_mem_field32_get(unit, mem, entry_buffer, MPLS__P2MP_LOCAL_RECEIVERS_PRESENTf)) && 2179 (info->action == BCM_MPLS_SWITCH_ACTION_POP)) { 2180 /* See if Second-pass BUD entry exists */ 2181 BCM_IF_ERROR_RETURN( 2182 _bcm_tr3_mpls_entry_set_key(unit, info, (uint32 *) &ment, MPLS_ENTRYm, key_type_2)); 2183 rv = soc_mem_search(unit, MPLS_ENTRYm, MEM_BLOCK_ANY, &index, 2184 &ment, &ment, 0); 2185 if (BCM_FAILURE(rv)) { 2186 BCM_IF_ERROR_RETURN( 2187 _bcm_tr3_mpls_entry_convert_to_extd_entry_key(unit, &ment, &ment_extd)); 2188 rv = soc_mem_search(unit, MPLS_ENTRY_EXTDm, MEM_BLOCK_ANY, &index, 2189 &ment_extd, &ment_extd, 0); 2190 if(rv == SOC_E_NONE) { 2191 mem = MPLS_ENTRY_EXTDm; 2192 entry_buffer = &ment_extd; 2193 } 2194 } else { 2195 mem = MPLS_ENTRYm; 2196 entry_buffer = &ment; 2197 } 2198 if (rv == SOC_E_NONE) { 2199 /* Entry exists */ 2200 old_action = 2201 soc_mem_field32_get(unit, mem, entry_buffer, MPLS__MPLS_ACTION_IF_BOSf); 2202 if (old_action == 2) { /* POP L3_IIF */ 2203 if (info->action == BCM_MPLS_SWITCH_ACTION_POP) { 2204 /* Update existing POP entry */ 2205 tunnel_switch_update = 1; 2206 bud_node_trigger = 0; 2207 } 2208 } 2209 } 2210 } 2211 } 2212 } else if (info->flags & BCM_MPLS_SWITCH_FRR) { 2213 rv = _bcm_tr3_mpls_tunnel_switch_frr_set(unit, info); 2214 return rv; 2215 } else { 2216 2217 BCM_IF_ERROR_RETURN( 2218 _bcm_tr3_mpls_entry_set_key(unit, info, (uint32 *)&ment, MPLS_ENTRYm, key_type_1)); 2219 2220 /* See if entry already exists */ 2221 rv = soc_mem_search(unit, MPLS_ENTRYm, MEM_BLOCK_ANY, &index, 2222 &ment, &ment, 0); 2223 if (BCM_FAILURE(rv)) { 2224 BCM_IF_ERROR_RETURN( 2225 _bcm_tr3_mpls_entry_convert_to_extd_entry_key(unit, &ment, &ment_extd)); 2226 rv = soc_mem_search(unit, MPLS_ENTRY_EXTDm, MEM_BLOCK_ANY, &index, 2227 &ment_extd, &ment_extd, 0); 2228 if(rv == SOC_E_NONE) { 2229 mem = MPLS_ENTRY_EXTDm; 2230 entry_buffer = &ment_extd; 2231 } 2232 } else { 2233 mem = MPLS_ENTRYm; 2234 entry_buffer = &ment; 2235 } 2236 2237 if (rv == SOC_E_NONE) { 2238 /* Entry exists */ 2239 tunnel_switch_update = 1; 2240 } 2241 } 2242 2243 2244 if (rv != BCM_E_NONE) { 2245 if (rv != SOC_E_NOT_FOUND) { 2246 return rv; 2247 } else if (rv == SOC_E_NOT_FOUND) { 2248 tunnel_switch_update = 0; 2249 } 2250 } else { 2251 if (tunnel_switch_update == -1) { 2252 return BCM_E_PARAM; 2253 } 2254 } 2255 2256 if (tunnel_switch_update == 1) { /* Update existing entry */ 2257 old_action = 2258 soc_mem_field32_get(unit, mem, entry_buffer, MPLS__MPLS_ACTION_IF_BOSf); 2259 switch (old_action) { 2260 case 3: /* SWAP_NHI */ 2261 case 6: /* PHP_NHI */ 2262 forwarding_field_type = _BCM_MPLS_FORWARD_NEXT_HOP; 2263 break; 2264 case 4: /* SWAP_ECMP */ 2265 case 7: /* PHP_ECMP */ 2266 forwarding_field_type = _BCM_MPLS_FORWARD_ECMP_GROUP; 2267 break; 2268 case 5: /* SWAP_L3MC_INDEX */ 2269 forwarding_field_type = _BCM_MPLS_FORWARD_MULTICAST_GROUP; 2270 break; 2271 default: 2272 break; 2273 } 2274 if (forwarding_field_type == _BCM_MPLS_FORWARD_NEXT_HOP) { 2275 old_nh_index = 2276 soc_mem_field32_get(unit, mem, entry_buffer, MPLS__NEXT_HOP_INDEXf); 2277 } else if (forwarding_field_type == _BCM_MPLS_FORWARD_ECMP_GROUP) { 2278 old_ecmp_index = 2279 soc_mem_field32_get(unit, mem, entry_buffer, MPLS__ECMP_PTRf); 2280 } else if (forwarding_field_type == _BCM_MPLS_FORWARD_MULTICAST_GROUP) { 2281 #if 0 2282 2283 int old_ipmc_index = 2284 soc_MPLS_ENTRYm_field32_get(unit, &ment, MPLS__L3MC_INDEXf); 2285 #endif 2286 } 2287 } 2288 2289 switch(info->action) { 2290 case BCM_MPLS_SWITCH_ACTION_SWAP: 2291 rv = _bcm_tr3_mpls_process_swap_label_action(unit, info, 2292 bud_node_trigger, &nh_index, &ment ); 2293 if (rv < 0) { 2294 goto cleanup; 2295 } 2296 break; 2297 2298 case BCM_MPLS_SWITCH_ACTION_POP: 2299 rv = _bcm_tr3_mpls_process_pop_label_action(unit, info, 2300 bud_node_trigger, old_action, &ment ); 2301 if (rv < 0) { 2302 goto cleanup; 2303 } 2304 break; 2305 2306 case BCM_MPLS_SWITCH_ACTION_PHP: 2307 rv = _bcm_tr3_mpls_process_php_label_action(unit, info, 2308 &nh_index, &ment ); 2309 if (rv < 0) { 2310 goto cleanup; 2311 } 2312 break; 2313 2314 default: 2315 return BCM_E_PARAM; 2316 break; 2317 } 2318 2319 v4_v6_override = soc_property_get(unit, spn_MPLS_SWITCH_IPV4_IPV6_INDEPENDENT_CONTROL, 0); 2320 if (!v4_v6_override) { 2321 soc_mem_field32_set(unit, mem, entry_buffer, MPLS__V4_ENABLEf, 1); 2322 soc_mem_field32_set(unit, mem, entry_buffer, MPLS__V6_ENABLEf, 1); 2323 } else { 2324 soc_mem_field32_set(unit, mem, entry_buffer, MPLS__V4_ENABLEf, 0); 2325 soc_mem_field32_set(unit, mem, entry_buffer, MPLS__V6_ENABLEf, 0); 2326 if (info->flags2 & BCM_MPLS_SWITCH2_ENABLE_IPV4) { 2327 soc_mem_field32_set(unit, mem, entry_buffer, MPLS__V4_ENABLEf, 1); 2328 } 2329 if (info->flags2 & BCM_MPLS_SWITCH2_ENABLE_IPV6) { 2330 soc_mem_field32_set(unit, mem, entry_buffer, MPLS__V6_ENABLEf, 1); 2331 } 2332 } 2333 if (info->flags & BCM_MPLS_SWITCH_INNER_TTL) { 2334 if (info->action == BCM_MPLS_SWITCH_ACTION_SWAP) { 2335 rv = BCM_E_PARAM; 2336 goto cleanup; 2337 } 2338 soc_mem_field32_set(unit, mem, entry_buffer, MPLS__DECAP_USE_TTLf, 0); 2339 } else { 2340 soc_mem_field32_set(unit, mem, entry_buffer, MPLS__DECAP_USE_TTLf, 1); 2341 } 2342 if (info->flags & BCM_MPLS_SWITCH_INNER_EXP) { 2343 if (info->action == BCM_MPLS_SWITCH_ACTION_SWAP) { 2344 rv = BCM_E_PARAM; 2345 goto cleanup; 2346 } 2347 soc_mem_field32_set(unit, mem, entry_buffer, MPLS__DECAP_USE_EXP_FOR_INNERf, 0); 2348 } else { 2349 /* For SWAP, Do-not PUSH EXP */ 2350 if (info->action == BCM_MPLS_SWITCH_ACTION_SWAP) { 2351 soc_mem_field32_set(unit, mem, entry_buffer, MPLS__DECAP_USE_EXP_FOR_INNERf, 0); 2352 } else { 2353 soc_mem_field32_set(unit, mem, entry_buffer, MPLS__DECAP_USE_EXP_FOR_INNERf, 1); 2354 } 2355 } 2356 if (info->flags & BCM_MPLS_SWITCH_DROP) { 2357 soc_mem_field32_set(unit, mem, entry_buffer, 2358 MPLS__DROP_DATA_ENABLEf, 1); 2359 } else { 2360 soc_mem_field32_set(unit, mem, entry_buffer, 2361 MPLS__DROP_DATA_ENABLEf, 0); 2362 } 2363 2364 (void) bcm_tr3_mpls_entry_internal_qos_set(unit, NULL, info, entry_buffer); 2365 2366 if ((!tunnel_switch_update) && (!bud_node_trigger)) { 2367 rv = soc_mem_insert(unit, mem, MEM_BLOCK_ALL, entry_buffer); 2368 } else { 2369 rv = soc_mem_write(unit, mem, 2370 MEM_BLOCK_ALL, index, entry_buffer); 2371 } 2372 2373 if (rv < 0) { 2374 goto cleanup; 2375 } 2376 2377 if ((tunnel_switch_update) && 2378 (forwarding_field_type != _BCM_MPLS_FORWARD_MULTICAST_GROUP)) { 2379 if (old_action == 0x3) { /* SWAP_NHI */ 2380 /* Check if tunnel_switch.egress_label mode is being used */ 2381 if (forwarding_field_type == _BCM_MPLS_FORWARD_NEXT_HOP) { 2382 rv = bcm_tr_mpls_get_vp_nh (unit, (bcm_if_t) old_nh_index, &egress_if); 2383 } 2384 if (rv == BCM_E_NONE) { 2385 if (forwarding_field_type == _BCM_MPLS_FORWARD_NEXT_HOP) { 2386 rv = bcm_tr_mpls_l3_nh_info_delete(unit, old_nh_index); 2387 } 2388 } else { 2389 /* Decrement next-hop Reference count */ 2390 if (forwarding_field_type == _BCM_MPLS_FORWARD_NEXT_HOP) { 2391 rv = bcm_xgs3_get_ref_count_from_nhi(unit, 0, &ref_count, old_nh_index); 2392 } 2393 } 2394 } else if (old_action == 0x6) {/* PHP_NHI */ 2395 if (forwarding_field_type == _BCM_MPLS_FORWARD_NEXT_HOP) { 2396 rv = bcm_xgs3_nh_del(unit, 0, old_nh_index); 2397 } 2398 } else if (old_action == 0x7) {/* PHP_ECMP */ 2399 if (forwarding_field_type == _BCM_MPLS_FORWARD_ECMP_GROUP) { 2400 rv = bcm_xgs3_ecmp_group_del(unit, old_ecmp_index, 0); 2401 } 2402 } 2403 } 2404 if (rv < 0) { 2405 goto cleanup; 2406 } 2407 2408 #ifdef BCM_WARM_BOOT_SUPPORT 2409 SOC_CONTROL_LOCK(unit); 2410 SOC_CONTROL(unit)->scache_dirty = 1; 2411 SOC_CONTROL_UNLOCK(unit); 2412 #endif 2413 2414 return rv; 2415 2416 cleanup: 2417 if (nh_index != -1) { 2418 if (info->action == BCM_MPLS_SWITCH_ACTION_SWAP) { 2419 if (BCM_XGS3_L3_MPLS_LBL_VALID(info->egress_label.label) || 2420 (info->action == BCM_MPLS_SWITCH_ACTION_PHP)) { 2421 (void) bcm_tr_mpls_l3_nh_info_delete(unit, nh_index); 2422 } 2423 } else if (info->action == BCM_MPLS_SWITCH_ACTION_PHP) { 2424 (void) bcm_xgs3_nh_del(unit, 0, nh_index); 2425 } 2426 } 2427 return rv; 2428 } 2429 2430 /* 2431 * Function: 2432 * bcm_tr3_mpls_tunnel_switch_delete 2433 * Purpose: 2434 * Delete an MPLS label entry. 2435 * Parameters: 2436 * unit - Device Number 2437 * info - Label (switch) information 2438 * Returns: 2439 * BCM_E_XXX 2440 */ 2441 int 2442 bcm_tr3_mpls_tunnel_switch_delete(int unit, bcm_mpls_tunnel_switch_t *info) 2443 { 2444 int index; 2445 uint32 hw_buf[SOC_MAX_MEM_FIELD_WORDS]; 2446 soc_mem_t hw_mem; 2447 int rv = BCM_E_NONE; 2448 2449 if (info->flags & BCM_MPLS_SWITCH_FRR) { 2450 rv = _bcm_tr3_mpls_tunnel_switch_frr_delete(unit, info); 2451 } else { 2452 /* Search for MPLS entry */ 2453 rv = _bcm_tr3_mpls_entry_find(unit, info, hw_buf, 2454 &hw_mem, &index); 2455 /* If Not found in both Memory, then return error */ 2456 if (BCM_FAILURE(rv)) { 2457 return (rv); 2458 } 2459 rv = _bcm_tr3_mpls_entry_delete(unit, hw_buf, hw_mem, info, index); 2460 } 2461 2462 #ifdef BCM_WARM_BOOT_SUPPORT 2463 SOC_CONTROL_LOCK(unit); 2464 SOC_CONTROL(unit)->scache_dirty = 1; 2465 SOC_CONTROL_UNLOCK(unit); 2466 #endif 2467 2468 return rv; 2469 } 2470 2471 /* 2472 * Function: 2473 * bcm_tr3_mpls_tunnel_switch_delete_all 2474 * Purpose: 2475 * Delete all MPLS label entries. 2476 * Parameters: 2477 * unit - Device Number 2478 * Returns: 2479 * BCM_E_XXX 2480 */ 2481 int 2482 bcm_tr3_mpls_tunnel_switch_delete_all(int unit) 2483 { 2484 int i, num_entries; 2485 uint32 hw_buf[SOC_MAX_MEM_FIELD_WORDS]; 2486 soc_mem_t hw_mem; 2487 bcm_mpls_tunnel_switch_t info; 2488 soc_tunnel_term_t tnl_entry; 2489 uint32 key_type=0; 2490 int rv = BCM_E_NONE; 2491 2492 2493 2494 hw_mem = MPLS_ENTRYm; 2495 num_entries = soc_mem_index_count(unit, hw_mem); 2496 for (i = 0; i < num_entries; i++) { 2497 sal_memset (hw_buf, 0, SOC_MAX_MEM_FIELD_WORDS * sizeof(uint32)); 2498 hw_mem = MPLS_ENTRYm; 2499 rv = READ_MPLS_ENTRYm(unit, MEM_BLOCK_ANY, i, hw_buf); 2500 if (rv < 0) { 2501 return rv; 2502 } 2503 key_type = soc_mem_field32_get(unit, hw_mem, hw_buf, KEY_TYPEf); 2504 if ((key_type == 0x11) || (key_type == 0x13)) { 2505 sal_memset (hw_buf, 0, SOC_MAX_MEM_FIELD_WORDS * sizeof(uint32)); 2506 hw_mem = MPLS_ENTRY_EXTDm; 2507 rv = READ_MPLS_ENTRY_EXTDm(unit, MEM_BLOCK_ANY, i/2, hw_buf); 2508 if (rv < 0) { 2509 return rv; 2510 } 2511 if (!soc_mem_field32_get(unit, hw_mem, hw_buf, VALID_0f)) { 2512 continue; 2513 } 2514 if (!soc_mem_field32_get(unit, hw_mem, hw_buf, VALID_1f)) { 2515 continue; 2516 } 2517 } else if ((key_type == 0x10) || (key_type == 0x12)) { 2518 if (!soc_mem_field32_get(unit, hw_mem, hw_buf, VALIDf)) { 2519 continue; 2520 } 2521 } else { 2522 continue; 2523 } 2524 2525 sal_memset(&info, 0, sizeof(bcm_mpls_tunnel_switch_t)); 2526 2527 if (soc_mem_field32_get(unit, hw_mem, hw_buf, 2528 MPLS__MPLS_ACTION_IF_BOSf) == 0x1) { 2529 /* L2_SVP */ 2530 continue; 2531 } 2532 rv = _bcm_tr3_mpls_entry_get_key(unit, hw_buf, hw_mem, &info); 2533 if (rv < 0) { 2534 return rv; 2535 } 2536 rv = _bcm_tr3_mpls_entry_get_data(unit, hw_buf, hw_mem, &info); 2537 if (rv < 0) { 2538 return rv; 2539 } 2540 rv = _bcm_tr3_mpls_entry_delete(unit, hw_buf, hw_mem, &info, i ); 2541 if (rv < 0) { 2542 return rv; 2543 } 2544 } 2545 2546 num_entries = soc_mem_index_count(unit, L3_TUNNELm); 2547 for (i = 0; i < num_entries; i++) { 2548 sal_memset(&tnl_entry, 0, sizeof(tnl_entry)); 2549 rv = READ_L3_TUNNELm(unit, MEM_BLOCK_ANY, i, (uint32 *)&tnl_entry.entry_arr[0]); 2550 if (rv < 0) { 2551 return rv; 2552 } 2553 if (!soc_L3_TUNNELm_field32_get(unit, &tnl_entry, VALIDf)) { 2554 continue; 2555 } 2556 if (0x2 != soc_L3_TUNNELm_field32_get(unit, &tnl_entry, KEY_TYPEf)) { 2557 continue; 2558 } 2559 2560 rv = soc_tunnel_term_delete(unit, &tnl_entry); 2561 if (rv < 0) { 2562 return rv; 2563 } 2564 2565 /*_soc_tunnel_term_slot_free() api moves last entry to 2566 *deleted entry position using _soc_tunnel_term_entry_shift(). 2567 *Therefore adding this index change to support delete all*/ 2568 i--; 2569 } 2570 2571 return BCM_E_NONE; 2572 } 2573 2574 /* 2575 * Function: 2576 * bcm_tr3_mpls_tunnel_switch_get 2577 * Purpose: 2578 * Get an MPLS label entry. 2579 * Parameters: 2580 * unit - Device Number 2581 * info - Label (switch) information 2582 * Returns: 2583 * BCM_E_XXX 2584 */ 2585 int 2586 bcm_tr3_mpls_tunnel_switch_get(int unit, bcm_mpls_tunnel_switch_t *info) 2587 { 2588 int index; 2589 uint32 hw_buf[SOC_MAX_MEM_FIELD_WORDS]; 2590 soc_mem_t hw_mem; 2591 int rv = BCM_E_NONE; 2592 2593 if (info->flags & BCM_MPLS_SWITCH_FRR) { 2594 rv = _bcm_tr3_mpls_tunnel_switch_frr_get(unit, info, &index); 2595 } else { 2596 /* Search for MPLS entry */ 2597 rv = _bcm_tr3_mpls_entry_find(unit, info, hw_buf, 2598 &hw_mem, &index); 2599 /* If Not found in both Memory, then return error */ 2600 if (BCM_FAILURE(rv)) { 2601 return (rv); 2602 } 2603 rv = _bcm_tr3_mpls_entry_get_data(unit, hw_buf, hw_mem, info); 2604 } 2605 return rv; 2606 } 2607 2608 /* 2609 * Function: 2610 * bcm_tr3_mpls_tunnel_switch_traverse 2611 * Purpose: 2612 * Traverse all valid MPLS label entries an call the 2613 * supplied callback routine. 2614 * Parameters: 2615 * unit - Device Number 2616 * cb - User callback function, called once per MPLS entry. 2617 * user_data - cookie 2618 * Returns: 2619 * BCM_E_XXX 2620 */ 2621 int 2622 bcm_tr3_mpls_tunnel_switch_traverse(int unit, 2623 bcm_mpls_tunnel_switch_traverse_cb cb, 2624 void *user_data) 2625 { 2626 int i, num_entries; 2627 uint32 hw_buf[SOC_MAX_MEM_FIELD_WORDS]; 2628 soc_mem_t hw_mem; 2629 bcm_mpls_tunnel_switch_t info; 2630 uint32 key_type=0; 2631 int rv = BCM_E_NONE; 2632 soc_tunnel_term_t tnl_entry; 2633 2634 2635 2636 2637 num_entries = soc_mem_index_count(unit, MPLS_ENTRYm); 2638 for (i = 0; i < num_entries; i++) { 2639 sal_memset (hw_buf, 0, SOC_MAX_MEM_FIELD_WORDS * sizeof(uint32)); 2640 hw_mem = MPLS_ENTRYm; 2641 rv = READ_MPLS_ENTRYm(unit, MEM_BLOCK_ANY, i, hw_buf); 2642 if (rv < 0) { 2643 return rv; 2644 } 2645 key_type = soc_mem_field32_get(unit, hw_mem, hw_buf, KEY_TYPEf); 2646 if ((key_type == 0x11) || (key_type == 0x13)) { 2647 sal_memset (hw_buf, 0, SOC_MAX_MEM_FIELD_WORDS * sizeof(uint32)); 2648 hw_mem = MPLS_ENTRY_EXTDm; 2649 rv = READ_MPLS_ENTRY_EXTDm(unit, MEM_BLOCK_ANY, i/2, hw_buf); 2650 if (rv < 0) { 2651 return rv; 2652 } 2653 if (!soc_mem_field32_get(unit, hw_mem, hw_buf, VALID_0f)) { 2654 continue; 2655 } 2656 if (!soc_mem_field32_get(unit, hw_mem, hw_buf, VALID_1f)) { 2657 continue; 2658 } 2659 } else if ((key_type == 0x10) || (key_type == 0x12)) { 2660 if (!soc_mem_field32_get(unit, hw_mem, hw_buf, VALIDf)) { 2661 continue; 2662 } 2663 } else { 2664 continue; 2665 } 2666 2667 if (soc_mem_field32_get(unit, hw_mem, hw_buf, 2668 MPLS__MPLS_ACTION_IF_BOSf) == 0x1) { 2669 /* L2_SVP */ 2670 continue; 2671 } 2672 sal_memset(&info, 0, sizeof(bcm_mpls_tunnel_switch_t)); 2673 rv = _bcm_tr3_mpls_entry_get_key(unit, hw_buf, hw_mem, &info); 2674 if (rv < 0) { 2675 return rv; 2676 } 2677 rv = _bcm_tr3_mpls_entry_get_data(unit, hw_buf, hw_mem, &info); 2678 if (rv < 0) { 2679 return rv; 2680 } 2681 rv = cb(unit, &info, user_data); 2682 #ifdef BCM_CB_ABORT_ON_ERR 2683 if (BCM_FAILURE(rv) && SOC_CB_ABORT_ON_ERR(unit)) { 2684 return rv; 2685 } 2686 #endif 2687 } 2688 2689 /* traverse L3_TUNNEL entries */ 2690 num_entries = soc_mem_index_count(unit, L3_TUNNELm); 2691 2692 for (i = 0; i < num_entries; i++) { 2693 2694 sal_memset(&tnl_entry, 0, sizeof(tnl_entry)); 2695 BCM_IF_ERROR_RETURN 2696 (READ_L3_TUNNELm(unit, MEM_BLOCK_ANY, i, (uint32 *)&tnl_entry.entry_arr[0])); 2697 2698 if (!soc_L3_TUNNELm_field32_get (unit, &tnl_entry, VALIDf)) { 2699 continue; 2700 } 2701 2702 /* Check for MPLS entry key */ 2703 key_type = soc_L3_TUNNELm_field32_get(unit, &tnl_entry, KEY_TYPEf); 2704 if (key_type != 0x2) { 2705 continue; 2706 } 2707 2708 sal_memset(&info, 0, sizeof(bcm_mpls_tunnel_switch_t)); 2709 rv = _bcm_tr3_mpls_tunnel_switch_frr_entry_key_get (unit, &tnl_entry, &info); 2710 if (rv < 0) { 2711 return rv; 2712 } 2713 2714 (void) _bcm_tr3_mpls_tunnel_switch_frr_parse(unit, &tnl_entry, &info); 2715 /* coverity[dead_error_begin] */ 2716 rv = cb(unit, &info, user_data); 2717 /* coverity[dead_error_begin] */ 2718 #ifdef BCM_CB_ABORT_ON_ERR 2719 if (BCM_FAILURE(rv) && SOC_CB_ABORT_ON_ERR(unit)) { 2720 return rv; 2721 } 2722 #endif 2723 } 2724 2725 return BCM_E_NONE; 2726 } 2727 2728 /* 2729 * Function: 2730 * _bcm_tr3_mpls_match_label_entry_update 2731 * Purpose: 2732 * Update Match MPLS Entry 2733 * Parameters: 2734 * IN : Unit 2735 * IN : mpls_entry 2736 * OUT : mpls_entry 2737 2738 */ 2739 2740 STATIC int 2741 _bcm_tr3_mpls_match_label_entry_update(int unit, bcm_mpls_port_t *mpls_port, 2742 mpls_entry_entry_t *ment, 2743 mpls_entry_entry_t *return_ment) 2744 { 2745 uint32 value, key_type; 2746 bcm_module_t mod_id; 2747 bcm_port_t port_id; 2748 bcm_trunk_t trunk_id; 2749 bcm_mpls_label_t match_label; 2750 2751 /* Check if Key_Type identical */ 2752 key_type = soc_MPLS_ENTRYm_field32_get (unit, ment, KEY_TYPEf); 2753 value = soc_MPLS_ENTRYm_field32_get (unit, return_ment, KEY_TYPEf); 2754 if (key_type != value) { 2755 return BCM_E_PARAM; 2756 } 2757 2758 value = soc_MPLS_ENTRYm_field32_get (unit, ment, MPLS__Tf); 2759 if (value) { 2760 soc_MPLS_ENTRYm_field32_set(unit, return_ment, MPLS__Tf, value); 2761 trunk_id = soc_MPLS_ENTRYm_field32_get (unit, ment, MPLS__TGIDf); 2762 soc_MPLS_ENTRYm_field32_set(unit, return_ment, MPLS__TGIDf, trunk_id); 2763 } else { 2764 mod_id = soc_MPLS_ENTRYm_field32_get (unit, ment, MPLS__MODULE_IDf); 2765 soc_MPLS_ENTRYm_field32_set(unit, return_ment, MPLS__MODULE_IDf, mod_id); 2766 port_id = soc_MPLS_ENTRYm_field32_get (unit, ment, MPLS__PORT_NUMf); 2767 soc_MPLS_ENTRYm_field32_set(unit, return_ment, MPLS__PORT_NUMf, port_id); 2768 } 2769 2770 match_label = soc_MPLS_ENTRYm_field32_get(unit, ment, MPLS__MPLS_LABELf); 2771 soc_MPLS_ENTRYm_field32_set(unit, return_ment, MPLS__MPLS_LABELf, match_label); 2772 soc_MPLS_ENTRYm_field32_set(unit, return_ment, VALIDf, 1); 2773 2774 value = soc_MPLS_ENTRYm_field32_get(unit, ment, MPLS__SOURCE_VPf); 2775 soc_MPLS_ENTRYm_field32_set(unit, return_ment, MPLS__SOURCE_VPf, value); 2776 soc_MPLS_ENTRYm_field32_set(unit, return_ment, MPLS__MPLS_ACTION_IF_BOSf, 0x1); /* L2 SVP */ 2777 value = soc_MPLS_ENTRYm_field32_get(unit, ment, MPLS__MPLS_ACTION_IF_NOT_BOSf); 2778 soc_MPLS_ENTRYm_field32_set(unit, return_ment, MPLS__MPLS_ACTION_IF_NOT_BOSf, value); 2779 value = soc_MPLS_ENTRYm_field32_get(unit, ment, MPLS__CW_CHECK_CTRLf); 2780 soc_MPLS_ENTRYm_field32_set(unit, return_ment, MPLS__CW_CHECK_CTRLf, value); 2781 value = soc_MPLS_ENTRYm_field32_get(unit, ment, MPLS__DECAP_USE_EXP_FOR_PRIf); 2782 soc_MPLS_ENTRYm_field32_set(unit, return_ment, MPLS__DECAP_USE_EXP_FOR_PRIf, 2783 value); 2784 value = soc_MPLS_ENTRYm_field32_get(unit, ment, MPLS__EXP_MAPPING_PTRf); 2785 soc_MPLS_ENTRYm_field32_set(unit, return_ment, MPLS__EXP_MAPPING_PTRf, value); 2786 value = soc_MPLS_ENTRYm_field32_get(unit, ment, MPLS__NEW_PRIf); 2787 soc_MPLS_ENTRYm_field32_set(unit, return_ment, MPLS__NEW_PRIf, value); 2788 if (soc_mem_field_valid(unit, MPLS_ENTRYm, MPLS__TRUST_OUTER_DOT1P_PTRf)) { 2789 value = soc_MPLS_ENTRYm_field32_get(unit, ment, MPLS__TRUST_OUTER_DOT1P_PTRf); 2790 soc_MPLS_ENTRYm_field32_set(unit, return_ment, MPLS__TRUST_OUTER_DOT1P_PTRf, 2791 value); 2792 } 2793 return BCM_E_NONE; 2794 } 2795 2796 2797 /* 2798 * Function: 2799 * _bcm_tr3_mpls_match_label_entry_set 2800 * Purpose: 2801 * Set MPLS Match Label Entry 2802 * Parameters: 2803 * IN : Unit 2804 * IN : mpls_port 2805 * IN : mpls_entry 2806 * Returns: 2807 * BCM_E_XXX 2808 */ 2809 2810 STATIC int 2811 _bcm_tr3_mpls_match_label_entry_set(int unit, bcm_mpls_port_t *mpls_port, mpls_entry_entry_t *ment) 2812 { 2813 mpls_entry_entry_t return_ment; 2814 int rv = BCM_E_UNAVAIL; 2815 int index; 2816 2817 rv = soc_mem_search(unit, MPLS_ENTRYm, MEM_BLOCK_ANY, &index, 2818 ment, &return_ment, 0); 2819 2820 if (rv == SOC_E_NONE) { 2821 BCM_IF_ERROR_RETURN( 2822 _bcm_tr3_mpls_match_label_entry_update (unit, mpls_port, ment, &return_ment)); 2823 rv = soc_mem_write(unit, MPLS_ENTRYm, 2824 MEM_BLOCK_ALL, index, 2825 &return_ment); 2826 } else if (rv != SOC_E_NOT_FOUND) { 2827 return rv; 2828 } else { 2829 rv = soc_mem_insert(unit, MPLS_ENTRYm, MEM_BLOCK_ALL, ment); 2830 } 2831 2832 return rv; 2833 } 2834 /* 2835 * Function: 2836 * _bcm_tr3_mpls_match_vlan_extd_entry_update 2837 * Purpose: 2838 * Update MPLS Match Vlan_xlate_extd Entry 2839 * Parameters: 2840 * IN : Unit 2841 * IN : vlan_xlate_extd_entry_t 2842 * OUT : vlan_xlate_extd_entry_t 2843 2844 */ 2845 2846 STATIC int 2847 _bcm_tr3_mpls_match_vlan_extd_entry_update(int unit, vlan_xlate_extd_entry_t *vent, 2848 vlan_xlate_extd_entry_t *return_ent) 2849 { 2850 uint32 vp, key_type, value; 2851 2852 2853 /* Check if Key_Type identical */ 2854 key_type = soc_VLAN_XLATE_EXTDm_field32_get (unit, vent, KEY_TYPE_0f); 2855 value = soc_VLAN_XLATE_EXTDm_field32_get (unit, return_ent, KEY_TYPE_0f); 2856 if (key_type != value) { 2857 return BCM_E_PARAM; 2858 } 2859 2860 /* Retain original Keys -- Update data only */ 2861 soc_VLAN_XLATE_EXTDm_field32_set(unit, return_ent, XLATE__MPLS_ACTIONf, 0x1); 2862 soc_VLAN_XLATE_EXTDm_field32_set(unit, return_ent, XLATE__DISABLE_VLAN_CHECKSf, 1); 2863 vp = soc_VLAN_XLATE_EXTDm_field32_get (unit, vent, XLATE__SOURCE_VPf); 2864 soc_VLAN_XLATE_EXTDm_field32_set(unit, return_ent, XLATE__SOURCE_VPf, vp); 2865 2866 return BCM_E_NONE; 2867 } 2868 2869 2870 /* 2871 * Function: 2872 * _bcm_tr3_mpls_match_vlan_extd_entry_set 2873 * Purpose: 2874 * Set MPLS Match Vlan Entry 2875 * Parameters: 2876 * IN : Unit 2877 * IN : mpls_port 2878 * IN : vlan_xlate_extd_entry_t 2879 * Returns: 2880 * BCM_E_XXX 2881 */ 2882 2883 STATIC int 2884 _bcm_tr3_mpls_match_vlan_extd_entry_set(int unit, bcm_mpls_port_t *mpls_port, vlan_xlate_extd_entry_t *vent) 2885 { 2886 vlan_xlate_extd_entry_t return_vent; 2887 int rv = BCM_E_UNAVAIL; 2888 int index; 2889 2890 rv = soc_mem_search(unit, VLAN_XLATE_EXTDm, MEM_BLOCK_ANY, &index, 2891 vent, &return_vent, 0); 2892 2893 if (rv == SOC_E_NONE) { 2894 BCM_IF_ERROR_RETURN( 2895 _bcm_tr3_mpls_match_vlan_extd_entry_update (unit, vent, &return_vent)); 2896 rv = soc_mem_write(unit, VLAN_XLATE_EXTDm, 2897 MEM_BLOCK_ALL, index, 2898 &return_vent); 2899 } else if (rv != SOC_E_NOT_FOUND) { 2900 return rv; 2901 } else { 2902 if (mpls_port->flags & BCM_MPLS_PORT_REPLACE) { 2903 return BCM_E_NOT_FOUND; 2904 } else { 2905 rv = soc_mem_insert(unit, VLAN_XLATE_EXTDm, MEM_BLOCK_ALL, vent); 2906 } 2907 } 2908 2909 return rv; 2910 } 2911 2912 /* 2913 * Function: 2914 * _bcm_tr3_mpls_extd_entry_update 2915 * Purpose: 2916 * Update extended MPLS entry 2917 * Parameters: 2918 * unit - (IN) Device Number 2919 * mpls_port - (IN) mpls port information 2920 * ment_extd - (IN) old extended MPLS entry 2921 * return_ment_extd - (IN) new extended MPLS entry 2922 * Returns: 2923 * BCM_E_XXX 2924 */ 2925 STATIC int 2926 _bcm_tr3_mpls_extd_entry_update(int unit, bcm_mpls_port_t *mpls_port, 2927 mpls_entry_extd_entry_t *ment_extd, 2928 mpls_entry_extd_entry_t *return_ment_extd) 2929 { 2930 uint32 value, key_type; 2931 bcm_module_t mod_id; 2932 bcm_port_t port_id; 2933 bcm_trunk_t trunk_id; 2934 bcm_mpls_label_t match_label; 2935 2936 /* Check if Key_Type identical */ 2937 key_type = soc_MPLS_ENTRY_EXTDm_field32_get (unit, ment_extd, KEY_TYPE_0f); 2938 value = soc_MPLS_ENTRY_EXTDm_field32_get (unit, return_ment_extd, KEY_TYPE_0f); 2939 if (key_type != value){ 2940 return BCM_E_PARAM; 2941 } 2942 2943 key_type = soc_MPLS_ENTRY_EXTDm_field32_get (unit, ment_extd, KEY_TYPE_1f); 2944 value = soc_MPLS_ENTRY_EXTDm_field32_get (unit, return_ment_extd, KEY_TYPE_1f); 2945 if (key_type != value){ 2946 return BCM_E_PARAM; 2947 } 2948 2949 value = soc_MPLS_ENTRY_EXTDm_field32_get (unit, ment_extd, MPLS__Tf); 2950 if (value) { 2951 soc_MPLS_ENTRY_EXTDm_field32_set(unit, return_ment_extd, MPLS__Tf, value); 2952 trunk_id = soc_MPLS_ENTRY_EXTDm_field32_get (unit, ment_extd, MPLS__TGIDf); 2953 soc_MPLS_ENTRY_EXTDm_field32_set(unit, return_ment_extd, MPLS__TGIDf, trunk_id); 2954 } else { 2955 mod_id = soc_MPLS_ENTRY_EXTDm_field32_get (unit, ment_extd, MPLS__MODULE_IDf); 2956 soc_MPLS_ENTRY_EXTDm_field32_set(unit, return_ment_extd, MPLS__MODULE_IDf, mod_id); 2957 port_id = soc_MPLS_ENTRY_EXTDm_field32_get (unit, ment_extd, MPLS__PORT_NUMf); 2958 soc_MPLS_ENTRY_EXTDm_field32_set(unit, return_ment_extd, MPLS__PORT_NUMf, port_id); 2959 } 2960 2961 match_label = soc_MPLS_ENTRY_EXTDm_field32_get(unit, ment_extd, MPLS__MPLS_LABELf); 2962 soc_MPLS_ENTRY_EXTDm_field32_set(unit, return_ment_extd, MPLS__MPLS_LABELf, match_label); 2963 soc_MPLS_ENTRY_EXTDm_field32_set(unit, return_ment_extd, VALIDf, 1); 2964 2965 value = soc_MPLS_ENTRY_EXTDm_field32_get(unit, ment_extd, MPLS__SOURCE_VPf); 2966 soc_MPLS_ENTRY_EXTDm_field32_set(unit, return_ment_extd, MPLS__SOURCE_VPf, value); 2967 soc_MPLS_ENTRY_EXTDm_field32_set(unit, return_ment_extd, MPLS__MPLS_ACTION_IF_BOSf, 0x1); /* L2 SVP */ 2968 2969 value = soc_MPLS_ENTRY_EXTDm_field32_get(unit, ment_extd, MPLS__MPLS_ACTION_IF_NOT_BOSf); 2970 soc_MPLS_ENTRY_EXTDm_field32_set(unit, return_ment_extd, MPLS__MPLS_ACTION_IF_NOT_BOSf, value); 2971 value = soc_MPLS_ENTRY_EXTDm_field32_get(unit, ment_extd, MPLS__CW_CHECK_CTRLf); 2972 soc_MPLS_ENTRY_EXTDm_field32_set(unit, return_ment_extd, MPLS__CW_CHECK_CTRLf, value); 2973 value = soc_MPLS_ENTRY_EXTDm_field32_get(unit, ment_extd, MPLS__DECAP_USE_EXP_FOR_PRIf); 2974 soc_MPLS_ENTRY_EXTDm_field32_set(unit, return_ment_extd, MPLS__DECAP_USE_EXP_FOR_PRIf, 2975 value); 2976 value = soc_MPLS_ENTRY_EXTDm_field32_get(unit, ment_extd, MPLS__EXP_MAPPING_PTRf); 2977 soc_MPLS_ENTRY_EXTDm_field32_set(unit, return_ment_extd, MPLS__EXP_MAPPING_PTRf, value); 2978 value = soc_MPLS_ENTRY_EXTDm_field32_get(unit, ment_extd, MPLS__NEW_PRIf); 2979 soc_MPLS_ENTRY_EXTDm_field32_set(unit, return_ment_extd, MPLS__NEW_PRIf, value); 2980 if (soc_mem_field_valid(unit, MPLS_ENTRY_EXTDm, MPLS__TRUST_OUTER_DOT1P_PTRf)) { 2981 value = soc_MPLS_ENTRY_EXTDm_field32_get(unit, ment_extd, MPLS__TRUST_OUTER_DOT1P_PTRf); 2982 soc_MPLS_ENTRY_EXTDm_field32_set(unit, return_ment_extd, MPLS__TRUST_OUTER_DOT1P_PTRf, 2983 value); 2984 } 2985 2986 return BCM_E_NONE; 2987 } 2988 2989 /* 2990 * Function: 2991 * _bcm_tr3_mpls_extd_entry_add 2992 * Purpose: 2993 * Write extended MPLS table entry 2994 * Parameters: 2995 * unit - (IN) Device Number 2996 * mpls_port - (IN) mpls port information 2997 * ment_extd - (IN) Extended MPLS table entry 2998 * Returns: 2999 * BCM_E_XXX 3000 */ 3001 STATIC int 3002 _bcm_tr3_mpls_extd_entry_add(int unit, bcm_mpls_port_t *mpls_port, 3003 mpls_entry_extd_entry_t *ment_extd) 3004 { 3005 mpls_entry_extd_entry_t return_ment; 3006 int rv = BCM_E_UNAVAIL; 3007 int index; 3008 3009 sal_memset(&return_ment, 0, sizeof(mpls_entry_extd_entry_t)); 3010 3011 rv = soc_mem_search(unit, MPLS_ENTRY_EXTDm, MEM_BLOCK_ANY, &index, 3012 ment_extd, &return_ment, 0); 3013 3014 if (rv == SOC_E_NONE) { 3015 BCM_IF_ERROR_RETURN( 3016 _bcm_tr3_mpls_extd_entry_update(unit, mpls_port, ment_extd, &return_ment)); 3017 rv = soc_mem_write(unit, MPLS_ENTRY_EXTDm, 3018 MEM_BLOCK_ALL, index, &return_ment); 3019 } else if (rv != SOC_E_NOT_FOUND) { 3020 return rv; 3021 } else { 3022 rv = soc_mem_insert(unit, MPLS_ENTRY_EXTDm, MEM_BLOCK_ALL, ment_extd); 3023 } 3024 3025 return rv; 3026 } 3027 3028 /* 3029 * Function: 3030 * _bcm_tr3_mpls_entry_convert_to_extd_entry_key 3031 * Purpose: 3032 * convert the key of regular source mpls tables 3033 * to the key of extended destination mpls table 3034 * Parameters: 3035 * unit - (IN) Device Number 3036 * mpls_entry_entry - (IN) Source table entry 3037 * mpls_entry_extd_entry - (OUT)Destination table entry 3038 * Returns: 3039 * BCM_E_XXX 3040 */ 3041 int 3042 _bcm_tr3_mpls_entry_convert_to_extd_entry_key( 3043 int unit, 3044 mpls_entry_entry_t *mpls_entry_entry, 3045 mpls_entry_extd_entry_t *mpls_entry_extd_entry) 3046 { 3047 uint32 value; 3048 3049 BCM_IF_ERROR_RETURN(_bcm_esw_mpls_entry_convert_to_extd_entry(unit, 3050 mpls_entry_entry, mpls_entry_extd_entry)); 3051 3052 value = soc_MPLS_ENTRYm_field32_get(unit, mpls_entry_entry, MPLS__MODULE_IDf); 3053 soc_MPLS_ENTRY_EXTDm_field32_set(unit, mpls_entry_extd_entry, MPLS__MODULE_IDf, value); 3054 3055 value = soc_MPLS_ENTRYm_field32_get(unit, mpls_entry_entry, MPLS__PORT_NUMf); 3056 soc_MPLS_ENTRY_EXTDm_field32_set(unit, mpls_entry_extd_entry, MPLS__PORT_NUMf, value); 3057 3058 value = soc_MPLS_ENTRYm_field32_get(unit, mpls_entry_entry, MPLS__Tf); 3059 soc_MPLS_ENTRY_EXTDm_field32_set(unit, mpls_entry_extd_entry, MPLS__Tf, value); 3060 3061 value = soc_MPLS_ENTRYm_field32_get(unit, mpls_entry_entry, MPLS__TGIDf); 3062 soc_MPLS_ENTRY_EXTDm_field32_set(unit, mpls_entry_extd_entry, MPLS__TGIDf, value); 3063 3064 value = soc_MPLS_ENTRYm_field32_get(unit, mpls_entry_entry, MPLS__MPLS_LABELf); 3065 soc_MPLS_ENTRY_EXTDm_field32_set(unit, mpls_entry_extd_entry, MPLS__MPLS_LABELf, value); 3066 3067 return BCM_E_NONE; 3068 } 3069 3070 /* 3071 * Function: 3072 * _bcm_esw_mpls_entry_convert_to_extd_entry_all 3073 * Description: 3074 * convert regular source mpls tables entry to extended destination mpls 3075 * table entry(MPLS_ENTRYm and MPLS_ENTRY_EXTDm) 3076 * 3077 * Parameters: 3078 * unit - (IN) unit number 3079 * ment - (IN) Source table entry 3080 * ment_extd - (OUT) Destination table entry 3081 * 3082 * Return Value: 3083 * BCM_E_XXX 3084 * Notes: 3085 */ 3086 STATIC int 3087 _bcm_esw_mpls_entry_convert_to_extd_entry_all( 3088 int unit, 3089 mpls_entry_entry_t *ment, 3090 mpls_entry_extd_entry_t *ment_extd) 3091 { 3092 uint32 value; 3093 3094 BCM_IF_ERROR_RETURN(_bcm_tr3_mpls_entry_convert_to_extd_entry_key(unit, 3095 ment, ment_extd)); 3096 3097 /* Take care about special fields */ 3098 value = soc_MPLS_ENTRYm_field32_get(unit, ment, MPLS__SOURCE_VPf); 3099 soc_MPLS_ENTRY_EXTDm_field32_set(unit, ment_extd, MPLS__SOURCE_VPf, value); 3100 3101 value = soc_MPLS_ENTRYm_field32_get(unit, ment, MPLS__CW_CHECK_CTRLf); 3102 soc_MPLS_ENTRY_EXTDm_field32_set(unit, ment_extd, MPLS__CW_CHECK_CTRLf, value); 3103 3104 value = soc_MPLS_ENTRYm_field32_get(unit, ment, MPLS__PW_CC_TYPEf); 3105 soc_MPLS_ENTRY_EXTDm_field32_set(unit, ment_extd, MPLS__PW_CC_TYPEf, value); 3106 3107 value = soc_MPLS_ENTRYm_field32_get(unit, ment, MPLS__MPLS_ACTION_IF_BOSf); 3108 soc_MPLS_ENTRY_EXTDm_field32_set(unit, ment_extd, MPLS__MPLS_ACTION_IF_BOSf, value); 3109 3110 value = soc_MPLS_ENTRYm_field32_get(unit, ment, MPLS__MPLS_ACTION_IF_NOT_BOSf); 3111 soc_MPLS_ENTRY_EXTDm_field32_set(unit, ment_extd, MPLS__MPLS_ACTION_IF_NOT_BOSf, value); 3112 3113 value = soc_MPLS_ENTRYm_field32_get(unit, ment, MPLS__DECAP_USE_EXP_FOR_PRIf); 3114 soc_MPLS_ENTRY_EXTDm_field32_set(unit, ment_extd, MPLS__DECAP_USE_EXP_FOR_PRIf, value); 3115 3116 value = soc_MPLS_ENTRYm_field32_get(unit, ment, MPLS__EXP_MAPPING_PTRf); 3117 soc_MPLS_ENTRY_EXTDm_field32_set(unit, ment_extd, MPLS__EXP_MAPPING_PTRf, value); 3118 3119 value = soc_MPLS_ENTRYm_field32_get(unit, ment, MPLS__NEW_PRIf); 3120 soc_MPLS_ENTRY_EXTDm_field32_set(unit, ment_extd, MPLS__NEW_PRIf, value); 3121 3122 if (soc_mem_field_valid(unit, MPLS_ENTRYm, MPLS__TRUST_OUTER_DOT1P_PTRf) && 3123 soc_mem_field_valid(unit, MPLS_ENTRY_EXTDm, MPLS__TRUST_OUTER_DOT1P_PTRf)) { 3124 value = soc_MPLS_ENTRY_EXTDm_field32_get(unit, ment, 3125 MPLS__TRUST_OUTER_DOT1P_PTRf); 3126 soc_MPLS_ENTRY_EXTDm_field32_set(unit, ment_extd, MPLS__TRUST_OUTER_DOT1P_PTRf, value); 3127 } 3128 3129 return BCM_E_NONE; 3130 } 3131 3132 /* 3133 * Function: 3134 * _bcm_tr3_mpls_extd_entry_set 3135 * Purpose: 3136 * Set MPLS extend entry 3137 * Parameters: 3138 * unit - (IN) Device Number 3139 * ment - (IN) MPLS entry 3140 * mpls_port - (IN) mpls port information 3141 * Returns: 3142 * BCM_E_XXX 3143 */ 3144 STATIC int 3145 _bcm_tr3_mpls_extd_entry_set(int unit, mpls_entry_entry_t *ment, bcm_mpls_port_t *mpls_port) 3146 { 3147 int new_pw_term_cntr_idx=-1; 3148 mpls_entry_extd_entry_t mpls_entry_extd_entry; 3149 3150 sal_memset(&mpls_entry_extd_entry, 0, sizeof(mpls_entry_extd_entry_t)); 3151 BCM_IF_ERROR_RETURN(_bcm_esw_mpls_entry_convert_to_extd_entry_all(unit, ment, &mpls_entry_extd_entry)); 3152 3153 BCM_IF_ERROR_RETURN(_bcm_tr_mpls_pw_term_counter_set(unit, &new_pw_term_cntr_idx)); 3154 if (new_pw_term_cntr_idx != -1) { 3155 soc_MPLS_ENTRY_EXTDm_field32_set(unit, &mpls_entry_extd_entry, MPLS__PW_TERM_NUMf, new_pw_term_cntr_idx); 3156 soc_MPLS_ENTRY_EXTDm_field32_set(unit, &mpls_entry_extd_entry, MPLS__PW_TERM_NUM_VALIDf, 1); 3157 } 3158 3159 return _bcm_tr3_mpls_extd_entry_add(unit, mpls_port, &mpls_entry_extd_entry); 3160 } 3161 3162 /* 3163 * Function: 3164 * _bcm_tr3_mpls_match_add 3165 * Purpose: 3166 * Assign match criteria of an MPLS port 3167 * Parameters: 3168 * unit - (IN) Device Number 3169 * mpls_port - (IN) mpls port information 3170 * vp - (IN) Source Virtual Port 3171 * Returns: 3172 * BCM_E_XXX 3173 */ 3174 3175 int 3176 _bcm_tr3_mpls_match_add(int unit, bcm_mpls_port_t *mpls_port, int vp, 3177 int hw_update) 3178 { 3179 _bcm_tr_mpls_bookkeeping_t *mpls_info = MPLS_INFO(unit); 3180 int rv = BCM_E_NONE, gport_id; 3181 bcm_module_t mod_out; 3182 bcm_port_t port_out; 3183 bcm_trunk_t trunk_id; 3184 vlan_xlate_extd_entry_t vent; 3185 int mod_id_idx=0; /* Module Id */ 3186 int src_trk_idx=0; /*Source Trunk table index.*/ 3187 uint32 key_type_1 = 0x10; /* MPLS_ENTRY Key Tyepe */ 3188 int vpless_failover_port = FALSE; 3189 int old_entry_found = BCM_E_NONE; 3190 if (_BCM_MPLS_GPORT_FAILOVER_VPLESS_GET(vp)) { 3191 if (mpls_port->criteria & BCM_MPLS_PORT_MATCH_LABEL) { 3192 /* should use same entry as primary */ 3193 return BCM_E_NONE; 3194 } 3195 vpless_failover_port = TRUE; 3196 vp = _BCM_MPLS_GPORT_FAILOVER_VPLESS_CLEAR(vp); 3197 } 3198 3199 sal_memset(&vent, 0, sizeof(vlan_xlate_extd_entry_t)); 3200 3201 if (mpls_port->criteria != BCM_MPLS_PORT_MATCH_LABEL) { 3202 rv = _bcm_esw_gport_resolve(unit, mpls_port->port, &mod_out, 3203 &port_out, &trunk_id, &gport_id); 3204 BCM_IF_ERROR_RETURN(rv); 3205 } 3206 3207 /* Get module id for unit. */ 3208 BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &mod_id_idx)); 3209 3210 if (mpls_port->criteria == BCM_MPLS_PORT_MATCH_PORT_VLAN ) { 3211 3212 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, VALID_0f, 1); 3213 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, VALID_1f, 1); 3214 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, XLATE__MPLS_ACTIONf, 0x1); /* SVP */ 3215 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, XLATE__DISABLE_VLAN_CHECKSf, 1); 3216 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, XLATE__SOURCE_VPf, vp); 3217 if (!BCM_VLAN_VALID(mpls_port->match_vlan)) { 3218 return BCM_E_PARAM; 3219 } 3220 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, KEY_TYPE_0f, 3221 TR3_VLXLT_X_HASH_KEY_TYPE_OVID); 3222 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, KEY_TYPE_1f, 3223 TR3_VLXLT_X_HASH_KEY_TYPE_OVID); 3224 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, OVIDf, 3225 mpls_port->match_vlan); 3226 mpls_info->match_key[vp].flags = _BCM_MPLS_PORT_MATCH_TYPE_VLAN; 3227 mpls_info->match_key[vp].match_vlan = mpls_port->match_vlan; 3228 3229 if (BCM_GPORT_IS_TRUNK(mpls_port->port)) { 3230 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, XLATE__Tf, 1); 3231 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, XLATE__TGIDf, trunk_id); 3232 mpls_info->match_key[vp].trunk_id = trunk_id; 3233 } else { 3234 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, XLATE__MODULE_IDf, mod_out); 3235 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, XLATE__PORT_NUMf, port_out); 3236 mpls_info->match_key[vp].port = port_out; 3237 mpls_info->match_key[vp].modid = mod_out; 3238 } 3239 rv = _bcm_tr3_mpls_match_vlan_extd_entry_set(unit, mpls_port, &vent); 3240 BCM_IF_ERROR_RETURN(rv); 3241 if (!(mpls_port->flags & BCM_MPLS_PORT_REPLACE)) { 3242 bcm_tr_mpls_port_match_count_adjust(unit, vp, 1); 3243 } 3244 } else if (mpls_port->criteria == 3245 BCM_MPLS_PORT_MATCH_PORT_INNER_VLAN) { 3246 3247 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, VALID_0f, 1); 3248 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, VALID_1f, 1); 3249 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, XLATE__MPLS_ACTIONf, 0x1); /* SVP */ 3250 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, XLATE__DISABLE_VLAN_CHECKSf, 1); 3251 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, XLATE__SOURCE_VPf, vp); 3252 if (!BCM_VLAN_VALID(mpls_port->match_inner_vlan)) { 3253 return BCM_E_PARAM; 3254 } 3255 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, KEY_TYPE_0f, 3256 TR3_VLXLT_X_HASH_KEY_TYPE_IVID); 3257 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, KEY_TYPE_1f, 3258 TR3_VLXLT_X_HASH_KEY_TYPE_IVID); 3259 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, XLATE__IVIDf, 3260 mpls_port->match_inner_vlan); 3261 mpls_info->match_key[vp].flags = _BCM_MPLS_PORT_MATCH_TYPE_INNER_VLAN; 3262 mpls_info->match_key[vp].match_inner_vlan = mpls_port->match_inner_vlan; 3263 3264 if (BCM_GPORT_IS_TRUNK(mpls_port->port)) { 3265 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, XLATE__Tf, 1); 3266 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, XLATE__TGIDf, trunk_id); 3267 mpls_info->match_key[vp].trunk_id = trunk_id; 3268 } else { 3269 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, XLATE__MODULE_IDf, mod_out); 3270 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, XLATE__PORT_NUMf, port_out); 3271 mpls_info->match_key[vp].port = port_out; 3272 mpls_info->match_key[vp].modid = mod_out; 3273 } 3274 rv = _bcm_tr3_mpls_match_vlan_extd_entry_set(unit, mpls_port, &vent); 3275 BCM_IF_ERROR_RETURN(rv); 3276 if (!(mpls_port->flags & BCM_MPLS_PORT_REPLACE)) { 3277 bcm_tr_mpls_port_match_count_adjust(unit, vp, 1); 3278 } 3279 } else if (mpls_port->criteria == 3280 BCM_MPLS_PORT_MATCH_PORT_VLAN_STACKED) { 3281 3282 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, VALID_0f, 1); 3283 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, VALID_1f, 1); 3284 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, XLATE__MPLS_ACTIONf, 0x1); /* SVP */ 3285 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, XLATE__DISABLE_VLAN_CHECKSf, 1); 3286 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, XLATE__SOURCE_VPf, vp); 3287 if (!BCM_VLAN_VALID(mpls_port->match_vlan) || 3288 !BCM_VLAN_VALID(mpls_port->match_inner_vlan)) { 3289 return BCM_E_PARAM; 3290 } 3291 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, KEY_TYPE_0f, 3292 TR3_VLXLT_X_HASH_KEY_TYPE_IVID_OVID); 3293 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, KEY_TYPE_1f, 3294 TR3_VLXLT_X_HASH_KEY_TYPE_IVID_OVID); 3295 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, XLATE__OVIDf, 3296 mpls_port->match_vlan); 3297 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, XLATE__IVIDf, 3298 mpls_port->match_inner_vlan); 3299 mpls_info->match_key[vp].flags = _BCM_MPLS_PORT_MATCH_TYPE_VLAN_STACKED; 3300 mpls_info->match_key[vp].match_vlan = mpls_port->match_vlan; 3301 mpls_info->match_key[vp].match_inner_vlan = mpls_port->match_inner_vlan; 3302 if (BCM_GPORT_IS_TRUNK(mpls_port->port)) { 3303 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, XLATE__Tf, 1); 3304 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, XLATE__TGIDf, trunk_id); 3305 mpls_info->match_key[vp].trunk_id = trunk_id; 3306 } else { 3307 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, XLATE__MODULE_IDf, mod_out); 3308 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, XLATE__PORT_NUMf, port_out); 3309 mpls_info->match_key[vp].port = port_out; 3310 mpls_info->match_key[vp].modid = mod_out; 3311 } 3312 rv = _bcm_tr3_mpls_match_vlan_extd_entry_set(unit, mpls_port, &vent); 3313 BCM_IF_ERROR_RETURN(rv); 3314 if (!(mpls_port->flags & BCM_MPLS_PORT_REPLACE)) { 3315 bcm_tr_mpls_port_match_count_adjust(unit, vp, 1); 3316 } 3317 } else if (mpls_port->criteria == 3318 BCM_MPLS_PORT_MATCH_VLAN_PRI) { 3319 3320 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, VALID_0f, 1); 3321 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, VALID_1f, 1); 3322 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, XLATE__MPLS_ACTIONf, 0x1); /* SVP */ 3323 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, XLATE__DISABLE_VLAN_CHECKSf, 1); 3324 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, XLATE__SOURCE_VPf, vp); 3325 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, KEY_TYPE_0f, 3326 TR3_VLXLT_X_HASH_KEY_TYPE_PRI_CFI); 3327 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, KEY_TYPE_1f, 3328 TR3_VLXLT_X_HASH_KEY_TYPE_PRI_CFI); 3329 /* match_vlan : Bits 12-15 contains VLAN_PRI + CFI, vlan=BCM_E_NONE */ 3330 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, OTAGf, 3331 mpls_port->match_vlan); 3332 mpls_info->match_key[vp].flags = _BCM_MPLS_PORT_MATCH_TYPE_VLAN_PRI; 3333 mpls_info->match_key[vp].match_vlan = mpls_port->match_vlan; 3334 3335 if (BCM_GPORT_IS_TRUNK(mpls_port->port)) { 3336 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, XLATE__Tf, 1); 3337 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, XLATE__TGIDf, trunk_id); 3338 mpls_info->match_key[vp].trunk_id = trunk_id; 3339 } else { 3340 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, XLATE__MODULE_IDf, mod_out); 3341 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, XLATE__PORT_NUMf, port_out); 3342 mpls_info->match_key[vp].port = port_out; 3343 mpls_info->match_key[vp].modid = mod_out; 3344 } 3345 rv = _bcm_tr3_mpls_match_vlan_extd_entry_set(unit, mpls_port, &vent); 3346 BCM_IF_ERROR_RETURN(rv); 3347 if (!(mpls_port->flags & BCM_MPLS_PORT_REPLACE)) { 3348 bcm_tr_mpls_port_match_count_adjust(unit, vp, 1); 3349 } 3350 } else if (mpls_port->criteria == BCM_MPLS_PORT_MATCH_PORT_VLAN_TAG) { 3351 3352 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, VALID_0f, 1); 3353 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, VALID_1f, 1); 3354 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, XLATE__MPLS_ACTIONf, 0x1); /* SVP */ 3355 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, XLATE__DISABLE_VLAN_CHECKSf, 1); 3356 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, XLATE__SOURCE_VPf, vp); 3357 3358 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, KEY_TYPE_0f, 3359 TR3_VLXLT_X_HASH_KEY_TYPE_OTAG); 3360 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, KEY_TYPE_1f, 3361 TR3_VLXLT_X_HASH_KEY_TYPE_OTAG); 3362 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, XLATE__OTAGf, 3363 mpls_port->match_vlan); 3364 mpls_info->match_key[vp].flags = _BCM_MPLS_PORT_MATCH_TYPE_VLAN_TAG; 3365 mpls_info->match_key[vp].match_vlan = mpls_port->match_vlan; 3366 3367 if (BCM_GPORT_IS_TRUNK(mpls_port->port)) { 3368 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, XLATE__Tf, 1); 3369 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, XLATE__TGIDf, trunk_id); 3370 mpls_info->match_key[vp].trunk_id = trunk_id; 3371 } else { 3372 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, XLATE__MODULE_IDf, mod_out); 3373 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, XLATE__PORT_NUMf, port_out); 3374 mpls_info->match_key[vp].port = port_out; 3375 mpls_info->match_key[vp].modid = mod_out; 3376 } 3377 rv = _bcm_tr3_mpls_match_vlan_extd_entry_set(unit, mpls_port, &vent); 3378 BCM_IF_ERROR_RETURN(rv); 3379 if (!(mpls_port->flags & BCM_MPLS_PORT_REPLACE)) { 3380 bcm_tr_mpls_port_match_count_adjust(unit, vp, 1); 3381 } 3382 3383 } else if (mpls_port->criteria == BCM_MPLS_PORT_MATCH_PORT_INNER_VLAN_TAG) { 3384 3385 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, VALID_0f, 1); 3386 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, VALID_1f, 1); 3387 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, XLATE__MPLS_ACTIONf, 0x1); /* SVP */ 3388 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, XLATE__DISABLE_VLAN_CHECKSf, 1); 3389 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, XLATE__SOURCE_VPf, vp); 3390 3391 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, KEY_TYPE_0f, 3392 TR3_VLXLT_X_HASH_KEY_TYPE_ITAG); 3393 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, KEY_TYPE_1f, 3394 TR3_VLXLT_X_HASH_KEY_TYPE_ITAG); 3395 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, XLATE__ITAGf, 3396 mpls_port->match_inner_vlan); 3397 mpls_info->match_key[vp].flags = _BCM_MPLS_PORT_MATCH_TYPE_INNER_VLAN_TAG; 3398 mpls_info->match_key[vp].match_inner_vlan = mpls_port->match_inner_vlan; 3399 3400 if (BCM_GPORT_IS_TRUNK(mpls_port->port)) { 3401 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, XLATE__Tf, 1); 3402 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, XLATE__TGIDf, trunk_id); 3403 mpls_info->match_key[vp].trunk_id = trunk_id; 3404 } else { 3405 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, XLATE__MODULE_IDf, mod_out); 3406 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, XLATE__PORT_NUMf, port_out); 3407 mpls_info->match_key[vp].port = port_out; 3408 mpls_info->match_key[vp].modid = mod_out; 3409 } 3410 rv = _bcm_tr3_mpls_match_vlan_extd_entry_set(unit, mpls_port, &vent); 3411 BCM_IF_ERROR_RETURN(rv); 3412 if (!(mpls_port->flags & BCM_MPLS_PORT_REPLACE)) { 3413 bcm_tr_mpls_port_match_count_adjust(unit, vp, 1); 3414 } 3415 3416 } else if (mpls_port->criteria == BCM_MPLS_PORT_MATCH_PORT) { 3417 if (BCM_GPORT_IS_TRUNK(mpls_port->port)) { 3418 rv = bcm_tr_mpls_match_trunk_add(unit, trunk_id, vp); 3419 if (rv >= 0) { 3420 mpls_info->match_key[vp].flags = _BCM_MPLS_PORT_MATCH_TYPE_TRUNK; 3421 mpls_info->match_key[vp].trunk_id = trunk_id; 3422 } 3423 BCM_IF_ERROR_RETURN(rv); 3424 } else { 3425 source_trunk_map_modbase_entry_t modbase_entry; 3426 int is_local; 3427 3428 BCM_IF_ERROR_RETURN 3429 ( _bcm_esw_modid_is_local(unit, mod_out, &is_local)); 3430 3431 if ((!is_local) && (mod_out != BCM_MODID_INVALID)) { 3432 mod_id_idx = mod_out; 3433 } 3434 3435 BCM_IF_ERROR_RETURN 3436 (soc_mem_read(unit, SOURCE_TRUNK_MAP_MODBASEm, MEM_BLOCK_ANY, 3437 mod_id_idx, &modbase_entry)); 3438 src_trk_idx = soc_mem_field32_get(unit, SOURCE_TRUNK_MAP_MODBASEm, 3439 &modbase_entry, BASEf) + port_out; 3440 rv = soc_mem_field32_modify(unit, SOURCE_TRUNK_MAP_TABLEm, 3441 src_trk_idx, SOURCE_VPf, vp); 3442 BCM_IF_ERROR_RETURN(rv); 3443 3444 if (is_local) { 3445 /* Convert system ports to physical ports */ 3446 if (soc_feature(unit, soc_feature_sysport_remap)) { 3447 BCM_XLATE_SYSPORT_S2P(unit, &port_out); 3448 } 3449 3450 rv = soc_mem_field32_modify(unit, PORT_TABm, port_out, 3451 PORT_OPERATIONf, 0x1); /* L2_SVP */ 3452 BCM_IF_ERROR_RETURN(rv); 3453 3454 /* Set TAG_ACTION_PROFILE_PTR */ 3455 rv = bcm_tr_mpls_port_untagged_profile_set(unit, port_out); 3456 BCM_IF_ERROR_RETURN(rv); 3457 } 3458 3459 mpls_info->match_key[vp].flags = _BCM_MPLS_PORT_MATCH_TYPE_PORT; 3460 mpls_info->match_key[vp].index = src_trk_idx; 3461 } 3462 }else if ((mpls_port->criteria == BCM_MPLS_PORT_MATCH_LABEL) || 3463 (mpls_port->criteria == BCM_MPLS_PORT_MATCH_LABEL_PORT)) { 3464 3465 mpls_entry_entry_t ment; 3466 bcm_mpls_label_t old_match_label; 3467 int entry_index=-1; 3468 soc_mem_t mem = MPLS_ENTRYm; 3469 uint32 hw_buf[SOC_MAX_MEM_FIELD_WORDS]; 3470 3471 sal_memset(&ment, 0, sizeof(mpls_entry_entry_t)); 3472 sal_memset (hw_buf, 0, SOC_MAX_MEM_FIELD_WORDS * sizeof(uint32)); 3473 3474 if (mpls_port->criteria == BCM_MPLS_PORT_MATCH_LABEL_PORT) { 3475 /* Check for Port_independent Label mapping */ 3476 rv = bcm_tr_mpls_port_independent_range (unit, mpls_port->match_label, mpls_port->port); 3477 if (rv < 0) { 3478 return rv; 3479 } 3480 if (BCM_GPORT_IS_TRUNK(mpls_port->port)) { 3481 soc_MPLS_ENTRYm_field32_set(unit, &ment, MPLS__Tf, 1); 3482 soc_MPLS_ENTRYm_field32_set(unit, &ment, MPLS__TGIDf, trunk_id); 3483 if (vpless_failover_port == FALSE) { 3484 mpls_info->match_key[vp].trunk_id = trunk_id; 3485 } else { 3486 mpls_info->match_key[vp].fo_trunk_id = trunk_id; 3487 } 3488 } else { 3489 soc_MPLS_ENTRYm_field32_set(unit, &ment, MPLS__MODULE_IDf, mod_out); 3490 soc_MPLS_ENTRYm_field32_set(unit, &ment, MPLS__PORT_NUMf, port_out); 3491 if (vpless_failover_port == FALSE) { 3492 mpls_info->match_key[vp].port = port_out; 3493 mpls_info->match_key[vp].modid = mod_out; 3494 } else { 3495 mpls_info->match_key[vp].fo_port = port_out; 3496 mpls_info->match_key[vp].fo_modid = mod_out; 3497 } 3498 } 3499 mpls_info->match_key[vp].flags = _BCM_MPLS_PORT_MATCH_TYPE_LABEL_PORT; 3500 3501 } else if (mpls_port->criteria == BCM_MPLS_PORT_MATCH_LABEL) { 3502 soc_MPLS_ENTRYm_field32_set(unit, &ment, MPLS__MODULE_IDf, 0); 3503 soc_MPLS_ENTRYm_field32_set(unit, &ment, MPLS__PORT_NUMf, 0); 3504 mpls_info->match_key[vp].port = 0; 3505 mpls_info->match_key[vp].modid = 0; 3506 mpls_info->match_key[vp].flags = _BCM_MPLS_PORT_MATCH_TYPE_LABEL; 3507 } 3508 3509 /* Use old label to get old mpls entry for replace operation */ 3510 old_match_label = mpls_info->match_key[vp].match_label; 3511 soc_MPLS_ENTRYm_field32_set(unit, &ment, MPLS__MPLS_LABELf, 3512 old_match_label); 3513 soc_MPLS_ENTRYm_field32_set(unit, &ment, VALIDf, 1); 3514 soc_MPLS_ENTRYm_field32_set(unit, &ment, MPLS__SOURCE_VPf, vp); 3515 soc_MPLS_ENTRYm_field32_set(unit, &ment, MPLS__MPLS_ACTION_IF_BOSf, 3516 0x1); /* L2 SVP */ 3517 if (SOC_IS_TRIUMPH3(unit)) { 3518 if (mpls_port->flags & BCM_MPLS_PORT2_WITH_LSP_OAM) { 3519 soc_MPLS_ENTRYm_field32_set(unit, &ment, MPLS__MPLS_ACTION_IF_NOT_BOSf, 3520 0x1); /* POP and forward based on the next label lookup */ 3521 } else { 3522 soc_MPLS_ENTRYm_field32_set(unit, &ment, MPLS__MPLS_ACTION_IF_NOT_BOSf, 3523 0x0); /* INVALID */ 3524 } 3525 } else { 3526 soc_MPLS_ENTRYm_field32_set(unit, &ment, MPLS__MPLS_ACTION_IF_NOT_BOSf, 3527 0x0); /* INVALID */ 3528 } 3529 soc_MPLS_ENTRYm_field32_set(unit, &ment, KEY_TYPEf, key_type_1); 3530 3531 if (mpls_port->flags & BCM_MPLS_PORT_REPLACE) { 3532 /* Find Entry within Hardware */ 3533 old_entry_found = soc_mem_search(unit, mem, MEM_BLOCK_ANY, &entry_index, 3534 &ment, hw_buf, 0); 3535 3536 if (old_entry_found == SOC_E_NOT_FOUND) { 3537 mpls_entry_extd_entry_t mpls_entry_extd_entry; 3538 3539 mem = MPLS_ENTRY_EXTDm; 3540 sal_memset(&mpls_entry_extd_entry, 0, sizeof(mpls_entry_extd_entry_t)); 3541 3542 BCM_IF_ERROR_RETURN(_bcm_tr3_mpls_entry_convert_to_extd_entry_key(unit, &ment, 3543 &mpls_entry_extd_entry)); 3544 old_entry_found = soc_mem_search(unit, mem, MEM_BLOCK_ANY, &entry_index, 3545 &mpls_entry_extd_entry, hw_buf, 0); 3546 } 3547 } 3548 3549 /* Add the new MPLS label for the new entry*/ 3550 soc_MPLS_ENTRYm_field32_set(unit, &ment, MPLS__MPLS_LABELf, 3551 mpls_port->match_label); 3552 3553 if (mpls_port->flags & BCM_MPLS_PORT_SEQUENCED) { 3554 /* Control word is present, check sequence number */ 3555 soc_MPLS_ENTRYm_field32_set(unit, &ment, MPLS__CW_CHECK_CTRLf, 3556 0x3); /* CW_CHECK_LOOSE */ 3557 3558 3559 } else if (mpls_port->flags & BCM_MPLS_PORT_CONTROL_WORD) { 3560 /* Control word is present, but no sequence number check */ 3561 soc_MPLS_ENTRYm_field32_set(unit, &ment, MPLS__CW_CHECK_CTRLf, 3562 0x1); /* CW_NO_CHECK */ 3563 } 3564 3565 /* VCCV defines 3 control-channels */ 3566 if (soc_mem_field_valid(unit, MPLS_ENTRYm, MPLS__PW_CC_TYPEf)) { 3567 soc_MPLS_ENTRYm_field32_set(unit, &ment, MPLS__PW_CC_TYPEf, 3568 mpls_port->vccv_type); 3569 } 3570 3571 (void) bcm_tr3_mpls_entry_internal_qos_set(unit, mpls_port, NULL, &ment); 3572 3573 if (soc_feature(unit, soc_feature_mpls_entropy)) { 3574 if ((mpls_port->flags & BCM_MPLS_PORT_ENTROPY_ENABLE) || 3575 (mpls_port->flags2 & BCM_MPLS_PORT2_INGRESS_ENTROPY_ENABLE)) { 3576 soc_MPLS_ENTRYm_field32_set(unit, &ment, MPLS__MPLS_ACTION_IF_BOSf, 3577 0x0); /* INVALID */ 3578 soc_MPLS_ENTRYm_field32_set(unit, &ment, MPLS__MPLS_ACTION_IF_NOT_BOSf, 3579 0x2); /* POP_SVP_ENTROPY */ 3580 } 3581 } 3582 3583 /* Add the new MPLS entry */ 3584 if (hw_update) { 3585 if (mpls_port->flags & BCM_MPLS_PORT_SEQUENCED) { 3586 rv = _bcm_tr3_mpls_extd_entry_set(unit, &ment, mpls_port); 3587 } else { 3588 rv = _bcm_tr3_mpls_match_label_entry_set(unit, mpls_port, &ment); 3589 } 3590 } 3591 3592 /* update the new label in match key of the VP*/ 3593 if (BCM_SUCCESS(rv)) { 3594 mpls_info->match_key[vp].match_label = mpls_port->match_label; 3595 } 3596 3597 /* Delete the old MPLS entry */ 3598 if (BCM_SUCCESS(rv) && (mpls_port->flags & BCM_MPLS_PORT_REPLACE)) { 3599 int failover_vp = -1; 3600 bcm_mpls_label_t failover_match_label = -1; 3601 3602 failover_vp = BCM_GPORT_MPLS_PORT_ID_GET(mpls_port->failover_port_id); 3603 if ((failover_vp >= 0) && 3604 _bcm_vp_used_get(unit, failover_vp, _bcmVpTypeMpls)) { 3605 failover_match_label = mpls_info->match_key[failover_vp].match_label; 3606 } 3607 3608 if ((old_entry_found == BCM_E_NONE) && 3609 (old_match_label != mpls_port->match_label)){ 3610 if ((failover_match_label != -1) && 3611 (old_match_label == failover_match_label)) { 3612 if (soc_mem_field_valid(unit, mem, MPLS__SOURCE_VPf)) { 3613 soc_mem_field32_set(unit, mem, hw_buf, MPLS__SOURCE_VPf, failover_vp); 3614 } 3615 BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, 3616 MEM_BLOCK_ALL, entry_index, 3617 hw_buf)); 3618 } else { 3619 BCM_IF_ERROR_RETURN(soc_mem_delete(unit, mem, 3620 MEM_BLOCK_ANY, hw_buf)); 3621 } 3622 } 3623 } 3624 } else if (mpls_port->criteria == BCM_MPLS_PORT_MATCH_NONE) { 3625 (void) bcm_tr_mpls_match_clear (unit, vp); 3626 mpls_info->match_key[vp].flags = _BCM_MPLS_PORT_MATCH_TYPE_NONE; 3627 if (!(mpls_port->flags & BCM_MPLS_PORT_REPLACE)) { 3628 bcm_tr_mpls_port_match_count_adjust(unit, vp, 1); 3629 } 3630 } 3631 3632 return rv; 3633 } 3634 3635 /* 3636 * Function: 3637 * _bcm_tr3_mpls_match_del 3638 * Purpose: 3639 * Delete match criteria of an MPLS port 3640 * Parameters: 3641 * unit - (IN) Device Number 3642 * vp - (IN) Source Virtual Port 3643 * Returns: 3644 * BCM_E_XXX 3645 */ 3646 3647 int 3648 _bcm_tr3_mpls_match_delete(int unit, int vp, int sw_clear) 3649 { 3650 _bcm_tr_mpls_bookkeeping_t *mpls_info = MPLS_INFO(unit); 3651 int rv=BCM_E_NONE; 3652 vlan_xlate_extd_entry_t vent; 3653 bcm_trunk_t trunk_id; 3654 int src_trk_idx=0; /*Source Trunk table index.*/ 3655 int mod_id_idx=0; /* Module_Id */ 3656 int port; 3657 uint32 key_type = 0x10; 3658 int vpless_failover_port = FALSE; 3659 3660 if (_BCM_MPLS_GPORT_FAILOVER_VPLESS_GET(vp)) { 3661 vp = _BCM_MPLS_GPORT_FAILOVER_VPLESS_CLEAR(vp); 3662 if (mpls_info->match_key[vp].flags & _BCM_MPLS_PORT_MATCH_TYPE_LABEL) { 3663 /* label entry belongs to primary port */ 3664 return BCM_E_NONE; 3665 } 3666 vpless_failover_port = TRUE; 3667 } 3668 sal_memset(&vent, 0, sizeof(vlan_xlate_extd_entry_t)); 3669 3670 3671 if (mpls_info->match_key[vp].flags == _BCM_MPLS_PORT_MATCH_TYPE_NONE) { 3672 (void) bcm_tr_mpls_match_clear (unit, vp); 3673 bcm_tr_mpls_port_match_count_adjust(unit, vp, -1); 3674 } else if (mpls_info->match_key[vp].flags == _BCM_MPLS_PORT_MATCH_TYPE_VLAN) { 3675 3676 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, VALID_0f, 1); 3677 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, VALID_1f, 1); 3678 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, KEY_TYPE_0f, 3679 TR3_VLXLT_X_HASH_KEY_TYPE_OVID); 3680 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, KEY_TYPE_1f, 3681 TR3_VLXLT_X_HASH_KEY_TYPE_OVID); 3682 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, XLATE__OVIDf, 3683 mpls_info->match_key[vp].match_vlan); 3684 if (mpls_info->match_key[vp].modid != -1) { 3685 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, XLATE__MODULE_IDf, 3686 mpls_info->match_key[vp].modid); 3687 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, XLATE__PORT_NUMf, 3688 mpls_info->match_key[vp].port); 3689 } else { 3690 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, XLATE__Tf, 1); 3691 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, XLATE__TGIDf, 3692 mpls_info->match_key[vp].trunk_id); 3693 } 3694 rv = soc_mem_delete(unit, VLAN_XLATE_EXTDm, MEM_BLOCK_ANY, &vent); 3695 BCM_IF_ERROR_RETURN(rv); 3696 3697 (void) bcm_tr_mpls_match_clear (unit, vp); 3698 bcm_tr_mpls_port_match_count_adjust(unit, vp, -1); 3699 3700 } else if (mpls_info->match_key[vp].flags == 3701 _BCM_MPLS_PORT_MATCH_TYPE_INNER_VLAN) { 3702 3703 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, VALID_0f, 1); 3704 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, VALID_1f, 1); 3705 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, KEY_TYPE_0f, 3706 TR3_VLXLT_X_HASH_KEY_TYPE_IVID); 3707 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, KEY_TYPE_1f, 3708 TR3_VLXLT_X_HASH_KEY_TYPE_IVID); 3709 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, XLATE__IVIDf, 3710 mpls_info->match_key[vp].match_inner_vlan); 3711 if (mpls_info->match_key[vp].modid != -1) { 3712 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, XLATE__MODULE_IDf, 3713 mpls_info->match_key[vp].modid); 3714 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, XLATE__PORT_NUMf, 3715 mpls_info->match_key[vp].port); 3716 } else { 3717 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, XLATE__Tf, 1); 3718 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, XLATE__TGIDf, 3719 mpls_info->match_key[vp].trunk_id); 3720 } 3721 rv = soc_mem_delete(unit, VLAN_XLATE_EXTDm, MEM_BLOCK_ANY, &vent); 3722 BCM_IF_ERROR_RETURN(rv); 3723 3724 (void) bcm_tr_mpls_match_clear (unit, vp); 3725 bcm_tr_mpls_port_match_count_adjust(unit, vp, -1); 3726 }else if (mpls_info->match_key[vp].flags == 3727 _BCM_MPLS_PORT_MATCH_TYPE_VLAN_STACKED) { 3728 3729 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, VALID_0f, 1); 3730 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, VALID_1f, 1); 3731 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, KEY_TYPE_0f, 3732 TR3_VLXLT_X_HASH_KEY_TYPE_IVID_OVID); 3733 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, KEY_TYPE_1f, 3734 TR3_VLXLT_X_HASH_KEY_TYPE_IVID_OVID); 3735 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, XLATE__OVIDf, 3736 mpls_info->match_key[vp].match_vlan); 3737 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, XLATE__IVIDf, 3738 mpls_info->match_key[vp].match_inner_vlan); 3739 if (mpls_info->match_key[vp].modid != -1) { 3740 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, XLATE__MODULE_IDf, 3741 mpls_info->match_key[vp].modid); 3742 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, XLATE__PORT_NUMf, 3743 mpls_info->match_key[vp].port); 3744 } else { 3745 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, XLATE__Tf, 1); 3746 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, XLATE__TGIDf, 3747 mpls_info->match_key[vp].trunk_id); 3748 } 3749 rv = soc_mem_delete(unit, VLAN_XLATE_EXTDm, MEM_BLOCK_ANY, &vent); 3750 BCM_IF_ERROR_RETURN(rv); 3751 3752 (void) bcm_tr_mpls_match_clear (unit, vp); 3753 bcm_tr_mpls_port_match_count_adjust(unit, vp, -1); 3754 3755 } else if (mpls_info->match_key[vp].flags == 3756 _BCM_MPLS_PORT_MATCH_TYPE_VLAN_PRI) { 3757 3758 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, VALID_0f, 1); 3759 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, VALID_1f, 1); 3760 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, KEY_TYPE_0f, 3761 TR3_VLXLT_X_HASH_KEY_TYPE_PRI_CFI); 3762 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, KEY_TYPE_1f, 3763 TR3_VLXLT_X_HASH_KEY_TYPE_PRI_CFI); 3764 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, XLATE__OTAGf, 3765 mpls_info->match_key[vp].match_vlan); 3766 if (mpls_info->match_key[vp].modid != -1) { 3767 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, XLATE__MODULE_IDf, 3768 mpls_info->match_key[vp].modid); 3769 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, XLATE__PORT_NUMf, 3770 mpls_info->match_key[vp].port); 3771 } else { 3772 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, XLATE__Tf, 1); 3773 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, XLATE__TGIDf, 3774 mpls_info->match_key[vp].trunk_id); 3775 } 3776 rv = soc_mem_delete(unit, VLAN_XLATE_EXTDm, MEM_BLOCK_ANY, &vent); 3777 BCM_IF_ERROR_RETURN(rv); 3778 3779 (void) bcm_tr_mpls_match_clear (unit, vp); 3780 bcm_tr_mpls_port_match_count_adjust(unit, vp, -1); 3781 } else if (mpls_info->match_key[vp].flags == 3782 _BCM_MPLS_PORT_MATCH_TYPE_VLAN_TAG) { 3783 3784 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, VALID_0f, 1); 3785 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, VALID_1f, 1); 3786 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, KEY_TYPE_0f, 3787 TR3_VLXLT_X_HASH_KEY_TYPE_OTAG); 3788 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, KEY_TYPE_1f, 3789 TR3_VLXLT_X_HASH_KEY_TYPE_OTAG); 3790 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, XLATE__OTAGf, 3791 mpls_info->match_key[vp].match_vlan); 3792 if (mpls_info->match_key[vp].modid != -1) { 3793 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, XLATE__MODULE_IDf, 3794 mpls_info->match_key[vp].modid); 3795 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, XLATE__PORT_NUMf, 3796 mpls_info->match_key[vp].port); 3797 } else { 3798 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, XLATE__Tf, 1); 3799 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, XLATE__TGIDf, 3800 mpls_info->match_key[vp].trunk_id); 3801 } 3802 rv = soc_mem_delete(unit, VLAN_XLATE_EXTDm, MEM_BLOCK_ANY, &vent); 3803 BCM_IF_ERROR_RETURN(rv); 3804 3805 (void) bcm_tr_mpls_match_clear (unit, vp); 3806 bcm_tr_mpls_port_match_count_adjust(unit, vp, -1); 3807 3808 } else if (mpls_info->match_key[vp].flags == 3809 _BCM_MPLS_PORT_MATCH_TYPE_INNER_VLAN_TAG) { 3810 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, VALID_0f, 1); 3811 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, VALID_1f, 1); 3812 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, KEY_TYPE_0f, 3813 TR3_VLXLT_X_HASH_KEY_TYPE_ITAG); 3814 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, KEY_TYPE_1f, 3815 TR3_VLXLT_X_HASH_KEY_TYPE_ITAG); 3816 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, XLATE__ITAGf, 3817 mpls_info->match_key[vp].match_inner_vlan); 3818 if (mpls_info->match_key[vp].modid != -1) { 3819 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, XLATE__MODULE_IDf, 3820 mpls_info->match_key[vp].modid); 3821 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, XLATE__PORT_NUMf, 3822 mpls_info->match_key[vp].port); 3823 } else { 3824 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, XLATE__Tf, 1); 3825 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, XLATE__TGIDf, 3826 mpls_info->match_key[vp].trunk_id); 3827 } 3828 rv = soc_mem_delete(unit, VLAN_XLATE_EXTDm, MEM_BLOCK_ANY, &vent); 3829 BCM_IF_ERROR_RETURN(rv); 3830 3831 (void) bcm_tr_mpls_match_clear (unit, vp); 3832 bcm_tr_mpls_port_match_count_adjust(unit, vp, -1); 3833 3834 } else if (mpls_info->match_key[vp].flags == 3835 _BCM_MPLS_PORT_MATCH_TYPE_PORT) { 3836 int is_local; 3837 3838 src_trk_idx = mpls_info->match_key[vp].index; 3839 rv = soc_mem_field32_modify(unit, SOURCE_TRUNK_MAP_TABLEm, 3840 src_trk_idx, SOURCE_VPf, 0); 3841 BCM_IF_ERROR_RETURN(rv); 3842 3843 BCM_IF_ERROR_RETURN(_bcm_esw_src_modid_port_get( unit, src_trk_idx, 3844 &mod_id_idx, &port)); 3845 BCM_IF_ERROR_RETURN 3846 ( _bcm_esw_modid_is_local(unit, mod_id_idx, &is_local)); 3847 3848 if (is_local) { 3849 rv = soc_mem_field32_modify(unit, PORT_TABm, port, 3850 PORT_OPERATIONf, 0x0); /* NORMAL */ 3851 BCM_IF_ERROR_RETURN(rv); 3852 3853 /* Reset TAG_ACTION_PROFILE_PTR */ 3854 rv = bcm_tr_mpls_port_untagged_profile_reset(unit, port); 3855 BCM_IF_ERROR_RETURN(rv); 3856 } 3857 } else if (mpls_info->match_key[vp].flags == 3858 _BCM_MPLS_PORT_MATCH_TYPE_TRUNK) { 3859 trunk_id = mpls_info->match_key[vp].trunk_id; 3860 rv = bcm_tr_mpls_match_trunk_delete(unit, trunk_id, vp); 3861 BCM_IF_ERROR_RETURN(rv); 3862 3863 (void) bcm_tr_mpls_match_clear (unit, vp); 3864 }else if ((mpls_info->match_key[vp].flags & 3865 _BCM_MPLS_PORT_MATCH_TYPE_LABEL) || 3866 (mpls_info->match_key[vp].flags == 3867 _BCM_MPLS_PORT_MATCH_TYPE_LABEL_PORT)) { 3868 mpls_entry_entry_t ment; 3869 soc_mem_t mem = MPLS_ENTRYm; 3870 uint32 hw_buf[SOC_MAX_MEM_FIELD_WORDS]; 3871 3872 sal_memset(&ment, 0, sizeof(mpls_entry_entry_t)); 3873 sal_memset (hw_buf, 0, SOC_MAX_MEM_FIELD_WORDS * sizeof(uint32)); 3874 3875 if (vpless_failover_port) { 3876 if (mpls_info->match_key[vp].fo_modid != -1) { 3877 soc_MPLS_ENTRYm_field32_set(unit, &ment, MPLS__MODULE_IDf, 3878 mpls_info->match_key[vp].fo_modid); 3879 soc_MPLS_ENTRYm_field32_set(unit, &ment, MPLS__PORT_NUMf, 3880 mpls_info->match_key[vp].fo_port); 3881 } else { 3882 soc_MPLS_ENTRYm_field32_set(unit, &ment, MPLS__Tf, 1); 3883 soc_MPLS_ENTRYm_field32_set(unit, &ment, MPLS__TGIDf, 3884 mpls_info->match_key[vp].fo_trunk_id); 3885 } 3886 } else { 3887 if (mpls_info->match_key[vp].modid != -1) { 3888 soc_MPLS_ENTRYm_field32_set(unit, &ment, MPLS__MODULE_IDf, 3889 mpls_info->match_key[vp].modid); 3890 soc_MPLS_ENTRYm_field32_set(unit, &ment, MPLS__PORT_NUMf, 3891 mpls_info->match_key[vp].port); 3892 } else { 3893 soc_MPLS_ENTRYm_field32_set(unit, &ment, MPLS__Tf, 1); 3894 soc_MPLS_ENTRYm_field32_set(unit, &ment, MPLS__TGIDf, 3895 mpls_info->match_key[vp].trunk_id); 3896 } 3897 } 3898 soc_MPLS_ENTRYm_field32_set(unit, &ment, MPLS__MPLS_LABELf, 3899 mpls_info->match_key[vp].match_label); 3900 soc_MPLS_ENTRYm_field32_set(unit, &ment, KEY_TYPEf, key_type); 3901 3902 rv = soc_mem_search(unit, mem, MEM_BLOCK_ANY, &src_trk_idx, 3903 &ment, hw_buf, 0); 3904 3905 if (rv == SOC_E_NOT_FOUND) { 3906 mpls_entry_extd_entry_t ment_extd; 3907 3908 mem = MPLS_ENTRY_EXTDm; 3909 sal_memset(&ment_extd, 0, sizeof(mpls_entry_extd_entry_t)); 3910 BCM_IF_ERROR_RETURN(_bcm_tr3_mpls_entry_convert_to_extd_entry_key(unit, 3911 &ment, &ment_extd)); 3912 rv = soc_mem_search(unit, mem, MEM_BLOCK_ANY, 3913 &src_trk_idx, &ment_extd, hw_buf, 0); 3914 } 3915 3916 if (rv == SOC_E_NONE) { 3917 rv = soc_mem_delete(unit, mem, MEM_BLOCK_ANY, hw_buf); 3918 BCM_IF_ERROR_RETURN(rv); 3919 if (sw_clear) { 3920 if (vpless_failover_port) { 3921 mpls_info->match_key[vp].fo_trunk_id = -1; 3922 mpls_info->match_key[vp].fo_port = 0; 3923 mpls_info->match_key[vp].fo_modid = -1; 3924 } else { 3925 if (mpls_info->match_key[vp].flags & 3926 _BCM_MPLS_PORT_MATCH_TYPE_NONE) { 3927 bcm_tr_mpls_port_match_count_adjust(unit, vp, -1); 3928 } 3929 (void) bcm_tr_mpls_match_clear (unit, vp); 3930 } 3931 } 3932 } 3933 } 3934 return rv; 3935 } 3936 3937 /* 3938 * Function: 3939 * _bcm_tr3_mpls_match_failover_update 3940 * Purpose: 3941 * Search mpls entry with provided source vp 3942 * and replace with failover vp 3943 * Parameters: 3944 * unit - (IN) Device Number 3945 * vp - (IN) Source Virtual Port 3946 * fo_vp - (IN) Failover Virtual Port 3947 * Returns: 3948 * BCM_E_XXX 3949 */ 3950 3951 int 3952 _bcm_tr3_mpls_match_failover_update(int unit, int vp, int fo_vp) 3953 { 3954 _bcm_tr_mpls_bookkeeping_t *mpls_info = MPLS_INFO(unit); 3955 int rv = BCM_E_NONE; 3956 uint32 key_type = 0x0; 3957 int vpless_failover_port = FALSE; 3958 mpls_entry_entry_t mpls_hw_entry = {{0}}; 3959 int m_index = -1; 3960 3961 /* For TR3 MPLS Key Type = 0x10, for Metrolite its 0x0 */ 3962 if (SOC_IS_TRIUMPH3(unit)) { 3963 key_type = 0x10; 3964 } 3965 if (_BCM_MPLS_GPORT_FAILOVER_VPLESS_GET(vp)) { 3966 vpless_failover_port = TRUE; 3967 } 3968 3969 if ((mpls_info->match_key[vp].flags == 3970 _BCM_MPLS_PORT_MATCH_TYPE_LABEL) || 3971 (mpls_info->match_key[vp].flags == 3972 _BCM_MPLS_PORT_MATCH_TYPE_LABEL_PORT)) { 3973 mpls_entry_entry_t ment; 3974 soc_mem_t mem = MPLS_ENTRYm; 3975 uint32 hw_buf[SOC_MAX_MEM_FIELD_WORDS]; 3976 3977 sal_memset(&ment, 0, sizeof(mpls_entry_entry_t)); 3978 sal_memset (hw_buf, 0, SOC_MAX_MEM_FIELD_WORDS * sizeof(uint32)); 3979 3980 if (vpless_failover_port) { 3981 if (mpls_info->match_key[vp].fo_modid != -1) { 3982 soc_MPLS_ENTRYm_field32_set(unit, &ment, MPLS__MODULE_IDf, 3983 mpls_info->match_key[vp].fo_modid); 3984 soc_MPLS_ENTRYm_field32_set(unit, &ment, MPLS__PORT_NUMf, 3985 mpls_info->match_key[vp].fo_port); 3986 } else { 3987 soc_MPLS_ENTRYm_field32_set(unit, &ment, MPLS__Tf, 1); 3988 soc_MPLS_ENTRYm_field32_set(unit, &ment, MPLS__TGIDf, 3989 mpls_info->match_key[vp].fo_trunk_id); 3990 } 3991 } else { 3992 if (mpls_info->match_key[vp].modid != -1) { 3993 soc_MPLS_ENTRYm_field32_set(unit, &ment, MPLS__MODULE_IDf, 3994 mpls_info->match_key[vp].modid); 3995 soc_MPLS_ENTRYm_field32_set(unit, &ment, MPLS__PORT_NUMf, 3996 mpls_info->match_key[vp].port); 3997 } else { 3998 soc_MPLS_ENTRYm_field32_set(unit, &ment, MPLS__Tf, 1); 3999 soc_MPLS_ENTRYm_field32_set(unit, &ment, MPLS__TGIDf, 4000 mpls_info->match_key[vp].trunk_id); 4001 } 4002 } 4003 soc_MPLS_ENTRYm_field32_set(unit, &ment, MPLS__MPLS_LABELf, 4004 mpls_info->match_key[vp].match_label); 4005 soc_MPLS_ENTRYm_field32_set(unit, &ment, KEY_TYPEf, key_type); 4006 4007 rv = soc_mem_search(unit, mem, MEM_BLOCK_ANY, &m_index, 4008 &ment, hw_buf, 0); 4009 } 4010 4011 /* If mpls entry found, update with failover vp */ 4012 if (BCM_SUCCESS(rv) && m_index != -1) { 4013 rv = soc_mem_read(unit, MPLS_ENTRYm, MEM_BLOCK_ANY, m_index, 4014 (void *)&mpls_hw_entry); 4015 soc_MPLS_ENTRYm_field32_set(unit, &mpls_hw_entry, MPLS__SOURCE_VPf, fo_vp); 4016 rv = soc_mem_write(unit, MPLS_ENTRYm, MEM_BLOCK_ALL, m_index, 4017 (void *)&mpls_hw_entry);; 4018 } 4019 4020 return rv; 4021 } 4022 4023 /* 4024 * Function: 4025 * _bcm_tr3_mpls_failover_nw_port_match_get 4026 * Purpose: 4027 * Get match criteria of an MPLS port 4028 * Parameters: 4029 * unit - (IN) Device Number 4030 * mpls_port - (IN) mpls port information 4031 * vp - (IN) Source Virtual Port 4032 * return_ment - (OUT) matched entry 4033 * Returns: 4034 * BCM_E_XXX 4035 */ 4036 int 4037 _bcm_tr3_mpls_failover_nw_port_match_get(int unit, bcm_mpls_port_t *mpls_port, 4038 int vp, mpls_entry_entry_t *return_ment) 4039 { 4040 4041 _bcm_tr_mpls_bookkeeping_t *mpls_info = MPLS_INFO(unit); 4042 mpls_entry_entry_t ment; 4043 int entry_index = -1; 4044 int key_type = 0x10; /* mpls_key_type */ 4045 int rv = BCM_E_NONE; 4046 bcm_module_t mod_out; 4047 bcm_port_t port_out; 4048 bcm_trunk_t trunk_id; 4049 bcm_gport_t gport_id; 4050 4051 /* return not found if both inputs are invalid. */ 4052 if ((mpls_port == NULL) && (vp == -1)) { 4053 return BCM_E_NOT_FOUND; 4054 } 4055 4056 sal_memset(&ment, 0, sizeof(mpls_entry_entry_t)); 4057 if (mpls_port != NULL) { 4058 if (mpls_port->criteria == BCM_MPLS_PORT_MATCH_LABEL_PORT) { 4059 /* Check for Port_independent Label mapping */ 4060 rv = bcm_tr_mpls_port_independent_range (unit, mpls_port->match_label, mpls_port->port); 4061 if (rv < 0) { 4062 return rv; 4063 } 4064 4065 rv = _bcm_esw_gport_resolve(unit, mpls_port->port, &mod_out, 4066 &port_out, &trunk_id, &gport_id); 4067 BCM_IF_ERROR_RETURN(rv); 4068 4069 if (BCM_GPORT_IS_TRUNK(mpls_port->port)) { 4070 soc_MPLS_ENTRYm_field32_set(unit, &ment, MPLS__Tf, 1); 4071 soc_MPLS_ENTRYm_field32_set(unit, &ment, MPLS__TGIDf, mpls_port->port); 4072 } else { 4073 soc_MPLS_ENTRYm_field32_set(unit, &ment, MPLS__MODULE_IDf, mod_out); 4074 soc_MPLS_ENTRYm_field32_set(unit, &ment, MPLS__PORT_NUMf, port_out); 4075 } 4076 4077 } else if (mpls_port->criteria == BCM_MPLS_PORT_MATCH_LABEL) { 4078 soc_MPLS_ENTRYm_field32_set(unit, &ment, MPLS__MODULE_IDf, 0); 4079 soc_MPLS_ENTRYm_field32_set(unit, &ment, MPLS__PORT_NUMf, 0); 4080 } else { 4081 return BCM_E_NOT_FOUND; 4082 } 4083 4084 /* Use old label to get old mpls entry for replace operation */ 4085 soc_MPLS_ENTRYm_field32_set(unit, &ment, MPLS__MPLS_LABELf, 4086 mpls_port->match_label); 4087 soc_MPLS_ENTRYm_field32_set(unit, &ment, VALIDf, 1); 4088 soc_MPLS_ENTRYm_field32_set(unit, &ment, MPLS__MPLS_ACTION_IF_BOSf, 4089 0x1); /* L2 SVP */ 4090 soc_MPLS_ENTRYm_field32_set(unit, &ment, MPLS__MPLS_ACTION_IF_NOT_BOSf, 4091 0x0); /* INVALID */ 4092 soc_MPLS_ENTRYm_field32_set(unit, &ment, KEY_TYPEf, key_type); 4093 } else { 4094 4095 if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeMpls)) { 4096 return BCM_E_NOT_FOUND; 4097 } 4098 4099 if ((mpls_info->match_key[vp].flags & 4100 _BCM_MPLS_PORT_MATCH_TYPE_LABEL) || 4101 (mpls_info->match_key[vp].flags == 4102 _BCM_MPLS_PORT_MATCH_TYPE_LABEL_PORT)) { 4103 4104 if (mpls_info->match_key[vp].flags & 4105 _BCM_MPLS_PORT_MATCH_TYPE_LABEL_PORT) { 4106 4107 if (mpls_info->match_key[vp].trunk_id != -1) { 4108 soc_MPLS_ENTRYm_field32_set(unit, &ment, MPLS__Tf, 1); 4109 soc_MPLS_ENTRYm_field32_set(unit, &ment, MPLS__TGIDf, 4110 mpls_info->match_key[vp].trunk_id); 4111 } else { 4112 soc_MPLS_ENTRYm_field32_set(unit, &ment, MPLS__MODULE_IDf, 4113 mpls_info->match_key[vp].modid); 4114 soc_MPLS_ENTRYm_field32_set(unit, &ment, MPLS__PORT_NUMf, 4115 mpls_info->match_key[vp].port); 4116 } 4117 } 4118 4119 soc_MPLS_ENTRYm_field32_set(unit, &ment, MPLS__MPLS_LABELf, 4120 mpls_info->match_key[vp].match_label); 4121 soc_MPLS_ENTRYm_field32_set(unit, &ment, KEY_TYPEf, key_type); 4122 4123 } else { 4124 return BCM_E_NOT_FOUND; 4125 } 4126 } 4127 4128 rv = soc_mem_search(unit, MPLS_ENTRYm, MEM_BLOCK_ANY, &entry_index, 4129 &ment, return_ment, 0); 4130 4131 return rv; 4132 } 4133 4134 /* 4135 * Function: 4136 * _bcm_tr3_mpls_match_get 4137 * Purpose: 4138 * Get match criteria of an MPLS port 4139 * Parameters: 4140 * unit - (IN) Device Number 4141 * mpls_port - (OUT) mpls port information 4142 * vp - (IN) Source Virtual Port 4143 * Returns: 4144 * BCM_E_XXX 4145 */ 4146 4147 int 4148 _bcm_tr3_mpls_match_get(int unit, bcm_mpls_port_t *mpls_port, int vp) 4149 { 4150 _bcm_tr_mpls_bookkeeping_t *mpls_info = MPLS_INFO(unit); 4151 int rv = BCM_E_NONE; 4152 bcm_module_t mod_in=0, mod_out; 4153 bcm_port_t port_in=0, port_out; 4154 bcm_trunk_t trunk_id=0; 4155 int src_trk_idx=0; /*Source Trunk table index.*/ 4156 int mode_in=0; /* Module_Id */ 4157 uint32 key_type = 0x10; 4158 int vpless_failover_port = FALSE; /* the failover port without a dedicated vp */ 4159 int match_trunk_id; 4160 int match_modid; 4161 int match_port; 4162 4163 if (_BCM_MPLS_GPORT_FAILOVER_VPLESS_GET(vp)) { 4164 4165 vp = _BCM_MPLS_GPORT_FAILOVER_VPLESS_CLEAR(vp); 4166 if (!(mpls_info->match_key[vp].flags & _BCM_MPLS_PORT_MATCH_TYPE_LABEL)) { 4167 vpless_failover_port = TRUE; 4168 } 4169 } 4170 4171 if (vpless_failover_port == FALSE) { 4172 match_trunk_id = mpls_info->match_key[vp].trunk_id; 4173 match_modid = mpls_info->match_key[vp].modid; 4174 match_port = mpls_info->match_key[vp].port; 4175 } else { 4176 match_trunk_id = mpls_info->match_key[vp].fo_trunk_id; 4177 match_modid = mpls_info->match_key[vp].fo_modid; 4178 match_port = mpls_info->match_key[vp].fo_port; 4179 } 4180 4181 /* Get module id for unit. */ 4182 BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &mode_in)); 4183 4184 if (mpls_info->match_key[vp].flags & _BCM_MPLS_PORT_MATCH_TYPE_VLAN) { 4185 4186 mpls_port->criteria = BCM_MPLS_PORT_MATCH_PORT_VLAN; 4187 mpls_port->match_vlan = mpls_info->match_key[vp].match_vlan; 4188 4189 if (mpls_info->match_key[vp].trunk_id != -1) { 4190 trunk_id = mpls_info->match_key[vp].trunk_id; 4191 BCM_GPORT_TRUNK_SET(mpls_port->port, trunk_id); 4192 } else { 4193 port_in = mpls_info->match_key[vp].port; 4194 mod_in = mpls_info->match_key[vp].modid; 4195 rv = _bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET, 4196 mod_in, port_in, &mod_out, &port_out); 4197 BCM_GPORT_MODPORT_SET(mpls_port->port, mod_out, port_out); 4198 } 4199 } else if (mpls_info->match_key[vp].flags & 4200 _BCM_MPLS_PORT_MATCH_TYPE_INNER_VLAN) { 4201 mpls_port->criteria = BCM_MPLS_PORT_MATCH_PORT_INNER_VLAN; 4202 mpls_port->match_inner_vlan = mpls_info->match_key[vp].match_inner_vlan; 4203 4204 if (mpls_info->match_key[vp].trunk_id != -1) { 4205 trunk_id = mpls_info->match_key[vp].trunk_id; 4206 BCM_GPORT_TRUNK_SET(mpls_port->port, trunk_id); 4207 } else { 4208 port_in = mpls_info->match_key[vp].port; 4209 mod_in = mpls_info->match_key[vp].modid; 4210 rv = _bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET, 4211 mod_in, port_in, &mod_out, &port_out); 4212 BCM_GPORT_MODPORT_SET(mpls_port->port, mod_out, port_out); 4213 } 4214 }else if (mpls_info->match_key[vp].flags & 4215 _BCM_MPLS_PORT_MATCH_TYPE_VLAN_STACKED) { 4216 4217 mpls_port->criteria = BCM_MPLS_PORT_MATCH_PORT_VLAN_STACKED; 4218 mpls_port->match_vlan = mpls_info->match_key[vp].match_vlan; 4219 mpls_port->match_inner_vlan = mpls_info->match_key[vp].match_inner_vlan; 4220 4221 if (mpls_info->match_key[vp].trunk_id != -1) { 4222 trunk_id = mpls_info->match_key[vp].trunk_id; 4223 BCM_GPORT_TRUNK_SET(mpls_port->port, trunk_id); 4224 } else { 4225 port_in = mpls_info->match_key[vp].port; 4226 mod_in = mpls_info->match_key[vp].modid; 4227 rv = _bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET, 4228 mod_in, port_in, &mod_out, &port_out); 4229 BCM_GPORT_MODPORT_SET(mpls_port->port, mod_out, port_out); 4230 } 4231 } else if (mpls_info->match_key[vp].flags & _BCM_MPLS_PORT_MATCH_TYPE_VLAN_PRI) { 4232 4233 mpls_port->criteria = BCM_MPLS_PORT_MATCH_VLAN_PRI; 4234 mpls_port->match_vlan = mpls_info->match_key[vp].match_vlan; 4235 4236 if (mpls_info->match_key[vp].trunk_id != -1) { 4237 trunk_id = mpls_info->match_key[vp].trunk_id; 4238 BCM_GPORT_TRUNK_SET(mpls_port->port, trunk_id); 4239 } else { 4240 port_in = mpls_info->match_key[vp].port; 4241 mod_in = mpls_info->match_key[vp].modid; 4242 rv = _bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET, 4243 mod_in, port_in, &mod_out, &port_out); 4244 BCM_GPORT_MODPORT_SET(mpls_port->port, mod_out, port_out); 4245 } 4246 } else if (mpls_info->match_key[vp].flags & 4247 _BCM_MPLS_PORT_MATCH_TYPE_VLAN_TAG) { 4248 4249 mpls_port->criteria = BCM_MPLS_PORT_MATCH_PORT_VLAN_TAG; 4250 mpls_port->match_vlan = mpls_info->match_key[vp].match_vlan; 4251 4252 if (mpls_info->match_key[vp].trunk_id != -1) { 4253 trunk_id = mpls_info->match_key[vp].trunk_id; 4254 BCM_GPORT_TRUNK_SET(mpls_port->port, trunk_id); 4255 } else { 4256 port_in = mpls_info->match_key[vp].port; 4257 mod_in = mpls_info->match_key[vp].modid; 4258 rv = _bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET, 4259 mod_in, port_in, &mod_out, &port_out); 4260 BCM_GPORT_MODPORT_SET(mpls_port->port, mod_out, port_out); 4261 } 4262 4263 } else if (mpls_info->match_key[vp].flags & 4264 _BCM_MPLS_PORT_MATCH_TYPE_INNER_VLAN_TAG) { 4265 4266 mpls_port->criteria = BCM_MPLS_PORT_MATCH_PORT_INNER_VLAN_TAG; 4267 mpls_port->match_inner_vlan = mpls_info->match_key[vp].match_inner_vlan; 4268 4269 if (mpls_info->match_key[vp].trunk_id != -1) { 4270 trunk_id = mpls_info->match_key[vp].trunk_id; 4271 BCM_GPORT_TRUNK_SET(mpls_port->port, trunk_id); 4272 } else { 4273 port_in = mpls_info->match_key[vp].port; 4274 mod_in = mpls_info->match_key[vp].modid; 4275 rv = _bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET, 4276 mod_in, port_in, &mod_out, &port_out); 4277 BCM_GPORT_MODPORT_SET(mpls_port->port, mod_out, port_out); 4278 } 4279 4280 } else if (mpls_info->match_key[vp].flags & 4281 _BCM_MPLS_PORT_MATCH_TYPE_PORT) { 4282 source_trunk_map_modbase_entry_t modbase_entry; 4283 4284 src_trk_idx = mpls_info->match_key[vp].index; 4285 4286 BCM_IF_ERROR_RETURN 4287 (soc_mem_read(unit, SOURCE_TRUNK_MAP_MODBASEm, 4288 MEM_BLOCK_ANY, mode_in, &modbase_entry)); 4289 port_in = src_trk_idx - soc_mem_field32_get(unit, 4290 SOURCE_TRUNK_MAP_MODBASEm, 4291 &modbase_entry, BASEf); 4292 4293 mpls_port->criteria = BCM_MPLS_PORT_MATCH_PORT; 4294 rv = _bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET, 4295 mod_in, port_in, &mod_out, &port_out); 4296 BCM_GPORT_MODPORT_SET(mpls_port->port, mod_out, port_out); 4297 }else if (mpls_info->match_key[vp].flags & 4298 _BCM_MPLS_PORT_MATCH_TYPE_TRUNK) { 4299 4300 trunk_id = mpls_info->match_key[vp].trunk_id; 4301 mpls_port->criteria = BCM_MPLS_PORT_MATCH_PORT; 4302 BCM_GPORT_TRUNK_SET(mpls_port->port, trunk_id); 4303 } else if ((mpls_info->match_key[vp].flags & 4304 _BCM_MPLS_PORT_MATCH_TYPE_LABEL) || 4305 (mpls_info->match_key[vp].flags == 4306 _BCM_MPLS_PORT_MATCH_TYPE_LABEL_PORT)) { 4307 mpls_entry_entry_t ment; 4308 soc_mem_t mem = MPLS_ENTRYm; 4309 uint32 hw_buf[SOC_MAX_MEM_FIELD_WORDS]; 4310 4311 sal_memset(&ment, 0, sizeof(mpls_entry_entry_t)); 4312 sal_memset (hw_buf, 0, SOC_MAX_MEM_FIELD_WORDS * sizeof(uint32)); 4313 4314 if (mpls_info->match_key[vp].flags & _BCM_MPLS_PORT_MATCH_TYPE_LABEL) { 4315 mpls_port->criteria = BCM_MPLS_PORT_MATCH_LABEL; 4316 } else if (mpls_info->match_key[vp].flags & 4317 _BCM_MPLS_PORT_MATCH_TYPE_LABEL_PORT) { 4318 mpls_port->criteria = BCM_MPLS_PORT_MATCH_LABEL_PORT; 4319 } 4320 mpls_port->match_label = mpls_info->match_key[vp].match_label; 4321 4322 if (match_trunk_id != -1) { 4323 trunk_id = match_trunk_id; 4324 soc_MPLS_ENTRYm_field32_set(unit, &ment, MPLS__Tf, 1); 4325 soc_MPLS_ENTRYm_field32_set(unit, &ment, MPLS__TGIDf, trunk_id); 4326 BCM_GPORT_TRUNK_SET(mpls_port->port, trunk_id); 4327 } else { 4328 mod_in = match_modid; 4329 port_in = match_port; 4330 soc_MPLS_ENTRYm_field32_set(unit, &ment, MPLS__MODULE_IDf, mod_in); 4331 soc_MPLS_ENTRYm_field32_set(unit, &ment, MPLS__PORT_NUMf, port_in); 4332 4333 rv = _bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET, 4334 mod_in, port_in, &mod_out, &port_out); 4335 if (rv < 0) { 4336 return rv; 4337 } 4338 BCM_GPORT_MODPORT_SET(mpls_port->port, mod_out, port_out); 4339 } 4340 soc_MPLS_ENTRYm_field32_set(unit, &ment, MPLS__MPLS_LABELf, 4341 mpls_info->match_key[vp].match_label); 4342 soc_MPLS_ENTRYm_field32_set(unit, &ment, KEY_TYPEf, key_type); 4343 4344 rv = soc_mem_search(unit, MPLS_ENTRYm, MEM_BLOCK_ANY, &src_trk_idx, 4345 &ment, hw_buf, 0); 4346 4347 if (rv == SOC_E_NOT_FOUND) { 4348 mpls_entry_extd_entry_t ment_extd; 4349 4350 mem = MPLS_ENTRY_EXTDm; 4351 sal_memset(&ment_extd, 0, sizeof(mpls_entry_extd_entry_t)); 4352 BCM_IF_ERROR_RETURN(_bcm_tr3_mpls_entry_convert_to_extd_entry_key(unit, 4353 &ment, &ment_extd)); 4354 rv = soc_mem_search(unit, mem, MEM_BLOCK_ANY, 4355 &src_trk_idx, &ment_extd, hw_buf, 0); 4356 } 4357 4358 if (rv == SOC_E_NONE) { 4359 if (soc_mem_field32_get(unit, mem, hw_buf, 4360 MPLS__CW_CHECK_CTRLf) == 0x3) { 4361 4362 /* Control word is present, and check sequence number */ 4363 mpls_port->flags |= BCM_MPLS_PORT_SEQUENCED; 4364 } else if (soc_mem_field32_get(unit, mem, hw_buf, 4365 MPLS__CW_CHECK_CTRLf) == 0x1) { 4366 mpls_port->flags |= BCM_MPLS_PORT_CONTROL_WORD; 4367 } 4368 4369 /* VCCV defines 3 control-channels */ 4370 if (soc_mem_field_valid(unit, mem, MPLS__PW_CC_TYPEf)) { 4371 mpls_port->vccv_type = soc_mem_field32_get(unit, mem, 4372 hw_buf, MPLS__PW_CC_TYPEf); 4373 } 4374 if (SOC_IS_TRIUMPH3(unit)) { 4375 if (soc_mem_field32_get(unit, mem, hw_buf, 4376 MPLS__MPLS_ACTION_IF_NOT_BOSf) == 0x1) { 4377 mpls_port->flags2 |= BCM_MPLS_PORT2_WITH_LSP_OAM; 4378 } 4379 } 4380 if (soc_feature(unit, soc_feature_mpls_entropy)) { 4381 if (soc_mem_field32_get(unit, mem, hw_buf, 4382 MPLS__MPLS_ACTION_IF_NOT_BOSf) == 0x2) { 4383 mpls_port->flags2 |= BCM_MPLS_PORT2_INGRESS_ENTROPY_ENABLE; 4384 } 4385 } 4386 if (soc_mem_field32_get(unit, mem, hw_buf, 4387 MPLS__DECAP_USE_EXP_FOR_PRIf) == 0x1) { 4388 /* MAP_PRI_AND_CNG */ 4389 /* Use specified EXP-map to determine internal prio/color */ 4390 mpls_port->exp_map = 4391 soc_mem_field32_get(unit, mem, hw_buf, MPLS__EXP_MAPPING_PTRf); 4392 mpls_port->exp_map |= _BCM_TR_MPLS_EXP_MAP_TABLE_TYPE_INGRESS; 4393 mpls_port->flags |= BCM_MPLS_PORT_INT_PRI_MAP; 4394 } else if (soc_mem_field32_get(unit, mem, hw_buf, 4395 MPLS__DECAP_USE_EXP_FOR_PRIf) == 0x2) { 4396 /* NEW_PRI_MAP_CNG */ 4397 /* Use the specified internal priority value */ 4398 mpls_port->int_pri = 4399 soc_mem_field32_get(unit, mem, hw_buf, MPLS__NEW_PRIf); 4400 mpls_port->flags |= BCM_MPLS_PORT_INT_PRI_SET; 4401 4402 /* Use specified EXP-map to determine internal color */ 4403 mpls_port->exp_map = 4404 soc_mem_field32_get(unit, mem, hw_buf, MPLS__EXP_MAPPING_PTRf); 4405 mpls_port->exp_map |= _BCM_TR_MPLS_EXP_MAP_TABLE_TYPE_INGRESS; 4406 mpls_port->flags |= BCM_MPLS_PORT_COLOR_MAP; 4407 } else { 4408 if (soc_mem_field_valid(unit, mem, 4409 MPLS__TRUST_OUTER_DOT1P_PTRf)) { 4410 if (soc_mem_field32_get(unit, mem, hw_buf, 4411 MPLS__TRUST_OUTER_DOT1P_PTRf) == 4412 _BCM_TR_MPLS_PRI_CNG_MAP_NONE) { 4413 /* 4414 * Don't trust the encapsulated packet's 802.1p pri/cfi. 4415 * Use a fixed value for internal priority. 4416 */ 4417 mpls_port->int_pri = 4418 soc_mem_field32_get(unit, mem, hw_buf, MPLS__NEW_PRIf); 4419 mpls_port->flags |= BCM_MPLS_PORT_INT_PRI_SET; 4420 } 4421 } 4422 } 4423 } 4424 } else { 4425 mpls_port->criteria = BCM_MPLS_PORT_MATCH_NONE; 4426 } 4427 return rv; 4428 4429 } 4430 4431 /* 4432 * Function: 4433 * bcm_tr3_mpls_port_stat_attach 4434 * Description: 4435 * Attach counters entries to the given mpls gport and vpn 4436 * 4437 * Parameters: 4438 * unit - (IN) unit number 4439 * vpn - (IN) VPN Id 4440 * port - (IN) MPLS GPORT ID 4441 * stat_counter_id - (IN) Stat Counter ID. 4442 * 4443 * Return Value: 4444 * BCM_E_XXX 4445 * Notes: 4446 */ 4447 bcm_error_t bcm_tr3_mpls_port_stat_attach( 4448 int unit, 4449 bcm_vpn_t vpn, 4450 bcm_gport_t port, 4451 uint32 stat_counter_id) 4452 { 4453 soc_mem_t table=0; 4454 bcm_stat_flex_direction_t direction=bcmStatFlexDirectionIngress; 4455 uint32 pool_number=0; 4456 uint32 base_index=0; 4457 bcm_stat_flex_mode_t offset_mode=0; 4458 bcm_stat_object_t object=bcmStatObjectIngPort; 4459 bcm_stat_group_mode_t group_mode= bcmStatGroupModeSingle; 4460 uint32 count=0; 4461 uint32 actual_num_tables=0; 4462 uint32 num_of_tables=0; 4463 bcm_stat_flex_table_info_t table_info[BCM_STAT_FLEX_COUNTER_MAX_DIRECTION]; 4464 4465 _bcm_esw_stat_get_counter_id_info( 4466 unit, stat_counter_id, 4467 &group_mode,&object,&offset_mode,&pool_number,&base_index); 4468 BCM_IF_ERROR_RETURN(_bcm_esw_stat_validate_object(unit,object,&direction)); 4469 BCM_IF_ERROR_RETURN(_bcm_esw_stat_validate_group(unit,group_mode)); 4470 BCM_IF_ERROR_RETURN(_bcm_esw_stat_flex_get_table_info( 4471 unit,object,1,&actual_num_tables,&table,&direction)); 4472 4473 BCM_IF_ERROR_RETURN(_bcm_tr3_mpls_port_stat_get_table_info( 4474 unit, vpn,port,&num_of_tables,&table_info[0])); 4475 for (count=0; count < num_of_tables ; count++) { 4476 if ((table_info[count].direction == direction) && 4477 (table_info[count].table == table) ) { 4478 if (direction == bcmStatFlexDirectionIngress) { 4479 return _bcm_esw_stat_flex_attach_ingress_table_counters( 4480 unit, 4481 table_info[count].table, 4482 table_info[count].index, 4483 offset_mode, 4484 base_index, 4485 pool_number); 4486 } else { 4487 return _bcm_esw_stat_flex_attach_egress_table_counters( 4488 unit, 4489 table_info[count].table, 4490 table_info[count].index, 4491 0, 4492 offset_mode, 4493 base_index, 4494 pool_number); 4495 } 4496 } 4497 } 4498 return BCM_E_UNAVAIL; 4499 } 4500 /* 4501 * Function: 4502 * bcm_tr3_mpls_port_stat_detach 4503 * Description: 4504 * Detach counters entries to the given mpls port and vpn 4505 * 4506 * Parameters: 4507 * unit - (IN) unit number 4508 * vpn - (IN) VPN Id 4509 * port - (IN) MPLS GPORT ID 4510 * 4511 * Return Value: 4512 * BCM_E_XXX 4513 * Notes: 4514 */ 4515 bcm_error_t bcm_tr3_mpls_port_stat_detach( 4516 int unit, 4517 bcm_vpn_t vpn, 4518 bcm_gport_t port) 4519 { 4520 uint32 count=0; 4521 uint32 num_of_tables=0; 4522 bcm_stat_flex_table_info_t table_info[BCM_STAT_FLEX_COUNTER_MAX_DIRECTION]; 4523 bcm_error_t rv = BCM_E_NONE; 4524 bcm_error_t err_code[BCM_STAT_FLEX_COUNTER_MAX_DIRECTION] = {BCM_E_NONE}; 4525 4526 BCM_IF_ERROR_RETURN(_bcm_tr3_mpls_port_stat_get_table_info( 4527 unit, vpn,port,&num_of_tables,&table_info[0])); 4528 4529 for (count=0; count < num_of_tables ; count++) { 4530 if (table_info[count].direction == bcmStatFlexDirectionIngress) { 4531 rv = _bcm_esw_stat_flex_detach_ingress_table_counters( 4532 unit, table_info[count].table, table_info[count].index); 4533 if (BCM_E_NONE != rv && 4534 BCM_E_NONE == err_code[bcmStatFlexDirectionIngress]) { 4535 err_code[bcmStatFlexDirectionIngress] = rv; 4536 } 4537 } else { 4538 rv = _bcm_esw_stat_flex_detach_egress_table_counters( 4539 unit, 0, table_info[count].table, table_info[count].index); 4540 if (BCM_E_NONE != rv && 4541 BCM_E_NONE == err_code[bcmStatFlexDirectionEgress]) { 4542 err_code[bcmStatFlexDirectionEgress] = rv; 4543 } 4544 } 4545 } 4546 4547 BCM_STAT_FLEX_DETACH_RETURN(err_code) 4548 } 4549 /* 4550 * Function: 4551 * bcm_tr3_mpls_port_stat_counter_get 4552 * Description: 4553 * Get counter statistic values for specific vpn and gport 4554 * if sync_mode is set, sync the sw accumulated count 4555 * with hw count value first, else return sw count. 4556 * 4557 * Parameters: 4558 * unit - (IN) unit number 4559 * sync_mode - (IN) hwcount is to be synced to sw count 4560 * vpn - (IN) VPN Id 4561 * port - (IN) MPLS GPORT ID 4562 * stat - (IN) Type of the counter to retrieve 4563 * I.e. ingress/egress byte/packet) 4564 * num_entries - (IN) Number of counter Entries 4565 * counter_indexes - (IN) Pointer to Counter indexes entries 4566 * counter_values - (OUT) Pointer to counter values 4567 * 4568 * Return Value: 4569 * BCM_E_XXX 4570 * Notes: 4571 */ 4572 bcm_error_t bcm_tr3_mpls_port_stat_counter_get( 4573 int unit, 4574 int sync_mode, 4575 bcm_vpn_t vpn, 4576 bcm_gport_t port, 4577 bcm_mpls_stat_t stat, 4578 uint32 num_entries, 4579 uint32 *counter_indexes, 4580 bcm_stat_value_t *counter_values) 4581 { 4582 uint32 table_count=0; 4583 uint32 index_count=0; 4584 uint32 num_of_tables=0; 4585 bcm_stat_flex_direction_t direction=bcmStatFlexDirectionIngress; 4586 uint32 byte_flag=0; 4587 bcm_stat_flex_table_info_t table_info[ 4588 BCM_STAT_FLEX_COUNTER_MAX_DIRECTION]; 4589 4590 if ((stat == bcmMplsInBytes) || 4591 (stat == bcmMplsInPkts)) { 4592 direction = bcmStatFlexDirectionIngress; 4593 } else { 4594 direction = bcmStatFlexDirectionEgress; 4595 } 4596 if ((stat == bcmMplsInPkts) || 4597 (stat == bcmMplsOutPkts)) { 4598 byte_flag=0; 4599 } else { 4600 byte_flag=1; 4601 } 4602 4603 BCM_IF_ERROR_RETURN(_bcm_tr3_mpls_port_stat_get_table_info( 4604 unit, vpn,port,&num_of_tables,&table_info[0])); 4605 4606 for (table_count=0; table_count < num_of_tables ; table_count++) { 4607 if (table_info[table_count].direction == direction) { 4608 for (index_count=0; index_count < num_entries ; index_count++) { 4609 BCM_IF_ERROR_RETURN(_bcm_esw_stat_counter_get( 4610 unit, sync_mode, 4611 table_info[table_count].index, 4612 table_info[table_count].table, 4613 0, 4614 byte_flag, 4615 counter_indexes[index_count], 4616 &counter_values[index_count])); 4617 } 4618 } 4619 } 4620 return BCM_E_NONE; 4621 } 4622 /* 4623 * Function: 4624 * bcm_tr3_mpls_port_stat_counter_set 4625 * Description: 4626 * Set counter statistic values for specific vpn and gport 4627 * 4628 * Parameters: 4629 * unit - (IN) unit number 4630 * vpn - (IN) VPN Id 4631 * port - (IN) MPLS GPORT ID 4632 * stat - (IN) Type of the counter to retrieve 4633 * I.e. ingress/egress byte/packet) 4634 * num_entries - (IN) Number of counter Entries 4635 * counter_indexes - (IN) Pointer to Counter indexes entries 4636 * counter_values - (OUT) Pointer to counter values 4637 * 4638 * Return Value: 4639 * BCM_E_XXX 4640 * Notes: 4641 */ 4642 bcm_error_t bcm_tr3_mpls_port_stat_counter_set( 4643 int unit, 4644 bcm_vpn_t vpn, 4645 bcm_gport_t port, 4646 bcm_mpls_stat_t stat, 4647 uint32 num_entries, 4648 uint32 *counter_indexes, 4649 bcm_stat_value_t *counter_values) 4650 { 4651 uint32 table_count=0; 4652 uint32 index_count=0; 4653 uint32 num_of_tables=0; 4654 bcm_stat_flex_direction_t direction=bcmStatFlexDirectionIngress; 4655 uint32 byte_flag=0; 4656 bcm_stat_flex_table_info_t table_info[ 4657 BCM_STAT_FLEX_COUNTER_MAX_DIRECTION]; 4658 4659 if ((stat == bcmMplsInBytes) || 4660 (stat == bcmMplsInPkts)) { 4661 direction = bcmStatFlexDirectionIngress; 4662 } else { 4663 direction = bcmStatFlexDirectionEgress; 4664 } 4665 if ((stat == bcmMplsInPkts) || 4666 (stat == bcmMplsOutPkts)) { 4667 byte_flag=0; 4668 } else { 4669 byte_flag=1; 4670 } 4671 4672 BCM_IF_ERROR_RETURN(_bcm_tr3_mpls_port_stat_get_table_info( 4673 unit, vpn,port,&num_of_tables,&table_info[0])); 4674 4675 for (table_count=0; table_count < num_of_tables ; table_count++) { 4676 if (table_info[table_count].direction == direction) { 4677 for (index_count=0; index_count < num_entries ; index_count++) { 4678 BCM_IF_ERROR_RETURN(_bcm_esw_stat_counter_set( 4679 unit, 4680 table_info[table_count].index, 4681 table_info[table_count].table, 4682 0, 4683 byte_flag, 4684 counter_indexes[index_count], 4685 &counter_values[index_count])); 4686 } 4687 } 4688 } 4689 return BCM_E_NONE; 4690 } 4691 /* 4692 * Function: 4693 * bcm_tr3_mpls_port_stat_id_get 4694 * Description: 4695 * Get stat counter id associated with specific vpn and gport 4696 * 4697 * Parameters: 4698 * unit - (IN) unit number 4699 * vpn - (IN) VPN Id 4700 * port - (IN) MPLS GPORT ID 4701 * stat - (IN) Type of the counter to retrieve 4702 * I.e. ingress/egress byte/packet) 4703 * Stat_counter_id - (OUT) Stat Counter ID 4704 * 4705 * Return Value: 4706 * BCM_E_XXX 4707 * Notes: 4708 */ 4709 bcm_error_t bcm_tr3_mpls_port_stat_id_get( 4710 int unit, 4711 bcm_vpn_t vpn, 4712 bcm_gport_t port, 4713 bcm_mpls_stat_t stat, 4714 uint32 *stat_counter_id) 4715 { 4716 bcm_stat_flex_direction_t direction=bcmStatFlexDirectionIngress; 4717 uint32 num_of_tables=0; 4718 bcm_stat_flex_table_info_t table_info[BCM_STAT_FLEX_COUNTER_MAX_DIRECTION]; 4719 uint32 index=0; 4720 uint32 num_stat_counter_ids=0; 4721 4722 if ((stat == bcmMplsInBytes) || 4723 (stat == bcmMplsInPkts)) { 4724 direction = bcmStatFlexDirectionIngress; 4725 } else { 4726 direction = bcmStatFlexDirectionEgress; 4727 } 4728 BCM_IF_ERROR_RETURN(_bcm_tr3_mpls_port_stat_get_table_info( 4729 unit,vpn,port,&num_of_tables,&table_info[0])); 4730 for (index=0; index < num_of_tables ; index++) { 4731 if (table_info[index].direction == direction) 4732 return _bcm_esw_stat_flex_get_counter_id( 4733 unit, 1, &table_info[index], 4734 &num_stat_counter_ids,stat_counter_id); 4735 } 4736 return BCM_E_NOT_FOUND; 4737 } 4738 /* 4739 * Function: 4740 * bcm_tr3_mpls_label_stat_attach 4741 * Description: 4742 * Attach counters entries to the given mpls label and gport 4743 * 4744 * Parameters: 4745 * unit - (IN) unit number 4746 * label - (IN) MPLS Label 4747 * port - (IN) MPLS Gport 4748 * stat_counter_id - (IN) Stat Counter ID. 4749 * 4750 * Return Value: 4751 * BCM_E_XXX 4752 * Notes: 4753 */ 4754 bcm_error_t bcm_tr3_mpls_label_stat_attach( 4755 int unit, 4756 bcm_mpls_label_t label, 4757 bcm_gport_t port, 4758 uint32 stat_counter_id) 4759 { 4760 soc_mem_t table=0; 4761 bcm_stat_flex_direction_t direction=bcmStatFlexDirectionIngress; 4762 uint32 pool_number=0; 4763 uint32 base_index=0; 4764 bcm_stat_flex_mode_t offset_mode=0; 4765 bcm_stat_object_t object=bcmStatObjectIngPort; 4766 bcm_stat_group_mode_t group_mode= bcmStatGroupModeSingle; 4767 uint32 count=0; 4768 uint32 actual_num_tables=0; 4769 uint32 num_of_tables=0; 4770 bcm_stat_flex_table_info_t table_info[BCM_STAT_FLEX_COUNTER_MAX_DIRECTION]; 4771 4772 _bcm_esw_stat_get_counter_id_info( 4773 unit, stat_counter_id, 4774 &group_mode,&object,&offset_mode,&pool_number,&base_index); 4775 BCM_IF_ERROR_RETURN(_bcm_esw_stat_validate_object(unit,object,&direction)); 4776 BCM_IF_ERROR_RETURN(_bcm_esw_stat_validate_group(unit,group_mode)); 4777 BCM_IF_ERROR_RETURN(_bcm_esw_stat_flex_get_table_info( 4778 unit,object,1,&actual_num_tables,&table,&direction)); 4779 4780 if (!BCM_XGS3_L3_MPLS_LBL_VALID(label)) { 4781 return BCM_E_PARAM; 4782 } 4783 4784 BCM_IF_ERROR_RETURN(_bcm_tr3_mpls_label_stat_get_table_info( 4785 unit, label, port, object, &num_of_tables, &table_info[0])); 4786 for (count=0; count < num_of_tables ; count++) { 4787 if ((table_info[count].direction == direction) && 4788 (table_info[count].table == table) ) { 4789 if (direction == bcmStatFlexDirectionIngress) { 4790 return _bcm_esw_stat_flex_attach_ingress_table_counters( 4791 unit, 4792 table_info[count].table, 4793 table_info[count].index, 4794 offset_mode, 4795 base_index, 4796 pool_number); 4797 } else { 4798 return _bcm_esw_stat_flex_attach_egress_table_counters( 4799 unit, 4800 table_info[count].table, 4801 table_info[count].index, 4802 0, 4803 offset_mode, 4804 base_index, 4805 pool_number); 4806 } 4807 } 4808 } 4809 return BCM_E_NOT_FOUND; 4810 } 4811 /* 4812 * Function: 4813 * bcm_tr3_mpls_label_stat_detach 4814 * Description: 4815 * Detach counters entries to the given mpls label and gport 4816 * 4817 * Parameters: 4818 * unit - (IN) unit number 4819 * label - (IN) MPLS Label 4820 * port - (IN) MPLS Gport 4821 * 4822 * Return Value: 4823 * BCM_E_XXX 4824 * Notes: 4825 */ 4826 bcm_error_t bcm_tr3_mpls_label_stat_detach( 4827 int unit, 4828 bcm_mpls_label_t label, 4829 bcm_gport_t port) 4830 { 4831 uint32 count=0; 4832 uint32 num_of_tables=0; 4833 bcm_stat_flex_table_info_t table_info[BCM_STAT_FLEX_COUNTER_MAX_DIRECTION]; 4834 bcm_error_t rv = BCM_E_NONE; 4835 bcm_error_t err_code[BCM_STAT_FLEX_COUNTER_MAX_DIRECTION] = {BCM_E_NONE}; 4836 mpls_entry_entry_t mpls_entry_entry={{0}}; 4837 mpls_entry_extd_entry_t mpls_entry_extd_entry={{0}}; 4838 4839 if (!BCM_XGS3_L3_MPLS_LBL_VALID(label)) { 4840 return BCM_E_PARAM; 4841 } 4842 4843 BCM_IF_ERROR_RETURN(_bcm_tr3_mpls_label_stat_get_table_info( 4844 unit, label, port, bcmStatObjectMaxValue, 4845 &num_of_tables,&table_info[0])); 4846 4847 for (count=0; count < num_of_tables ; count++) { 4848 if (table_info[count].direction == bcmStatFlexDirectionIngress) { 4849 rv = _bcm_esw_stat_flex_detach_ingress_table_counters( 4850 unit, table_info[count].table, table_info[count].index); 4851 if (SOC_IS_TRIUMPH3(unit)) { 4852 BCM_IF_ERROR_RETURN(soc_mem_read( 4853 unit, MPLS_ENTRY_EXTDm, MEM_BLOCK_ANY, 4854 table_info[count].index, 4855 (void *)&mpls_entry_extd_entry)); 4856 /* NO check required */ 4857 BCM_IF_ERROR_RETURN( 4858 _bcm_esw_mpls_entry_convert_to_regular_entry( 4859 unit,&mpls_entry_extd_entry,&mpls_entry_entry)); 4860 BCM_IF_ERROR_RETURN(soc_mem_delete( 4861 unit, MPLS_ENTRY_EXTDm, MEM_BLOCK_ANY, 4862 (void *)&mpls_entry_extd_entry)); 4863 BCM_IF_ERROR_RETURN(soc_mem_insert( 4864 unit, MPLS_ENTRYm, MEM_BLOCK_ALL, 4865 (void *)&mpls_entry_entry)); 4866 } 4867 if (BCM_E_NONE != rv && 4868 BCM_E_NONE == err_code[bcmStatFlexDirectionIngress]) { 4869 err_code[bcmStatFlexDirectionIngress] = rv; 4870 } 4871 } else { 4872 rv = _bcm_esw_stat_flex_detach_egress_table_counters( 4873 unit, 0, table_info[count].table, table_info[count].index); 4874 if (BCM_E_NONE != rv && 4875 BCM_E_NONE == err_code[bcmStatFlexDirectionEgress]) { 4876 err_code[bcmStatFlexDirectionEgress] = rv; 4877 } 4878 } 4879 } 4880 4881 BCM_STAT_FLEX_DETACH_RETURN(err_code) 4882 } 4883 /* 4884 * Function: 4885 * bcm_tr3_mpls_label_stat_counter_get 4886 * Description: 4887 * Get counter statistic values for specific MPLS label and gport 4888 * if sync_mode is set, sync the sw accumulated count 4889 * with hw count value first, else return sw count. 4890 * 4891 * Parameters: 4892 * unit - (IN) unit number 4893 * sync_mode - (IN) hwcount is to be synced to sw count 4894 * label - (IN) MPLS Label 4895 * port - (IN) MPLS Gport 4896 * stat - (IN) Type of the counter to retrieve 4897 * I.e. ingress/egress byte/packet) 4898 * num_entries - (IN) Number of counter Entries 4899 * counter_indexes - (IN) Pointer to Counter indexes entries 4900 * counter_values - (OUT) Pointer to counter values 4901 * 4902 * Return Value: 4903 * BCM_E_XXX 4904 * Notes: 4905 */ 4906 bcm_error_t bcm_tr3_mpls_label_stat_counter_get( 4907 int unit, 4908 int sync_mode, 4909 bcm_mpls_label_t label, 4910 bcm_gport_t port, 4911 bcm_mpls_stat_t stat, 4912 uint32 num_entries, 4913 uint32 *counter_indexes, 4914 bcm_stat_value_t *counter_values) 4915 { 4916 uint32 table_count=0; 4917 uint32 index_count=0; 4918 uint32 num_of_tables=0; 4919 bcm_stat_flex_direction_t direction=bcmStatFlexDirectionIngress; 4920 uint32 byte_flag=0; 4921 bcm_stat_flex_table_info_t table_info[ 4922 BCM_STAT_FLEX_COUNTER_MAX_DIRECTION]; 4923 4924 if ((stat == bcmMplsInBytes) || 4925 (stat == bcmMplsInPkts)) { 4926 direction = bcmStatFlexDirectionIngress; 4927 } else { 4928 direction = bcmStatFlexDirectionEgress; 4929 } 4930 if ((stat == bcmMplsInPkts) || 4931 (stat == bcmMplsOutPkts)) { 4932 byte_flag=0; 4933 } else { 4934 byte_flag=1; 4935 } 4936 4937 if (!BCM_XGS3_L3_MPLS_LBL_VALID(label)) { 4938 return BCM_E_PARAM; 4939 } 4940 4941 BCM_IF_ERROR_RETURN(_bcm_tr3_mpls_label_stat_get_table_info( 4942 unit, label, port, bcmStatObjectMaxValue, 4943 &num_of_tables,&table_info[0])); 4944 4945 for (table_count=0; table_count < num_of_tables ; table_count++) { 4946 if (table_info[table_count].direction == direction) { 4947 for (index_count=0; index_count < num_entries ; index_count++) { 4948 BCM_IF_ERROR_RETURN(_bcm_esw_stat_counter_get( 4949 unit, sync_mode, 4950 table_info[table_count].index, 4951 table_info[table_count].table, 4952 0, 4953 byte_flag, 4954 counter_indexes[index_count], 4955 &counter_values[index_count])); 4956 } 4957 } 4958 } 4959 return BCM_E_NONE; 4960 } 4961 /* 4962 * Function: 4963 * bcm_tr3_mpls_label_stat_counter_set 4964 * Description: 4965 * Set counter statistic values for specific MPLS label and gport 4966 * 4967 * Parameters: 4968 * unit - (IN) unit number 4969 * label - (IN) MPLS Label 4970 * port - (IN) MPLS Gport 4971 * stat - (IN) Type of the counter to retrieve 4972 * I.e. ingress/egress byte/packet) 4973 * num_entries - (IN) Number of counter Entries 4974 * counter_indexes - (IN) Pointer to Counter indexes entries 4975 * counter_values - (IN) Pointer to counter values 4976 * 4977 * Return Value: 4978 * BCM_E_XXX 4979 * Notes: 4980 */ 4981 bcm_error_t bcm_tr3_mpls_label_stat_counter_set( 4982 int unit, 4983 bcm_mpls_label_t label, 4984 bcm_gport_t port, 4985 bcm_mpls_stat_t stat, 4986 uint32 num_entries, 4987 uint32 *counter_indexes, 4988 bcm_stat_value_t *counter_values) 4989 { 4990 uint32 table_count=0; 4991 uint32 index_count=0; 4992 uint32 num_of_tables=0; 4993 bcm_stat_flex_direction_t direction=bcmStatFlexDirectionIngress; 4994 uint32 byte_flag=0; 4995 bcm_stat_flex_table_info_t table_info[ 4996 BCM_STAT_FLEX_COUNTER_MAX_DIRECTION]; 4997 bcm_vpn_t vpn = 0; 4998 4999 if ((stat == bcmMplsInBytes) || 5000 (stat == bcmMplsInPkts)) { 5001 direction = bcmStatFlexDirectionIngress; 5002 } else { 5003 direction = bcmStatFlexDirectionEgress; 5004 } 5005 if ((stat == bcmMplsInPkts) || 5006 (stat == bcmMplsOutPkts)) { 5007 byte_flag=0; 5008 } else { 5009 byte_flag=1; 5010 } 5011 5012 if (BCM_GPORT_IS_MPLS_PORT(port)) { 5013 _BCM_MPLS_VPN_SET(vpn, _BCM_MPLS_VPN_TYPE_VPWS, 1); 5014 BCM_IF_ERROR_RETURN(_bcm_tr3_mpls_port_stat_get_table_info( 5015 unit, vpn, port, &num_of_tables, &table_info[0])); 5016 } else { 5017 if (!BCM_XGS3_L3_MPLS_LBL_VALID(label)) { 5018 return BCM_E_PARAM; 5019 } 5020 5021 BCM_IF_ERROR_RETURN(_bcm_tr3_mpls_label_stat_get_table_info( 5022 unit, label, port, bcmStatObjectMaxValue, 5023 &num_of_tables,&table_info[0])); 5024 } 5025 5026 for (table_count=0; table_count < num_of_tables ; table_count++) { 5027 if (table_info[table_count].direction == direction) { 5028 for (index_count=0; index_count < num_entries ; index_count++) { 5029 BCM_IF_ERROR_RETURN(_bcm_esw_stat_counter_set( 5030 unit, 5031 table_info[table_count].index, 5032 table_info[table_count].table, 5033 0, 5034 byte_flag, 5035 counter_indexes[index_count], 5036 &counter_values[index_count])); 5037 } 5038 } 5039 } 5040 return BCM_E_NONE; 5041 } 5042 /* 5043 * Function: 5044 * bcm_tr3_mpls_label_stat_id_get 5045 * Description: 5046 * Get stat counter id associated with given vlan 5047 * 5048 * Parameters: 5049 * unit - (IN) unit number 5050 * label - (IN) MPLS Label 5051 * port - (IN) MPLS Gport 5052 * stat - (IN) Type of the counter to retrieve 5053 * I.e. ingress/egress byte/packet) 5054 * Stat_counter_id - (OUT) Stat Counter ID 5055 * 5056 * Return Value: 5057 * BCM_E_XXX 5058 * Notes: 5059 */ 5060 bcm_error_t bcm_tr3_mpls_label_stat_id_get( 5061 int unit, 5062 bcm_mpls_label_t label, 5063 bcm_gport_t port, 5064 bcm_mpls_stat_t stat, 5065 uint32 *stat_counter_id) 5066 { 5067 bcm_stat_flex_direction_t direction=bcmStatFlexDirectionIngress; 5068 uint32 num_of_tables=0; 5069 bcm_stat_flex_table_info_t table_info[BCM_STAT_FLEX_COUNTER_MAX_DIRECTION]; 5070 uint32 index=0; 5071 uint32 num_stat_counter_ids=0; 5072 5073 if (!BCM_XGS3_L3_MPLS_LBL_VALID(label)) { 5074 return BCM_E_PARAM; 5075 } 5076 5077 if ((stat == bcmMplsInBytes) || 5078 (stat == bcmMplsInPkts)) { 5079 direction = bcmStatFlexDirectionIngress; 5080 } else { 5081 direction = bcmStatFlexDirectionEgress; 5082 } 5083 BCM_IF_ERROR_RETURN(_bcm_tr3_mpls_label_stat_get_table_info( 5084 unit, label, port, bcmStatObjectMaxValue, 5085 &num_of_tables, &table_info[0])); 5086 for (index=0; index < num_of_tables ; index++) { 5087 if (table_info[index].direction == direction) 5088 return _bcm_esw_stat_flex_get_counter_id( 5089 unit, 1, &table_info[index], 5090 &num_stat_counter_ids,stat_counter_id); 5091 } 5092 return BCM_E_NOT_FOUND; 5093 } 5094 /* 5095 * Function: 5096 * bcm_tr3_mpls_label_stat_enable_set 5097 * Purpose: 5098 * Enable statistics collection for MPLS label or MPLS gport 5099 * Parameters: 5100 * unit - (IN) Unit number. 5101 * label - (IN) MPLS label 5102 * port - (IN) MPLS gport 5103 * enable - (IN) Non-zero to enable counter collection, zero to disable. 5104 * Returns: 5105 * BCM_E_xxx 5106 * Notes: 5107 */ 5108 int bcm_tr3_mpls_label_stat_enable_set( 5109 int unit, 5110 bcm_mpls_label_t label, 5111 bcm_gport_t port, 5112 int enable) 5113 { 5114 uint32 num_of_tables=0; 5115 uint32 num_stat_counter_ids=0; 5116 bcm_stat_flex_table_info_t table_info[BCM_STAT_FLEX_COUNTER_MAX_DIRECTION]; 5117 bcm_stat_object_t object=bcmStatObjectIngPort; 5118 uint32 stat_counter_id[ 5119 BCM_STAT_FLEX_COUNTER_MAX_DIRECTION]={0}; 5120 uint32 num_entries=0; 5121 int index=0; 5122 5123 if (BCM_GPORT_IS_MPLS_PORT(port)) { 5124 /* When the gport is an MPLS port, we'll turn on the 5125 * port-based tracking to comply with API definition. 5126 */ 5127 5128 int vpn; 5129 5130 /* just create a valid vpn id to pass the check */ 5131 _BCM_MPLS_VPN_SET(vpn, _BCM_MPLS_VPN_TYPE_VPWS, 1); 5132 BCM_IF_ERROR_RETURN(_bcm_tr3_mpls_port_stat_get_table_info( 5133 unit,vpn,port,&num_of_tables,&table_info[0])); 5134 if (enable ) { 5135 for(index=0;index < num_of_tables ;index++) { 5136 if (table_info[index].direction == bcmStatFlexDirectionIngress) { 5137 BCM_IF_ERROR_RETURN(_bcm_esw_stat_flex_get_ingress_object( 5138 unit,table_info[index].table, 5139 table_info[index].index,NULL,&object)); 5140 } else { 5141 BCM_IF_ERROR_RETURN(_bcm_esw_stat_flex_get_egress_object( 5142 unit,table_info[index].table, 5143 table_info[index].table,NULL,&object)); 5144 } 5145 BCM_IF_ERROR_RETURN(bcm_esw_stat_group_create( 5146 unit,object,bcmStatGroupModeSingle, 5147 &stat_counter_id[table_info[index].direction], 5148 &num_entries)); 5149 BCM_IF_ERROR_RETURN(bcm_tr3_mpls_port_stat_attach( 5150 unit,vpn,port, 5151 stat_counter_id[table_info[index].direction])); 5152 } 5153 return BCM_E_NONE; 5154 } else { 5155 BCM_IF_ERROR_RETURN(_bcm_esw_stat_flex_get_counter_id( 5156 unit, num_of_tables,&table_info[0], 5157 &num_stat_counter_ids,&stat_counter_id[0])); 5158 if ((stat_counter_id[bcmStatFlexDirectionIngress] == 0) && 5159 (stat_counter_id[bcmStatFlexDirectionEgress] == 0)) { 5160 return BCM_E_PARAM; 5161 } 5162 BCM_IF_ERROR_RETURN(bcm_tr3_mpls_port_stat_detach(unit,vpn,port)); 5163 if (stat_counter_id[bcmStatFlexDirectionIngress] != 0) { 5164 BCM_IF_ERROR_RETURN(bcm_esw_stat_group_destroy( 5165 unit, 5166 stat_counter_id[bcmStatFlexDirectionIngress])); 5167 } 5168 if (stat_counter_id[bcmStatFlexDirectionEgress] != 0) { 5169 BCM_IF_ERROR_RETURN(bcm_esw_stat_group_destroy( 5170 unit, 5171 stat_counter_id[bcmStatFlexDirectionEgress])); 5172 } 5173 return BCM_E_NONE; 5174 } 5175 5176 } 5177 5178 if (!BCM_XGS3_L3_MPLS_LBL_VALID(label)) { 5179 return BCM_E_PARAM; 5180 } 5181 5182 BCM_IF_ERROR_RETURN(_bcm_tr3_mpls_label_stat_get_table_info( 5183 unit, label, port, bcmStatObjectMaxValue, 5184 &num_of_tables, &table_info[0])); 5185 if (enable ) { 5186 for(index=0;index < num_of_tables ;index++) { 5187 if (table_info[index].direction == bcmStatFlexDirectionIngress) { 5188 BCM_IF_ERROR_RETURN(_bcm_esw_stat_flex_get_ingress_object( 5189 unit,table_info[index].table, 5190 table_info[index].index,NULL,&object)); 5191 } else { 5192 BCM_IF_ERROR_RETURN(_bcm_esw_stat_flex_get_egress_object( 5193 unit,table_info[index].table, 5194 table_info[index].table,NULL,&object)); 5195 } 5196 BCM_IF_ERROR_RETURN(bcm_esw_stat_group_create( 5197 unit,object,bcmStatGroupModeSingle, 5198 &stat_counter_id[table_info[index].direction], 5199 &num_entries)); 5200 BCM_IF_ERROR_RETURN(bcm_esw_mpls_label_stat_attach( 5201 unit,label,port, 5202 stat_counter_id[table_info[index].direction])); 5203 } 5204 return BCM_E_NONE; 5205 } else { 5206 BCM_IF_ERROR_RETURN(_bcm_esw_stat_flex_get_counter_id( 5207 unit, num_of_tables,&table_info[0], 5208 &num_stat_counter_ids,&stat_counter_id[0])); 5209 if ((stat_counter_id[bcmStatFlexDirectionIngress] == 0) && 5210 (stat_counter_id[bcmStatFlexDirectionEgress] == 0)) { 5211 return BCM_E_PARAM; 5212 } 5213 BCM_IF_ERROR_RETURN(bcm_esw_mpls_label_stat_detach(unit,label,port)); 5214 if (stat_counter_id[bcmStatFlexDirectionIngress] != 0) { 5215 BCM_IF_ERROR_RETURN(bcm_esw_stat_group_destroy( 5216 unit, 5217 stat_counter_id[bcmStatFlexDirectionIngress])); 5218 } 5219 if (stat_counter_id[bcmStatFlexDirectionEgress] != 0) { 5220 BCM_IF_ERROR_RETURN(bcm_esw_stat_group_destroy( 5221 unit, 5222 stat_counter_id[bcmStatFlexDirectionEgress])); 5223 } 5224 return BCM_E_NONE; 5225 } 5226 5227 } 5228 /* 5229 * Function: 5230 * bcm_tr3_mpls_label_stat_get 5231 * Purpose: 5232 * Get L2 MPLS PW Stats 5233 * Parameters: 5234 * unit - (IN) SOC unit # 5235 * label - (IN) MPLS label 5236 * port - (IN) MPLS gport 5237 * stat - (IN) specify the Stat type 5238 * val - (OUT) 64-bit Stats value 5239 * Returns: 5240 * BCM_E_XXX 5241 */ 5242 5243 int bcm_tr3_mpls_label_stat_get(int unit, 5244 int sync_mode, 5245 bcm_mpls_label_t label, 5246 bcm_gport_t port, 5247 bcm_mpls_stat_t stat, 5248 uint64 *val) 5249 { 5250 uint32 counter_indexes=0 ; 5251 bcm_stat_value_t counter_values={0}; 5252 5253 if (BCM_GPORT_IS_MPLS_PORT(port)) { 5254 int vpn; 5255 5256 /* just create a valid vpn id to pass the check */ 5257 _BCM_MPLS_VPN_SET(vpn, _BCM_MPLS_VPN_TYPE_VPWS, 1); 5258 5259 BCM_IF_ERROR_RETURN( 5260 bcm_tr3_mpls_port_stat_counter_get(unit, sync_mode, vpn, 5261 port, stat, 1, 5262 &counter_indexes, 5263 &counter_values)); 5264 } else { 5265 if (!BCM_XGS3_L3_MPLS_LBL_VALID(label)) { 5266 return BCM_E_PARAM; 5267 } 5268 5269 BCM_IF_ERROR_RETURN( 5270 bcm_tr3_mpls_label_stat_counter_get(unit, sync_mode, label, 5271 port, stat, 1, 5272 &counter_indexes, 5273 &counter_values)); 5274 } 5275 5276 if ((stat == bcmMplsInPkts) || 5277 (stat == bcmMplsOutPkts)) { 5278 COMPILER_64_SET(*val, 5279 COMPILER_64_HI(counter_values.packets64), 5280 COMPILER_64_LO(counter_values.packets64)); 5281 } else { 5282 COMPILER_64_SET(*val, 5283 COMPILER_64_HI(counter_values.bytes), 5284 COMPILER_64_LO(counter_values.bytes)); 5285 } 5286 return BCM_E_NONE; 5287 } 5288 /* 5289 * Function: 5290 * bcm_tr3_mpls_label_stat_get32 5291 * Purpose: 5292 * Get L2 MPLS PW Stats 5293 * if sync_mode is set, sync the sw accumulated count 5294 * with hw count value first, else return sw count. 5295 * Parameters: 5296 * unit - (IN) SOC unit # 5297 * sync_mode - (IN) hwcount is to be synced to sw count 5298 * label - (IN) MPLS label 5299 * port - (IN) MPLS gport 5300 * stat - (IN) specify the Stat type 5301 * val - (OUT) 32-bit Stats value 5302 * Returns: 5303 * BCM_E_XXX 5304 */ 5305 5306 int bcm_tr3_mpls_label_stat_get32(int unit, 5307 int sync_mode, 5308 bcm_mpls_label_t label, 5309 bcm_gport_t port, 5310 bcm_mpls_stat_t stat, 5311 uint32 *val) 5312 { 5313 uint32 counter_indexes=0; 5314 bcm_stat_value_t counter_values={0}; 5315 5316 if (BCM_GPORT_IS_MPLS_PORT(port)) { 5317 int vpn; 5318 5319 /* just create a valid vpn id to pass the check */ 5320 _BCM_MPLS_VPN_SET(vpn, _BCM_MPLS_VPN_TYPE_VPWS, 1); 5321 5322 BCM_IF_ERROR_RETURN( 5323 bcm_tr3_mpls_port_stat_counter_get(unit, sync_mode, vpn, 5324 port, stat, 1, 5325 &counter_indexes, 5326 &counter_values)); 5327 } else { 5328 if (!BCM_XGS3_L3_MPLS_LBL_VALID(label)) { 5329 return BCM_E_PARAM; 5330 } 5331 BCM_IF_ERROR_RETURN( 5332 bcm_tr3_mpls_label_stat_counter_get(unit, sync_mode, label, 5333 port, stat, 1, 5334 &counter_indexes, 5335 &counter_values)); 5336 } 5337 5338 if ((stat == bcmMplsInPkts) || 5339 (stat == bcmMplsOutPkts)) { 5340 *val = counter_values.packets; 5341 } else { 5342 /* Ignoring Hi bytes value */ 5343 *val = COMPILER_64_LO(counter_values.bytes); 5344 } 5345 return BCM_E_NONE; 5346 } 5347 /* 5348 * Function: 5349 * bcm_tr3_mpls_label_stat_clear 5350 * Purpose: 5351 * Clear L2 MPLS PW Stats 5352 * Parameters: 5353 * unit - (IN) SOC unit # 5354 * label - (IN) MPLS label 5355 * port - (IN) MPLS gport 5356 * stat - (IN) specify the Stat type 5357 * Returns: 5358 * BCM_E_XXX 5359 */ 5360 5361 int bcm_tr3_mpls_label_stat_clear( 5362 int unit, 5363 bcm_mpls_label_t label, 5364 bcm_gport_t port, 5365 bcm_mpls_stat_t stat) 5366 { 5367 uint32 counter_indexes=0 ; 5368 bcm_stat_value_t counter_values={0}; 5369 5370 if (!BCM_XGS3_L3_MPLS_LBL_VALID(label)) { 5371 return BCM_E_PARAM; 5372 } 5373 5374 BCM_IF_ERROR_RETURN(bcm_esw_mpls_label_stat_counter_set( 5375 unit,label,port,stat,1, 5376 &counter_indexes,&counter_values)); 5377 return BCM_E_NONE; 5378 } 5379 5380 #ifdef BCM_WARM_BOOT_SUPPORT 5381 /* 5382 * Function: 5383 * _bcm_tr3_mpls_match_key_recover 5384 * Purpose: 5385 * - Recover MPLS match key from h/w tables 5386 * Parameters: 5387 * unit : (IN) Device Unit Number 5388 * Returns: 5389 * BCM_E_XXX 5390 */ 5391 int 5392 _bcm_tr3_mpls_match_key_recover(int unit) 5393 { 5394 int key_type, i, vp, port_type; 5395 int index_min, index_max; 5396 vlan_xlate_extd_entry_t vent; 5397 mpls_entry_entry_t mpls_entry; 5398 source_trunk_map_table_entry_t trunk_entry; 5399 _bcm_tr_mpls_bookkeeping_t *mpls_info = MPLS_INFO(unit); 5400 5401 5402 /* Recover match keys from VLAN_XLATE_EXTDm table */ 5403 index_min = soc_mem_index_min(unit, VLAN_XLATE_EXTDm); 5404 index_max = soc_mem_index_max(unit, VLAN_XLATE_EXTDm); 5405 for (i = index_min; i <= index_max; i++) { 5406 SOC_IF_ERROR_RETURN(soc_mem_read(unit, 5407 VLAN_XLATE_EXTDm, MEM_BLOCK_ANY, i, &vent)); 5408 if (soc_VLAN_XLATE_EXTDm_field32_get(unit, &vent, VALID_0f) == 0) { 5409 continue; 5410 } 5411 5412 key_type = soc_VLAN_XLATE_EXTDm_field32_get(unit, &vent, KEY_TYPE_0f); 5413 if ((key_type != TR3_VLXLT_X_HASH_KEY_TYPE_OVID) && 5414 (key_type != TR3_VLXLT_X_HASH_KEY_TYPE_IVID) && 5415 (key_type != TR3_VLXLT_X_HASH_KEY_TYPE_IVID_OVID) && 5416 (key_type != TR3_VLXLT_X_HASH_KEY_TYPE_PRI_CFI)) { 5417 continue; 5418 } 5419 5420 if (soc_VLAN_XLATE_EXTDm_field32_get(unit, &vent, XLATE__MPLS_ACTIONf) != 0x1) { 5421 continue; 5422 } 5423 5424 vp = soc_VLAN_XLATE_EXTDm_field32_get(unit, &vent, XLATE__SOURCE_VPf); 5425 5426 /* Proceed only if this VP belongs to MPLS */ 5427 if (_bcm_vp_used_get(unit, vp, _bcmVpTypeMpls)) { 5428 if (key_type == TR3_VLXLT_X_HASH_KEY_TYPE_OVID) { 5429 5430 mpls_info->match_key[vp].flags = _BCM_MPLS_PORT_MATCH_TYPE_VLAN; 5431 mpls_info->match_key[vp].match_vlan = 5432 soc_VLAN_XLATE_EXTDm_field32_get(unit, &vent, XLATE__OVIDf); 5433 if (soc_VLAN_XLATE_EXTDm_field32_get(unit, &vent, XLATE__Tf) == 0x1) { 5434 mpls_info->match_key[vp].trunk_id = 5435 soc_VLAN_XLATE_EXTDm_field32_get(unit, &vent, XLATE__TGIDf); 5436 } else { 5437 mpls_info->match_key[vp].port = 5438 soc_VLAN_XLATE_EXTDm_field32_get(unit, &vent, XLATE__PORT_NUMf); 5439 mpls_info->match_key[vp].modid = 5440 soc_VLAN_XLATE_EXTDm_field32_get(unit, &vent, XLATE__MODULE_IDf); 5441 } 5442 bcm_tr_mpls_port_match_count_adjust(unit, vp, 1); 5443 } else if (key_type == TR3_VLXLT_X_HASH_KEY_TYPE_IVID) { 5444 5445 mpls_info->match_key[vp].flags = _BCM_MPLS_PORT_MATCH_TYPE_INNER_VLAN; 5446 mpls_info->match_key[vp].match_inner_vlan = 5447 soc_VLAN_XLATE_EXTDm_field32_get(unit, &vent, XLATE__IVIDf); 5448 if (soc_VLAN_XLATE_EXTDm_field32_get(unit, &vent, XLATE__Tf) == 0x1) { 5449 mpls_info->match_key[vp].trunk_id = 5450 soc_VLAN_XLATE_EXTDm_field32_get(unit, &vent, XLATE__TGIDf); 5451 } else { 5452 mpls_info->match_key[vp].port = 5453 soc_VLAN_XLATE_EXTDm_field32_get(unit, &vent, XLATE__PORT_NUMf); 5454 mpls_info->match_key[vp].modid = 5455 soc_VLAN_XLATE_EXTDm_field32_get(unit, &vent, XLATE__MODULE_IDf); 5456 } 5457 bcm_tr_mpls_port_match_count_adjust(unit, vp, 1); 5458 } else if (key_type == TR3_VLXLT_X_HASH_KEY_TYPE_IVID_OVID) { 5459 5460 mpls_info->match_key[vp].flags = 5461 _BCM_MPLS_PORT_MATCH_TYPE_VLAN_STACKED; 5462 mpls_info->match_key[vp].match_vlan = 5463 soc_VLAN_XLATE_EXTDm_field32_get(unit, &vent, XLATE__OVIDf); 5464 mpls_info->match_key[vp].match_inner_vlan = 5465 soc_VLAN_XLATE_EXTDm_field32_get(unit, &vent, XLATE__IVIDf); 5466 if (soc_VLAN_XLATE_EXTDm_field32_get(unit, &vent, Tf) == 0x1) { 5467 mpls_info->match_key[vp].trunk_id = 5468 soc_VLAN_XLATE_EXTDm_field32_get(unit, &vent, XLATE__TGIDf); 5469 } else { 5470 mpls_info->match_key[vp].port = 5471 soc_VLAN_XLATE_EXTDm_field32_get(unit, &vent, XLATE__PORT_NUMf); 5472 mpls_info->match_key[vp].modid = 5473 soc_VLAN_XLATE_EXTDm_field32_get(unit, &vent, XLATE__MODULE_IDf); 5474 } 5475 bcm_tr_mpls_port_match_count_adjust(unit, vp, 1); 5476 } 5477 5478 #ifdef BCM_TRIUMPH2_SUPPORT /* Recover flex stats */ 5479 if (soc_feature(unit, soc_feature_gport_service_counters)) { 5480 BCM_IF_ERROR_RETURN(_bcm_tr_mpls_flex_stat_recover(unit, vp)); 5481 } 5482 #endif /* BCM_TRIUMPH2_SUPPORT */ 5483 5484 /* Recover TPID ref count */ 5485 BCM_IF_ERROR_RETURN(_bcm_tr_mpls_source_vp_tpid_recover(unit, vp)); 5486 } 5487 } 5488 5489 /* Recover misc associated data */ 5490 BCM_IF_ERROR_RETURN(_bcm_tr_mpls_associated_data_recover(unit)); 5491 5492 /* Recover match keys from SOURCE_TRUNK_MAP_TABLEm table */ 5493 index_min = soc_mem_index_min(unit, SOURCE_TRUNK_MAP_TABLEm); 5494 index_max = soc_mem_index_max(unit, SOURCE_TRUNK_MAP_TABLEm); 5495 for (i = index_min; i <= index_max; i++) { 5496 SOC_IF_ERROR_RETURN(soc_mem_read(unit, SOURCE_TRUNK_MAP_TABLEm, 5497 MEM_BLOCK_ANY, i, &trunk_entry)); 5498 5499 vp = soc_SOURCE_TRUNK_MAP_TABLEm_field32_get(unit, 5500 &trunk_entry, SOURCE_VPf); 5501 5502 /* Proceed only if this VP belongs to MPLS */ 5503 if (_bcm_vp_used_get(unit, vp, _bcmVpTypeMpls)) { 5504 5505 port_type = soc_SOURCE_TRUNK_MAP_TABLEm_field32_get(unit, 5506 &trunk_entry, PORT_TYPEf); 5507 if (0 == port_type) { /* Normal port */ 5508 mpls_info->match_key[vp].flags = _BCM_MPLS_PORT_MATCH_TYPE_PORT; 5509 mpls_info->match_key[vp].index = i; 5510 } else if(1 == port_type) { /* Trunk port */ 5511 mpls_info->match_key[vp].flags =_BCM_MPLS_PORT_MATCH_TYPE_TRUNK; 5512 mpls_info->match_key[vp].trunk_id = 5513 soc_SOURCE_TRUNK_MAP_TABLEm_field32_get(unit, &trunk_entry, 5514 TGIDf); 5515 } 5516 5517 #ifdef BCM_TRIUMPH2_SUPPORT /* Recover flex stats */ 5518 if (soc_feature(unit, soc_feature_gport_service_counters)) { 5519 BCM_IF_ERROR_RETURN(_bcm_tr_mpls_flex_stat_recover(unit, vp)); 5520 } 5521 #endif /* BCM_TRIUMPH2_SUPPORT */ 5522 5523 /* Recover TPID ref count */ 5524 BCM_IF_ERROR_RETURN(_bcm_tr_mpls_source_vp_tpid_recover(unit, vp)); 5525 } 5526 } 5527 5528 /* Recover match keys from MPLS_ENTRYm table */ 5529 index_min = soc_mem_index_min(unit, MPLS_ENTRYm); 5530 index_max = soc_mem_index_max(unit, MPLS_ENTRYm); 5531 for (i = index_min; i <= index_max; i++) { 5532 SOC_IF_ERROR_RETURN(soc_mem_read(unit, MPLS_ENTRYm, 5533 MEM_BLOCK_ANY, i, &mpls_entry)); 5534 5535 if (soc_MPLS_ENTRYm_field32_get(unit, &mpls_entry, VALIDf) == 0) { 5536 continue; 5537 } 5538 5539 key_type = soc_MPLS_ENTRYm_field32_get(unit, &mpls_entry, KEY_TYPEf); 5540 5541 if (key_type != 0x12 && key_type != 0x10 && 5542 key_type != 0x11 && key_type != 0x13) { 5543 continue; 5544 } 5545 5546 if ((key_type == 0x11) || 5547 (key_type == 0x13)) { 5548 i++; /* MPLS_ENTRY_2 */ 5549 } 5550 5551 vp = soc_MPLS_ENTRYm_field32_get(unit, &mpls_entry, MPLS__SOURCE_VPf); 5552 5553 /* Proceed only if this VP belongs to MPLS */ 5554 if (_bcm_vp_used_get(unit, vp, _bcmVpTypeMpls)) { 5555 bcm_module_t modid; 5556 bcm_port_t local_port; 5557 bcm_trunk_t trunk_id; 5558 int local_id; 5559 bcm_gport_t mpls_port_id; 5560 bcm_trunk_t mpls_tid = 0; 5561 bcm_port_t mpls_local_port = 0; 5562 int mpls_local_modid = 0; 5563 int rv; 5564 5565 BCM_GPORT_MPLS_PORT_ID_SET(mpls_port_id,vp); 5566 rv = _bcm_esw_gport_resolve(unit, mpls_port_id, &modid, 5567 &local_port, &trunk_id, 5568 &local_id); 5569 if (rv != BCM_E_NONE) { 5570 continue; 5571 } 5572 5573 if (soc_MPLS_ENTRYm_field32_get(unit, &mpls_entry, MPLS__Tf) == 0x1) { 5574 mpls_tid = soc_MPLS_ENTRYm_field32_get(unit, &mpls_entry, MPLS__TGIDf); 5575 if (mpls_tid == trunk_id) { 5576 mpls_info->match_key[vp].trunk_id = mpls_tid; 5577 } else { 5578 mpls_info->match_key[vp].fo_trunk_id = mpls_tid; 5579 } 5580 mpls_info->match_key[vp].flags = _BCM_MPLS_PORT_MATCH_TYPE_LABEL_PORT; 5581 } else { 5582 mpls_local_port = 5583 soc_MPLS_ENTRYm_field32_get(unit, &mpls_entry, MPLS__PORT_NUMf); 5584 mpls_local_modid = 5585 soc_MPLS_ENTRYm_field32_get(unit, &mpls_entry, MPLS__MODULE_IDf); 5586 if ((mpls_local_port == 0) && (mpls_local_modid == 0)) { 5587 mpls_info->match_key[vp].flags = _BCM_MPLS_PORT_MATCH_TYPE_LABEL; 5588 mpls_info->match_key[vp].port = mpls_local_port; 5589 mpls_info->match_key[vp].modid = mpls_local_modid; 5590 } else { 5591 mpls_info->match_key[vp].flags = _BCM_MPLS_PORT_MATCH_TYPE_LABEL_PORT; 5592 if (mpls_local_port == local_port && mpls_local_modid == modid) { 5593 mpls_info->match_key[vp].port = mpls_local_port; 5594 mpls_info->match_key[vp].modid = mpls_local_modid; 5595 } else { 5596 mpls_info->match_key[vp].fo_port = mpls_local_port; 5597 mpls_info->match_key[vp].fo_modid = mpls_local_modid; 5598 } 5599 } 5600 } 5601 mpls_info->match_key[vp].match_label = 5602 soc_MPLS_ENTRYm_field32_get(unit, &mpls_entry, MPLS__MPLS_LABELf); 5603 5604 #ifdef BCM_TRIUMPH2_SUPPORT /* Recover flex stats */ 5605 if (soc_feature(unit, soc_feature_gport_service_counters)) { 5606 BCM_IF_ERROR_RETURN 5607 (_bcm_tr_mpls_flex_stat_recover(unit, vp)); 5608 _bcm_tr_mpls_label_flex_stat_recover(unit, &mpls_entry); 5609 } 5610 #endif /* BCM_TRIUMPH2_SUPPORT */ 5611 5612 /* Recover TPID ref count */ 5613 BCM_IF_ERROR_RETURN(_bcm_tr_mpls_source_vp_tpid_recover(unit, vp)); 5614 } 5615 } 5616 return BCM_E_NONE; 5617 } 5618 #endif 5619 5620 #else /* BCM_TRIUMPH3_SUPPORT && BCM_MPLS_SUPPORT && INCLUDE_L3 */ 5621 int bcm_esw_tr3_mpls_not_empty; 5622 #endif /* BCM_TRIUMPH3_SUPPORT && BCM_MPLS_SUPPORT && INCLUDE_L3 */ 5623