mirror.c (30245B)
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: bcmx/mirror.c 8 * Purpose: BCMX Mirroring APIs 9 */ 10 11 #include <sal/core/libc.h> 12 #include <bcm/types.h> 13 #include <bcm/topo.h> 14 15 #include <bcmx/mirror.h> 16 #include <bcmx/lport.h> 17 #include <bcmx/bcmx.h> 18 #include <bcmx/lplist.h> 19 20 #include "bcmx_int.h" 21 22 #define BCMX_MIRROR_INIT_CHECK BCMX_READY_CHECK 23 24 #define BCMX_MIRROR_ERROR_CHECK(_unit, _check, _rv) \ 25 BCMX_ERROR_CHECK(_unit, _check, _rv) 26 27 #define BCMX_MIRROR_SET_ERROR_CHECK(_unit, _check, _rv) \ 28 BCMX_SET_ERROR_CHECK(_unit, _check, _rv) 29 30 #define BCMX_MIRROR_DELETE_ERROR_CHECK(_unit, _check, _rv) \ 31 BCMX_DELETE_ERROR_CHECK(_unit, _check, _rv) 32 33 #define BCMX_MIRROR_GET_IS_VALID(_unit, _rv) \ 34 BCMX_ERROR_IS_VALID(_unit, _rv) 35 36 37 #define BCMX_MIRROR_DESTINATION_T_PTR_TO_BCM(_dest) \ 38 ((bcm_mirror_destination_t *)(_dest)) 39 40 41 /* Mirror-to port and preserve-format are cached locally */ 42 static bcmx_lport_t mirror_to_lport = BCMX_LPORT_INVALID; 43 44 /* 45 Get system-wide state of directed mirroring from the first switch 46 found. 47 */ 48 49 STATIC int 50 _bcmx_mirror_directed_get(int *directed) 51 { 52 int bcm_unit, i, rv; 53 bcm_info_t info; 54 55 rv = BCM_E_NONE; 56 *directed = 0; 57 58 BCMX_UNIT_ITER(bcm_unit, i) { 59 60 BCM_IF_ERROR_RETURN(bcm_info_get(bcm_unit, &info)); 61 62 if (info.capability & BCM_INFO_SWITCH) { 63 rv = bcm_switch_control_get(bcm_unit, 64 bcmSwitchDirectedMirroring, 65 directed); 66 if (rv == BCM_E_NONE || rv != BCM_E_UNAVAIL) { 67 break; 68 } 69 } 70 } 71 72 if (rv == BCM_E_UNAVAIL) { 73 rv = BCM_E_NONE; 74 } 75 76 return rv; 77 } 78 79 80 /* 81 * Function: 82 * bcmx_mirror_destination_t_init 83 */ 84 void 85 bcmx_mirror_destination_t_init(bcmx_mirror_destination_t *mirror_dest) 86 { 87 if (mirror_dest != NULL) { 88 bcm_mirror_destination_t_init 89 (BCMX_MIRROR_DESTINATION_T_PTR_TO_BCM(mirror_dest)); 90 } 91 } 92 93 94 /* 95 * Function: 96 * bcmx_mirror_init 97 */ 98 99 int 100 bcmx_mirror_init(void) 101 { 102 int rv = BCM_E_UNAVAIL, tmp_rv; 103 int i, bcm_unit; 104 105 BCMX_MIRROR_INIT_CHECK; 106 107 BCMX_UNIT_ITER(bcm_unit, i) { 108 tmp_rv = bcm_mirror_init(bcm_unit); 109 if (BCM_FAILURE(BCMX_MIRROR_ERROR_CHECK(bcm_unit, tmp_rv, &rv))) { 110 break; 111 } 112 } 113 114 mirror_to_lport = BCMX_LPORT_INVALID; 115 116 return rv; 117 } 118 119 /* 120 * Function: 121 * bcmx_mirror_mode_set 122 */ 123 124 int 125 bcmx_mirror_mode_set(int mode) 126 { 127 int rv = BCM_E_UNAVAIL, tmp_rv; 128 int i, bcm_unit; 129 130 BCMX_MIRROR_INIT_CHECK; 131 132 BCMX_UNIT_ITER(bcm_unit, i) { 133 tmp_rv = bcm_mirror_mode_set(bcm_unit, mode); 134 BCM_IF_ERROR_RETURN(BCMX_MIRROR_SET_ERROR_CHECK(bcm_unit, tmp_rv, &rv)); 135 } 136 137 return rv; 138 } 139 140 /* 141 * Function: 142 * bcmx_mirror_mode_get 143 */ 144 145 int 146 bcmx_mirror_mode_get(int *mode) 147 { 148 int rv; 149 int i, bcm_unit; 150 151 BCMX_MIRROR_INIT_CHECK; 152 153 BCMX_PARAM_NULL_CHECK(mode); 154 155 BCMX_UNIT_ITER(bcm_unit, i) { 156 rv = bcm_mirror_mode_get(bcm_unit, mode); 157 if (BCMX_MIRROR_GET_IS_VALID(bcm_unit, rv)) { 158 return rv; 159 } 160 } 161 162 *mode = BCM_MIRROR_DISABLE; 163 return BCM_E_UNAVAIL; 164 } 165 166 /* 167 * Function: 168 * _bcmx_port_info 169 * 170 * A device is a switch if it has one or more Ethernet ports. 171 * A device is a fabric if it has two or more stack ports. 172 * A device could be both a switch and a fabric at the same time. 173 */ 174 175 STATIC void 176 _bcmx_device_info(bcm_port_config_t *config, int *switchlike, int *fabriclike) 177 { 178 int eport, sport; 179 180 BCM_PBMP_COUNT(config->e, eport); 181 BCM_PBMP_COUNT(config->stack_ext, sport); 182 *switchlike = (eport > 0); 183 *fabriclike = (sport > 1); 184 } 185 186 STATIC int 187 _bcmx_undirected_mirror_fabric_set(int unit, 188 bcm_port_config_t *config, 189 bcm_module_t mirror_modid) 190 { 191 int rv; 192 bcm_port_t hport; 193 bcm_pbmp_t pbmp; 194 195 BCM_PBMP_ITER(config->stack_ext, hport) { 196 /* 197 * Fabric device needs to use the UC bitmap 198 * to set each stack port individually 199 */ 200 BCM_PBMP_CLEAR(pbmp); 201 BCM_IF_ERROR_RETURN 202 (bcm_stk_ucbitmap_get(unit, hport, 203 mirror_modid, &pbmp)); 204 /* Remove the CMIC from the bitmap */ 205 BCM_PBMP_REMOVE(pbmp, config->cpu); 206 rv = bcm_mirror_to_pbmp_set(unit, hport, pbmp); 207 if (rv != BCM_E_UNAVAIL) { 208 BCM_IF_ERROR_RETURN(rv); 209 } 210 } 211 return BCM_E_NONE; 212 } 213 214 /* 215 * Function: 216 * _bcmx_undirected_mirror_stk_clear 217 * 218 * Clear stack ports of any undirected mirroring forwarding 219 * configuration. 220 */ 221 222 STATIC int 223 _bcmx_undirected_mirror_stk_clear(int unit) 224 { 225 int rv; 226 bcm_port_config_t config; 227 bcm_port_t hport; 228 bcm_pbmp_t pbmp; 229 230 231 BCM_PBMP_CLEAR(pbmp); 232 BCM_IF_ERROR_RETURN(bcm_port_config_get(unit, &config)); 233 BCM_PBMP_ITER(config.stack_ext, hport) { 234 rv = bcm_mirror_to_pbmp_set(unit, hport, pbmp); 235 if (rv != BCM_E_UNAVAIL) { 236 BCM_IF_ERROR_RETURN(rv); 237 } 238 } 239 return BCM_E_NONE; 240 } 241 242 /* 243 * Function: 244 * bcmx_mirror_to_set 245 */ 246 247 int 248 bcmx_mirror_to_set(bcmx_lport_t port) 249 { 250 int bcm_unit, i; 251 bcm_port_t port_on_src; 252 bcm_module_t mirror_modid; 253 int unit_src; 254 bcm_port_t modport; 255 bcm_port_config_t config; 256 int switchlike, fabriclike; 257 258 BCMX_MIRROR_INIT_CHECK; 259 260 BCM_IF_ERROR_RETURN 261 (_bcmx_dest_to_unit_port(port, 262 &unit_src, &port_on_src, 263 BCMX_DEST_CONVERT_DEFAULT)); 264 265 BCM_IF_ERROR_RETURN 266 (_bcmx_dest_to_modid_port(port, 267 &mirror_modid, &modport, 268 BCMX_DEST_CONVERT_DEFAULT)); 269 270 mirror_to_lport = port; 271 BCMX_UNIT_ITER(bcm_unit, i) { 272 if (bcm_unit == unit_src) { 273 BCM_IF_ERROR_RETURN(bcm_mirror_to_set(bcm_unit, port_on_src)); 274 } else { 275 BCM_IF_ERROR_RETURN(bcm_port_config_get(bcm_unit, &config)); 276 _bcmx_device_info(&config, &switchlike, &fabriclike); 277 278 if (fabriclike) { 279 BCM_IF_ERROR_RETURN 280 (_bcmx_undirected_mirror_fabric_set(bcm_unit, &config, 281 mirror_modid)); 282 } 283 if (switchlike) { 284 int port_on_src; 285 286 BCM_IF_ERROR_RETURN 287 (bcm_topo_port_get(bcm_unit, mirror_modid, 288 &port_on_src)); 289 BCM_IF_ERROR_RETURN 290 (bcm_mirror_to_set(bcm_unit, port_on_src)); 291 } 292 } 293 } 294 295 return BCM_E_NONE; 296 } 297 298 299 /* 300 * Function: 301 * bcmx_mirror_to_get 302 */ 303 304 int 305 bcmx_mirror_to_get(bcmx_lport_t *port) 306 { 307 BCMX_MIRROR_INIT_CHECK; 308 309 BCMX_PARAM_NULL_CHECK(port); 310 311 *port = mirror_to_lport; 312 313 return BCM_E_NONE; 314 } 315 316 317 /* 318 * Function: 319 * bcmx_mirror_ingress_set 320 */ 321 322 int 323 bcmx_mirror_ingress_set(bcmx_lport_t port, int val) 324 { 325 int bcm_unit; 326 bcm_port_t bcm_port; 327 328 BCMX_MIRROR_INIT_CHECK; 329 330 BCM_IF_ERROR_RETURN 331 (_bcmx_dest_to_unit_port(port, &bcm_unit, &bcm_port, 332 BCMX_DEST_CONVERT_DEFAULT)); 333 334 return bcm_mirror_ingress_set(bcm_unit, bcm_port, val); 335 } 336 337 338 /* 339 * Function: 340 * bcmx_mirror_ingress_get 341 */ 342 343 int 344 bcmx_mirror_ingress_get(bcmx_lport_t port, int *val) 345 { 346 int bcm_unit; 347 bcm_port_t bcm_port; 348 349 BCMX_MIRROR_INIT_CHECK; 350 351 BCM_IF_ERROR_RETURN 352 (_bcmx_dest_to_unit_port(port, &bcm_unit, &bcm_port, 353 BCMX_DEST_CONVERT_DEFAULT)); 354 355 return bcm_mirror_ingress_get(bcm_unit, bcm_port, val); 356 } 357 358 359 /* 360 * Function: 361 * bcmx_mirror_egress_set 362 */ 363 364 int 365 bcmx_mirror_egress_set(bcmx_lport_t port, int val) 366 { 367 int bcm_unit; 368 bcm_port_t bcm_port; 369 370 BCMX_MIRROR_INIT_CHECK; 371 372 BCM_IF_ERROR_RETURN 373 (_bcmx_dest_to_unit_port(port, &bcm_unit, &bcm_port, 374 BCMX_DEST_CONVERT_DEFAULT)); 375 376 return bcm_mirror_egress_set(bcm_unit, bcm_port, val); 377 } 378 379 380 /* 381 * Function: 382 * bcmx_mirror_egress_get 383 */ 384 385 int 386 bcmx_mirror_egress_get(bcmx_lport_t port, int *val) 387 { 388 int bcm_unit; 389 bcm_port_t bcm_port; 390 391 BCMX_MIRROR_INIT_CHECK; 392 393 BCM_IF_ERROR_RETURN 394 (_bcmx_dest_to_unit_port(port, &bcm_unit, &bcm_port, 395 BCMX_DEST_CONVERT_DEFAULT)); 396 397 return bcm_mirror_egress_get(bcm_unit, bcm_port, val); 398 } 399 400 401 /* 402 * Function: 403 * bcmx_mirror_fabric_list_set 404 */ 405 406 int 407 bcmx_mirror_fabric_list_set(bcmx_lport_t port, bcmx_lplist_t lplist) 408 { 409 int bcm_unit, i; 410 int rv = BCM_E_UNAVAIL, tmp_rv; 411 bcm_pbmp_t pbmp; 412 int lport_unit; 413 bcm_port_t lport_port; 414 415 BCMX_MIRROR_INIT_CHECK; 416 417 BCM_IF_ERROR_RETURN 418 (_bcmx_dest_to_unit_port(port, 419 &lport_unit, &lport_port, 420 BCMX_DEST_CONVERT_DEFAULT)); 421 422 BCMX_UNIT_ITER(bcm_unit, i) { 423 BCMX_LPLIST_TO_PBMP(lplist, bcm_unit, pbmp); 424 if (BCM_PBMP_NOT_NULL(pbmp)) { 425 tmp_rv = bcm_mirror_to_pbmp_set(bcm_unit, lport_port, 426 pbmp); 427 BCM_IF_ERROR_RETURN 428 (BCMX_MIRROR_SET_ERROR_CHECK(bcm_unit, tmp_rv, &rv)); 429 } 430 } 431 432 return rv; 433 } 434 435 436 /* 437 * Function: 438 * bcmx_mirror_fabric_list_get 439 */ 440 441 int 442 bcmx_mirror_fabric_list_get(bcmx_lport_t port, bcmx_lplist_t *lplist) 443 { 444 int bcm_unit, i; 445 int rv = BCM_E_UNAVAIL, tmp_rv; 446 bcm_pbmp_t pbmp; 447 int lport_unit; 448 bcm_port_t lport_port; 449 450 BCMX_MIRROR_INIT_CHECK; 451 452 BCM_IF_ERROR_RETURN 453 (_bcmx_dest_to_unit_port(port, 454 &lport_unit, &lport_port, 455 BCMX_DEST_CONVERT_DEFAULT)); 456 457 if (BCMX_LPLIST_IS_NULL(lplist)) { 458 return BCM_E_PARAM; 459 } 460 461 BCMX_UNIT_ITER(bcm_unit, i) { 462 tmp_rv = bcm_mirror_to_pbmp_get(bcm_unit, 463 lport_port, 464 &pbmp); 465 if (BCMX_MIRROR_GET_IS_VALID(bcm_unit, tmp_rv)) { 466 rv = tmp_rv; 467 if (BCM_FAILURE(tmp_rv)) { 468 break; 469 } 470 if (BCM_PBMP_NOT_NULL(pbmp)) { 471 BCMX_LPLIST_PBMP_ADD(lplist, bcm_unit, pbmp); 472 } 473 } 474 } 475 476 return rv; 477 } 478 479 480 /* 481 * Function: 482 * _bcmx_directed_mirror_port_set 483 * 484 * When the system supports directed mirroring, program the mirrored 485 * port and the MTP on the unit with the mirrored port. 486 */ 487 488 STATIC int 489 _bcmx_directed_mirror_port_set(bcmx_lport_t lport, 490 bcmx_lport_t dest_lport, 491 uint32 flags) 492 { 493 int bcm_unit, i; 494 int lport_unit; 495 bcm_port_t lport_port; 496 bcm_module_t dest_modid; 497 bcm_port_t dest_modport; 498 499 BCM_IF_ERROR_RETURN 500 (_bcmx_dest_to_unit_port(lport, 501 &lport_unit, &lport_port, 502 BCMX_DEST_CONVERT_DEFAULT)); 503 BCM_IF_ERROR_RETURN 504 (_bcmx_dest_to_modid_port(dest_lport, 505 &dest_modid, &dest_modport, 506 BCMX_DEST_CONVERT_DEFAULT)); 507 508 /* Clear any existing undirected mirroring settings */ 509 BCMX_UNIT_ITER(bcm_unit, i) { 510 BCM_IF_ERROR_RETURN 511 (_bcmx_undirected_mirror_stk_clear(bcm_unit)); 512 513 } 514 515 /* set mirror port and MTP */ 516 BCM_IF_ERROR_RETURN(bcm_mirror_port_set(lport_unit, lport_port, 517 dest_modid, dest_modport, 518 flags)); 519 520 return BCM_E_NONE; 521 } 522 523 /* 524 * Function: 525 * _bcmx_undirected_mirror_port_set 526 * 527 * When the system does not support directed mirroring, program the 528 * stack ports to be MTPs on all units that are not the unit the 529 * system MTP is on. 530 * 531 * If mirroring is being disabled, only disable the mirror port 532 * not any intermediate fabrics or MTP only units, as they may still 533 * be in use by other mirrored ports. 534 */ 535 536 STATIC int 537 _bcmx_undirected_mirror_port_set(bcmx_lport_t lport, 538 bcmx_lport_t dest_lport, 539 uint32 flags) 540 { 541 int bcm_unit, i; 542 bcm_module_t mirror_modid; 543 int enable; 544 int lport_unit, dest_unit; 545 bcm_port_t lport_port, dest_port, dest_modport; 546 bcm_port_config_t config; 547 int switchlike, fabriclike; 548 549 550 BCM_IF_ERROR_RETURN 551 (_bcmx_dest_to_unit_port(lport, 552 &lport_unit, &lport_port, 553 BCMX_DEST_CONVERT_DEFAULT)); 554 BCM_IF_ERROR_RETURN 555 (_bcmx_dest_to_unit_port(dest_lport, 556 &dest_unit, &dest_port, 557 BCMX_DEST_CONVERT_DEFAULT)); 558 BCM_IF_ERROR_RETURN 559 (_bcmx_dest_to_modid_port(dest_lport, 560 &mirror_modid, &dest_modport, 561 BCMX_DEST_CONVERT_DEFAULT)); 562 563 enable = ((flags & (BCM_MIRROR_PORT_INGRESS | 564 BCM_MIRROR_PORT_EGRESS | 565 BCM_MIRROR_PORT_ENABLE)) != 0); 566 567 BCMX_UNIT_ITER(bcm_unit, i) { 568 if (bcm_unit == lport_unit) { 569 /* bcm_unit is the mirrored port unit. If this happens to 570 be the MTP unit, too, then the MTP will be taken care 571 of here. */ 572 BCM_IF_ERROR_RETURN 573 (bcm_mirror_port_set(bcm_unit, lport_port, 574 mirror_modid, dest_modport, flags)); 575 } else if (bcm_unit == dest_unit) { 576 BCM_IF_ERROR_RETURN 577 (bcm_mirror_port_set(bcm_unit, BCM_GPORT_INVALID, 578 mirror_modid, dest_modport, flags)); 579 } else { 580 /* bcm_unit is neither a mirrored port unit or an MTP unit */ 581 if (enable) { 582 BCM_IF_ERROR_RETURN(bcm_port_config_get(bcm_unit, &config)); 583 _bcmx_device_info(&config, &switchlike, &fabriclike); 584 585 if (fabriclike) { 586 BCM_IF_ERROR_RETURN 587 (_bcmx_undirected_mirror_fabric_set(bcm_unit, &config, 588 mirror_modid)); 589 } 590 if (switchlike) { 591 BCM_IF_ERROR_RETURN 592 (bcm_mirror_port_set(bcm_unit, BCM_GPORT_INVALID, 593 mirror_modid, dest_modport, 594 flags)); 595 } 596 } 597 } 598 } 599 600 return BCM_E_NONE; 601 } 602 603 /* 604 * Function: 605 * bcmx_mirror_port_set 606 */ 607 608 int 609 bcmx_mirror_port_set(bcmx_lport_t lport, 610 bcmx_lport_t dest_lport, 611 uint32 flags) 612 { 613 int directed; 614 615 BCMX_MIRROR_INIT_CHECK; 616 617 BCMX_LPORT_CHECK(lport); 618 BCMX_LPORT_CHECK(dest_lport); 619 620 BCM_IF_ERROR_RETURN(_bcmx_mirror_directed_get(&directed)); 621 622 return directed ? 623 _bcmx_directed_mirror_port_set(lport, dest_lport, flags) : 624 _bcmx_undirected_mirror_port_set(lport, dest_lport, flags); 625 } 626 627 628 /* 629 * Function: 630 * bcmx_mirror_port_get 631 * Notes: 632 * dest_lport is undefined when no flags are set in returning function. 633 */ 634 635 int 636 bcmx_mirror_port_get(bcmx_lport_t lport, 637 bcmx_lport_t *dest_lport, 638 uint32 *flags) 639 { 640 bcm_module_t dest_mod; 641 bcm_port_t dest_port; 642 int bcm_unit; 643 bcm_port_t bcm_port; 644 645 BCMX_MIRROR_INIT_CHECK; 646 647 BCMX_PARAM_NULL_CHECK(dest_lport); 648 BCMX_PARAM_NULL_CHECK(flags); 649 650 BCM_IF_ERROR_RETURN 651 (_bcmx_dest_to_unit_port(lport, &bcm_unit, &bcm_port, 652 BCMX_DEST_CONVERT_DEFAULT)); 653 654 BCM_IF_ERROR_RETURN(bcm_mirror_port_get(bcm_unit, bcm_port, 655 &dest_mod, &dest_port, 656 flags)); 657 658 /* 659 * Convert only when flags is set, since dest_mod/dest_port are 660 * undefined when BCM returns no flags set. 661 */ 662 if (*flags != 0) { 663 BCM_IF_ERROR_RETURN 664 (_bcmx_dest_from_modid_port(dest_lport, dest_mod, dest_port, 665 BCMX_DEST_CONVERT_DEFAULT)); 666 } 667 668 return BCM_E_NONE; 669 } 670 671 672 /* 673 * Function: 674 * bcmx_mirror_vlan_set 675 */ 676 677 int 678 bcmx_mirror_vlan_set(bcmx_lport_t lport, 679 uint16 tpid, 680 uint16 vlan) 681 { 682 int bcm_unit; 683 bcm_port_t bcm_port; 684 685 BCMX_MIRROR_INIT_CHECK; 686 687 BCM_IF_ERROR_RETURN 688 (_bcmx_dest_to_unit_port(lport, &bcm_unit, &bcm_port, 689 BCMX_DEST_CONVERT_DEFAULT)); 690 691 return bcm_mirror_vlan_set(bcm_unit, bcm_port, tpid, vlan); 692 } 693 694 695 /* 696 * Function: 697 * bcmx_mirror_vlan_get 698 */ 699 700 int 701 bcmx_mirror_vlan_get(bcmx_lport_t lport, 702 uint16 *tpid, 703 uint16 *vlan) 704 { 705 int bcm_unit; 706 bcm_port_t bcm_port; 707 708 BCMX_MIRROR_INIT_CHECK; 709 710 BCMX_PARAM_NULL_CHECK(tpid); 711 BCMX_PARAM_NULL_CHECK(vlan); 712 713 BCM_IF_ERROR_RETURN 714 (_bcmx_dest_to_unit_port(lport, &bcm_unit, &bcm_port, 715 BCMX_DEST_CONVERT_DEFAULT)); 716 717 return bcm_mirror_vlan_get(bcm_unit, bcm_port, tpid, vlan); 718 } 719 720 721 /* 722 * Function: 723 * _bcmx_directed_mirror_port_dest_add 724 * 725 * Notes: 726 * When the system supports directed mirroring, add the 727 * destination mirror on the unit with the mirrored port. 728 */ 729 STATIC int 730 _bcmx_directed_mirror_port_dest_add(bcmx_lport_t port, uint32 flags, 731 bcm_gport_t mirror_dest_id) 732 { 733 int i; 734 int bcm_unit; 735 bcm_port_t bcm_port; 736 737 /* Clear any existing undirected mirroring settings */ 738 BCMX_UNIT_ITER(bcm_unit, i) { 739 BCM_IF_ERROR_RETURN 740 (_bcmx_undirected_mirror_stk_clear(bcm_unit)); 741 742 } 743 744 BCM_IF_ERROR_RETURN 745 (_bcmx_dest_to_unit_port(port, 746 &bcm_unit, &bcm_port, 747 BCMX_DEST_CONVERT_DEFAULT)); 748 749 return bcm_mirror_port_dest_add(bcm_unit, bcm_port, 750 flags, mirror_dest_id); 751 } 752 753 /* 754 * Function: 755 * _bcmx_undirected_mirror_port_dest_add 756 * Notes: 757 * Non-direct (undirected) mirroring mode only supports 758 * single mirroring destination. 759 * 760 * Assumes that BCM API will handle cases where 761 * the 'same' port is being added (need to check if BCM returns 762 * an error, if so, it should at least return BCM_E_EXISTS. 763 */ 764 STATIC int 765 _bcmx_undirected_mirror_port_dest_add(bcmx_lport_t port, uint32 flags, 766 bcm_gport_t mirror_dest_id) 767 { 768 int bcm_unit, i; 769 int mirrored_unit; 770 bcm_port_t mirrored_port; 771 bcm_port_config_t config; 772 bcmx_mirror_destination_t mirror_dest; 773 bcm_module_t mirror_modid; 774 int switchlike, fabriclike; 775 776 BCM_IF_ERROR_RETURN 777 (_bcmx_dest_to_unit_port(port, 778 &mirrored_unit, &mirrored_port, 779 BCMX_DEST_CONVERT_DEFAULT)); 780 781 bcmx_mirror_destination_t_init(&mirror_dest); 782 BCM_IF_ERROR_RETURN 783 (bcmx_mirror_destination_get(mirror_dest_id, &mirror_dest)); 784 785 mirror_modid = BCM_GPORT_MODPORT_MODID_GET(mirror_dest.gport); 786 787 if (mirror_modid < 0) { 788 return BCM_E_PORT; 789 } 790 791 BCMX_UNIT_ITER(bcm_unit, i) { 792 if (bcm_unit == mirrored_unit) { 793 /* bcm_unit is the mirrored port unit. If this happens to 794 be the MTP unit, too, then the MTP will be taken care 795 of here. */ 796 BCM_IF_ERROR_RETURN 797 (bcm_mirror_port_dest_add(mirrored_unit, mirrored_port, 798 flags, mirror_dest_id)); 799 } else { 800 /* bcm_unit is not a mirrored port unit */ 801 BCM_IF_ERROR_RETURN(bcm_port_config_get(bcm_unit, &config)); 802 _bcmx_device_info(&config, &switchlike, &fabriclike); 803 804 if (fabriclike) { 805 BCM_IF_ERROR_RETURN 806 (_bcmx_undirected_mirror_fabric_set(bcm_unit, &config, 807 mirror_modid)); 808 } 809 if (switchlike) { 810 BCM_IF_ERROR_RETURN 811 (bcm_mirror_port_dest_add(bcm_unit,BCM_GPORT_INVALID, 812 flags, mirror_dest_id)); 813 } 814 } 815 } 816 817 return BCM_E_NONE; 818 } 819 820 /* 821 * Function: 822 * bcmx_mirror_port_dest_add 823 */ 824 int 825 bcmx_mirror_port_dest_add(bcmx_lport_t port, uint32 flags, 826 bcm_gport_t mirror_dest_id) 827 { 828 int directed; 829 830 BCMX_MIRROR_INIT_CHECK; 831 832 BCMX_LPORT_CHECK(port); 833 834 BCM_IF_ERROR_RETURN(_bcmx_mirror_directed_get(&directed)); 835 836 return directed ? 837 _bcmx_directed_mirror_port_dest_add(port, flags, mirror_dest_id) : 838 _bcmx_undirected_mirror_port_dest_add(port, flags, mirror_dest_id); 839 840 } 841 842 /* 843 * Function: 844 * _bcmx_undirected_dest_delete_transit 845 * 846 * Delete any "transit device" settings programmed by 847 * _bcmx_undirected_mirror_port_dest_add() 848 */ 849 STATIC int 850 _bcmx_undirected_dest_delete_transit(bcmx_lport_t port, 851 uint32 flags, 852 bcm_gport_t mirror_dest_id) 853 { 854 int i, bcm_unit; 855 int mirrored_unit; 856 bcm_port_t mirrored_port; 857 int switchlike, fabriclike; 858 bcm_port_config_t config; 859 860 BCM_IF_ERROR_RETURN 861 (_bcmx_dest_to_unit_port(port, 862 &mirrored_unit, &mirrored_port, 863 BCMX_DEST_CONVERT_DEFAULT)); 864 865 BCMX_UNIT_ITER(bcm_unit, i) { 866 if (bcm_unit != mirrored_unit) { 867 BCM_IF_ERROR_RETURN(bcm_port_config_get(bcm_unit, &config)); 868 _bcmx_device_info(&config, &switchlike, &fabriclike); 869 if (switchlike) { 870 BCM_IF_ERROR_RETURN 871 (bcm_mirror_port_dest_delete(bcm_unit, 872 BCM_GPORT_INVALID, 873 flags, mirror_dest_id)); 874 } 875 } 876 } 877 878 return BCM_E_NONE; 879 } 880 881 882 /* 883 * Function: 884 * bcmx_mirror_port_dest_delete 885 */ 886 int 887 bcmx_mirror_port_dest_delete(bcmx_lport_t port, uint32 flags, 888 bcm_gport_t mirror_dest_id) 889 { 890 int bcm_unit; 891 bcm_port_t bcm_port; 892 int directed; 893 894 BCMX_MIRROR_INIT_CHECK; 895 896 BCM_IF_ERROR_RETURN(_bcmx_mirror_directed_get(&directed)); 897 if (!directed) { 898 BCM_IF_ERROR_RETURN 899 (_bcmx_undirected_dest_delete_transit(port, 900 flags, 901 mirror_dest_id)); 902 } 903 BCM_IF_ERROR_RETURN 904 (_bcmx_dest_to_unit_port(port, &bcm_unit, &bcm_port, 905 BCMX_DEST_CONVERT_DEFAULT)); 906 907 return bcm_mirror_port_dest_delete(bcm_unit, bcm_port, flags, 908 mirror_dest_id); 909 } 910 911 /* 912 * Function: 913 * bcmx_mirror_port_dest_delete_all 914 */ 915 int 916 bcmx_mirror_port_dest_delete_all(bcmx_lport_t port, uint32 flags) 917 { 918 int bcm_unit; 919 bcm_port_t bcm_port; 920 int directed; 921 922 BCMX_MIRROR_INIT_CHECK; 923 924 BCM_IF_ERROR_RETURN(_bcmx_mirror_directed_get(&directed)); 925 if (!directed) { 926 bcm_gport_t mirror_dest_id; 927 int mirror_dest_count; 928 929 /* Delete any transit device configuration */ 930 BCM_IF_ERROR_RETURN 931 (bcmx_mirror_port_dest_get(port, flags, 932 1, &mirror_dest_id, 933 &mirror_dest_count)); 934 935 if (mirror_dest_count > 0) { 936 BCM_IF_ERROR_RETURN 937 (_bcmx_undirected_dest_delete_transit(port, 938 flags, 939 mirror_dest_id)); 940 } 941 } 942 943 BCM_IF_ERROR_RETURN 944 (_bcmx_dest_to_unit_port(port, &bcm_unit, &bcm_port, 945 BCMX_DEST_CONVERT_DEFAULT)); 946 947 return bcm_mirror_port_dest_delete_all(bcm_unit, bcm_port, flags); 948 } 949 950 951 /* 952 * Function: 953 * bcmx_mirror_port_dest_get 954 */ 955 int 956 bcmx_mirror_port_dest_get(bcmx_lport_t port, uint32 flags, 957 int mirror_dest_size, bcm_gport_t *mirror_dest_id, 958 int *mirror_dest_count) 959 { 960 int bcm_unit; 961 bcm_port_t bcm_port; 962 963 BCMX_MIRROR_INIT_CHECK; 964 965 BCMX_PARAM_ARRAY_NULL_CHECK(mirror_dest_size, mirror_dest_id); 966 BCMX_PARAM_NULL_CHECK(mirror_dest_count); 967 968 BCM_IF_ERROR_RETURN 969 (_bcmx_dest_to_unit_port(port, &bcm_unit, &bcm_port, 970 BCMX_DEST_CONVERT_DEFAULT)); 971 972 return bcm_mirror_port_dest_get(bcm_unit, bcm_port, flags, 973 mirror_dest_size, mirror_dest_id, 974 mirror_dest_count); 975 } 976 977 978 /* 979 * Function: 980 * bcmx_mirror_destination_create 981 */ 982 int 983 bcmx_mirror_destination_create(bcmx_mirror_destination_t *mirror_dest) 984 { 985 int rv = BCM_E_UNAVAIL, tmp_rv; 986 int i, bcm_unit; 987 bcm_gport_t gport_orig; 988 uint32 flags_orig; 989 990 BCMX_MIRROR_INIT_CHECK; 991 992 BCMX_PARAM_NULL_CHECK(mirror_dest); 993 994 /* 995 * Need to save original 'gport' value and copy it back to structure 996 * for each iteration since BCM API may change its value (this happens 997 * when the MTP does not reside in the local unit). 998 */ 999 gport_orig = mirror_dest->gport; 1000 1001 /* Store original 'xxx_WITH_ID' flag bit */ 1002 flags_orig = mirror_dest->flags & BCM_MIRROR_DEST_WITH_ID; 1003 1004 BCMX_UNIT_ITER(bcm_unit, i) { 1005 mirror_dest->gport = gport_orig; 1006 1007 tmp_rv = bcm_mirror_destination_create 1008 (bcm_unit, 1009 BCMX_MIRROR_DESTINATION_T_PTR_TO_BCM(mirror_dest)); 1010 1011 if (BCM_FAILURE(BCMX_MIRROR_SET_ERROR_CHECK(bcm_unit, tmp_rv, &rv))) { 1012 break; 1013 } 1014 1015 /* 1016 * Use the ID from first successful 'create' if mirror destination ID 1017 * is not specified. 1018 */ 1019 if (!(mirror_dest->flags & BCM_MIRROR_DEST_WITH_ID)) { 1020 if (BCM_SUCCESS(tmp_rv)) { 1021 mirror_dest->flags |= BCM_MIRROR_DEST_WITH_ID; 1022 } 1023 } 1024 } 1025 1026 /* Restore 'xxx_WITH_ID' flag bit */ 1027 mirror_dest->flags &= ~BCM_MIRROR_DEST_WITH_ID; 1028 mirror_dest->flags |= flags_orig; 1029 1030 return rv; 1031 } 1032 1033 /* 1034 * Function: 1035 * bcmx_mirror_destination_destroy 1036 */ 1037 int 1038 bcmx_mirror_destination_destroy(bcm_gport_t mirror_dest_id) 1039 { 1040 int rv = BCM_E_UNAVAIL, tmp_rv; 1041 int i, bcm_unit; 1042 1043 BCMX_MIRROR_INIT_CHECK; 1044 1045 BCMX_UNIT_ITER(bcm_unit, i) { 1046 tmp_rv = bcm_mirror_destination_destroy(bcm_unit, mirror_dest_id); 1047 BCM_IF_ERROR_RETURN 1048 (BCMX_MIRROR_DELETE_ERROR_CHECK(bcm_unit, tmp_rv, &rv)); 1049 } 1050 1051 return rv; 1052 } 1053 1054 1055 /* 1056 * Function: 1057 * _bcmx_undirected_mirror_destination_get 1058 * 1059 * Iterate on units and return mirror destination information from 1060 * first successful call on unit that returns an MTP that is 1061 * a front-panel (ethernet) port. 1062 */ 1063 int 1064 _bcmx_undirected_mirror_destination_get(bcm_gport_t mirror_dest_id, 1065 bcmx_mirror_destination_t *mirror_dest) 1066 { 1067 int rv; 1068 int i, bcm_unit; 1069 bcm_port_encap_config_t mode; 1070 uint32 stk_mode; 1071 1072 BCMX_UNIT_ITER(bcm_unit, i) { 1073 rv = bcm_mirror_destination_get(bcm_unit, mirror_dest_id, 1074 BCMX_MIRROR_DESTINATION_T_PTR_TO_BCM 1075 (mirror_dest)); 1076 1077 if (!BCMX_MIRROR_GET_IS_VALID(bcm_unit, rv)) { 1078 continue; 1079 } 1080 1081 /* 1082 * The MTP must be a modport, so skip if not. 1083 */ 1084 if (BCM_FAILURE(rv) || !BCM_GPORT_IS_MODPORT(mirror_dest->gport)) { 1085 continue; 1086 } 1087 1088 /* make sure the mirror_dest is an Ethernet port. In 1089 undirected mode, that's the only kind of port an MTP can 1090 be. */ 1091 1092 sal_memset(&mode, 0, sizeof(mode)); 1093 rv = bcm_port_encap_config_get(bcm_unit, mirror_dest->gport, &mode); 1094 if (BCM_FAILURE(rv)) { 1095 continue; 1096 } 1097 1098 rv = bcm_stk_mode_get(bcm_unit, &stk_mode); 1099 if (BCM_FAILURE(rv)) { 1100 continue; 1101 } 1102 1103 if (mode.encap == BCM_PORT_ENCAP_IEEE && stk_mode != BCM_STK_SL) { 1104 /* Ethernet port found */ 1105 return BCM_E_NONE; 1106 } 1107 } 1108 1109 return BCM_E_UNAVAIL; 1110 } 1111 1112 1113 /* 1114 * Function: 1115 * bcmx_mirror_destination_get 1116 */ 1117 int 1118 bcmx_mirror_destination_get(bcm_gport_t mirror_dest_id, 1119 bcmx_mirror_destination_t *mirror_dest) 1120 { 1121 int rv; 1122 int i, bcm_unit; 1123 int directed; 1124 1125 BCMX_MIRROR_INIT_CHECK; 1126 1127 BCMX_PARAM_NULL_CHECK(mirror_dest); 1128 1129 /* 1130 * Directed Mirroring - 1131 * Return information from the first successful call on a unit. 1132 * 1133 * Non-Directed Mirroring - 1134 * Needs special handling. 1135 * Iterate over units until a front-panel MTP is found. 1136 */ 1137 1138 BCM_IF_ERROR_RETURN(_bcmx_mirror_directed_get(&directed)); 1139 1140 if (directed) { 1141 BCMX_UNIT_ITER(bcm_unit, i) { 1142 rv = bcm_mirror_destination_get(bcm_unit, mirror_dest_id, 1143 BCMX_MIRROR_DESTINATION_T_PTR_TO_BCM 1144 (mirror_dest)); 1145 if (BCMX_MIRROR_GET_IS_VALID(bcm_unit, rv)) { 1146 return rv; 1147 } 1148 } 1149 1150 } else { 1151 return _bcmx_undirected_mirror_destination_get(mirror_dest_id, 1152 mirror_dest); 1153 } 1154 1155 return BCM_E_UNAVAIL; 1156 } 1157