mpls.c (50242B)
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: Handle trident3 specific MPLS APIs 9 */ 10 11 12 #include <shared/bsl.h> 13 14 #include <soc/defs.h> 15 #include <sal/core/libc.h> 16 #include <bcm/error.h> 17 18 #ifdef INCLUDE_L3 19 #ifdef BCM_MPLS_SUPPORT 20 #ifdef BCM_SPECIAL_LABEL_SUPPORT 21 22 #include <soc/drv.h> 23 #include <soc/mem.h> 24 #include <soc/util.h> 25 #include <soc/debug.h> 26 27 #include <bcm/types.h> 28 #include <bcm/error.h> 29 30 #include <include/bcm_int/esw/mpls.h> 31 #include <bcm_int/esw/firebolt.h> 32 #include <bcm_int/esw/triumph.h> 33 #include <bcm_int/esw/trident3.h> 34 35 /* 36 * External Linkages. 37 */ 38 #define MPLS_INFO(_unit_) (&_bcm_tr_mpls_bk_info[_unit_]) 39 40 /* 41 * Global Defines. 42 */ 43 bcmi_mpls_special_label_control_t *bcmi_special_label_precedence_state[BCM_MAX_NUM_UNITS]; 44 45 /* 46 * Structure to store REF counts for egress special labels. 47 */ 48 bcmi_mpls_special_label_egress_t bcmi_special_label_egress_state[BCM_MAX_NUM_UNITS] = {{ 0 }}; 49 50 /************************************ 51 ******** Enf Of Headers *********** 52 */ 53 /* 54 * Function: 55 * bcmi_mpls_special_label_identifier_sw_state_init 56 * Purpose: 57 * Initialize software state for special label routines. 58 * 59 * Parameters: 60 * unit - (IN) Device Number 61 * Returns: 62 * BCM_E_XXX 63 */ 64 int 65 bcmi_mpls_special_label_identifier_sw_state_init(int unit) 66 { 67 68 soc_mem_t mem; 69 int index_min = 0; 70 int index_max = 0; 71 uint32 *spl_label_buf = NULL; 72 int buf_size = 0; 73 bcmi_mpls_special_label_control_t *ptr; 74 int rv = BCM_E_NONE; 75 int i = 0; 76 special_label_control_entry_t *label_entry; 77 78 mem = SPECIAL_LABEL_CONTROLm; 79 index_min = soc_mem_index_min(unit, mem); 80 index_max = soc_mem_index_max(unit, mem); 81 82 buf_size = SOC_MEM_TABLE_BYTES(unit, mem) * ((index_max - index_min ) + 1); 83 ptr = bcmi_special_label_precedence_state[unit]; 84 85 spl_label_buf = soc_cm_salloc(unit, buf_size, 86 "SPECIAL_LABEL_CONTROL buffer"); 87 if (NULL == spl_label_buf) { 88 return BCM_E_MEMORY; 89 } 90 rv = soc_mem_read_range(unit, mem, MEM_BLOCK_ANY, index_min, index_max, spl_label_buf); 91 if (rv < 0) { 92 soc_cm_sfree(unit, spl_label_buf); 93 return rv; 94 } 95 96 for (i = index_min; i <= index_max; i++) { 97 98 label_entry = soc_mem_table_idx_to_pointer(unit, 99 mem, special_label_control_entry_t *, spl_label_buf, i); 100 101 if (soc_mem_field32_get(unit, mem, label_entry, VALIDf) != 0x1) { 102 continue; 103 } 104 105 ptr[i].valid = 1; 106 ptr[i].label_value = 107 soc_mem_field32_get(unit, mem, label_entry, LABEL_VALUEf); 108 ptr[i].label_mask = 109 soc_mem_field32_get(unit, mem, label_entry, LABEL_VALUE_MASKf); 110 ptr[i].label_type = 111 soc_mem_field32_get(unit, mem, label_entry, CURRENT_LABEL_TYPEf); 112 113 if (!SOC_WARM_BOOT(unit)) { 114 ptr[i].ref_count++; 115 ptr[i].cancun_added = 1; 116 } 117 } 118 119 bcmi_special_label_egress_state[unit].special_label_ref_count = 0; 120 bcmi_special_label_egress_state[unit].entropy_label_ref_count = 0; 121 soc_cm_sfree(unit, spl_label_buf); 122 return BCM_E_NONE; 123 } 124 125 /* 126 * Function: 127 * bcmi_mpls_special_label_deinit 128 * Purpose: 129 * Cleans software state for special label routines. 130 * 131 * Parameters: 132 * unit - (IN) Device Number 133 * Returns: 134 * None 135 */ 136 void 137 bcmi_mpls_special_label_deinit(int unit) 138 { 139 if (bcmi_special_label_precedence_state[unit]) { 140 soc_cm_sfree(unit, bcmi_special_label_precedence_state[unit]); 141 bcmi_special_label_precedence_state[unit] = NULL; 142 } 143 144 } 145 146 /* 147 * Function: 148 * bcmi_mpls_special_label_init 149 * Purpose: 150 * Initializes software state for special label routines. 151 * 152 * Parameters: 153 * unit - (IN) Device Number 154 * Returns: 155 * BCM_E_XXX 156 */ 157 int 158 bcmi_mpls_special_label_init(int unit) 159 { 160 int num_entry; 161 162 num_entry = soc_mem_index_count(unit, SPECIAL_LABEL_CONTROLm); 163 164 /* First clean if some old state is still not freed */ 165 bcmi_mpls_special_label_deinit(unit); 166 167 bcmi_special_label_precedence_state[unit] = soc_cm_salloc(unit, 168 (num_entry * sizeof(bcmi_mpls_special_label_control_t)), 169 "software state to set precedence of special labels"); 170 171 if (bcmi_special_label_precedence_state[unit] == NULL) { 172 return BCM_E_MEMORY; 173 } 174 sal_memset(bcmi_special_label_precedence_state[unit], 0, 175 (num_entry * sizeof(bcmi_mpls_special_label_control_t))); 176 177 /* 178 * Sync the state with h/w. 179 * Currently, CanCun is writing some default entries at start. 180 * it will be difficult to maintain refcount if user also adds 181 * similar entries and then deletes them. 182 * therefore SDK will read those entries first and then keep 183 * track of them so there is no affect if user deletes their entry. 184 * this will also be helpful during warmboot recovery. 185 */ 186 bcmi_mpls_special_label_identifier_sw_state_init(unit); 187 188 return BCM_E_NONE; 189 } 190 191 int 192 bcmi_mpls_special_label_egress_match(int unit, 193 bcm_mpls_special_label_type_t label_type, 194 void * read_value, 195 void * new_value) 196 { 197 uint64 val64; 198 uint64 val64_r; 199 uint32 val = 0; 200 uint32 val_r = 0; 201 202 if (label_type == bcmMplsSpecialLabelTypeSpecial) { 203 COMPILER_64_ZERO(val64); 204 COMPILER_64_ZERO(val64_r); 205 206 val64 = *((uint64 *)(new_value)); 207 val64_r = *((uint64 *)(read_value)); 208 209 if (COMPILER_64_EQ(val64_r, val64)) { 210 return TRUE; 211 } 212 213 } else { 214 val = *((uint32 *)(new_value)); 215 val_r = *((uint32 *)(read_value)); 216 217 if (val == val_r) { 218 return TRUE; 219 } 220 } 221 222 return FALSE; 223 } 224 225 226 227 /* 228 * Function: 229 * bcmi_mpls_special_label_egress_add 230 * Purpose: 231 * Add an MPLS entropy/special label in 232 * MPLS stack for egress tunnel encap. 233 * Parameters: 234 * unit - (IN) Device Number 235 * label_type - (IN) type of label 236 * label_info - (IN) Info about special label. 237 * Returns: 238 * BCM_E_XXX 239 */ 240 int 241 bcmi_mpls_special_label_egress_add(int unit, 242 bcm_mpls_special_label_type_t label_type, 243 bcm_mpls_special_label_t label_info) 244 { 245 int rv = BCM_E_NONE; 246 uint64 val64; 247 uint64 val64_r; 248 uint32 val = 0; 249 uint32 val_r = 0; 250 bcmi_mpls_special_label_egress_t *ptr; 251 252 ptr = (&(bcmi_special_label_egress_state[unit])); 253 254 255 if (!BCMI_MPLS_LABEL_ID_VALID(label_info.label_value)) { 256 return BCM_E_PARAM; 257 } 258 259 if (!BCMI_MPLS_EXP_VALID(label_info.exp)) { 260 return BCM_E_PARAM; 261 } 262 263 if (!BCMI_MPLS_TTL_VALID(label_info.ttl)) { 264 return BCM_E_PARAM; 265 } 266 267 268 /* Only Special and entropy labels can be added here*/ 269 if ((label_type != bcmMplsSpecialLabelTypeSpecial) && 270 (label_type != bcmMplsSpecialLabelTypeEntropy)) { 271 272 return BCM_E_PARAM; 273 } 274 275 if (label_type == bcmMplsSpecialLabelTypeSpecial) { 276 277 COMPILER_64_ZERO(val64); 278 COMPILER_64_ZERO(val64_r); 279 BCM_IF_ERROR_RETURN(READ_EGR_MPLS_SPECIAL_LABEL_CONTROLr(unit, &(val64_r))); 280 281 soc_reg64_field32_set(unit, EGR_MPLS_SPECIAL_LABEL_CONTROLr, &val64, 282 EXPf, label_info.exp); 283 soc_reg64_field32_set(unit, EGR_MPLS_SPECIAL_LABEL_CONTROLr, &val64, 284 TTLf, label_info.ttl); 285 286 soc_reg64_field32_set(unit, EGR_MPLS_SPECIAL_LABEL_CONTROLr, &val64, 287 LABEL_VALUEf, label_info.label_value); 288 289 if (label_info.flags & BCM_MPLS_SPECIAL_LABEL_USE_TABLE_EXP) { 290 soc_reg64_field32_set(unit, EGR_MPLS_SPECIAL_LABEL_CONTROLr, &val64, 291 EXP_SOURCEf, 1); 292 } 293 if (label_info.flags & BCM_MPLS_SPECIAL_LABEL_USE_TABLE_TTL) { 294 soc_reg64_field32_set(unit, EGR_MPLS_SPECIAL_LABEL_CONTROLr, &val64, 295 TTL_SOURCEf, 1); 296 } 297 298 if (bcmi_mpls_special_label_egress_match 299 (unit, label_type, (void *)(&val64_r), (void *)(&val64))) { 300 /* Similar entry exists. Add an refcount */ 301 ptr->special_label_ref_count++; 302 return BCM_E_NONE; 303 } else if (ptr->special_label_ref_count) { 304 return BCM_E_RESOURCE; 305 } 306 307 rv = WRITE_EGR_MPLS_SPECIAL_LABEL_CONTROLr(unit, val64); 308 if (BCM_SUCCESS(rv)) { 309 ptr->special_label_ref_count++; 310 } 311 312 } else if (label_type == bcmMplsSpecialLabelTypeEntropy) { 313 314 /* Only reserved labels are allowed here */ 315 if (label_info.label_value > 0xf) { 316 return BCM_E_PARAM; 317 } 318 319 BCM_IF_ERROR_RETURN(READ_EGR_MPLS_ENTROPY_LABEL_CONTROLr(unit, &val_r)); 320 321 soc_reg_field_set(unit, EGR_MPLS_ENTROPY_LABEL_CONTROLr, &val, 322 EXPf, label_info.exp); 323 soc_reg_field_set(unit, EGR_MPLS_ENTROPY_LABEL_CONTROLr, &val, 324 TTLf, label_info.ttl); 325 326 soc_reg_field_set(unit, EGR_MPLS_ENTROPY_LABEL_CONTROLr, &val, 327 LABEL_OFFSETf, label_info.label_value); 328 329 if (label_info.flags & BCM_MPLS_SPECIAL_LABEL_USE_TABLE_EXP) { 330 soc_reg_field_set(unit, EGR_MPLS_ENTROPY_LABEL_CONTROLr, &val, 331 EXP_SOURCEf, 1); 332 } 333 if (label_info.flags & BCM_MPLS_SPECIAL_LABEL_USE_TABLE_TTL) { 334 soc_reg_field_set(unit, EGR_MPLS_ENTROPY_LABEL_CONTROLr, &val, 335 TTL_SOURCEf, 1); 336 } 337 if (bcmi_mpls_special_label_egress_match 338 (unit, label_type, (void *) (&(val_r)), (void *)(&val))) { 339 /* Similar entry exists. Add an refcount */ 340 ptr->entropy_label_ref_count++; 341 return BCM_E_NONE; 342 } else if (ptr->entropy_label_ref_count) { 343 return BCM_E_RESOURCE; 344 } 345 346 rv = WRITE_EGR_MPLS_ENTROPY_LABEL_CONTROLr(unit, val); 347 if (BCM_SUCCESS(rv)) { 348 ptr->entropy_label_ref_count++; 349 } 350 } 351 352 return rv; 353 } 354 355 /* 356 * Function: 357 * bcmi_mpls_special_label_egress_get 358 * Purpose: 359 * Get an MPLS entropy/special label in 360 * MPLS stack for egress tunnel encap. 361 * Parameters: 362 * unit - (IN) Device Number 363 * label_type - (IN) type of label 364 * label_info - (OUT) Info about special label. 365 * Returns: 366 * BCM_E_XXX 367 */ 368 int 369 bcmi_mpls_special_label_egress_get(int unit, 370 bcm_mpls_special_label_type_t label_type, 371 bcm_mpls_special_label_t *label_info) 372 { 373 int rv = BCM_E_NONE; 374 uint64 val64; 375 uint32 val = 0; 376 bcmi_mpls_special_label_egress_t *ptr; 377 378 COMPILER_64_ZERO(val64); 379 380 ptr = (&(bcmi_special_label_egress_state[unit])); 381 382 if (label_info == NULL) { 383 return BCM_E_PARAM; 384 } 385 386 /* Only Special and entropy labels can be added here*/ 387 if ((label_type != bcmMplsSpecialLabelTypeSpecial) && 388 (label_type != bcmMplsSpecialLabelTypeEntropy)) { 389 390 return BCM_E_PARAM; 391 } 392 393 if (label_type == bcmMplsSpecialLabelTypeSpecial) { 394 if (!(ptr->special_label_ref_count)) { 395 return BCM_E_NOT_FOUND; 396 } 397 398 COMPILER_64_ZERO(val64); 399 BCM_IF_ERROR_RETURN(READ_EGR_MPLS_SPECIAL_LABEL_CONTROLr(unit, &val64)); 400 401 label_info->exp = soc_reg64_field32_get(unit, 402 EGR_MPLS_SPECIAL_LABEL_CONTROLr, val64, EXPf); 403 404 label_info->ttl = soc_reg64_field32_get(unit, 405 EGR_MPLS_SPECIAL_LABEL_CONTROLr, val64, TTLf); 406 407 label_info->label_value = soc_reg64_field32_get(unit, 408 EGR_MPLS_SPECIAL_LABEL_CONTROLr, val64, LABEL_VALUEf); 409 410 if (soc_reg64_field32_get(unit, EGR_MPLS_SPECIAL_LABEL_CONTROLr, val64, 411 EXP_SOURCEf)) { 412 413 label_info->flags |= BCM_MPLS_SPECIAL_LABEL_USE_TABLE_EXP; 414 } 415 416 if (soc_reg64_field32_get(unit, EGR_MPLS_SPECIAL_LABEL_CONTROLr, val64, 417 TTL_SOURCEf)) { 418 419 label_info->flags |= BCM_MPLS_SPECIAL_LABEL_USE_TABLE_TTL; 420 } 421 422 } else if (label_type == bcmMplsSpecialLabelTypeEntropy) { 423 if (!(ptr->entropy_label_ref_count)) { 424 return BCM_E_NOT_FOUND; 425 } 426 427 BCM_IF_ERROR_RETURN(READ_EGR_MPLS_ENTROPY_LABEL_CONTROLr(unit, &val)); 428 429 label_info->exp = soc_reg_field_get(unit, 430 EGR_MPLS_ENTROPY_LABEL_CONTROLr, val, EXPf); 431 432 label_info->ttl = soc_reg_field_get(unit, 433 EGR_MPLS_ENTROPY_LABEL_CONTROLr, val, TTLf); 434 435 label_info->label_value = soc_reg_field_get(unit, 436 EGR_MPLS_ENTROPY_LABEL_CONTROLr, val, LABEL_OFFSETf); 437 438 if (soc_reg_field_get(unit, EGR_MPLS_ENTROPY_LABEL_CONTROLr, val, 439 EXP_SOURCEf)) { 440 441 label_info->flags |= BCM_MPLS_SPECIAL_LABEL_USE_TABLE_EXP; 442 } 443 444 if (soc_reg_field_get(unit, EGR_MPLS_ENTROPY_LABEL_CONTROLr, val, 445 TTL_SOURCEf)) { 446 447 label_info->flags |= BCM_MPLS_SPECIAL_LABEL_USE_TABLE_TTL; 448 } 449 } 450 451 return rv; 452 } 453 454 /* 455 * Function: 456 * bcmi_mpls_special_label_egress_delete 457 * Purpose: 458 * Delete an MPLS entropy/special label in 459 * MPLS stack for egress tunnel encap. 460 * Parameters: 461 * unit - (IN) Device Number 462 * label_type - (IN) type of label 463 * label_info - (IN) Info about special label. 464 * Returns: 465 * BCM_E_XXX 466 */ 467 468 int 469 bcmi_mpls_special_label_egress_delete(int unit, 470 bcm_mpls_special_label_type_t label_type, 471 bcm_mpls_special_label_t label_info) 472 { 473 int rv = BCM_E_NONE; 474 uint64 val64; 475 uint32 val = 0; 476 bcmi_mpls_special_label_egress_t *ptr; 477 478 COMPILER_64_ZERO(val64); 479 480 ptr = (&(bcmi_special_label_egress_state[unit])); 481 482 /* Only Special and entropy labels can be added here*/ 483 if ((label_type != bcmMplsSpecialLabelTypeSpecial) && 484 (label_type != bcmMplsSpecialLabelTypeEntropy)) { 485 486 return BCM_E_PARAM; 487 } 488 489 if (label_type == bcmMplsSpecialLabelTypeSpecial) { 490 491 /* If there is no entry to delete then reutrn not found. */ 492 if (!(ptr->special_label_ref_count)) { 493 return BCM_E_NOT_FOUND; 494 } 495 496 497 COMPILER_64_ZERO(val64); 498 BCM_IF_ERROR_RETURN(READ_EGR_MPLS_SPECIAL_LABEL_CONTROLr(unit, &val64)); 499 500 if (label_info.exp != soc_reg64_field32_get(unit, 501 EGR_MPLS_SPECIAL_LABEL_CONTROLr, val64, EXPf)) { 502 return BCM_E_NOT_FOUND; 503 } 504 505 if (label_info.ttl != soc_reg64_field32_get(unit, 506 EGR_MPLS_SPECIAL_LABEL_CONTROLr, val64, TTLf)) { 507 return BCM_E_NOT_FOUND; 508 } 509 510 if (label_info.label_value != soc_reg64_field32_get(unit, 511 EGR_MPLS_SPECIAL_LABEL_CONTROLr, val64, LABEL_VALUEf)) { 512 return BCM_E_NOT_FOUND; 513 } 514 515 if (soc_reg64_field32_get(unit, EGR_MPLS_SPECIAL_LABEL_CONTROLr, val64, 516 EXP_SOURCEf)) { 517 518 if (!(label_info.flags & BCM_MPLS_SPECIAL_LABEL_USE_TABLE_EXP)) { 519 return BCM_E_NOT_FOUND; 520 } 521 } else if (label_info.flags & BCM_MPLS_SPECIAL_LABEL_USE_TABLE_EXP) { 522 return BCM_E_NOT_FOUND; 523 } 524 525 526 if (soc_reg64_field32_get(unit, EGR_MPLS_SPECIAL_LABEL_CONTROLr, val64, 527 TTL_SOURCEf)) { 528 529 if (!(label_info.flags & BCM_MPLS_SPECIAL_LABEL_USE_TABLE_TTL)) { 530 return BCM_E_NOT_FOUND; 531 } 532 } else if (label_info.flags & BCM_MPLS_SPECIAL_LABEL_USE_TABLE_TTL) { 533 return BCM_E_NOT_FOUND; 534 } 535 536 ptr->special_label_ref_count--; 537 if (ptr->special_label_ref_count > 0) { 538 return BCM_E_NONE; 539 } 540 541 COMPILER_64_ZERO(val64); 542 rv = WRITE_EGR_MPLS_SPECIAL_LABEL_CONTROLr(unit, val64); 543 544 } else { 545 /* If there is no entry to delete then reutrn not found. */ 546 if (!(ptr->entropy_label_ref_count)) { 547 return BCM_E_NOT_FOUND; 548 } 549 550 BCM_IF_ERROR_RETURN(READ_EGR_MPLS_ENTROPY_LABEL_CONTROLr(unit, &val)); 551 552 if (label_info.exp != soc_reg_field_get(unit, 553 EGR_MPLS_ENTROPY_LABEL_CONTROLr, val, EXPf)) { 554 return BCM_E_NOT_FOUND; 555 } 556 557 if (label_info.ttl != soc_reg_field_get(unit, 558 EGR_MPLS_ENTROPY_LABEL_CONTROLr, val, TTLf)) { 559 return BCM_E_NOT_FOUND; 560 } 561 562 if (label_info.label_value != soc_reg_field_get(unit, 563 EGR_MPLS_ENTROPY_LABEL_CONTROLr, val, LABEL_OFFSETf)) { 564 return BCM_E_NOT_FOUND; 565 } 566 567 if (soc_reg_field_get(unit, EGR_MPLS_ENTROPY_LABEL_CONTROLr, val, 568 EXP_SOURCEf)) { 569 570 if (!(label_info.flags & BCM_MPLS_SPECIAL_LABEL_USE_TABLE_EXP)) { 571 return BCM_E_NOT_FOUND; 572 } 573 } else if (label_info.flags & BCM_MPLS_SPECIAL_LABEL_USE_TABLE_EXP) { 574 return BCM_E_NOT_FOUND; 575 } 576 577 578 if (soc_reg_field_get(unit, EGR_MPLS_ENTROPY_LABEL_CONTROLr, val, 579 TTL_SOURCEf)) { 580 581 if (!(label_info.flags & BCM_MPLS_SPECIAL_LABEL_USE_TABLE_TTL)) { 582 return BCM_E_NOT_FOUND; 583 } 584 } else if (label_info.flags & BCM_MPLS_SPECIAL_LABEL_USE_TABLE_TTL) { 585 return BCM_E_NOT_FOUND; 586 } 587 588 589 ptr->entropy_label_ref_count--; 590 if (ptr->entropy_label_ref_count > 0) { 591 return BCM_E_NONE; 592 } 593 val = 0; 594 rv = WRITE_EGR_MPLS_ENTROPY_LABEL_CONTROLr(unit, val); 595 } 596 597 return rv; 598 } 599 /* 600 * Function: 601 * bcmi_mpls_special_label_egress_delete_all 602 * Purpose: 603 * Delete MPLS entropy/special labels in 604 * MPLS stack for egress tunnel encap. 605 * Parameters: 606 * unit - (IN) Device Number 607 * label_type - (IN) type of label 608 * label_info - (IN) Info about special label. 609 * Returns: 610 * BCM_E_XXX 611 */ 612 int 613 bcmi_mpls_special_label_egress_delete_all(int unit) 614 615 { 616 617 uint64 val64; 618 uint32 val = 0; 619 bcmi_mpls_special_label_egress_t *ptr; 620 621 /* pick up the local state. */ 622 ptr = (&(bcmi_special_label_egress_state[unit])); 623 624 /* First delete the special label.*/ 625 COMPILER_64_ZERO(val64); 626 BCM_IF_ERROR_RETURN(WRITE_EGR_MPLS_SPECIAL_LABEL_CONTROLr(unit, val64)); 627 ptr->special_label_ref_count = 0; 628 629 /* Now delete the Entropy label.*/ 630 BCM_IF_ERROR_RETURN(WRITE_EGR_MPLS_ENTROPY_LABEL_CONTROLr(unit, val)); 631 ptr->entropy_label_ref_count = 0; 632 633 return BCM_E_NONE; 634 } 635 /* 636 * Function: 637 * bcmi_mpls_special_label_egress_traverse 638 * Purpose: 639 * Traverse MPLS entropy/special labels in 640 * MPLS stack for egress tunnel encap. 641 * Parameters: 642 * unit - (IN) Device Number 643 * label_type - (IN) type of label 644 * cb - (IN) callback from user. 645 * user_data - (INOUT) user provided data 646 * Returns: 647 * BCM_E_XXX 648 */ 649 650 int 651 bcmi_mpls_special_label_egress_traverse( 652 int unit, 653 bcm_mpls_special_label_egress_traverse_cb cb, 654 void *user_data) 655 { 656 int rv = BCM_E_NONE; 657 bcm_mpls_special_label_t label_info; 658 int i = 0; 659 bcmi_mpls_special_label_egress_t *ptr; 660 bcm_mpls_special_label_type_t label_type[2] = 661 {bcmMplsSpecialLabelTypeSpecial, 662 bcmMplsSpecialLabelTypeEntropy}; 663 664 ptr = (&(bcmi_special_label_egress_state[unit])); 665 666 667 if (cb == NULL) { 668 return BCM_E_PARAM; 669 } 670 671 /* run loop for both label types to get info */ 672 for (; i<2; i++) { 673 674 if (label_type[i] == bcmMplsSpecialLabelTypeSpecial) { 675 if (ptr->special_label_ref_count == 0) { 676 continue; 677 } 678 } else { 679 if (ptr->entropy_label_ref_count == 0) { 680 continue; 681 } 682 } 683 sal_memset(&label_info, 0, sizeof(label_info)); 684 685 BCM_IF_ERROR_RETURN( 686 bcmi_mpls_special_label_egress_get(unit, 687 label_type[i], &label_info)); 688 689 rv = cb(unit, &(label_type[i]), &label_info, user_data); 690 #ifdef BCM_CB_ABORT_ON_ERR 691 if (BCM_FAILURE(rv) && SOC_CB_ABORT_ON_ERR(unit)) { 692 return rv; 693 } 694 #endif 695 } 696 697 return rv; 698 } 699 700 /* 701 * Function: 702 * bcmi_mpls_special_label_push_action_set 703 * Description: 704 * Set mpls push action in MPLS objects. 705 * going into MPLS tunnel. 706 * 707 * Parameters: 708 * unit - (IN) unit number 709 * element - (IN) MPLS object 710 * push_type - (OUT) push action 711 * Return Value: 712 * BCM_E_XXX 713 * Notes: 714 */ 715 int 716 bcmi_mpls_special_label_push_action_set(int unit, 717 bcm_mpls_special_label_push_element_t *element, 718 bcm_mpls_special_label_push_type_t push_type) 719 { 720 int vp=0xFFFF; 721 ing_dvp_table_entry_t dvp; 722 bcm_if_t nh_index; 723 egr_mpls_vc_and_swap_label_table_entry_t vc_entry; 724 egr_l3_next_hop_entry_t egr_nh; 725 int rv = BCM_E_NONE; 726 int vc_swap_idx = 0, new_vc_swap_index = -1; 727 _bcm_tr_mpls_bookkeeping_t *mpls_info = MPLS_INFO(unit); 728 int action = 0; 729 730 if (element == NULL) { 731 return BCM_E_PARAM; 732 } 733 734 if (push_type > bcmMplsSpecialLabelPushSpecialPlusEntropy) { 735 return BCM_E_PARAM; 736 } 737 738 if (element->gport != BCM_GPORT_INVALID) { 739 740 if (!BCM_GPORT_IS_MPLS_PORT(element->gport)) { 741 return BCM_E_PARAM; 742 } 743 744 vp = BCM_GPORT_MPLS_PORT_ID_GET(element->gport); 745 746 if (vp >= soc_mem_index_count(unit, SOURCE_VPm)) { 747 return BCM_E_PARAM; 748 } 749 750 BCM_IF_ERROR_RETURN(READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp, &dvp)); 751 752 /* Get nh index from the DVP table */ 753 nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, NEXT_HOP_INDEXf); 754 } else { 755 756 if (BCM_XGS3_L3_EGRESS_IDX_VALID(unit, element->egr_obj_id) || 757 BCM_XGS3_DVP_EGRESS_IDX_VALID(unit, element->egr_obj_id)) { 758 759 /* Extract next hop index from unipath egress object. */ 760 if (BCM_XGS3_L3_EGRESS_IDX_VALID(unit, element->egr_obj_id)) { 761 nh_index = element->egr_obj_id - BCM_XGS3_EGRESS_IDX_MIN(unit); 762 } else { 763 nh_index = element->egr_obj_id - BCM_XGS3_DVP_EGRESS_IDX_MIN(unit); 764 } 765 } else { 766 return BCM_E_PARAM; 767 } 768 } 769 770 BCM_IF_ERROR_RETURN(soc_mem_read(unit, EGR_L3_NEXT_HOPm, MEM_BLOCK_ANY, 771 nh_index, &egr_nh)); 772 773 /* First check if this is the correct MPLS next hop */ 774 if (soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, DATA_TYPEf) != 1) { 775 return BCM_E_PARAM; 776 } 777 778 vc_swap_idx = soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, 779 MPLS__VC_AND_SWAP_INDEXf); 780 781 BCM_IF_ERROR_RETURN(soc_mem_read(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 782 MEM_BLOCK_ANY, vc_swap_idx, &vc_entry)); 783 784 785 soc_mem_field32_set(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 786 &vc_entry, SPECIAL_LABEL_PUSH_TYPEf, push_type); 787 788 /* Action for sw state management */ 789 action = mpls_info->egr_vc_swap_lbl_action[vc_swap_idx]; 790 791 /* Now we need to look if someone has similar entry like this */ 792 if ( mpls_info->vc_swap_ref_count[vc_swap_idx] > 1) { 793 794 /* we have more objects pointing to it. so we can not update it just like that. 795 * Look for some similar entry. 796 * The new index is ref counted inside the below method only. 797 * just remove the ref-count from old index once everything is set. 798 */ 799 BCM_IF_ERROR_RETURN(_bcm_tr_mpls_get_vc_and_swap_table_index (unit, 0, 800 NULL, NULL, NULL, &vc_entry, 801 action, 802 &new_vc_swap_index)); 803 804 if ((new_vc_swap_index != -1) && (new_vc_swap_index != vc_swap_idx)) { 805 /* write vc_entry into the new index */ 806 rv = soc_mem_write(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 807 MEM_BLOCK_ALL, new_vc_swap_index, &vc_entry); 808 809 if (BCM_FAILURE(rv)) { 810 goto cleanup; 811 } 812 813 /* Got new index. Point NH to it.*/ 814 soc_EGR_L3_NEXT_HOPm_field32_set(unit, &egr_nh, 815 MPLS__VC_AND_SWAP_INDEXf, new_vc_swap_index); 816 817 /* Lock the memory before writing. */ 818 soc_mem_lock(unit, EGR_L3_NEXT_HOPm); 819 820 /* Write new index in NH */ 821 rv = soc_mem_write(unit, EGR_L3_NEXT_HOPm, MEM_BLOCK_ALL, 822 nh_index, &egr_nh); 823 824 soc_mem_unlock(unit, EGR_L3_NEXT_HOPm); 825 if (BCM_FAILURE(rv)) { 826 goto cleanup; 827 } 828 } 829 if (new_vc_swap_index != -1) { 830 /* Remove the reference from old index */ 831 (void)_bcm_tr_mpls_vc_and_swap_ref_count_adjust(unit, 832 vc_swap_idx, -1); 833 834 mpls_info->egr_vc_swap_lbl_action[new_vc_swap_index] = action; 835 } 836 } else { 837 838 BCM_IF_ERROR_RETURN(soc_mem_write(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 839 MEM_BLOCK_ALL, vc_swap_idx, &vc_entry)); 840 } 841 842 return rv; 843 844 cleanup: 845 846 if (new_vc_swap_index != -1) { 847 (void)_bcm_tr_mpls_vc_and_swap_ref_count_adjust (unit, 848 new_vc_swap_index, -1); 849 (void) _bcm_tr_mpls_vc_and_swap_table_index_reset (unit, 850 new_vc_swap_index); 851 } 852 853 854 return rv; 855 } 856 857 /* 858 * Function: 859 * bcmi_mpls_special_label_push_action_get 860 * Description: 861 * Get mpls push action in MPLS objects. 862 * going into MPLS tunnel. 863 * 864 * Parameters: 865 * unit - (IN) unit number 866 * element - (IN) MPLS object 867 * push_type - (OUT) push action 868 * Return Value: 869 * BCM_E_XXX 870 * Notes: 871 */ 872 int 873 bcmi_mpls_special_label_push_action_get(int unit, 874 bcm_mpls_special_label_push_element_t *element, 875 bcm_mpls_special_label_push_type_t *push_type) 876 { 877 int vp=0xFFFF; 878 ing_dvp_table_entry_t dvp; 879 bcm_if_t nh_index; 880 egr_mpls_vc_and_swap_label_table_entry_t vc_entry; 881 egr_l3_next_hop_entry_t egr_nh; 882 int vc_swap_idx = 0; 883 884 if (element == NULL) { 885 return BCM_E_PARAM; 886 } 887 888 if (push_type == NULL) { 889 return BCM_E_PARAM; 890 } 891 892 if (element->gport != BCM_GPORT_INVALID) { 893 894 if (!BCM_GPORT_IS_MPLS_PORT(element->gport)) { 895 return BCM_E_PARAM; 896 } 897 898 vp = BCM_GPORT_MPLS_PORT_ID_GET(element->gport); 899 900 if (vp >= soc_mem_index_count(unit, SOURCE_VPm)) { 901 return BCM_E_PARAM; 902 } 903 904 BCM_IF_ERROR_RETURN(READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp, &dvp)); 905 906 /* Get nh index from the DVP table */ 907 nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, NEXT_HOP_INDEXf); 908 } else { 909 nh_index = element->egr_obj_id; 910 911 if (BCM_XGS3_L3_EGRESS_IDX_VALID(unit, element->egr_obj_id) || 912 BCM_XGS3_DVP_EGRESS_IDX_VALID(unit, element->egr_obj_id)) { 913 914 /* Extract next hop index from unipath egress object. */ 915 if (BCM_XGS3_L3_EGRESS_IDX_VALID(unit, element->egr_obj_id)) { 916 nh_index = element->egr_obj_id - BCM_XGS3_EGRESS_IDX_MIN(unit); 917 } else { 918 nh_index = element->egr_obj_id - BCM_XGS3_DVP_EGRESS_IDX_MIN(unit); 919 } 920 } else { 921 return BCM_E_PARAM; 922 } 923 } 924 925 sal_memset(&egr_nh, 0, sizeof(egr_l3_next_hop_entry_t)); 926 BCM_IF_ERROR_RETURN (soc_mem_read(unit, EGR_L3_NEXT_HOPm, MEM_BLOCK_ANY, 927 nh_index, &egr_nh)); 928 929 /* First check if this is the correct MPLS next hop */ 930 if (soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, DATA_TYPEf) != 1) { 931 return BCM_E_PARAM; 932 } 933 934 vc_swap_idx = soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, 935 MPLS__VC_AND_SWAP_INDEXf); 936 937 BCM_IF_ERROR_RETURN (soc_mem_read(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 938 MEM_BLOCK_ANY, vc_swap_idx, &vc_entry)); 939 940 *push_type = soc_mem_field32_get(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 941 &vc_entry, SPECIAL_LABEL_PUSH_TYPEf); 942 943 return BCM_E_NONE; 944 } 945 946 /* 947 * Function: 948 * bcmi_mpls_special_label_move_entries 949 * Description: 950 * In order to keep precedence of labels, we 951 * need to move entries. 952 * 953 * Parameters: 954 * unit - (IN) unit number 955 * from - (IN) Move from 956 * to - (OUT) Move to 957 * Return Value: 958 * BCM_E_XXX 959 * Notes: 960 */ 961 int 962 bcmi_mpls_special_label_move_entries(int unit, int from, int to) 963 { 964 965 special_label_control_entry_t spl_label_entry; 966 soc_mem_t mem = SPECIAL_LABEL_CONTROLm; 967 int i = 0; 968 uint32 total_moves = 0; 969 int num_entry; 970 bcmi_mpls_special_label_control_t *ptr; 971 972 ptr = bcmi_special_label_precedence_state[unit]; 973 974 total_moves = ((to>from) ? (to - from) : (from - to)); 975 num_entry = soc_mem_index_count(unit, SPECIAL_LABEL_CONTROLm); 976 if (total_moves > num_entry) { 977 return BCM_E_PARAM; 978 } 979 980 if (from != -1) { 981 if (to < from) { 982 /* move entries up first*/ 983 while (total_moves) { 984 985 BCM_IF_ERROR_RETURN( 986 soc_mem_read(unit, mem, MEM_BLOCK_ALL, (to + i + 1), 987 &spl_label_entry)); 988 989 BCM_IF_ERROR_RETURN( 990 soc_mem_write(unit, mem, MEM_BLOCK_ALL, (to + i), &spl_label_entry)); 991 992 sal_memcpy((&(ptr[to + i])), (&(ptr[to + i + 1])), 993 sizeof(bcmi_mpls_special_label_control_t)); 994 995 total_moves--; 996 i++; 997 } 998 } else { 999 while (total_moves) { 1000 1001 BCM_IF_ERROR_RETURN( 1002 soc_mem_read(unit, mem, MEM_BLOCK_ALL, 1003 (to - i - 1), &spl_label_entry)); 1004 1005 BCM_IF_ERROR_RETURN( 1006 soc_mem_write(unit, mem, MEM_BLOCK_ALL, 1007 (to - i), &spl_label_entry)); 1008 1009 sal_memcpy((&(ptr[to - i])), (&(ptr[to - i - 1])), 1010 sizeof(bcmi_mpls_special_label_control_t)); 1011 1012 total_moves--; 1013 i++; 1014 } 1015 } 1016 sal_memset((&(ptr[from])), 0, 1017 sizeof(bcmi_mpls_special_label_control_t)); 1018 } 1019 1020 return BCM_E_NONE; 1021 } 1022 1023 /* 1024 * Function: 1025 * bcmi_mpls_special_label_make_slot 1026 * Description: 1027 * Make slot for label identifiers in order of precedence. 1028 * 1029 * Parameters: 1030 * unit - (IN) unit number 1031 * mpls_label - (IN) label value 1032 * mpls_label_mask - (IN) Mask of label 1033 * slot - (OUT) slot to add entry 1034 * Return Value: 1035 * BCM_E_XXX 1036 * Notes: 1037 */ 1038 int 1039 bcmi_mpls_special_label_make_slot(int unit, uint32 mpls_label, 1040 uint32 mpls_label_mask, int *slot) 1041 { 1042 1043 soc_mem_t mem; 1044 bcmi_mpls_special_label_control_t *ptr; 1045 int num_entry = 0, i; 1046 int free_slot = -1, move_start = -1; 1047 1048 mem = SPECIAL_LABEL_CONTROLm; 1049 ptr = bcmi_special_label_precedence_state[unit]; 1050 1051 num_entry = soc_mem_index_count(unit, mem); 1052 1053 /* First get the slot where it should go */ 1054 for (i = 0; i < num_entry; i++) { 1055 1056 if (!(ptr[i].valid)) { 1057 if (free_slot == -1) { 1058 free_slot = i; 1059 } 1060 continue; 1061 } 1062 1063 if ((mpls_label & mpls_label_mask) < 1064 (ptr[i].label_value & ptr[i].label_mask)) { 1065 continue; 1066 } 1067 1068 if ((mpls_label & mpls_label_mask) == 1069 (ptr[i].label_value & ptr[i].label_mask)) { 1070 if (mpls_label < ptr[i].label_value) { 1071 continue; 1072 } 1073 } 1074 1075 if (free_slot != -1) { 1076 break; 1077 } 1078 1079 /* if we are here then we have got the slot where we can put values*/ 1080 if (move_start == -1) { 1081 move_start = i; 1082 } 1083 1084 } 1085 1086 if (free_slot == -1) { 1087 /* we do not have any free slot left */ 1088 return BCM_E_RESOURCE; 1089 } 1090 1091 /* If there is nothing to move then just return free index */ 1092 *slot = ((move_start == -1) ? free_slot : move_start); 1093 1094 /* When free index is before move index, then we need to move 1095 * one less entry as logic will give index to smaller entry. 1096 * In case free index is after move index, we will have to manage 1097 * entries from move index so we are okay. 1098 */ 1099 move_start = ((free_slot < move_start) ? (move_start - 1) : move_start); 1100 bcmi_mpls_special_label_move_entries(unit, move_start, free_slot); 1101 1102 return BCM_E_NONE; 1103 } 1104 1105 1106 /* 1107 * Function: 1108 * bcmi_mpls_special_label_match_entry 1109 * Description: 1110 * Match incoming entry with label identifiers in h/w. 1111 * 1112 * Parameters: 1113 * unit - (IN) unit number 1114 * label type - (IN) Type of label to match 1115 * mpls_label - (IN) label value 1116 * mpls_label_mask - (IN) Mask of label 1117 * slot - (OUT) matched slot 1118 * Return Value: 1119 * BCM_E_XXX 1120 * Notes: 1121 */ 1122 1123 int 1124 bcmi_mpls_special_label_match_entry(int unit, int label_type, uint32 mpls_label, 1125 uint32 mpls_label_mask, int *slot) 1126 { 1127 1128 soc_mem_t mem; 1129 int index_min = 0; 1130 int index_max = 0; 1131 bcmi_mpls_special_label_control_t *ptr; 1132 int i = 0; 1133 1134 mem = SPECIAL_LABEL_CONTROLm; 1135 index_min = soc_mem_index_min(unit, mem); 1136 index_max = soc_mem_index_max(unit, mem); 1137 1138 ptr = bcmi_special_label_precedence_state[unit]; 1139 1140 for (i = index_min; i <= index_max; i++) { 1141 1142 if (!(ptr[i].valid)) { 1143 continue; 1144 } 1145 1146 if (ptr[i].label_type != label_type) { 1147 continue; 1148 } 1149 1150 if ((mpls_label == ptr[i].label_value) && 1151 (mpls_label_mask == ptr[i].label_mask)) { 1152 *slot = i; 1153 return BCM_E_NONE; 1154 } 1155 1156 } 1157 1158 return BCM_E_NOT_FOUND; 1159 } 1160 /* 1161 * Function: 1162 * bcmi_mpls_special_label_get_slot 1163 * Description: 1164 * Get slot to add identifier entry of special label. 1165 * 1166 * Parameters: 1167 * unit - (IN) unit number 1168 * label_value - (IN) MPLS Label 1169 * label_mask - (IN) MPLS mask 1170 * slot - (OUT) slot number 1171 * Return Value: 1172 * BCM_E_XXX 1173 * Notes: 1174 */ 1175 int 1176 bcmi_mpls_special_label_get_slot(int unit, int label_type, 1177 bcm_mpls_special_label_t label_info, uint32 mpls_label, 1178 uint32 mpls_label_mask, int *slot, int *new_slot) 1179 { 1180 int rv = BCM_E_NONE; 1181 special_label_control_entry_t entry; 1182 1183 /* first match the entry and check if matching entry is there */ 1184 rv = bcmi_mpls_special_label_match_entry(unit, label_type, 1185 mpls_label, mpls_label_mask, slot); 1186 if (BCM_SUCCESS(rv)) { 1187 /* Match the complete entry */ 1188 BCM_IF_ERROR_RETURN(READ_SPECIAL_LABEL_CONTROLm(unit, MEM_BLOCK_ALL, 1189 *slot, &entry)); 1190 1191 if (soc_SPECIAL_LABEL_CONTROLm_field32_get(unit, &entry, 1192 CURRENT_LABEL_HASH_ACTIONf)) { 1193 1194 if (!(label_info.flags & 1195 BCM_MPLS_SPECIAL_LABEL_CURR_LABEL_EXCLUDE_HASH)) { 1196 return BCM_E_EXISTS; 1197 } 1198 } else if (label_info.flags & 1199 BCM_MPLS_SPECIAL_LABEL_CURR_LABEL_EXCLUDE_HASH) { 1200 1201 return BCM_E_EXISTS; 1202 } 1203 1204 1205 if (soc_SPECIAL_LABEL_CONTROLm_field32_get(unit, &entry, 1206 NEXT_LABEL_HASH_ACTIONf)) { 1207 1208 if (!(label_info.flags & 1209 BCM_MPLS_SPECIAL_LABEL_NEXT_LABEL_EXCLUDE_HASH)) { 1210 return BCM_E_EXISTS; 1211 } 1212 } else if (label_info.flags & 1213 BCM_MPLS_SPECIAL_LABEL_NEXT_LABEL_EXCLUDE_HASH) { 1214 return BCM_E_EXISTS; 1215 } 1216 1217 if (soc_SPECIAL_LABEL_CONTROLm_field32_get(unit, &entry, 1218 CURRENT_LABEL_LOOKUP_ACTIONf)) { 1219 1220 if (!(label_info.flags & 1221 BCM_MPLS_SPECIAL_LABEL_CURR_LABEL_EXCLUDE_LKUP)) { 1222 return BCM_E_EXISTS; 1223 } 1224 } else if (label_info.flags & 1225 BCM_MPLS_SPECIAL_LABEL_CURR_LABEL_EXCLUDE_LKUP) { 1226 return BCM_E_EXISTS; 1227 } 1228 1229 1230 if (soc_SPECIAL_LABEL_CONTROLm_field32_get(unit, &entry, 1231 NEXT_LABEL_LOOKUP_ACTIONf)) { 1232 1233 if (!(label_info.flags & 1234 BCM_MPLS_SPECIAL_LABEL_NEXT_LABEL_EXCLUDE_LKUP)) { 1235 return BCM_E_EXISTS; 1236 } 1237 } else if (label_info.flags & 1238 BCM_MPLS_SPECIAL_LABEL_NEXT_LABEL_EXCLUDE_LKUP) { 1239 return BCM_E_EXISTS; 1240 } 1241 1242 1243 if (soc_SPECIAL_LABEL_CONTROLm_field32_get(unit, &entry, 1244 LABEL_INHERIT_ENf)) { 1245 1246 if (!(label_info.flags & 1247 BCM_MPLS_SPECIAL_LABEL_INHERITANCE_ENABLE)) { 1248 return BCM_E_EXISTS; 1249 } 1250 } else if (label_info.flags & 1251 BCM_MPLS_SPECIAL_LABEL_INHERITANCE_ENABLE) { 1252 return BCM_E_EXISTS; 1253 } 1254 1255 } 1256 1257 if (rv != BCM_E_NOT_FOUND) { 1258 *new_slot = 0; 1259 return rv; 1260 } 1261 1262 /* 1263 * We have not got matching entry. 1264 * we need to check if we can fit it somewhere. 1265 */ 1266 rv = bcmi_mpls_special_label_make_slot(unit, mpls_label, mpls_label_mask, 1267 slot); 1268 *new_slot = 1; 1269 return rv; 1270 } 1271 1272 /* 1273 * Function: 1274 * bcmi_mpls_special_label_identifier_add 1275 * Description: 1276 * Add identifier entry of special label. 1277 * 1278 * Parameters: 1279 * unit - (IN) unit number 1280 * label_type - (IN) MPLS Label 1281 * label_info - (IN) MPLS Gport 1282 * Return Value: 1283 * BCM_E_XXX 1284 * Notes: 1285 */ 1286 int 1287 bcmi_mpls_special_label_identifier_add(int unit, 1288 bcm_mpls_special_label_type_t label_type, 1289 bcm_mpls_special_label_t label_info) 1290 { 1291 1292 uint32 mpls_label = 0, mpls_label_mask = 0; 1293 int rv = BCM_E_NONE; 1294 special_label_control_entry_t entry; 1295 int slot = -1, new_slot = -1; 1296 bcmi_mpls_special_label_control_t *ptr; 1297 int bos_value = 0; 1298 int bos_mask = 0; 1299 1300 if (!BCMI_MPLS_LABEL_ID_VALID(label_info.label_value)) { 1301 return BCM_E_PARAM; 1302 } 1303 1304 if (!BCMI_MPLS_EXP_VALID(label_info.exp)) { 1305 return BCM_E_PARAM; 1306 } 1307 1308 if (!BCMI_MPLS_TTL_VALID(label_info.ttl)) { 1309 return BCM_E_PARAM; 1310 } 1311 1312 /* Check for range of mask also. */ 1313 if (label_info.label_mask > BCMI_MPLS_LABEL_MASK_MAX) { 1314 return BCM_E_PARAM; 1315 } 1316 1317 if (label_info.exp_mask > BCMI_MPLS_EXP_MASK_MAX) { 1318 return BCM_E_PARAM; 1319 } 1320 1321 if (label_info.ttl_mask > BCMI_MPLS_TTL_MASK_MAX) { 1322 return BCM_E_PARAM; 1323 } 1324 1325 if (label_type > bcmMplsSpecialLabelTypeEntropy) { 1326 return BCM_E_PARAM; 1327 } 1328 1329 ptr = bcmi_special_label_precedence_state[unit]; 1330 1331 bos_value = ((label_info.flags & BCM_MPLS_SPECIAL_LABEL_BOS_PRESENT) ? 1:0); 1332 bos_mask = ((label_info.flags & BCM_MPLS_SPECIAL_LABEL_BOS_MASKED) ? 1:0); 1333 1334 mpls_label = BCMI_MPLS_CONSTRUCT_LABEL( 1335 label_info.label_value,label_info.exp,label_info.ttl, 1336 bos_value); 1337 1338 mpls_label_mask = BCMI_MPLS_CONSTRUCT_LABEL( 1339 label_info.label_mask, label_info.exp_mask, 1340 label_info.ttl_mask, 1341 bos_mask); 1342 1343 /* get matching entry or new slot for adding new entry */ 1344 BCM_IF_ERROR_RETURN(bcmi_mpls_special_label_get_slot(unit, label_type, label_info, 1345 mpls_label, mpls_label_mask, &slot, &new_slot)); 1346 1347 /* Check if we found some old slot */ 1348 if (!new_slot) { 1349 ptr[slot].ref_count++; 1350 return BCM_E_NONE; 1351 } 1352 /* For new slots, start writing the entry */ 1353 sal_memset(&entry, 0, sizeof(special_label_control_entry_t)); 1354 soc_SPECIAL_LABEL_CONTROLm_field32_set(unit, &entry, LABEL_VALUEf, 1355 mpls_label); 1356 soc_SPECIAL_LABEL_CONTROLm_field32_set(unit, &entry, LABEL_VALUE_MASKf, 1357 mpls_label_mask); 1358 1359 soc_SPECIAL_LABEL_CONTROLm_field32_set(unit, &entry, CURRENT_LABEL_TYPEf, 1360 label_type); 1361 1362 if (label_info.flags & BCM_MPLS_SPECIAL_LABEL_CURR_LABEL_EXCLUDE_HASH) { 1363 soc_SPECIAL_LABEL_CONTROLm_field32_set(unit, &entry, 1364 CURRENT_LABEL_HASH_ACTIONf, 1); 1365 } 1366 1367 if (label_info.flags & BCM_MPLS_SPECIAL_LABEL_NEXT_LABEL_EXCLUDE_HASH) { 1368 soc_SPECIAL_LABEL_CONTROLm_field32_set(unit, &entry, 1369 NEXT_LABEL_HASH_ACTIONf, 1); 1370 } 1371 1372 if (label_info.flags & BCM_MPLS_SPECIAL_LABEL_CURR_LABEL_EXCLUDE_LKUP) { 1373 soc_SPECIAL_LABEL_CONTROLm_field32_set(unit, &entry, 1374 CURRENT_LABEL_LOOKUP_ACTIONf, 1); 1375 } 1376 1377 if (label_info.flags & BCM_MPLS_SPECIAL_LABEL_NEXT_LABEL_EXCLUDE_LKUP) { 1378 soc_SPECIAL_LABEL_CONTROLm_field32_set(unit, &entry, 1379 NEXT_LABEL_LOOKUP_ACTIONf, 1); 1380 } 1381 if (label_info.flags & BCM_MPLS_SPECIAL_LABEL_INHERITANCE_ENABLE) { 1382 soc_SPECIAL_LABEL_CONTROLm_field32_set(unit, &entry, 1383 LABEL_INHERIT_ENf, 1); 1384 } 1385 1386 if (label_type == bcmMplsSpecialLabelTypeNone) { 1387 if (label_info.flags & BCM_MPLS_SPECIAL_LABEL_INHERITANCE_ENABLE) { 1388 soc_SPECIAL_LABEL_CONTROLm_field32_set(unit, &entry, 1389 INHERITANCE_TYPEf, 0); 1390 } 1391 } else { 1392 if (label_info.flags & BCM_MPLS_SPECIAL_LABEL_INHERITANCE_ENABLE) { 1393 soc_SPECIAL_LABEL_CONTROLm_field32_set(unit, &entry, 1394 INHERITANCE_TYPEf, 1); 1395 } 1396 } 1397 1398 soc_SPECIAL_LABEL_CONTROLm_field32_set(unit, &entry, VALIDf, 1); 1399 1400 rv = WRITE_SPECIAL_LABEL_CONTROLm(unit, MEM_BLOCK_ALL, slot, &entry); 1401 if (BCM_SUCCESS(rv)) { 1402 /* Clear the s/w state first */ 1403 sal_memset((&(ptr[slot])), 0, sizeof(bcmi_mpls_special_label_control_t)); 1404 1405 if (rv == BCM_E_NONE) { 1406 ptr[slot].label_value = mpls_label; 1407 ptr[slot].label_mask = mpls_label_mask; 1408 ptr[slot].label_type = label_type; 1409 ptr[slot].valid = 1; 1410 ptr[slot].ref_count = 1; 1411 } 1412 } 1413 1414 return rv; 1415 } 1416 1417 /* 1418 * Function: 1419 * bcmi_mpls_special_label_identifier_get 1420 * Description: 1421 * Get identifier entry of special label. 1422 * 1423 * Parameters: 1424 * unit - (IN) unit number 1425 * label_type - (IN) MPLS Label 1426 * label_info - (IN) MPLS Gport 1427 * Return Value: 1428 * BCM_E_XXX 1429 * Notes: 1430 */ 1431 int 1432 bcmi_mpls_special_label_identifier_get(int unit, 1433 bcm_mpls_special_label_type_t label_type, 1434 bcm_mpls_special_label_t *label_info) 1435 { 1436 int slot = -1; 1437 special_label_control_entry_t entry; 1438 uint32 mpls_label = 0; 1439 uint32 mpls_label_mask = 0; 1440 int bos_value = 0; 1441 int bos_mask = 0; 1442 1443 if (label_info == NULL) { 1444 return BCM_E_PARAM; 1445 } 1446 1447 if (label_type > bcmMplsSpecialLabelTypeEntropy) { 1448 return BCM_E_PARAM; 1449 } 1450 1451 bos_value = 1452 ((label_info->flags & BCM_MPLS_SPECIAL_LABEL_BOS_PRESENT) ? 1:0); 1453 bos_mask = 1454 ((label_info->flags & BCM_MPLS_SPECIAL_LABEL_BOS_MASKED) ? 1:0); 1455 1456 mpls_label = BCMI_MPLS_CONSTRUCT_LABEL( 1457 label_info->label_value, label_info->exp, label_info->ttl, 1458 bos_value); 1459 1460 mpls_label_mask = BCMI_MPLS_CONSTRUCT_LABEL( 1461 label_info->label_mask, label_info->exp_mask, 1462 label_info->ttl_mask, 1463 bos_mask); 1464 1465 /* get matching entry or new slot for adding new entry */ 1466 BCM_IF_ERROR_RETURN(bcmi_mpls_special_label_match_entry(unit, label_type, 1467 mpls_label, mpls_label_mask, &slot)); 1468 1469 sal_memset(&entry, 0, sizeof(special_label_control_entry_t)); 1470 BCM_IF_ERROR_RETURN(READ_SPECIAL_LABEL_CONTROLm(unit, MEM_BLOCK_ALL, 1471 slot, &entry)); 1472 1473 if (soc_SPECIAL_LABEL_CONTROLm_field32_get(unit, &entry, 1474 CURRENT_LABEL_HASH_ACTIONf)) { 1475 1476 label_info->flags |= BCM_MPLS_SPECIAL_LABEL_CURR_LABEL_EXCLUDE_HASH; 1477 } 1478 1479 if (soc_SPECIAL_LABEL_CONTROLm_field32_get(unit, &entry, 1480 NEXT_LABEL_HASH_ACTIONf)) { 1481 label_info->flags |= BCM_MPLS_SPECIAL_LABEL_NEXT_LABEL_EXCLUDE_HASH; 1482 } 1483 1484 if (soc_SPECIAL_LABEL_CONTROLm_field32_get(unit, &entry, 1485 CURRENT_LABEL_LOOKUP_ACTIONf)) { 1486 1487 label_info->flags |= BCM_MPLS_SPECIAL_LABEL_CURR_LABEL_EXCLUDE_LKUP; 1488 } 1489 1490 if (soc_SPECIAL_LABEL_CONTROLm_field32_get(unit, &entry, 1491 NEXT_LABEL_LOOKUP_ACTIONf)) { 1492 label_info->flags |= BCM_MPLS_SPECIAL_LABEL_NEXT_LABEL_EXCLUDE_LKUP; 1493 } 1494 1495 if (soc_SPECIAL_LABEL_CONTROLm_field32_get(unit, &entry, 1496 LABEL_INHERIT_ENf)) { 1497 label_info->flags |= BCM_MPLS_SPECIAL_LABEL_INHERITANCE_ENABLE; 1498 } 1499 1500 if (soc_SPECIAL_LABEL_CONTROLm_field32_get(unit, &entry, 1501 INHERITANCE_TYPEf)) { 1502 1503 label_info->flags |= BCM_MPLS_SPECIAL_LABEL_INHERITANCE_ENABLE; 1504 } 1505 1506 return BCM_E_NONE; 1507 } 1508 1509 /* 1510 * Function: 1511 * bcmi_mpls_special_label_identifier_delete 1512 * Description: 1513 * Delete identifiers of special label. 1514 * 1515 * Parameters: 1516 * unit - (IN) unit number 1517 * label_type - (IN) MPLS Label 1518 * label_info - (IN) MPLS Gport 1519 * Return Value: 1520 * BCM_E_XXX 1521 * Notes: 1522 */ 1523 int 1524 bcmi_mpls_special_label_identifier_delete(int unit, 1525 bcm_mpls_special_label_type_t label_type, 1526 bcm_mpls_special_label_t label_info) 1527 { 1528 int slot = -1; 1529 int rv = BCM_E_NONE; 1530 special_label_control_entry_t entry; 1531 bcmi_mpls_special_label_control_t *ptr; 1532 uint32 mpls_label = 0; 1533 uint32 mpls_label_mask = 0; 1534 int bos_value = 0; 1535 int bos_mask = 0; 1536 1537 ptr = bcmi_special_label_precedence_state[unit]; 1538 1539 if (label_type > bcmMplsSpecialLabelTypeEntropy) { 1540 return BCM_E_PARAM; 1541 } 1542 1543 bos_value = ((label_info.flags & BCM_MPLS_SPECIAL_LABEL_BOS_PRESENT) ? 1:0); 1544 bos_mask = ((label_info.flags & BCM_MPLS_SPECIAL_LABEL_BOS_MASKED) ? 1:0); 1545 1546 mpls_label = BCMI_MPLS_CONSTRUCT_LABEL( 1547 label_info.label_value,label_info.exp,label_info.ttl, 1548 bos_value); 1549 1550 mpls_label_mask = BCMI_MPLS_CONSTRUCT_LABEL( 1551 label_info.label_mask, label_info.exp_mask, 1552 label_info.ttl_mask, 1553 bos_mask); 1554 1555 /* get matching entry or new slot for adding new entry */ 1556 BCM_IF_ERROR_RETURN(bcmi_mpls_special_label_match_entry(unit, label_type, 1557 mpls_label, mpls_label_mask, &slot)); 1558 1559 ptr[slot].ref_count--; 1560 if (ptr[slot].ref_count > 0) { 1561 /* more applications are still using this. Do not remove*/ 1562 return BCM_E_NONE; 1563 } 1564 /* If we are here then nobody else has programmed this*/ 1565 sal_memset(&(ptr[slot]), 0, sizeof(bcmi_mpls_special_label_control_t)); 1566 /* Make the s/w entry as 0 */ 1567 sal_memset(&entry, 0, sizeof(special_label_control_entry_t)); 1568 /* Write the cleared entry into h/w */ 1569 rv = WRITE_SPECIAL_LABEL_CONTROLm(unit, MEM_BLOCK_ALL, slot, &entry); 1570 1571 return rv; 1572 } 1573 1574 /* 1575 * Function: 1576 * bcmi_mpls_special_label_identifier_delete_all 1577 * Description: 1578 * Delete all identifiers ofs pecial labels. 1579 * 1580 * Parameters: 1581 * unit - (IN) unit number 1582 * label_type - (IN) MPLS Label 1583 * label_info - (IN) MPLS Gport 1584 * Return Value: 1585 * BCM_E_XXX 1586 * Notes: 1587 */ 1588 int 1589 bcmi_mpls_special_label_identifier_delete_all(int unit) 1590 { 1591 int i=0; 1592 special_label_control_entry_t entry; 1593 bcmi_mpls_special_label_control_t *ptr; 1594 int num_entry; 1595 1596 num_entry = soc_mem_index_count(unit, SPECIAL_LABEL_CONTROLm); 1597 1598 ptr = bcmi_special_label_precedence_state[unit]; 1599 1600 for (; i<num_entry; i++) { 1601 if (ptr[i].cancun_added) { 1602 /* if this is added by cancun then 1603 make ref_count to 1 and do not do much. */ 1604 ptr[i].ref_count = 1; 1605 continue; 1606 } 1607 1608 /* If we are here then nobody else has programmed this*/ 1609 sal_memset(&(ptr[i]), 0, sizeof(bcmi_mpls_special_label_control_t)); 1610 /* Make the s/w entry as 0 */ 1611 sal_memset(&entry, 0, sizeof(special_label_control_entry_t)); 1612 /* Write the cleared entry into h/w */ 1613 BCM_IF_ERROR_RETURN( 1614 WRITE_SPECIAL_LABEL_CONTROLm(unit, MEM_BLOCK_ALL, i, &entry)); 1615 } 1616 return BCM_E_NONE; 1617 } 1618 1619 /* 1620 * Function: 1621 * bcmi_mpls_special_label_identifier_traverse 1622 * Description: 1623 * Traverse and call user call back for all special labels identifiers. 1624 * 1625 * Parameters: 1626 * unit - (IN) unit number 1627 * cb - (IN) user callback 1628 * user data - (IN) option user data 1629 * Return Value: 1630 * BCM_E_XXX 1631 * Notes: 1632 */ 1633 int 1634 bcmi_mpls_special_label_identifier_traverse(int unit, 1635 bcm_mpls_special_label_identifier_traverse_cb cb, void *user_data) 1636 { 1637 int i=0; 1638 bcmi_mpls_special_label_control_t *ptr; 1639 int num_entry; 1640 bcm_mpls_special_label_t label_info; 1641 int rv = BCM_E_NONE; 1642 bcm_mpls_special_label_type_t label_type; 1643 1644 num_entry = soc_mem_index_count(unit, SPECIAL_LABEL_CONTROLm); 1645 1646 ptr = bcmi_special_label_precedence_state[unit]; 1647 1648 for (; i<num_entry; i++) { 1649 sal_memset(&label_info, 0, sizeof(bcm_mpls_special_label_t)); 1650 if (!(ptr[i].valid)) { 1651 continue; 1652 } 1653 label_info.label_value = BCMI_MPLS_LABEL_VAL_FROM_LABEL_GET(ptr[i].label_value); 1654 label_info.label_mask = BCMI_MPLS_LABEL_VAL_FROM_LABEL_GET(ptr[i].label_mask); 1655 1656 label_info.exp = BCMI_MPLS_EXP_FROM_LABEL_GET(ptr[i].label_value); 1657 label_info.exp_mask = BCMI_MPLS_EXP_FROM_LABEL_GET(ptr[i].label_mask); 1658 1659 label_info.ttl = BCMI_MPLS_TTL_FROM_LABEL_GET(ptr[i].label_value); 1660 label_info.ttl_mask = BCMI_MPLS_TTL_FROM_LABEL_GET(ptr[i].label_mask); 1661 label_type = ptr[i].label_type; 1662 1663 if (BCMI_MPLS_EXP_FROM_LABEL_GET(ptr[i].label_value)) { 1664 label_info.flags |= BCM_MPLS_SPECIAL_LABEL_BOS_PRESENT; 1665 } 1666 1667 if (BCMI_MPLS_EXP_FROM_LABEL_GET(ptr[i].label_mask)) { 1668 label_info.flags |= BCM_MPLS_SPECIAL_LABEL_BOS_MASKED; 1669 } 1670 1671 bcmi_mpls_special_label_identifier_get(unit, label_type, &label_info); 1672 1673 rv = cb(unit, &label_type, &label_info, user_data); 1674 #ifdef BCM_CB_ABORT_ON_ERR 1675 if (BCM_FAILURE(rv) && SOC_CB_ABORT_ON_ERR(unit)) { 1676 return rv; 1677 } 1678 #endif 1679 } 1680 return rv; 1681 } 1682 1683 #endif /* BCM_SPECIAL_LABEL_SUPPORT */ 1684 #endif /* BCM_MPLS_SUPPORT */ 1685 #endif /* INCLUDE_L3 */