mirror.c (1022837B)
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 * Mirror - Broadcom StrataSwitch Mirror API. 8 * 9 * The mirroring code has become more complex after the introduction 10 * of XGS3 devices, which support multiple MTPs (mirror-to ports) as 11 * well as directed mirroring. When directed mirroring is enabled 12 * it is also possible to mirror to a trunk. 13 * 14 * Non-directed mirroring (aka. Draco1.5-style mirroring and XGS2-style 15 * mirroring) only allows for a single MTP in a system (which can be 16 * either a single device or a stack.) In order to mirror a packet to 17 * a remote module in non-directed mode, the local MTP must be the 18 * appropriate stacking port and all modules traversed from the 19 * mirrored port to the MTP need to have mirroring configured to 20 * reflect the desired path for mirror packets. 21 * 22 * Directed mirroring means that the MTP info includes a module ID, 23 * which allows mirror packets to follow the normal path of switched 24 * packets, i.e. when mirroring to a remote MTP there is no need to 25 * configure the mirror path separately. 26 * 27 * Since the original mirror API did not support module IDs in the MTP 28 * definition, a new API was introduced to handle this. The new API is 29 * called bcm_mirror_port_set/get and allows the application to 30 * configure mirroring with a single API call, whereas the the old API 31 * would require two (and in most cases three or more) API calls. 32 * 33 * For compatibility, the original API will also work on XGS3 devices, 34 * and in this case the MTP module ID is automatically set to be the 35 * local module ID. Likewise, the new API will also work on pre-XGS3 36 * devices as long as the MTP module ID is specified as the local 37 * module ID. 38 * 39 * In addition to normal ingress and egress mirroring, the FP (field 40 * processor) can specify actions that include ingress and egress 41 * mirroring. This feature uses the same hardware MTP resources as 42 * the mirror API, so in order to coordinate this, the FP APIs must 43 * allocate MTP resources through internal reserve/unreserve 44 * functions. Since multiple FP rules can use the same MTP resource 45 * the reserve/unreserve functions maintain a reference count for 46 * each MTP resource. In the software MTP structure this reference 47 * counter is called 'reserved'. Within the same structure, the 48 * mirror API uses the 'pbmp' to indicate whether this MTP resource 49 * is being used by the mirror API. 50 * 51 * Note that the MTP resource management code allows resources to be 52 * shared between the mirror API and the FP whenever the requested 53 * MTP is identical. 54 */ 55 56 #include <shared/bsl.h> 57 58 #include <soc/drv.h> 59 #include <soc/scache.h> 60 #ifdef BCM_TRIDENT_SUPPORT 61 #include <soc/profile_mem.h> 62 #endif /* BCM_TRIDENT_SUPPORT */ 63 64 #include <bcm/error.h> 65 #include <bcm/mirror.h> 66 #include <bcm/port.h> 67 #include <bcm_int/esw/mbcm.h> 68 #include <bcm_int/esw/port.h> 69 #include <bcm_int/esw/mirror.h> 70 #include <bcm_int/esw/trunk.h> 71 #include <bcm_int/esw/stack.h> 72 #ifdef BCM_WARM_BOOT_SUPPORT 73 #include <bcm_int/common/field.h> 74 #include <bcm_int/esw/switch.h> 75 #endif /* BCM_WARM_BOOT_SUPPORT */ 76 77 #include <bcm_int/esw_dispatch.h> 78 79 #if defined(BCM_TRIUMPH2_SUPPORT) && defined(INCLUDE_L3) 80 #include <bcm_int/esw/virtual.h> 81 #endif 82 #ifdef BCM_TRIUMPH2_SUPPORT 83 #include <bcm_int/esw/triumph2.h> 84 #endif 85 #ifdef BCM_TRIDENT_SUPPORT 86 #include <bcm_int/esw/trident.h> 87 #endif 88 #ifdef BCM_TRIUMPH3_SUPPORT 89 #include <bcm_int/esw/triumph3.h> 90 #endif 91 #ifdef BCM_TRIUMPH_SUPPORT 92 #include <bcm_int/esw/triumph.h> 93 #endif 94 #ifdef BCM_KATANA2_SUPPORT 95 #include <bcm_int/esw/katana2.h> 96 #endif 97 #ifdef BCM_MPLS_SUPPORT 98 #include <bcm_int/esw/mpls.h> 99 #endif 100 #ifdef BCM_HGPROXY_COE_SUPPORT 101 #include <bcm_int/esw/xgs5.h> 102 #endif /*BCM_HGPROXY_COE_SUPPORT */ 103 #ifdef BCM_TRIDENT2_SUPPORT 104 #include <bcm_int/esw/trident2.h> 105 #include <bcm_int/esw/vxlan.h> 106 #endif 107 108 #ifdef BCM_TRIDENT3_SUPPORT 109 #include <soc/esw/cancun.h> 110 #include <soc/esw/cancun_enums.h> 111 #endif /* BCM_TRIDENT3_SUPPORT */ 112 113 /* local macros */ 114 #define VP_PORT_INVALID (-1) 115 #define IPV4_GRE_PROTOCOL (0x2F) 116 #define IPV4_UDP_PROTOCOL (0x11) 117 #define IPV4_HEADER_LENGTH_WORDS 5 118 #define IPV4_VERSION 4 119 #define IPV4_HDR_CHECKSUM_BYTES 2 120 #define IPV4_IP_ADDR_BYTES 8 121 #define IPV4_PKT_VLAN_MASK 0xFFF 122 #define IPV4_PKT_PRIO_SHIFT 13 123 #define IPV4_PKT_PRIO_MASK 7 124 #define IPV4_PKT_PRIO(p) (((p) & IPV4_PKT_PRIO_MASK) << IPV4_PKT_PRIO_SHIFT) 125 126 #define IPV4_NIV_ETHER_TYPE 0x220E 127 #define MIRROR_PORT_MASK 0x7FF 128 #define PKT_ENCAP_VXLAN 0x08 129 130 #define IPV6_VERSION 6 131 #define IPV6_TRAFFIC_CLASS 2 132 #define IPV6_NEXT_HDR_TCP 6 133 #define IPV6_NEXT_HDR_UDP 17 134 #define IPV6_NEXT_HDR_GRE 47 135 #define IPV6_HOP_LIMIT 0x3F 136 #define IPV6_ETHER_TYPE 0x86DD 137 138 #define IPV6_HEADER_LEN 40 139 #define IPV4_HEADER_LEN 20 140 #define UDP_HEADER_LEN 8 141 #define SFLOW_HEADER_LEN 16 142 #define GRE_HEADER_LEN 4 143 #define VXLAN_HEADER_LEN 8 144 145 #define TWOS_COMPLEMENT(x) (0x100 - (x)) 146 #define NIBBLE_SHIFT_OFFSET 4 147 148 #define DF_FLAG_SHIFTER 6 /* IP don't fragment flag position */ 149 150 /* For identification SEQ looks like 5E0.., 151 * so adding a constant 152 * 0x5E0XXxxx to the sequence number generation */ 153 #define BCM_MIRROR_IP_GRE_SEQ_NUM 0x5E022000 154 #define BCM_MIRROR_PSAMP_SEQ_NUM 0x5E011000 155 156 /* STATIC FUNCTIONS DECLARATION. */ 157 STATIC int _bcm_esw_mirror_enable(int unit); 158 STATIC int _bcm_esw_mirror_egress_set(int unit, bcm_port_t port, int enable); 159 STATIC int _bcm_esw_mirror_egress_get(int unit, bcm_port_t port, int *enable); 160 STATIC int _bcm_esw_directed_mirroring_get(int unit, int *enable); 161 STATIC int _bcm_esw_mirror_port_dest_search(int unit, bcm_port_t port, 162 uint32 flags, bcm_gport_t mirror_dest); 163 164 /* LOCAL VARIABLES DECLARATION. */ 165 static int _bcm_mirror_mtp_method_init[BCM_MAX_NUM_UNITS]; 166 _bcm_mirror_config_p _bcm_mirror_config[BCM_MAX_NUM_UNITS]; 167 static int _bcm_switch_mirror_exclusive_config[BCM_MAX_NUM_UNITS]; 168 169 #ifdef BCM_TRIUMPH2_SUPPORT 170 static const soc_field_t _mtp_index_field[] = { 171 MTP_INDEX0f, MTP_INDEX1f, MTP_INDEX2f, MTP_INDEX3f 172 }; 173 static const soc_field_t _non_uc_mtp_index_field[] = { 174 NON_UC_EM_MTP_INDEX0f, NON_UC_EM_MTP_INDEX1f, NON_UC_EM_MTP_INDEX2f, 175 NON_UC_EM_MTP_INDEX3f 176 }; 177 #endif /* BCM_TRIUMPH2_SUPPORT */ 178 179 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_GREYHOUND_SUPPORT) 180 /* Cache of Egress Mirror Encap Profile Tables */ 181 static soc_profile_mem_t *egr_mirror_encap_profile[BCM_MAX_NUM_UNITS] = {NULL}; 182 #define EGR_MIRROR_ENCAP(_unit_) \ 183 (egr_mirror_encap_profile[_unit_]) 184 #define EGR_MIRROR_ENCAP_PROFILE_DEFAULT 0 185 186 #define EGR_MIRROR_ENCAP_ENTRIES_CONTROL 0 187 #define EGR_MIRROR_ENCAP_ENTRIES_DATA_1 1 188 #define EGR_MIRROR_ENCAP_ENTRIES_DATA_2 2 189 #define EGR_MIRROR_ENCAP_ENTRIES_NUM 3 190 191 #if defined(BCM_TRIDENT3_SUPPORT) 192 static soc_profile_mem_t *egr_mirror_table_profile[BCM_MAX_NUM_UNITS] = {NULL}; 193 #define EGR_MIRROR_TABLE(_unit_) (egr_mirror_table_profile[_unit_]) 194 static soc_profile_mem_t *egr_seq_number_profile[BCM_MAX_NUM_UNITS] = {NULL}; 195 #define EGR_SEQ_NUMBER_PROFILE(_unit_) (egr_seq_number_profile[_unit_]) 196 197 #define TD3_EGR_VXLT_HASH_ERPSAN3_KEY_TYPE 20 198 #define EGR_VXLT_HASH_ERPSAN3_KEY_TYPE 21 199 #define EGR_VXLT_HASH_ERPSAN3_DATA_TYPE 27 200 201 #define I2E_CLASS_ID_VLAN_TYPE 10 202 #define I2E_CLASS_ID_IFP_TYPE 15 203 204 #define ERSPAN3_GRE_PROTOCOL_TYPE 0x22EB 205 #define ERSPAN3_MIRROR_VXLT_CTRL_ID 0xFF 206 static uint32 encap_profile_index_bmap=0x00; 207 208 /* [31:24] remote_mapped_profile_index, [23:16] local_mapped_profile_index 209 [15:8] egress_edit_ctrl_id [7:0] ingress edit ctrl id */ 210 static uint32 encap_to_edit_ctrl_id[BCM_MIRROR_MTP_COUNT * 2]={0x00}; 211 212 /* ECD = EDIT CTRL ID */ 213 #define MIRROR_ECD_INGRESS(x) ((x) & 0xFF) 214 #define MIRROR_ECD_EGRESS(x) (((x) >> 8) & 0xFF) 215 #define MIRROR_ECD_INDEX_LOCAL(x) ((x >> 16) & 0xFF) 216 #define MIRROR_ECD_INDEX_REMOTE(x) ((x >> 24) & 0xFF) 217 #define MIRROR_ECD_VALID(x) ((x) & 0xFFFF) 218 219 #endif /* BCM_TRIDENT3_SUPPORT */ 220 221 #endif /* BCM_TRIDENT_SUPPORT || BCM_GREYHOUND_SUPPORT */ 222 223 #define BCM_EGR_MIRROR_ENCAP_ENTRIES_CONTROL 0 224 #define BCM_EGR_MIRROR_ENCAP_ENTRIES_DATA_1 1 225 #define BCM_EGR_MIRROR_ENCAP_ENTRIES_DATA_2 2 226 #define BCM_EGR_MIRROR_ENCAP_ENTRIES_NUM 3 227 228 #if defined (BCM_TOMAHAWK_SUPPORT) 229 /* Field callback functions for recovering Mirror Destination during warmboot */ 230 extern int 231 _field_mirror_actions_recover_callback(int unit,_bcm_mirror_config_p _bcm_mirror_config); 232 #endif 233 234 #if defined(BCM_KATANA2_SUPPORT) 235 extern int bcm_esw_subport_port_get(int, bcm_gport_t, bcm_subport_config_t *); 236 extern int bcm_subport_group_get(int unit, bcm_gport_t, bcm_subport_group_config_t *config); 237 #endif 238 239 int 240 _bcm_esw_mirror_flexible_get(int unit, int *enable) 241 { 242 if (soc_feature(unit, soc_feature_mirror_flexible)) { 243 *enable = (_bcm_mirror_mtp_method_init[unit] == 244 BCM_MIRROR_MTP_METHOD_DIRECTED_FLEXIBLE) ? TRUE : FALSE; 245 246 return BCM_E_NONE; 247 } else { 248 return BCM_E_UNAVAIL; 249 } 250 } 251 252 int 253 _bcm_esw_mirror_flexible_set(int unit, int enable) 254 { 255 if (soc_feature(unit, soc_feature_mirror_flexible)) { 256 if (enable) { 257 _bcm_mirror_mtp_method_init[unit] = 258 BCM_MIRROR_MTP_METHOD_DIRECTED_FLEXIBLE; 259 } else if (soc_feature(unit, soc_feature_directed_mirror_only)) { 260 _bcm_mirror_mtp_method_init[unit] = 261 BCM_MIRROR_MTP_METHOD_DIRECTED_LOCKED; 262 } else { 263 _bcm_mirror_mtp_method_init[unit] = 264 BCM_MIRROR_MTP_METHOD_NON_DIRECTED; 265 } 266 return BCM_E_NONE; 267 } else { 268 return BCM_E_UNAVAIL; 269 } 270 } 271 272 /* 273 * Function: 274 * _bcm_esw_mirror_exclusive_get 275 * Purpose: 276 * Get mirror exclusive status on the chip. 277 * Parameters: 278 * unit - (IN) BCM device number. 279 * enable - (OUT) Mirror Exclusive Control Status. 280 * Returns: 281 * BCM_E_XXX 282 * Notes: Applicable for devices not supporting 283 * flexible mirroring. 284 */ 285 int 286 _bcm_esw_mirror_exclusive_get(int unit, int *enable) 287 { 288 if (SOC_IS_TRX(unit) && !SOC_IS_HURRICANEX(unit) && 289 !SOC_IS_GREYHOUND(unit) && !SOC_IS_GREYHOUND2(unit) && 290 !soc_feature(unit, soc_feature_mirror_flexible)) { 291 *enable = _bcm_switch_mirror_exclusive_config[unit]; 292 return BCM_E_NONE; 293 } 294 return BCM_E_UNAVAIL; 295 } 296 297 /* 298 * Function: 299 * _bcm_esw_mirror_exclusive_set 300 * Purpose: 301 * Set mirror exclusive control on the chip. 302 * Parameters: 303 * unit - (IN) BCM device number. 304 * enable - (IN) Mirror Exclusive Control Status. 305 * Returns: 306 * BCM_E_XXX 307 * Notes: Applicable for devices not supporting 308 * flexible mirroring. 309 */ 310 int 311 _bcm_esw_mirror_exclusive_set(int unit, int enable) 312 { 313 if (SOC_IS_TRX(unit) && !SOC_IS_HURRICANEX(unit) && 314 !SOC_IS_GREYHOUND(unit) && !SOC_IS_GREYHOUND2(unit) && 315 !soc_feature(unit, soc_feature_mirror_flexible)) { 316 if (enable) { 317 _bcm_switch_mirror_exclusive_config[unit] = 318 _BCM_SWITCH_MIRROR_EXCLUSIVE; 319 } else { 320 _bcm_switch_mirror_exclusive_config[unit] = 321 _BCM_SWITCH_MIRROR_NON_EXCLUSIVE; 322 } 323 return BCM_E_NONE; 324 } 325 return BCM_E_UNAVAIL; 326 } 327 328 /* 329 * Function: 330 * _bcm_esw_local_modid_get 331 * Purpose: 332 * Get local unit module id. 333 * Parameters: 334 * unit - (IN) BCM device number. 335 * modid - (OUT)module id. 336 * Returns: 337 * BCM_E_XXX 338 */ 339 STATIC int 340 _bcm_esw_local_modid_get(int unit, int *modid) 341 { 342 int rv; /* Operation return status. */ 343 344 /* Input parameters check. */ 345 if (NULL == modid) { 346 return (BCM_E_PARAM); 347 } 348 349 /* Get local module id. */ 350 rv = bcm_esw_stk_my_modid_get(unit, modid); 351 if ((BCM_E_UNAVAIL == rv) || (*modid < 0) ){ 352 *modid = 0; 353 rv = (BCM_E_NONE); 354 } 355 return (rv); 356 } 357 358 /* 359 * Function: 360 * _bcm_mirror_gport_adapt 361 * Description: 362 * Adapts gport encoding for dual mode devices 363 * Parameters: 364 * unit - BCM device number 365 * gport (IN/OUT)- gport to adapt 366 * Returns: 367 * BCM_E_XXX 368 */ 369 STATIC int 370 _bcm_mirror_gport_adapt(int unit, bcm_gport_t *gport) 371 { 372 bcm_module_t modid; 373 bcm_port_t port; 374 bcm_trunk_t tgid; 375 int id; 376 bcm_gport_t gport_out; 377 _bcm_gport_dest_t gport_st; 378 379 if (NULL == gport) { 380 return BCM_E_PARAM; 381 } 382 383 BCM_IF_ERROR_RETURN( 384 _bcm_esw_gport_resolve(unit, *gport, &modid, 385 &port, &tgid, &id)); 386 387 if (soc_feature(unit, soc_feature_hgproxy_subtag_coe)) { 388 #if defined(BCM_HGPROXY_COE_SUPPORT) 389 if(BCM_GPORT_IS_SET(*gport) && 390 _BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, *gport) && 391 _bcm_xgs5_subport_coe_gport_local(unit, *gport)) { 392 gport_st.gport_type = BCM_GPORT_TYPE_MODPORT; 393 gport_st.modid = modid; 394 gport_st.port = port; 395 BCM_IF_ERROR_RETURN( 396 _bcm_esw_gport_construct(unit, &gport_st, &gport_out)); 397 *gport = gport_out; 398 } 399 #endif 400 } else if (soc_feature(unit, soc_feature_linkphy_coe) || 401 soc_feature(unit, soc_feature_subtag_coe)) { 402 #if defined(BCM_KATANA2_SUPPORT) 403 if (BCM_GPORT_IS_SET(*gport) && 404 _BCM_KT2_GPORT_IS_LINKPHY_OR_SUBTAG_SUBPORT_GPORT (unit, *gport)) { 405 if (_bcm_kt2_mod_is_coe_mod_check(unit, modid) == BCM_E_NONE) { 406 gport_st.gport_type = BCM_GPORT_TYPE_MODPORT; 407 gport_st.modid = modid; 408 gport_st.port = port; 409 BCM_IF_ERROR_RETURN( 410 _bcm_esw_gport_construct(unit, &gport_st, &gport_out)); 411 *gport = gport_out; 412 } 413 } 414 #endif 415 } 416 417 /* Adaptation is needed only for dual mod devices */ 418 if ((NUM_MODID(unit) > 1)) { 419 420 if (-1 != id) { 421 return BCM_E_PARAM; 422 } 423 424 if (BCM_TRUNK_INVALID != tgid) { 425 gport_st.gport_type = BCM_GPORT_TYPE_TRUNK; 426 gport_st.tgid = tgid; 427 } else { 428 gport_st.gport_type = BCM_GPORT_TYPE_MODPORT; 429 gport_st.modid = modid; 430 gport_st.port = port; 431 } 432 BCM_IF_ERROR_RETURN( 433 _bcm_esw_gport_construct(unit, &gport_st, &gport_out)); 434 435 *gport = gport_out; 436 } 437 438 return BCM_E_NONE; 439 } 440 441 442 /* 443 * Function: 444 * _bcm_mirror_gport_resolve 445 * Description: 446 * Resolves gport for mirror module for local ports 447 * Parameters: 448 * unit - (IN) BCM device number 449 * gport - (IN)- gport to to resolve 450 * port - (OUT)- port encoded to gport 451 * modid - (OUT)- modid encoded to gport 452 * Returns: 453 * BCM_E_XXX 454 * Note : 455 * if modid == NULL port must be local port 456 */ 457 STATIC int 458 _bcm_mirror_gport_resolve(int unit, bcm_gport_t gport, bcm_port_t *port, 459 bcm_module_t *modid) 460 { 461 bcm_module_t lmodid; 462 bcm_trunk_t tgid; 463 bcm_port_t lport; 464 int id, islocal; 465 466 if (NULL == port) { 467 return BCM_E_PARAM; 468 } 469 470 BCM_IF_ERROR_RETURN( 471 _bcm_esw_gport_resolve(unit, gport, &lmodid, &lport, &tgid, &id)); 472 473 #if defined(BCM_HGPROXY_COE_SUPPORT) 474 if (soc_feature(unit, soc_feature_hgproxy_subtag_coe) && 475 BCM_GPORT_IS_SET(gport) && 476 _BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, gport)) { 477 } else 478 #endif 479 480 #if defined(BCM_KATANA2_SUPPORT) 481 if (BCM_GPORT_IS_SET(gport) && 482 _BCM_KT2_GPORT_IS_LINKPHY_OR_SUBTAG_SUBPORT_GPORT (unit, gport)) { 483 } else 484 #endif 485 { 486 if ((-1 != id) || (BCM_TRUNK_INVALID != tgid)) { 487 return BCM_E_PARAM; 488 } 489 } 490 491 if (NULL == modid) { 492 BCM_IF_ERROR_RETURN( 493 _bcm_esw_modid_is_local(unit, lmodid, &islocal)); 494 if (islocal != TRUE) { 495 return BCM_E_PARAM; 496 } 497 } else { 498 *modid = lmodid; 499 } 500 *port = lport; 501 502 return (BCM_E_NONE); 503 } 504 505 /* 506 * Function: 507 * _bcm_mirror_gport_construct 508 * Description: 509 * Constructs gport for mirror module 510 * Parameters: 511 * unit - (IN) BCM device number 512 * port_tgid - (IN) port or trunk id to construct into a gprot 513 * modid - (IN) module id to construct into a gport 514 * flags - (IN) Mirror trunk flag 515 * gport - (OUT)- gport to to construct 516 * Returns: 517 * BCM_E_XXX 518 */ 519 STATIC int 520 _bcm_mirror_gport_construct(int unit, int port_tgid, int modid, uint32 flags, 521 bcm_gport_t *gport) 522 { 523 _bcm_gport_dest_t dest; 524 bcm_module_t mymodid; 525 int rv; 526 527 _bcm_gport_dest_t_init(&dest); 528 if (flags & BCM_MIRROR_PORT_DEST_TRUNK) { 529 dest.tgid = port_tgid; 530 dest.gport_type = _SHR_GPORT_TYPE_TRUNK; 531 } else { 532 dest.port = port_tgid; 533 if (IS_ST_PORT(unit, port_tgid)) { 534 rv = bcm_esw_stk_my_modid_get(unit, &mymodid); 535 if (BCM_E_UNAVAIL == rv) { 536 dest.gport_type = _SHR_GPORT_TYPE_DEVPORT; 537 } else { 538 dest.gport_type = _SHR_GPORT_TYPE_MODPORT; 539 dest.modid = modid; 540 } 541 } else { 542 dest.gport_type = _SHR_GPORT_TYPE_MODPORT; 543 dest.modid = modid; 544 } 545 } 546 BCM_IF_ERROR_RETURN( 547 _bcm_esw_gport_construct(unit, &dest, gport)); 548 549 return BCM_E_NONE; 550 } 551 552 /* 553 * Function: 554 * _bcm_mirror_destination_gport_parse 555 * Description: 556 * Parse mirror destinations gport. 557 * Parameters: 558 * unit - BCM device number 559 * mirror_dest_id - mirror destination id. 560 * dest_mod - (OUT) module id of mirror-to port 561 * dest_port - (OUT) mirror-to port 562 * flags - (OUT) Trunk flag 563 * Returns: 564 * BCM_E_XXX 565 */ 566 STATIC int 567 _bcm_mirror_destination_gport_parse(int unit, bcm_gport_t mirror_dest_id, 568 bcm_module_t *dest_mod, bcm_port_t *dest_port, 569 uint32 *flags) 570 { 571 bcm_mirror_destination_t mirror_dest; 572 bcm_module_t modid; 573 bcm_port_t port; 574 bcm_trunk_t tgid; 575 int id; 576 577 578 BCM_IF_ERROR_RETURN 579 (bcm_esw_mirror_destination_get(unit, mirror_dest_id, &mirror_dest)); 580 581 BCM_IF_ERROR_RETURN( 582 _bcm_esw_gport_resolve(unit, mirror_dest.gport, &modid, &port, 583 &tgid, &id)); 584 585 #if defined(BCM_HGPROXY_COE_SUPPORT) 586 if (soc_feature(unit, soc_feature_hgproxy_subtag_coe) && 587 BCM_GPORT_IS_SET( mirror_dest.gport) && 588 _BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT (unit, 589 mirror_dest.gport)) { 590 id = -1; 591 } else 592 #endif 593 594 #if defined(BCM_KATANA2_SUPPORT) 595 if (BCM_GPORT_IS_SET( mirror_dest.gport) && 596 _BCM_KT2_GPORT_IS_LINKPHY_OR_SUBTAG_SUBPORT_GPORT (unit, 597 mirror_dest.gport)) { 598 id = -1; 599 } 600 #endif 601 602 if (-1 != id) { 603 return BCM_E_PARAM; 604 } 605 606 if (BCM_TRUNK_INVALID != tgid) { 607 if (NULL != dest_mod) { 608 *dest_mod = -1; 609 } 610 if (NULL != dest_port) { 611 *dest_port = tgid; 612 } 613 if (NULL != flags) { 614 *flags |= BCM_MIRROR_PORT_DEST_TRUNK; 615 } 616 } else { 617 if (NULL != dest_mod) { 618 *dest_mod = modid; 619 } 620 if (NULL != dest_port) { 621 *dest_port = port; 622 } 623 } 624 625 return (BCM_E_NONE); 626 } 627 628 #if defined (BCM_TOMAHAWK3_SUPPORT) 629 int _bcm_esw_mirror_zero_profile_ref_count_get(int unit, 630 uint32 profile_index, 631 int *ref_count) 632 { 633 soc_profile_mem_t *profile; 634 635 if (NULL == ref_count) { 636 return (BCM_E_PARAM); 637 } 638 639 profile = &(MIRROR_CONFIG(unit)->mirror_zeroing_profile); 640 return (soc_profile_mem_ref_count_get(unit, profile, 641 profile_index, ref_count)); 642 643 } 644 645 646 int _bcm_esw_mirror_zero_profile_get(int unit, 647 soc_profile_mem_t **profile) 648 { 649 650 *profile = &(MIRROR_CONFIG(unit)->mirror_zeroing_profile); 651 return BCM_E_NONE; 652 653 } 654 655 /* Creates a mirror zeroing profile and returns the profile index. 656 This function need to be called only when all parameters 657 are validated before. */ 658 659 STATIC int _bcm_esw_mirror_payload_zero_profile_create( 660 int unit, 661 bcm_mirror_payload_zero_offsets_t *mirror_payload_offset_info, 662 uint32 flags, 663 uint32 *profile_index) 664 { 665 egr_mirror_zero_offset_profile_entry_t entry_arr[1]; 666 uint32 *entry_ptr[1]; 667 int rv; 668 void *entries[1]; 669 soc_mem_t profile_mem = EGR_MIRROR_ZERO_OFFSET_PROFILEm; 670 soc_profile_mem_t *profile; 671 entry_ptr[0] = (uint32 *)(&entry_arr[0]); 672 entries[0] = (void *)&entry_arr[0]; 673 674 /* Reset redirection profile entry. */ 675 sal_memset(entry_arr, 0, 676 sizeof(egr_mirror_zero_offset_profile_entry_t)); 677 profile = &(MIRROR_CONFIG(unit)->mirror_zeroing_profile); 678 soc_mem_field32_set(unit, profile_mem, entry_ptr[0], 679 L2_OFFSETf, 680 mirror_payload_offset_info->l2_offset); 681 soc_mem_field32_set(unit, profile_mem, entry_ptr[0], 682 L3_OFFSETf, 683 mirror_payload_offset_info->l3_offset); 684 soc_mem_field32_set(unit, profile_mem, entry_ptr[0], 685 L3_UDP_OFFSETf, 686 mirror_payload_offset_info->udp_offset); 687 rv = soc_profile_mem_add(unit, profile, entries, 688 1, profile_index); 689 return rv; 690 } 691 #endif 692 693 int bcm_esw_mirror_payload_zero_profile_create( 694 int unit, 695 bcm_mirror_payload_zero_offsets_t *mirror_payload_offset_info, 696 uint32 flags, 697 uint32 *profile_index) 698 { 699 int rv; 700 701 #if defined (BCM_TOMAHAWK3_SUPPORT) 702 if ((NULL == mirror_payload_offset_info) || 703 (NULL == profile_index)) { 704 return BCM_E_PARAM; 705 } 706 707 if (!(flags & BCM_MIRROR_PAYLOAD_ZERO_FP)) { 708 return (BCM_E_PARAM); 709 } 710 if (SOC_IS_TOMAHAWK3(unit)) { 711 if ((mirror_payload_offset_info->l2_offset < 0) && 712 (mirror_payload_offset_info->l2_offset > 0x3f)) { 713 return (BCM_E_PARAM); 714 } 715 if ((mirror_payload_offset_info->l3_offset < 0) && 716 (mirror_payload_offset_info->l3_offset > 0x3f)) { 717 return (BCM_E_PARAM); 718 } 719 if ((mirror_payload_offset_info->udp_offset < 0) && 720 (mirror_payload_offset_info->udp_offset > 0x3f)) { 721 return (BCM_E_PARAM); 722 } 723 724 rv = _bcm_esw_mirror_payload_zero_profile_create(unit, 725 mirror_payload_offset_info, 726 flags, profile_index); 727 } else 728 #endif 729 { 730 rv = BCM_E_UNAVAIL; 731 } 732 733 return rv; 734 735 } 736 737 738 /* Destroys a mirror zeroing profile for the given profile index. */ 739 int bcm_esw_mirror_payload_zero_profile_destroy( 740 int unit, 741 uint32 flags, 742 uint32 profile_index) 743 { 744 #if defined (BCM_TOMAHAWK3_SUPPORT) 745 soc_profile_mem_t *profile; 746 747 if (!(flags & BCM_MIRROR_PAYLOAD_ZERO_FP)) { 748 return (BCM_E_PARAM); 749 } 750 751 if ((profile_index < MIRROR_ZERO_PROFILE_INDEX_MIN) 752 && (profile_index > MIRROR_ZERO_PROFILE_INDEX_MAX)) { 753 return (BCM_E_PARAM); 754 } 755 756 profile = &(MIRROR_CONFIG(unit)->mirror_zeroing_profile); 757 758 759 if (SOC_IS_TOMAHAWK3(unit)) { 760 return (soc_profile_mem_delete(unit, profile, profile_index)); 761 } else 762 #endif 763 { 764 return BCM_E_UNAVAIL; 765 } 766 } 767 768 #ifdef BCM_TRIDENT3_SUPPORT 769 770 771 #define MIRROR_EDIT_CTRL_ID_PSAMP 1 772 #define MIRROR_EDIT_CTRL_ID_RSPAN_INGRESS_MIRROR 2 773 #define MIRROR_EDIT_CTRL_ID_RSPAN_EGRESS_MIRROR 3 774 775 #define MIRROR_EDIT_CTRL_ID_INGRESS_MIRROR_LOCAL_MTP 4 776 #define MIRROR_EDIT_CTRL_ID_INGRESS_MIRROR_REMOTE_MTP 4 777 #define MIRROR_EDIT_CTRL_ID_INGRESS_MIRROR_HG_UNTAG 4 778 #define MIRROR_EDIT_CTRL_ID_INGRESS_MIRROR_HG_TAG 5 779 780 #define MIRROR_EDIT_CTRL_ID_SFLOW_INGRESS_MIRROR 6 781 #define MIRROR_EDIT_CTRL_ID_SFLOW_UNTAG_INGRESS_MIRROR 7 782 783 #define MIRROR_EDIT_CTRL_ID_ERSPAN_EGRESS_MIRROR 8 784 #define MIRROR_EDIT_CTRL_ID_ERSPAN_EGRESS_MIRROR_UNTAG_PAYLOAD 9 785 786 #define MIRROR_EDIT_CTRL_ID_ERSPAN_INGRESS_MIRROR 10 787 #define MIRROR_EDIT_CTRL_ID_ERSPAN_INGRESS_MIRROR_UNTAG_PAYLOAD 11 788 789 #define MIRROR_EDIT_CTRL_ID_ERSPAN_UNTAG_EGRESS_MIRROR 12 790 #define MIRROR_EDIT_CTRL_ID_ERSPAN_UNTAG_EGRESS_MIRROR_UNTAG_PAYLOAD 13 791 792 #define MIRROR_EDIT_CTRL_ID_ERSPAN_UNTAG_INGRESS_MIRROR 14 793 #define MIRROR_EDIT_CTRL_ID_ERSPAN_UNTAG_INGRESS_MIRROR_UNTAG_PAYLOAD 15 794 795 #define MIRROR_EDIT_CTRL_ID_SFLOW_VNTAG 16 796 #define MIRROR_EDIT_CTRL_ID_SFLOW_VNTAG_OTAG 17 797 #define MIRROR_EDIT_CTRL_ID_SFLOW_ETAG 18 798 #define MIRROR_EDIT_CTRL_ID_SFLOW_ETAG_OTAG 19 799 800 #define MIRROR_EDIT_CTRL_ID_PSAMP_UNTAG 20 801 #define MIRROR_EDIT_CTRL_ID_PSAMP_TRUNCATE 21 802 #define MIRROR_EDIT_CTRL_ID_PSAMP_IPV6 22 803 #define MIRROR_EDIT_CTRL_ID_PSAMP_VNTAG_OTAG 23 804 805 #define MIRROR_EDIT_CTRL_ID_ERSPAN_GRE_SEQUENCE_INGRESS_MIRROR 24 806 #define MIRROR_EDIT_CTRL_ID_ERSPAN_GRE_SEQUENCE_EGRESS_MIRROR 25 807 808 #define MIRROR_EDIT_CTRL_ID_RSPAN_INGRESS_MIRROR_WITH_VNTAG 26 809 #define MIRROR_EDIT_CTRL_ID_RSPAN_EGRESS_MIRROR_WITH_VNTAG 27 810 811 #define MIRROR_EDIT_CTRL_ID_VXLAN 30 812 #define MIRROR_EDIT_CTRL_ID_VXLAN_IPV6 36 813 814 #define MIRROR_EDIT_CTRL_ID_ERSPAN3_INGRESS_MIRROR 31 815 #define MIRROR_EDIT_CTRL_ID_ERSPAN3_INGRESS_MIRROR_NO_SUBHDR 33 816 817 #define MIRROR_EDIT_CTRL_ID_INT_PROBE 37 818 #define MIRROR_EDIT_CTRL_ID_IFA 32 819 820 #define MIRROR_EDIT_CTRL_ID_ERSPAN_IPV6_INGRESS_MIRROR 38 821 #define MIRROR_EDIT_CTRL_ID_ERSPAN_UNTAG_IPV6_INGRESS_MIRROR 39 822 #define MIRROR_EDIT_CTRL_ID_ERSPAN_IPV6_INGRESS_MIRROR_UNTAG_PAYLOAD 40 823 #define MIRROR_EDIT_CTRL_ID_ERSPAN_UNTAG_IPV6_INGRESS_MIRROR_UNTAG_PAYLOAD 41 824 #define MIRROR_EDIT_CTRL_ID_ERSPAN_GRE_SEQUENCE_IPV6_INGRESS_MIRROR 42 825 #define EGR_MIRROR_TABLE_PROFILE_DEFAULT 0 826 #define EGR_MIRROR_TABLE_ENTRIES 0 827 #define EGR_MIRROR_TABLE_ENTRIES_NUM 1 828 #define EGR_MIRROR_FLEX_EDITOR_WIDTH 40 829 830 /* 831 * Function: 832 * _bcm_td3_egr_mirror_table_entry_add 833 * Purpose: 834 * Internal function for adding an entry to the EGR_MIRROR_TABLE* tables 835 * Adds an entry to the global shared SW copy of the EGR_MIRROR_TABLE* 836 * tables 837 * Parameters: 838 * unit - (IN) Device number. 839 * entries - (IN) Pointer to EGR_MIRROR_TABLE* entries array 840 * index - (OUT) Base index for the entires allocated in HW 841 * Returns: 842 * BCM_X_XXX 843 */ 844 int 845 _bcm_td3_egr_mirror_table_entry_add(int unit, void **entries, uint32 *index) 846 { 847 return soc_profile_mem_add(unit, EGR_MIRROR_TABLE(unit), entries, 848 1, index); 849 } 850 851 /* 852 * Function: 853 * _bcm_td3_egr_mirror_table_entry_delete 854 * Purpose: 855 * Internal function for deleting an entry from the EGR_MIRROR_TABLE* 856 * tables 857 * Deletes an entry from the global shared SW copy of the 858 * EGR_MIRROR_TABLE* tables 859 * Parameters: 860 * unit - (IN) Device number. 861 * index - (OUT) Base index for the entires allocated in HW 862 * Returns: 863 * BCM_X_XXX 864 */ 865 int 866 _bcm_td3_egr_mirror_table_entry_delete(int unit, uint32 index) 867 { 868 return soc_profile_mem_delete(unit, EGR_MIRROR_TABLE(unit), index); 869 } 870 871 STATIC int _is_edit_ctrl_id_ipv6(int id) 872 { 873 return (((id == MIRROR_EDIT_CTRL_ID_PSAMP_IPV6) || 874 (id == MIRROR_EDIT_CTRL_ID_ERSPAN_IPV6_INGRESS_MIRROR) || 875 (id == MIRROR_EDIT_CTRL_ID_ERSPAN_UNTAG_IPV6_INGRESS_MIRROR) || 876 (id == MIRROR_EDIT_CTRL_ID_ERSPAN_IPV6_INGRESS_MIRROR_UNTAG_PAYLOAD) || 877 (id == MIRROR_EDIT_CTRL_ID_ERSPAN_UNTAG_IPV6_INGRESS_MIRROR_UNTAG_PAYLOAD) || 878 (id == MIRROR_EDIT_CTRL_ID_ERSPAN_GRE_SEQUENCE_IPV6_INGRESS_MIRROR) || 879 (id == MIRROR_EDIT_CTRL_ID_VXLAN_IPV6))? 1 : 0); 880 } 881 882 STATIC int _is_edit_ctrl_id_egress(int id) 883 { 884 int egress = 0; 885 switch(id) { 886 case MIRROR_EDIT_CTRL_ID_RSPAN_EGRESS_MIRROR: 887 case MIRROR_EDIT_CTRL_ID_ERSPAN_EGRESS_MIRROR: 888 case MIRROR_EDIT_CTRL_ID_ERSPAN_EGRESS_MIRROR_UNTAG_PAYLOAD: 889 case MIRROR_EDIT_CTRL_ID_ERSPAN_UNTAG_EGRESS_MIRROR: 890 case MIRROR_EDIT_CTRL_ID_ERSPAN_UNTAG_EGRESS_MIRROR_UNTAG_PAYLOAD: 891 case MIRROR_EDIT_CTRL_ID_ERSPAN_GRE_SEQUENCE_EGRESS_MIRROR: 892 case MIRROR_EDIT_CTRL_ID_RSPAN_EGRESS_MIRROR_WITH_VNTAG: 893 egress = 1; 894 break; 895 default: 896 egress = 0; 897 break; 898 } 899 return (egress); 900 } 901 902 STATIC int _is_edit_ctrl_id_vntag(int id) 903 { 904 return (((id == MIRROR_EDIT_CTRL_ID_RSPAN_INGRESS_MIRROR_WITH_VNTAG) || 905 (id == MIRROR_EDIT_CTRL_ID_RSPAN_EGRESS_MIRROR_WITH_VNTAG) || 906 (id == MIRROR_EDIT_CTRL_ID_PSAMP_VNTAG_OTAG) || 907 (id == MIRROR_EDIT_CTRL_ID_SFLOW_VNTAG) || 908 (id == MIRROR_EDIT_CTRL_ID_SFLOW_VNTAG_OTAG)) ? 1 : 0); 909 } 910 911 STATIC int _is_edit_ctrl_id_vxlan(int id) 912 { 913 return (((id == MIRROR_EDIT_CTRL_ID_VXLAN_IPV6) || 914 (id == MIRROR_EDIT_CTRL_ID_VXLAN)) ? 1 : 0); 915 } 916 917 STATIC int _is_edit_ctrl_id_int_probe(int id) 918 { 919 return (((id == MIRROR_EDIT_CTRL_ID_INT_PROBE) || 920 (id == MIRROR_EDIT_CTRL_ID_IFA)) ? 1 : 0); 921 } 922 923 STATIC int _is_edit_ctrl_id_psamp(int id) 924 { 925 return (((id == MIRROR_EDIT_CTRL_ID_PSAMP_UNTAG) || 926 (id == MIRROR_EDIT_CTRL_ID_PSAMP_IPV6) || 927 (id == MIRROR_EDIT_CTRL_ID_PSAMP_TRUNCATE) || 928 (id == MIRROR_EDIT_CTRL_ID_PSAMP_VNTAG_OTAG) || 929 (id == MIRROR_EDIT_CTRL_ID_PSAMP)) ? 1 : 0); 930 } 931 932 STATIC int _is_edit_ctrl_id_sflow(int id) 933 { 934 if ((id == MIRROR_EDIT_CTRL_ID_SFLOW_INGRESS_MIRROR) || 935 (id == MIRROR_EDIT_CTRL_ID_SFLOW_UNTAG_INGRESS_MIRROR) || 936 (id == MIRROR_EDIT_CTRL_ID_SFLOW_VNTAG_OTAG) || 937 (id == MIRROR_EDIT_CTRL_ID_SFLOW_ETAG) || 938 (id == MIRROR_EDIT_CTRL_ID_SFLOW_ETAG_OTAG) || 939 (id == MIRROR_EDIT_CTRL_ID_SFLOW_VNTAG)) { 940 return (1); 941 } 942 return (0); 943 } 944 945 STATIC int _is_edit_ctrl_id_rspan(int id) 946 { 947 if ((id == MIRROR_EDIT_CTRL_ID_RSPAN_INGRESS_MIRROR) || 948 (id == MIRROR_EDIT_CTRL_ID_RSPAN_EGRESS_MIRROR) || 949 (id == MIRROR_EDIT_CTRL_ID_RSPAN_INGRESS_MIRROR_WITH_VNTAG) || 950 (id == MIRROR_EDIT_CTRL_ID_RSPAN_EGRESS_MIRROR_WITH_VNTAG)) { 951 return (1); 952 } 953 return (0); 954 } 955 956 STATIC int _is_edit_ctrl_id_erspan_seq(int id) 957 { 958 if ((id == MIRROR_EDIT_CTRL_ID_ERSPAN_GRE_SEQUENCE_INGRESS_MIRROR) || 959 (id == MIRROR_EDIT_CTRL_ID_ERSPAN_GRE_SEQUENCE_IPV6_INGRESS_MIRROR) || 960 (id == MIRROR_EDIT_CTRL_ID_ERSPAN_GRE_SEQUENCE_EGRESS_MIRROR)) { 961 return (1); 962 } 963 return (0); 964 } 965 966 STATIC int _is_edit_ctrl_id_erspan(int id) 967 { 968 if ((id == MIRROR_EDIT_CTRL_ID_ERSPAN_EGRESS_MIRROR) || 969 (id == MIRROR_EDIT_CTRL_ID_ERSPAN_EGRESS_MIRROR_UNTAG_PAYLOAD) || 970 (id == MIRROR_EDIT_CTRL_ID_ERSPAN_INGRESS_MIRROR) || 971 (id == MIRROR_EDIT_CTRL_ID_ERSPAN_INGRESS_MIRROR_UNTAG_PAYLOAD)|| 972 (id == MIRROR_EDIT_CTRL_ID_ERSPAN_GRE_SEQUENCE_INGRESS_MIRROR) || 973 (id == MIRROR_EDIT_CTRL_ID_ERSPAN_GRE_SEQUENCE_EGRESS_MIRROR) || 974 (id == MIRROR_EDIT_CTRL_ID_ERSPAN_UNTAG_EGRESS_MIRROR) || 975 (id == MIRROR_EDIT_CTRL_ID_ERSPAN_UNTAG_EGRESS_MIRROR_UNTAG_PAYLOAD) || 976 (id == MIRROR_EDIT_CTRL_ID_ERSPAN_UNTAG_INGRESS_MIRROR) || 977 (id == MIRROR_EDIT_CTRL_ID_ERSPAN_UNTAG_INGRESS_MIRROR_UNTAG_PAYLOAD) || 978 (id == MIRROR_EDIT_CTRL_ID_ERSPAN_IPV6_INGRESS_MIRROR) || 979 (id == MIRROR_EDIT_CTRL_ID_ERSPAN_UNTAG_IPV6_INGRESS_MIRROR) || 980 (id == MIRROR_EDIT_CTRL_ID_ERSPAN_IPV6_INGRESS_MIRROR_UNTAG_PAYLOAD) || 981 (id == MIRROR_EDIT_CTRL_ID_ERSPAN_UNTAG_IPV6_INGRESS_MIRROR_UNTAG_PAYLOAD) || 982 (id == MIRROR_EDIT_CTRL_ID_ERSPAN_GRE_SEQUENCE_IPV6_INGRESS_MIRROR) || 983 (id == MIRROR_EDIT_CTRL_ID_ERSPAN3_INGRESS_MIRROR) || 984 (id == MIRROR_EDIT_CTRL_ID_ERSPAN3_INGRESS_MIRROR_NO_SUBHDR)) { 985 return (1); 986 } 987 return (0); 988 } 989 990 STATIC int _is_edit_ctrl_id_erspan_tagged(int id) 991 { 992 if ((id == MIRROR_EDIT_CTRL_ID_ERSPAN_EGRESS_MIRROR) || 993 (id == MIRROR_EDIT_CTRL_ID_ERSPAN_EGRESS_MIRROR_UNTAG_PAYLOAD) || 994 (id == MIRROR_EDIT_CTRL_ID_ERSPAN_GRE_SEQUENCE_INGRESS_MIRROR) || 995 (id == MIRROR_EDIT_CTRL_ID_ERSPAN_GRE_SEQUENCE_EGRESS_MIRROR) || 996 (id == MIRROR_EDIT_CTRL_ID_ERSPAN_INGRESS_MIRROR) || 997 (id == MIRROR_EDIT_CTRL_ID_ERSPAN_INGRESS_MIRROR_UNTAG_PAYLOAD) || 998 (id == MIRROR_EDIT_CTRL_ID_ERSPAN_GRE_SEQUENCE_IPV6_INGRESS_MIRROR) || 999 (id == MIRROR_EDIT_CTRL_ID_ERSPAN_IPV6_INGRESS_MIRROR) || 1000 (id == MIRROR_EDIT_CTRL_ID_ERSPAN_IPV6_INGRESS_MIRROR_UNTAG_PAYLOAD) || 1001 (id == MIRROR_EDIT_CTRL_ID_ERSPAN3_INGRESS_MIRROR) || 1002 (id == MIRROR_EDIT_CTRL_ID_ERSPAN3_INGRESS_MIRROR_NO_SUBHDR)) { 1003 return (1); 1004 } 1005 return (0); 1006 } 1007 1008 #define ENCAP_PROF_INDEX_VAR_CNT 4 1009 1010 #define ENCAP_PROF_PSAMP_LOCAL_MTP 52 1011 #define ENCAP_PROF_PSAMP_TRUNCATE_LOCAL_MTP 53 1012 #define ENCAP_PROF_SFLOW_INGRESS_MIRROR_LOCAL_MTP 54 1013 #define ENCAP_PROF_SFLOW_VNTAG_LOCAL_MTP 55 1014 #define ENCAP_PROF_SFLOW_ETAG_LOCAL_MTP 56 1015 #define ENCAP_PROF_SFLOW_VNTAG_OTAG_LOCAL_MTP 57 1016 #define ENCAP_PROF_RSPAN_INGRESS_MIRROR_LOCAL_MTP 58 1017 #define ENCAP_PROF_RSPAN_EGRESS_MIRROR_LOCAL_MTP 59 1018 #define ENCAP_PROF_ERSPAN_INGRESS_MIRROR_LOCAL_MTP 60 1019 #define ENCAP_PROF_ERSPAN_EGRESS_MIRROR_LOCAL_MTP 61 1020 #define ENCAP_PROF_PSAMP_IPV6_LOCAL_MTP 62 1021 #define ENCAP_PROF_PSAMP_IPV6_REMOTE_MTP 63 1022 #define ENCAP_PROF_VXLAN_LOCAL_MTP 64 1023 #define ENCAP_PROF_VXLAN_REMOTE_MTP 65 1024 #define ENCAP_PROF_VXLAN_IPV6_LOCAL_MTP 66 1025 #define ENCAP_PROF_VXLAN_IPV6_REMOTE_MTP 67 1026 #define ENCAP_PROF_ERSPAN3_INGRESS_MIRROR_LOCAL_MTP 68 1027 #define ENCAP_PROF_ERSPAN3_INGRESS_MIRROR_REMOTE_MTP 69 1028 #define ENCAP_PROF_ERSPAN3_INGRESS_MIRROR_NO_SUBHDR_LOCAL_MTP 70 1029 #define ENCAP_PROF_ERSPAN3_INGRESS_MIRROR_NO_SUBHDR_REMOTE_MTP 71 1030 #define ENCAP_PROF_INT_PROBE_LOCAL_MTP 72 1031 #define ENCAP_PROF_IFA_LOCAL_MTP 73 1032 #define ENCAP_PROF_ERSPAN_IPV6_INGRESS_MIRROR_LOCAL_MTP 74 1033 #define ENCAP_PROF_ERSPAN_IPV6_INGRESS_MIRROR_REMOTE_MTP 75 1034 #define ENCAP_PROF_ERSPAN_UNTAG_IPV6_INGRESS_MIRROR_LOCAL_MTP 76 1035 #define ENCAP_PROF_ERSPAN_UNTAG_IPV6_INGRESS_MIRROR_REMOTE_MTP 77 1036 #define ENCAP_PROF_ERSPAN_IPV6_INGRESS_MIRROR_UNTAG_PAYLOAD_LOCAL_MTP 78 1037 #define ENCAP_PROF_ERSPAN_IPV6_INGRESS_MIRROR_UNTAG_PAYLOAD_REMOTE_MTP 79 1038 #define ENCAP_PROF_ERSPAN_UNTAG_IPV6_INGRESS_MIRROR_UNTAG_PAYLOAD_LOCAL_MTP 80 1039 #define ENCAP_PROF_ERSPAN_UNTAG_IPV6_INGRESS_MIRROR_UNTAG_PAYLOAD_REMOTE_MTP 81 1040 #define ENCAP_PROF_ERSPAN_GRE_SEQUENCE_IPV6_INGRESS_MIRROR_LOCAL_MTP 82 1041 #define ENCAP_PROF_ERSPAN_GRE_SEQUENCE_IPV6_INGRESS_MIRROR_REMOTE_MTP 83 1042 1043 1044 #define ENCAP_PROF_PSAMP_UNTAG_LOCAL_MTP 16 1045 #define ENCAP_PROF_PSAMP_VNTAG_OTAG_LOCAL_MTP 17 1046 #define ENCAP_PROF_SFLOW_ETAG_OTAG_LOCAL_MTP 18 1047 #define ENCAP_PROF_SFLOW_UNTAG_INGRESS_MIRROR_LOCAL_MTP 19 1048 #define ENCAP_PROF_RSPAN_INGRESS_MIRROR_WITH_VNTAG_LOCAL_MTP 20 1049 #define ENCAP_PROF_RSPAN_EGRESS_MIRROR_WITH_VNTAG_LOCAL_MTP 21 1050 #define ENCAP_PROF_ERSPAN_EGRESS_MIRROR_UNTAG_PAYLOAD_LOCAL_MTP 22 1051 #define ENCAP_PROF_ERSPAN_INGRESS_MIRROR_UNTAG_PAYLOAD_LOCAL_MTP 23 1052 #define ENCAP_PROF_ERSPAN_UNTAG_INGRESS_MIRROR_LOCAL_MTP 24 1053 #define ENCAP_PROF_ERSPAN_UNTAG_INGRESS_MIRROR_UNTAG_PAYLOAD_LOCAL_MTP 25 1054 #define ENCAP_PROF_ERSPAN_UNTAG_EGRESS_MIRROR_LOCAL_MTP 26 1055 #define ENCAP_PROF_ERSPAN_UNTAG_EGRESS_MIRROR_UNTAG_PAYLOAD_LOCAL_MTP 27 1056 #define ENCAP_PROF_ERSPAN_GRE_SEQUENCE_INGRESS_MIRROR_LOCAL_MTP 28 1057 #define ENCAP_PROF_ERSPAN_GRE_SEQUENCE_EGRESS_MIRROR_LOCAL_MTP 29 1058 1059 #define ENCAP_PROF_PSAMP_REMOTE_MTP 30 1060 #define ENCAP_PROF_PSAMP_UNTAG_REMOTE_MTP 31 1061 #define ENCAP_PROF_PSAMP_TRUNCATE_REMOTE_MTP 32 1062 #define ENCAP_PROF_PSAMP_VNTAG_OTAG_REMOTE_MTP 33 1063 #define ENCAP_PROF_SFLOW_INGRESS_MIRROR_REMOTE_MTP 34 1064 #define ENCAP_PROF_SFLOW_ETAG_OTAG_REMOTE_MTP 35 1065 #define ENCAP_PROF_SFLOW_ETAG_REMOTE_MTP 36 1066 #define ENCAP_PROF_SFLOW_VNTAG_REMOTE_MTP 37 1067 #define ENCAP_PROF_SFLOW_VNTAG_OTAG_REMOTE_MTP 38 1068 #define ENCAP_PROF_SFLOW_UNTAG_INGRESS_MIRROR_REMOTE_MTP 39 1069 #define ENCAP_PROF_RSPAN_INGRESS_MIRROR_WITH_VNTAG_REMOTE_MTP 40 1070 #define ENCAP_PROF_RSPAN_EGRESS_MIRROR_WITH_VNTAG_REMOTE_MTP 41 1071 #define ENCAP_PROF_ERSPAN_INGRESS_MIRROR_REMOTE_MTP 42 1072 #define ENCAP_PROF_ERSPAN_EGRESS_MIRROR_REMOTE_MTP 43 1073 #define ENCAP_PROF_ERSPAN_GRE_SEQUENCE_INGRESS_MIRROR_REMOTE_MTP 44 1074 #define ENCAP_PROF_ERSPAN_GRE_SEQUENCE_EGRESS_MIRROR_REMOTE_MTP 45 1075 #define ENCAP_PROF_ERSPAN_INGRESS_MIRROR_UNTAG_PAYLOAD_REMOTE_MTP 46 1076 #define ENCAP_PROF_ERSPAN_EGRESS_MIRROR_UNTAG_PAYLOAD_REMOTE_MTP 47 1077 #define ENCAP_PROF_ERSPAN_UNTAG_INGRESS_MIRROR_REMOTE_MTP 48 1078 #define ENCAP_PROF_ERSPAN_UNTAG_INGRESS_MIRROR_UNTAG_PAYLOAD_REMOTE_MTP 49 1079 #define ENCAP_PROF_ERSPAN_UNTAG_EGRESS_MIRROR_REMOTE_MTP 50 1080 #define ENCAP_PROF_ERSPAN_UNTAG_EGRESS_MIRROR_UNTAG_PAYLOAD_REMOTE_MTP 51 1081 1082 #define TD3_PSAMP_TRUNCATE_LEN_ADJUST 60 1083 #define TD3_PSAMP_TRUNCATE_UDP_LEN_ADJUST 40 1084 1085 STATIC int 1086 _bcm_td3_mirror_cancun_app_get(int unit, int edit_ctrl_id, int encap_profile_index, uint32 *app) 1087 { 1088 switch(encap_profile_index) { 1089 /* PSAMP IPV6 LOCAL */ 1090 case ENCAP_PROF_PSAMP_IPV6_LOCAL_MTP: 1091 *app = CANCUN_APP__MIRROR__PSAMP_IPV6_LOCAL_MTP; 1092 break; 1093 1094 /* PSAMP IPV6 REMOTE */ 1095 case ENCAP_PROF_PSAMP_IPV6_REMOTE_MTP: 1096 *app = CANCUN_APP__MIRROR__PSAMP_IPV6_REMOTE_MTP; 1097 break; 1098 1099 /* PSAMP LOCAL */ 1100 case ENCAP_PROF_PSAMP_LOCAL_MTP: 1101 *app = CANCUN_APP__MIRROR__PSAMP_LOCAL_MTP; 1102 break; 1103 1104 case ENCAP_PROF_PSAMP_TRUNCATE_LOCAL_MTP: 1105 *app = CANCUN_APP__MIRROR__PSAMP_TRUNCATE_LOCAL_MTP; 1106 break; 1107 1108 case ENCAP_PROF_PSAMP_VNTAG_OTAG_LOCAL_MTP: 1109 *app = CANCUN_APP__MIRROR__PSAMP_VNTAG_OTAG_LOCAL_MTP; 1110 break; 1111 1112 /* PSAMP REMOTE */ 1113 case ENCAP_PROF_PSAMP_REMOTE_MTP: 1114 *app = CANCUN_APP__MIRROR__PSAMP_REMOTE_MTP; 1115 break; 1116 1117 case ENCAP_PROF_PSAMP_TRUNCATE_REMOTE_MTP: 1118 *app = CANCUN_APP__MIRROR__PSAMP_TRUNCATE_REMOTE_MTP; 1119 break; 1120 1121 case ENCAP_PROF_PSAMP_VNTAG_OTAG_REMOTE_MTP: 1122 *app = CANCUN_APP__MIRROR__PSAMP_VNTAG_OTAG_REMOTE_MTP; 1123 break; 1124 1125 /* RSPAN INGRESS LOCAL */ 1126 case ENCAP_PROF_RSPAN_INGRESS_MIRROR_LOCAL_MTP: 1127 *app = CANCUN_APP__MIRROR__RSPAN_INGRESS_MIRROR_LOCAL_MTP; 1128 break; 1129 1130 case ENCAP_PROF_RSPAN_INGRESS_MIRROR_WITH_VNTAG_LOCAL_MTP: 1131 *app = CANCUN_APP__MIRROR__RSPAN_INGRESS_MIRROR_WITH_VNTAG_LOCAL_MTP; 1132 break; 1133 1134 /* RSPAN INGRESS REMOTE */ 1135 case ENCAP_PROF_RSPAN_INGRESS_MIRROR_WITH_VNTAG_REMOTE_MTP: 1136 *app = CANCUN_APP__MIRROR__RSPAN_INGRESS_MIRROR_WITH_VNTAG_REMOTE_MTP; 1137 break; 1138 1139 /* RSPAN EGRESS LOCAL */ 1140 case ENCAP_PROF_RSPAN_EGRESS_MIRROR_LOCAL_MTP: 1141 *app = CANCUN_APP__MIRROR__RSPAN_EGRESS_MIRROR_LOCAL_MTP; 1142 break; 1143 1144 case ENCAP_PROF_RSPAN_EGRESS_MIRROR_WITH_VNTAG_LOCAL_MTP: 1145 *app = CANCUN_APP__MIRROR__RSPAN_EGRESS_MIRROR_WITH_VNTAG_LOCAL_MTP; 1146 break; 1147 1148 /* RSPAN EGRESS REMOTE */ 1149 case ENCAP_PROF_RSPAN_EGRESS_MIRROR_WITH_VNTAG_REMOTE_MTP: 1150 *app = CANCUN_APP__MIRROR__RSPAN_EGRESS_MIRROR_WITH_VNTAG_REMOTE_MTP; 1151 break; 1152 1153 /* SFLOW INGRESS LOCAL TAG/UNTAG */ 1154 case ENCAP_PROF_SFLOW_INGRESS_MIRROR_LOCAL_MTP: 1155 *app = CANCUN_APP__MIRROR__SFLOW_LOCAL_MTP; 1156 break; 1157 1158 case ENCAP_PROF_SFLOW_UNTAG_INGRESS_MIRROR_LOCAL_MTP: 1159 *app = CANCUN_APP__MIRROR__SFLOW_UNTAG_LOCAL_MTP; 1160 break; 1161 1162 /* SFLOW INGRESS REMOTE TAG/UNTAG */ 1163 case ENCAP_PROF_SFLOW_INGRESS_MIRROR_REMOTE_MTP: 1164 *app = CANCUN_APP__MIRROR__SFLOW_REMOTE_MTP; 1165 break; 1166 1167 case ENCAP_PROF_SFLOW_UNTAG_INGRESS_MIRROR_REMOTE_MTP: 1168 *app = CANCUN_APP__MIRROR__SFLOW_UNTAG_REMOTE_MTP; 1169 break; 1170 1171 /* SFLOW INGRESS LOCAL ETAG/ETAG+OTAG */ 1172 case ENCAP_PROF_SFLOW_ETAG_OTAG_LOCAL_MTP: 1173 *app = CANCUN_APP__MIRROR__SFLOW_ETAG_OTAG_LOCAL_MTP; 1174 break; 1175 1176 case ENCAP_PROF_SFLOW_ETAG_LOCAL_MTP: 1177 *app = CANCUN_APP__MIRROR__SFLOW_ETAG_LOCAL_MTP; 1178 break; 1179 1180 /* SFLOW INGRESS REMOTE ETAG/ETAG+OTAG */ 1181 case ENCAP_PROF_SFLOW_ETAG_OTAG_REMOTE_MTP: 1182 *app = CANCUN_APP__MIRROR__SFLOW_ETAG_OTAG_REMOTE_MTP; 1183 break; 1184 1185 case ENCAP_PROF_SFLOW_ETAG_REMOTE_MTP: 1186 *app = CANCUN_APP__MIRROR__SFLOW_ETAG_REMOTE_MTP; 1187 break; 1188 1189 /* SFLOW INGRESS LOCAL VNTAG/VNTAG+OTAG */ 1190 case ENCAP_PROF_SFLOW_VNTAG_LOCAL_MTP: 1191 *app = CANCUN_APP__MIRROR__SFLOW_VNTAG_LOCAL_MTP; 1192 break; 1193 1194 case ENCAP_PROF_SFLOW_VNTAG_OTAG_LOCAL_MTP: 1195 *app = CANCUN_APP__MIRROR__SFLOW_VNTAG_OTAG_LOCAL_MTP; 1196 break; 1197 1198 /* SFLOW INGRESS REMOTE VNTAG/VNTAG+OTAG */ 1199 case ENCAP_PROF_SFLOW_VNTAG_OTAG_REMOTE_MTP: 1200 *app = CANCUN_APP__MIRROR__SFLOW_VNTAG_OTAG_REMOTE_MTP; 1201 break; 1202 1203 case ENCAP_PROF_SFLOW_VNTAG_REMOTE_MTP: 1204 *app = CANCUN_APP__MIRROR__SFLOW_VNTAG_REMOTE_MTP; 1205 break; 1206 1207 /* ERSPAN INGRESS LOCAL */ 1208 case ENCAP_PROF_ERSPAN_INGRESS_MIRROR_LOCAL_MTP: 1209 *app = CANCUN_APP__MIRROR__ERSPAN_INGRESS_MIRROR_LOCAL_MTP; 1210 break; 1211 1212 case ENCAP_PROF_ERSPAN_INGRESS_MIRROR_UNTAG_PAYLOAD_LOCAL_MTP: 1213 *app = CANCUN_APP__MIRROR__ERSPAN_INGRESS_MIRROR_UNTAG_PAYLOAD_LOCAL_MTP; 1214 break; 1215 1216 case ENCAP_PROF_ERSPAN_UNTAG_INGRESS_MIRROR_LOCAL_MTP: 1217 *app = CANCUN_APP__MIRROR__ERSPAN_UNTAG_INGRESS_MIRROR_LOCAL_MTP; 1218 break; 1219 1220 case ENCAP_PROF_ERSPAN_UNTAG_INGRESS_MIRROR_UNTAG_PAYLOAD_LOCAL_MTP: 1221 *app = CANCUN_APP__MIRROR__ERSPAN_UNTAG_INGRESS_MIRROR_UNTAG_PAYLOAD_LOCAL_MTP; 1222 break; 1223 1224 /* ERSPAN INGRESS REMOTE */ 1225 case ENCAP_PROF_ERSPAN_UNTAG_INGRESS_MIRROR_UNTAG_PAYLOAD_REMOTE_MTP: 1226 *app = CANCUN_APP__MIRROR__ERSPAN_UNTAG_INGRESS_MIRROR_UNTAG_PAYLOAD_REMOTE_MTP; 1227 break; 1228 1229 case ENCAP_PROF_ERSPAN_INGRESS_MIRROR_REMOTE_MTP: 1230 *app = CANCUN_APP__MIRROR__ERSPAN_INGRESS_MIRROR_REMOTE_MTP; 1231 break; 1232 1233 case ENCAP_PROF_ERSPAN_UNTAG_INGRESS_MIRROR_REMOTE_MTP: 1234 *app = CANCUN_APP__MIRROR__ERSPAN_UNTAG_INGRESS_MIRROR_REMOTE_MTP; 1235 break; 1236 1237 case ENCAP_PROF_ERSPAN_INGRESS_MIRROR_UNTAG_PAYLOAD_REMOTE_MTP: 1238 *app = CANCUN_APP__MIRROR__ERSPAN_INGRESS_MIRROR_UNTAG_PAYLOAD_REMOTE_MTP; 1239 break; 1240 1241 /* ERSPAN EGRESS LOCAL */ 1242 case ENCAP_PROF_ERSPAN_EGRESS_MIRROR_LOCAL_MTP: 1243 *app = CANCUN_APP__MIRROR__ERSPAN_EGRESS_MIRROR_LOCAL_MTP; 1244 break; 1245 1246 case ENCAP_PROF_ERSPAN_EGRESS_MIRROR_UNTAG_PAYLOAD_LOCAL_MTP: 1247 *app = CANCUN_APP__MIRROR__ERSPAN_EGRESS_MIRROR_UNTAG_PAYLOAD_LOCAL_MTP; 1248 break; 1249 1250 case ENCAP_PROF_ERSPAN_UNTAG_EGRESS_MIRROR_LOCAL_MTP: 1251 *app = CANCUN_APP__MIRROR__ERSPAN_UNTAG_EGRESS_MIRROR_LOCAL_MTP; 1252 break; 1253 1254 case ENCAP_PROF_ERSPAN_UNTAG_EGRESS_MIRROR_UNTAG_PAYLOAD_LOCAL_MTP: 1255 *app = CANCUN_APP__MIRROR__ERSPAN_UNTAG_EGRESS_MIRROR_UNTAG_PAYLOAD_LOCAL_MTP; 1256 break; 1257 1258 /* ERSPAN EGRESS REMOTE */ 1259 case ENCAP_PROF_ERSPAN_EGRESS_MIRROR_REMOTE_MTP: 1260 *app = CANCUN_APP__MIRROR__ERSPAN_EGRESS_MIRROR_REMOTE_MTP; 1261 break; 1262 1263 case ENCAP_PROF_ERSPAN_EGRESS_MIRROR_UNTAG_PAYLOAD_REMOTE_MTP: 1264 *app = CANCUN_APP__MIRROR__ERSPAN_EGRESS_MIRROR_UNTAG_PAYLOAD_REMOTE_MTP; 1265 break; 1266 1267 case ENCAP_PROF_ERSPAN_UNTAG_EGRESS_MIRROR_REMOTE_MTP: 1268 *app = CANCUN_APP__MIRROR__ERSPAN_UNTAG_EGRESS_MIRROR_REMOTE_MTP; 1269 break; 1270 1271 case ENCAP_PROF_ERSPAN_UNTAG_EGRESS_MIRROR_UNTAG_PAYLOAD_REMOTE_MTP: 1272 *app = CANCUN_APP__MIRROR__ERSPAN_UNTAG_EGRESS_MIRROR_UNTAG_PAYLOAD_REMOTE_MTP; 1273 break; 1274 1275 /* INGRESS GRE LOCAL */ 1276 case ENCAP_PROF_ERSPAN_GRE_SEQUENCE_INGRESS_MIRROR_LOCAL_MTP: 1277 *app = CANCUN_APP__MIRROR__ERSPAN_GRE_SEQUENCE_INGRESS_MIRROR_LOCAL_MTP; 1278 break; 1279 1280 /* EGRESS GRE LOCAL */ 1281 case ENCAP_PROF_ERSPAN_GRE_SEQUENCE_EGRESS_MIRROR_LOCAL_MTP: 1282 *app = CANCUN_APP__MIRROR__ERSPAN_GRE_SEQUENCE_EGRESS_MIRROR_LOCAL_MTP; 1283 break; 1284 1285 /* INGRESS GRE REMOTE */ 1286 case ENCAP_PROF_ERSPAN_GRE_SEQUENCE_INGRESS_MIRROR_REMOTE_MTP: 1287 *app = CANCUN_APP__MIRROR__ERSPAN_GRE_SEQUENCE_INGRESS_MIRROR_REMOTE_MTP; 1288 break; 1289 1290 /* EGRESS GRE REMOTE */ 1291 case ENCAP_PROF_ERSPAN_GRE_SEQUENCE_EGRESS_MIRROR_REMOTE_MTP: 1292 *app = CANCUN_APP__MIRROR__ERSPAN_GRE_SEQUENCE_EGRESS_MIRROR_REMOTE_MTP; 1293 break; 1294 1295 case ENCAP_PROF_PSAMP_UNTAG_LOCAL_MTP: 1296 case ENCAP_PROF_PSAMP_UNTAG_REMOTE_MTP: 1297 return (BCM_E_UNAVAIL); 1298 break; 1299 1300 case ENCAP_PROF_VXLAN_LOCAL_MTP: 1301 *app = CANCUN_APP__MIRROR__VXLAN_INGRESS_MIRROR_LOCAL_MTP; 1302 break; 1303 1304 case ENCAP_PROF_VXLAN_REMOTE_MTP: 1305 *app = CANCUN_APP__MIRROR__VXLAN_INGRESS_MIRROR_REMOTE_MTP; 1306 break; 1307 1308 case ENCAP_PROF_VXLAN_IPV6_LOCAL_MTP: 1309 *app = CANCUN_APP__MIRROR__VXLAN_INGRESS_MIRROR_IPV6_LOCAL_MTP; 1310 break; 1311 1312 case ENCAP_PROF_VXLAN_IPV6_REMOTE_MTP: 1313 *app = CANCUN_APP__MIRROR__VXLAN_INGRESS_MIRROR_IPV6_REMOTE_MTP; 1314 break; 1315 1316 case ENCAP_PROF_ERSPAN3_INGRESS_MIRROR_LOCAL_MTP: 1317 *app = CANCUN_APP__MIRROR__ERSPAN3_INGRESS_MIRROR_LOCAL_MTP; 1318 break; 1319 1320 case ENCAP_PROF_ERSPAN3_INGRESS_MIRROR_REMOTE_MTP: 1321 *app = CANCUN_APP__MIRROR__ERSPAN3_INGRESS_MIRROR_REMOTE_MTP; 1322 break; 1323 1324 case ENCAP_PROF_ERSPAN3_INGRESS_MIRROR_NO_SUBHDR_LOCAL_MTP: 1325 *app = CANCUN_APP__MIRROR__ERSPAN3_INGRESS_MIRROR_NO_SUBHDR_LOCAL_MTP; 1326 break; 1327 1328 case ENCAP_PROF_ERSPAN3_INGRESS_MIRROR_NO_SUBHDR_REMOTE_MTP: 1329 *app = CANCUN_APP__MIRROR__ERSPAN3_INGRESS_MIRROR_NO_SUBHDR_REMOTE_MTP; 1330 break; 1331 1332 case ENCAP_PROF_IFA_LOCAL_MTP: 1333 *app = CANCUN_APP__MIRROR__IFA_EGRESS_MIRROR_LOCAL_MTP; 1334 break; 1335 1336 case ENCAP_PROF_INT_PROBE_LOCAL_MTP: 1337 *app = CANCUN_APP__MIRROR__INGRESS_MIRROR_WITH_INT_PROBE; 1338 break; 1339 1340 case ENCAP_PROF_ERSPAN_IPV6_INGRESS_MIRROR_LOCAL_MTP: 1341 *app = CANCUN_APP__MIRROR__ERSPAN_IPV6_INGRESS_MIRROR_LOCAL_MTP; 1342 break; 1343 case ENCAP_PROF_ERSPAN_IPV6_INGRESS_MIRROR_REMOTE_MTP: 1344 *app = CANCUN_APP__MIRROR__ERSPAN_IPV6_INGRESS_MIRROR_REMOTE_MTP; 1345 break; 1346 case ENCAP_PROF_ERSPAN_UNTAG_IPV6_INGRESS_MIRROR_LOCAL_MTP: 1347 *app = CANCUN_APP__MIRROR__ERSPAN_UNTAG_IPV6_INGRESS_MIRROR_LOCAL_MTP; 1348 break; 1349 case ENCAP_PROF_ERSPAN_UNTAG_IPV6_INGRESS_MIRROR_REMOTE_MTP: 1350 *app = CANCUN_APP__MIRROR__ERSPAN_UNTAG_IPV6_INGRESS_MIRROR_REMOTE_MTP; 1351 break; 1352 case ENCAP_PROF_ERSPAN_IPV6_INGRESS_MIRROR_UNTAG_PAYLOAD_LOCAL_MTP: 1353 *app = CANCUN_APP__MIRROR__ERSPAN_IPV6_INGRESS_MIRROR_UNTAG_PAYLOAD_LOCAL_MTP; 1354 break; 1355 case ENCAP_PROF_ERSPAN_IPV6_INGRESS_MIRROR_UNTAG_PAYLOAD_REMOTE_MTP: 1356 *app = CANCUN_APP__MIRROR__ERSPAN_IPV6_INGRESS_MIRROR_UNTAG_PAYLOAD_REMOTE_MTP; 1357 break; 1358 case ENCAP_PROF_ERSPAN_UNTAG_IPV6_INGRESS_MIRROR_UNTAG_PAYLOAD_LOCAL_MTP: 1359 *app = CANCUN_APP__MIRROR__ERSPAN_UNTAG_IPV6_INGRESS_MIRROR_UNTAG_PAYLOAD_LOCAL_MTP; 1360 break; 1361 case ENCAP_PROF_ERSPAN_UNTAG_IPV6_INGRESS_MIRROR_UNTAG_PAYLOAD_REMOTE_MTP: 1362 *app = CANCUN_APP__MIRROR__ERSPAN_UNTAG_IPV6_INGRESS_MIRROR_UNTAG_PAYLOAD_REMOTE_MTP; 1363 break; 1364 case ENCAP_PROF_ERSPAN_GRE_SEQUENCE_IPV6_INGRESS_MIRROR_LOCAL_MTP: 1365 *app = CANCUN_APP__MIRROR__ERSPAN_GRE_SEQUENCE_IPV6_INGRESS_MIRROR_LOCAL_MTP; 1366 break; 1367 case ENCAP_PROF_ERSPAN_GRE_SEQUENCE_IPV6_INGRESS_MIRROR_REMOTE_MTP: 1368 *app = CANCUN_APP__MIRROR__ERSPAN_GRE_SEQUENCE_IPV6_INGRESS_MIRROR_REMOTE_MTP; 1369 break; 1370 default: 1371 return (BCM_E_INTERNAL); 1372 break; 1373 } 1374 1375 return (BCM_E_NONE); 1376 } 1377 1378 STATIC int 1379 _bcm_td3_mirror_non_tunnel_truncate_set(int unit, int index, 1380 bcm_gport_t *trunk_arr, int flags) 1381 { 1382 bcm_mirror_destination_t *mirror_dest; /* Destination & Encapsulation.*/ 1383 _bcm_mtp_config_p mtp_cfg; /* MTP configuration . */ 1384 int rv = BCM_E_NONE; /* Operation return status. */ 1385 int max_num_trunk_ports = 0; 1386 egr_mirror_table_entry_t table_entry; 1387 int offset; 1388 uint32 profile_index; 1389 int idx; 1390 void *entries[1]; 1391 uint32 old_profile_index = -1; 1392 int profile_ref_count = 0; 1393 egr_im_mtp_index_entry_t egr_im_mtp_index_entry; 1394 egr_em_mtp_index_entry_t egr_em_mtp_index_entry; 1395 int encap_enable; 1396 1397 mtp_cfg = MIRROR_CONFIG_MTP(unit, index, flags); 1398 mirror_dest = MIRROR_DEST(unit, mtp_cfg->dest_id); 1399 1400 if (!(mirror_dest->flags & BCM_MIRROR_DEST_REPLACE)) { 1401 if (!(mirror_dest->truncate)) { 1402 return BCM_E_NONE; 1403 } 1404 } 1405 1406 sal_memset(&table_entry, 0, sizeof(table_entry)); 1407 entries[0] = &table_entry; 1408 1409 max_num_trunk_ports = BCM_SWITCH_TRUNK_MAX_PORTCNT; 1410 offset = index * max_num_trunk_ports; 1411 1412 if (mirror_dest->flags & BCM_MIRROR_DEST_REPLACE) { 1413 if (flags & BCM_MIRROR_PORT_INGRESS) { 1414 rv = READ_EGR_IM_MTP_INDEXm(unit, MEM_BLOCK_ANY, offset, 1415 &egr_im_mtp_index_entry); 1416 1417 if (BCM_SUCCESS(rv) && 1418 (0 != soc_EGR_IM_MTP_INDEXm_field32_get(unit, 1419 &egr_im_mtp_index_entry, 1420 MIRROR_ENCAP_ENABLEf))) { 1421 old_profile_index = 1422 soc_EGR_IM_MTP_INDEXm_field32_get(unit, 1423 &egr_im_mtp_index_entry, 1424 MIRROR_ENCAP_INDEXf); 1425 1426 } 1427 } 1428 if (flags & BCM_MIRROR_PORT_EGRESS && BCM_SUCCESS(rv)) { 1429 rv = READ_EGR_EM_MTP_INDEXm(unit, MEM_BLOCK_ANY, offset, 1430 &egr_em_mtp_index_entry); 1431 if (BCM_SUCCESS(rv) && 1432 (0 != soc_EGR_EM_MTP_INDEXm_field32_get(unit, 1433 &egr_em_mtp_index_entry, 1434 MIRROR_ENCAP_ENABLEf))) { 1435 old_profile_index = 1436 soc_EGR_EM_MTP_INDEXm_field32_get(unit, 1437 &egr_em_mtp_index_entry, 1438 MIRROR_ENCAP_INDEXf); 1439 1440 } 1441 } 1442 if (-1 != old_profile_index) { 1443 BCM_IF_ERROR_RETURN(soc_profile_mem_ref_count_get(unit, 1444 EGR_MIRROR_TABLE(unit), old_profile_index, &profile_ref_count)); 1445 if (profile_ref_count != 0) { 1446 rv = _bcm_td3_egr_mirror_table_entry_delete(unit, 1447 old_profile_index); 1448 } 1449 } 1450 } 1451 1452 if (mirror_dest->truncate) { 1453 soc_mem_field32_set (unit, EGR_MIRROR_TABLEm, &table_entry, 1454 TRUNCATE_ENf,1); 1455 encap_enable = 1; 1456 if (BCM_SUCCESS(rv)) { 1457 rv = _bcm_td3_egr_mirror_table_entry_add(unit, entries, &profile_index); 1458 } 1459 } else { 1460 encap_enable = 0; 1461 profile_index = 0; 1462 } 1463 1464 for (idx = 0; idx < max_num_trunk_ports; idx++, offset++) { 1465 if (flags & BCM_MIRROR_PORT_INGRESS) { 1466 BCM_IF_ERROR_RETURN(soc_mem_field32_modify(unit, EGR_IM_MTP_INDEXm, 1467 offset, MIRROR_ENCAP_ENABLEf, encap_enable)); 1468 BCM_IF_ERROR_RETURN(soc_mem_field32_modify(unit, EGR_IM_MTP_INDEXm, 1469 offset, MIRROR_ENCAP_INDEXf, profile_index)); 1470 } 1471 /* EGR_EM_MTP_INDEX has same layout as EGR_IM_MTP_INDEX */ 1472 if (flags & BCM_MIRROR_PORT_EGRESS) { 1473 BCM_IF_ERROR_RETURN(soc_mem_field32_modify(unit, EGR_EM_MTP_INDEXm, 1474 offset, MIRROR_ENCAP_ENABLEf, encap_enable)); 1475 BCM_IF_ERROR_RETURN(soc_mem_field32_modify(unit, EGR_EM_MTP_INDEXm, 1476 offset, MIRROR_ENCAP_INDEXf, profile_index)); 1477 } 1478 } 1479 return rv; 1480 } 1481 1482 STATIC int 1483 _bcm_td3_mirror_encap_profile_idx_get(int unit, int edit_ctrl_id, int local) 1484 { 1485 int encap_profile_index = 0; 1486 1487 switch(edit_ctrl_id) { 1488 case MIRROR_EDIT_CTRL_ID_ERSPAN3_INGRESS_MIRROR: 1489 encap_profile_index = local? 1490 ENCAP_PROF_ERSPAN3_INGRESS_MIRROR_LOCAL_MTP: 1491 ENCAP_PROF_ERSPAN3_INGRESS_MIRROR_REMOTE_MTP; 1492 break; 1493 1494 case MIRROR_EDIT_CTRL_ID_ERSPAN3_INGRESS_MIRROR_NO_SUBHDR: 1495 encap_profile_index = local? 1496 ENCAP_PROF_ERSPAN3_INGRESS_MIRROR_NO_SUBHDR_LOCAL_MTP: 1497 ENCAP_PROF_ERSPAN3_INGRESS_MIRROR_NO_SUBHDR_REMOTE_MTP; 1498 break; 1499 1500 case MIRROR_EDIT_CTRL_ID_VXLAN: 1501 encap_profile_index = local ? 1502 ENCAP_PROF_VXLAN_LOCAL_MTP : 1503 ENCAP_PROF_VXLAN_REMOTE_MTP; 1504 break; 1505 1506 case MIRROR_EDIT_CTRL_ID_VXLAN_IPV6: 1507 encap_profile_index = local ? 1508 ENCAP_PROF_VXLAN_IPV6_LOCAL_MTP : 1509 ENCAP_PROF_VXLAN_IPV6_REMOTE_MTP; 1510 break; 1511 case MIRROR_EDIT_CTRL_ID_PSAMP: 1512 encap_profile_index = local ? 1513 ENCAP_PROF_PSAMP_LOCAL_MTP : 1514 ENCAP_PROF_PSAMP_REMOTE_MTP; 1515 break; 1516 1517 case MIRROR_EDIT_CTRL_ID_PSAMP_IPV6: 1518 encap_profile_index = local ? 1519 ENCAP_PROF_PSAMP_IPV6_LOCAL_MTP : 1520 ENCAP_PROF_PSAMP_IPV6_REMOTE_MTP; 1521 break; 1522 1523 case MIRROR_EDIT_CTRL_ID_RSPAN_INGRESS_MIRROR: 1524 encap_profile_index = 1525 ENCAP_PROF_RSPAN_INGRESS_MIRROR_LOCAL_MTP; 1526 break; 1527 1528 case MIRROR_EDIT_CTRL_ID_RSPAN_EGRESS_MIRROR: 1529 encap_profile_index = 1530 ENCAP_PROF_RSPAN_EGRESS_MIRROR_LOCAL_MTP; 1531 break; 1532 1533 case MIRROR_EDIT_CTRL_ID_RSPAN_INGRESS_MIRROR_WITH_VNTAG: 1534 encap_profile_index = local? 1535 ENCAP_PROF_RSPAN_INGRESS_MIRROR_WITH_VNTAG_LOCAL_MTP: 1536 ENCAP_PROF_RSPAN_INGRESS_MIRROR_WITH_VNTAG_REMOTE_MTP; 1537 break; 1538 1539 case MIRROR_EDIT_CTRL_ID_RSPAN_EGRESS_MIRROR_WITH_VNTAG: 1540 encap_profile_index = local? 1541 ENCAP_PROF_RSPAN_EGRESS_MIRROR_WITH_VNTAG_LOCAL_MTP: 1542 ENCAP_PROF_RSPAN_EGRESS_MIRROR_WITH_VNTAG_REMOTE_MTP; 1543 break; 1544 1545 case MIRROR_EDIT_CTRL_ID_SFLOW_INGRESS_MIRROR: 1546 encap_profile_index = local? 1547 ENCAP_PROF_SFLOW_INGRESS_MIRROR_LOCAL_MTP: 1548 ENCAP_PROF_SFLOW_INGRESS_MIRROR_REMOTE_MTP; 1549 break; 1550 1551 case MIRROR_EDIT_CTRL_ID_SFLOW_UNTAG_INGRESS_MIRROR: 1552 encap_profile_index = local? 1553 ENCAP_PROF_SFLOW_UNTAG_INGRESS_MIRROR_LOCAL_MTP: 1554 ENCAP_PROF_SFLOW_UNTAG_INGRESS_MIRROR_REMOTE_MTP; 1555 break; 1556 1557 case MIRROR_EDIT_CTRL_ID_ERSPAN_EGRESS_MIRROR: 1558 encap_profile_index = local? 1559 ENCAP_PROF_ERSPAN_EGRESS_MIRROR_LOCAL_MTP: 1560 ENCAP_PROF_ERSPAN_EGRESS_MIRROR_REMOTE_MTP; 1561 break; 1562 1563 case MIRROR_EDIT_CTRL_ID_ERSPAN_EGRESS_MIRROR_UNTAG_PAYLOAD: 1564 encap_profile_index = local? 1565 ENCAP_PROF_ERSPAN_EGRESS_MIRROR_UNTAG_PAYLOAD_LOCAL_MTP: 1566 ENCAP_PROF_ERSPAN_EGRESS_MIRROR_UNTAG_PAYLOAD_REMOTE_MTP; 1567 break; 1568 1569 case MIRROR_EDIT_CTRL_ID_ERSPAN_INGRESS_MIRROR: 1570 encap_profile_index = local? 1571 ENCAP_PROF_ERSPAN_INGRESS_MIRROR_LOCAL_MTP: 1572 ENCAP_PROF_ERSPAN_INGRESS_MIRROR_REMOTE_MTP; 1573 break; 1574 1575 case MIRROR_EDIT_CTRL_ID_ERSPAN_INGRESS_MIRROR_UNTAG_PAYLOAD: 1576 encap_profile_index = local? 1577 ENCAP_PROF_ERSPAN_INGRESS_MIRROR_UNTAG_PAYLOAD_LOCAL_MTP: 1578 ENCAP_PROF_ERSPAN_INGRESS_MIRROR_UNTAG_PAYLOAD_REMOTE_MTP; 1579 break; 1580 1581 case MIRROR_EDIT_CTRL_ID_ERSPAN_UNTAG_EGRESS_MIRROR: 1582 encap_profile_index = local ? 1583 ENCAP_PROF_ERSPAN_UNTAG_EGRESS_MIRROR_LOCAL_MTP: 1584 ENCAP_PROF_ERSPAN_UNTAG_EGRESS_MIRROR_REMOTE_MTP; 1585 break; 1586 1587 case MIRROR_EDIT_CTRL_ID_ERSPAN_UNTAG_EGRESS_MIRROR_UNTAG_PAYLOAD: 1588 encap_profile_index = local? 1589 ENCAP_PROF_ERSPAN_UNTAG_EGRESS_MIRROR_UNTAG_PAYLOAD_LOCAL_MTP: 1590 ENCAP_PROF_ERSPAN_UNTAG_EGRESS_MIRROR_UNTAG_PAYLOAD_REMOTE_MTP; 1591 break; 1592 1593 case MIRROR_EDIT_CTRL_ID_ERSPAN_UNTAG_INGRESS_MIRROR: 1594 encap_profile_index = local ? 1595 ENCAP_PROF_ERSPAN_UNTAG_INGRESS_MIRROR_LOCAL_MTP: 1596 ENCAP_PROF_ERSPAN_UNTAG_INGRESS_MIRROR_REMOTE_MTP; 1597 break; 1598 1599 case MIRROR_EDIT_CTRL_ID_ERSPAN_UNTAG_INGRESS_MIRROR_UNTAG_PAYLOAD: 1600 encap_profile_index = local ? 1601 ENCAP_PROF_ERSPAN_UNTAG_INGRESS_MIRROR_UNTAG_PAYLOAD_LOCAL_MTP: 1602 ENCAP_PROF_ERSPAN_UNTAG_INGRESS_MIRROR_UNTAG_PAYLOAD_REMOTE_MTP; 1603 break; 1604 1605 case MIRROR_EDIT_CTRL_ID_SFLOW_VNTAG: 1606 encap_profile_index = local ? 1607 ENCAP_PROF_SFLOW_VNTAG_LOCAL_MTP: 1608 ENCAP_PROF_SFLOW_VNTAG_REMOTE_MTP; 1609 break; 1610 1611 case MIRROR_EDIT_CTRL_ID_SFLOW_VNTAG_OTAG: 1612 encap_profile_index = local ? 1613 ENCAP_PROF_SFLOW_VNTAG_OTAG_LOCAL_MTP: 1614 ENCAP_PROF_SFLOW_VNTAG_OTAG_REMOTE_MTP; 1615 break; 1616 1617 case MIRROR_EDIT_CTRL_ID_SFLOW_ETAG: 1618 encap_profile_index = local ? 1619 ENCAP_PROF_SFLOW_ETAG_LOCAL_MTP: 1620 ENCAP_PROF_SFLOW_ETAG_REMOTE_MTP; 1621 break; 1622 1623 case MIRROR_EDIT_CTRL_ID_SFLOW_ETAG_OTAG: 1624 encap_profile_index = local ? 1625 ENCAP_PROF_SFLOW_ETAG_OTAG_LOCAL_MTP: 1626 ENCAP_PROF_SFLOW_ETAG_OTAG_REMOTE_MTP; 1627 break; 1628 1629 case MIRROR_EDIT_CTRL_ID_PSAMP_UNTAG: 1630 encap_profile_index = local ? 1631 ENCAP_PROF_PSAMP_UNTAG_LOCAL_MTP: 1632 ENCAP_PROF_PSAMP_UNTAG_REMOTE_MTP; 1633 break; 1634 1635 case MIRROR_EDIT_CTRL_ID_PSAMP_TRUNCATE: 1636 encap_profile_index = local ? 1637 ENCAP_PROF_PSAMP_TRUNCATE_LOCAL_MTP: 1638 ENCAP_PROF_PSAMP_TRUNCATE_REMOTE_MTP; 1639 break; 1640 1641 case MIRROR_EDIT_CTRL_ID_PSAMP_VNTAG_OTAG: 1642 encap_profile_index = local ? 1643 ENCAP_PROF_PSAMP_VNTAG_OTAG_LOCAL_MTP: 1644 ENCAP_PROF_PSAMP_VNTAG_OTAG_REMOTE_MTP; 1645 break; 1646 1647 case MIRROR_EDIT_CTRL_ID_ERSPAN_GRE_SEQUENCE_INGRESS_MIRROR: 1648 encap_profile_index = local ? 1649 ENCAP_PROF_ERSPAN_GRE_SEQUENCE_INGRESS_MIRROR_LOCAL_MTP: 1650 ENCAP_PROF_ERSPAN_GRE_SEQUENCE_INGRESS_MIRROR_REMOTE_MTP; 1651 break; 1652 1653 case MIRROR_EDIT_CTRL_ID_ERSPAN_GRE_SEQUENCE_EGRESS_MIRROR: 1654 encap_profile_index = local ? 1655 ENCAP_PROF_ERSPAN_GRE_SEQUENCE_EGRESS_MIRROR_LOCAL_MTP: 1656 ENCAP_PROF_ERSPAN_GRE_SEQUENCE_EGRESS_MIRROR_REMOTE_MTP; 1657 break; 1658 1659 case MIRROR_EDIT_CTRL_ID_INT_PROBE: 1660 encap_profile_index = ENCAP_PROF_INT_PROBE_LOCAL_MTP; 1661 break; 1662 1663 case MIRROR_EDIT_CTRL_ID_IFA: 1664 encap_profile_index = ENCAP_PROF_IFA_LOCAL_MTP; 1665 break; 1666 1667 case MIRROR_EDIT_CTRL_ID_ERSPAN_IPV6_INGRESS_MIRROR: 1668 encap_profile_index = local? 1669 ENCAP_PROF_ERSPAN_IPV6_INGRESS_MIRROR_LOCAL_MTP: 1670 ENCAP_PROF_ERSPAN_IPV6_INGRESS_MIRROR_REMOTE_MTP; 1671 break; 1672 case MIRROR_EDIT_CTRL_ID_ERSPAN_UNTAG_IPV6_INGRESS_MIRROR: 1673 encap_profile_index = local? 1674 ENCAP_PROF_ERSPAN_UNTAG_IPV6_INGRESS_MIRROR_LOCAL_MTP: 1675 ENCAP_PROF_ERSPAN_UNTAG_IPV6_INGRESS_MIRROR_REMOTE_MTP; 1676 break; 1677 case MIRROR_EDIT_CTRL_ID_ERSPAN_IPV6_INGRESS_MIRROR_UNTAG_PAYLOAD: 1678 encap_profile_index = local? 1679 ENCAP_PROF_ERSPAN_IPV6_INGRESS_MIRROR_UNTAG_PAYLOAD_LOCAL_MTP: 1680 ENCAP_PROF_ERSPAN_IPV6_INGRESS_MIRROR_UNTAG_PAYLOAD_REMOTE_MTP; 1681 break; 1682 case MIRROR_EDIT_CTRL_ID_ERSPAN_UNTAG_IPV6_INGRESS_MIRROR_UNTAG_PAYLOAD: 1683 encap_profile_index = local? 1684 ENCAP_PROF_ERSPAN_UNTAG_IPV6_INGRESS_MIRROR_UNTAG_PAYLOAD_LOCAL_MTP: 1685 ENCAP_PROF_ERSPAN_UNTAG_IPV6_INGRESS_MIRROR_UNTAG_PAYLOAD_REMOTE_MTP; 1686 break; 1687 case MIRROR_EDIT_CTRL_ID_ERSPAN_GRE_SEQUENCE_IPV6_INGRESS_MIRROR: 1688 encap_profile_index = local? 1689 ENCAP_PROF_ERSPAN_GRE_SEQUENCE_IPV6_INGRESS_MIRROR_LOCAL_MTP: 1690 ENCAP_PROF_ERSPAN_GRE_SEQUENCE_IPV6_INGRESS_MIRROR_REMOTE_MTP; 1691 break; 1692 default: 1693 encap_profile_index = 0; 1694 break; 1695 } 1696 return (encap_profile_index); 1697 } 1698 1699 STATIC int 1700 _bcm_td3_mirror_encap_edit_ctrl_id_get(int unit, int edit_ctrl_id, 1701 int dest_id, int *profile_index) 1702 { 1703 if (encap_to_edit_ctrl_id[dest_id]) { 1704 *profile_index = encap_to_edit_ctrl_id[dest_id]; 1705 return (SOC_E_NONE); 1706 } 1707 1708 return (SOC_E_INTERNAL); 1709 } 1710 1711 STATIC int 1712 _bcm_td3_mirror_encap_profile_index_clear(int unit, int dest_id) 1713 { 1714 int mapped_profile_index = 0; 1715 flex_editor_mirror_encap_0_profile_1_table_entry_t profile_1; 1716 flex_editor_mirror_encap_0_profile_2_table_entry_t profile_2; 1717 flex_editor_mirror_encap_0_profile_3_table_entry_t profile_3; 1718 1719 memset(&profile_1, 0, sizeof(profile_1)); 1720 memset(&profile_2, 0, sizeof(profile_2)); 1721 memset(&profile_3, 0, sizeof(profile_3)); 1722 1723 /* Clear port encap profile */ 1724 if (encap_to_edit_ctrl_id[dest_id]) { 1725 mapped_profile_index = MIRROR_ECD_INDEX_LOCAL(encap_to_edit_ctrl_id[dest_id]); 1726 1727 if (mapped_profile_index) { 1728 encap_profile_index_bmap &= ~(0x01 << mapped_profile_index); 1729 BCM_IF_ERROR_RETURN 1730 (soc_mem_write(unit, 1731 FLEX_EDITOR_MIRROR_ENCAP_0_PROFILE_1_TABLEm, 1732 MEM_BLOCK_ANY, mapped_profile_index, (uint32*)&profile_1)); 1733 BCM_IF_ERROR_RETURN 1734 (soc_mem_write(unit, 1735 FLEX_EDITOR_MIRROR_ENCAP_0_PROFILE_2_TABLEm, 1736 MEM_BLOCK_ANY, mapped_profile_index, (uint32*)&profile_2)); 1737 BCM_IF_ERROR_RETURN 1738 (soc_mem_write(unit, 1739 FLEX_EDITOR_MIRROR_ENCAP_0_PROFILE_3_TABLEm, 1740 MEM_BLOCK_ANY, mapped_profile_index, (uint32*)&profile_3)); 1741 } 1742 1743 mapped_profile_index = MIRROR_ECD_INDEX_REMOTE(encap_to_edit_ctrl_id[dest_id]); 1744 if (mapped_profile_index) { 1745 encap_profile_index_bmap &= ~(0x01 << mapped_profile_index); 1746 BCM_IF_ERROR_RETURN 1747 (soc_mem_write(unit, 1748 FLEX_EDITOR_MIRROR_ENCAP_0_PROFILE_1_TABLEm, 1749 MEM_BLOCK_ANY, mapped_profile_index, (uint32*)&profile_1)); 1750 BCM_IF_ERROR_RETURN 1751 (soc_mem_write(unit, 1752 FLEX_EDITOR_MIRROR_ENCAP_0_PROFILE_2_TABLEm, 1753 MEM_BLOCK_ANY, mapped_profile_index, (uint32*)&profile_2)); 1754 BCM_IF_ERROR_RETURN 1755 (soc_mem_write(unit, 1756 FLEX_EDITOR_MIRROR_ENCAP_0_PROFILE_3_TABLEm, 1757 MEM_BLOCK_ANY, mapped_profile_index, (uint32*)&profile_3)); 1758 } 1759 1760 encap_to_edit_ctrl_id[dest_id] = 0; 1761 } 1762 1763 return (SOC_E_NONE); 1764 } 1765 1766 STATIC int 1767 _bcm_td3_mirror_encap_profile_index_set(int unit, int edit_ctrl_id, int local, 1768 int dest_id, int *profile_index, 1769 void **entries) 1770 { 1771 int rv = BCM_E_NONE, prof_idx = 0; 1772 int encap_profile_index = 0, mapped_profile_index = 0; 1773 uint32 cancun_app = 0, id = encap_to_edit_ctrl_id[dest_id]; 1774 egr_mirror_table_entry_t *mirror_table_p; 1775 int egress = _is_edit_ctrl_id_egress(edit_ctrl_id); 1776 uint64 cancun_data; 1777 1778 COMPILER_64_SET( cancun_data, 0, 1 ); 1779 encap_profile_index = _bcm_td3_mirror_encap_profile_idx_get(unit, 1780 edit_ctrl_id, local); 1781 if (!encap_profile_index) { 1782 /* Edit Ctrl ID passed in is wrong */ 1783 return (SOC_E_PARAM); 1784 } 1785 1786 /* before encap_profile index is mapped, get cancun_app */ 1787 rv = _bcm_td3_mirror_cancun_app_get(unit, edit_ctrl_id, 1788 encap_profile_index, &cancun_app); 1789 if (rv) return (rv); 1790 1791 /* Check if this dest id is already programmed (like replace) */ 1792 if (MIRROR_ECD_VALID(id)) { 1793 if (egress) { 1794 if (MIRROR_ECD_EGRESS(id) == 0) { 1795 /* Save egress edit ctrl id */ 1796 encap_to_edit_ctrl_id[dest_id] |= (edit_ctrl_id << 8); 1797 } else if (edit_ctrl_id != MIRROR_ECD_EGRESS(id)) { 1798 1799 /* Save new ECD. replace could change ECD. Ex. erspan->vxlan */ 1800 encap_to_edit_ctrl_id[dest_id] &= 0xFFFF00FF; 1801 encap_to_edit_ctrl_id[dest_id] |= (edit_ctrl_id << 8); 1802 } 1803 } else { 1804 if (MIRROR_ECD_INGRESS(id) == 0) { 1805 /* Save inress edit ctrl id */ 1806 encap_to_edit_ctrl_id[dest_id] |= edit_ctrl_id; 1807 } else if (edit_ctrl_id != MIRROR_ECD_INGRESS(id)) { 1808 1809 /* Save new ECD. replace could change ECD. Ex. erspan->vxlan */ 1810 encap_to_edit_ctrl_id[dest_id] &= 0xFFFFFF00; 1811 encap_to_edit_ctrl_id[dest_id] |= edit_ctrl_id; 1812 } 1813 } 1814 1815 if (local && MIRROR_ECD_INDEX_LOCAL(id)) { 1816 mapped_profile_index = MIRROR_ECD_INDEX_LOCAL(id); 1817 } else if (!local && MIRROR_ECD_INDEX_REMOTE(id)) { 1818 mapped_profile_index = MIRROR_ECD_INDEX_REMOTE(id); 1819 } else { 1820 mapped_profile_index = 0; 1821 } 1822 if (mapped_profile_index) { 1823 rv = soc_cancun_cch_app_set(unit, cancun_app, cancun_data); 1824 if (rv) return (rv); 1825 1826 /* Set the profile offset */ 1827 mirror_table_p = entries[EGR_MIRROR_TABLE_ENTRIES]; 1828 soc_mem_field32_set (unit, EGR_MIRROR_TABLEm, mirror_table_p, 1829 MIRROR_ENGINE_PROFILE_OFFSETf, 1830 mapped_profile_index - 1); 1831 1832 *profile_index = mapped_profile_index; 1833 return (SOC_E_NONE); 1834 } 1835 } 1836 1837 /* Find a empty profile index available, and map it */ 1838 for (prof_idx = 1; prof_idx < 16; prof_idx++) { 1839 if (encap_profile_index_bmap & (0x01 << prof_idx)) { 1840 continue; 1841 } 1842 mapped_profile_index = prof_idx; 1843 break; 1844 } 1845 1846 /* Save edit_ctrl_id and mapped_profile_index */ 1847 if (local) { 1848 encap_to_edit_ctrl_id[dest_id] |= (mapped_profile_index << 16); 1849 } else { 1850 encap_to_edit_ctrl_id[dest_id] |= (mapped_profile_index << 24); 1851 } 1852 encap_to_edit_ctrl_id[dest_id] |= (edit_ctrl_id << (8*egress)); 1853 1854 /* Set the profile offset */ 1855 mirror_table_p = entries[EGR_MIRROR_TABLE_ENTRIES]; 1856 soc_mem_field32_set (unit, EGR_MIRROR_TABLEm, mirror_table_p, 1857 MIRROR_ENGINE_PROFILE_OFFSETf, 1858 mapped_profile_index - 1); 1859 encap_profile_index_bmap |= (0x01 << mapped_profile_index); 1860 1861 rv = soc_cancun_cch_app_set(unit, cancun_app, cancun_data); 1862 if (rv) return (rv); 1863 1864 *profile_index = mapped_profile_index; 1865 1866 return (rv); 1867 } 1868 1869 /* 1870 * Function: 1871 * _bcm_td3_mirror_flex_editor_header_create 1872 * Purpose: 1873 * Create the header to be written into flex 1874 * editor 1875 * Parameters: 1876 * unit - (IN) BCM device number. 1877 * edit_ctrl_id - (IN) Encapsulation information. 1878 * mirror_dest - (IN) destination information. 1879 * p_profile_1_hdr- (OUT) profile header 1880 * p_profile_2_hdr- (OUT) profile header 1881 * p_profile_3_hdr- (OUT) profile header 1882 * Returns: 1883 * BCM_E_XXX 1884 */ 1885 STATIC int 1886 _bcm_td3_mirror_flex_editor_header_create(int unit, int edit_ctrl_id, 1887 bcm_mirror_destination_t *mirror_dest, void **entries, int is_eport) 1888 { 1889 soc_mem_t mem; 1890 uint8 *p_profile_header, p_profile_hdr[2*EGR_MIRROR_FLEX_EDITOR_WIDTH]; 1891 uint16 gre_protocol = 0x88be, etag_type = 0, flow_label=0; 1892 int len_offset = 0, len_adjust = 0, encap_profile_index; 1893 int udp_len_offset = 0, udp_len_adjust = 0, ether_type = 0; 1894 int rv = BCM_E_NONE; 1895 int tagged = FALSE; 1896 1897 flex_editor_mirror_encap_0_profile_1_table_entry_t profile_1; 1898 flex_editor_mirror_encap_0_profile_2_table_entry_t profile_2; 1899 flex_editor_mirror_encap_0_profile_3_table_entry_t profile_3; 1900 uint8 *p_profile_3_hdr; 1901 uint32 *p_profile_1_hdr, *p_profile_2_hdr; 1902 1903 p_profile_header = p_profile_hdr; 1904 p_profile_1_hdr = (uint32*) &profile_1; 1905 p_profile_2_hdr = (uint32*) &profile_2; 1906 p_profile_3_hdr = (uint8*) &profile_3; 1907 1908 sal_memset(p_profile_hdr, 0, sizeof(p_profile_hdr)); 1909 sal_memset(p_profile_1_hdr, 0, sizeof(profile_1)); 1910 sal_memset(p_profile_2_hdr, 0, sizeof(profile_2)); 1911 sal_memset(p_profile_3_hdr, 0, sizeof(profile_3)); 1912 1913 if (_is_edit_ctrl_id_sflow(edit_ctrl_id) || 1914 _is_edit_ctrl_id_vxlan(edit_ctrl_id) || 1915 _is_edit_ctrl_id_psamp(edit_ctrl_id)) { 1916 1917 /* SFLOW VNTAG construct MACDA,MACSA,VNTAG, IPV4,UDP, SFLOW_SHIM */ 1918 /* PSAMP construct MACDA,MACSA,OTAG, IPV4,UDP, IPFIX, PSAMP */ 1919 /* SFLOW construct MACDA,MACSA,OTAG, IPV4,UDP, SFLOW SHIM, */ 1920 1921 /* Construct MAC and VLAN information L2 Stuff */ 1922 1923 sal_memcpy(p_profile_header, mirror_dest->dst_mac, 6); 1924 p_profile_header+=6; 1925 sal_memcpy(p_profile_header, mirror_dest->src_mac, 6); 1926 p_profile_header+=6; 1927 1928 /* for VNTAG */ 1929 if (_is_edit_ctrl_id_vntag(edit_ctrl_id)) { 1930 *(uint16*)p_profile_header = soc_ntohs(IPV4_NIV_ETHER_TYPE); 1931 p_profile_header+=sizeof(uint16); /* VNTAG ether type 2 bytes*/ 1932 1933 *(uint16*)p_profile_header = soc_ntohs(mirror_dest->niv_dst_vif); 1934 p_profile_header+=sizeof(uint16); 1935 1936 *(uint16*)p_profile_header = soc_ntohs(mirror_dest->niv_src_vif); 1937 if (mirror_dest->niv_flags & BCM_MIRROR_NIV_LOOP) { 1938 *(uint16*)p_profile_header |= soc_ntohs(_BCM_TD_MIRROR_NIV_LOOP_BIT); 1939 } 1940 p_profile_header+=sizeof(uint16); 1941 } 1942 1943 /* for ETAG */ 1944 if ((edit_ctrl_id == MIRROR_EDIT_CTRL_ID_SFLOW_ETAG_OTAG) || 1945 (edit_ctrl_id == MIRROR_EDIT_CTRL_ID_SFLOW_ETAG)) { 1946 rv = bcm_esw_switch_control_get(unit, bcmSwitchEtagEthertype, ðer_type); 1947 BCM_IF_ERROR_RETURN(rv); 1948 1949 etag_type = (uint16)ether_type; 1950 *(uint16*)p_profile_header = soc_ntohs(etag_type); 1951 p_profile_header+=sizeof(uint16); /* ETAG ether type 2 bytes*/ 1952 1953 *(uint16*)p_profile_header = soc_ntohs(mirror_dest->etag_src_vid & 1954 _BCM_MIRROR_ETAG_SRC_VID_MASK); 1955 p_profile_header+=sizeof(uint16); 1956 *(uint16*)p_profile_header = soc_ntohs(mirror_dest->etag_dst_vid & 1957 _BCM_MIRROR_ETAG_DST_VID_MASK); 1958 p_profile_header+=sizeof(uint16); 1959 1960 /* ETAG Extension (2 bytes) */ 1961 *(uint16*)p_profile_header = 0; 1962 p_profile_header+=sizeof(uint16); 1963 } 1964 1965 /* for OTAG */ 1966 if ((edit_ctrl_id == MIRROR_EDIT_CTRL_ID_SFLOW_INGRESS_MIRROR) || 1967 (edit_ctrl_id == MIRROR_EDIT_CTRL_ID_SFLOW_VNTAG_OTAG) || 1968 (edit_ctrl_id == MIRROR_EDIT_CTRL_ID_SFLOW_ETAG_OTAG) || 1969 (edit_ctrl_id == MIRROR_EDIT_CTRL_ID_VXLAN) || 1970 (edit_ctrl_id == MIRROR_EDIT_CTRL_ID_VXLAN_IPV6) || 1971 (edit_ctrl_id == MIRROR_EDIT_CTRL_ID_PSAMP_IPV6) || 1972 (edit_ctrl_id == MIRROR_EDIT_CTRL_ID_PSAMP_UNTAG) || 1973 (edit_ctrl_id == MIRROR_EDIT_CTRL_ID_PSAMP_TRUNCATE) || 1974 (edit_ctrl_id == MIRROR_EDIT_CTRL_ID_PSAMP_VNTAG_OTAG) || 1975 (edit_ctrl_id == MIRROR_EDIT_CTRL_ID_PSAMP)) { 1976 /* If destination port is HG port, VLAN is not included */ 1977 if (is_eport) { 1978 tagged = TRUE; 1979 *(uint16*)p_profile_header = soc_ntohs(mirror_dest->tpid); 1980 p_profile_header+=sizeof(uint16); 1981 *(uint16*)p_profile_header = soc_ntohs((mirror_dest->vlan_id & IPV4_PKT_VLAN_MASK) | 1982 IPV4_PKT_PRIO(mirror_dest->pkt_prio)); 1983 p_profile_header+=sizeof(uint16); 1984 } 1985 } 1986 1987 if (_is_edit_ctrl_id_ipv6(edit_ctrl_id)) { 1988 /* Add Ether Type */ 1989 *(uint16*)p_profile_header = soc_ntohs(IPV6_ETHER_TYPE); 1990 p_profile_header+=sizeof(uint16); 1991 1992 /* Construct IPV6 Information */ 1993 len_adjust = TWOS_COMPLEMENT(p_profile_header - p_profile_hdr); 1994 1995 /* Version and traffic Class upper nibble */ 1996 *p_profile_header = ((mirror_dest->version << NIBBLE_SHIFT_OFFSET)| 1997 (IPV6_TRAFFIC_CLASS >> NIBBLE_SHIFT_OFFSET)); 1998 p_profile_header+=1; 1999 2000 /* Traffic_class lower nibble */ 2001 flow_label = (uint16)(mirror_dest->flow_label >> 16); 2002 *p_profile_header = (((IPV6_TRAFFIC_CLASS & 0xF) << NIBBLE_SHIFT_OFFSET) | 2003 (flow_label & 0xF)); 2004 p_profile_header+=1; 2005 2006 /* Flow label */ 2007 flow_label = (uint16)mirror_dest->flow_label; 2008 *(uint16*)p_profile_header = soc_ntohs(flow_label); 2009 p_profile_header+=sizeof(uint16); 2010 2011 len_offset = p_profile_header - p_profile_hdr; 2012 2013 /* payload length */ 2014 *(uint16*)p_profile_header = 0; 2015 p_profile_header+=sizeof(uint16); 2016 2017 /* Next Header TCP/UDP */ 2018 *p_profile_header = IPV6_NEXT_HDR_UDP; 2019 p_profile_header+=1; 2020 2021 /* HOP Limit */ 2022 *p_profile_header = IPV6_HOP_LIMIT; 2023 p_profile_header+=1; 2024 2025 sal_memcpy(p_profile_header, mirror_dest->src6_addr, sizeof(bcm_ip6_t)); 2026 p_profile_header+=sizeof(bcm_ip6_t); 2027 sal_memcpy(p_profile_header, mirror_dest->dst6_addr, sizeof(bcm_ip6_t)); 2028 p_profile_header+=sizeof(bcm_ip6_t); 2029 } else { 2030 /* Add Ether Type */ 2031 *(uint16*)p_profile_header = soc_ntohs(0x0800); 2032 p_profile_header+=sizeof(uint16); 2033 2034 /* Construct IPV4 Information */ 2035 len_adjust = TWOS_COMPLEMENT(p_profile_header - p_profile_hdr); 2036 2037 *p_profile_header = mirror_dest->version? 2038 ((mirror_dest->version &0xF)<< NIBBLE_SHIFT_OFFSET) | IPV4_HEADER_LENGTH_WORDS : 2039 ((IPV4_VERSION << NIBBLE_SHIFT_OFFSET) | IPV4_HEADER_LENGTH_WORDS); 2040 p_profile_header+=1; 2041 2042 *p_profile_header = mirror_dest->tos; 2043 p_profile_header+=1; 2044 2045 len_offset = p_profile_header - p_profile_hdr; 2046 2047 /* From Length move to flags field. Set DF flag */ 2048 p_profile_header+=4; 2049 *p_profile_header =mirror_dest->df? 1 << DF_FLAG_SHIFTER: 0; 2050 2051 /* From flags move to Time to Live */ 2052 p_profile_header+=2; 2053 2054 *p_profile_header = mirror_dest->ttl; 2055 *(p_profile_header+1) = IPV4_UDP_PROTOCOL; 2056 p_profile_header+=sizeof(uint32); 2057 2058 *(uint32*)p_profile_header = soc_ntohl(mirror_dest->src_addr); 2059 p_profile_header+=sizeof(uint32); 2060 2061 *(uint32*)p_profile_header = soc_ntohl(mirror_dest->dst_addr); 2062 p_profile_header+=sizeof(uint32); 2063 } 2064 2065 /* Construct UDP Information */ 2066 udp_len_adjust = TWOS_COMPLEMENT(p_profile_header - p_profile_hdr); 2067 2068 *(uint16*)p_profile_header = soc_ntohs(mirror_dest->udp_src_port); 2069 p_profile_header+=sizeof(uint16); 2070 *(uint16*)p_profile_header = soc_ntohs(mirror_dest->udp_dst_port); 2071 p_profile_header+=sizeof(uint16); 2072 2073 udp_len_offset = p_profile_header - p_profile_hdr; 2074 /* UDP Length and check sum */ 2075 p_profile_header+= sizeof(uint32); 2076 2077 if (_is_edit_ctrl_id_vntag(edit_ctrl_id)) { 2078 mirror_dest->flags |= BCM_MIRROR_DEST_TUNNEL_NIV; 2079 } else if (_is_edit_ctrl_id_vxlan(edit_ctrl_id)) { 2080 mirror_dest->flags2 |= BCM_MIRROR_DEST_FLAGS2_TUNNEL_VXLAN; 2081 } else if (_is_edit_ctrl_id_psamp(edit_ctrl_id)) { 2082 mirror_dest->flags |= BCM_MIRROR_DEST_TUNNEL_PSAMP; 2083 } else { 2084 mirror_dest->flags |= BCM_MIRROR_DEST_TUNNEL_SFLOW; 2085 } 2086 } else if (_is_edit_ctrl_id_erspan(edit_ctrl_id)) { 2087 2088 /* ERSPAN construct MACDA,MACSA,OTAG,IPV4,GRE*/ 2089 2090 /* Construct MAC and VLAN Information - L2 stuff */ 2091 sal_memcpy(p_profile_header, mirror_dest->dst_mac, 6); 2092 p_profile_header+=6; 2093 sal_memcpy(p_profile_header, mirror_dest->src_mac, 6); 2094 p_profile_header+=6; 2095 2096 if (_is_edit_ctrl_id_erspan_tagged(edit_ctrl_id)) { 2097 if (is_eport) { 2098 tagged = TRUE; 2099 *(uint16*)p_profile_header = soc_ntohs(mirror_dest->tpid); 2100 p_profile_header+=sizeof(uint16); 2101 *(uint16*)p_profile_header = soc_ntohs((mirror_dest->vlan_id & IPV4_PKT_VLAN_MASK) | 2102 IPV4_PKT_PRIO(mirror_dest->pkt_prio)); 2103 p_profile_header+=sizeof(uint16); 2104 } 2105 } 2106 2107 if (_is_edit_ctrl_id_ipv6(edit_ctrl_id)) { 2108 /* Add Ether Type */ 2109 *(uint16*)p_profile_header = soc_ntohs(IPV6_ETHER_TYPE); 2110 p_profile_header+=sizeof(uint16); 2111 /* Construct IPV6 Information */ 2112 len_adjust = TWOS_COMPLEMENT(p_profile_header - p_profile_hdr); 2113 /* Version and traffic Class upper nibble */ 2114 *p_profile_header = ((mirror_dest->version << NIBBLE_SHIFT_OFFSET)| 2115 (IPV6_TRAFFIC_CLASS >> NIBBLE_SHIFT_OFFSET)); 2116 p_profile_header+=1; 2117 /* Traffic_class lower nibble */ 2118 flow_label = (uint16)(mirror_dest->flow_label >> 16); 2119 *p_profile_header = (((IPV6_TRAFFIC_CLASS & 0xF) << NIBBLE_SHIFT_OFFSET) | 2120 (flow_label & 0xF)); 2121 p_profile_header+=1; 2122 /* Flow label */ 2123 flow_label = (uint16)mirror_dest->flow_label; 2124 *(uint16*)p_profile_header = soc_ntohs(flow_label); 2125 p_profile_header+=sizeof(uint16); 2126 len_offset = p_profile_header - p_profile_hdr; 2127 2128 /* payload length */ 2129 *(uint16*)p_profile_header = 0; 2130 p_profile_header+=sizeof(uint16); 2131 2132 /* Next Header GRE */ 2133 *p_profile_header = IPV6_NEXT_HDR_GRE; 2134 p_profile_header+=1; 2135 2136 /* HOP Limit */ 2137 *p_profile_header = IPV6_HOP_LIMIT; 2138 p_profile_header+=1; 2139 2140 sal_memcpy(p_profile_header, mirror_dest->src6_addr, sizeof(bcm_ip6_t)); 2141 p_profile_header+=sizeof(bcm_ip6_t); 2142 sal_memcpy(p_profile_header, mirror_dest->dst6_addr, sizeof(bcm_ip6_t)); 2143 p_profile_header+=sizeof(bcm_ip6_t); 2144 /* will be used for IPv6 payload length */ 2145 udp_len_adjust = TWOS_COMPLEMENT(p_profile_header - p_profile_hdr); 2146 } else { 2147 /* Add Ether Type */ 2148 *(uint16*)p_profile_header = soc_ntohs(0x0800); 2149 p_profile_header+=sizeof(uint16); 2150 2151 /* construct IPV4 Information */ 2152 len_adjust = TWOS_COMPLEMENT(p_profile_header - p_profile_hdr); 2153 /**************************************** 2154 | BYTE 0 | BYTE 1 | BYTE 2 | BYTE 3 | 2155 ----------------------------------------- 2156 |0123-4567|0123-4567|0123-4567|0123-4567| 2157 ----------------------------------------- 2158 |VERS|IHL |TOS |TOTAL LENGTH | 2159 ----------------------------------------- 2160 |IDENTIFICATION |FLG|FRAGMENT OFFSET| 2161 ----------------------------------------- 2162 |TTL |PROTOCOL |HEADER CHECKSUM | 2163 ----------------------------------------- 2164 |SOURCE IP ADDRESS | 2165 ----------------------------------------- 2166 |DEST IP ADDRESS | 2167 ----------------------------------------- 2168 |UDP SRC PORT | UDP DEST PORT | 2169 ----------------------------------------- 2170 |LENGTH | CHECK SUM | 2171 */ 2172 2173 *p_profile_header = ((mirror_dest->version & 0xF) << NIBBLE_SHIFT_OFFSET) | 2174 IPV4_HEADER_LENGTH_WORDS; 2175 p_profile_header+=1; 2176 2177 *p_profile_header = mirror_dest->tos; 2178 p_profile_header+=1; 2179 2180 len_offset = p_profile_header - p_profile_hdr; 2181 2182 /* From Length move to flags field. Set DF flag */ 2183 p_profile_header+=4; 2184 *p_profile_header =mirror_dest->df? 1 << DF_FLAG_SHIFTER: 0; 2185 2186 /* From flags move to Time to Live */ 2187 p_profile_header+=2; 2188 2189 *p_profile_header = mirror_dest->ttl; 2190 *(p_profile_header+1) = IPV4_GRE_PROTOCOL; 2191 p_profile_header+=sizeof(uint32); 2192 2193 *(uint32*)p_profile_header = soc_ntohl(mirror_dest->src_addr); 2194 p_profile_header+=sizeof(uint32); 2195 *(uint32*)p_profile_header = soc_ntohl(mirror_dest->dst_addr); 2196 p_profile_header+=sizeof(uint32); 2197 } 2198 /* construct GRE Protocol */ 2199 if (mirror_dest->gre_protocol == ERSPAN3_GRE_PROTOCOL_TYPE) { 2200 /* Only sequence number present bit is set in erspan3 */ 2201 *(uint16*)p_profile_header = soc_ntohs(0x1000); 2202 } 2203 p_profile_header+=sizeof(uint16); 2204 gre_protocol = (0 != mirror_dest->gre_protocol) ? 2205 mirror_dest->gre_protocol : 0x88be; 2206 *(uint16*)p_profile_header = soc_ntohs(gre_protocol); 2207 } else if (_is_edit_ctrl_id_rspan(edit_ctrl_id)) { 2208 if (_is_edit_ctrl_id_vntag(edit_ctrl_id)) { 2209 *(uint16*)p_profile_header = soc_ntohs(IPV4_NIV_ETHER_TYPE); 2210 p_profile_header+=sizeof(uint16); /* VNTAG ether type 2 bytes*/ 2211 2212 *(uint16*)p_profile_header = soc_ntohs(mirror_dest->niv_dst_vif); 2213 p_profile_header+=sizeof(uint16); 2214 2215 *(uint16*)p_profile_header = soc_ntohs(mirror_dest->niv_src_vif); 2216 if (mirror_dest->niv_flags & BCM_MIRROR_NIV_LOOP) { 2217 *(uint16*)p_profile_header |= soc_ntohs(_BCM_TD_MIRROR_NIV_LOOP_BIT); 2218 } 2219 p_profile_header+=sizeof(uint16); 2220 } 2221 2222 /* RSPAN construct */ 2223 tagged = TRUE; 2224 *(uint16*)p_profile_header = soc_ntohs(mirror_dest->tpid); 2225 p_profile_header+=sizeof(uint16); 2226 *(uint16*)p_profile_header = soc_ntohs((mirror_dest->vlan_id & IPV4_PKT_VLAN_MASK) | 2227 IPV4_PKT_PRIO(mirror_dest->pkt_prio)); 2228 } else if (_is_edit_ctrl_id_int_probe(edit_ctrl_id)) { 2229 int probe_marker; 2230 2231 BCM_IF_ERROR_RETURN(bcm_esw_switch_control_get(unit, 2232 bcmSwitchIntProbeMarker1, &probe_marker)); 2233 2234 /* probe marker1 */ 2235 *(uint32 *)p_profile_header = soc_htonl(probe_marker); 2236 p_profile_header += sizeof(uint32); 2237 2238 BCM_IF_ERROR_RETURN(bcm_esw_switch_control_get(unit, 2239 bcmSwitchIntProbeMarker2, &probe_marker)); 2240 2241 /* probe marker2 */ 2242 *(uint32 *)p_profile_header = soc_htonl(probe_marker); 2243 p_profile_header += sizeof(uint32); 2244 2245 /* version number. set to 1 */ 2246 *(uint8 *)p_profile_header = 1; 2247 p_profile_header += sizeof(uint8); 2248 2249 /* message type. 1 probe packet */ 2250 *(uint8 *)p_profile_header = 1; 2251 p_profile_header += sizeof(uint8); 2252 2253 /* flags. Overflow bit. default 0 */ 2254 *(uint16 *)p_profile_header = 0; 2255 p_profile_header += sizeof(uint16); 2256 2257 /* Request vector. */ 2258 *(uint32 *)p_profile_header = 0xffffffff; 2259 p_profile_header += sizeof(uint32); 2260 2261 /* Hop limit */ 2262 *(uint8 *)p_profile_header = 0xff; 2263 p_profile_header += sizeof(uint8); 2264 2265 /* Hop count */ 2266 *(uint8 *)p_profile_header = 1; 2267 p_profile_header += sizeof(uint8); 2268 2269 /* reserved, must be zero */ 2270 *(uint16 *)p_profile_header = 0; 2271 p_profile_header += sizeof(uint16); 2272 2273 /* max_length - maximum telemetry payload bytes */ 2274 *(uint16 *)p_profile_header = soc_htons(0x400); 2275 p_profile_header += sizeof(uint16); 2276 2277 /* current_length - current payload bytes */ 2278 *(uint16 *)p_profile_header = soc_htons(0x20); 2279 p_profile_header += sizeof(uint16); 2280 2281 /* Sender handler */ 2282 *(uint16 *)p_profile_header = 0; 2283 p_profile_header += sizeof(uint16); 2284 2285 /* sequence number */ 2286 *(uint16 *)p_profile_header = soc_htons(0x1); 2287 p_profile_header += sizeof(uint16); 2288 2289 } 2290 2291 /* Reverse Copy -- Could be endian thingee -- for bcmsim purposes */ 2292 { 2293 int mcnt; 2294 uint32 tmp; 2295 uint32 idx; 2296 2297 for (mcnt = 0; mcnt < EGR_MIRROR_FLEX_EDITOR_WIDTH/4; mcnt++) { 2298 idx = EGR_MIRROR_FLEX_EDITOR_WIDTH - 4*(mcnt + 1); 2299 tmp = *(uint32 *)(&p_profile_hdr[idx]); 2300 p_profile_1_hdr[mcnt] = soc_ntohl(tmp); 2301 idx = (2*EGR_MIRROR_FLEX_EDITOR_WIDTH) - 4*(mcnt + 1); 2302 tmp = *(uint32 *)(&p_profile_hdr[idx]); 2303 p_profile_2_hdr[mcnt] = soc_ntohl(tmp); 2304 } 2305 } 2306 2307 rv = _bcm_td3_mirror_encap_profile_index_set(unit, 2308 edit_ctrl_id, 2309 is_eport? 1 : 0, 2310 BCM_GPORT_MIRROR_GET(mirror_dest->mirror_dest_id), 2311 &encap_profile_index, entries); 2312 if (rv) return (rv); 2313 2314 if (_is_edit_ctrl_id_int_probe(edit_ctrl_id)) { 2315 if (encap_profile_index) { 2316 BCM_IF_ERROR_RETURN 2317 (soc_mem_write(unit, 2318 FLEX_EDITOR_MIRROR_ENCAP_0_PROFILE_1_TABLEm, 2319 MEM_BLOCK_ANY, encap_profile_index, p_profile_1_hdr)); 2320 BCM_IF_ERROR_RETURN 2321 (soc_mem_write(unit, 2322 FLEX_EDITOR_MIRROR_ENCAP_0_PROFILE_2_TABLEm, 2323 MEM_BLOCK_ANY, encap_profile_index, p_profile_2_hdr)); 2324 } 2325 return BCM_E_NONE; 2326 } 2327 2328 /* update PROFILE_3_TABLE */ 2329 if (len_offset) { 2330 int hdr_chksum_offset = len_offset+8; 2331 2332 mem = FLEX_EDITOR_MIRROR_ENCAP_0_PROFILE_3_TABLEm; 2333 if (_is_edit_ctrl_id_ipv6(edit_ctrl_id) == 0) { 2334 soc_mem_field32_set (unit, mem, p_profile_3_hdr, 2335 MIRROR_ENCAP_CHECKSUM_0_VALIDf, 1); 2336 soc_mem_field32_set (unit, mem, p_profile_3_hdr, 2337 MIRROR_ENCAP_CHECKSUM_0_FIELD_REL_OFFSETf, 2338 hdr_chksum_offset); 2339 { 2340 uint32 mask[3] = {0x00000000, 0x3ffffc00, 0x00000000}; 2341 2342 /* higig or no vlan: subtract 4 bytes of tpid and vlan */ 2343 if (tagged == FALSE) { 2344 mask[0] = 0x00000000; 2345 mask[1] = 0xffffc000; 2346 mask[2] = 0x00000003; 2347 } 2348 soc_mem_field_set (unit, mem, (uint32*)p_profile_3_hdr, 2349 MIRROR_ENCAP_CHECKSUM_0_MASKf, mask); 2350 } 2351 } 2352 2353 /* length adjust is a 2's complement of adjusted length. */ 2354 if (is_eport == 0) { /* HG PORT */ 2355 len_adjust -= 0x10; /* sizeof(soc_higig2_hdr_t) */ 2356 udp_len_adjust -= 0x10; /* sizeof(soc_higig2_hdr_t) */ 2357 } 2358 2359 soc_mem_field32_set (unit, mem, p_profile_3_hdr, 2360 MIRROR_ENCAP_PKT_LEN_0_VALIDf, 1); 2361 soc_mem_field32_set (unit, mem, p_profile_3_hdr, 2362 MIRROR_ENCAP_PKT_LEN_0_FIELD_REL_OFFSETf, 2363 len_offset); 2364 if (edit_ctrl_id == MIRROR_EDIT_CTRL_ID_PSAMP_TRUNCATE) { 2365 soc_mem_field32_set (unit, mem, p_profile_3_hdr, 2366 MIRROR_ENCAP_PKT_LEN_0_SRCf, 2); 2367 soc_mem_field32_set (unit, mem, p_profile_3_hdr, 2368 MIRROR_ENCAP_PKT_LEN_0_ADJUSTf, 2369 TD3_PSAMP_TRUNCATE_LEN_ADJUST); 2370 if (udp_len_offset) { 2371 soc_mem_field32_set (unit, mem, p_profile_3_hdr, 2372 MIRROR_ENCAP_PKT_LEN_1_ADJUSTf, 2373 TD3_PSAMP_TRUNCATE_UDP_LEN_ADJUST); 2374 soc_mem_field32_set (unit, mem, p_profile_3_hdr, 2375 MIRROR_ENCAP_PKT_LEN_1_SRCf, 2); 2376 } 2377 } else { 2378 if (mirror_dest->truncate == BCM_MIRROR_PAYLOAD_TRUNCATE) { 2379 /* when MIRROR_ENCAP_PKT_LEN_0_SRC = 2, the length is 2380 * the original truncated packet length, need to add 2381 * the encap header length 2382 */ 2383 int truncate_ip_len_adjust = 0; 2384 int truncate_udp_len_adjust = 0; 2385 if (_is_edit_ctrl_id_sflow(edit_ctrl_id) || 2386 _is_edit_ctrl_id_vxlan(edit_ctrl_id) || 2387 _is_edit_ctrl_id_erspan(edit_ctrl_id)) { 2388 /* psamp is already done above */ 2389 2390 if (_is_edit_ctrl_id_sflow(edit_ctrl_id)) { 2391 truncate_ip_len_adjust = SFLOW_HEADER_LEN; 2392 truncate_ip_len_adjust += UDP_HEADER_LEN; 2393 truncate_udp_len_adjust = truncate_ip_len_adjust; 2394 } else if (_is_edit_ctrl_id_vxlan(edit_ctrl_id)) { 2395 truncate_ip_len_adjust = VXLAN_HEADER_LEN; 2396 truncate_ip_len_adjust += UDP_HEADER_LEN; 2397 truncate_udp_len_adjust = truncate_ip_len_adjust; 2398 } else if (_is_edit_ctrl_id_erspan(edit_ctrl_id)) { 2399 truncate_ip_len_adjust = GRE_HEADER_LEN; 2400 } 2401 /* len in IPv6 header is the payload length. 2402 * Adjust only for IPv4 header 2403 */ 2404 if (!_is_edit_ctrl_id_ipv6(edit_ctrl_id)) { 2405 truncate_ip_len_adjust += IPV4_HEADER_LEN; 2406 } 2407 } 2408 if (truncate_ip_len_adjust) { 2409 soc_mem_field32_set (unit, mem, p_profile_3_hdr, 2410 MIRROR_ENCAP_PKT_LEN_0_SRCf, 2); 2411 soc_mem_field32_set (unit, mem, p_profile_3_hdr, 2412 MIRROR_ENCAP_PKT_LEN_0_ADJUSTf, 2413 truncate_ip_len_adjust); 2414 } 2415 if (truncate_udp_len_adjust) { 2416 soc_mem_field32_set (unit, mem, p_profile_3_hdr, 2417 MIRROR_ENCAP_PKT_LEN_1_ADJUSTf, 2418 truncate_udp_len_adjust); 2419 soc_mem_field32_set (unit, mem, p_profile_3_hdr, 2420 MIRROR_ENCAP_PKT_LEN_1_SRCf, 2); 2421 } 2422 } else { 2423 soc_mem_field32_set (unit, mem, p_profile_3_hdr, 2424 MIRROR_ENCAP_PKT_LEN_0_SRCf, 1); 2425 soc_mem_field32_set (unit, mem, p_profile_3_hdr, 2426 MIRROR_ENCAP_PKT_LEN_0_ADJUSTf, 2427 ((_is_edit_ctrl_id_ipv6(edit_ctrl_id)) ? 2428 udp_len_adjust : len_adjust)); 2429 if (udp_len_offset) { 2430 soc_mem_field32_set (unit, mem, p_profile_3_hdr, 2431 MIRROR_ENCAP_PKT_LEN_1_ADJUSTf, 2432 udp_len_adjust); 2433 soc_mem_field32_set (unit, mem, p_profile_3_hdr, 2434 MIRROR_ENCAP_PKT_LEN_1_SRCf, 1); 2435 } 2436 } 2437 } 2438 2439 if (udp_len_offset) { 2440 soc_mem_field32_set (unit, mem, p_profile_3_hdr, 2441 MIRROR_ENCAP_PKT_LEN_1_VALIDf, 1); 2442 soc_mem_field32_set (unit, mem, p_profile_3_hdr, 2443 MIRROR_ENCAP_PKT_LEN_1_FIELD_REL_OFFSETf, 2444 udp_len_offset); 2445 } 2446 2447 } 2448 2449 if (encap_profile_index) { 2450 BCM_IF_ERROR_RETURN 2451 (soc_mem_write(unit, 2452 FLEX_EDITOR_MIRROR_ENCAP_0_PROFILE_1_TABLEm, 2453 MEM_BLOCK_ANY, encap_profile_index, p_profile_1_hdr)); 2454 BCM_IF_ERROR_RETURN 2455 (soc_mem_write(unit, 2456 FLEX_EDITOR_MIRROR_ENCAP_0_PROFILE_2_TABLEm, 2457 MEM_BLOCK_ANY, encap_profile_index, p_profile_2_hdr)); 2458 BCM_IF_ERROR_RETURN 2459 (soc_mem_write(unit, 2460 FLEX_EDITOR_MIRROR_ENCAP_0_PROFILE_3_TABLEm, 2461 MEM_BLOCK_ANY, encap_profile_index, p_profile_3_hdr)); 2462 } 2463 2464 return BCM_E_NONE; 2465 } 2466 2467 2468 /* 2469 * Function: 2470 * _bcm_td3_mirror_l2_tunnel_set 2471 * Purpose: 2472 * Prepare & write L2 mirror tunnel encapsulation on Trident. 2473 * Parameters: 2474 * unit - (IN) BCM device number 2475 * index - (IN) Mtp index. 2476 * flags - (IN) Mirror direction flags. 2477 * entries - (IN) Pointer to EGR_MIRROR_ENCAP_* entries array 2478 * Returns: 2479 * BCM_E_XXX 2480 */ 2481 int 2482 _bcm_td3_mirror_l2_tunnel_set(int unit, int index, 2483 int flags, void **entries, int is_eport) 2484 { 2485 bcm_mirror_destination_t *mirror_dest;/* Destination & encapsulation. */ 2486 _bcm_mtp_config_p mtp_cfg; /* Mtp configuration. */ 2487 uint32 edit_ctrl_id, reg_val = 0; 2488 egr_mirror_table_entry_t *mirror_table_p; 2489 2490 /* These entries were initialized by the calling function */ 2491 mirror_table_p = entries[EGR_MIRROR_TABLE_ENTRIES]; 2492 2493 /* Get mtp configuration structure by direction & index. */ 2494 mtp_cfg = MIRROR_CONFIG_MTP(unit, index, flags); 2495 mirror_dest = MIRROR_DEST(unit, mtp_cfg->dest_id); 2496 2497 edit_ctrl_id = mtp_cfg->egress ? MIRROR_EDIT_CTRL_ID_RSPAN_EGRESS_MIRROR : 2498 MIRROR_EDIT_CTRL_ID_RSPAN_INGRESS_MIRROR; 2499 2500 /* Setup Mirror Table Entry */ 2501 soc_mem_field32_set (unit, EGR_MIRROR_TABLEm, mirror_table_p, 2502 MIRROR_EDIT_CTRL_IDf, edit_ctrl_id); 2503 soc_mem_field32_set (unit, EGR_MIRROR_TABLEm, mirror_table_p, 2504 MIRROR_VLAN_VLDf, 2505 is_eport? 0:1); 2506 soc_mem_field32_set (unit, EGR_MIRROR_TABLEm, mirror_table_p, 2507 MIRROR_VLANf, mirror_dest->vlan_id); 2508 2509 if (mirror_dest->truncate == BCM_MIRROR_PAYLOAD_TRUNCATE) { 2510 soc_mem_field32_set (unit, EGR_MIRROR_TABLEm, mirror_table_p, 2511 TRUNCATE_ENf,1); 2512 } else if (!mirror_dest->truncate) { 2513 soc_mem_field32_set (unit, EGR_MIRROR_TABLEm, mirror_table_p, 2514 TRUNCATE_ENf,0); 2515 } 2516 if (soc_feature(unit, soc_feature_trill)) { 2517 /* TD3 Does not support TRILL optional header */ 2518 return (BCM_E_UNAVAIL); 2519 } 2520 2521 /* Create the flex editor header */ 2522 BCM_IF_ERROR_RETURN(_bcm_td3_mirror_flex_editor_header_create(unit, 2523 edit_ctrl_id, mirror_dest, entries, is_eport)); 2524 2525 /* Set up for HiGig source port */ 2526 soc_reg_field_set(unit, EGR_HG_MIRROR_EDIT_CTRL_IDr, 2527 ®_val, HG_MIRROR_EDIT_CTRL_ID_0f, 2528 MIRROR_EDIT_CTRL_ID_INGRESS_MIRROR_HG_UNTAG); 2529 soc_reg_field_set(unit, EGR_HG_MIRROR_EDIT_CTRL_IDr, 2530 ®_val, HG_MIRROR_EDIT_CTRL_ID_1f, 2531 MIRROR_EDIT_CTRL_ID_INGRESS_MIRROR_HG_TAG); 2532 BCM_IF_ERROR_RETURN(WRITE_EGR_HG_MIRROR_EDIT_CTRL_IDr(unit, reg_val)); 2533 2534 /* Profile entries will be committed to HW by the calling function. */ 2535 return (BCM_E_NONE); 2536 } 2537 2538 STATIC int 2539 _bcm_td3_mirror_seq_num_enable (int unit, 2540 egr_mirror_table_entry_t *mirror_table_p, 2541 int seq_num_counter_index, int seq_number) 2542 { 2543 egr_sequence_number_table_entry_t seq_num_entry; 2544 2545 soc_mem_field32_set (unit, EGR_MIRROR_TABLEm, mirror_table_p, 2546 SEQUENCE_NUMBER_ENf, 1); 2547 soc_mem_field32_set (unit, EGR_MIRROR_TABLEm, mirror_table_p, 2548 SEQ_NUM_PROFILE_INDEXf, 1); 2549 soc_mem_field32_set (unit, EGR_MIRROR_TABLEm, mirror_table_p, 2550 SEQ_NUM_COUNTER_INDEXf, seq_num_counter_index); 2551 2552 BCM_IF_ERROR_RETURN(soc_mem_read(unit, EGR_SEQUENCE_NUMBER_TABLEm, 2553 MEM_BLOCK_ANY, seq_num_counter_index, &seq_num_entry)); 2554 soc_EGR_SEQUENCE_NUMBER_TABLEm_field32_set(unit, &seq_num_entry, 2555 SEQUENCE_NUMBERf, seq_number); 2556 BCM_IF_ERROR_RETURN(soc_mem_write(unit, EGR_SEQUENCE_NUMBER_TABLEm, 2557 MEM_BLOCK_ANY, seq_num_counter_index, &seq_num_entry)); 2558 2559 return (BCM_E_NONE); 2560 } 2561 /* 2562 * Function: 2563 * _bcm_td3_mirror_ipv4_gre_tunnel_set 2564 * Purpose: 2565 * Prepare IPv4 mirror tunnel encapsulation for Trident. 2566 * Parameters: 2567 * unit - (IN) BCM device number 2568 * index - (IN) Mtp index. 2569 * flags - (IN) Mirror direction flags. 2570 * entries - (IN) Pointer to EGR_MIRROR_ENCAP_* entries array 2571 * Returns: 2572 * BCM_E_XXX 2573 */ 2574 int 2575 _bcm_td3_mirror_ipv4_gre_tunnel_set(int unit, int index, int flags, 2576 int dest_flags, void **entries, 2577 int is_eport) 2578 { 2579 bcm_mirror_destination_t *mirror_dest; /* Destination & encapsulation.*/ 2580 _bcm_mtp_config_p mtp_cfg; /* Mtp configuration.*/ 2581 2582 uint32 edit_ctrl_id; 2583 egr_mirror_table_entry_t *mirror_table_p; 2584 uint32 reg_val = 0; 2585 uint16 opaque = 0; 2586 uint32 opaque32 = 0; 2587 uint8 erspan3_version = 2; 2588 uint8 erspan3_protocol_flag = 1; 2589 uint8 erspan3_granularity = 0; 2590 egr_sequence_number_table_entry_t seq_num_entry; 2591 void *seq_entries[1]; 2592 uint32 profile_idx; 2593 egr_sequence_number_profile_entry_t seq_num_profile_entry; 2594 2595 /* These entries were initialized by the calling function */ 2596 mirror_table_p = entries[EGR_MIRROR_TABLE_ENTRIES]; 2597 2598 /* Get mtp configuration structure by direction & index. */ 2599 mtp_cfg = MIRROR_CONFIG_MTP(unit, index, flags); 2600 mirror_dest = MIRROR_DEST(unit, mtp_cfg->dest_id); 2601 if ((!(flags & BCM_MIRROR_PORT_INGRESS)) && 2602 (mirror_dest->gre_protocol == ERSPAN3_GRE_PROTOCOL_TYPE)) { 2603 return BCM_E_PARAM; 2604 } 2605 /* Outer vlan tag. */ 2606 2607 if (dest_flags & BCM_MIRROR_DEST_TUNNEL_WITH_SEQ) { 2608 edit_ctrl_id = mtp_cfg->egress ? 2609 MIRROR_EDIT_CTRL_ID_ERSPAN_GRE_SEQUENCE_EGRESS_MIRROR: 2610 MIRROR_EDIT_CTRL_ID_ERSPAN_GRE_SEQUENCE_INGRESS_MIRROR; 2611 } else { 2612 if (mtp_cfg->egress) { 2613 if (mirror_dest->flags & BCM_MIRROR_DEST_PAYLOAD_UNTAGGED) { 2614 if (BCM_VLAN_CTRL_ID(mirror_dest->vlan_id) > 0) { 2615 edit_ctrl_id = MIRROR_EDIT_CTRL_ID_ERSPAN_EGRESS_MIRROR_UNTAG_PAYLOAD; 2616 } else { 2617 edit_ctrl_id = MIRROR_EDIT_CTRL_ID_ERSPAN_UNTAG_EGRESS_MIRROR_UNTAG_PAYLOAD; 2618 } 2619 } else { 2620 if (BCM_VLAN_CTRL_ID(mirror_dest->vlan_id) > 0) { 2621 edit_ctrl_id = MIRROR_EDIT_CTRL_ID_ERSPAN_EGRESS_MIRROR; 2622 } else { 2623 edit_ctrl_id = MIRROR_EDIT_CTRL_ID_ERSPAN_UNTAG_EGRESS_MIRROR; 2624 } 2625 } 2626 } else { 2627 if (mirror_dest->gre_protocol == ERSPAN3_GRE_PROTOCOL_TYPE) { 2628 if (mirror_dest->erspan_header.optional_hdr) { 2629 if (mirror_dest->erspan_header.platform_id == 0x5) { 2630 edit_ctrl_id = MIRROR_EDIT_CTRL_ID_ERSPAN3_INGRESS_MIRROR; 2631 } else { 2632 /* The default Cancun configuration will support a choice 2633 * of no subheader or inclusion of subheader 5. 2634 * If other choices are desired, a different Cancun 2635 * configuration is needed. 2636 */ 2637 return BCM_E_UNAVAIL; 2638 } 2639 } else { 2640 edit_ctrl_id = 2641 MIRROR_EDIT_CTRL_ID_ERSPAN3_INGRESS_MIRROR_NO_SUBHDR; 2642 } 2643 } else 2644 if (mirror_dest->flags & BCM_MIRROR_DEST_PAYLOAD_UNTAGGED) { 2645 if (BCM_VLAN_CTRL_ID(mirror_dest->vlan_id) > 0) { 2646 edit_ctrl_id = MIRROR_EDIT_CTRL_ID_ERSPAN_INGRESS_MIRROR_UNTAG_PAYLOAD; 2647 } else { 2648 edit_ctrl_id = MIRROR_EDIT_CTRL_ID_ERSPAN_UNTAG_INGRESS_MIRROR_UNTAG_PAYLOAD; 2649 } 2650 } else { 2651 if (BCM_VLAN_CTRL_ID(mirror_dest->vlan_id) > 0) { 2652 edit_ctrl_id = MIRROR_EDIT_CTRL_ID_ERSPAN_INGRESS_MIRROR; 2653 } else { 2654 edit_ctrl_id = MIRROR_EDIT_CTRL_ID_ERSPAN_UNTAG_INGRESS_MIRROR; 2655 } 2656 } 2657 } 2658 } 2659 2660 /* Setup Mirror Table Entry */ 2661 soc_mem_field32_set (unit, EGR_MIRROR_TABLEm, mirror_table_p, 2662 MIRROR_EDIT_CTRL_IDf, edit_ctrl_id); 2663 2664 if (dest_flags & BCM_MIRROR_DEST_TUNNEL_WITH_SEQ) { 2665 BCM_IF_ERROR_RETURN(_bcm_td3_mirror_seq_num_enable (unit, 2666 mirror_table_p, 2667 EGR_MIRROR_TABLE_SEQNUM_OFFSET + index, 2668 BCM_MIRROR_IP_GRE_SEQ_NUM|index)); 2669 } 2670 2671 /* coverity[result_independent_of_operands] */ 2672 if (BCM_VLAN_VALID(mirror_dest->vlan_id)) { 2673 soc_mem_field32_set (unit, EGR_MIRROR_TABLEm, mirror_table_p, 2674 MIRROR_VLAN_VLDf, is_eport? 0:1); 2675 soc_mem_field32_set (unit, EGR_MIRROR_TABLEm, mirror_table_p, 2676 MIRROR_VLANf, mirror_dest->vlan_id); 2677 } 2678 if (mirror_dest->gre_protocol == ERSPAN3_GRE_PROTOCOL_TYPE) { 2679 /* Enabling sequence number */ 2680 soc_mem_field32_set (unit, EGR_MIRROR_TABLEm, mirror_table_p, 2681 SEQUENCE_NUMBER_ENf, 1); 2682 /* CCH Configuration to increment sequence number */ 2683 soc_reg_field_set(unit, PSAMP_CONTROLr, ®_val, INCREMENT_SEQ_NUMf, 2684 1); 2685 BCM_IF_ERROR_RETURN(WRITE_PSAMP_CONTROLr(unit, reg_val)); 2686 /* Configuring Sequence number and its index in EGR_MIRROR_TABLE */ 2687 sal_memset(&seq_num_entry, 0, sizeof(seq_num_entry)); 2688 BCM_IF_ERROR_RETURN(soc_mem_read(unit, EGR_SEQUENCE_NUMBER_TABLEm, 2689 MEM_BLOCK_ANY, 2690 index + EGR_MIRROR_TABLE_SEQNUM_OFFSET, 2691 &seq_num_entry)); 2692 soc_mem_field32_set(unit, EGR_SEQUENCE_NUMBER_TABLEm, 2693 &seq_num_entry, SEQUENCE_NUMBERf, 2694 mirror_dest->gre_seq_number); 2695 BCM_IF_ERROR_RETURN(soc_mem_write(unit, EGR_SEQUENCE_NUMBER_TABLEm, 2696 MEM_BLOCK_ANY, 2697 index + EGR_MIRROR_TABLE_SEQNUM_OFFSET, 2698 &seq_num_entry)); 2699 soc_mem_field32_set (unit, EGR_MIRROR_TABLEm, mirror_table_p, 2700 SEQ_NUM_COUNTER_INDEXf, 2701 index + EGR_MIRROR_TABLE_SEQNUM_OFFSET); 2702 /* Configuring sequence number mask and profile index in 2703 * EGR_MIRROR_TABLE. 2704 * Output Sequence Number = EGR_SEQUENCE_NUMBER_TABLE.SEQUENCE_NUMBER & 2705 * ~(EGR_SEQUENCE_NUMBER_PROFILE.MASK) 2706 */ 2707 sal_memset(&seq_num_profile_entry, 0, sizeof(seq_num_profile_entry)); 2708 soc_mem_field32_set (unit, EGR_SEQUENCE_NUMBER_PROFILEm, 2709 &seq_num_profile_entry, MASKf, 0x0); 2710 soc_mem_field32_set (unit, EGR_SEQUENCE_NUMBER_PROFILEm, 2711 &seq_num_profile_entry, RESERVED_VALUEf, 0x0); 2712 soc_mem_field32_set (unit, EGR_SEQUENCE_NUMBER_PROFILEm, 2713 &seq_num_profile_entry, SEQUENCE_NUMBER_INCREMENTf, 2714 0x1); 2715 seq_entries[0] = &seq_num_profile_entry; 2716 BCM_IF_ERROR_RETURN(soc_profile_mem_add(unit, 2717 EGR_SEQ_NUMBER_PROFILE(unit), seq_entries, 1, 2718 &profile_idx)); 2719 soc_mem_field32_set (unit, EGR_MIRROR_TABLEm, mirror_table_p, 2720 SEQ_NUM_PROFILE_INDEXf, profile_idx); 2721 soc_mem_field32_set (unit, EGR_MIRROR_TABLEm, mirror_table_p, 2722 MIRROR_ENCAP_DATA_VALIDf, 0x1); 2723 soc_mem_field32_set (unit, EGR_MIRROR_TABLEm, mirror_table_p, 2724 TRUNCATE_ENf, 2725 mirror_dest->erspan_header.truncated_flag); 2726 2727 if (SOC_IS_HELIX5(unit)) { 2728 /* Encoding ERSPAN3 version, truncated flag and 15 msb of session_id in 2729 * opaque data and configuring in MIRROR_ENCAP_DATA_2. 2730 */ 2731 opaque = (erspan3_version << 12) | 2732 (mirror_dest->erspan_header.truncated_flag << 9) | 2733 ((mirror_dest->erspan_header.session_id >> 1) & 0x1ff); 2734 soc_mem_field32_set (unit, EGR_MIRROR_TABLEm, mirror_table_p, 2735 MIRROR_ENCAP_DATA_2f, opaque); 2736 opaque = 0; 2737 if (mirror_dest->erspan_header.timestamp_granularity) { 2738 /* PTP timestamp granularity */ 2739 erspan3_granularity = 0x2; 2740 } else { 2741 /* NTP timestamp granularity */ 2742 erspan3_granularity = 0x3; 2743 } 2744 /* Encoding remaining 1 lsb of session id, ERSPAN3 protocol flag, HW_ID 2745 * and timestamp granularity in opaque data and configuring in 2746 * MIRROR_ENCAP_DATA_1. 2747 */ 2748 opaque = ((mirror_dest->erspan_header.session_id & 0x1) << 15) | 2749 (erspan3_protocol_flag << 14) | 2750 (mirror_dest->erspan_header.hw_id << 3) | 2751 (erspan3_granularity); 2752 soc_mem_field32_set (unit, EGR_MIRROR_TABLEm, mirror_table_p, 2753 MIRROR_ENCAP_DATA_1f, opaque); 2754 opaque = 0; 2755 if (mirror_dest->erspan_header.optional_hdr) { 2756 if (mirror_dest->erspan_header.platform_id == 0x5) { 2757 /* For platform id 0x5, encoding sub-header switch_id, 2758 * platform_id and optional header presence bit in opaque data 2759 * and configuring in MIRROR_ENCAP_DATA_0. 2760 */ 2761 opaque = (mirror_dest->erspan_header.switch_id << 7) | 2762 (mirror_dest->erspan_header.platform_id << 1) | 2763 (mirror_dest->erspan_header.optional_hdr); 2764 } 2765 } 2766 soc_mem_field32_set (unit, EGR_MIRROR_TABLEm, mirror_table_p, 2767 MIRROR_ENCAP_DATA_0f, opaque); 2768 } else { 2769 /* opaque data configuring in MIRROR_ENCAP_DATA_1. */ 2770 /* 2771 * Version -- 4 bits -- EGR_MIRROR_TABLE.OPAQUE_DATA 2772 * BSO -- 2 bits -- EGR_MIRROR_TABLE.OPAQUE_DATA -- always 0 2773 * Truncated -- 1 bit -- EGR_MIRROR_TABLE.OPAQUE_DATA 2774 * Session ID -- 10 bits -- EGR_MIRROR_TABLE.OPAQUE_DATA 2775 * PROTOCOL -- 1 bit -- EGR_MIRROR_TABLE.OPAQUE_DATA 2776 * FRAME_TYPE -- 5 bits -- EGR_MIRROR_TABLE.OPAQUE_DATA -- always 0 2777 * HW_ID -- 6 bits -- EGR_MIRROR_TABLE.OPAQUE_DATA 2778 * DIRECTION -- 1 bit -- EGR_MIRROR_TABLE.OPAQUE_DATA -- always 0 2779 * GRANULARITY -- 2 bits -- EGR_MIRROR_TABLE.OPAQUE_DATA 2780 * OPTIONAL SUBHDR -- 1 bit -- EGR_MIRROR_TABLE.OPAQUE_DATA 2781 */ 2782 if (mirror_dest->erspan_header.timestamp_granularity) { 2783 /* PTP timestamp granularity */ 2784 erspan3_granularity = 0x2; 2785 } else { 2786 /* NTP timestamp granularity */ 2787 erspan3_granularity = 0x3; 2788 } 2789 opaque32 = (erspan3_version << 28) | 2790 ((mirror_dest->erspan_header.truncated_flag & 1) << 25) | 2791 ((mirror_dest->erspan_header.session_id & 0x3ff) << 15) | 2792 ((erspan3_protocol_flag & 1) << 14) | 2793 ((mirror_dest->erspan_header.hw_id & 0x3f) << 3) | 2794 (erspan3_granularity & 0x3); 2795 ; 2796 soc_mem_field32_set (unit, EGR_MIRROR_TABLEm, mirror_table_p, 2797 MIRROR_ENCAP_DATA_1f, opaque32); 2798 2799 opaque = 0; 2800 if (mirror_dest->erspan_header.optional_hdr) { 2801 if (mirror_dest->erspan_header.platform_id == 0x5) { 2802 /* For platform id 0x5, encoding sub-header switch_id, 2803 * platform_id and optional header presence bit in opaque data 2804 * and configuring in MIRROR_ENCAP_DATA_0. 2805 */ 2806 opaque = (mirror_dest->erspan_header.switch_id << 7) | 2807 (mirror_dest->erspan_header.platform_id << 1) | 2808 (mirror_dest->erspan_header.optional_hdr); 2809 } 2810 } 2811 soc_mem_field32_set (unit, EGR_MIRROR_TABLEm, mirror_table_p, 2812 MIRROR_ENCAP_DATA_0f, opaque); 2813 } 2814 2815 } 2816 2817 if (mirror_dest->truncate == BCM_MIRROR_PAYLOAD_TRUNCATE) { 2818 soc_mem_field32_set (unit, EGR_MIRROR_TABLEm, mirror_table_p, 2819 TRUNCATE_ENf,1); 2820 } else if (!mirror_dest->truncate) { 2821 soc_mem_field32_set (unit, EGR_MIRROR_TABLEm, mirror_table_p, 2822 TRUNCATE_ENf,0); 2823 } 2824 /* Create the flex editor header */ 2825 BCM_IF_ERROR_RETURN(_bcm_td3_mirror_flex_editor_header_create(unit, 2826 edit_ctrl_id, mirror_dest, entries, is_eport)); 2827 2828 /* Profile entries will be committed to HW by the calling function. */ 2829 2830 return (BCM_E_NONE); 2831 } 2832 2833 /* 2834 * Function: 2835 * _bcm_td3_mirror_ipv6_gre_tunnel_set 2836 * Purpose: 2837 * Prepare IPv6 mirror tunnel encapsulation for Trident3. 2838 * Parameters: 2839 * unit - (IN) BCM device number 2840 * index - (IN) Mtp index. 2841 * flags - (IN) Mirror direction flags. 2842 * entries - (IN) Pointer to EGR_MIRROR_ENCAP_* entries array 2843 * Returns: 2844 * BCM_E_XXX 2845 */ 2846 int 2847 _bcm_td3_mirror_ipv6_gre_tunnel_set(int unit, int index, int flags, 2848 int dest_flags, void **entries, 2849 int is_eport) 2850 { 2851 bcm_mirror_destination_t *mirror_dest; /* Destination & encapsulation.*/ 2852 _bcm_mtp_config_p mtp_cfg; /* Mtp configuration.*/ 2853 uint32 edit_ctrl_id; 2854 egr_mirror_table_entry_t *mirror_table_p; 2855 2856 /* These entries were initialized by the calling function */ 2857 mirror_table_p = entries[EGR_MIRROR_TABLE_ENTRIES]; 2858 2859 /* Get mtp configuration structure by direction & index. */ 2860 mtp_cfg = MIRROR_CONFIG_MTP(unit, index, flags); 2861 mirror_dest = MIRROR_DEST(unit, mtp_cfg->dest_id); 2862 2863 /* egress IPv6 ERSPAN and IPv6 ERSPAN3 is not supported */ 2864 if ((mirror_dest->gre_protocol == ERSPAN3_GRE_PROTOCOL_TYPE) || 2865 (mtp_cfg->egress)) { 2866 return BCM_E_PARAM; 2867 } 2868 /* Outer vlan tag. */ 2869 2870 if (dest_flags & BCM_MIRROR_DEST_TUNNEL_WITH_SEQ) { 2871 edit_ctrl_id = MIRROR_EDIT_CTRL_ID_ERSPAN_GRE_SEQUENCE_IPV6_INGRESS_MIRROR; 2872 } else { 2873 if (mirror_dest->flags & BCM_MIRROR_DEST_PAYLOAD_UNTAGGED) { 2874 if (BCM_VLAN_CTRL_ID(mirror_dest->vlan_id) > 0) { 2875 edit_ctrl_id = MIRROR_EDIT_CTRL_ID_ERSPAN_IPV6_INGRESS_MIRROR_UNTAG_PAYLOAD; 2876 } else { 2877 edit_ctrl_id = MIRROR_EDIT_CTRL_ID_ERSPAN_UNTAG_IPV6_INGRESS_MIRROR_UNTAG_PAYLOAD; 2878 } 2879 } else { 2880 if (BCM_VLAN_CTRL_ID(mirror_dest->vlan_id) > 0) { 2881 edit_ctrl_id = MIRROR_EDIT_CTRL_ID_ERSPAN_IPV6_INGRESS_MIRROR; 2882 } else { 2883 edit_ctrl_id = MIRROR_EDIT_CTRL_ID_ERSPAN_UNTAG_IPV6_INGRESS_MIRROR; 2884 } 2885 } 2886 } 2887 2888 /* Setup Mirror Table Entry */ 2889 soc_mem_field32_set (unit, EGR_MIRROR_TABLEm, mirror_table_p, 2890 MIRROR_EDIT_CTRL_IDf, edit_ctrl_id); 2891 2892 if (dest_flags & BCM_MIRROR_DEST_TUNNEL_WITH_SEQ) { 2893 BCM_IF_ERROR_RETURN(_bcm_td3_mirror_seq_num_enable (unit, 2894 mirror_table_p, 2895 EGR_MIRROR_TABLE_SEQNUM_OFFSET + index, 2896 BCM_MIRROR_IP_GRE_SEQ_NUM|index)); 2897 } 2898 2899 /* coverity[result_independent_of_operands] */ 2900 if (BCM_VLAN_VALID(mirror_dest->vlan_id)) { 2901 soc_mem_field32_set (unit, EGR_MIRROR_TABLEm, mirror_table_p, 2902 MIRROR_VLAN_VLDf, is_eport? 0:1); 2903 soc_mem_field32_set (unit, EGR_MIRROR_TABLEm, mirror_table_p, 2904 MIRROR_VLANf, mirror_dest->vlan_id); 2905 } 2906 2907 if (mirror_dest->truncate == BCM_MIRROR_PAYLOAD_TRUNCATE) { 2908 soc_mem_field32_set (unit, EGR_MIRROR_TABLEm, mirror_table_p, 2909 TRUNCATE_ENf,1); 2910 } else if (!mirror_dest->truncate) { 2911 soc_mem_field32_set (unit, EGR_MIRROR_TABLEm, mirror_table_p, 2912 TRUNCATE_ENf,0); 2913 } 2914 /* Create the flex editor header */ 2915 BCM_IF_ERROR_RETURN(_bcm_td3_mirror_flex_editor_header_create(unit, 2916 edit_ctrl_id, mirror_dest, entries, is_eport)); 2917 2918 /* Profile entries will be committed to HW by the calling function. */ 2919 2920 return (BCM_E_NONE); 2921 } 2922 2923 /* 2924 * Function: 2925 * _bcm_td3_mirror_trill_tunnel_set 2926 * Purpose: 2927 * Prepare Trill mirror tunnel encapsulation for TD3. 2928 * Parameters: 2929 * unit - (IN) BCM device number 2930 * index - (IN) Mtp index. 2931 * flags - (IN) Mirror direction flags. 2932 * entries - (IN) Pointer to EGR_MIRROR_ENCAP_* entries array 2933 * Returns: 2934 * BCM_E_XXX 2935 */ 2936 int 2937 _bcm_td3_mirror_trill_tunnel_set(int unit, int index, int flags, 2938 void **entries) 2939 { 2940 LOG_ERROR(BSL_LS_SOC_COMMON, 2941 (BSL_META_U(unit, "TD3 NO TRILL SUPPORT \n"))); 2942 return (BCM_E_UNAVAIL); 2943 } 2944 2945 /* 2946 * Function: 2947 * _bcm_td3_mirror_etag_tunnel_set 2948 * Purpose: 2949 * Prepare ETAG mirror tunnel encapsulation for TD3. 2950 * Parameters: 2951 * unit - (IN) BCM device number 2952 * index - (IN) Mtp index. 2953 * flags - (IN) Mirror direction flags. 2954 * entries - (IN) Pointer to EGR_MIRROR_ENCAP_* entries array 2955 * Returns: 2956 * BCM_E_XXX 2957 */ 2958 int 2959 _bcm_td3_mirror_etag_tunnel_set(int unit, int index, int flags, 2960 void **entries, int is_eport) 2961 { 2962 #if 0 2963 _bcm_mtp_config_p mtp_cfg; /* Mtp configuration. */ 2964 bcm_mirror_destination_t *mirror_dest;/* Destination & encapsulation. */ 2965 2966 uint32 edit_ctrl_id, etag = 0; 2967 egr_mirror_table_entry_t *mirror_table_p; 2968 2969 /* These entries were initialized by the calling function */ 2970 mirror_table_p = entries[EGR_MIRROR_TABLE_ENTRIES]; 2971 2972 /* Get mtp configuration structure by direction & index. */ 2973 mtp_cfg = MIRROR_CONFIG_MTP(unit, index, flags); 2974 mirror_dest = MIRROR_DEST(unit, mtp_cfg->dest_id); 2975 2976 edit_ctrl_id = MIRROR_EDIT_CTRL_ID_INGRESS_MIRROR_HG_TAG; 2977 2978 etag = ((uint32)mirror_dest->etag_src_vid & _BCM_MIRROR_ETAG_SRC_VID_MASK) 2979 << _BCM_MIRROR_ETAG_SRC_VID_OFFSET; 2980 etag |= (uint32) mirror_dest->etag_dst_vid & _BCM_MIRROR_ETAG_DST_VID_MASK; 2981 2982 /* Setup Mirror Table Entry */ 2983 soc_mem_field32_set (unit, EGR_MIRROR_TABLEm, mirror_table_p, 2984 MIRROR_EDIT_CTRL_IDf, edit_ctrl_id); 2985 2986 if (BCM_VLAN_VALID(etag)) { 2987 int e_port; 2988 2989 BCM_IF_ERROR_RETURN(_bcm_mirror_eport_status_get(unit, 2990 mirror_dest->gport, &e_port)); 2991 soc_mem_field32_set (unit, EGR_MIRROR_TABLEm, mirror_table_p, 2992 MIRROR_VLAN_VLDf, e_port? 0:1); 2993 soc_mem_field32_set (unit, EGR_MIRROR_TABLEm, mirror_table_p, 2994 MIRROR_VLANf, mirror_dest->etag_dst_vid); 2995 } 2996 2997 if (mirror_dest->truncate == BCM_MIRROR_PAYLOAD_TRUNCATE) { 2998 soc_mem_field32_set (unit, EGR_MIRROR_TABLEm, mirror_table_p, 2999 TRUNCATE_ENf,1); 3000 } else if (!mirror_dest->truncate) { 3001 soc_mem_field32_set (unit, EGR_MIRROR_TABLEm, mirror_table_p, 3002 TRUNCATE_ENf,0); 3003 } 3004 /* Create the flex editor header */ 3005 BCM_IF_ERROR_RETURN(_bcm_td3_mirror_flex_editor_header_create(unit, 3006 edit_ctrl_id, mirror_dest, entries, is_eport)); 3007 3008 /* Profile entries will be committed to HW by the calling function. */ 3009 return (BCM_E_NONE); 3010 #endif 3011 return (BCM_E_UNAVAIL); 3012 } 3013 3014 /* 3015 * Function: 3016 * _bcm_td3_mirror_niv_tunnel_set 3017 * Purpose: 3018 * Prepare NIV mirror tunnel encapsulation for Trident. 3019 * Parameters: 3020 * unit - (IN) BCM device number 3021 * index - (IN) Mtp index. 3022 * flags - (IN) Mirror direction flags. 3023 * entries - (IN) Pointer to EGR_MIRROR_ENCAP_* entries array 3024 * Returns: 3025 * BCM_E_XXX 3026 */ 3027 int 3028 _bcm_td3_mirror_niv_tunnel_set(int unit, int index, int flags, 3029 void **entries, int is_eport) 3030 { 3031 _bcm_mtp_config_p mtp_cfg; /* Mtp configuration. */ 3032 bcm_mirror_destination_t *mirror_dest;/* Destination & encapsulation. */ 3033 3034 uint32 edit_ctrl_id; 3035 egr_mirror_table_entry_t *mirror_table_p; 3036 3037 /* These entries were initialized by the calling function */ 3038 mirror_table_p = entries[EGR_MIRROR_TABLE_ENTRIES]; 3039 3040 /* Get mtp configuration structure by direction & index. */ 3041 mtp_cfg = MIRROR_CONFIG_MTP(unit, index, flags); 3042 mirror_dest = MIRROR_DEST(unit, mtp_cfg->dest_id); 3043 3044 if (flags & BCM_MIRROR_PORT_EGRESS) { 3045 edit_ctrl_id = MIRROR_EDIT_CTRL_ID_RSPAN_EGRESS_MIRROR_WITH_VNTAG; 3046 } else { 3047 edit_ctrl_id = MIRROR_EDIT_CTRL_ID_RSPAN_INGRESS_MIRROR_WITH_VNTAG; 3048 } 3049 3050 /* Setup Mirror Table Entry */ 3051 soc_mem_field32_set (unit, EGR_MIRROR_TABLEm, mirror_table_p, 3052 MIRROR_EDIT_CTRL_IDf, edit_ctrl_id); 3053 3054 if (BCM_VLAN_VALID(mirror_dest->vlan_id)) { 3055 soc_mem_field32_set (unit, EGR_MIRROR_TABLEm, mirror_table_p, 3056 MIRROR_VLAN_VLDf, is_eport? 0:1); 3057 soc_mem_field32_set (unit, EGR_MIRROR_TABLEm, mirror_table_p, 3058 MIRROR_VLANf, mirror_dest->vlan_id); 3059 } 3060 3061 /* Create the flex editor header */ 3062 BCM_IF_ERROR_RETURN(_bcm_td3_mirror_flex_editor_header_create(unit, 3063 edit_ctrl_id, mirror_dest, entries, is_eport)); 3064 3065 /* Profile entries will be committed to HW by the calling function. */ 3066 return (BCM_E_NONE); 3067 } 3068 3069 /* 3070 * Function: 3071 * _bcm_trident3_mirror_sflow_tunnel_set 3072 * Purpose: 3073 * Prepare sFlow mirror tunnel encapsulation. 3074 * Parameters: 3075 * unit - (IN) BCM device number 3076 * index - (IN) Mtp index. 3077 * trunk_arr - (IN) Mirror destinations array. 3078 * flags - (IN) Mirror direction flags. 3079 * Returns: 3080 * BCM_E_XXX 3081 */ 3082 int 3083 _bcm_trident3_mirror_sflow_tunnel_set(int unit, int index, 3084 int flags, int dest_flags, void **entries, int is_eport) 3085 { 3086 uint32 edit_ctrl_id; 3087 _bcm_mtp_config_p mtp_cfg; 3088 bcm_mirror_destination_t *mirror_dest; 3089 egr_mirror_table_entry_t *mirror_table_p; 3090 void *seq_entries[1]; 3091 uint32 profile_idx; 3092 egr_sequence_number_profile_entry_t seq_num_profile_entry; 3093 3094 /* Currently this flag is not supported for TD3 sflow */ 3095 if (dest_flags & BCM_MIRROR_DEST_PAYLOAD_UNTAGGED) { 3096 LOG_ERROR(BSL_LS_BCM_MIRROR, (BSL_META_U(unit, 3097 "Error: Flag BCM_MIRROR_DEST_PAYLOAD_UNTAGGED is not supported\n"))); 3098 return BCM_E_UNAVAIL; 3099 } 3100 3101 /* These entries were initialized by the calling function */ 3102 mirror_table_p = entries[EGR_MIRROR_TABLE_ENTRIES]; 3103 3104 /* Get mtp configuration structure by direction & index. */ 3105 mtp_cfg = MIRROR_CONFIG_MTP(unit, index, flags); 3106 mirror_dest = MIRROR_DEST(unit, mtp_cfg->dest_id); 3107 3108 if (dest_flags & BCM_MIRROR_DEST_TUNNEL_NIV) { 3109 if (BCM_VLAN_CTRL_ID(mirror_dest->vlan_id) > 0) { 3110 edit_ctrl_id = MIRROR_EDIT_CTRL_ID_SFLOW_VNTAG_OTAG; 3111 } else { 3112 edit_ctrl_id = MIRROR_EDIT_CTRL_ID_SFLOW_VNTAG; 3113 } 3114 } else if (dest_flags & BCM_MIRROR_DEST_TUNNEL_ETAG) { 3115 if (BCM_VLAN_CTRL_ID(mirror_dest->vlan_id) > 0) { 3116 edit_ctrl_id = MIRROR_EDIT_CTRL_ID_SFLOW_ETAG_OTAG; 3117 } else { 3118 edit_ctrl_id = MIRROR_EDIT_CTRL_ID_SFLOW_ETAG; 3119 } 3120 } else if (!BCM_VLAN_CTRL_ID(mirror_dest->vlan_id)) { 3121 edit_ctrl_id = MIRROR_EDIT_CTRL_ID_SFLOW_UNTAG_INGRESS_MIRROR; 3122 } else { 3123 edit_ctrl_id = MIRROR_EDIT_CTRL_ID_SFLOW_INGRESS_MIRROR; 3124 } 3125 3126 /* Setup Mirror Table Entry */ 3127 soc_mem_field32_set (unit, EGR_MIRROR_TABLEm, mirror_table_p, 3128 MIRROR_EDIT_CTRL_IDf, edit_ctrl_id); 3129 3130 if (BCM_VLAN_VALID(mirror_dest->vlan_id)) { 3131 soc_mem_field32_set (unit, EGR_MIRROR_TABLEm, mirror_table_p, 3132 MIRROR_VLAN_VLDf, is_eport? 0:1); 3133 soc_mem_field32_set (unit, EGR_MIRROR_TABLEm, mirror_table_p, 3134 MIRROR_VLANf, mirror_dest->vlan_id); 3135 } 3136 if (mirror_dest->truncate == BCM_MIRROR_PAYLOAD_TRUNCATE) { 3137 soc_mem_field32_set (unit, EGR_MIRROR_TABLEm, mirror_table_p, 3138 TRUNCATE_ENf,1); 3139 } else if (!mirror_dest->truncate) { 3140 soc_mem_field32_set (unit, EGR_MIRROR_TABLEm, mirror_table_p, 3141 TRUNCATE_ENf,0); 3142 } 3143 3144 /* Sequence Number Information 3145 * SEQ number counter index is unique for all applications. 3146 * This is shared by EGR_IP_TUNNEL (4K) and VC_SWAP(8K). 3147 * Mirroring uses the region after (4K+8K =12K). Hence 12K added. 3148 */ 3149 BCM_IF_ERROR_RETURN 3150 (soc_reg_field32_modify(unit, PSAMP_CONTROLr, REG_PORT_ANY, INCREMENT_SEQ_NUMf, 1)); 3151 BCM_IF_ERROR_RETURN(_bcm_td3_mirror_seq_num_enable (unit, 3152 mirror_table_p, 3153 EGR_MIRROR_TABLE_SEQNUM_OFFSET + index, 3154 mirror_dest->initial_seq_number)); 3155 /* Configuring sequence number mask and profile index in EGR_MIRROR_TABLE. 3156 * Output Sequence Number = EGR_SEQUENCE_NUMBER_TABLE.SEQUENCE_NUMBER & 3157 * ~(EGR_SEQUENCE_NUMBER_PROFILE.MASK) 3158 */ 3159 sal_memset(&seq_num_profile_entry, 0, sizeof(seq_num_profile_entry)); 3160 soc_mem_field32_set (unit, EGR_SEQUENCE_NUMBER_PROFILEm, 3161 &seq_num_profile_entry, MASKf, 0xffff0000); 3162 soc_mem_field32_set (unit, EGR_SEQUENCE_NUMBER_PROFILEm, 3163 &seq_num_profile_entry, RESERVED_VALUEf, 0xffffffff); 3164 soc_mem_field32_set (unit, EGR_SEQUENCE_NUMBER_PROFILEm, 3165 &seq_num_profile_entry, SEQUENCE_NUMBER_INCREMENTf, 3166 0x1); 3167 seq_entries[0] = &seq_num_profile_entry; 3168 BCM_IF_ERROR_RETURN(soc_profile_mem_add(unit, 3169 EGR_SEQ_NUMBER_PROFILE(unit), seq_entries, 1, 3170 &profile_idx)); 3171 soc_mem_field32_set (unit, EGR_MIRROR_TABLEm, mirror_table_p, 3172 SEQ_NUM_PROFILE_INDEXf, profile_idx); 3173 3174 /* sFlow shim header user meta data field */ 3175 soc_mem_field32_set (unit, EGR_MIRROR_TABLEm, mirror_table_p, 3176 MIRROR_ENCAP_DATA_VALIDf, 1); 3177 soc_mem_field32_set (unit, EGR_MIRROR_TABLEm, mirror_table_p, 3178 MIRROR_ENCAP_DATA_0f, mirror_dest->meta_data); 3179 3180 /* Create the flex editor header */ 3181 BCM_IF_ERROR_RETURN(_bcm_td3_mirror_flex_editor_header_create(unit, 3182 edit_ctrl_id, mirror_dest, entries, is_eport)); 3183 3184 return BCM_E_NONE; 3185 } 3186 3187 extern int 3188 _bcm_egr_mirror_encap_entry_mtp_update(int unit, int index, 3189 uint32 profile_index, int flags); 3190 STATIC int 3191 _bcm_td3_egr_mirror_encap_entry_mtp_update(int unit, int index, 3192 uint32 profile_index, int flags, 3193 bcm_gport_t *trunk_arr, int is_eport) 3194 { 3195 int offset; 3196 int idx, id; 3197 int refs = 0; 3198 int max_num_trunk_ports = 0; 3199 bcm_port_t port = -1, port_out; 3200 bcm_module_t modid = 0, mod_out; 3201 bcm_trunk_t trunk = BCM_TRUNK_INVALID; 3202 int is_local_modid = 0; 3203 _bcm_mtp_config_p mtp_cfg; 3204 int is_trunk = 0; 3205 3206 /* Get mtp configuration structure by direction & index. */ 3207 mtp_cfg = MIRROR_CONFIG_MTP(unit, index, flags); 3208 is_trunk = BCM_GPORT_IS_TRUNK(MIRROR_DEST_GPORT(unit, mtp_cfg->dest_id)); 3209 3210 refs = 0; 3211 max_num_trunk_ports = BCM_SWITCH_TRUNK_MAX_PORTCNT; 3212 3213 offset = index * max_num_trunk_ports; 3214 3215 for (idx = 0; idx < max_num_trunk_ports; idx++, offset++) { 3216 BCM_IF_ERROR_RETURN(_bcm_esw_gport_resolve( 3217 unit, trunk_arr[idx],&modid,&port,&trunk, &id)); 3218 BCM_IF_ERROR_RETURN 3219 (_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_SET, 3220 modid, port, &mod_out, &port_out)); 3221 BCM_IF_ERROR_RETURN 3222 (_bcm_esw_modid_is_local(unit, mod_out, &is_local_modid)); 3223 3224 if (is_trunk) { 3225 if (is_eport) { 3226 /* Update only local trunk members */ 3227 if (!is_local_modid || IS_HG_PORT(unit, port)) { 3228 continue; 3229 } 3230 } else { 3231 /* Update only remote trunk members */ 3232 if (is_local_modid && !(IS_HG_PORT(unit, port))) { 3233 continue; 3234 } 3235 } 3236 } 3237 3238 if (flags & BCM_MIRROR_PORT_INGRESS) { 3239 if ((MIRROR_DEST(unit, mtp_cfg->dest_id))->flags2 & 3240 BCM_MIRROR_DEST_FLAGS2_IFA) { 3241 BCM_IF_ERROR_RETURN 3242 (soc_mem_field32_modify(unit, EGR_EM_MTP_INDEXm, 3243 offset, MIRROR_ENCAP_INDEXf, 3244 profile_index)); 3245 } else { 3246 BCM_IF_ERROR_RETURN 3247 (soc_mem_field32_modify(unit, EGR_IM_MTP_INDEXm, 3248 offset, MIRROR_ENCAP_INDEXf, 3249 profile_index)); 3250 } 3251 3252 if (0 == idx) { 3253 refs++; 3254 } 3255 } 3256 3257 if (flags & BCM_MIRROR_PORT_EGRESS) { 3258 BCM_IF_ERROR_RETURN 3259 (soc_mem_field32_modify(unit, EGR_EM_MTP_INDEXm, 3260 offset, MIRROR_ENCAP_INDEXf, 3261 profile_index)); 3262 if (0 == idx) { 3263 refs++; 3264 } 3265 } 3266 3267 if (soc_feature(unit, soc_feature_egr_mirror_true) && 3268 (flags & BCM_MIRROR_PORT_EGRESS_TRUE)) { 3269 BCM_IF_ERROR_RETURN 3270 (soc_mem_field32_modify(unit, EGR_EP_REDIRECT_EM_MTP_INDEXm, 3271 offset, MIRROR_ENCAP_INDEXf, 3272 profile_index)); 3273 if (0 == idx) { 3274 refs++; 3275 } 3276 } 3277 } 3278 3279 if (refs > 1) { 3280 /* We should never have more than one mirror direction flag set. */ 3281 return BCM_E_INTERNAL; 3282 } 3283 3284 return (BCM_E_NONE); 3285 } 3286 3287 /* 3288 * Function: 3289 * _bcm_td3_mirror_vlan_set 3290 * Description: 3291 * Set VLAN for egressing mirrored packets on a port (RSPAN) 3292 * This will support the legacy mode where RSPAN is a per-egress-port 3293 * property. 3294 * Parameters: 3295 * unit - (IN) Bcm device number. 3296 * port - (IN) Mirror-to port to set (-1 for all ports). 3297 * tpid - (IN) Tag protocol id (0 to disable). 3298 * vlan - (IN) Virtual lan number (0 to disable). 3299 * Returns: 3300 * BCM_E_XXX 3301 */ 3302 int 3303 _bcm_td3_mirror_vlan_set(int unit, bcm_port_t port, 3304 uint16 tpid, uint16 vlan) 3305 { 3306 void *entries[EGR_MIRROR_TABLE_ENTRIES_NUM]; 3307 int rv = BCM_E_NONE, encap_profile_index; 3308 uint32 profile_index, old_profile_index = 0; 3309 uint32 vtag, edit_ctrl_id; 3310 3311 egr_lport_profile_entry_t egr_lport_profile_entry; 3312 egr_mirror_table_entry_t table_entry; 3313 3314 flex_editor_mirror_encap_0_profile_1_table_entry_t profile_1; 3315 3316 vtag = (uint32)(tpid << 16) | vlan; 3317 3318 if (0 != vtag) { 3319 sal_memset(&table_entry, 0, sizeof(table_entry)); 3320 sal_memset(&profile_1, 0, sizeof(profile_1)); 3321 3322 entries[0] = &table_entry; 3323 3324 /* Get profile index before EGR_MIRROR_TABLE is programmed */ 3325 edit_ctrl_id = MIRROR_EDIT_CTRL_ID_RSPAN_EGRESS_MIRROR; 3326 BCM_IF_ERROR_RETURN (_bcm_td3_mirror_encap_profile_index_set(unit, 3327 edit_ctrl_id, IS_E_PORT(unit, port)? 1 : 0, 3328 0, &encap_profile_index, entries)); 3329 3330 /* Create the flex editor header */ 3331 *((uint32*)&profile_1) = vtag; 3332 3333 BCM_IF_ERROR_RETURN (soc_mem_write(unit, 3334 FLEX_EDITOR_MIRROR_ENCAP_0_PROFILE_1_TABLEm, 3335 MEM_BLOCK_ANY, encap_profile_index, &profile_1)); 3336 3337 /* Setup Mirror Table Entry */ 3338 soc_mem_field32_set (unit, EGR_MIRROR_TABLEm, &table_entry, 3339 MIRROR_EDIT_CTRL_IDf, edit_ctrl_id); 3340 soc_mem_field32_set (unit, EGR_MIRROR_TABLEm, &table_entry, 3341 MIRROR_VLAN_VLDf, IS_E_PORT(unit, port)? 0:1); 3342 soc_mem_field32_set (unit, EGR_MIRROR_TABLEm, &table_entry, 3343 MIRROR_VLANf, vlan); 3344 3345 rv = _bcm_td3_egr_mirror_table_entry_add(unit, entries, &profile_index); 3346 3347 if (BCM_SUCCESS(rv)) { 3348 /* Remove the previous profile index if any */ 3349 rv = READ_EGR_LPORT_PROFILEm(unit, MEM_BLOCK_ANY, port, 3350 &egr_lport_profile_entry); 3351 3352 old_profile_index = -1; 3353 if (BCM_SUCCESS(rv) && 3354 (0 != soc_EGR_LPORT_PROFILEm_field32_get(unit, 3355 &egr_lport_profile_entry, MIRROR_ENCAP_ENABLEf))) { 3356 old_profile_index = 3357 soc_EGR_LPORT_PROFILEm_field32_get(unit, 3358 &egr_lport_profile_entry, MIRROR_ENCAP_INDEXf); 3359 } 3360 3361 /* Supply the correct profile index to the egress port */ 3362 soc_EGR_LPORT_PROFILEm_field32_set(unit, &egr_lport_profile_entry, 3363 MIRROR_ENCAP_ENABLEf, 1); 3364 soc_EGR_LPORT_PROFILEm_field32_set(unit, &egr_lport_profile_entry, 3365 MIRROR_ENCAP_INDEXf, profile_index); 3366 rv = WRITE_EGR_LPORT_PROFILEm(unit, MEM_BLOCK_ANY, port, 3367 &egr_lport_profile_entry); 3368 3369 } 3370 if (BCM_SUCCESS(rv) && (-1 != old_profile_index)) { 3371 rv = _bcm_td3_egr_mirror_table_entry_delete(unit, old_profile_index); 3372 } 3373 } else { 3374 rv = READ_EGR_LPORT_PROFILEm(unit, MEM_BLOCK_ANY, port, 3375 &egr_lport_profile_entry); 3376 3377 if (BCM_SUCCESS(rv) && 3378 (0 != soc_EGR_LPORT_PROFILEm_field32_get(unit, 3379 &egr_lport_profile_entry, MIRROR_ENCAP_ENABLEf))) { 3380 old_profile_index = 3381 soc_EGR_LPORT_PROFILEm_field32_get(unit, 3382 &egr_lport_profile_entry, MIRROR_ENCAP_INDEXf); 3383 soc_EGR_LPORT_PROFILEm_field32_set(unit, &egr_lport_profile_entry, 3384 MIRROR_ENCAP_ENABLEf, 0); 3385 soc_EGR_LPORT_PROFILEm_field32_set(unit, &egr_lport_profile_entry, 3386 MIRROR_ENCAP_INDEXf, 0); 3387 rv = WRITE_EGR_LPORT_PROFILEm(unit, MEM_BLOCK_ANY, port, 3388 &egr_lport_profile_entry); 3389 3390 if (BCM_SUCCESS(rv)) { 3391 rv = _bcm_td3_egr_mirror_table_entry_delete(unit, 3392 old_profile_index); 3393 } 3394 } 3395 } 3396 return rv; 3397 } 3398 3399 /* 3400 * Function: 3401 * _bcm_td3_mirror_vlan_get 3402 * Description: 3403 * Get VLAN for egressing mirrored packets on a port (RSPAN) 3404 * This will support the legacy mode where RSPAN is a per-egress-port 3405 * property. 3406 * Parameters: 3407 * unit - (IN) Bcm device number. 3408 * port - (IN) Mirror-to port to set (-1 for all ports). 3409 * tpid - (OUT) Tag protocol id (0 to disable). 3410 * vlan - (OUT) Virtual lan number (0 to disable). 3411 * Returns: 3412 * BCM_E_XXX 3413 */ 3414 int 3415 _bcm_td3_mirror_vlan_get(int unit, bcm_port_t port, 3416 uint16 *tpid, uint16 *vlan) 3417 { 3418 void *entries[EGR_MIRROR_TABLE_ENTRIES_NUM]; 3419 uint32 profile_index = 0, vtag, edit_ctrl_id; 3420 int encap_profile_index; 3421 3422 egr_lport_profile_entry_t egr_lport_profile_entry; 3423 egr_mirror_table_entry_t table_entry; 3424 3425 flex_editor_mirror_encap_0_profile_1_table_entry_t profile_1; 3426 3427 BCM_IF_ERROR_RETURN(READ_EGR_LPORT_PROFILEm(unit, MEM_BLOCK_ANY, port, 3428 &egr_lport_profile_entry)); 3429 3430 if (0 == soc_EGR_LPORT_PROFILEm_field32_get(unit, &egr_lport_profile_entry, 3431 MIRROR_ENCAP_ENABLEf)) { 3432 return BCM_E_NOT_FOUND; 3433 } 3434 3435 profile_index = soc_EGR_LPORT_PROFILEm_field32_get(unit, 3436 &egr_lport_profile_entry, MIRROR_ENCAP_INDEXf); 3437 entries[0] = &table_entry; 3438 3439 BCM_IF_ERROR_RETURN (soc_profile_mem_get(unit, EGR_MIRROR_TABLE(unit), 3440 profile_index, 1, entries)); 3441 3442 3443 edit_ctrl_id = soc_EGR_MIRROR_TABLEm_field32_get(unit, entries[0], 3444 MIRROR_EDIT_CTRL_IDf); 3445 if (!_is_edit_ctrl_id_rspan(edit_ctrl_id)) { 3446 return BCM_E_CONFIG; 3447 } 3448 3449 BCM_IF_ERROR_RETURN (_bcm_td3_mirror_encap_edit_ctrl_id_get(unit, 3450 edit_ctrl_id, 0, 3451 &encap_profile_index)); 3452 BCM_IF_ERROR_RETURN (soc_mem_read(unit, 3453 FLEX_EDITOR_MIRROR_ENCAP_0_PROFILE_1_TABLEm, 3454 MEM_BLOCK_ANY, MIRROR_ECD_INDEX_LOCAL(encap_profile_index), &profile_1)); 3455 3456 /* RSPAN recovery */ 3457 vtag = *((uint32*)&profile_1); 3458 3459 *vlan = (bcm_vlan_t) (vtag & 0xffff); 3460 *tpid = (uint16) ((vtag >> 16) & 0xffff); 3461 3462 return BCM_E_NONE; 3463 } 3464 3465 3466 #ifdef BCM_WARM_BOOT_SUPPORT_SW_DUMP 3467 /* 3468 * Function: 3469 * _bcm_td3_mirror_encap_sw_dump 3470 * Purpose: 3471 * Displays mirror software structure information. 3472 * Parameters: 3473 * unit - Device unit number 3474 * Returns: 3475 * None 3476 */ 3477 void 3478 _bcm_td3_mirror_encap_sw_dump(int unit) 3479 { 3480 void *entries[EGR_MIRROR_TABLE_ENTRIES_NUM]; 3481 egr_mirror_table_entry_t table_entry; 3482 int encap_profile_offset = 0; 3483 3484 flex_editor_mirror_encap_0_profile_1_table_entry_t profile_1; 3485 flex_editor_mirror_encap_0_profile_2_table_entry_t profile_2; 3486 flex_editor_mirror_encap_0_profile_3_table_entry_t profile_3; 3487 3488 int i, rv, ref_count, num_entries; 3489 3490 entries[EGR_MIRROR_TABLE_ENTRIES] = &table_entry; 3491 3492 num_entries = soc_mem_index_count(unit, EGR_MIRROR_TABLEm); 3493 3494 LOG_CLI((BSL_META_U(unit, "\n Egress encap profiles\n"))); 3495 LOG_CLI((BSL_META_U(unit, " Number of entries: %d\n"), num_entries)); 3496 3497 for (i = 0; i < num_entries; i ++) { 3498 rv = soc_profile_mem_ref_count_get(unit, EGR_MIRROR_TABLE(unit), 3499 i, &ref_count); 3500 if (SOC_FAILURE(rv)) { 3501 LOG_CLI((BSL_META_U(unit, 3502 " *** Error retrieving profile reference: %d ***\n"), rv)); 3503 break; 3504 } 3505 3506 if (ref_count <= 0) { 3507 continue; 3508 } 3509 3510 rv = soc_profile_mem_get(unit, EGR_MIRROR_TABLE(unit), i, 1, entries); 3511 if (SOC_FAILURE(rv)) { 3512 LOG_CLI((BSL_META_U(unit, 3513 " *** Error retrieving profile data: %d ***\n"), rv)); 3514 break; 3515 } 3516 3517 encap_profile_offset = soc_mem_field32_get (unit, EGR_MIRROR_TABLEm, 3518 entries[EGR_MIRROR_TABLE_ENTRIES], 3519 MIRROR_ENGINE_PROFILE_OFFSETf); 3520 3521 rv = soc_mem_read(unit, FLEX_EDITOR_MIRROR_ENCAP_0_PROFILE_1_TABLEm, 3522 MEM_BLOCK_ANY, encap_profile_offset+1, &profile_1); 3523 if (rv) break; 3524 rv = soc_mem_read(unit, FLEX_EDITOR_MIRROR_ENCAP_0_PROFILE_2_TABLEm, 3525 MEM_BLOCK_ANY, encap_profile_offset+1, &profile_2); 3526 if (rv) break; 3527 rv = soc_mem_read(unit, FLEX_EDITOR_MIRROR_ENCAP_0_PROFILE_3_TABLEm, 3528 MEM_BLOCK_ANY, encap_profile_offset+1, &profile_3); 3529 if (rv) break; 3530 3531 if (SOC_FAILURE(rv)) { 3532 LOG_CLI((BSL_META_U(unit, 3533 " *** Error retrieving encap profile data: %d ***\n"), rv)); 3534 break; 3535 } 3536 3537 LOG_CLI((BSL_META_U(unit, " %5d %8d\n"), i, ref_count)); 3538 soc_mem_entry_dump(unit, EGR_MIRROR_TABLEm, 3539 entries[EGR_MIRROR_TABLE_ENTRIES], BSL_LSS_CLI); 3540 LOG_CLI((BSL_META_U(unit, "\n"))); 3541 soc_mem_entry_dump(unit, FLEX_EDITOR_MIRROR_ENCAP_0_PROFILE_1_TABLEm, 3542 &profile_1, BSL_LSS_CLI); 3543 LOG_CLI((BSL_META_U(unit, "\n"))); 3544 soc_mem_entry_dump(unit, FLEX_EDITOR_MIRROR_ENCAP_0_PROFILE_2_TABLEm, 3545 &profile_2, BSL_LSS_CLI); 3546 LOG_CLI((BSL_META_U(unit, "\n"))); 3547 soc_mem_entry_dump(unit, FLEX_EDITOR_MIRROR_ENCAP_0_PROFILE_3_TABLEm, 3548 &profile_3, BSL_LSS_CLI); 3549 LOG_CLI((BSL_META_U(unit, "\n"))); 3550 } 3551 3552 return; 3553 } 3554 #endif /* BCM_WARM_BOOT_SUPPORT_SW_DUMP */ 3555 3556 /* 3557 * Function: 3558 * _bcm_td3_mirror_vxlan_tunnel_set 3559 * Purpose: 3560 * Prepare VXLAN for Trident3. 3561 * Parameters: 3562 * unit - (IN) BCM device number 3563 * index - (IN) Mtp index. 3564 * flags - (IN) Mirror direction flags. 3565 * entries - (IN) Pointer to EGR_MIRROR_ENCAP_* entries array 3566 * Returns: 3567 * BCM_E_XXX 3568 */ 3569 int 3570 _bcm_td3_mirror_vxlan_tunnel_set(int unit, int index, int flags, 3571 void **entries, int is_eport) 3572 { 3573 _bcm_mtp_config_p mtp_cfg; /* Mtp configuration. */ 3574 bcm_mirror_destination_t *mirror_dest;/* Destination & encapsulation. */ 3575 uint32 edit_ctrl_id; 3576 egr_mirror_table_entry_t *mirror_table_p; 3577 int lcl_port; 3578 3579 /* These entries were initialized by the calling function */ 3580 mirror_table_p = entries[EGR_MIRROR_TABLE_ENTRIES]; 3581 3582 /* Get mtp configuration structure by direction & index. */ 3583 mtp_cfg = MIRROR_CONFIG_MTP(unit, index, flags); 3584 mirror_dest = MIRROR_DEST(unit, mtp_cfg->dest_id); 3585 3586 edit_ctrl_id = (mirror_dest->version == IPV6_VERSION) ? 3587 MIRROR_EDIT_CTRL_ID_VXLAN_IPV6 : 3588 MIRROR_EDIT_CTRL_ID_VXLAN; 3589 3590 /* Setup Mirror Table Entry */ 3591 soc_mem_field32_set (unit, EGR_MIRROR_TABLEm, mirror_table_p, 3592 MIRROR_EDIT_CTRL_IDf, edit_ctrl_id); 3593 3594 lcl_port = mirror_dest->gport & MIRROR_PORT_MASK; 3595 if (BCM_VLAN_VALID(mirror_dest->vlan_id)) { 3596 soc_mem_field32_set (unit, EGR_MIRROR_TABLEm, mirror_table_p, 3597 MIRROR_VLAN_VLDf, is_eport? 0:1); 3598 soc_mem_field32_set (unit, EGR_MIRROR_TABLEm, mirror_table_p, 3599 MIRROR_VLANf, mirror_dest->vlan_id); 3600 } 3601 if (mirror_dest->truncate == BCM_MIRROR_PAYLOAD_TRUNCATE) { 3602 soc_mem_field32_set (unit, EGR_MIRROR_TABLEm, mirror_table_p, 3603 TRUNCATE_ENf,1); 3604 } else if (!mirror_dest->truncate) { 3605 soc_mem_field32_set (unit, EGR_MIRROR_TABLEm, mirror_table_p, 3606 TRUNCATE_ENf,0); 3607 } 3608 3609 /* set VXLT_CTRL_ID */ 3610 BCM_IF_ERROR_RETURN(_bcm_esw_egr_port_tab_set(unit, lcl_port, 3611 VXLT_CTRL_IDf, 0xF)); 3612 /* Create the flex editor header */ 3613 BCM_IF_ERROR_RETURN(_bcm_td3_mirror_flex_editor_header_create(unit, 3614 edit_ctrl_id, mirror_dest, entries, is_eport)); 3615 3616 return (BCM_E_NONE); 3617 } 3618 /* 3619 * Function: 3620 * _bcm_td3_mirror_int_probe_set 3621 * Purpose: 3622 * Set up INT probe base header mirror encap profile. 3623 * Parameters: 3624 * unit - (IN) BCM device number 3625 * index - (IN) Mtp index. 3626 * flags - (IN) Mirror direction flags. 3627 * entries - (IN) Pointer to EGR_MIRROR_ENCAP_* entries array 3628 * Returns: 3629 * BCM_E_XXX 3630 */ 3631 int 3632 _bcm_td3_mirror_int_probe_set(int unit, int index, int flags, 3633 void **entries, int is_eport) 3634 { 3635 _bcm_mtp_config_p mtp_cfg; /* Mtp configuration. */ 3636 bcm_mirror_destination_t *mirror_dest;/* Destination & encapsulation. */ 3637 uint32 edit_ctrl_id; 3638 egr_mirror_table_entry_t *mirror_table_p; 3639 3640 /* These entries were initialized by the calling function */ 3641 mirror_table_p = entries[EGR_MIRROR_TABLE_ENTRIES]; 3642 3643 /* Get mtp configuration structure by direction & index. */ 3644 mtp_cfg = MIRROR_CONFIG_MTP(unit, index, flags); 3645 mirror_dest = MIRROR_DEST(unit, mtp_cfg->dest_id); 3646 3647 edit_ctrl_id = (mirror_dest->flags2 & BCM_MIRROR_DEST_FLAGS2_INT_PROBE) ? 3648 MIRROR_EDIT_CTRL_ID_INT_PROBE : 3649 MIRROR_EDIT_CTRL_ID_IFA; 3650 3651 /* Setup Mirror Table Entry */ 3652 soc_mem_field32_set (unit, EGR_MIRROR_TABLEm, mirror_table_p, 3653 MIRROR_EDIT_CTRL_IDf, edit_ctrl_id); 3654 3655 if (mirror_dest->truncate == BCM_MIRROR_PAYLOAD_TRUNCATE) { 3656 soc_mem_field32_set (unit, EGR_MIRROR_TABLEm, mirror_table_p, 3657 TRUNCATE_ENf,1); 3658 } else if (!mirror_dest->truncate) { 3659 soc_mem_field32_set (unit, EGR_MIRROR_TABLEm, mirror_table_p, 3660 TRUNCATE_ENf,0); 3661 } 3662 3663 /* Create the flex editor header */ 3664 BCM_IF_ERROR_RETURN(_bcm_td3_mirror_flex_editor_header_create(unit, 3665 edit_ctrl_id, mirror_dest, entries, is_eport)); 3666 3667 return (BCM_E_NONE); 3668 } 3669 /* 3670 * Function: 3671 * _bcm_td3_mirror_psamp_tunnel_set 3672 * Purpose: 3673 * Prepare PSAMP for Trident. 3674 * Parameters: 3675 * unit - (IN) BCM device number 3676 * index - (IN) Mtp index. 3677 * flags - (IN) Mirror direction flags. 3678 * entries - (IN) Pointer to EGR_MIRROR_ENCAP_* entries array 3679 * Returns: 3680 * BCM_E_XXX 3681 */ 3682 int 3683 _bcm_td3_mirror_psamp_tunnel_set(int unit, int index, int flags, 3684 int dest_flags, void **entries, int is_eport) 3685 { 3686 _bcm_mtp_config_p mtp_cfg; /* Mtp configuration. */ 3687 bcm_mirror_destination_t *mirror_dest;/* Destination & encapsulation. */ 3688 uint32 edit_ctrl_id; 3689 egr_mirror_table_entry_t *mirror_table_p; 3690 void *seq_entries[1]; 3691 uint32 profile_idx; 3692 egr_sequence_number_profile_entry_t seq_num_profile_entry; 3693 3694 /* These entries were initialized by the calling function */ 3695 mirror_table_p = entries[EGR_MIRROR_TABLE_ENTRIES]; 3696 3697 /* Get mtp configuration structure by direction & index. */ 3698 mtp_cfg = MIRROR_CONFIG_MTP(unit, index, flags); 3699 mirror_dest = MIRROR_DEST(unit, mtp_cfg->dest_id); 3700 3701 if (mirror_dest->version == IPV6_VERSION) { 3702 edit_ctrl_id = MIRROR_EDIT_CTRL_ID_PSAMP_IPV6; 3703 } else if (dest_flags & BCM_MIRROR_DEST_TUNNEL_NIV) { 3704 edit_ctrl_id = MIRROR_EDIT_CTRL_ID_PSAMP_VNTAG_OTAG; 3705 } else if (mirror_dest->truncate == BCM_MIRROR_PAYLOAD_TRUNCATE) { 3706 edit_ctrl_id = MIRROR_EDIT_CTRL_ID_PSAMP_TRUNCATE; 3707 } else if (dest_flags & BCM_MIRROR_DEST_PAYLOAD_UNTAGGED) { 3708 edit_ctrl_id = MIRROR_EDIT_CTRL_ID_PSAMP_UNTAG; 3709 /* this feature is not supported currently (TD3ARCH-3196) */ 3710 return (BCM_E_UNAVAIL); 3711 } else { 3712 edit_ctrl_id = MIRROR_EDIT_CTRL_ID_PSAMP; 3713 } 3714 3715 /* Setup Mirror Table Entry */ 3716 soc_mem_field32_set (unit, EGR_MIRROR_TABLEm, mirror_table_p, 3717 MIRROR_EDIT_CTRL_IDf, edit_ctrl_id); 3718 3719 if (BCM_VLAN_VALID(mirror_dest->vlan_id)) { 3720 soc_mem_field32_set (unit, EGR_MIRROR_TABLEm, mirror_table_p, 3721 MIRROR_VLAN_VLDf, is_eport? 0:1); 3722 soc_mem_field32_set (unit, EGR_MIRROR_TABLEm, mirror_table_p, 3723 MIRROR_VLANf, mirror_dest->vlan_id); 3724 } 3725 3726 soc_mem_field32_set (unit, EGR_MIRROR_TABLEm, mirror_table_p, 3727 TRUNCATE_ENf, mirror_dest->truncate); 3728 3729 /* Sequence Number Information */ 3730 /* SEQ number counter index is unique for all applications. 3731 * This is shared by EGR_IP_TUNNEL (4K) and VC_SWAP(8K). 3732 * Mirroring uses the region after (4K+8K =12K). Hence 12K added. 3733 */ 3734 BCM_IF_ERROR_RETURN(_bcm_td3_mirror_seq_num_enable (unit, 3735 mirror_table_p, 3736 EGR_MIRROR_TABLE_SEQNUM_OFFSET + index, 3737 BCM_MIRROR_PSAMP_SEQ_NUM|mirror_dest->vlan_id)); 3738 /* Configuring sequence number mask and profile index in EGR_MIRROR_TABLE. 3739 * Output Sequence Number = EGR_SEQUENCE_NUMBER_TABLE.SEQUENCE_NUMBER & 3740 * ~(EGR_SEQUENCE_NUMBER_PROFILE.MASK) 3741 */ 3742 sal_memset(&seq_num_profile_entry, 0, sizeof(seq_num_profile_entry)); 3743 soc_mem_field32_set (unit, EGR_SEQUENCE_NUMBER_PROFILEm, 3744 &seq_num_profile_entry, MASKf, 0xffff0000); 3745 soc_mem_field32_set (unit, EGR_SEQUENCE_NUMBER_PROFILEm, 3746 &seq_num_profile_entry, RESERVED_VALUEf, 0xffffffff); 3747 soc_mem_field32_set (unit, EGR_SEQUENCE_NUMBER_PROFILEm, 3748 &seq_num_profile_entry, SEQUENCE_NUMBER_INCREMENTf, 3749 0x1); 3750 seq_entries[0] = &seq_num_profile_entry; 3751 BCM_IF_ERROR_RETURN(soc_profile_mem_add(unit, 3752 EGR_SEQ_NUMBER_PROFILE(unit), seq_entries, 1, 3753 &profile_idx)); 3754 soc_mem_field32_set (unit, EGR_MIRROR_TABLEm, mirror_table_p, 3755 SEQ_NUM_PROFILE_INDEXf, profile_idx); 3756 3757 /* Packet Sampling Information */ 3758 soc_mem_field32_set (unit, EGR_MIRROR_TABLEm, mirror_table_p, 3759 PSAMP_DATA_VALIDf, 1); 3760 soc_mem_field32_set (unit, EGR_MIRROR_TABLEm, mirror_table_p, 3761 IPFIX_VERSIONf, 0xa); 3762 soc_mem_field32_set (unit, EGR_MIRROR_TABLEm, mirror_table_p, 3763 IPFIX_OBSERVATION_DOMAINf, 3764 mirror_dest->observation_domain ? 3765 mirror_dest->observation_domain : 3766 BCM_MIRROR_IPFIX_OBSERVATION_DOMAIN_DFLT); 3767 soc_mem_field32_set (unit, EGR_MIRROR_TABLEm, mirror_table_p, 3768 PSAMP_TEMPLATE_IDf, 3769 mirror_dest->template_id? 3770 mirror_dest->template_id : 3771 BCM_MIRROR_IPFIX_TEMPLATE_ID_DFLT); 3772 soc_mem_field32_set (unit, EGR_MIRROR_TABLEm, mirror_table_p, 3773 PSAMP_PADf, 0x00FF); 3774 3775 /* Create the flex editor header */ 3776 BCM_IF_ERROR_RETURN(_bcm_td3_mirror_flex_editor_header_create(unit, 3777 edit_ctrl_id, mirror_dest, entries, is_eport)); 3778 3779 /* Profile entries will be committed to HW by the calling function. */ 3780 return (BCM_E_NONE); 3781 } 3782 3783 /* 3784 * Function: 3785 * _bcm_td3_mirror_flex_editor_header_decode 3786 * Purpose: 3787 * Create the header to be written into flex 3788 * editor 3789 * Parameters: 3790 * unit - (IN) BCM device number. 3791 * edit_ctrl_id - (IN) Encapsulation information. 3792 * mirror_dest - (OUT) destination information. 3793 * profile_1_entry - (IN) Encap profile index 3794 * profile_2_entry - (IN) Encap profile index 3795 * Returns: 3796 * BCM_E_XXX 3797 */ 3798 STATIC int 3799 _bcm_td3_mirror_flex_editor_header_decode(int unit, int edit_ctrl_id, 3800 bcm_mirror_destination_t *mirror_dest, 3801 uint8 *p_profile_1_hdr, uint8 *p_profile_2_hdr) 3802 3803 { 3804 uint8 *p_profile_header, p_profile_hdr[EGR_MIRROR_FLEX_EDITOR_WIDTH * 2]; 3805 uint32 tmp, idx, mcnt; 3806 uint32 *p_hdr = (uint32*)p_profile_hdr; 3807 uint8 flow_label_upper; 3808 3809 /* Reverse Copy -- endian thingee */ 3810 for (mcnt = 0; mcnt < EGR_MIRROR_FLEX_EDITOR_WIDTH/4; mcnt++) { 3811 idx = EGR_MIRROR_FLEX_EDITOR_WIDTH - 4*(mcnt + 1); 3812 3813 tmp = *((uint32*)&p_profile_1_hdr[idx]); 3814 p_hdr[mcnt] = soc_ntohl(tmp); 3815 3816 tmp = *((uint32*)&p_profile_2_hdr[idx]); 3817 p_hdr[mcnt+(EGR_MIRROR_FLEX_EDITOR_WIDTH/4)] = soc_ntohl(tmp); 3818 } 3819 3820 p_profile_header = p_profile_hdr; 3821 3822 if (_is_edit_ctrl_id_sflow(edit_ctrl_id) || 3823 _is_edit_ctrl_id_vxlan(edit_ctrl_id) || 3824 _is_edit_ctrl_id_psamp(edit_ctrl_id)) { 3825 3826 /* SFLOW VNTAG recovery MACDA,MACSA,VNTAG, IPV4,UDP, SFLOW_SHIM */ 3827 /* PSAMP recovery MACDA,MACSA,OTAG, IPV4,UDP, IPFIX, PSAMP */ 3828 /* SFLOW recovery MACDA,MACSA,OTAG, IPV4,UDP, SFLOW SHIM, */ 3829 3830 /* Extract MAC and VLAN information L2 Stuff */ 3831 sal_memcpy(mirror_dest->dst_mac, p_profile_header, 6); 3832 p_profile_header+=6; 3833 sal_memcpy(mirror_dest->src_mac, p_profile_header, 6); 3834 p_profile_header+=6; 3835 3836 /* for VNTAG */ 3837 if (_is_edit_ctrl_id_vntag(edit_ctrl_id)) { 3838 p_profile_header+=sizeof(uint16); /* VNTAG ether type 2 bytes*/ 3839 3840 mirror_dest->niv_dst_vif = 3841 *(uint16*)p_profile_header & _BCM_TD_MIRROR_NIV_DST_VIF_MASK; 3842 p_profile_header+=sizeof(uint16); 3843 mirror_dest->niv_dst_vif = soc_ntohs(mirror_dest->niv_dst_vif); 3844 3845 mirror_dest->niv_src_vif = 3846 *(uint16*)p_profile_header & _BCM_TD_MIRROR_NIV_SRC_VIF_MASK; 3847 p_profile_header+=sizeof(uint16); 3848 mirror_dest->niv_src_vif = soc_ntohs(mirror_dest->niv_src_vif); 3849 3850 mirror_dest->niv_flags = (mirror_dest->niv_src_vif & 3851 soc_ntohs(_BCM_TD_MIRROR_NIV_LOOP_BIT)) ? 3852 BCM_MIRROR_NIV_LOOP : 0; 3853 } 3854 3855 /* for ETAG */ 3856 if ((edit_ctrl_id == MIRROR_EDIT_CTRL_ID_SFLOW_ETAG_OTAG) || 3857 (edit_ctrl_id == MIRROR_EDIT_CTRL_ID_SFLOW_ETAG)) { 3858 sal_memcpy(&mirror_dest->etag_src_vid, p_profile_header, sizeof(uint16)); 3859 mirror_dest->etag_src_vid = soc_ntohs(mirror_dest->etag_src_vid); 3860 p_profile_header+=sizeof(uint16); 3861 3862 sal_memcpy(&mirror_dest->etag_dst_vid, p_profile_header, sizeof(uint16)); 3863 mirror_dest->etag_dst_vid = soc_ntohs(mirror_dest->etag_dst_vid); 3864 p_profile_header+=sizeof(uint16); 3865 3866 /* ETAG Extension (2 bytes). */ 3867 p_profile_header+=sizeof(uint16); 3868 } 3869 /* for OTAG */ 3870 if ((edit_ctrl_id == MIRROR_EDIT_CTRL_ID_SFLOW_INGRESS_MIRROR) || 3871 (edit_ctrl_id == MIRROR_EDIT_CTRL_ID_SFLOW_VNTAG_OTAG) || 3872 (edit_ctrl_id == MIRROR_EDIT_CTRL_ID_SFLOW_ETAG_OTAG) || 3873 (edit_ctrl_id == MIRROR_EDIT_CTRL_ID_VXLAN) || 3874 (edit_ctrl_id == MIRROR_EDIT_CTRL_ID_VXLAN_IPV6) || 3875 (edit_ctrl_id == MIRROR_EDIT_CTRL_ID_PSAMP_IPV6) || 3876 (edit_ctrl_id == MIRROR_EDIT_CTRL_ID_PSAMP_UNTAG) || 3877 (edit_ctrl_id == MIRROR_EDIT_CTRL_ID_PSAMP_TRUNCATE) || 3878 (edit_ctrl_id == MIRROR_EDIT_CTRL_ID_PSAMP_VNTAG_OTAG) || 3879 (edit_ctrl_id == MIRROR_EDIT_CTRL_ID_PSAMP)) { 3880 sal_memcpy(&mirror_dest->tpid, p_profile_header, sizeof(uint16)); 3881 p_profile_header+=sizeof(uint16); 3882 mirror_dest->tpid = soc_ntohs(mirror_dest->tpid); 3883 sal_memcpy(&mirror_dest->vlan_id, p_profile_header, sizeof(uint16)); 3884 p_profile_header+=sizeof(uint16); 3885 mirror_dest->vlan_id = soc_ntohs(mirror_dest->vlan_id); 3886 } 3887 3888 if (_is_edit_ctrl_id_ipv6(edit_ctrl_id)) { 3889 /* Add Ether Type */ 3890 p_profile_header += 2; 3891 3892 /* Version and traffic Class upper nibble */ 3893 mirror_dest->version = *p_profile_header >> NIBBLE_SHIFT_OFFSET; 3894 p_profile_header += 1; 3895 3896 flow_label_upper = *p_profile_header & 0xF; 3897 p_profile_header += 1; 3898 3899 mirror_dest->flow_label = soc_ntohs(*(uint16 *)p_profile_header); 3900 mirror_dest->flow_label |= (flow_label_upper << 16); 3901 p_profile_header += 2; 3902 3903 /* payload length */ 3904 p_profile_header += 2; 3905 3906 /* next header */ 3907 p_profile_header += 1; 3908 3909 /* hop limit */ 3910 p_profile_header += 1; 3911 3912 sal_memcpy(mirror_dest->src6_addr, p_profile_header, 3913 sizeof(bcm_ip6_t)); 3914 p_profile_header+=sizeof(bcm_ip6_t); 3915 sal_memcpy(mirror_dest->dst6_addr, p_profile_header, 3916 sizeof(bcm_ip6_t)); 3917 p_profile_header+=sizeof(bcm_ip6_t); 3918 3919 } else { /* IPv4 */ 3920 3921 /* Account for Ether Type */ 3922 p_profile_header+=sizeof(uint16); 3923 3924 /* Extract IPV4 Information */ 3925 3926 /**************************************** 3927 | BYTE 0 | BYTE 1 | BYTE 2 | BYTE 3 | 3928 ----------------------------------------- 3929 |0123-4567|0123-4567|0123-4567|0123-4567| 3930 ----------------------------------------- 3931 |VERS|IHL |TOS |TOTAL LENGTH | 3932 ----------------------------------------- 3933 |IDENTIFICATION |FLG|FRAGMENT OFFSET| 3934 ----------------------------------------- 3935 |TTL |PROTOCOL |HEADER CHECKSUM | 3936 ----------------------------------------- 3937 |SOURCE IP ADDRESS | 3938 ----------------------------------------- 3939 |DEST IP ADDRESS | 3940 */ 3941 3942 mirror_dest->version = *p_profile_header >> NIBBLE_SHIFT_OFFSET; 3943 p_profile_header+=1; 3944 mirror_dest->tos = *p_profile_header; 3945 p_profile_header+=5; 3946 mirror_dest->df = ((*p_profile_header) & (1 << DF_FLAG_SHIFTER))? 1: 0; 3947 p_profile_header+=2; 3948 mirror_dest->ttl = *p_profile_header; 3949 p_profile_header+=sizeof(uint32); 3950 3951 mirror_dest->src_addr = soc_ntohl(*(uint32*)p_profile_header); 3952 p_profile_header+=sizeof(uint32); 3953 mirror_dest->dst_addr = soc_ntohl(*(uint32*)p_profile_header); 3954 p_profile_header+=sizeof(uint32); 3955 } 3956 3957 /* Extract UDP Information */ 3958 sal_memcpy(&mirror_dest->udp_src_port, p_profile_header,sizeof(uint16)); 3959 p_profile_header+=sizeof(uint16); 3960 sal_memcpy(&mirror_dest->udp_dst_port, p_profile_header,sizeof(uint16)); 3961 p_profile_header+=sizeof(uint16); 3962 3963 mirror_dest->udp_src_port = soc_ntohs(mirror_dest->udp_src_port); 3964 mirror_dest->udp_dst_port = soc_ntohs(mirror_dest->udp_dst_port); 3965 3966 if (_is_edit_ctrl_id_vntag(edit_ctrl_id)) { 3967 mirror_dest->flags |= BCM_MIRROR_DEST_TUNNEL_NIV; 3968 } else if (_is_edit_ctrl_id_vxlan(edit_ctrl_id)) { 3969 mirror_dest->flags2 |= BCM_MIRROR_DEST_FLAGS2_TUNNEL_VXLAN; 3970 } else if (_is_edit_ctrl_id_psamp(edit_ctrl_id)) { 3971 mirror_dest->flags |= BCM_MIRROR_DEST_TUNNEL_PSAMP; 3972 } else { 3973 mirror_dest->flags |= BCM_MIRROR_DEST_TUNNEL_SFLOW; 3974 } 3975 } else if (_is_edit_ctrl_id_erspan(edit_ctrl_id)) { 3976 3977 /* ERSPAN recovery MACDA,MACSA,OTAG,IPV4,GRE*/ 3978 3979 /* Extract MAC and VLAN Information - L2 stuff */ 3980 sal_memcpy(mirror_dest->dst_mac, p_profile_header, 6); 3981 p_profile_header+=6; 3982 sal_memcpy(mirror_dest->src_mac, p_profile_header, 6); 3983 p_profile_header+=6; 3984 3985 if (_is_edit_ctrl_id_erspan_tagged(edit_ctrl_id)) { 3986 sal_memcpy(&mirror_dest->tpid, p_profile_header, sizeof(uint16)); 3987 p_profile_header+=sizeof(uint16); 3988 mirror_dest->tpid = soc_ntohs(mirror_dest->tpid); 3989 sal_memcpy(&mirror_dest->vlan_id, p_profile_header, sizeof(uint16)); 3990 p_profile_header+=sizeof(uint16); 3991 mirror_dest->vlan_id = soc_ntohs(mirror_dest->vlan_id); 3992 } 3993 3994 if (_is_edit_ctrl_id_ipv6(edit_ctrl_id)) { 3995 /* Add Ether Type */ 3996 p_profile_header += 2; 3997 3998 /* Version and traffic Class upper nibble */ 3999 mirror_dest->version = *p_profile_header >> NIBBLE_SHIFT_OFFSET; 4000 p_profile_header += 1; 4001 4002 flow_label_upper = *p_profile_header & 0xF; 4003 p_profile_header += 1; 4004 4005 mirror_dest->flow_label = soc_ntohs(*(uint16 *)p_profile_header); 4006 mirror_dest->flow_label |= (flow_label_upper << 16); 4007 p_profile_header += 2; 4008 4009 /* payload length */ 4010 p_profile_header += 2; 4011 4012 /* next header */ 4013 p_profile_header += 1; 4014 4015 /* hop limit */ 4016 p_profile_header += 1; 4017 4018 sal_memcpy(mirror_dest->src6_addr, p_profile_header, 4019 sizeof(bcm_ip6_t)); 4020 p_profile_header+=sizeof(bcm_ip6_t); 4021 sal_memcpy(mirror_dest->dst6_addr, p_profile_header, 4022 sizeof(bcm_ip6_t)); 4023 p_profile_header+=sizeof(bcm_ip6_t); 4024 4025 } else { /* IPv4 */ 4026 /* Account for Ether Type */ 4027 p_profile_header+=sizeof(uint16); 4028 4029 /* Extract IPV4 Information */ 4030 mirror_dest->version = *p_profile_header >> NIBBLE_SHIFT_OFFSET; 4031 p_profile_header+=1; 4032 mirror_dest->tos = *p_profile_header; 4033 p_profile_header+=5; 4034 mirror_dest->df = ((*p_profile_header) & (1 << DF_FLAG_SHIFTER))? 1: 0; 4035 p_profile_header+=2; 4036 mirror_dest->ttl = *p_profile_header; 4037 p_profile_header+=sizeof(uint32); 4038 4039 mirror_dest->src_addr = soc_ntohl(*(uint32*)p_profile_header); 4040 p_profile_header+=sizeof(uint32); 4041 mirror_dest->dst_addr = soc_ntohl(*(uint32*)p_profile_header); 4042 p_profile_header+=sizeof(uint32); 4043 } 4044 4045 /* Extract GRE Protocol */ 4046 p_profile_header+=sizeof(uint16); 4047 sal_memcpy(&mirror_dest->gre_protocol, p_profile_header,sizeof(uint16)); 4048 mirror_dest->gre_protocol = soc_ntohs(mirror_dest->gre_protocol); 4049 4050 mirror_dest->flags |= BCM_MIRROR_DEST_TUNNEL_IP_GRE; 4051 if (_is_edit_ctrl_id_erspan_seq(edit_ctrl_id)) { 4052 mirror_dest->flags |= BCM_MIRROR_DEST_TUNNEL_WITH_SEQ; 4053 } 4054 } else if (_is_edit_ctrl_id_rspan(edit_ctrl_id)) { 4055 /* for VNTAG */ 4056 if (_is_edit_ctrl_id_vntag(edit_ctrl_id)) { 4057 p_profile_header+=sizeof(uint16); /* VNTAG ether type 2 bytes*/ 4058 4059 mirror_dest->niv_dst_vif = 4060 *(uint16*)p_profile_header & _BCM_TD_MIRROR_NIV_DST_VIF_MASK; 4061 p_profile_header+=sizeof(uint16); 4062 mirror_dest->niv_dst_vif = soc_ntohs(mirror_dest->niv_dst_vif); 4063 4064 mirror_dest->niv_src_vif = 4065 *(uint16*)p_profile_header & _BCM_TD_MIRROR_NIV_SRC_VIF_MASK; 4066 p_profile_header+=sizeof(uint16); 4067 mirror_dest->niv_src_vif = soc_ntohs(mirror_dest->niv_src_vif); 4068 4069 mirror_dest->niv_flags = (mirror_dest->niv_src_vif & 4070 soc_ntohs(_BCM_TD_MIRROR_NIV_LOOP_BIT)) ? 4071 BCM_MIRROR_NIV_LOOP : 0; 4072 } 4073 /* RSPAN recovery */ 4074 mirror_dest->tpid = soc_ntohs(*(uint16*)p_profile_header); 4075 p_profile_header+=sizeof(uint16); 4076 mirror_dest->vlan_id = soc_ntohs(*(uint16*)p_profile_header); 4077 4078 mirror_dest->flags |= BCM_MIRROR_DEST_TUNNEL_L2; 4079 } else if (edit_ctrl_id == MIRROR_EDIT_CTRL_ID_INGRESS_MIRROR_HG_TAG) { 4080 4081 /* VERIFY THIS CODE -- if this is the correct way to extract etag */ 4082 /* ETAG recovery */ 4083 mirror_dest->etag_src_vid = soc_ntohs(*(uint16*)p_profile_header); 4084 p_profile_header+=sizeof(uint16); 4085 mirror_dest->etag_dst_vid = soc_ntohs(*(uint16*)p_profile_header); 4086 4087 mirror_dest->flags |= BCM_MIRROR_DEST_TUNNEL_ETAG; 4088 } 4089 4090 return BCM_E_NONE; 4091 } 4092 4093 /* 4094 * Function: 4095 * _bcm_td3_mirror_tunnel_reload 4096 * Purpose: 4097 * Restores mirroring tunnel destination encap info 4098 * for warm boot recovery 4099 * Parameters: 4100 * unit - (IN) BCM device number. 4101 * dest_id - (IN) Mirror destination description. 4102 * profile_index - (IN) Encap profile index 4103 * Returns: 4104 * BCM_E_XXX 4105 */ 4106 int 4107 _bcm_td3_mirror_tunnel_reload(int unit, bcm_gport_t dest_id, 4108 uint32 profile_index) 4109 { 4110 int edit_ctrl_id; 4111 void *entries[EGR_MIRROR_TABLE_ENTRIES_NUM]; 4112 uint8 *p_profile_1_header = NULL; 4113 uint8 *p_profile_2_header = NULL; 4114 int encap_profile_offset = 0; 4115 uint32 opaque32 = 0; 4116 uint16 opaque16 = 0; 4117 int granularity = 0, seq_num_profile_idx = 0; 4118 4119 bcm_mirror_destination_t *mirror_dest; 4120 egr_mirror_table_entry_t table_entry; 4121 4122 flex_editor_mirror_encap_0_profile_1_table_entry_t profile_1; 4123 flex_editor_mirror_encap_0_profile_2_table_entry_t profile_2; 4124 flex_editor_mirror_encap_0_profile_3_table_entry_t profile_3; 4125 4126 sal_memset(&table_entry, 0, sizeof(table_entry)); 4127 sal_memset(&profile_1, 0, sizeof(profile_1)); 4128 sal_memset(&profile_2, 0, sizeof(profile_2)); 4129 sal_memset(&profile_3, 0, sizeof(profile_3)); 4130 4131 entries[EGR_MIRROR_TABLE_ENTRIES] = &table_entry; 4132 4133 p_profile_1_header = (uint8 *) &profile_1; 4134 p_profile_2_header = (uint8 *) &profile_2; 4135 4136 /* Tunnel type? */ 4137 BCM_IF_ERROR_RETURN 4138 (soc_profile_mem_get(unit, EGR_MIRROR_TABLE(unit), profile_index, 4139 1, entries)); 4140 4141 mirror_dest = MIRROR_DEST(unit, dest_id); 4142 4143 /* get the truncation flag */ 4144 if (soc_EGR_MIRROR_TABLEm_field32_get (unit, &table_entry, TRUNCATE_ENf)) { 4145 mirror_dest->truncate = 1; 4146 } 4147 4148 /* get mirror edit ctrl id */ 4149 edit_ctrl_id = soc_EGR_MIRROR_TABLEm_field32_get (unit, &table_entry, 4150 MIRROR_EDIT_CTRL_IDf); 4151 4152 encap_profile_offset = soc_EGR_MIRROR_TABLEm_field32_get (unit, 4153 &table_entry, MIRROR_ENGINE_PROFILE_OFFSETf); 4154 4155 BCM_IF_ERROR_RETURN 4156 (soc_mem_read(unit, 4157 FLEX_EDITOR_MIRROR_ENCAP_0_PROFILE_1_TABLEm, 4158 MEM_BLOCK_ANY, encap_profile_offset + 1, &profile_1)); 4159 BCM_IF_ERROR_RETURN 4160 (soc_mem_read(unit, 4161 FLEX_EDITOR_MIRROR_ENCAP_0_PROFILE_2_TABLEm, 4162 MEM_BLOCK_ANY, encap_profile_offset + 1, &profile_2)); 4163 BCM_IF_ERROR_RETURN 4164 (soc_mem_read(unit, 4165 FLEX_EDITOR_MIRROR_ENCAP_0_PROFILE_3_TABLEm, 4166 MEM_BLOCK_ANY, encap_profile_offset + 1, &profile_3)); 4167 4168 BCM_IF_ERROR_RETURN(_bcm_td3_mirror_flex_editor_header_decode(unit, 4169 edit_ctrl_id, mirror_dest, p_profile_1_header, p_profile_2_header)); 4170 4171 /* Extract the ERSPAN3 specific info and populate in SW */ 4172 4173 if (SOC_IS_HELIX5(unit)) { 4174 4175 /* Get the MIRROR_ENCAP_DATA_2f and related data */ 4176 opaque16 = soc_EGR_MIRROR_TABLEm_field32_get (unit, &table_entry, 4177 MIRROR_ENCAP_DATA_2f); 4178 4179 mirror_dest->erspan_header.truncated_flag = ((opaque16 >> 9) & 1); 4180 /* Get the 9 bits of session-id starting from MSB */ 4181 mirror_dest->erspan_header.session_id = ((opaque16 & 0x1FF) << 1); 4182 4183 /* Get the MIRROR_ENCAP_DATA_1f and related data */ 4184 opaque16 = soc_EGR_MIRROR_TABLEm_field32_get (unit, &table_entry, 4185 MIRROR_ENCAP_DATA_1f); 4186 4187 /* Get the 1st bit of session-id, stored in 16th bit of 4188 MIRROR_ENCAP_DATA_1f */ 4189 mirror_dest->erspan_header.session_id |= ((opaque16 >> 15) & 1); 4190 4191 mirror_dest->erspan_header.hw_id = ((opaque16 >> 3) & 0x3F); 4192 4193 granularity = ((opaque16) & 0x3); 4194 if (granularity == 0x2) { 4195 mirror_dest->erspan_header.timestamp_granularity = 0x1; 4196 } else { 4197 mirror_dest->erspan_header.timestamp_granularity = 0x0; 4198 } 4199 4200 /* Get the MIRROR_ENCAP_DATA_1f and related data */ 4201 opaque16 = soc_EGR_MIRROR_TABLEm_field32_get (unit, &table_entry, 4202 MIRROR_ENCAP_DATA_0f); 4203 4204 mirror_dest->erspan_header.switch_id = ((opaque16 >> 7) & 0x3FF); 4205 mirror_dest->erspan_header.platform_id = ((opaque16 >> 1) & 0x2F); 4206 mirror_dest->erspan_header.optional_hdr = (opaque16 & 0x1); 4207 } else { 4208 4209 /* Get the MIRROR_ENCAP_DATA_1f and related data */ 4210 opaque32 = soc_EGR_MIRROR_TABLEm_field32_get (unit, &table_entry, 4211 MIRROR_ENCAP_DATA_1f); 4212 4213 mirror_dest->erspan_header.truncated_flag = ((opaque32 >> 25) & 1); 4214 mirror_dest->erspan_header.session_id = ((opaque32 >> 15) & 0x3FF); 4215 mirror_dest->erspan_header.hw_id = ((opaque32 >> 3) & 0x3F); 4216 4217 granularity = ((opaque32) & 0x3); 4218 if (granularity == 0x2) { 4219 mirror_dest->erspan_header.timestamp_granularity = 0x1; 4220 } else { 4221 mirror_dest->erspan_header.timestamp_granularity = 0x0; 4222 } 4223 4224 /* Get the MIRROR_ENCAP_DATA_0f and related data */ 4225 opaque16 = soc_EGR_MIRROR_TABLEm_field32_get (unit, &table_entry, 4226 MIRROR_ENCAP_DATA_0f); 4227 4228 mirror_dest->erspan_header.switch_id = ((opaque16 >> 7) & 0x3FF); 4229 mirror_dest->erspan_header.platform_id = ((opaque16 >> 1) & 0x1F); 4230 mirror_dest->erspan_header.optional_hdr = ((opaque16) & 0x1); 4231 } 4232 4233 edit_ctrl_id = soc_EGR_MIRROR_TABLEm_field32_get (unit, &table_entry, 4234 MIRROR_EDIT_CTRL_IDf); 4235 4236 /* Based on the edit ctrl id update the gre_protocol value */ 4237 if ((edit_ctrl_id == MIRROR_EDIT_CTRL_ID_ERSPAN3_INGRESS_MIRROR) || 4238 (edit_ctrl_id == MIRROR_EDIT_CTRL_ID_ERSPAN3_INGRESS_MIRROR_NO_SUBHDR)) { 4239 mirror_dest->gre_protocol = ERSPAN3_GRE_PROTOCOL_TYPE; 4240 } 4241 4242 /* Get the seq num profile index */ 4243 seq_num_profile_idx = soc_EGR_MIRROR_TABLEm_field32_get (unit, &table_entry, 4244 SEQ_NUM_PROFILE_INDEXf); 4245 4246 /* Update the ref count for EGR_SEQUENCE_NUMBER_PROFILEm */ 4247 SOC_PROFILE_MEM_REFERENCE(unit, EGR_SEQ_NUMBER_PROFILE(unit), 4248 seq_num_profile_idx, 1); 4249 4250 return BCM_E_NONE; 4251 } 4252 4253 void _bcm_td3_mirror_flags_update (int unit, int edit_ctrl_id, uint32 *flags, uint32 *flags2) 4254 { 4255 if (_is_edit_ctrl_id_vxlan(edit_ctrl_id)) { 4256 *flags2 |= BCM_MIRROR_DEST_FLAGS2_TUNNEL_VXLAN; 4257 } 4258 if (_is_edit_ctrl_id_psamp(edit_ctrl_id)) { 4259 *flags |= BCM_MIRROR_DEST_TUNNEL_PSAMP; 4260 } else if (_is_edit_ctrl_id_sflow(edit_ctrl_id)) { 4261 *flags |= BCM_MIRROR_DEST_TUNNEL_SFLOW; 4262 } else if (_is_edit_ctrl_id_vntag(edit_ctrl_id)) { 4263 *flags |= BCM_MIRROR_DEST_TUNNEL_NIV; 4264 } else if (_is_edit_ctrl_id_erspan(edit_ctrl_id)) { 4265 *flags |= BCM_MIRROR_DEST_TUNNEL_IP_GRE; 4266 if (_is_edit_ctrl_id_erspan_seq(edit_ctrl_id)) { 4267 *flags |= BCM_MIRROR_DEST_TUNNEL_WITH_SEQ; 4268 } 4269 } else { 4270 *flags |= BCM_MIRROR_DEST_TUNNEL_L2; 4271 } 4272 4273 if (edit_ctrl_id == MIRROR_EDIT_CTRL_ID_INGRESS_MIRROR_HG_TAG) { 4274 if(soc_feature(unit, soc_feature_port_extension)) { 4275 *flags |= BCM_MIRROR_DEST_TUNNEL_ETAG; 4276 } 4277 } 4278 } 4279 4280 STATIC int _bcm_td3_mirror_vxlt_ctrl_id_set (int unit, 4281 bcm_mirror_destination_t *mirror_dest, 4282 int cancun_ver, 4283 int action) /* TRUE: set, FALSE: clear */ 4284 { 4285 bcm_trunk_member_t active_member_array[BCM_SWITCH_TRUNK_MAX_PORTCNT]; 4286 int active_member_count = 0; 4287 int egr_gpp_index; 4288 int i; 4289 int rv; 4290 4291 /* set the vxlt_ctrl_id for the given mtp */ 4292 if (BCM_GPORT_IS_TRUNK(mirror_dest->gport)) { 4293 rv = _bcm_trunk_id_validate(unit, 4294 BCM_GPORT_TRUNK_GET(mirror_dest->gport)); 4295 if (BCM_FAILURE(rv)) { 4296 return (BCM_E_PORT); 4297 } 4298 4299 /* get only active trunk members and the count */ 4300 rv = _bcm_esw_trunk_active_member_get(unit, 4301 BCM_GPORT_TRUNK_GET(mirror_dest->gport), 4302 NULL, 4303 BCM_SWITCH_TRUNK_MAX_PORTCNT, 4304 active_member_array, 4305 &active_member_count); 4306 if (BCM_FAILURE(rv)) { 4307 return (BCM_E_PORT); 4308 } 4309 for (i = 0; i < active_member_count; i++) { 4310 if (SOC_IS_TRIDENT3(unit) && 4311 (SOC_CANCUN_VERSION_5_2_UNDER_SERIES(cancun_ver))) { 4312 if (soc_feature(unit, soc_feature_egr_lport_tab_profile)) { 4313 rv = bcm_esw_port_egr_lport_field_set(unit, 4314 active_member_array[i].gport, 4315 EGR_LPORT_PROFILEm, VXLT_CTRL_IDf, 4316 action? ERSPAN3_MIRROR_VXLT_CTRL_ID: 0); 4317 BCM_IF_ERROR_RETURN(rv); 4318 } 4319 } else { 4320 BCM_IF_ERROR_RETURN(_bcm_esw_src_mod_port_table_index_get( 4321 unit, 4322 BCM_GPORT_MODPORT_MODID_GET(active_member_array[i].gport), 4323 BCM_GPORT_MODPORT_PORT_GET(active_member_array[i].gport), 4324 &egr_gpp_index)); 4325 BCM_IF_ERROR_RETURN(soc_mem_field32_modify(unit, 4326 EGR_GPP_ATTRIBUTESm, egr_gpp_index, 4327 VXLT_CTRL_IDf, 4328 action? ERSPAN3_MIRROR_VXLT_CTRL_ID: 0)); 4329 } 4330 } 4331 } else { 4332 if (SOC_IS_TRIDENT3(unit) && 4333 (SOC_CANCUN_VERSION_5_2_UNDER_SERIES(cancun_ver))) { 4334 if (soc_feature(unit, soc_feature_egr_lport_tab_profile)) { 4335 rv = (bcm_esw_port_egr_lport_field_set(unit, 4336 mirror_dest->gport, 4337 EGR_LPORT_PROFILEm, VXLT_CTRL_IDf, 4338 action? ERSPAN3_MIRROR_VXLT_CTRL_ID: 0)); 4339 BCM_IF_ERROR_RETURN(rv); 4340 } 4341 } else { 4342 BCM_IF_ERROR_RETURN(_bcm_esw_src_mod_port_table_index_get( 4343 unit, 4344 BCM_GPORT_MODPORT_MODID_GET(mirror_dest->gport), 4345 BCM_GPORT_MODPORT_PORT_GET(mirror_dest->gport), 4346 &egr_gpp_index)); 4347 BCM_IF_ERROR_RETURN(soc_mem_field32_modify(unit, 4348 EGR_GPP_ATTRIBUTESm, egr_gpp_index, 4349 VXLT_CTRL_IDf, 4350 action? ERSPAN3_MIRROR_VXLT_CTRL_ID: 0)); 4351 } 4352 } 4353 return BCM_E_NONE; 4354 } 4355 4356 /* 4357 * Function: 4358 * _bcm_mirror_port_match_add 4359 * Purpose: 4360 * Internal function to add a match to Mirror destination ID. 4361 * Parameters: 4362 * unit - (IN) Device number. 4363 * mirror_dest - (IN) Mirror destination structure. 4364 * match_port - (IN) Ingress port 4365 * match_vlan - (IN) Payload vlan ID. 4366 * match_type - (IN) match criteria 4367 * Returns: 4368 * BCM_X_XXX 4369 */ 4370 int 4371 _bcm_mirror_port_match_add(int unit, bcm_mirror_destination_t *mirror_dest, 4372 bcm_gport_t match_port, bcm_vlan_t match_vlan, 4373 bcm_port_match_t match_type) 4374 { 4375 4376 soc_mem_t evx_mem = EGR_VLAN_XLATE_1_DOUBLEm; 4377 uint32 vent[SOC_MAX_MEM_FIELD_WORDS]; 4378 bcm_port_t local_port; 4379 int rv; 4380 uint32 cancun_ver; 4381 4382 SOC_IF_ERROR_RETURN(soc_cancun_version_get(unit, &cancun_ver)); 4383 /* Programming GBP SID in EGR_VLAN_XLATE_1_DOUBLEm */ 4384 if (soc_mem_is_valid(unit, EGR_VLAN_XLATE_1_DOUBLEm)) { 4385 if (((mirror_dest->flags & BCM_MIRROR_DEST_TUNNEL_IP_GRE) && 4386 (mirror_dest->gre_protocol == ERSPAN3_GRE_PROTOCOL_TYPE)) || 4387 (mirror_dest->flags2 & BCM_MIRROR_DEST_FLAGS2_TUNNEL_VXLAN)) { 4388 BCM_IF_ERROR_RETURN(_bcm_esw_port_gport_validate(unit, match_port, 4389 &local_port)); 4390 sal_memset(vent, 0, sizeof(vent)); 4391 soc_mem_field32_set(unit, evx_mem, &vent, BASE_VALID_0f, 3); 4392 soc_mem_field32_set(unit, evx_mem, &vent, BASE_VALID_1f, 7); 4393 soc_mem_field32_set(unit, evx_mem, &vent, DATA_TYPEf, 4394 EGR_VXLT_HASH_ERPSAN3_DATA_TYPE); 4395 /* Key type is ERSPAN3_VXLT_CTRL_ID */ 4396 if (SOC_IS_TRIDENT3(unit) || SOC_IS_MAVERICK2(unit)) { 4397 soc_mem_field32_set(unit, evx_mem, &vent, KEY_TYPEf, 4398 TD3_EGR_VXLT_HASH_ERPSAN3_KEY_TYPE); 4399 } else { 4400 soc_mem_field32_set(unit, evx_mem, &vent, KEY_TYPEf, 4401 EGR_VXLT_HASH_ERPSAN3_KEY_TYPE); 4402 } 4403 soc_mem_field32_set(unit, evx_mem, &vent, 4404 ERSPAN3_VXLAN_MIRROR__INGRESS_PORTf, 4405 local_port); 4406 if (SOC_IS_TRIDENT3(unit) && 4407 (SOC_CANCUN_VERSION_5_2_UNDER_SERIES(cancun_ver))) { 4408 soc_mem_field32_set(unit, evx_mem, &vent, 4409 ERSPAN3_VXLAN_MIRROR__ZONE_3_FWD_DOMAIN_TYPEf, 0x1); 4410 soc_mem_field32_set(unit, evx_mem, &vent, 4411 ERSPAN3_VXLAN_MIRROR__VLANf, match_vlan); 4412 soc_mem_field32_set(unit, evx_mem, &vent, 4413 ERSPAN3_VXLAN_MIRROR__MIRROR_ENABLEf, 0x1); 4414 soc_mem_field32_set(unit, evx_mem, &vent, 4415 ERSPAN3_VXLAN_MIRROR__GBPf, 4416 mirror_dest->erspan_header.gbp_sid); 4417 } else { 4418 if (match_type == BCM_PORT_MATCH_PORT_I2E_CLASS) { 4419 soc_mem_field32_set(unit, evx_mem, &vent, 4420 ERSPAN3_VXLAN_MIRROR__I2E_CLASS_ID_TYPEf, 4421 I2E_CLASS_ID_VLAN_TYPE); 4422 } else { /* BCM_PORT_MATCH_PORT_I2E_CLASS_IFP_TYPE */ 4423 soc_mem_field32_set(unit, evx_mem, &vent, 4424 ERSPAN3_VXLAN_MIRROR__I2E_CLASS_ID_TYPEf, 4425 I2E_CLASS_ID_IFP_TYPE); 4426 } 4427 soc_mem_field32_set(unit, evx_mem, &vent, 4428 ERSPAN3_VXLAN_MIRROR__I2E_CLASS_IDf, 4429 match_vlan); 4430 soc_mem_field32_set(unit, evx_mem, &vent, 4431 ERSPAN3_VXLAN_MIRROR__MIRRORf, 0x1); 4432 soc_mem_field32_set(unit, evx_mem, &vent, 4433 ERSPAN3_VXLAN_MIRROR__GBP_SIDf, 4434 mirror_dest->erspan_header.gbp_sid); 4435 soc_mem_field32_set(unit, evx_mem, &vent, 4436 ERSPAN3_VXLAN_MIRROR__VNIDf, 4437 mirror_dest->vni); 4438 } 4439 rv = soc_mem_insert(unit, evx_mem, MEM_BLOCK_ALL, 4440 &vent); 4441 if (SOC_FAILURE(rv) && (rv != SOC_E_EXISTS)) { 4442 return rv; 4443 } 4444 } else { 4445 return BCM_E_PARAM; 4446 } 4447 BCM_IF_ERROR_RETURN(_bcm_td3_mirror_vxlt_ctrl_id_set (unit, 4448 mirror_dest, cancun_ver, TRUE)); 4449 } 4450 4451 return BCM_E_NONE; 4452 } 4453 4454 /* 4455 * Function: 4456 * _bcm_mirror_port_match_delete 4457 * Purpose: 4458 * Internal function to delete a match added to Mirror destination ID. 4459 * Parameters: 4460 * unit - (IN) Device number. 4461 * mirror_dest - (IN) Mirror destination structure. 4462 * match_port - (IN) Ingress port 4463 * match_vlan - (IN) Payload vlan ID. 4464 * match_type - (IN) match criteria 4465 * Returns: 4466 * BCM_X_XXX 4467 */ 4468 int 4469 _bcm_mirror_port_match_delete(int unit, bcm_mirror_destination_t *mirror_dest, 4470 bcm_gport_t match_port, bcm_vlan_t match_vlan, 4471 bcm_port_match_t match_type) 4472 { 4473 4474 soc_mem_t evx_mem = EGR_VLAN_XLATE_1_DOUBLEm; 4475 uint32 vent[SOC_MAX_MEM_FIELD_WORDS]; 4476 bcm_port_t local_port; 4477 uint32 cancun_ver; 4478 4479 SOC_IF_ERROR_RETURN(soc_cancun_version_get(unit, &cancun_ver)); 4480 4481 /* Programming GBP SID in EGR_VLAN_XLATE_1_DOUBLEm */ 4482 if (soc_mem_is_valid(unit, EGR_VLAN_XLATE_1_DOUBLEm)) { 4483 if (((mirror_dest->flags & BCM_MIRROR_DEST_TUNNEL_IP_GRE) && 4484 (mirror_dest->gre_protocol == ERSPAN3_GRE_PROTOCOL_TYPE)) || 4485 (mirror_dest->flags2 & BCM_MIRROR_DEST_FLAGS2_TUNNEL_VXLAN)) { 4486 BCM_IF_ERROR_RETURN(_bcm_esw_port_gport_validate(unit, match_port, 4487 &local_port)); 4488 sal_memset(vent, 0, sizeof(vent)); 4489 soc_mem_field32_set(unit, evx_mem, &vent, BASE_VALID_0f, 3); 4490 soc_mem_field32_set(unit, evx_mem, &vent, BASE_VALID_1f, 7); 4491 soc_mem_field32_set(unit, evx_mem, &vent, DATA_TYPEf, 4492 EGR_VXLT_HASH_ERPSAN3_DATA_TYPE); 4493 /* Key type is ERSPAN3_VXLT_CTRL_ID */ 4494 if (SOC_IS_TRIDENT3(unit) || SOC_IS_MAVERICK2(unit)) { 4495 soc_mem_field32_set(unit, evx_mem, &vent, KEY_TYPEf, 4496 TD3_EGR_VXLT_HASH_ERPSAN3_KEY_TYPE); 4497 } else { 4498 soc_mem_field32_set(unit, evx_mem, &vent, KEY_TYPEf, 4499 EGR_VXLT_HASH_ERPSAN3_KEY_TYPE); 4500 } 4501 soc_mem_field32_set(unit, evx_mem, &vent, 4502 ERSPAN3_VXLAN_MIRROR__INGRESS_PORTf, 4503 local_port); 4504 4505 if (SOC_IS_TRIDENT3(unit) && 4506 (SOC_CANCUN_VERSION_5_2_UNDER_SERIES(cancun_ver))) { 4507 soc_mem_field32_set(unit, evx_mem, &vent, 4508 ERSPAN3_VXLAN_MIRROR__ZONE_3_FWD_DOMAIN_TYPEf, 0x1); 4509 soc_mem_field32_set(unit, evx_mem, &vent, 4510 ERSPAN3_VXLAN_MIRROR__VLANf, match_vlan); 4511 soc_mem_field32_set(unit, evx_mem, &vent, 4512 ERSPAN3_VXLAN_MIRROR__MIRROR_ENABLEf, 0x1); 4513 } else { 4514 if (match_type == BCM_PORT_MATCH_PORT_I2E_CLASS) { 4515 soc_mem_field32_set(unit, evx_mem, &vent, 4516 ERSPAN3_VXLAN_MIRROR__I2E_CLASS_ID_TYPEf, 4517 I2E_CLASS_ID_VLAN_TYPE); 4518 } else { /* BCM_PORT_MATCH_PORT_I2E_CLASS_IFP_TYPE */ 4519 soc_mem_field32_set(unit, evx_mem, &vent, 4520 ERSPAN3_VXLAN_MIRROR__I2E_CLASS_ID_TYPEf, 4521 I2E_CLASS_ID_IFP_TYPE); 4522 } 4523 soc_mem_field32_set(unit, evx_mem, &vent, 4524 ERSPAN3_VXLAN_MIRROR__I2E_CLASS_IDf, 4525 match_vlan); 4526 soc_mem_field32_set(unit, evx_mem, &vent, 4527 ERSPAN3_VXLAN_MIRROR__MIRRORf, 0x1); 4528 } 4529 SOC_IF_ERROR_RETURN(soc_mem_delete(unit, evx_mem, MEM_BLOCK_ALL, 4530 &vent)); 4531 } else { 4532 return BCM_E_PARAM; 4533 } 4534 4535 /* clear the vxlt_ctrl_id for the given mtp */ 4536 BCM_IF_ERROR_RETURN(_bcm_td3_mirror_vxlt_ctrl_id_set (unit, 4537 mirror_dest, cancun_ver, FALSE)); 4538 } 4539 4540 return BCM_E_NONE; 4541 } 4542 4543 /* 4544 * Function: 4545 * _bcm_mirror_port_match_multi_get 4546 * Purpose: 4547 * Get all the matches for an existing mirror destination id. 4548 * Parameters: 4549 * unit - (IN) Device number. 4550 * gport - (IN) Mirror destination gport. 4551 * size - (IN) Number of elements in match array 4552 * match_array - (OUT) Match array 4553 * count - (OUT) Match count 4554 * Returns: 4555 * BCM_E_xxx 4556 */ 4557 int 4558 _bcm_mirror_port_match_multi_get(int unit, bcm_gport_t gport, int size, 4559 bcm_port_match_info_t *match_array, 4560 int *count) 4561 { 4562 int rv = BCM_E_NONE; 4563 uint8 *egr_vt_buf = NULL; 4564 int index, index_min, index_max; 4565 void *vent = NULL; 4566 bcm_gport_t match_gport = 0; 4567 int key_type_value; 4568 int cnt = 0; 4569 bcm_port_t port_in; 4570 soc_mem_t egr_vx_mem = EGR_VLAN_XLATE_1_DOUBLEm; 4571 bcm_mirror_destination_t mirror_dest; 4572 uint16 gbp_sid; 4573 uint32 cancun_ver; 4574 uint32 vni; 4575 int match_type; 4576 4577 SOC_IF_ERROR_RETURN(soc_cancun_version_get(unit, &cancun_ver)); 4578 bcm_mirror_destination_t_init(&mirror_dest); 4579 BCM_IF_ERROR_RETURN(bcm_esw_mirror_destination_get(unit, gport, 4580 &mirror_dest)); 4581 egr_vt_buf = soc_cm_salloc(unit, SOC_MEM_TABLE_BYTES(unit, egr_vx_mem), 4582 "EGR_VLAN_XLATE buffer"); 4583 4584 if (NULL == egr_vt_buf) { 4585 return BCM_E_MEMORY; 4586 } 4587 4588 index_min = soc_mem_index_min(unit, egr_vx_mem); 4589 index_max = soc_mem_index_max(unit, egr_vx_mem); 4590 4591 soc_mem_lock(unit, egr_vx_mem); 4592 if ((rv = soc_mem_read_range(unit, egr_vx_mem, MEM_BLOCK_ANY, 4593 index_min, index_max, egr_vt_buf)) < 0) { 4594 goto cleanup; 4595 } 4596 4597 for (index = index_min; index <= index_max; index++) { 4598 if ((size != 0) && (size <= cnt)) { 4599 break; 4600 } 4601 vent = soc_mem_table_idx_to_pointer(unit, egr_vx_mem, 4602 void *, 4603 egr_vt_buf, index); 4604 if (soc_mem_field32_get(unit, egr_vx_mem, vent, BASE_VALID_0f) != 3 || 4605 soc_mem_field32_get(unit, egr_vx_mem, vent, BASE_VALID_1f) != 7) { 4606 continue; 4607 } 4608 if (SOC_IS_TRIDENT3(unit) && 4609 (SOC_CANCUN_VERSION_5_2_UNDER_SERIES(cancun_ver))) { 4610 gbp_sid = soc_mem_field32_get(unit, egr_vx_mem, vent, 4611 ERSPAN3_VXLAN_MIRROR__GBPf); 4612 vni = 0xFFFFFFFF; 4613 } else { 4614 gbp_sid = soc_mem_field32_get(unit, egr_vx_mem, vent, 4615 ERSPAN3_VXLAN_MIRROR__GBP_SIDf); 4616 vni = soc_mem_field32_get(unit, egr_vx_mem, vent, 4617 ERSPAN3_VXLAN_MIRROR__VNIDf); 4618 } 4619 if ((gbp_sid != mirror_dest.erspan_header.gbp_sid) && 4620 (vni != mirror_dest.vni)) { 4621 continue; 4622 } 4623 4624 if ((size > 0) && (size > cnt)) { 4625 key_type_value = (int)soc_mem_field32_get(unit, egr_vx_mem, vent, 4626 KEY_TYPEf); 4627 sal_memset(match_array, 0, sizeof(bcm_port_match_info_t)); 4628 switch (key_type_value) { 4629 case TD3_EGR_VXLT_HASH_ERPSAN3_KEY_TYPE: 4630 case EGR_VXLT_HASH_ERPSAN3_KEY_TYPE: 4631 if (SOC_IS_TRIDENT3(unit) && 4632 (SOC_CANCUN_VERSION_5_2_UNDER_SERIES(cancun_ver))) { 4633 match_array->match = BCM_PORT_MATCH_PORT_VLAN; 4634 match_array->match_vlan = 4635 soc_mem_field32_get(unit, egr_vx_mem, vent, 4636 ERSPAN3_VXLAN_MIRROR__VLANf); 4637 } else { 4638 match_type = soc_mem_field32_get(unit, egr_vx_mem, vent, 4639 ERSPAN3_VXLAN_MIRROR__I2E_CLASS_ID_TYPEf); 4640 if (match_type == I2E_CLASS_ID_VLAN_TYPE) { 4641 match_array->match = BCM_PORT_MATCH_PORT_I2E_CLASS; 4642 } else { 4643 match_array->match = 4644 BCM_PORT_MATCH_PORT_I2E_CLASS_IFP_TYPE; 4645 } 4646 match_array->match_vlan = 4647 soc_mem_field32_get(unit, egr_vx_mem, vent, 4648 ERSPAN3_VXLAN_MIRROR__I2E_CLASS_IDf); 4649 } 4650 port_in = soc_mem_field32_get(unit, egr_vx_mem, vent, 4651 ERSPAN3_VXLAN_MIRROR__INGRESS_PORTf); 4652 rv = bcm_esw_port_gport_get(unit, port_in, 4653 &match_gport); 4654 if (BCM_FAILURE(rv)) { 4655 goto cleanup; 4656 } 4657 match_array->port = match_gport; 4658 match_array++; 4659 break; 4660 default: 4661 rv = BCM_E_PARAM; 4662 goto cleanup; 4663 } 4664 } 4665 cnt++; 4666 } 4667 4668 *count = cnt; 4669 cleanup: 4670 if (egr_vt_buf) { 4671 soc_cm_sfree(unit, egr_vt_buf); 4672 } 4673 soc_mem_unlock(unit, egr_vx_mem); 4674 return rv; 4675 } 4676 #endif /* BCM_TRIDENT3_SUPPORT */ 4677 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_GREYHOUND_SUPPORT) 4678 /* 4679 * Function: 4680 * _bcm_egr_mirror_encap_entry_add 4681 * Purpose: 4682 * Internal function for adding an entry to the EGR_MIRROR_ENCAP_* tables 4683 * Adds an entry to the global shared SW copy of the EGR_MIRROR_ENCAP_* 4684 * tables 4685 * Parameters: 4686 * unit - (IN) Device number. 4687 * entries - (IN) Pointer to EGR_MIRROR_ENCAP_* entries array 4688 * index - (OUT) Base index for the entires allocated in HW 4689 * Returns: 4690 * BCM_X_XXX 4691 */ 4692 int 4693 _bcm_egr_mirror_encap_entry_add(int unit, void **entries, uint32 *index) 4694 { 4695 #if defined(BCM_TRIDENT3_SUPPORT) 4696 if (SOC_IS_TRIDENT3X(unit)) { 4697 return soc_profile_mem_add(unit, EGR_MIRROR_TABLE(unit), 4698 entries, 1, index); 4699 } else 4700 #endif /* BCM_TRIDENT3_SUPPORT */ 4701 { 4702 return soc_profile_mem_add(unit, EGR_MIRROR_ENCAP(unit), entries, 4703 1, index); 4704 } 4705 } 4706 4707 /* 4708 * Function: 4709 * _bcm_egr_mirror_encap_entry_delete 4710 * Purpose: 4711 * Internal function for deleting an entry from the EGR_MIRROR_ENCAP_* 4712 * tables 4713 * Deletes an entry from the global shared SW copy of the 4714 * EGR_MIRROR_ENCAP_* tables 4715 * Parameters: 4716 * unit - (IN) Device number. 4717 * index - (OUT) Base index for the entires allocated in HW 4718 * Returns: 4719 * BCM_X_XXX 4720 */ 4721 int 4722 _bcm_egr_mirror_encap_entry_delete(int unit, uint32 index) 4723 { 4724 #if defined(BCM_TRIDENT3_SUPPORT) 4725 if (SOC_IS_TRIDENT3X(unit)) { 4726 return soc_profile_mem_delete(unit, EGR_MIRROR_TABLE(unit), index); 4727 } else 4728 #endif /* BCM_TRIDENT3_SUPPORT */ 4729 { 4730 return soc_profile_mem_delete(unit, EGR_MIRROR_ENCAP(unit), index); 4731 } 4732 } 4733 4734 /* 4735 * Function: 4736 * _bcm_egr_mirror_encap_entry_reference 4737 * Purpose: 4738 * Internal function for indicating that an entry in EGR_MIRROR_ENCAP_* 4739 * tables is being used. Updates the global shared SW copy. 4740 * Parameters: 4741 * unit - (IN) Device number 4742 * index - (IN) Base index for the entry to be updated 4743 * Returns: 4744 * BCM_X_XXX 4745 */ 4746 int 4747 _bcm_egr_mirror_encap_entry_reference(int unit, uint32 index) 4748 { 4749 #if defined(BCM_TRIDENT3_SUPPORT) 4750 if (SOC_IS_TRIDENT3X(unit)) { 4751 return soc_profile_mem_reference(unit, EGR_MIRROR_TABLE(unit), 4752 (int) index, 1); 4753 } else 4754 #endif /* BCM_TRIDENT3_SUPPORT */ 4755 { 4756 return soc_profile_mem_reference(unit, EGR_MIRROR_ENCAP(unit), 4757 (int) index, 1); 4758 } 4759 } 4760 4761 /* 4762 * Function: 4763 * _bcm_egr_mirror_encap_entry_ref_get 4764 * Purpose: 4765 * Get the reference count of the mirror encap entry at the specified index. 4766 * Parameters: 4767 * unit - (IN) Device number 4768 * index - (IN) Base index for the entry to get 4769 * ref_count - (OUT) Reference count 4770 * Returns: 4771 * BCM_X_XXX 4772 */ 4773 int 4774 _bcm_egr_mirror_encap_entry_ref_get(int unit, uint32 index, 4775 int *ref_count) 4776 { 4777 #if defined(BCM_TRIDENT3_SUPPORT) 4778 if (SOC_IS_TRIDENT3X(unit)) { 4779 return soc_profile_mem_ref_count_get(unit, EGR_MIRROR_TABLE(unit), 4780 (int) index, ref_count); 4781 } else 4782 #endif /* BCM_TRIDENT3_SUPPORT */ 4783 { 4784 return soc_profile_mem_ref_count_get(unit, EGR_MIRROR_ENCAP(unit), 4785 (int)index, ref_count); 4786 } 4787 } 4788 4789 /* 4790 * Function: 4791 * _bcm_egr_mirror_encap_entry_mtp_update 4792 * Purpose: 4793 * Internal function for recording updating the EGR_*_MTP_INDEX 4794 * tables when ERSPAN is activated. 4795 * Parameters: 4796 * unit - (IN) Device number 4797 * index - (IN) MTP index for the entries to be updated 4798 * profile_index - (IN) Encap profile index 4799 * flags - (IN) Mirror direction flags. 4800 * Returns: 4801 * BCM_X_XXX 4802 */ 4803 int 4804 _bcm_egr_mirror_encap_entry_mtp_update(int unit, int index, 4805 uint32 profile_index, int flags) 4806 { 4807 int offset; 4808 int idx; 4809 int refs = 0; 4810 int max_num_trunk_ports = 0; 4811 4812 refs = 0; 4813 #ifdef BCM_METROLITE_SUPPORT 4814 if (soc_feature(unit, soc_feature_mirror_four_port_trunk)) { 4815 max_num_trunk_ports = 4; 4816 } else 4817 #endif 4818 max_num_trunk_ports = BCM_SWITCH_TRUNK_MAX_PORTCNT; 4819 4820 #ifdef BCM_TOMAHAWK3_SUPPORT 4821 if (SOC_IS_TOMAHAWK3(unit)) { 4822 max_num_trunk_ports = 1; 4823 /* We use offset = index below since EGR_IM/EM_MTP_INDEX are 4824 * 4 entries deep 4825 */ 4826 } 4827 #endif /* BCM_TOMAHAWK3_SUPPORT */ 4828 4829 offset = index * max_num_trunk_ports; 4830 4831 for (idx = 0; idx < max_num_trunk_ports; idx++, offset++) { 4832 if (flags & BCM_MIRROR_PORT_INGRESS) { 4833 BCM_IF_ERROR_RETURN 4834 (soc_mem_field32_modify(unit, EGR_IM_MTP_INDEXm, 4835 offset, MIRROR_ENCAP_INDEXf, 4836 profile_index)); 4837 if (0 == idx) { 4838 refs++; 4839 } 4840 } 4841 4842 if (flags & BCM_MIRROR_PORT_EGRESS) { 4843 #ifdef BCM_TOMAHAWK_SUPPORT 4844 if (SOC_INFO(unit).th_tflow_enabled == 1) { 4845 BCM_IF_ERROR_RETURN 4846 (soc_mem_field32_modify(unit, EGR_IM_MTP_INDEXm, 4847 offset, MIRROR_ENCAP_INDEXf, 4848 profile_index)); 4849 } else 4850 #endif /* BCM_TOMAHAWK_SUPPORT */ 4851 { 4852 BCM_IF_ERROR_RETURN 4853 (soc_mem_field32_modify(unit, EGR_EM_MTP_INDEXm, 4854 offset, MIRROR_ENCAP_INDEXf, 4855 profile_index)); 4856 } 4857 if (0 == idx) { 4858 refs++; 4859 } 4860 } 4861 4862 if (soc_feature(unit, soc_feature_egr_mirror_true) && 4863 (flags & BCM_MIRROR_PORT_EGRESS_TRUE)) { 4864 BCM_IF_ERROR_RETURN 4865 (soc_mem_field32_modify(unit, EGR_EP_REDIRECT_EM_MTP_INDEXm, 4866 offset, MIRROR_ENCAP_INDEXf, 4867 profile_index)); 4868 if (0 == idx) { 4869 refs++; 4870 } 4871 } 4872 } 4873 4874 if (refs > 1) { 4875 /* We should never have more than one mirror direction flag set. */ 4876 return BCM_E_INTERNAL; 4877 } 4878 4879 return (BCM_E_NONE); 4880 } 4881 4882 STATIC int 4883 _bcm_egr_mirror_encap_entry_mtp_enable(int unit, int index, 4884 bcm_gport_t *trunk_arr, int flags) 4885 { 4886 bcm_port_t port_out; 4887 bcm_module_t mod_out; 4888 _bcm_mtp_config_p mtp_cfg; 4889 int offset; 4890 int idx, id; 4891 bcm_trunk_t trunk = BCM_TRUNK_INVALID; 4892 bcm_module_t modid = 0; 4893 bcm_port_t port = -1; 4894 int max_num_trunk_ports = 0; 4895 4896 /* Input parameters check */ 4897 if (NULL == trunk_arr) { 4898 return (BCM_E_PARAM); 4899 } 4900 4901 /* Get mtp configuration structure by direction & index. */ 4902 mtp_cfg = MIRROR_CONFIG_MTP(unit, index, flags); 4903 4904 #ifdef BCM_METROLITE_SUPPORT 4905 if (soc_feature(unit, soc_feature_mirror_four_port_trunk)) { 4906 max_num_trunk_ports = 4; 4907 } else 4908 #endif 4909 max_num_trunk_ports = BCM_SWITCH_TRUNK_MAX_PORTCNT; 4910 4911 #ifdef BCM_TOMAHAWK3_SUPPORT 4912 if (SOC_IS_TOMAHAWK3(unit)) { 4913 max_num_trunk_ports = 1; 4914 /* We use offset = index below since EGR_IM/EM_MTP_INDEX are 4915 * 4 entries deep 4916 */ 4917 } 4918 #endif /* BCM_TOMAHAWK3_SUPPORT */ 4919 4920 offset = index * max_num_trunk_ports; 4921 4922 for (idx = 0; idx < max_num_trunk_ports; idx++, offset++) { 4923 4924 BCM_IF_ERROR_RETURN(_bcm_esw_gport_resolve( 4925 unit, trunk_arr[idx],&modid,&port,&trunk, &id)); 4926 BCM_IF_ERROR_RETURN 4927 (_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_SET, modid, port, 4928 &mod_out, &port_out)); 4929 4930 /* HW write. based on mirrored traffic direction. */ 4931 if (flags & BCM_MIRROR_PORT_INGRESS) { 4932 if (MIRROR_DEST_IS_TUNNEL(unit, mtp_cfg->dest_id)) { 4933 if ((MIRROR_DEST(unit, mtp_cfg->dest_id))->flags2 & 4934 BCM_MIRROR_DEST_FLAGS2_IFA) { 4935 BCM_IF_ERROR_RETURN 4936 (soc_mem_field32_modify(unit, EGR_EM_MTP_INDEXm, offset, 4937 MIRROR_ENCAP_ENABLEf, 1)); 4938 } else { 4939 BCM_IF_ERROR_RETURN 4940 (soc_mem_field32_modify(unit, EGR_IM_MTP_INDEXm, offset, 4941 MIRROR_ENCAP_ENABLEf, 1)); 4942 } 4943 } 4944 } 4945 /* EGR_EM_MTP_INDEX has same layout as EGR_IM_MTP_INDEX */ 4946 if (flags & BCM_MIRROR_PORT_EGRESS) { 4947 #ifdef BCM_TOMAHAWK_SUPPORT 4948 if (SOC_INFO(unit).th_tflow_enabled == 1) { 4949 /* Enable encap only for sFlow tunnel header on LB port */ 4950 if (BCM_PBMP_MEMBER(PBMP_LB(unit), port) || 4951 (MIRROR_DEST_IS_TUNNEL(unit, mtp_cfg->dest_id))) { 4952 BCM_IF_ERROR_RETURN 4953 (soc_mem_field32_modify(unit, EGR_IM_MTP_INDEXm, offset, 4954 MIRROR_ENCAP_ENABLEf, 1)); 4955 } 4956 4957 } else 4958 #endif /* BCM_TOMAHAWK_SUPPORT */ 4959 { 4960 if (MIRROR_DEST_IS_TUNNEL(unit, mtp_cfg->dest_id)) { 4961 BCM_IF_ERROR_RETURN 4962 (soc_mem_field32_modify(unit, EGR_EM_MTP_INDEXm, offset, 4963 MIRROR_ENCAP_ENABLEf, 1)); 4964 } 4965 } 4966 } 4967 4968 /* EGR_EP_REDIRECT_EM_MTP_INDEX has same layout as 4969 * EGR_IM_MTP_INDEX */ 4970 if (soc_feature(unit, soc_feature_egr_mirror_true) && 4971 (flags & BCM_MIRROR_PORT_EGRESS_TRUE)) { 4972 if (MIRROR_DEST_IS_TUNNEL(unit, mtp_cfg->dest_id)) { 4973 BCM_IF_ERROR_RETURN 4974 (soc_mem_field32_modify(unit, EGR_EP_REDIRECT_EM_MTP_INDEXm, 4975 offset, MIRROR_ENCAP_ENABLEf, 1)); 4976 } 4977 } 4978 } 4979 4980 return BCM_E_NONE; 4981 } 4982 4983 #endif /* BCM_TRIDENT_SUPPORT || BCM_GREYHOUND_SUPPORT */ 4984 4985 /* 4986 * Function: 4987 * _bcm_mirror_destination_match 4988 * Description: 4989 * Limited match utility used to identify mirror destination 4990 * with identical gport. 4991 * Parameters: 4992 * unit - (IN) BCM device number 4993 * mirror_dest - (IN) Mirror destination. 4994 * mirror_dest_id - (OUT)Matching mirror destination id. 4995 * Returns: 4996 * BCM_E_XXX 4997 */ 4998 int 4999 _bcm_mirror_destination_match(int unit, bcm_mirror_destination_t *mirror_dest, 5000 bcm_gport_t *mirror_dest_id) 5001 5002 { 5003 int idx; /* Mirror destinations iteration index.*/ 5004 _bcm_mirror_dest_config_p mdest;/* Mirror destination description. */ 5005 bcm_module_t mymodid; /* Local module id. */ 5006 int isLocal; /* Local modid indicator */ 5007 bcm_module_t dest_mod; /* Destination module id. */ 5008 bcm_port_t dest_port; /* Destination port number. */ 5009 _bcm_gport_dest_t gport_st; /* Structure to construct a GPORT */ 5010 int is_local_subport = FALSE; 5011 5012 /* Input parameters check. */ 5013 if ((NULL == mirror_dest_id) || (NULL == mirror_dest)) { 5014 return (BCM_E_PARAM); 5015 } 5016 5017 /* Get local modid. */ 5018 BCM_IF_ERROR_RETURN(_bcm_esw_local_modid_get(unit, &mymodid)); 5019 5020 /* Directed mirroring support check. */ 5021 if (MIRROR_MTP_METHOD_IS_NON_DIRECTED(unit) && !SOC_WARM_BOOT(unit)){ 5022 /* NB: If Warm Boot, then the ports should already be mapped. */ 5023 /* Set mirror destination to outgoing port on local module. */ 5024 dest_mod = BCM_GPORT_MODPORT_MODID_GET(mirror_dest->gport); 5025 if (soc_feature(unit, soc_feature_hgproxy_subtag_coe)) { 5026 #if defined(BCM_HGPROXY_COE_SUPPORT) 5027 dest_port = BCM_GPORT_MODPORT_PORT_GET(mirror_dest->gport); 5028 if(_bcm_xgs5_subport_coe_mod_port_local(unit, dest_mod, dest_port)) { 5029 is_local_subport = TRUE; 5030 } 5031 #endif 5032 } else 5033 if (soc_feature(unit, soc_feature_linkphy_coe) || 5034 soc_feature(unit, soc_feature_subtag_coe)) { 5035 #if defined(BCM_KATANA2_SUPPORT) 5036 dest_port = BCM_GPORT_MODPORT_PORT_GET(mirror_dest->gport); 5037 BCM_IF_ERROR_RETURN( 5038 _bcm_kt2_modport_is_local_coe_subport (unit, dest_mod, 5039 dest_port, &is_local_subport)); 5040 #endif 5041 } 5042 5043 BCM_IF_ERROR_RETURN(_bcm_esw_modid_is_local(unit, dest_mod, &isLocal)); 5044 if ((FALSE == isLocal) && (FALSE == is_local_subport)) { 5045 BCM_IF_ERROR_RETURN 5046 (bcm_esw_topo_port_get(unit, dest_mod, &dest_port)); 5047 gport_st.gport_type = BCM_GPORT_TYPE_MODPORT; 5048 gport_st.modid = mymodid; 5049 gport_st.port = dest_port; 5050 BCM_IF_ERROR_RETURN( 5051 _bcm_esw_gport_construct(unit,&gport_st, 5052 &(mirror_dest->gport))); 5053 } 5054 } 5055 5056 /* Find unused mirror destination & allocate it. */ 5057 for (idx = 0; idx < MIRROR_CONFIG(unit)->dest_count; idx++) { 5058 mdest = MIRROR_CONFIG(unit)->dest_arr + idx; 5059 /* Skip unused entries. */ 5060 if (0 == mdest->ref_count) { 5061 continue; 5062 } 5063 5064 /* Skip tunnel destinations. */ 5065 if (mdest->mirror_dest.flags & BCM_MIRROR_DEST_TUNNELS) { 5066 continue; 5067 } 5068 5069 if (mdest->mirror_dest.flags2) { 5070 continue; 5071 } 5072 5073 if (mdest->mirror_dest.gport == mirror_dest->gport) { 5074 /* Matching mirror destination found. */ 5075 *mirror_dest_id = mdest->mirror_dest.mirror_dest_id; 5076 return (BCM_E_NONE); 5077 } 5078 } 5079 return (BCM_E_NOT_FOUND); 5080 } 5081 5082 /* 5083 * Function: 5084 * _bcm_tr2_mirror_shared_mtp_match 5085 * Description: 5086 * Match a mirror-to port with one of the mtp indexes. 5087 * Parameters: 5088 * unit - (IN) BCM device number 5089 * dest_port - (IN) Mirror destination gport. 5090 * egress - (IN) Egress/Ingress indication 5091 * match_idx - (OUT) MTP index matching destination. 5092 * Returns: 5093 * BCM_E_XXX 5094 */ 5095 STATIC int 5096 _bcm_tr2_mirror_shared_mtp_match(int unit, bcm_gport_t gport, 5097 int egress, int *match_idx) 5098 { 5099 int idx; /* Mtp iteration index. */ 5100 5101 /* Input parameters check. */ 5102 if (NULL == match_idx) { 5103 return (BCM_E_PARAM); 5104 } 5105 5106 /* Look for existing MTP in use */ 5107 for (idx = 0; idx < BCM_MIRROR_MTP_COUNT; idx++) { 5108 if (MIRROR_CONFIG_SHARED_MTP_REF_COUNT(unit, idx)) { 5109 if ((gport == MIRROR_CONFIG_SHARED_MTP_DEST(unit, idx)) && 5110 egress == MIRROR_CONFIG_SHARED_MTP(unit, idx).egress) { 5111 *match_idx = idx; 5112 return (BCM_E_NONE); 5113 } 5114 } 5115 } 5116 return (BCM_E_NOT_FOUND); 5117 } 5118 5119 5120 /* 5121 * Function: 5122 * _bcm_esw_mirror_ingress_mtp_match 5123 * Description: 5124 * Match a mirror-to port with one of the mtp indexes. 5125 * Parameters: 5126 * unit - (IN) BCM device number 5127 * dest_port - (IN) Mirror destination gport. 5128 * match_idx - (OUT) MTP index matching destination. 5129 * Returns: 5130 * BCM_E_XXX 5131 */ 5132 STATIC int 5133 _bcm_esw_mirror_ingress_mtp_match(int unit, bcm_gport_t gport, int *match_idx) 5134 { 5135 int idx; /* Mtp iteration index. */ 5136 5137 /* Input parameters check. */ 5138 if (NULL == match_idx) { 5139 return (BCM_E_PARAM); 5140 } 5141 5142 /* Look for existing MTP in use */ 5143 for (idx = 0; idx < MIRROR_CONFIG(unit)->ing_mtp_count; idx++) { 5144 if (MIRROR_CONFIG_ING_MTP_REF_COUNT(unit, idx)) { 5145 if (gport == MIRROR_CONFIG_ING_MTP_DEST(unit, idx)) { 5146 *match_idx = idx; 5147 return (BCM_E_NONE); 5148 } 5149 } 5150 } 5151 return (BCM_E_NOT_FOUND); 5152 } 5153 5154 /* 5155 * Function: 5156 * _bcm_esw_mirror_egress_mtp_match 5157 * Description: 5158 * Match a mirror-to port with one of the mtp indexes. 5159 * Parameters: 5160 * unit - (IN) BCM device number 5161 * dest_port - (IN) Mirror destination gport. 5162 * match_idx - (OUT) MTP index matching destination. 5163 * Returns: 5164 * BCM_E_XXX 5165 */ 5166 STATIC int 5167 _bcm_esw_mirror_egress_mtp_match(int unit, bcm_gport_t gport, int *match_idx) 5168 { 5169 int idx; /* Mtp iteration index. */ 5170 5171 /* Input parameters check. */ 5172 if (NULL == match_idx) { 5173 return (BCM_E_PARAM); 5174 } 5175 5176 /* Look for existing MTP in use */ 5177 for (idx = 0; idx < MIRROR_CONFIG(unit)->egr_mtp_count; idx++) { 5178 if (MIRROR_CONFIG_EGR_MTP_REF_COUNT(unit, idx)) { 5179 if (gport == MIRROR_CONFIG_EGR_MTP_DEST(unit, idx)) { 5180 *match_idx = idx; 5181 return (BCM_E_NONE); 5182 } 5183 } 5184 } 5185 return (BCM_E_NOT_FOUND); 5186 } 5187 5188 #ifdef BCM_TRIUMPH2_SUPPORT 5189 /* 5190 * Function: 5191 * _bcm_esw_mirror_egress_true_mtp_match 5192 * Description: 5193 * Match a mirror-to port with one of the mtp indexes. 5194 * Parameters: 5195 * unit - (IN) BCM device number 5196 * dest_port - (IN) Mirror destination gport. 5197 * match_idx - (OUT) MTP index matching destination. 5198 * Returns: 5199 * BCM_E_XXX 5200 */ 5201 STATIC int 5202 _bcm_esw_mirror_egress_true_mtp_match(int unit, bcm_gport_t gport, 5203 int *match_idx) 5204 { 5205 int idx; /* Mtp iteration index. */ 5206 5207 /* Input parameters check. */ 5208 if (NULL == match_idx) { 5209 return (BCM_E_PARAM); 5210 } 5211 5212 /* Look for existing MTP in use */ 5213 for (idx = 0; idx < MIRROR_CONFIG(unit)->egr_true_mtp_count; idx++) { 5214 if (MIRROR_CONFIG_EGR_TRUE_MTP_REF_COUNT(unit, idx)) { 5215 if (gport == MIRROR_CONFIG_EGR_TRUE_MTP_DEST(unit, idx)) { 5216 *match_idx = idx; 5217 return (BCM_E_NONE); 5218 } 5219 } 5220 } 5221 5222 if (SOC_IS_APOLLO(unit) && 5223 (MIRROR_CONFIG(unit)->egr_true_mtp_count == 0) && 5224 soc_feature(unit, soc_feature_ipfix_flow_mirror)) { 5225 idx = 0; 5226 5227 if (MIRROR_CONFIG_EGR_TRUE_MTP_REF_COUNT(unit, idx)) { 5228 if (gport == MIRROR_CONFIG_EGR_TRUE_MTP_DEST(unit, idx)) { 5229 *match_idx = idx; 5230 return (BCM_E_NONE); 5231 } 5232 } 5233 } 5234 return (BCM_E_NOT_FOUND); 5235 } 5236 #endif /* BCM_TRIUMPH2_SUPPORT */ 5237 5238 /* 5239 * Function: 5240 * _bcm_esw_mirror_mtp_match 5241 * Description: 5242 * Match a mirror-to port with one of the mtp indexes. 5243 * Parameters: 5244 * unit - (IN) BCM device number 5245 * gport - (IN) Mirror destination gport. 5246 * match_idx - (OUT) MTP index matching destination. 5247 * Returns: 5248 * BCM_E_XXX 5249 */ 5250 int 5251 _bcm_esw_mirror_mtp_match(int unit, bcm_gport_t gport, uint32 flags, 5252 int *match_idx) 5253 { 5254 if (!soc_feature(unit, soc_feature_egr_mirror_true) && 5255 (flags & BCM_MIRROR_PORT_EGRESS_TRUE)) { 5256 return (BCM_E_PARAM); 5257 } 5258 5259 if (!(flags & (BCM_MIRROR_PORT_INGRESS | BCM_MIRROR_PORT_EGRESS | 5260 BCM_MIRROR_PORT_PSAMP | BCM_MIRROR_PORT_EGRESS_TRUE))) { 5261 return (BCM_E_PARAM); 5262 } 5263 5264 if (flags & BCM_MIRROR_PORT_INGRESS) { 5265 if (soc_feature(unit, soc_feature_mirror_flexible) && 5266 !MIRROR_MTP_METHOD_IS_DIRECTED_FLEXIBLE(unit)) { 5267 return _bcm_tr2_mirror_shared_mtp_match(unit, gport, FALSE, 5268 match_idx); 5269 } else { 5270 return _bcm_esw_mirror_ingress_mtp_match(unit, gport, match_idx); 5271 } 5272 } 5273 5274 if (flags & BCM_MIRROR_PORT_EGRESS) { 5275 return _bcm_esw_mirror_egress_mtp_match(unit, gport, match_idx); 5276 } 5277 5278 #ifdef BCM_TRIUMPH2_SUPPORT 5279 if (flags & BCM_MIRROR_PORT_EGRESS_TRUE) { 5280 return _bcm_esw_mirror_egress_true_mtp_match(unit, gport, match_idx); 5281 } 5282 #endif /* BCM_TRIUMPH2_SUPPORT */ 5283 return BCM_E_NOT_FOUND; 5284 } 5285 5286 /* 5287 * Function: 5288 * _bcm_tr2_mirror_vp_port_get 5289 * Description: 5290 * Get the virtual port number and the ingress gport associated 5291 * with the vp. 5292 * Parameters: 5293 * unit - (IN) BCM device number 5294 * gport - (IN) vp gport 5295 * vp_out - (OUT) virtual port number 5296 * port_out - (OUT) ingress gport associated with the vp 5297 * Returns: 5298 * BCM_E_XXX 5299 */ 5300 STATIC int 5301 _bcm_tr2_mirror_vp_port_get(int unit, bcm_gport_t gport, 5302 int *vp_out, int *port_out) 5303 { 5304 #if defined(BCM_TRIUMPH2_SUPPORT) && defined(INCLUDE_L3) 5305 int vp; 5306 bcm_gport_t phy_port_trunk; 5307 5308 if (BCM_GPORT_IS_VP_GROUP(gport)) { 5309 vp = BCM_GPORT_VP_GROUP_GET(gport); 5310 if (_bcm_vp_used_get(unit, vp, _bcmVpTypeVlan)) { 5311 BCM_GPORT_VLAN_PORT_ID_SET(gport, vp); 5312 } else if (_bcm_vp_used_get(unit, vp, _bcmVpTypeNiv)) { 5313 BCM_GPORT_NIV_PORT_ID_SET(gport, vp); 5314 } else if (_bcm_vp_used_get(unit, vp, _bcmVpTypeExtender)) { 5315 BCM_GPORT_EXTENDER_PORT_ID_SET(gport, vp); 5316 } else if (_bcm_vp_used_get(unit, vp, _bcmVpTypeMpls)) { 5317 BCM_GPORT_MPLS_PORT_ID_SET(gport, vp); 5318 } else { 5319 return BCM_E_INTERNAL; 5320 } 5321 } 5322 5323 if (BCM_GPORT_IS_VLAN_PORT(gport)) { 5324 bcm_vlan_port_t vlan_vp; 5325 5326 vp = BCM_GPORT_VLAN_PORT_ID_GET(gport); 5327 /* Get the physical port or trunk the VP resides on */ 5328 bcm_vlan_port_t_init(&vlan_vp); 5329 vlan_vp.vlan_port_id = gport; 5330 BCM_IF_ERROR_RETURN(bcm_tr2_vlan_vp_find(unit, &vlan_vp)); 5331 phy_port_trunk = vlan_vp.port; 5332 *port_out = phy_port_trunk; 5333 *vp_out = vp; 5334 return BCM_E_NONE; 5335 } else 5336 #ifdef BCM_TRIDENT_SUPPORT 5337 if (BCM_GPORT_IS_NIV_PORT(gport)) { 5338 bcm_niv_port_t niv_port; 5339 bcm_niv_egress_t niv_egress; 5340 int rv = BCM_E_NONE; 5341 int count; 5342 5343 vp = BCM_GPORT_NIV_PORT_ID_GET(gport); 5344 5345 /* Get the physical port or trunk the VP resides on */ 5346 bcm_niv_port_t_init(&niv_port); 5347 niv_port.niv_port_id = gport; 5348 BCM_IF_ERROR_RETURN(bcm_trident_niv_port_get(unit, &niv_port)); 5349 if (niv_port.flags & BCM_NIV_PORT_MATCH_NONE) { 5350 bcm_niv_egress_t_init(&niv_egress); 5351 rv = bcm_trident_niv_egress_get(unit, niv_port.niv_port_id, 5352 1, &niv_egress, &count); 5353 if (BCM_FAILURE(rv)) { 5354 return BCM_E_PARAM; 5355 } 5356 5357 if (niv_egress.flags & BCM_NIV_EGRESS_MULTICAST) { 5358 return BCM_E_PARAM; 5359 } else { 5360 phy_port_trunk = niv_egress.port; 5361 } 5362 } else { 5363 phy_port_trunk = niv_port.port; 5364 } 5365 *port_out = phy_port_trunk; 5366 *vp_out = vp; 5367 return BCM_E_NONE; 5368 } else 5369 #endif /* BCM_TRIDENT_SUPPORT */ 5370 #ifdef BCM_TRIUMPH3_SUPPORT 5371 if (BCM_GPORT_IS_EXTENDER_PORT(gport)) { 5372 bcm_extender_port_t extender_port; 5373 bcm_extender_egress_t extender_egress; 5374 int count; 5375 vp = BCM_GPORT_EXTENDER_PORT_ID_GET(gport); 5376 5377 /* Get the physical port or trunk the VP resides on */ 5378 bcm_extender_port_t_init(&extender_port); 5379 extender_port.extender_port_id = gport; 5380 BCM_IF_ERROR_RETURN(bcm_tr3_extender_port_get(unit, &extender_port)); 5381 if (extender_port.flags & BCM_EXTENDER_PORT_MATCH_NONE) { 5382 bcm_extender_egress_t_init(&extender_egress); 5383 BCM_IF_ERROR_RETURN(bcm_tr3_extender_egress_get_all(unit, 5384 extender_port.extender_port_id, 1, &extender_egress, &count)); 5385 if (count == 0) { 5386 /* No Extender egress object has been added to VP yet. */ 5387 return BCM_E_CONFIG; 5388 } 5389 if (extender_egress.flags & BCM_EXTENDER_EGRESS_MULTICAST) { 5390 return BCM_E_PARAM; 5391 } 5392 phy_port_trunk = extender_egress.port; 5393 } else { 5394 phy_port_trunk = extender_port.port; 5395 } 5396 *port_out = phy_port_trunk; 5397 *vp_out = vp; 5398 return BCM_E_NONE; 5399 } else 5400 #endif /* BCM_TRIUMPH3_SUPPORT */ 5401 #ifdef BCM_MPLS_SUPPORT 5402 if (BCM_GPORT_IS_MPLS_PORT(gport)) { 5403 bcm_mpls_port_t mpls_port; 5404 int vpn0; 5405 5406 vp = BCM_GPORT_MPLS_PORT_ID_GET(gport); 5407 bcm_mpls_port_t_init(&mpls_port); 5408 mpls_port.mpls_port_id = gport; 5409 _BCM_MPLS_VPN_SET(vpn0,_BCM_MPLS_VPN_TYPE_VPWS,0); 5410 BCM_IF_ERROR_RETURN(bcm_tr_mpls_port_get(unit, 5411 vpn0, &mpls_port)); 5412 phy_port_trunk = mpls_port.port; 5413 *port_out = phy_port_trunk; 5414 *vp_out = vp; 5415 return BCM_E_NONE; 5416 } else 5417 #endif /* BCM_MPLS_SUPPORT */ 5418 #if defined(BCM_TRIDENT2_SUPPORT) 5419 if (BCM_GPORT_IS_VXLAN_PORT(gport)) { 5420 int gport_id = -1; 5421 bcm_module_t mod_out = -1; 5422 bcm_trunk_t trunk_id = -1; 5423 bcm_port_t port = -1; 5424 5425 vp = BCM_GPORT_VXLAN_PORT_ID_GET(gport); 5426 BCM_IF_ERROR_RETURN(_bcm_esw_gport_resolve(unit, gport, &mod_out, 5427 &port, &trunk_id, &gport_id)); 5428 phy_port_trunk = _bcm_esw_port_gport_get_from_modport(unit, mod_out, 5429 port); 5430 *port_out = phy_port_trunk; 5431 *vp_out = vp; 5432 return BCM_E_NONE; 5433 } else 5434 #endif 5435 {} 5436 5437 #endif /* defined(BCM_TRIUMPH2_SUPPORT) && defined(INCLUDE_L3) */ 5438 return BCM_E_NOT_FOUND; 5439 } 5440 5441 /* 5442 * Function: 5443 * _bcm_tr2_mirror_svp_enable_get 5444 * Description: 5445 * check if the ingress mirroring is enabled on the given vp. 5446 * Parameters: 5447 * unit - (IN) BCM device number 5448 * vp - (IN) virtual port number 5449 * enable - (OUT) enable status 5450 * Returns: 5451 * BCM_E_XXX 5452 */ 5453 STATIC int 5454 _bcm_tr2_mirror_svp_enable_get(int unit, int vp, 5455 int *enable) 5456 { 5457 #ifdef BCM_TRIUMPH2_SUPPORT 5458 if (soc_feature(unit, soc_feature_mirror_flexible)) { 5459 source_vp_entry_t svp_entry; 5460 5461 sal_memset(&svp_entry, 0, sizeof(source_vp_entry_t)); 5462 BCM_IF_ERROR_RETURN(READ_SOURCE_VPm(unit, MEM_BLOCK_ALL, vp, 5463 &svp_entry)); 5464 *enable = soc_SOURCE_VPm_field32_get(unit, &svp_entry, 5465 ING_MIRROR_ENABLEf); 5466 return BCM_E_NONE; 5467 } 5468 #endif 5469 return BCM_E_UNAVAIL; 5470 } 5471 5472 /* 5473 * Function: 5474 * _bcm_tr2_mirror_svp_enable_set 5475 * Description: 5476 * Enable the ingress mirroring on the given vp. 5477 * Parameters: 5478 * unit - (IN) BCM device number 5479 * vp - (IN) virtual port number 5480 * enable - (IN) enable the given MTP 5481 * Returns: 5482 * BCM_E_XXX 5483 */ 5484 STATIC int 5485 _bcm_tr2_mirror_svp_enable_set(int unit, int vp, 5486 int enable) 5487 { 5488 #ifdef BCM_TRIUMPH2_SUPPORT 5489 if (soc_feature(unit, soc_feature_mirror_flexible)) { 5490 source_vp_entry_t svp_entry; 5491 5492 sal_memset(&svp_entry, 0, sizeof(source_vp_entry_t)); 5493 BCM_IF_ERROR_RETURN(READ_SOURCE_VPm(unit, MEM_BLOCK_ALL, vp, 5494 &svp_entry)); 5495 soc_SOURCE_VPm_field32_set(unit, &svp_entry, 5496 ING_MIRROR_ENABLEf, enable); 5497 BCM_IF_ERROR_RETURN(WRITE_SOURCE_VPm(unit, 5498 MEM_BLOCK_ALL, vp, &svp_entry)); 5499 return BCM_E_NONE; 5500 } 5501 #endif 5502 return BCM_E_UNAVAIL; 5503 } 5504 5505 /* 5506 * Function: 5507 * _bcm_tr2_mirror_dvp_enable_get 5508 * Description: 5509 * check if the egress mirroring is enabled on the given vp. 5510 * Parameters: 5511 * unit - (IN) BCM device number 5512 * vp - (IN) virtual port number 5513 * enable - (OUT) enable status 5514 * Returns: 5515 * BCM_E_XXX 5516 */ 5517 STATIC int 5518 _bcm_tr2_mirror_dvp_enable_get(int unit, int vp, 5519 int *enable) 5520 { 5521 #ifdef BCM_TRIUMPH2_SUPPORT 5522 if (soc_feature(unit, soc_feature_mirror_flexible)) { 5523 soc_mem_t mem; 5524 void *entry; 5525 ing_dvp_table_entry_t dvp_entry; 5526 ing_dvp_2_table_entry_t dvp_2_entry; 5527 5528 if (soc_feature(unit, soc_feature_td2p_dvp_mirroring)) { 5529 mem = ING_DVP_2_TABLEm; 5530 sal_memset(&dvp_2_entry, 0, sizeof(ing_dvp_2_table_entry_t)); 5531 entry = &dvp_2_entry; 5532 } else { 5533 mem = ING_DVP_TABLEm; 5534 sal_memset(&dvp_entry, 0, sizeof(ing_dvp_table_entry_t)); 5535 entry = &dvp_entry; 5536 } 5537 5538 BCM_IF_ERROR_RETURN 5539 (soc_mem_read(unit, mem, MEM_BLOCK_ALL, vp, entry)); 5540 *enable = soc_mem_field32_get(unit, mem, entry, 5541 EGR_MIRROR_ENABLEf); 5542 5543 return BCM_E_NONE; 5544 } 5545 #endif /* BCM_TRIUMPH2_SUPPORT */ 5546 return BCM_E_UNAVAIL; 5547 } 5548 5549 /* 5550 * Function: 5551 * _bcm_tr2_mirror_dvp_enable_set 5552 * Description: 5553 * enable the egress mirroring on the given vp. 5554 * Parameters: 5555 * unit - (IN) BCM device number 5556 * gport - (IN) virtual port number 5557 * enable - (IN) enable the given MTP 5558 * Returns: 5559 * BCM_E_XXX 5560 */ 5561 STATIC int 5562 _bcm_tr2_mirror_dvp_enable_set(int unit, int vp, 5563 int enable) 5564 { 5565 #ifdef BCM_TRIUMPH2_SUPPORT 5566 if (soc_feature(unit, soc_feature_mirror_flexible)) { 5567 soc_mem_t mem; 5568 void *entry; 5569 ing_dvp_table_entry_t dvp_entry; 5570 ing_dvp_2_table_entry_t dvp_2_entry; 5571 5572 if (soc_feature(unit, soc_feature_td2p_dvp_mirroring)) { 5573 mem = ING_DVP_2_TABLEm; 5574 sal_memset(&dvp_2_entry, 0, sizeof(ing_dvp_2_table_entry_t)); 5575 entry = &dvp_2_entry; 5576 } else { 5577 mem = ING_DVP_TABLEm; 5578 sal_memset(&dvp_entry, 0, sizeof(ing_dvp_table_entry_t)); 5579 entry = &dvp_entry; 5580 } 5581 5582 BCM_IF_ERROR_RETURN 5583 (soc_mem_read(unit, mem, MEM_BLOCK_ALL, vp, entry)); 5584 soc_mem_field32_set(unit, mem, entry, EGR_MIRROR_ENABLEf, enable); 5585 BCM_IF_ERROR_RETURN 5586 (soc_mem_write(unit, mem, MEM_BLOCK_ALL, vp, entry)); 5587 5588 return BCM_E_NONE; 5589 } 5590 #endif /* BCM_TRIUMPH2_SUPPORT */ 5591 return BCM_E_UNAVAIL; 5592 } 5593 5594 /* 5595 * Function: 5596 * _bcm_esw_mirror_destination_find 5597 * Purpose: 5598 * Find mirror destination for all gport types. 5599 * Parameters: 5600 * unit - (IN) BCM device number. 5601 * port - (IN) port, gport or mirror gport 5602 * modid - (IN) module id. 5603 * flags - (IN) BCM_MIRROR_PORT_DEST_* flags 5604 * mirror_dest - (OUT) mirror destination 5605 * Returns: 5606 * BCM_E_XXX 5607 */ 5608 5609 STATIC int 5610 _bcm_esw_mirror_destination_find(int unit, bcm_port_t port, bcm_module_t modid, 5611 uint32 flags, bcm_mirror_destination_t *mirror_dest) 5612 { 5613 if (NULL == mirror_dest) { 5614 return BCM_E_PARAM; 5615 } 5616 5617 if (BCM_GPORT_IS_SET(port)) { 5618 /* If gport passed, work with it directly */ 5619 mirror_dest->gport = port; 5620 } else { 5621 _bcm_gport_dest_t gport_st; /* Structure to construct a GPORT */ 5622 5623 /* If not gport then construct the gport from given parameters.*/ 5624 if (flags & BCM_MIRROR_PORT_DEST_TRUNK) { 5625 /* Mirror destination is a trunk. */ 5626 gport_st.gport_type = BCM_GPORT_TYPE_TRUNK; 5627 gport_st.tgid = port; 5628 } else { 5629 /* Convert port + mod to GPORT format. No trunking destination support. */ 5630 if (-1 == modid) { 5631 /* Get local modid. */ 5632 BCM_IF_ERROR_RETURN( 5633 _bcm_esw_local_modid_get(unit, &modid)); 5634 } else if (!SOC_MODID_ADDRESSABLE(unit, modid)){ 5635 return BCM_E_PARAM; 5636 } 5637 5638 gport_st.gport_type = BCM_GPORT_TYPE_MODPORT; 5639 gport_st.modid = modid; 5640 gport_st.port = port; 5641 } 5642 BCM_IF_ERROR_RETURN( 5643 _bcm_esw_gport_construct(unit, &gport_st, &(mirror_dest->gport))); 5644 } 5645 5646 /* Adapt miror destination gport */ 5647 BCM_IF_ERROR_RETURN( 5648 _bcm_mirror_gport_adapt(unit, &(mirror_dest->gport))); 5649 5650 /* Find matching mirror destination */ 5651 BCM_IF_ERROR_RETURN( 5652 _bcm_mirror_destination_match(unit, mirror_dest, 5653 &(mirror_dest->mirror_dest_id))); 5654 return (BCM_E_NONE); 5655 } 5656 5657 /* 5658 * Function: 5659 * _bcm_mirror_destination_alloc 5660 * Purpose: 5661 * Allocate mirror destination description. 5662 * Parameters: 5663 * unit - (IN) BCM device number. 5664 * mirror_dest_id - (OUT) Mirror destination id. 5665 * Returns: 5666 * BCM_X_XXX 5667 */ 5668 5669 /* Create a mirror (destination, encapsulation) pair. */ 5670 STATIC int 5671 _bcm_mirror_destination_alloc(int unit, bcm_gport_t *mirror_dest_id) 5672 { 5673 int idx; /* Mirror destinations iteration index.*/ 5674 _bcm_mirror_dest_config_p mdest; /* Mirror destination description. */ 5675 5676 /* Input parameters check. */ 5677 if (NULL == mirror_dest_id) { 5678 return (BCM_E_PARAM); 5679 } 5680 5681 /* Find unused mirror destination & allocate it. */ 5682 for (idx = 0; idx < MIRROR_CONFIG(unit)->dest_count; idx++) { 5683 mdest = MIRROR_CONFIG(unit)->dest_arr + idx; 5684 if (mdest->ref_count) { 5685 continue; 5686 } 5687 mdest->ref_count++; 5688 *mirror_dest_id = mdest->mirror_dest.mirror_dest_id; 5689 return (BCM_E_NONE); 5690 } 5691 5692 /* All mirror destinations are used. */ 5693 return (BCM_E_RESOURCE); 5694 } 5695 5696 /* 5697 * Function: 5698 * _bcm_mirror_destination_free 5699 * Purpose: 5700 * Free mirror destination description. 5701 * Parameters: 5702 * unit - (IN) BCM device number. 5703 * mirror_dest_id - (IN) Mirror destination id. 5704 * Returns: 5705 * BCM_X_XXX 5706 */ 5707 5708 /* Create a mirror (destination, encapsulation) pair. */ 5709 STATIC int 5710 _bcm_mirror_destination_free(int unit, bcm_gport_t mirror_dest_id) 5711 { 5712 _bcm_mirror_dest_config_p mdest_cfg; /* Mirror destination config.*/ 5713 5714 mdest_cfg = &MIRROR_DEST_CONFIG(unit, mirror_dest_id); 5715 5716 if (mdest_cfg->ref_count > 0) { 5717 mdest_cfg->ref_count--; 5718 5719 if (0 == mdest_cfg->ref_count) { 5720 sal_memset(&mdest_cfg->mirror_dest, 0, 5721 sizeof(bcm_mirror_destination_t)); 5722 mdest_cfg->mirror_dest.mirror_dest_id = mirror_dest_id; 5723 mdest_cfg->mirror_dest.gport = BCM_GPORT_INVALID; 5724 } 5725 } else { 5726 return BCM_E_NOT_FOUND; 5727 } 5728 5729 return (BCM_E_NONE); 5730 } 5731 5732 #ifdef BCM_TRIDENT2_SUPPORT 5733 /* Search a mtp node in a shared-id mirror destination. */ 5734 STATIC int 5735 _bcm_mirror_dest_mtp_search(int unit, bcm_gport_t mirror_dest_id, 5736 bcm_gport_t gport, uint8 *found) 5737 { 5738 _bcm_mirror_dest_config_p mdest_cfg; /* Mirror destination config head node */ 5739 _bcm_mirror_dest_config_p cur_dest = NULL; /* current node */ 5740 int i = 0, max_portcnt = BCM_SWITCH_TRUNK_MAX_PORTCNT; 5741 5742 if (!BCM_GPORT_IS_MIRROR(mirror_dest_id)) { 5743 return (BCM_E_PARAM); 5744 } 5745 5746 mdest_cfg = &MIRROR_DEST_CONFIG(unit, mirror_dest_id); 5747 5748 if (mdest_cfg->ref_count <= 0) { 5749 *found = FALSE; 5750 return (BCM_E_NONE); 5751 } 5752 5753 cur_dest = mdest_cfg->next; 5754 *found = FALSE; 5755 5756 for (i = 0; i < max_portcnt; i++) { 5757 if (NULL == cur_dest) { 5758 break; 5759 } 5760 5761 if (cur_dest->mirror_dest.gport == gport) { 5762 *found = TRUE; 5763 break; 5764 } 5765 cur_dest = cur_dest->next; 5766 } 5767 5768 return (BCM_E_NONE); 5769 } 5770 5771 /* Add an MTP into a shared-id mirror destination. */ 5772 STATIC int 5773 _bcm_mirror_dest_mtp_add(int unit, bcm_gport_t mirror_dest_id, 5774 _bcm_mirror_dest_config_p mirror_dest_node) 5775 { 5776 _bcm_mirror_dest_config_p mdest_cfg; /* Mirror destination config head node */ 5777 _bcm_mirror_dest_config_p cur_dest = NULL; /* Current node */ 5778 _bcm_mirror_dest_config_p prev_dest = NULL; /* Previous node */ 5779 int i = 0, max_portcnt = BCM_SWITCH_TRUNK_MAX_PORTCNT; 5780 5781 if (!BCM_GPORT_IS_MIRROR(mirror_dest_id)) { 5782 return (BCM_E_PARAM); 5783 } 5784 5785 mdest_cfg = &MIRROR_DEST_CONFIG(unit, mirror_dest_id); 5786 if (mdest_cfg->ref_count <= 0) { 5787 return (BCM_E_NOT_FOUND); 5788 } 5789 5790 prev_dest = mdest_cfg; 5791 cur_dest = mdest_cfg->next; 5792 5793 /* Insert at tail, so find the last node */ 5794 for (i = 0; i < max_portcnt; i++) { 5795 if (NULL == cur_dest) { 5796 break; 5797 } else { 5798 prev_dest = cur_dest; 5799 cur_dest = cur_dest->next; 5800 } 5801 } 5802 5803 if (i < max_portcnt) { 5804 prev_dest->next = mirror_dest_node; 5805 mirror_dest_node->next = NULL; 5806 } else { 5807 /* Support 8 ports(include head node) at most */ 5808 return (BCM_E_FULL); 5809 } 5810 5811 return (BCM_E_NONE); 5812 } 5813 5814 /* Update an MTP info in a shared-id mirror destination. */ 5815 STATIC int 5816 _bcm_mirror_dest_mtp_update(int unit, bcm_gport_t mirror_dest_id, 5817 bcm_mirror_destination_t *mirror_dest) 5818 { 5819 _bcm_mirror_dest_config_p mdest_cfg; /* Mirror destination config head node */ 5820 _bcm_mirror_dest_config_p cur_dest = NULL; /* Current node */ 5821 int i = 0, max_portcnt = BCM_SWITCH_TRUNK_MAX_PORTCNT; 5822 uint8 found = FALSE; 5823 5824 if (!BCM_GPORT_IS_MIRROR(mirror_dest_id)) { 5825 return (BCM_E_PARAM); 5826 } 5827 5828 mdest_cfg = &MIRROR_DEST_CONFIG(unit, mirror_dest_id); 5829 if (mdest_cfg->ref_count <= 0) { 5830 return (BCM_E_NOT_FOUND); 5831 } 5832 5833 cur_dest = mdest_cfg->next; 5834 for (i = 0; i < max_portcnt; i++) { 5835 if (NULL == cur_dest) { 5836 break; 5837 } 5838 5839 if (cur_dest->mirror_dest.gport == mirror_dest->gport) { 5840 found = TRUE; 5841 break; 5842 } 5843 cur_dest = cur_dest->next; 5844 } 5845 5846 if (found == TRUE) { 5847 sal_memcpy(&cur_dest->mirror_dest, 5848 mirror_dest, 5849 sizeof(bcm_mirror_destination_t)); 5850 } else { 5851 return (BCM_E_NOT_FOUND); 5852 } 5853 5854 return (BCM_E_NONE); 5855 } 5856 5857 /* Get an MTP info from a shared-id mirror destination. */ 5858 STATIC int 5859 _bcm_mirror_dest_mtp_get(int unit, 5860 bcm_gport_t mirror_dest_id, 5861 bcm_gport_t gport, 5862 bcm_mirror_destination_t *mirror_dest) 5863 { 5864 _bcm_mirror_dest_config_p mdest_cfg; /* Mirror destination config head node */ 5865 _bcm_mirror_dest_config_p cur_dest = NULL; /* Current node */ 5866 int i = 0, max_portcnt = BCM_SWITCH_TRUNK_MAX_PORTCNT; 5867 uint8 found = FALSE; 5868 5869 if (!BCM_GPORT_IS_MIRROR(mirror_dest_id)) { 5870 return (BCM_E_PARAM); 5871 } 5872 5873 mdest_cfg = &MIRROR_DEST_CONFIG(unit, mirror_dest_id); 5874 if (mdest_cfg->ref_count <= 0) { 5875 return (BCM_E_NOT_FOUND); 5876 } 5877 5878 cur_dest = mdest_cfg->next; 5879 for (i = 0; i < max_portcnt; i++) { 5880 if (NULL == cur_dest) { 5881 break; 5882 } 5883 5884 if (cur_dest->mirror_dest.gport == gport) { 5885 found = TRUE; 5886 break; 5887 } 5888 cur_dest = cur_dest->next; 5889 } 5890 5891 if (found == TRUE) { 5892 sal_memcpy(mirror_dest, 5893 &cur_dest->mirror_dest, 5894 sizeof(bcm_mirror_destination_t)); 5895 } else { 5896 return (BCM_E_NOT_FOUND); 5897 } 5898 5899 return (BCM_E_NONE); 5900 } 5901 5902 /* Traverse MTP of a shared-id mirror destination. */ 5903 STATIC int 5904 _bcm_mirror_dest_mtp_traverse(int unit, 5905 bcm_gport_t mirror_dest_id, 5906 bcm_mirror_destination_traverse_cb cb, 5907 void *user_data) 5908 { 5909 _bcm_mirror_dest_config_p mdest_cfg; /* Mirror destination config head node */ 5910 _bcm_mirror_dest_config_p cur_dest = NULL; /* Current node */ 5911 bcm_mirror_destination_t mirror_dest; /* User cb mirror destination. */ 5912 int i = 0, max_portcnt = BCM_SWITCH_TRUNK_MAX_PORTCNT; 5913 int rv = BCM_E_NONE; 5914 5915 if (!BCM_GPORT_IS_MIRROR(mirror_dest_id)) { 5916 return (BCM_E_PARAM); 5917 } 5918 5919 mdest_cfg = &MIRROR_DEST_CONFIG(unit, mirror_dest_id); 5920 if (mdest_cfg->ref_count <= 0) { 5921 return (BCM_E_NOT_FOUND); 5922 } 5923 5924 cur_dest = mdest_cfg->next; 5925 for (i = 0; i < max_portcnt; i++) { 5926 if (NULL == cur_dest) { 5927 break; 5928 } 5929 5930 mirror_dest = cur_dest->mirror_dest; 5931 rv = (*cb)(unit, &mirror_dest, user_data); 5932 if (BCM_FAILURE(rv)) { 5933 #ifdef BCM_CB_ABORT_ON_ERR 5934 if (SOC_CB_ABORT_ON_ERR(unit)) { 5935 return rv; 5936 } 5937 #endif 5938 } 5939 cur_dest = cur_dest->next; 5940 } 5941 5942 return (BCM_E_NONE); 5943 } 5944 5945 /* Get MTP gport array from a shared-id mirror destination. */ 5946 STATIC int 5947 _bcm_mirror_dest_mtp_gport_get(int unit, bcm_gport_t mirror_dest_id, 5948 bcm_gport_t *gport_array, int *count) 5949 { 5950 _bcm_mirror_dest_config_p mdest_cfg; /* Mirror destination config head node */ 5951 _bcm_mirror_dest_config_p cur_dest = NULL; /* Current node */ 5952 int i = 0, max_portcnt = BCM_SWITCH_TRUNK_MAX_PORTCNT; 5953 5954 if (!BCM_GPORT_IS_MIRROR(mirror_dest_id)) { 5955 return (BCM_E_PARAM); 5956 } 5957 5958 mdest_cfg = &MIRROR_DEST_CONFIG(unit, mirror_dest_id); 5959 if (mdest_cfg->ref_count <= 0) { 5960 return (BCM_E_NOT_FOUND); 5961 } 5962 5963 cur_dest = mdest_cfg->next; 5964 for (i = 0; i < max_portcnt; i++) { 5965 if (NULL == cur_dest) { 5966 break; 5967 } 5968 gport_array[i] = cur_dest->mirror_dest.gport; 5969 cur_dest = cur_dest->next; 5970 *count = i + 1; 5971 } 5972 5973 return (BCM_E_NONE); 5974 } 5975 5976 5977 /* Delete an MTP from a shared-id mirror destination. */ 5978 STATIC int 5979 _bcm_mirror_dest_mtp_delete(int unit, bcm_gport_t mirror_dest_id, 5980 bcm_gport_t gport) 5981 { 5982 _bcm_mirror_dest_config_p mdest_cfg; /* Mirror destination config head node */ 5983 _bcm_mirror_dest_config_p prev_dest = NULL; 5984 _bcm_mirror_dest_config_p cur_dest = NULL; 5985 int i = 0, max_portcnt = BCM_SWITCH_TRUNK_MAX_PORTCNT; 5986 uint8 found = FALSE; 5987 5988 if (!BCM_GPORT_IS_MIRROR(mirror_dest_id)) { 5989 return (BCM_E_PARAM); 5990 } 5991 5992 mdest_cfg = &MIRROR_DEST_CONFIG(unit, mirror_dest_id); 5993 if (mdest_cfg->ref_count <= 0) { 5994 return (BCM_E_NOT_FOUND); 5995 } 5996 5997 prev_dest = mdest_cfg; 5998 cur_dest = mdest_cfg->next; 5999 for (i = 0; i < max_portcnt; i++) { 6000 if (NULL == cur_dest) { 6001 break; 6002 } 6003 6004 if (cur_dest->mirror_dest.gport == gport) { 6005 found = TRUE; 6006 break; 6007 } 6008 prev_dest = cur_dest; 6009 cur_dest = cur_dest->next; 6010 } 6011 6012 if (found == TRUE) { 6013 prev_dest->next = cur_dest->next; 6014 cur_dest->next = NULL; 6015 sal_free(cur_dest); 6016 } else { 6017 return (BCM_E_NOT_FOUND); 6018 } 6019 6020 return (BCM_E_NONE); 6021 } 6022 6023 /* Delete all MTPs of a shared-id mirror destination. */ 6024 STATIC int 6025 _bcm_mirror_dest_mtp_delete_all(int unit, 6026 bcm_gport_t mirror_dest_id) 6027 { 6028 _bcm_mirror_dest_config_p mdest_cfg; /* Mirror destination config head node */ 6029 _bcm_mirror_dest_config_p next_dest = NULL; 6030 _bcm_mirror_dest_config_p free_dest = NULL; 6031 6032 if (!BCM_GPORT_IS_MIRROR(mirror_dest_id)) { 6033 return (BCM_E_PARAM); 6034 } 6035 6036 mdest_cfg = &MIRROR_DEST_CONFIG(unit, mirror_dest_id); 6037 if (mdest_cfg->ref_count <= 0) { 6038 return (BCM_E_NOT_FOUND); 6039 } 6040 6041 free_dest = mdest_cfg->next; 6042 mdest_cfg->next = NULL; 6043 while (free_dest) { 6044 next_dest = free_dest->next; 6045 free_dest->next = NULL; 6046 sal_free(free_dest); 6047 free_dest = next_dest; 6048 } 6049 6050 return (BCM_E_NONE); 6051 } 6052 6053 /* Free all MTP nodes of one mirror destination array. */ 6054 STATIC int 6055 _bcm_mirror_dest_array_mtp_free(int unit, 6056 _bcm_mirror_config_p cfg_ptr) 6057 { 6058 _bcm_mirror_config_p ptr; 6059 _bcm_mirror_dest_config_p mdest_cfg; /* Mirror destination config head node */ 6060 _bcm_mirror_dest_config_p next_dest = NULL; 6061 _bcm_mirror_dest_config_p free_dest = NULL; 6062 int i = 0, dest_count = 0; 6063 6064 if (NULL == cfg_ptr) { 6065 return (BCM_E_PARAM); 6066 } 6067 6068 ptr = cfg_ptr; 6069 dest_count = ptr->dest_count; 6070 for (i = 0; i < dest_count; i++) { 6071 mdest_cfg = ptr->dest_arr + i; 6072 6073 if (mdest_cfg->ref_count > 0) { 6074 free_dest = mdest_cfg->next; 6075 mdest_cfg->next = NULL; 6076 6077 while (free_dest) { 6078 next_dest = free_dest->next; 6079 free_dest->next = NULL; 6080 sal_free(free_dest); 6081 free_dest = next_dest; 6082 } 6083 } 6084 } 6085 6086 return (BCM_E_NONE); 6087 } 6088 6089 /* Set a shared-id mirror destination. */ 6090 STATIC int 6091 _bcm_esw_mirror_shared_dest_set(int unit, 6092 bcm_mirror_destination_t *mirror_dest) 6093 { 6094 _bcm_mirror_dest_config_p mir_dest_node = NULL; 6095 int rv = BCM_E_NONE; 6096 uint8 found = FALSE; 6097 6098 if (mirror_dest->flags & BCM_MIRROR_DEST_WITH_ID) { 6099 if (0 != MIRROR_DEST_REF_COUNT(unit, mirror_dest->mirror_dest_id)) { 6100 if (mirror_dest->flags & BCM_MIRROR_DEST_REPLACE) { 6101 /* Replace a shared-id mirror destination */ 6102 *(MIRROR_DEST(unit, mirror_dest->mirror_dest_id)) = *mirror_dest; 6103 (MIRROR_DEST(unit, mirror_dest->mirror_dest_id))->flags &= 6104 (BCM_MIRROR_DEST_TUNNELS | 6105 BCM_MIRROR_DEST_INT_PRI_SET | BCM_MIRROR_DEST_REPLACE | 6106 BCM_MIRROR_DEST_FIELD | BCM_MIRROR_DEST_PORT | 6107 BCM_MIRROR_DEST_ID_SHARE); 6108 } else if (mirror_dest->flags & BCM_MIRROR_DEST_MTP_ADD) { 6109 /* Add an MTP into a shared-id mirror destination */ 6110 BCM_IF_ERROR_RETURN( 6111 _bcm_mirror_dest_mtp_search( 6112 unit, mirror_dest->mirror_dest_id, 6113 mirror_dest->gport, &found)); 6114 if (TRUE == found) { 6115 return (BCM_E_EXISTS); 6116 } 6117 mir_dest_node = sal_alloc(sizeof(_bcm_mirror_dest_config_t), 6118 "Mirror destination config node"); 6119 6120 if (NULL == mir_dest_node) { 6121 rv = (BCM_E_MEMORY); 6122 return rv; 6123 } 6124 6125 sal_memset(mir_dest_node, 0, 6126 sizeof(_bcm_mirror_dest_config_t)); 6127 sal_memcpy(&mir_dest_node->mirror_dest, mirror_dest, 6128 sizeof(bcm_mirror_destination_t)); 6129 rv= _bcm_mirror_dest_mtp_add( 6130 unit, mirror_dest->mirror_dest_id, 6131 mir_dest_node); 6132 if (BCM_FAILURE(rv)) { 6133 if (NULL != mir_dest_node) { 6134 sal_free(mir_dest_node); 6135 } 6136 } 6137 } else if (mirror_dest->flags & BCM_MIRROR_DEST_MTP_REPLACE) { 6138 /* Replace an MTP of a shared-id mirror destination */ 6139 rv = _bcm_mirror_dest_mtp_update( 6140 unit, mirror_dest->mirror_dest_id, 6141 mirror_dest); 6142 } else if (mirror_dest->flags & BCM_MIRROR_DEST_MTP_DELETE) { 6143 /* Delete an MTP from a shared-id mirror destination */ 6144 rv = _bcm_mirror_dest_mtp_delete( 6145 unit, mirror_dest->mirror_dest_id, 6146 mirror_dest->gport); 6147 } else { 6148 rv = (BCM_E_PARAM); 6149 } 6150 } else { 6151 /* Create a new shared-id mirror destination with id. */ 6152 MIRROR_DEST_REF_COUNT(unit, mirror_dest->mirror_dest_id) = 1; 6153 *(MIRROR_DEST(unit, mirror_dest->mirror_dest_id)) = *mirror_dest; 6154 (MIRROR_DEST(unit, mirror_dest->mirror_dest_id))->flags &= 6155 (BCM_MIRROR_DEST_TUNNELS | 6156 BCM_MIRROR_DEST_INT_PRI_SET | BCM_MIRROR_DEST_REPLACE | 6157 BCM_MIRROR_DEST_FIELD | BCM_MIRROR_DEST_PORT | 6158 BCM_MIRROR_DEST_ID_SHARE); 6159 rv = (BCM_E_NONE); 6160 } 6161 } else { 6162 /* Create a new shared-id mirror destination. */ 6163 BCM_IF_ERROR_RETURN( 6164 _bcm_mirror_destination_alloc(unit, &mirror_dest->mirror_dest_id)); 6165 6166 *(MIRROR_DEST(unit, mirror_dest->mirror_dest_id)) = *mirror_dest; 6167 (MIRROR_DEST(unit, mirror_dest->mirror_dest_id))->flags &= 6168 (BCM_MIRROR_DEST_TUNNELS | 6169 BCM_MIRROR_DEST_INT_PRI_SET | BCM_MIRROR_DEST_REPLACE | 6170 BCM_MIRROR_DEST_FIELD | BCM_MIRROR_DEST_PORT | 6171 BCM_MIRROR_DEST_ID_SHARE); 6172 rv = (BCM_E_NONE); 6173 } 6174 6175 return rv; 6176 } 6177 #endif /* BCM_TRIDENT2_SUPPORT */ 6178 6179 /* 6180 * Function: 6181 * _bcm_esw_mirror_destination_create 6182 * Purpose: 6183 * Helper function to API that creates mirror destination description. 6184 * Parameters: 6185 * unit - (IN) BCM device number. 6186 * mirror_dest - (IN) Mirror destination description. 6187 * Returns: 6188 * BCM_X_XXX 6189 */ 6190 STATIC int 6191 _bcm_esw_mirror_destination_create(int unit, 6192 bcm_mirror_destination_t *mirror_dest) 6193 { 6194 #ifdef BCM_TRIDENT2_SUPPORT 6195 if (mirror_dest->flags & BCM_MIRROR_DEST_ID_SHARE) { 6196 return _bcm_esw_mirror_shared_dest_set(unit, mirror_dest); 6197 } 6198 #endif /* BCM_TRIDENT2_SUPPORT */ 6199 6200 if (mirror_dest->flags & BCM_MIRROR_DEST_WITH_ID) { 6201 /* Check mirror destination id */ 6202 if ((0 == BCM_GPORT_IS_MIRROR(mirror_dest->mirror_dest_id)) || 6203 (BCM_GPORT_MIRROR_GET(mirror_dest->mirror_dest_id) >= 6204 MIRROR_DEST_CONFIG_COUNT(unit))) { 6205 return (BCM_E_BADID); 6206 } 6207 6208 /* Check if mirror destination is being updated */ 6209 if (0 != MIRROR_DEST_REF_COUNT(unit, mirror_dest->mirror_dest_id)) { 6210 if (0 == (mirror_dest->flags & BCM_MIRROR_DEST_REPLACE)) { 6211 return (BCM_E_EXISTS); 6212 } 6213 } else { 6214 MIRROR_DEST_REF_COUNT(unit, mirror_dest->mirror_dest_id) = 1; 6215 } 6216 } else { 6217 /* Allocate new mirror destination. */ 6218 BCM_IF_ERROR_RETURN( 6219 _bcm_mirror_destination_alloc(unit, &mirror_dest->mirror_dest_id)); 6220 } 6221 6222 /* Set mirror destination configuration. */ 6223 6224 *(MIRROR_DEST(unit, mirror_dest->mirror_dest_id)) = *mirror_dest; 6225 (MIRROR_DEST(unit, mirror_dest->mirror_dest_id))->flags &= 6226 (BCM_MIRROR_DEST_TUNNELS | BCM_MIRROR_DEST_PAYLOAD_UNTAGGED | 6227 BCM_MIRROR_DEST_INT_PRI_SET | BCM_MIRROR_DEST_REPLACE | 6228 BCM_MIRROR_DEST_FIELD | BCM_MIRROR_DEST_PORT); 6229 6230 return (BCM_E_NONE); 6231 } 6232 6233 /* 6234 * Function: 6235 * _bcm_esw_mirror_ingress_get 6236 * Description: 6237 * Get the mirroring per ingress enabled/disabled status 6238 * Parameters: 6239 * unit - (IN) BCM device number 6240 * port - (IN) The port to check 6241 * enable - (OUT) Place to store boolean return value for on/off 6242 * Returns: 6243 * BCM_E_XXX 6244 */ 6245 STATIC int 6246 _bcm_esw_mirror_ingress_get(int unit, bcm_port_t port, int *enable) 6247 { 6248 int vp = VP_PORT_INVALID; 6249 bcm_module_t mod_out; 6250 bcm_trunk_t tgid_out; 6251 #ifdef BCM_TRIDENT2PLUS_SUPPORT 6252 int rv = BCM_E_NONE; 6253 #endif 6254 6255 #ifdef BCM_TRIDENT2PLUS_SUPPORT 6256 if (soc_feature(unit, soc_feature_hgproxy_subtag_coe) && 6257 _BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, port)) { 6258 if (!_bcm_xgs5_subport_coe_gport_local(unit, port)) { 6259 return BCM_E_PORT; 6260 } 6261 6262 PORT_LOCK(unit); 6263 rv = bcm_esw_port_lport_field_get(unit, port, LPORT_PROFILE_LPORT_TAB, 6264 MIRRORf, (uint32*)enable); 6265 PORT_UNLOCK(unit); 6266 if (BCM_FAILURE(rv)) { 6267 return rv; 6268 } 6269 } else 6270 #endif 6271 { 6272 if (BCM_GPORT_IS_SET(port)) { 6273 #if defined(BCM_TRIUMPH2_SUPPORT) && defined(INCLUDE_L3) 6274 #ifdef BCM_TRIDENT_SUPPORT 6275 if (BCM_GPORT_IS_NIV_PORT(port)) { 6276 bcm_niv_port_t niv_port; 6277 6278 bcm_niv_port_t_init(&niv_port); 6279 niv_port.niv_port_id = port; 6280 BCM_IF_ERROR_RETURN(bcm_trident_niv_port_get(unit, &niv_port)); 6281 if (niv_port.flags & BCM_NIV_PORT_MATCH_NONE) { 6282 /* getting vp is enough in this case */ 6283 vp = BCM_GPORT_NIV_PORT_ID_GET(port); 6284 if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeNiv)) { 6285 return BCM_E_NOT_FOUND; 6286 } 6287 } 6288 } else 6289 #endif /* BCM_TRIDENT_SUPPORT */ 6290 #ifdef BCM_TRIUMPH3_SUPPORT 6291 if (BCM_GPORT_IS_EXTENDER_PORT(port)) { 6292 bcm_extender_port_t extender_port; 6293 6294 bcm_extender_port_t_init(&extender_port); 6295 extender_port.extender_port_id = port; 6296 BCM_IF_ERROR_RETURN(bcm_tr3_extender_port_get(unit, &extender_port)); 6297 if (extender_port.flags & BCM_EXTENDER_PORT_MATCH_NONE) { 6298 /* getting vp is enough in this case */ 6299 vp = BCM_GPORT_EXTENDER_PORT_ID_GET(port); 6300 if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeExtender)) { 6301 return BCM_E_NOT_FOUND; 6302 } 6303 } 6304 } 6305 #endif /* BCM_TRIUMPH3_SUPPORT */ 6306 #endif /* BCM_TRIUMPH2_SUPPORT && INCLUDE_L3 */ 6307 6308 /* if VP has not been resolved */ 6309 if (VP_PORT_INVALID == vp){ 6310 BCM_IF_ERROR_RETURN( 6311 _bcm_esw_gport_resolve(unit, port, &mod_out, 6312 &port, &tgid_out, &vp)); 6313 } 6314 } 6315 6316 if (VP_PORT_INVALID != vp) { 6317 BCM_IF_ERROR_RETURN( 6318 _bcm_tr2_mirror_svp_enable_get(unit, vp, enable)); 6319 } else { 6320 BCM_IF_ERROR_RETURN( 6321 _bcm_port_mirror_enable_get(unit, port, enable)); 6322 } 6323 } 6324 6325 return BCM_E_NONE; 6326 } 6327 6328 6329 /* 6330 * Function: 6331 * _bcm_esw_mirror_ingress_set 6332 * Description: 6333 * Set the mirroring per ingress enabled/disabled status 6334 * Parameters: 6335 * unit - (IN) BCM device number 6336 * port - (IN) The port to check 6337 * enable - (IN) Place to store boolean return value for on/off 6338 * Returns: 6339 * BCM_E_XXX 6340 */ 6341 STATIC int 6342 _bcm_esw_mirror_ingress_set(int unit, bcm_port_t port, int enable) 6343 { 6344 int vp = VP_PORT_INVALID; 6345 bcm_module_t mod_out; 6346 bcm_trunk_t tgid_out; 6347 #ifdef BCM_TRIDENT2PLUS_SUPPORT 6348 int rv = BCM_E_NONE; 6349 #endif 6350 6351 #ifdef BCM_TRIDENT2PLUS_SUPPORT 6352 if (soc_feature(unit, soc_feature_hgproxy_subtag_coe) && 6353 _BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, port)) { 6354 if (!_bcm_xgs5_subport_coe_gport_local(unit, port)) { 6355 return BCM_E_PORT; 6356 } 6357 6358 PORT_LOCK(unit); 6359 rv = bcm_esw_port_lport_field_set(unit, port, LPORT_PROFILE_LPORT_TAB, 6360 MIRRORf, enable); 6361 PORT_UNLOCK(unit); 6362 if (BCM_FAILURE(rv)) { 6363 return rv; 6364 } 6365 } else 6366 #endif 6367 { 6368 if (BCM_GPORT_IS_SET(port)) { 6369 #if defined(BCM_TRIUMPH2_SUPPORT) && defined(INCLUDE_L3) 6370 #ifdef BCM_TRIDENT_SUPPORT 6371 if (BCM_GPORT_IS_NIV_PORT(port)) { 6372 bcm_niv_port_t niv_port; 6373 6374 bcm_niv_port_t_init(&niv_port); 6375 niv_port.niv_port_id = port; 6376 BCM_IF_ERROR_RETURN(bcm_trident_niv_port_get(unit, &niv_port)); 6377 if (niv_port.flags & BCM_NIV_PORT_MATCH_NONE) { 6378 /* getting vp is enough in this case */ 6379 vp = BCM_GPORT_NIV_PORT_ID_GET(port); 6380 if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeNiv)) { 6381 return BCM_E_NOT_FOUND; 6382 } 6383 } 6384 } else 6385 #endif /* BCM_TRIDENT_SUPPORT */ 6386 #ifdef BCM_TRIUMPH3_SUPPORT 6387 if (BCM_GPORT_IS_EXTENDER_PORT(port)) { 6388 bcm_extender_port_t extender_port; 6389 6390 bcm_extender_port_t_init(&extender_port); 6391 extender_port.extender_port_id = port; 6392 BCM_IF_ERROR_RETURN(bcm_tr3_extender_port_get(unit, &extender_port)); 6393 if (extender_port.flags & BCM_EXTENDER_PORT_MATCH_NONE) { 6394 /* getting vp is enough in this case */ 6395 vp = BCM_GPORT_EXTENDER_PORT_ID_GET(port); 6396 if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeExtender)) { 6397 return BCM_E_NOT_FOUND; 6398 } 6399 } 6400 } 6401 #endif /* BCM_TRIUMPH3_SUPPORT */ 6402 #endif /* BCM_TRIUMPH2_SUPPORT && INCLUDE_L3 */ 6403 6404 /* if VP has not been resolved */ 6405 if (VP_PORT_INVALID == vp){ 6406 BCM_IF_ERROR_RETURN( 6407 _bcm_esw_gport_resolve(unit, port, &mod_out, 6408 &port, &tgid_out, &vp)); 6409 } 6410 } 6411 6412 if (VP_PORT_INVALID != vp) { 6413 BCM_IF_ERROR_RETURN( 6414 _bcm_tr2_mirror_svp_enable_set(unit, vp, enable)); 6415 } else { 6416 BCM_IF_ERROR_RETURN( 6417 _bcm_port_mirror_enable_set(unit, port, enable)); 6418 } 6419 } 6420 6421 return BCM_E_NONE; 6422 } 6423 6424 #ifdef BCM_WARM_BOOT_SUPPORT 6425 6426 #define BCM_WB_VERSION_1_0 SOC_SCACHE_VERSION(1,0) 6427 #define BCM_WB_VERSION_1_1 SOC_SCACHE_VERSION(1,1) 6428 #define BCM_WB_VERSION_1_2 SOC_SCACHE_VERSION(1,2) 6429 #define BCM_WB_VERSION_1_3 SOC_SCACHE_VERSION(1,3) 6430 #define BCM_WB_VERSION_1_4 SOC_SCACHE_VERSION(1,4) 6431 #define BCM_WB_VERSION_1_5 SOC_SCACHE_VERSION(1,5) 6432 #define BCM_WB_VERSION_1_6 SOC_SCACHE_VERSION(1,6) 6433 #define BCM_WB_VERSION_1_7 SOC_SCACHE_VERSION(1,7) 6434 #define BCM_WB_VERSION_1_8 SOC_SCACHE_VERSION(1,8) 6435 #define BCM_WB_VERSION_1_9 SOC_SCACHE_VERSION(1,9) 6436 #define BCM_WB_VERSION_1_10 SOC_SCACHE_VERSION(1,10) 6437 #define BCM_WB_VERSION_1_11 SOC_SCACHE_VERSION(1,11) 6438 /* BCM_WB_VERSION_1_12 is to fix a trident3 specific warmboot issue. */ 6439 #define BCM_WB_VERSION_1_12 SOC_SCACHE_VERSION(1,12) 6440 #define BCM_WB_DEFAULT_VERSION BCM_WB_VERSION_1_12 6441 6442 /* 6443 * From SDK 6.5.16 release onward, will need to support partial-to-all and 6444 * all-to-partial warmboot. The WB_VERSION_1_7/1_11 will have problem with 6445 * this requirement on the non-TD3 devices. The WB_VERSION_1_12 is created 6446 * to deal with this problem as well as to ensure downgrade and upgrade 6447 * to/from previous SDK releases for all-to-all and partial-to-partial. 6448 * This is a TD3 specific issue. This flag is part of the fix indicating 6449 * the macro BCM_TRIDENT3_SUPPORT is defined for the given build. 6450 */ 6451 #define WB_MIRROR_FLAGS_TD3 1 6452 6453 6454 #ifdef BCM_TRX_SUPPORT 6455 STATIC int 6456 _bcm_esw_mirror_mtp_entry_trunk_get(int unit, void *mtp_entry, 6457 bcm_gport_t *port) 6458 { 6459 bcm_module_t tp_mod; 6460 bcm_port_t tp_port; 6461 bcm_gport_t tgid; 6462 int rv = BCM_E_NONE; 6463 6464 /* We're working with IM_MTP_INDEXm, but it is equivalent for 6465 * all of the .._MTP_INDEXm tables. */ 6466 if (soc_mem_field_valid(unit, IM_MTP_INDEXm, TGIDf)) { 6467 tgid = soc_IM_MTP_INDEXm_field32_get(unit, mtp_entry, TGIDf); 6468 } else { 6469 if (0 == soc_IM_MTP_INDEXm_field32_get(unit, mtp_entry, RTAGf)) { 6470 #ifdef BCM_METROLITE_SUPPORT 6471 if (SOC_IS_METROLITE(unit)) { 6472 tgid = soc_IM_MTP_INDEXm_field32_get(unit, mtp_entry, 6473 PORT_NUM_3f); 6474 } else 6475 #endif 6476 /* No ports in trunk, so the trunk id is cached */ 6477 if (soc_mem_field_valid(unit, IM_MTP_INDEXm, PORT_NUM_7f)) { 6478 tgid = soc_IM_MTP_INDEXm_field32_get(unit, mtp_entry, 6479 PORT_NUM_7f); 6480 } else { 6481 /* This case should not occur. */ 6482 return BCM_E_INTERNAL; 6483 } 6484 } else { 6485 tp_port = soc_IM_MTP_INDEXm_field32_get(unit, mtp_entry, PORT_NUMf); 6486 tp_mod = soc_IM_MTP_INDEXm_field32_get(unit, mtp_entry, MODULE_IDf); 6487 rv = _bcm_esw_trunk_port_property_get(unit, tp_mod, 6488 tp_port, &tgid); 6489 if (BCM_FAILURE(rv) || (tgid == -1)) { 6490 return rv; 6491 } 6492 } 6493 } 6494 6495 BCM_IF_ERROR_RETURN 6496 (_bcm_mirror_gport_construct(unit, tgid, 0, 6497 BCM_MIRROR_PORT_DEST_TRUNK, port)); 6498 return BCM_E_NONE; 6499 } 6500 #endif /* BCM_TRX_SUPPORT */ 6501 6502 int 6503 _bcm_esw_mirror_mtp_to_modport(int unit, int mtp_index, int modport, 6504 int flags, bcm_module_t *modid, 6505 bcm_gport_t *port) 6506 { 6507 im_mtp_index_entry_t im_mtp; 6508 em_mtp_index_entry_t em_mtp; 6509 6510 if (0 != (flags & BCM_MIRROR_PORT_INGRESS)) { 6511 BCM_IF_ERROR_RETURN 6512 (soc_mem_read(unit, IM_MTP_INDEXm, MEM_BLOCK_ALL, 6513 mtp_index, &im_mtp)); 6514 #ifdef BCM_TRX_SUPPORT 6515 #ifdef BCM_TOMAHAWK3_SUPPORT 6516 if (SOC_IS_TOMAHAWK3(unit)) { 6517 *port = soc_IM_MTP_INDEXm_field32_get(unit, &im_mtp, PORT_NUMf); 6518 *modid = 0; 6519 } else 6520 #endif /* BCM_TOMAHAWK3_SUPPORT */ 6521 if (soc_mem_field_valid(unit, IM_MTP_INDEXm, Tf)) { 6522 if (0 != soc_IM_MTP_INDEXm_field32_get(unit, &im_mtp, Tf)) { 6523 BCM_IF_ERROR_RETURN 6524 (_bcm_esw_mirror_mtp_entry_trunk_get(unit, &im_mtp, 6525 port)); 6526 *modid = 0; 6527 } else { 6528 *port = soc_IM_MTP_INDEXm_field32_get(unit, &im_mtp, 6529 PORT_NUMf); 6530 *modid = soc_IM_MTP_INDEXm_field32_get(unit, &im_mtp, 6531 MODULE_IDf); 6532 } 6533 } else 6534 #endif /* BCM_TRX_SUPPORT */ 6535 { 6536 *port = 6537 soc_IM_MTP_INDEXm_field32_get(unit, &im_mtp, PORT_TGIDf); 6538 *modid = 6539 soc_IM_MTP_INDEXm_field32_get(unit, &im_mtp, MODULE_IDf); 6540 } 6541 } else if (0 != (flags & BCM_MIRROR_PORT_EGRESS)) { 6542 BCM_IF_ERROR_RETURN 6543 (soc_mem_read(unit, EM_MTP_INDEXm, MEM_BLOCK_ALL, 6544 mtp_index, &em_mtp)); 6545 #ifdef BCM_TRX_SUPPORT 6546 #ifdef BCM_TOMAHAWK3_SUPPORT 6547 if (SOC_IS_TOMAHAWK3(unit)) { 6548 *port = soc_IM_MTP_INDEXm_field32_get(unit, &em_mtp, PORT_NUMf); 6549 *modid = 0; 6550 } else 6551 #endif /* BCM_TOMAHAWK3_SUPPORT */ 6552 if (soc_mem_field_valid(unit, EM_MTP_INDEXm, Tf)) { 6553 if (0 != soc_EM_MTP_INDEXm_field32_get(unit, &em_mtp, Tf)) { 6554 BCM_IF_ERROR_RETURN 6555 (_bcm_esw_mirror_mtp_entry_trunk_get(unit, &em_mtp, 6556 port)); 6557 *modid = 0; 6558 } else { 6559 *port = soc_EM_MTP_INDEXm_field32_get(unit, &em_mtp, 6560 PORT_NUMf); 6561 *modid = soc_EM_MTP_INDEXm_field32_get(unit, &em_mtp, 6562 MODULE_IDf); 6563 } 6564 } else 6565 #endif /* BCM_TRX_SUPPORT */ 6566 { 6567 *port = 6568 soc_EM_MTP_INDEXm_field32_get(unit, &em_mtp, PORT_TGIDf); 6569 *modid = 6570 soc_EM_MTP_INDEXm_field32_get(unit, &em_mtp, MODULE_IDf); 6571 } 6572 #ifdef BCM_TRIUMPH2_SUPPORT 6573 } else if (soc_feature(unit, soc_feature_egr_mirror_true) && 6574 (0 != (flags & BCM_MIRROR_PORT_EGRESS_TRUE))) { 6575 ep_redirect_em_mtp_index_entry_t epm_mtp; 6576 6577 BCM_IF_ERROR_RETURN 6578 (soc_mem_read(unit, EP_REDIRECT_EM_MTP_INDEXm, 6579 MEM_BLOCK_ALL, mtp_index, &epm_mtp)); 6580 if (0 != soc_EP_REDIRECT_EM_MTP_INDEXm_field32_get(unit, 6581 &epm_mtp, Tf)) { 6582 BCM_IF_ERROR_RETURN 6583 (_bcm_esw_mirror_mtp_entry_trunk_get(unit, &epm_mtp, 6584 port)); 6585 *modid = 0; 6586 } else { 6587 *port = soc_EP_REDIRECT_EM_MTP_INDEXm_field32_get(unit, &epm_mtp, 6588 PORT_NUMf); 6589 *modid = 6590 soc_EP_REDIRECT_EM_MTP_INDEXm_field32_get(unit, &epm_mtp, 6591 MODULE_IDf); 6592 } 6593 #endif /* BCM_TRIUMPH2_SUPPORT */ 6594 } else { 6595 return BCM_E_PARAM; 6596 } 6597 6598 if (!BCM_GPORT_IS_TRUNK(*port)) { 6599 if (modport) { 6600 /* Put into modport gport format */ 6601 BCM_IF_ERROR_RETURN 6602 (_bcm_mirror_gport_construct(unit, *port, *modid, 0, port)); 6603 } else { 6604 /* Translate into normalized (modport, port) form */ 6605 BCM_IF_ERROR_RETURN 6606 (_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET, 6607 *modid, *port, 6608 modid, port)); 6609 } 6610 } 6611 6612 return BCM_E_NONE; 6613 } 6614 6615 #ifdef BCM_FIELD_SUPPORT 6616 /* 6617 * Function: 6618 * _bcm_esw_mirror_field_group_reload 6619 * Purpose: 6620 * Used as a callback routine to traverse over field groups 6621 * Parameters: 6622 * unit - (IN) BCM device number. 6623 * group - (IN) Group id 6624 * user_data - (IN) User data pointer 6625 * Returns: 6626 * BCM_E_XXX 6627 */ 6628 STATIC int 6629 _bcm_esw_mirror_field_group_reload(int unit, bcm_field_group_t group, 6630 void *user_data) 6631 { 6632 int entry_count, entry_num; 6633 int alloc_sz, rv = BCM_E_NONE, flags, idx; 6634 bcm_field_entry_t *entry_array, entry_id; 6635 bcm_mirror_destination_t mirror_dest; 6636 bcm_gport_t gport; 6637 uint32 param0, param1; 6638 bcm_field_qset_t group_qset; 6639 6640 if (soc_feature(unit, soc_feature_mirror_flexible)) { 6641 return BCM_E_NONE; 6642 } 6643 6644 BCM_IF_ERROR_RETURN 6645 (bcm_esw_field_entry_multi_get(unit, group, 0, NULL, &entry_num)); 6646 if (entry_num == 0) { 6647 /* In Level 1 the FP may detect extra groups if a slice if the group 6648 PBMP is not ALL. These will come across as dummy groups with 6649 no entries. */ 6650 return BCM_E_NONE; 6651 } 6652 6653 alloc_sz = sizeof(bcm_field_entry_t) * entry_num; 6654 entry_array = sal_alloc(alloc_sz, "Field IDs"); 6655 if (NULL == entry_array) { 6656 return BCM_E_MEMORY; 6657 } 6658 sal_memset(entry_array, 0, alloc_sz); 6659 6660 rv = bcm_esw_field_entry_multi_get(unit, group, entry_num, 6661 entry_array, &entry_count); 6662 if (BCM_FAILURE(rv)) { 6663 sal_free(entry_array); 6664 return rv; 6665 } 6666 if (entry_count != entry_num) { 6667 /* Why didn't we get the number of ID's we were told existed? */ 6668 sal_free(entry_array); 6669 return BCM_E_INTERNAL; 6670 } 6671 6672 for (entry_count = 0; entry_count < entry_num; entry_count++) { 6673 entry_id = entry_array[entry_count]; 6674 rv = bcm_esw_field_action_get(unit, entry_id, 6675 bcmFieldActionMirrorIngress, 6676 ¶m0, ¶m1); 6677 if (BCM_SUCCESS(rv)) { 6678 gport = param1; 6679 if (!BCM_GPORT_IS_SET(gport)) { 6680 rv = _bcm_mirror_gport_construct(unit, param1, param0, 6681 0, &gport); 6682 if (BCM_FAILURE(rv)) { 6683 break; 6684 } 6685 } 6686 flags = BCM_MIRROR_PORT_INGRESS; 6687 bcm_mirror_destination_t_init(&mirror_dest); 6688 rv = _bcm_esw_mirror_destination_find(unit, gport, 0, 6689 flags, &mirror_dest); 6690 if (BCM_E_NOT_FOUND == rv) { 6691 rv = BCM_E_INTERNAL; 6692 /* Should have recovered the destination already. */ 6693 } 6694 if (BCM_FAILURE(rv)) { 6695 break; 6696 } 6697 if (soc_feature(unit, soc_feature_mirror_flexible)) { 6698 for (idx = 0; idx < BCM_MIRROR_MTP_COUNT; idx++) { 6699 if (mirror_dest.mirror_dest_id == 6700 MIRROR_CONFIG_SHARED_MTP_DEST(unit, idx) && 6701 !MIRROR_CONFIG_SHARED_MTP(unit, idx).egress) { 6702 break; 6703 } 6704 } 6705 if (idx < BCM_MIRROR_MTP_COUNT) { 6706 MIRROR_CONFIG_SHARED_MTP_REF_COUNT(unit, idx)++; 6707 MIRROR_DEST_REF_COUNT(unit, 6708 MIRROR_CONFIG_SHARED_MTP_DEST(unit, idx))++; 6709 /* If we found a mirror action, then mirroring is enabled */ 6710 MIRROR_CONFIG_MODE(unit) = BCM_MIRROR_L2; 6711 } else { 6712 rv = BCM_E_INTERNAL; 6713 break; 6714 } 6715 } else { 6716 for (idx = 0; idx < MIRROR_CONFIG(unit)->ing_mtp_count; idx++) { 6717 if (mirror_dest.mirror_dest_id == 6718 MIRROR_CONFIG_ING_MTP_DEST(unit, idx)) { 6719 break; 6720 } 6721 } 6722 if (idx < MIRROR_CONFIG(unit)->ing_mtp_count) { 6723 MIRROR_CONFIG_ING_MTP_REF_COUNT(unit, idx)++; 6724 MIRROR_DEST_REF_COUNT(unit, 6725 MIRROR_CONFIG_ING_MTP_DEST(unit, idx))++; 6726 /* If we found a mirror action, then mirroring is enabled */ 6727 MIRROR_CONFIG_MODE(unit) = BCM_MIRROR_L2; 6728 } else { 6729 rv = BCM_E_INTERNAL; 6730 break; 6731 } 6732 } 6733 } else if (rv != BCM_E_NOT_FOUND) { 6734 break; 6735 } else { 6736 LOG_VERBOSE(BSL_LS_BCM_FP, 6737 (BSL_META_U(unit, 6738 "Mirror module reload, ignore FP error report\n"))); 6739 } 6740 6741 rv = bcm_esw_field_action_get(unit, entry_id, 6742 bcmFieldActionMirrorEgress, 6743 ¶m0, ¶m1); 6744 if (BCM_SUCCESS(rv)) { 6745 gport = param1; 6746 if (!BCM_GPORT_IS_SET(gport)) { 6747 rv = _bcm_mirror_gport_construct(unit, param1, param0, 6748 0, &gport); 6749 if (BCM_FAILURE(rv)) { 6750 break; 6751 } 6752 } 6753 6754 /* Initialize the qset */ 6755 BCM_FIELD_QSET_INIT(group_qset); 6756 6757 /* Get the group Qset info */ 6758 rv = bcm_esw_field_group_get(unit, group, &group_qset); 6759 if (BCM_FAILURE(rv)) { 6760 break; 6761 } 6762 6763 /* Check if Mirroring is set for Egress Stage */ 6764 if (BCM_FIELD_QSET_TEST(group_qset, bcmFieldQualifyStageEgress)) { 6765 flags = BCM_MIRROR_PORT_EGRESS_TRUE; 6766 } else { 6767 flags = BCM_MIRROR_PORT_EGRESS; 6768 } 6769 6770 bcm_mirror_destination_t_init(&mirror_dest); 6771 rv = _bcm_esw_mirror_destination_find(unit, gport, 0, 6772 flags, &mirror_dest); 6773 if (BCM_E_NOT_FOUND == rv) { 6774 rv = BCM_E_INTERNAL; 6775 /* Should have recovered the destination already. */ 6776 } 6777 if (BCM_FAILURE(rv)) { 6778 break; 6779 } 6780 6781 if (flags & BCM_MIRROR_PORT_EGRESS_TRUE) { 6782 for (idx = 0; idx < BCM_MIRROR_MTP_COUNT; idx++) { 6783 if ((mirror_dest.mirror_dest_id 6784 == MIRROR_CONFIG_EGR_TRUE_MTP_DEST(unit, idx))) { 6785 break; 6786 } 6787 } 6788 if (idx < BCM_MIRROR_MTP_COUNT) { 6789 MIRROR_CONFIG_EGR_TRUE_MTP_REF_COUNT(unit, idx)++; 6790 MIRROR_DEST_REF_COUNT(unit, mirror_dest.mirror_dest_id)++; 6791 /* If we found a mirror action, then mirroring is enabled */ 6792 MIRROR_CONFIG_MODE(unit) = BCM_MIRROR_L2; 6793 } else { 6794 rv = BCM_E_INTERNAL; 6795 break; 6796 } 6797 } else if (soc_feature(unit, soc_feature_mirror_flexible)) { 6798 for (idx = 0; idx < BCM_MIRROR_MTP_COUNT; idx++) { 6799 if (mirror_dest.mirror_dest_id == 6800 MIRROR_CONFIG_SHARED_MTP_DEST(unit, idx) && 6801 MIRROR_CONFIG_SHARED_MTP(unit, idx).egress) { 6802 break; 6803 } 6804 } 6805 if (idx < BCM_MIRROR_MTP_COUNT) { 6806 MIRROR_CONFIG_SHARED_MTP_REF_COUNT(unit, idx) += 6807 (1 << BCM_MIRROR_MTP_REF_FP_OFFSET); 6808 MIRROR_DEST_REF_COUNT(unit, 6809 MIRROR_CONFIG_SHARED_MTP_DEST(unit, idx))++; 6810 /* If we found a mirror action, then mirroring is enabled */ 6811 MIRROR_CONFIG_MODE(unit) = BCM_MIRROR_L2; 6812 } else { 6813 rv = BCM_E_INTERNAL; 6814 break; 6815 } 6816 } else { 6817 for (idx = 0; idx < MIRROR_CONFIG(unit)->egr_mtp_count; idx++) { 6818 if (mirror_dest.mirror_dest_id == 6819 MIRROR_CONFIG_EGR_MTP_DEST(unit, idx)) { 6820 break; 6821 } 6822 } 6823 if (idx < MIRROR_CONFIG(unit)->egr_mtp_count) { 6824 MIRROR_CONFIG_EGR_MTP_REF_COUNT(unit, idx)++; 6825 MIRROR_DEST_REF_COUNT(unit, 6826 MIRROR_CONFIG_EGR_MTP_DEST(unit, idx))++; 6827 /* If we found a mirror action, then mirroring is enabled */ 6828 MIRROR_CONFIG_MODE(unit) = BCM_MIRROR_L2; 6829 } else { 6830 rv = BCM_E_INTERNAL; 6831 break; 6832 } 6833 } 6834 } else if (rv != BCM_E_NOT_FOUND) { 6835 break; 6836 } else { 6837 LOG_VERBOSE(BSL_LS_BCM_FP, 6838 (BSL_META_U(unit, 6839 "Mirror module reload, ignore FP error report\n"))); 6840 } 6841 } 6842 6843 if (BCM_E_NOT_FOUND == rv) { 6844 rv = BCM_E_NONE; /* Do not propagate this error */ 6845 } 6846 6847 sal_free(entry_array); 6848 return rv; 6849 } 6850 #endif /* BCM_FIELD_SUPPORT */ 6851 6852 6853 #ifdef BCM_XGS12_FABRIC_SUPPORT 6854 STATIC int 6855 _bcm_xgs12_fabric_mirror_reinit(int unit) 6856 { 6857 uint32 mirbmap; 6858 pbmp_t pbmp; 6859 bcm_port_t port; 6860 6861 PBMP_HG_ITER(unit, port) { 6862 SOC_IF_ERROR_RETURN(READ_ING_MIRTOBMAPr(unit, port, &mirbmap)); 6863 SOC_PBMP_CLEAR(pbmp); 6864 SOC_PBMP_WORD_SET(pbmp, 0, mirbmap); 6865 if (SOC_PBMP_NOT_NULL(pbmp)) { 6866 MIRROR_CONFIG(unit)->mode = BCM_MIRROR_L2; 6867 break; 6868 } 6869 } 6870 6871 /* 6872 * Cannot recover MTP info for 5675 6873 */ 6874 6875 return BCM_E_NONE; 6876 } 6877 #endif /* BCM_XGS12_FABRIC_SUPPORT */ 6878 6879 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_GREYHOUND_SUPPORT) 6880 6881 #ifdef BCM_TOMAHAWK3_SUPPORT 6882 /* 6883 * Function: 6884 * _bcm_th3_mirror_tunnel_reload 6885 * Purpose: 6886 * Restores mirroring tunnel destination encap info 6887 * for warm boot recovery 6888 * Parameters: 6889 * unit - (IN) BCM device number 6890 * mirror_dest - (IN) Mirror destination description 6891 * profile_index - (IN) Encap profile index 6892 * Returns: 6893 * BCM_E_XXX 6894 */ 6895 STATIC int 6896 _bcm_th3_mirror_tunnel_reload(int unit, bcm_mirror_destination_t *mirror_dest, 6897 bcm_gport_t dest_id, uint32 profile_index) 6898 { 6899 egr_mirror_encap_control_entry_t control_entry; 6900 egr_mirror_encap_data_1_entry_t data_1_entry; 6901 egr_mirror_encap_data_2_entry_t data_2_entry; 6902 void *entries[EGR_MIRROR_ENCAP_ENTRIES_NUM]; 6903 uint32 fldval; 6904 6905 entries[EGR_MIRROR_ENCAP_ENTRIES_CONTROL] = &control_entry; 6906 entries[EGR_MIRROR_ENCAP_ENTRIES_DATA_1] = &data_1_entry; 6907 entries[EGR_MIRROR_ENCAP_ENTRIES_DATA_2] = &data_2_entry; 6908 6909 /* Tunnel type */ 6910 BCM_IF_ERROR_RETURN(soc_profile_mem_get(unit, EGR_MIRROR_ENCAP(unit), 6911 profile_index, 1, entries)); 6912 6913 fldval = soc_EGR_MIRROR_ENCAP_CONTROLm_field32_get(unit, &control_entry, 6914 ENTRY_TYPEf); 6915 if ((fldval == _BCM_TH3_MIRROR_ENCAP_TYPE_SFLOW) || 6916 (fldval == _BCM_TH3_MIRROR_ENCAP_TYPE_SFLOW_SEQ)) { 6917 uint32 hw_buffer[_BCM_TH3_MIRROR_V4_BUFFER_SZ]; 6918 6919 /* SFLOW recovery */ 6920 soc_mem_mac_addr_get(unit, EGR_MIRROR_ENCAP_DATA_1m, 6921 &data_1_entry, SFLOW__SFLOW_HEADER_DAf, 6922 mirror_dest->dst_mac); 6923 soc_mem_mac_addr_get(unit, EGR_MIRROR_ENCAP_DATA_1m, 6924 &data_1_entry, SFLOW__SFLOW_HEADER_SAf, 6925 mirror_dest->src_mac); 6926 hw_buffer[0] = 6927 soc_EGR_MIRROR_ENCAP_DATA_1m_field32_get(unit, &data_1_entry, 6928 SFLOW__SFLOW_HEADER_VLAN_TAGf); 6929 mirror_dest->vlan_id = (bcm_vlan_t) (hw_buffer[0] & 0xFFFF); 6930 mirror_dest->tpid = (uint16) ((hw_buffer[0] >> 16) & 0xFFFF); 6931 soc_EGR_MIRROR_ENCAP_DATA_1m_field_get(unit, &data_1_entry, 6932 SFLOW__SFLOW_HEADER_V4f, hw_buffer); 6933 6934 mirror_dest->version = 4; 6935 mirror_dest->dst_addr = hw_buffer[0]; 6936 mirror_dest->src_addr = hw_buffer[1]; 6937 mirror_dest->ttl = (uint8) ((hw_buffer[2] >> 24) & 0xFF); 6938 mirror_dest->df = (uint8) ((hw_buffer[3] >> 14) & 0x1); 6939 mirror_dest->tos = (uint8) ((hw_buffer[4] >> 16) & 0xFF); 6940 6941 soc_EGR_MIRROR_ENCAP_DATA_1m_field_get(unit, &data_1_entry, 6942 SFLOW__SFLOW_HEADER_UDPf, hw_buffer); 6943 mirror_dest->udp_dst_port = hw_buffer[1] & 0xFFFF; 6944 mirror_dest->udp_src_port = (hw_buffer[1] >> 16) & 0xFFFF; 6945 6946 mirror_dest->flags |= BCM_MIRROR_DEST_TUNNEL_SFLOW; 6947 if (fldval == _BCM_TH3_MIRROR_ENCAP_TYPE_SFLOW_SEQ) { 6948 mirror_dest->flags |= BCM_MIRROR_DEST_TUNNEL_WITH_SEQ; 6949 } 6950 } else if ((fldval == _BCM_TH3_MIRROR_ENCAP_TYPE_SFLOW_V6) || 6951 (fldval == _BCM_TH3_MIRROR_ENCAP_TYPE_SFLOW_V6_SEQ)) { 6952 uint32 hw_buffer[_BCM_TH3_MIRROR_V6_GRE_BUFFER_SZ]; 6953 6954 soc_mem_mac_addr_get(unit, EGR_MIRROR_ENCAP_DATA_2m, 6955 &data_2_entry, SFLOW_V6__SFLOW_HEADER_DAf, 6956 mirror_dest->dst_mac); 6957 soc_mem_mac_addr_get(unit, EGR_MIRROR_ENCAP_DATA_2m, 6958 &data_2_entry, SFLOW_V6__SFLOW_HEADER_SAf, 6959 mirror_dest->src_mac); 6960 6961 mirror_dest->gre_protocol = 0; 6962 6963 hw_buffer[0] = 6964 soc_EGR_MIRROR_ENCAP_DATA_2m_field32_get(unit, &data_2_entry, 6965 SFLOW_V6__SFLOW_HEADER_VLAN_TAGf); 6966 6967 mirror_dest->vlan_id = (bcm_vlan_t)(hw_buffer[0] & 0xFFFF); 6968 mirror_dest->tpid = (uint16)((hw_buffer[0] >> 16) & 0xFFFF); 6969 6970 soc_EGR_MIRROR_ENCAP_DATA_1m_field_get(unit, &data_1_entry, 6971 SFLOW_V6__SFLOW_HEADER_V6f, hw_buffer); 6972 6973 mirror_dest->version = 6; 6974 mirror_dest->flow_label = hw_buffer[9] & 0xFFFFF; 6975 mirror_dest->tos = (uint8)((hw_buffer[9] >> 20) & 0xFF); 6976 6977 mirror_dest->ttl = (uint8)(hw_buffer[8] & 0xFF); 6978 6979 _BCM_TH3_IP6_ADDR_COPY_FROM(mirror_dest->src6_addr, hw_buffer[7]); 6980 _BCM_TH3_IP6_ADDR_COPY_FROM(mirror_dest->src6_addr + 4, hw_buffer[6]); 6981 _BCM_TH3_IP6_ADDR_COPY_FROM(mirror_dest->src6_addr + 8, hw_buffer[5]); 6982 _BCM_TH3_IP6_ADDR_COPY_FROM(mirror_dest->src6_addr + 12, hw_buffer[4]); 6983 6984 _BCM_TH3_IP6_ADDR_COPY_FROM(mirror_dest->dst6_addr, hw_buffer[3]); 6985 _BCM_TH3_IP6_ADDR_COPY_FROM(mirror_dest->dst6_addr + 4, hw_buffer[2]); 6986 _BCM_TH3_IP6_ADDR_COPY_FROM(mirror_dest->dst6_addr + 8, hw_buffer[1]); 6987 _BCM_TH3_IP6_ADDR_COPY_FROM(mirror_dest->dst6_addr + 12, hw_buffer[0]); 6988 6989 soc_EGR_MIRROR_ENCAP_DATA_1m_field_get(unit, &data_1_entry, 6990 SFLOW_V6__SFLOW_HEADER_UDPf, hw_buffer); 6991 mirror_dest->udp_dst_port = hw_buffer[1] & 0xFFFF; 6992 mirror_dest->udp_src_port = (hw_buffer[1] >> 16) & 0xFFFF; 6993 6994 mirror_dest->flags |= BCM_MIRROR_DEST_TUNNEL_SFLOW; 6995 if (fldval == _BCM_TH3_MIRROR_ENCAP_TYPE_SFLOW_V6_SEQ) { 6996 mirror_dest->flags |= BCM_MIRROR_DEST_TUNNEL_WITH_SEQ; 6997 } 6998 } else if ((fldval == _BCM_TH3_MIRROR_ENCAP_TYPE_PSAMP) || 6999 (fldval == _BCM_TH3_MIRROR_ENCAP_TYPE_PSAMP_FORMAT_2)) { 7000 uint32 hw_buffer[_BCM_TH3_MIRROR_V4_BUFFER_SZ]; 7001 7002 soc_mem_mac_addr_get(unit, EGR_MIRROR_ENCAP_DATA_1m, 7003 &data_1_entry, PSAMP__PSAMP_HEADER_DAf, 7004 mirror_dest->dst_mac); 7005 soc_mem_mac_addr_get(unit, EGR_MIRROR_ENCAP_DATA_1m, 7006 &data_1_entry, PSAMP__PSAMP_HEADER_SAf, 7007 mirror_dest->src_mac); 7008 hw_buffer[0] = 7009 soc_EGR_MIRROR_ENCAP_DATA_1m_field32_get(unit, &data_1_entry, 7010 PSAMP__PSAMP_HEADER_VLAN_TAGf); 7011 mirror_dest->vlan_id = (bcm_vlan_t) (hw_buffer[0] & 0xFFFF); 7012 mirror_dest->tpid = (uint16) ((hw_buffer[0] >> 16) & 0xFFFF); 7013 soc_EGR_MIRROR_ENCAP_DATA_1m_field_get(unit, &data_1_entry, 7014 PSAMP__PSAMP_HEADER_V4f, hw_buffer); 7015 7016 mirror_dest->version = 4; 7017 mirror_dest->dst_addr = hw_buffer[0]; 7018 mirror_dest->src_addr = hw_buffer[1]; 7019 mirror_dest->ttl = (uint8) ((hw_buffer[2] >> 24) & 0xFF); 7020 mirror_dest->df = (uint8) ((hw_buffer[3] >> 14) & 0x1); 7021 mirror_dest->tos = (uint8) ((hw_buffer[4] >> 16) & 0xFF); 7022 7023 /* Recover UDP values */ 7024 soc_EGR_MIRROR_ENCAP_DATA_1m_field_get(unit, &data_1_entry, 7025 PSAMP__PSAMP_HEADER_UDPf, hw_buffer); 7026 mirror_dest->udp_dst_port = hw_buffer[1] & 0xFFFF; 7027 mirror_dest->udp_src_port = (hw_buffer[1] >> 16) & 0xFFFF; 7028 7029 /* Recover obs and template ids */ 7030 mirror_dest->observation_domain = 7031 soc_EGR_MIRROR_ENCAP_DATA_2m_field32_get(unit, &data_2_entry, 7032 PSAMP__OBSERVATION_IDf); 7033 7034 mirror_dest->template_id = 7035 soc_EGR_MIRROR_ENCAP_DATA_2m_field32_get(unit, &data_2_entry, 7036 PSAMP__TEMPLATE_IDf); 7037 7038 mirror_dest->flags |= BCM_MIRROR_DEST_TUNNEL_PSAMP; 7039 if (fldval == _BCM_TH3_MIRROR_ENCAP_TYPE_PSAMP_FORMAT_2) { 7040 mirror_dest->flags2 |= BCM_MIRROR_DEST_FLAGS2_PSAMP_FORMAT_2; 7041 } 7042 7043 } else if ((fldval == _BCM_TH3_MIRROR_ENCAP_TYPE_PSAMP_V6) || 7044 (fldval == _BCM_TH3_MIRROR_ENCAP_TYPE_PSAMP_FORMAT_2_V6)) { 7045 uint32 hw_buffer[_BCM_TH3_MIRROR_V6_GRE_BUFFER_SZ]; 7046 7047 soc_mem_mac_addr_get(unit, EGR_MIRROR_ENCAP_DATA_2m, 7048 &data_2_entry, PSAMP_V6__PSAMP_HEADER_DAf, 7049 mirror_dest->dst_mac); 7050 soc_mem_mac_addr_get(unit, EGR_MIRROR_ENCAP_DATA_2m, 7051 &data_2_entry, PSAMP_V6__PSAMP_HEADER_SAf, 7052 mirror_dest->src_mac); 7053 7054 mirror_dest->gre_protocol = 0; 7055 7056 hw_buffer[0] = 7057 soc_EGR_MIRROR_ENCAP_DATA_2m_field32_get(unit, &data_2_entry, 7058 PSAMP_V6__PSAMP_HEADER_VLAN_TAGf); 7059 7060 mirror_dest->vlan_id = (bcm_vlan_t)(hw_buffer[0] & 0xFFFF); 7061 mirror_dest->tpid = (uint16)((hw_buffer[0] >> 16) & 0xFFFF); 7062 7063 soc_EGR_MIRROR_ENCAP_DATA_1m_field_get(unit, &data_1_entry, 7064 PSAMP_V6__PSAMP_HEADER_V6f, hw_buffer); 7065 7066 mirror_dest->version = 6; 7067 mirror_dest->flow_label = hw_buffer[9] & 0xFFFFF; 7068 mirror_dest->tos = (uint8)((hw_buffer[9] >> 20) & 0xFF); 7069 7070 mirror_dest->ttl = (uint8)(hw_buffer[8] & 0xFF); 7071 7072 _BCM_TH3_IP6_ADDR_COPY_FROM(mirror_dest->src6_addr, hw_buffer[7]); 7073 _BCM_TH3_IP6_ADDR_COPY_FROM(mirror_dest->src6_addr + 4, hw_buffer[6]); 7074 _BCM_TH3_IP6_ADDR_COPY_FROM(mirror_dest->src6_addr + 8, hw_buffer[5]); 7075 _BCM_TH3_IP6_ADDR_COPY_FROM(mirror_dest->src6_addr + 12, hw_buffer[4]); 7076 7077 _BCM_TH3_IP6_ADDR_COPY_FROM(mirror_dest->dst6_addr, hw_buffer[3]); 7078 _BCM_TH3_IP6_ADDR_COPY_FROM(mirror_dest->dst6_addr + 4, hw_buffer[2]); 7079 _BCM_TH3_IP6_ADDR_COPY_FROM(mirror_dest->dst6_addr + 8, hw_buffer[1]); 7080 _BCM_TH3_IP6_ADDR_COPY_FROM(mirror_dest->dst6_addr + 12, hw_buffer[0]); 7081 7082 /* Recover UDP values */ 7083 soc_EGR_MIRROR_ENCAP_DATA_1m_field_get(unit, &data_1_entry, 7084 PSAMP_V6__PSAMP_HEADER_UDPf, hw_buffer); 7085 7086 mirror_dest->udp_dst_port = hw_buffer[1] & 0xFFFF; 7087 mirror_dest->udp_src_port = (hw_buffer[1] >> 16) & 0xFFFF; 7088 7089 /* Recover obs and template ids */ 7090 mirror_dest->observation_domain = 7091 soc_EGR_MIRROR_ENCAP_DATA_2m_field32_get(unit, &data_2_entry, 7092 PSAMP_V6__OBSERVATION_IDf); 7093 7094 mirror_dest->template_id = 7095 soc_EGR_MIRROR_ENCAP_DATA_2m_field32_get(unit, &data_2_entry, 7096 PSAMP_V6__TEMPLATE_IDf); 7097 7098 mirror_dest->flags |= BCM_MIRROR_DEST_TUNNEL_PSAMP; 7099 if (fldval == _BCM_TH3_MIRROR_ENCAP_TYPE_PSAMP_FORMAT_2_V6) { 7100 mirror_dest->flags2 |= BCM_MIRROR_DEST_FLAGS2_PSAMP_FORMAT_2; 7101 } 7102 } else if (fldval == _BCM_TH3_MIRROR_ENCAP_TYPE_ERSPAN) { 7103 uint32 hw_buffer[_BCM_TD_MIRROR_V4_GRE_BUFFER_SZ]; 7104 7105 /* ERSPAN v4 recovery */ 7106 soc_mem_mac_addr_get(unit, EGR_MIRROR_ENCAP_DATA_1m, 7107 &data_1_entry, ERSPAN__ERSPAN_HEADER_DAf, 7108 mirror_dest->dst_mac); 7109 soc_mem_mac_addr_get(unit, EGR_MIRROR_ENCAP_DATA_1m, 7110 &data_1_entry, ERSPAN__ERSPAN_HEADER_SAf, 7111 mirror_dest->src_mac); 7112 7113 mirror_dest->gre_protocol = 7114 soc_EGR_MIRROR_ENCAP_DATA_1m_field32_get(unit, &data_1_entry, 7115 ERSPAN__ERSPAN_HEADER_GREf); 7116 7117 hw_buffer[0] = 7118 soc_EGR_MIRROR_ENCAP_DATA_1m_field32_get(unit, &data_1_entry, 7119 ERSPAN__ERSPAN_HEADER_VLAN_TAGf); 7120 7121 mirror_dest->vlan_id = (bcm_vlan_t) (hw_buffer[0] & 0xFFFF); 7122 mirror_dest->tpid = (uint16) ((hw_buffer[0] >> 16) & 0xFFFF); 7123 7124 soc_EGR_MIRROR_ENCAP_DATA_1m_field_get(unit, &data_1_entry, 7125 ERSPAN__ERSPAN_HEADER_V4f, hw_buffer); 7126 /* See _bcm_trident_mirror_ipv4_gre_tunnel_set for the encoding */ 7127 mirror_dest->version = 4; 7128 mirror_dest->dst_addr = hw_buffer[0]; 7129 mirror_dest->src_addr = hw_buffer[1]; 7130 mirror_dest->ttl = (uint8) ((hw_buffer[2] >> 24) & 0xFF); 7131 mirror_dest->df = (uint8) ((hw_buffer[3] >> 14) & 0x1); 7132 mirror_dest->tos = (uint8) ((hw_buffer[4] >> 16) & 0xFF); 7133 7134 mirror_dest->flags |= BCM_MIRROR_DEST_TUNNEL_IP_GRE; 7135 } else if (fldval == _BCM_TH3_MIRROR_ENCAP_TYPE_ERSPAN_V6) { 7136 uint32 hw_buffer[_BCM_TH3_MIRROR_V6_GRE_BUFFER_SZ]; 7137 7138 /* ERSPAN v6 recovery */ 7139 soc_mem_mac_addr_get(unit, EGR_MIRROR_ENCAP_DATA_2m, 7140 &data_2_entry, ERSPAN_V6__ERSPAN_HEADER_DAf, 7141 mirror_dest->dst_mac); 7142 soc_mem_mac_addr_get(unit, EGR_MIRROR_ENCAP_DATA_2m, 7143 &data_2_entry, ERSPAN_V6__ERSPAN_HEADER_SAf, 7144 mirror_dest->src_mac); 7145 7146 mirror_dest->gre_protocol = 7147 soc_EGR_MIRROR_ENCAP_DATA_1m_field32_get(unit, &data_1_entry, 7148 ERSPAN_V6__ERSPAN_HEADER_GREf); 7149 hw_buffer[0] = 7150 soc_EGR_MIRROR_ENCAP_DATA_2m_field32_get(unit, &data_2_entry, 7151 ERSPAN_V6__ERSPAN_HEADER_VLAN_TAGf); 7152 7153 mirror_dest->vlan_id = (bcm_vlan_t)(hw_buffer[0] & 0xFFFF); 7154 mirror_dest->tpid = (uint16)((hw_buffer[0] >> 16) & 0xFFFF); 7155 7156 soc_EGR_MIRROR_ENCAP_DATA_1m_field_get(unit, &data_1_entry, 7157 ERSPAN_V6__ERSPAN_HEADER_V6f, hw_buffer); 7158 /* See _bcm_tomahawk3_mirror_ipv6_gre_tunnel_set for the encoding */ 7159 mirror_dest->version = 6; 7160 mirror_dest->flow_label = hw_buffer[9] & 0xFFFFF; 7161 mirror_dest->tos = (uint8)((hw_buffer[9] >> 20) & 0xFF); 7162 7163 mirror_dest->ttl = (uint8)(hw_buffer[8] & 0xFF); 7164 7165 _BCM_TH3_IP6_ADDR_COPY_FROM(mirror_dest->src6_addr, hw_buffer[7]); 7166 _BCM_TH3_IP6_ADDR_COPY_FROM(mirror_dest->src6_addr + 4, hw_buffer[6]); 7167 _BCM_TH3_IP6_ADDR_COPY_FROM(mirror_dest->src6_addr + 8, hw_buffer[5]); 7168 _BCM_TH3_IP6_ADDR_COPY_FROM(mirror_dest->src6_addr + 12, hw_buffer[4]); 7169 7170 _BCM_TH3_IP6_ADDR_COPY_FROM(mirror_dest->dst6_addr, hw_buffer[3]); 7171 _BCM_TH3_IP6_ADDR_COPY_FROM(mirror_dest->dst6_addr + 4, hw_buffer[2]); 7172 _BCM_TH3_IP6_ADDR_COPY_FROM(mirror_dest->dst6_addr + 8, hw_buffer[1]); 7173 _BCM_TH3_IP6_ADDR_COPY_FROM(mirror_dest->dst6_addr + 12, hw_buffer[0]); 7174 7175 mirror_dest->flags |= BCM_MIRROR_DEST_TUNNEL_IP_GRE; 7176 } else { 7177 uint32 hw_buffer[_BCM_TH3_MIRROR_V4_BUFFER_SZ]; 7178 7179 /* RSPAN recovery */ 7180 hw_buffer[0] = 7181 soc_EGR_MIRROR_ENCAP_DATA_1m_field32_get( 7182 unit, &data_1_entry, RSPAN__RSPAN_VLAN_TAGf); 7183 7184 mirror_dest->vlan_id = (bcm_vlan_t) (hw_buffer[0] & 0xffff); 7185 mirror_dest->tpid = (uint16) ((hw_buffer[0] >> 16) & 0xffff); 7186 7187 mirror_dest->flags |= BCM_MIRROR_DEST_TUNNEL_L2; 7188 } 7189 7190 if ((fldval == _BCM_TH3_MIRROR_ENCAP_TYPE_PSAMP_FORMAT_2_V6) || 7191 (fldval == _BCM_TH3_MIRROR_ENCAP_TYPE_PSAMP_FORMAT_2) || 7192 (fldval == _BCM_TH3_MIRROR_ENCAP_TYPE_SFLOW_SEQ) || 7193 (fldval == _BCM_TH3_MIRROR_ENCAP_TYPE_SFLOW_V6_SEQ)) { 7194 egr_mirror_user_meta_data_entry_t entry; 7195 uint32 type; 7196 uint32 data; 7197 soc_mem_t mem = EGR_MIRROR_USER_META_DATAm; 7198 7199 sal_memset((void *)&entry, 0, 7200 sizeof(egr_mirror_user_meta_data_entry_t)); 7201 7202 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ANY, 7203 profile_index, &entry)); 7204 7205 type = soc_mem_field32_get(unit, mem, &entry, 7206 USER_META_OR_CLASS_IDf); 7207 7208 if (type == bcmMirrorPsampFmt2HeaderUserMeta) { 7209 data = soc_mem_field32_get(unit, mem, &entry, 7210 USER_META_DATAf); 7211 } else { 7212 data = 0; 7213 } 7214 7215 mirror_dest->meta_data_type = (bcm_mirror_psamp_fmt2_meta_data_t)type; 7216 mirror_dest->meta_data = (uint16)(data & 0xFFFF); 7217 } 7218 7219 return BCM_E_NONE; 7220 } 7221 #endif /* BCM_TOMAHAWK3_SUPPORT */ 7222 7223 /* 7224 * Function: 7225 * _bcm_td_mirror_tunnel_reload 7226 * Purpose: 7227 * Restores mirroring tunnel destination encap info 7228 * for warm boot recovery 7229 * Parameters: 7230 * unit - (IN) BCM device number. 7231 * mirror_dest - (IN) Mirror destination description. 7232 * profile_index - (IN) Encap profile index 7233 * Returns: 7234 * BCM_E_XXX 7235 */ 7236 STATIC int 7237 _bcm_td_mirror_tunnel_reload(int unit, bcm_mirror_destination_t *mirror_dest, 7238 bcm_gport_t dest_id, uint32 profile_index) 7239 { 7240 egr_mirror_encap_control_entry_t control_entry; 7241 egr_mirror_encap_data_1_entry_t data_1_entry; 7242 egr_mirror_encap_data_2_entry_t data_2_entry; 7243 void *entries[EGR_MIRROR_ENCAP_ENTRIES_NUM]; 7244 int optional_header; 7245 uint32 hw_buffer[_BCM_TD_MIRROR_V4_GRE_BUFFER_SZ]; /* Max size needed */ 7246 7247 #ifdef BCM_TRIDENT3_SUPPORT 7248 if (SOC_IS_TRIDENT3X(unit)) { 7249 return (_bcm_td3_mirror_tunnel_reload(unit, dest_id, profile_index)); 7250 } 7251 #endif /* BCM_TRIDENT3_SUPPORT */ 7252 7253 #ifdef BCM_TOMAHAWK3_SUPPORT 7254 if (SOC_IS_TOMAHAWK3(unit)) { 7255 return (_bcm_th3_mirror_tunnel_reload(unit, mirror_dest, dest_id, 7256 profile_index)); 7257 } 7258 #endif /* BCM_TOMAHAWK3_SUPPORT */ 7259 7260 entries[EGR_MIRROR_ENCAP_ENTRIES_CONTROL] = &control_entry; 7261 entries[EGR_MIRROR_ENCAP_ENTRIES_DATA_1] = &data_1_entry; 7262 entries[EGR_MIRROR_ENCAP_ENTRIES_DATA_2] = &data_2_entry; 7263 7264 /* Tunnel type? */ 7265 BCM_IF_ERROR_RETURN 7266 (soc_profile_mem_get(unit, EGR_MIRROR_ENCAP(unit), 7267 profile_index, 1, entries)); 7268 7269 optional_header = 7270 soc_EGR_MIRROR_ENCAP_CONTROLm_field32_get(unit, &control_entry, 7271 RSPAN__ADD_OPTIONAL_HEADERf); 7272 if (soc_EGR_MIRROR_ENCAP_CONTROLm_field32_get(unit, &control_entry, 7273 ENTRY_TYPEf) == BCM_TD_MIRROR_ENCAP_TYPE_SFLOW) { 7274 /* SFLOW recovery */ 7275 soc_mem_mac_addr_get(unit, EGR_MIRROR_ENCAP_DATA_1m, 7276 &data_1_entry, SFLOW__SFLOW_HEADER_DAf, 7277 mirror_dest->dst_mac); 7278 soc_mem_mac_addr_get(unit, EGR_MIRROR_ENCAP_DATA_1m, 7279 &data_1_entry, SFLOW__SFLOW_HEADER_SAf, 7280 mirror_dest->src_mac); 7281 hw_buffer[0] = 7282 soc_EGR_MIRROR_ENCAP_DATA_1m_field32_get(unit, &data_1_entry, 7283 SFLOW__SFLOW_HEADER_VLAN_TAGf); 7284 mirror_dest->vlan_id = (bcm_vlan_t) (hw_buffer[0] & 0xffff); 7285 mirror_dest->tpid = (uint16) ((hw_buffer[0] >> 16) & 0xffff); 7286 soc_EGR_MIRROR_ENCAP_DATA_1m_field_get(unit, &data_1_entry, 7287 SFLOW__SFLOW_HEADER_V4f, hw_buffer); 7288 7289 /* See _bcm_trident_mirror_ipv4_gre_tunnel_set for the encoding */ 7290 mirror_dest->version = 4; 7291 mirror_dest->dst_addr = hw_buffer[0]; 7292 mirror_dest->src_addr = hw_buffer[1]; 7293 mirror_dest->ttl = (uint8) ((hw_buffer[2] >> 24) & 0xff); 7294 mirror_dest->df = (uint8) ((hw_buffer[3] >> 14) & 0x1); 7295 mirror_dest->tos = (uint8) ((hw_buffer[4] >> 16) & 0xff); 7296 7297 soc_EGR_MIRROR_ENCAP_DATA_1m_field_get(unit, &data_1_entry, 7298 SFLOW__SFLOW_HEADER_UDPf, hw_buffer); 7299 mirror_dest->udp_dst_port = hw_buffer[1] & 0xffff; 7300 mirror_dest->udp_src_port = (hw_buffer[1] >> 16) & 0xffff; 7301 7302 mirror_dest->flags |= BCM_MIRROR_DEST_TUNNEL_SFLOW; 7303 7304 } else if (soc_EGR_MIRROR_ENCAP_CONTROLm_field32_get(unit, &control_entry, 7305 ENTRY_TYPEf) == BCM_TD_MIRROR_ENCAP_TYPE_ERSPAN) { 7306 /* ERSPAN recovery */ 7307 soc_mem_mac_addr_get(unit, EGR_MIRROR_ENCAP_DATA_1m, 7308 &data_1_entry, ERSPAN__ERSPAN_HEADER_DAf, 7309 mirror_dest->dst_mac); 7310 soc_mem_mac_addr_get(unit, EGR_MIRROR_ENCAP_DATA_1m, 7311 &data_1_entry, ERSPAN__ERSPAN_HEADER_SAf, 7312 mirror_dest->src_mac); 7313 7314 mirror_dest->gre_protocol = 7315 soc_EGR_MIRROR_ENCAP_DATA_1m_field32_get(unit, &data_1_entry, 7316 ERSPAN__ERSPAN_HEADER_GREf); 7317 7318 hw_buffer[0] = 7319 soc_EGR_MIRROR_ENCAP_DATA_1m_field32_get(unit, &data_1_entry, 7320 ERSPAN__ERSPAN_HEADER_VLAN_TAGf); 7321 7322 mirror_dest->vlan_id = (bcm_vlan_t) (hw_buffer[0] & 0xffff); 7323 mirror_dest->tpid = (uint16) ((hw_buffer[0] >> 16) & 0xffff); 7324 7325 soc_EGR_MIRROR_ENCAP_DATA_1m_field_get(unit, &data_1_entry, 7326 ERSPAN__ERSPAN_HEADER_V4f, hw_buffer); 7327 /* See _bcm_trident_mirror_ipv4_gre_tunnel_set for the encoding */ 7328 mirror_dest->version = 4; 7329 mirror_dest->dst_addr = hw_buffer[0]; 7330 mirror_dest->src_addr = hw_buffer[1]; 7331 mirror_dest->ttl = (uint8) ((hw_buffer[2] >> 24) & 0xff); 7332 mirror_dest->df = (uint8) ((hw_buffer[3] >> 14) & 0x1); 7333 mirror_dest->tos = (uint8) ((hw_buffer[4] >> 16) & 0xff); 7334 7335 mirror_dest->flags |= BCM_MIRROR_DEST_TUNNEL_IP_GRE; 7336 } else { 7337 /* RSPAN recovery */ 7338 if (BCM_TD_MIRROR_HEADER_ONLY == optional_header) { 7339 hw_buffer[0] = 7340 soc_EGR_MIRROR_ENCAP_DATA_1m_field32_get( 7341 unit, &data_1_entry, RSPAN__RSPAN_VLAN_TAGf); 7342 7343 mirror_dest->vlan_id = (bcm_vlan_t) (hw_buffer[0] & 0xffff); 7344 mirror_dest->tpid = (uint16) ((hw_buffer[0] >> 16) & 0xffff); 7345 7346 mirror_dest->flags |= BCM_MIRROR_DEST_TUNNEL_L2; 7347 } 7348 } 7349 7350 if (BCM_TD_MIRROR_HEADER_TRILL == optional_header) { 7351 /* TRILL recovery */ 7352 soc_EGR_MIRROR_ENCAP_DATA_2m_field_get(unit, &data_2_entry, 7353 HEADER_DATAf, hw_buffer); 7354 7355 mirror_dest->trill_dst_name = 7356 (hw_buffer[0] >> BCM_TD_MIRROR_TRILL_DEST_NAME_OFFSET) & 7357 _BCM_TD_MIRROR_TRILL_NAME_MASK; 7358 mirror_dest->trill_src_name = 7359 (hw_buffer[1] & _BCM_TD_MIRROR_TRILL_NAME_MASK); 7360 mirror_dest->trill_hopcount = 7361 ((hw_buffer[1] >> BCM_TD_MIRROR_TRILL_HOPCOUNT_OFFSET) & 7362 _BCM_TD_MIRROR_TRILL_HOPCOUNT_MASK); 7363 7364 mirror_dest->flags |= BCM_MIRROR_DEST_TUNNEL_TRILL; 7365 } else if (BCM_TD_MIRROR_HEADER_VNTAG == optional_header) { 7366 /* NIV recovery */ 7367 hw_buffer[0] = 7368 soc_EGR_MIRROR_ENCAP_DATA_2m_field32_get(unit, &data_2_entry, 7369 VNTAG_HEADERf); 7370 7371 if (0 != (hw_buffer[0] & _BCM_TD_MIRROR_NIV_LOOP_BIT)) { 7372 mirror_dest->niv_flags = BCM_MIRROR_NIV_LOOP; 7373 } 7374 7375 mirror_dest->niv_src_vif = 7376 (hw_buffer[0] & _BCM_TD_MIRROR_NIV_SRC_VIF_MASK); 7377 mirror_dest->niv_dst_vif = 7378 ((hw_buffer[0] >> _BCM_TD_MIRROR_NIV_DST_VIF_OFFSET) & 7379 _BCM_TD_MIRROR_NIV_DST_VIF_MASK); 7380 7381 mirror_dest->flags |= BCM_MIRROR_DEST_TUNNEL_NIV; 7382 } else if (BCM_MIRROR_HEADER_ETAG == optional_header) { 7383 if(soc_feature(unit, soc_feature_port_extension)) { 7384 /* ETAG recovery */ 7385 soc_EGR_MIRROR_ENCAP_DATA_2m_field_get(unit, &data_2_entry, 7386 HEADER_DATAf, hw_buffer); 7387 7388 mirror_dest->etag_dst_vid = 7389 (hw_buffer[0] & _BCM_MIRROR_ETAG_DST_VID_MASK); 7390 mirror_dest->etag_src_vid = 7391 ((hw_buffer[0] >> _BCM_MIRROR_ETAG_SRC_VID_OFFSET) & 7392 _BCM_MIRROR_ETAG_SRC_VID_MASK); 7393 7394 mirror_dest->flags |= BCM_MIRROR_DEST_TUNNEL_ETAG; 7395 } 7396 } /* Else no additional header to recover */ 7397 7398 return BCM_E_NONE; 7399 } 7400 #endif /* BCM_TRIDENT_SUPPORT || BCM_GREYHOUND_SUPPORT */ 7401 7402 /* 7403 * Function: 7404 * _bcm_mirror_sflow_mtp_ref_count_recover 7405 * Purpose: 7406 * Restores virtual port mtp usage reference counts for warm boot recovery 7407 * Parameters: 7408 * unit - (IN) BCM device number. 7409 * Returns: 7410 * BCM_E_XXX 7411 */ 7412 7413 STATIC int 7414 _bcm_mirror_sflow_mtp_ref_count_recover(int unit) 7415 { 7416 #if defined(BCM_TOMAHAWK_SUPPORT) 7417 uint32 reg_val; 7418 int mc_enable; 7419 int mtp_index; 7420 int mtp_slot, mtp_bit; 7421 int i; 7422 uint32 index_val[BCM_MIRROR_MTP_COUNT]; 7423 soc_field_t mtp_idxf[BCM_MIRROR_MTP_COUNT] = { 7424 MTP_INDEX0f,MTP_INDEX1f,MTP_INDEX2f,MTP_INDEX3f}; 7425 7426 if (!soc_feature(unit, soc_feature_sflow_ing_mirror)) { 7427 return BCM_E_NONE; 7428 } 7429 7430 BCM_IF_ERROR_RETURN(READ_SFLOW_ING_MIRROR_CONFIGr(unit, ®_val)); 7431 mc_enable = soc_reg_field_get(unit, SFLOW_ING_MIRROR_CONFIGr, 7432 reg_val, MIRROR_ENABLEf); 7433 7434 /* Read mirror control structure to get programmed mtp indexes. */ 7435 for (i = 0; i < BCM_MIRROR_MTP_COUNT; i++) { 7436 index_val[i] = soc_reg_field_get(unit, SFLOW_ING_MIRROR_CONFIGr, 7437 reg_val, mtp_idxf[i]); 7438 } 7439 /* Read mirror control register to check if mtp index is used. */ 7440 for (mtp_slot = 0; mtp_slot < BCM_MIRROR_MTP_COUNT; 7441 mtp_slot++) { 7442 7443 mtp_bit = 1 << mtp_slot; 7444 /* Check if MTP slot is enabled on port */ 7445 if (!(mc_enable & mtp_bit)) { 7446 continue; 7447 } 7448 /* MTP index is enabled and direction matches */ 7449 mtp_index = index_val[mtp_slot]; 7450 7451 if (!MIRROR_MTP_METHOD_IS_DIRECTED_FLEXIBLE(unit)) { 7452 MIRROR_CONFIG_SHARED_MTP_REF_COUNT(unit, mtp_index)++; 7453 MIRROR_DEST_REF_COUNT(unit, 7454 MIRROR_CONFIG_SHARED_MTP_DEST(unit, mtp_index))++; 7455 } 7456 } 7457 return BCM_E_NONE; 7458 #else 7459 return BCM_E_NONE; 7460 #endif 7461 } 7462 7463 /* 7464 * Function: 7465 * _bcm_mirror_vp_mtp_ref_count_recover 7466 * Purpose: 7467 * Restores virtual port mtp usage reference counts for warm boot recovery 7468 * Parameters: 7469 * unit - (IN) BCM device number. 7470 * Returns: 7471 * BCM_E_XXX 7472 */ 7473 7474 STATIC int 7475 _bcm_mirror_vp_mtp_ref_count_recover(int unit) 7476 { 7477 uint8 *mem_buf = NULL; 7478 int i, index_min, index_max; 7479 int mirror_enable; 7480 int rv; 7481 soc_mem_t mem; 7482 int j; 7483 void *entry_ptr; 7484 int mtp_index; 7485 struct { 7486 soc_mem_t mem; 7487 soc_field_t field; 7488 int egress; 7489 } vp_mirror[2]; 7490 7491 vp_mirror[0].mem = SOURCE_VPm; 7492 vp_mirror[0].field = ING_MIRROR_ENABLEf; 7493 vp_mirror[0].egress = FALSE; 7494 7495 if (soc_feature(unit, soc_feature_td2p_dvp_mirroring)) { 7496 mem = ING_DVP_2_TABLEm; 7497 } else { 7498 mem = ING_DVP_TABLEm; 7499 } 7500 vp_mirror[1].mem = mem; 7501 vp_mirror[1].field = EGR_MIRROR_ENABLEf; 7502 vp_mirror[1].egress = TRUE; 7503 7504 for (j = 0; j < 2; j++) { 7505 if (SOC_MEM_IS_VALID(unit, vp_mirror[j].mem) && 7506 SOC_MEM_FIELD_VALID(unit, vp_mirror[j].mem, vp_mirror[j].field)) { 7507 mem_buf = soc_cm_salloc(unit, SOC_MEM_TABLE_BYTES(unit, vp_mirror[j].mem), 7508 "SDVP_buffer"); 7509 if (NULL == mem_buf) { 7510 return BCM_E_MEMORY; 7511 } 7512 sal_memset(mem_buf, 0, SOC_MEM_TABLE_BYTES(unit, vp_mirror[j].mem)); 7513 index_min = soc_mem_index_min(unit, vp_mirror[j].mem); 7514 index_max = soc_mem_index_max(unit, vp_mirror[j].mem); 7515 rv = soc_mem_read_range(unit, vp_mirror[j].mem, MEM_BLOCK_ANY, 7516 index_min, index_max, mem_buf); 7517 if (SOC_FAILURE(rv)) { 7518 soc_cm_sfree(unit, mem_buf); 7519 return rv; 7520 } 7521 7522 for (i = 0; i <= (index_max - index_min); i++) { 7523 entry_ptr = soc_mem_table_idx_to_pointer(unit, 7524 vp_mirror[j].mem, void *, mem_buf, i); 7525 mirror_enable = soc_mem_field32_get(unit, vp_mirror[j].mem, 7526 entry_ptr, vp_mirror[j].field); 7527 for (mtp_index = 0; mtp_index < BCM_MIRROR_MTP_COUNT; 7528 mtp_index++) { 7529 if (mirror_enable & (1 << mtp_index)) { 7530 if (!MIRROR_MTP_METHOD_IS_DIRECTED_FLEXIBLE(unit)) { 7531 if (vp_mirror[j].egress != 7532 MIRROR_CONFIG_SHARED_MTP(unit, mtp_index).egress) { 7533 /* global mtp selection type(ingress/egress) doesn't match 7534 * the virtual port mtp usage type 7535 */ 7536 soc_cm_sfree(unit, mem_buf); 7537 return BCM_E_INTERNAL; 7538 } 7539 MIRROR_CONFIG_SHARED_MTP_REF_COUNT(unit, mtp_index)++; 7540 MIRROR_DEST_REF_COUNT(unit, 7541 MIRROR_CONFIG_SHARED_MTP_DEST(unit, mtp_index))++; 7542 } 7543 MIRROR_CONFIG_SHARED_MTP_REF_COUNT(unit, mtp_index)++; 7544 MIRROR_DEST_REF_COUNT(unit, 7545 MIRROR_CONFIG_SHARED_MTP_DEST(unit, mtp_index))++; 7546 } 7547 } 7548 } 7549 soc_cm_sfree(unit, mem_buf); 7550 } 7551 } 7552 return BCM_E_NONE; 7553 } 7554 7555 STATIC int 7556 _bcm_esw_mirror_method_reinit(int unit, uint32 *wb_flags) 7557 { 7558 int rv; 7559 uint16 recovered_ver; 7560 soc_scache_handle_t scache_handle; 7561 uint8 *method_scache; 7562 int extra_scache_size = 0; 7563 7564 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_MIRROR, 1); 7565 rv = _bcm_esw_scache_ptr_get(unit, scache_handle, FALSE, 7566 0, &method_scache, 7567 BCM_WB_DEFAULT_VERSION, &recovered_ver); 7568 if (BCM_E_NOT_FOUND == rv) { 7569 return BCM_E_NONE; 7570 } else if (BCM_FAILURE(rv)) { 7571 LOG_CLI((BSL_META_U(unit, 7572 "mirror_method_scache error \n"))); 7573 return rv; 7574 } 7575 7576 *wb_flags = 0; 7577 if (method_scache != NULL) { 7578 /* Retrieve MTP method from scache */ 7579 sal_memcpy(&(_bcm_mirror_mtp_method_init[unit]), method_scache, 7580 sizeof(_bcm_mirror_mtp_method_init[unit])); 7581 method_scache += sizeof(_bcm_mirror_mtp_method_init[unit]); 7582 if (recovered_ver >= BCM_WB_VERSION_1_12) { 7583 /* recover TD3 include flags */ 7584 sal_memcpy(wb_flags, method_scache, sizeof(uint32)); 7585 method_scache += sizeof(uint32); 7586 } else { 7587 extra_scache_size += sizeof(uint32); 7588 } 7589 7590 if (extra_scache_size > 0) { 7591 BCM_IF_ERROR_RETURN 7592 (soc_scache_realloc(unit, scache_handle, extra_scache_size)); 7593 } 7594 } 7595 return BCM_E_NONE; 7596 } 7597 7598 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_GREYHOUND_SUPPORT) 7599 STATIC int 7600 _bcm_esw_mirror_dest_tunnel_flags_get(int unit, int egress, int offset, 7601 uint32 *flags, uint32 *flags2) 7602 { 7603 egr_im_mtp_index_entry_t egr_mtp_entry; 7604 uint32 profile_index = 0; 7605 soc_mem_t mtp_index_mem, encap_control_mem; 7606 egr_mirror_encap_control_entry_t control_entry; 7607 int optional_header; 7608 if (soc_feature(unit, soc_feature_mirror_encap_profile)) { 7609 /* 7610 * EGR_*_MTP_INDEX tables are arranged as blocks of 7611 * BCM_SWITCH_TRUNK_MAX_PORTCNT entries, with 7612 * BCM_MIRROR_MTP_COUNT sets. Check the 7613 * first entry of each block to see if the 7614 * encap enable is set. Track one reference count 7615 * for each set, by each destination type (IM, EM, TRUE EM) 7616 */ 7617 if (egress) { 7618 mtp_index_mem = EGR_EM_MTP_INDEXm; 7619 } else { 7620 mtp_index_mem = EGR_IM_MTP_INDEXm; 7621 } 7622 7623 BCM_IF_ERROR_RETURN 7624 (soc_mem_read(unit, mtp_index_mem, MEM_BLOCK_ANY, 7625 offset, &egr_mtp_entry)); 7626 if (soc_mem_field32_get(unit, mtp_index_mem, 7627 &egr_mtp_entry, 7628 MIRROR_ENCAP_ENABLEf)) { 7629 profile_index = 7630 soc_mem_field32_get(unit, mtp_index_mem, 7631 &egr_mtp_entry, 7632 MIRROR_ENCAP_INDEXf); 7633 #if defined(BCM_TRIDENT3_SUPPORT) 7634 if (SOC_IS_TRIDENT3X(unit)) { 7635 int edit_ctrl_id; 7636 egr_mirror_table_entry_t table_entry; 7637 if ((EGR_MIRROR_TABLE(unit) == NULL) || 7638 (EGR_MIRROR_TABLE(unit)->tables == NULL)) { 7639 return BCM_E_INIT; 7640 } 7641 encap_control_mem = EGR_MIRROR_TABLE(unit)->tables[0].mem; 7642 BCM_IF_ERROR_RETURN 7643 (soc_mem_read(unit, encap_control_mem, MEM_BLOCK_ANY, 7644 profile_index, &table_entry)); 7645 edit_ctrl_id = soc_EGR_MIRROR_TABLEm_field32_get (unit, 7646 &table_entry, MIRROR_EDIT_CTRL_IDf); 7647 7648 _bcm_td3_mirror_flags_update(unit, edit_ctrl_id, flags, flags2); 7649 } else 7650 #endif /* BCM_TRIDENT3_SUPPORT */ 7651 { 7652 if ((EGR_MIRROR_ENCAP(unit) == NULL) || 7653 (EGR_MIRROR_ENCAP(unit)->tables == NULL)) { 7654 return BCM_E_INIT; 7655 } 7656 encap_control_mem = EGR_MIRROR_ENCAP(unit)->tables[0].mem; 7657 BCM_IF_ERROR_RETURN 7658 (soc_mem_read(unit, encap_control_mem, MEM_BLOCK_ANY, 7659 profile_index, &control_entry)); 7660 #ifdef BCM_TOMAHAWK3_SUPPORT 7661 if (SOC_IS_TOMAHAWK3(unit)) { 7662 /* Set to invalid value as there is no support for 7663 * optional header 7664 */ 7665 optional_header = -1; 7666 } else 7667 #endif /* BCM_TOMAHAWK3_SUPPORT */ 7668 { 7669 optional_header = 7670 soc_EGR_MIRROR_ENCAP_CONTROLm_field32_get(unit, 7671 &control_entry, RSPAN__ADD_OPTIONAL_HEADERf); 7672 } 7673 7674 #ifdef BCM_TOMAHAWK3_SUPPORT 7675 if (SOC_IS_TOMAHAWK3(unit)) { 7676 uint32 fldval; 7677 7678 fldval = soc_EGR_MIRROR_ENCAP_CONTROLm_field32_get(unit, 7679 &control_entry, ENTRY_TYPEf); 7680 7681 switch (fldval) { 7682 case _BCM_TH3_MIRROR_ENCAP_TYPE_SFLOW: 7683 case _BCM_TH3_MIRROR_ENCAP_TYPE_SFLOW_V6: 7684 case _BCM_TH3_MIRROR_ENCAP_TYPE_SFLOW_SEQ: 7685 case _BCM_TH3_MIRROR_ENCAP_TYPE_SFLOW_V6_SEQ: 7686 *flags |= BCM_MIRROR_DEST_TUNNEL_SFLOW; 7687 break; 7688 7689 case _BCM_TH3_MIRROR_ENCAP_TYPE_PSAMP: 7690 case _BCM_TH3_MIRROR_ENCAP_TYPE_PSAMP_V6: 7691 case _BCM_TH3_MIRROR_ENCAP_TYPE_PSAMP_FORMAT_2: 7692 case _BCM_TH3_MIRROR_ENCAP_TYPE_PSAMP_FORMAT_2_V6: 7693 *flags |= BCM_MIRROR_DEST_TUNNEL_PSAMP; 7694 if (fldval == 7695 _BCM_TH3_MIRROR_ENCAP_TYPE_PSAMP_FORMAT_2_V6) { 7696 *flags2 |= BCM_MIRROR_DEST_FLAGS2_PSAMP_FORMAT_2; 7697 } 7698 break; 7699 7700 case _BCM_TH3_MIRROR_ENCAP_TYPE_ERSPAN: 7701 case _BCM_TH3_MIRROR_ENCAP_TYPE_ERSPAN_V6: 7702 *flags |= BCM_MIRROR_DEST_TUNNEL_IP_GRE; 7703 break; 7704 7705 case _BCM_TH3_MIRROR_ENCAP_TYPE_RSPAN: 7706 default: 7707 *flags |= BCM_MIRROR_DEST_TUNNEL_L2; 7708 break; 7709 } 7710 } else 7711 #endif /* BCM_TOMAHAWK3_SUPPORT */ 7712 { 7713 if (soc_EGR_MIRROR_ENCAP_CONTROLm_field32_get(unit, 7714 &control_entry, ENTRY_TYPEf) == 7715 BCM_TD_MIRROR_ENCAP_TYPE_SFLOW) { 7716 *flags |= BCM_MIRROR_DEST_TUNNEL_SFLOW; 7717 } else if (soc_EGR_MIRROR_ENCAP_CONTROLm_field32_get(unit, 7718 &control_entry, ENTRY_TYPEf) == 7719 BCM_TD_MIRROR_ENCAP_TYPE_ERSPAN) { 7720 *flags |= BCM_MIRROR_DEST_TUNNEL_IP_GRE; 7721 } else { 7722 *flags |= BCM_MIRROR_DEST_TUNNEL_L2; 7723 } 7724 } 7725 7726 if (BCM_TD_MIRROR_HEADER_TRILL == optional_header) { 7727 *flags |= BCM_MIRROR_DEST_TUNNEL_TRILL; 7728 } else if (BCM_TD_MIRROR_HEADER_VNTAG == optional_header) { 7729 *flags |= BCM_MIRROR_DEST_TUNNEL_NIV; 7730 } else if (BCM_MIRROR_HEADER_ETAG == optional_header) { 7731 if(soc_feature(unit, soc_feature_port_extension)) { 7732 *flags |= BCM_MIRROR_DEST_TUNNEL_ETAG; 7733 } 7734 } 7735 } 7736 } 7737 } 7738 return BCM_E_NONE; 7739 } 7740 #endif /* BCM_TRIDENT_SUPPORT) || BCM_GREYHOUND_SUPPORT */ 7741 7742 STATIC int 7743 _bcm_esw_mirror_scache_version_incremental_size_get(int unit, 7744 uint16 version, 7745 int *alloc_size) 7746 { 7747 int ing_mtp_count = 0, egr_mtp_count = 0; 7748 int alloc_sz = 0; 7749 #ifdef BCM_TRIUMPH2_SUPPORT 7750 int egr_true_mtp_count = 0; 7751 #endif /* BCM_TRIUMPH2_SUPPORT */ 7752 #if defined(BCM_TOMAHAWK3_SUPPORT) 7753 int num_slot_types; 7754 #endif /* BCM_TOMAHAWK3_SUPPORT */ 7755 7756 if (alloc_size == NULL) { 7757 return BCM_E_PARAM; 7758 } 7759 7760 egr_mtp_count = BCM_MIRROR_MTP_COUNT; 7761 ing_mtp_count = BCM_MIRROR_MTP_COUNT; 7762 #ifdef BCM_TRIUMPH2_SUPPORT 7763 if (soc_feature(unit, soc_feature_egr_mirror_true)) { 7764 egr_true_mtp_count = BCM_MIRROR_MTP_COUNT; 7765 } 7766 #endif /* BCM_TRIUMPH2_SUPPORT */ 7767 7768 if (version == BCM_WB_VERSION_1_1) { 7769 if (soc_feature(unit, soc_feature_mirror_flexible) && 7770 MIRROR_MTP_METHOD_IS_DIRECTED_FLEXIBLE(unit)) { 7771 /* Slot-MTP mapping information for respective slot types */ 7772 alloc_sz += (sizeof(bcm_gport_t) * BCM_MIRROR_MTP_COUNT) * (BCM_MTP_SLOT_TYPE_SFLOW + 1); 7773 /* Reference counter for respective slot types */ 7774 alloc_sz += (sizeof(int) * BCM_MIRROR_MTP_COUNT) * (BCM_MTP_SLOT_TYPE_SFLOW + 1); 7775 /* BCM_MIRROR_DEST_FIELD flag */ 7776 alloc_sz += sizeof(uint16); 7777 /* Reference counter for MTP slot */ 7778 alloc_sz += sizeof(int) * BCM_MIRROR_MTP_COUNT; 7779 /* For ING MTP reference counter */ 7780 alloc_sz += sizeof(int) * ing_mtp_count; 7781 /* For ING MTP reference counter */ 7782 alloc_sz += sizeof(int) * egr_mtp_count; 7783 /* For destination reference counter */ 7784 alloc_sz += sizeof(int) * (egr_mtp_count + ing_mtp_count); 7785 #ifdef BCM_TRIUMPH2_SUPPORT 7786 if (soc_feature(unit, soc_feature_egr_mirror_true)) { 7787 alloc_sz += sizeof(int) * egr_true_mtp_count; 7788 } 7789 #endif /* BCM_TRIUMPH2_SUPPORT */ 7790 /* For pbmp_mtp_slot_used */ 7791 alloc_sz += sizeof(bcm_pbmp_t) * BCM_MIRROR_MTP_COUNT; 7792 7793 *alloc_size = alloc_sz; 7794 return BCM_E_NONE; 7795 } else { 7796 *alloc_size = 0; 7797 return BCM_E_NONE; 7798 } 7799 } else if (version == BCM_WB_VERSION_1_2) { 7800 if (soc_feature(unit, soc_feature_mirror_flexible) && 7801 MIRROR_MTP_METHOD_IS_DIRECTED_FLEXIBLE(unit)) { 7802 /* Save destination flags for flexible mtp mirror */ 7803 alloc_sz += sizeof(uint32) * (egr_mtp_count + ing_mtp_count); 7804 #ifdef BCM_TRIUMPH2_SUPPORT 7805 if (soc_feature(unit, soc_feature_egr_mirror_true)) { 7806 alloc_sz += sizeof(uint32) * egr_true_mtp_count; 7807 } 7808 #endif /* BCM_TRIUMPH2_SUPPORT */ 7809 *alloc_size = alloc_sz; 7810 return BCM_E_NONE; 7811 } else { 7812 *alloc_size = 0; 7813 return BCM_E_NONE; 7814 } 7815 } else if (version == BCM_WB_VERSION_1_3) { 7816 if (soc_feature(unit, soc_feature_mirror_flexible) && 7817 !MIRROR_MTP_METHOD_IS_DIRECTED_FLEXIBLE(unit)) { 7818 /* Save destination flags for non-flexible mtp mirror */ 7819 alloc_sz += sizeof(uint32) * BCM_MIRROR_MTP_COUNT; 7820 #ifdef BCM_TRIUMPH2_SUPPORT 7821 if (soc_feature(unit, soc_feature_egr_mirror_true)) { 7822 alloc_sz += sizeof(uint32) * egr_true_mtp_count; 7823 } 7824 #endif /* BCM_TRIUMPH2_SUPPORT */ 7825 *alloc_size = alloc_sz; 7826 return BCM_E_NONE; 7827 } else { 7828 *alloc_size = 0; 7829 return BCM_E_NONE; 7830 } 7831 } else if (version == BCM_WB_VERSION_1_4) { 7832 if (soc_feature(unit, soc_feature_mirror_flexible) && 7833 !MIRROR_MTP_METHOD_IS_DIRECTED_FLEXIBLE(unit)) { 7834 /* For Shared MTP ref_count */ 7835 alloc_sz += sizeof(int) * BCM_MIRROR_MTP_COUNT; 7836 /* For Egress True MTP ref_count */ 7837 #ifdef BCM_TRIUMPH2_SUPPORT 7838 if (soc_feature(unit, soc_feature_egr_mirror_true)) { 7839 alloc_sz += sizeof(int) * egr_true_mtp_count; 7840 } 7841 #endif /* BCM_TRIUMPH2_SUPPORT */ 7842 7843 /* For destination ref_count */ 7844 alloc_sz += sizeof(int) * BCM_MIRROR_MTP_COUNT; 7845 #ifdef BCM_TRIUMPH2_SUPPORT 7846 if (soc_feature(unit, soc_feature_egr_mirror_true)) { 7847 alloc_sz += sizeof(int) * egr_true_mtp_count; 7848 } 7849 #endif /* BCM_TRIUMPH2_SUPPORT */ 7850 7851 /* For MIRROR_CONFIG_MODE */ 7852 alloc_sz += sizeof(int); 7853 *alloc_size = alloc_sz; 7854 return BCM_E_NONE; 7855 } else { 7856 *alloc_size = 0; 7857 return BCM_E_NONE; 7858 } 7859 } else if (version == BCM_WB_VERSION_1_5) { 7860 if (soc_feature(unit, soc_feature_mirror_flexible)) { 7861 if (MIRROR_MTP_METHOD_IS_DIRECTED_FLEXIBLE(unit)) { 7862 /* For Ingress,Egress MTP destination gport */ 7863 alloc_sz += sizeof(bcm_gport_t) * BCM_SWITCH_TRUNK_MAX_PORTCNT * 7864 (ing_mtp_count + egr_mtp_count); 7865 /* For Ingress,Egress MTP destination flags */ 7866 alloc_sz += sizeof(uint32) * BCM_SWITCH_TRUNK_MAX_PORTCNT * 7867 (ing_mtp_count + egr_mtp_count); 7868 } else { 7869 /* For Shared MTP destination gport */ 7870 alloc_sz += sizeof(bcm_gport_t) * BCM_SWITCH_TRUNK_MAX_PORTCNT * 7871 BCM_MIRROR_MTP_COUNT; 7872 /* For Shared MTP destination flags */ 7873 alloc_sz += sizeof(uint32) * BCM_SWITCH_TRUNK_MAX_PORTCNT * 7874 BCM_MIRROR_MTP_COUNT; 7875 } 7876 *alloc_size = alloc_sz; 7877 return BCM_E_NONE; 7878 } else { 7879 *alloc_size = 0; 7880 return BCM_E_NONE; 7881 } 7882 } else if (version == BCM_WB_VERSION_1_6) { 7883 if (soc_feature(unit, soc_feature_mirror_flexible)) { 7884 if (MIRROR_MTP_METHOD_IS_DIRECTED_FLEXIBLE(unit)) { 7885 #ifdef BCM_TRIUMPH2_SUPPORT 7886 /* For Ingress,Egress MTP destination gport */ 7887 if (soc_feature(unit, soc_feature_egr_mirror_true)) { 7888 alloc_sz += sizeof(int) * egr_true_mtp_count; 7889 *alloc_size = alloc_sz; 7890 return BCM_E_NONE; 7891 } 7892 #endif 7893 } 7894 } 7895 } else if (version == BCM_WB_VERSION_1_7) { 7896 if (soc_feature(unit, soc_feature_mirror_flexible)) { 7897 #if defined(BCM_TRIDENT3_SUPPORT) 7898 /* For encap_to_edit_ctrl_id */ 7899 alloc_sz += sizeof(uint32) * BCM_MIRROR_MTP_COUNT; 7900 /* For encap_profile_index_bmap */ 7901 alloc_sz += sizeof(uint32); 7902 *alloc_size = alloc_sz; 7903 return BCM_E_NONE; 7904 #endif /* BCM_TRIDENT3_SUPPORT */ 7905 } else { 7906 *alloc_size = 0; 7907 return BCM_E_NONE; 7908 } 7909 } else if (version == BCM_WB_VERSION_1_8) { 7910 *alloc_size = 0; 7911 if (soc_feature(unit, soc_feature_mirror_flexible) && 7912 MIRROR_MTP_METHOD_IS_DIRECTED_FLEXIBLE(unit)) { 7913 #if defined(BCM_TOMAHAWK3_SUPPORT) 7914 /* Scache info of slot types till BCM_MTP_SLOT_TYPE_SFLOW was synced 7915 * in previous versions, store INT and ETRAP here. 7916 */ 7917 7918 /* INT, ETRAP, DLB Flow Monitoring */ 7919 num_slot_types = 3; 7920 7921 /* Slot-MTP mapping information for respective slot type */ 7922 alloc_sz += sizeof(bcm_gport_t) * BCM_MIRROR_MTP_COUNT * num_slot_types; 7923 /* Reference counter for respective slot type */ 7924 alloc_sz += sizeof(int) * BCM_MIRROR_MTP_COUNT * num_slot_types; 7925 7926 *alloc_size = alloc_sz; 7927 #endif /* BCM_TOMAHAWK3_SUPPORT */ 7928 } 7929 return BCM_E_NONE; 7930 } else if (version == BCM_WB_VERSION_1_9) { 7931 if (soc_feature(unit, soc_feature_th3_style_fp)) { 7932 #ifdef BCM_TOMAHAWK3_SUPPORT 7933 alloc_sz += (sizeof(_bcm_mirror_zero_profile_t) * MIRROR_ZERO_PROFILE_INDEX_MAX); 7934 *alloc_size = alloc_sz; 7935 #endif 7936 return BCM_E_NONE; 7937 } else { 7938 *alloc_size = 0; 7939 return BCM_E_NONE; 7940 } 7941 } else if (version == BCM_WB_VERSION_1_10) { 7942 if (soc_feature(unit, soc_feature_erspan3_support)) { 7943 #ifdef BCM_TRIDENT3_SUPPORT 7944 /* GBP SID values stored for ERSPANv3, gbp_sid and gre_seq_number 7945 allocate space enough for Ingress, Egress and True-Egress */ 7946 alloc_sz += (sizeof(uint16) * (BCM_MIRROR_MTP_COUNT * 3)); 7947 alloc_sz += (sizeof(uint32) * (BCM_MIRROR_MTP_COUNT * 3)); 7948 *alloc_size = alloc_sz; 7949 #endif 7950 return BCM_E_NONE; 7951 } else { 7952 *alloc_size = 0; 7953 return BCM_E_NONE; 7954 } 7955 } else if (version == BCM_WB_VERSION_1_11) { 7956 #ifdef BCM_TRIDENT3_SUPPORT 7957 if (soc_feature(unit, soc_feature_mirror_encap_profile)) { 7958 /* Save VNI for vxlan encap 7959 allocate space enough for Ingress, Egress and True-Egress */ 7960 alloc_sz += (sizeof(uint32) * (BCM_MIRROR_MTP_COUNT * 3)); 7961 *alloc_size = alloc_sz; 7962 return BCM_E_NONE; 7963 } else 7964 #endif 7965 { 7966 *alloc_size = 0; 7967 return BCM_E_NONE; 7968 } 7969 } 7970 7971 return BCM_E_NONE; 7972 } 7973 7974 #if defined(BCM_TRIDENT_SUPPORT) 7975 STATIC int 7976 _bcm_td_mirror_destination_pri_recover(int unit, 7977 bcm_mirror_destination_t *mirror_dest, 7978 int offset, 7979 int flags) 7980 { 7981 int mdest_flags = 0; 7982 egr_im_mtp_index_entry_t egr_im_mtp_index_entry; 7983 egr_em_mtp_index_entry_t egr_em_mtp_index_entry; 7984 egr_ep_redirect_em_mtp_index_entry_t egr_em_redirect_mtp_index_entry; 7985 7986 if (mirror_dest == NULL) { 7987 return BCM_E_PARAM; 7988 } 7989 7990 #ifdef BCM_TOMAHAWK3_SUPPORT 7991 /* Internal priority assignment and usage is not supported on TH3 */ 7992 if (SOC_IS_TOMAHAWK3(unit)) { 7993 mirror_dest->int_pri = 0xFF; /* Invalid value */ 7994 return BCM_E_NONE; 7995 } 7996 #endif /* BCM_TOMAHAWK3_SUPPORT */ 7997 7998 mdest_flags = mirror_dest->flags; 7999 if (mdest_flags & BCM_MIRROR_DEST_INT_PRI_SET) { 8000 if (soc_feature(unit, soc_feature_mirror_encap_profile)) { 8001 if (flags & BCM_MIRROR_PORT_INGRESS) { 8002 BCM_IF_ERROR_RETURN 8003 (READ_EGR_IM_MTP_INDEXm(unit, MEM_BLOCK_ANY, offset, 8004 &egr_im_mtp_index_entry)); 8005 mirror_dest->int_pri = 8006 soc_EGR_IM_MTP_INDEXm_field32_get(unit, 8007 &egr_im_mtp_index_entry, 8008 NEW_INT_PRIf); 8009 } 8010 8011 if (flags & BCM_MIRROR_PORT_EGRESS) { 8012 BCM_IF_ERROR_RETURN 8013 (READ_EGR_EM_MTP_INDEXm(unit, MEM_BLOCK_ANY, offset, 8014 &egr_em_mtp_index_entry)); 8015 mirror_dest->int_pri = 8016 soc_EGR_EM_MTP_INDEXm_field32_get(unit, 8017 &egr_em_mtp_index_entry, 8018 NEW_INT_PRIf); 8019 } 8020 } 8021 8022 if (soc_feature(unit, soc_feature_egr_mirror_true)) { 8023 if (flags & BCM_MIRROR_PORT_EGRESS_TRUE) { 8024 BCM_IF_ERROR_RETURN 8025 (READ_EGR_EP_REDIRECT_EM_MTP_INDEXm( 8026 unit, MEM_BLOCK_ANY, offset, 8027 &egr_em_redirect_mtp_index_entry)); 8028 mirror_dest->int_pri = 8029 soc_EGR_EP_REDIRECT_EM_MTP_INDEXm_field32_get( 8030 unit, &egr_em_redirect_mtp_index_entry, NEW_INT_PRIf); 8031 } 8032 } 8033 } 8034 8035 return BCM_E_NONE; 8036 } 8037 #endif 8038 8039 #ifdef BCM_TRIDENT2_SUPPORT 8040 /* Save MTP gport info of a shared-id mirror destination. */ 8041 STATIC int 8042 _bcm_mirror_dest_gport_sync(int unit, bcm_gport_t mirror_dest_id, 8043 uint8 *scache) 8044 { 8045 _bcm_mirror_dest_config_p mdest_cfg; /* Mirror destination config head node */ 8046 _bcm_mirror_dest_config_p cur_dest = NULL; /* Current node */ 8047 int i = 0, max_portcnt = BCM_SWITCH_TRUNK_MAX_PORTCNT; 8048 uint8 *scache_ptr = scache; 8049 8050 if (!BCM_GPORT_IS_MIRROR(mirror_dest_id)) { 8051 return (BCM_E_PARAM); 8052 } 8053 8054 mdest_cfg = &MIRROR_DEST_CONFIG(unit, mirror_dest_id); 8055 8056 if (mdest_cfg->ref_count > 0) { 8057 cur_dest = mdest_cfg->next; 8058 8059 for (i = 0; i < max_portcnt; i++) { 8060 if (NULL == cur_dest) { 8061 break; 8062 } 8063 sal_memcpy(scache_ptr, &(cur_dest->mirror_dest.gport), 8064 sizeof(bcm_gport_t)); 8065 scache_ptr += sizeof(bcm_gport_t); 8066 cur_dest = cur_dest->next; 8067 } 8068 } 8069 return (BCM_E_NONE); 8070 } 8071 8072 /* Save MTP flags info of a shared-id mirror destination. */ 8073 STATIC int 8074 _bcm_mirror_dest_flags_sync(int unit, bcm_gport_t mirror_dest_id, 8075 uint8 *scache) 8076 { 8077 _bcm_mirror_dest_config_p mdest_cfg; /* Mirror destination config head node */ 8078 _bcm_mirror_dest_config_p cur_dest = NULL; /* Current node */ 8079 int i = 0, max_portcnt = BCM_SWITCH_TRUNK_MAX_PORTCNT; 8080 uint8 *scache_ptr = scache; 8081 8082 if (!BCM_GPORT_IS_MIRROR(mirror_dest_id)) { 8083 return (BCM_E_PARAM); 8084 } 8085 8086 mdest_cfg = &MIRROR_DEST_CONFIG(unit, mirror_dest_id); 8087 8088 if (mdest_cfg->ref_count > 0) { 8089 cur_dest = mdest_cfg->next; 8090 8091 for (i = 0; i < max_portcnt; i++) { 8092 if (NULL == cur_dest) { 8093 break; 8094 } 8095 sal_memcpy(scache_ptr, &(cur_dest->mirror_dest.flags), 8096 sizeof(uint32)); 8097 scache_ptr += sizeof(uint32); 8098 cur_dest = cur_dest->next; 8099 } 8100 } 8101 return (BCM_E_NONE); 8102 } 8103 8104 /* Rtag recovery for shared-id mirror destination */ 8105 STATIC int 8106 _bcm_td2_mirror_destination_rtag_recover(int unit, 8107 bcm_mirror_destination_t *mirror_dest, 8108 int offset, 8109 int flags) 8110 { 8111 im_mtp_index_entry_t im_mtp_index_entry; 8112 em_mtp_index_entry_t em_mtp_index_entry; 8113 8114 if (mirror_dest == NULL) { 8115 return BCM_E_PARAM; 8116 } 8117 8118 if (soc_feature(unit, soc_feature_mirror_flexible)) { 8119 #ifdef BCM_TOMAHAWK3_SUPPORT 8120 /* No support for shared dest id */ 8121 if (SOC_IS_TOMAHAWK3(unit)) { 8122 mirror_dest->rtag = bcmMirrorPscNone; /* Invalid value */ 8123 return BCM_E_NONE; 8124 } 8125 #endif /* BCM_TOMAHAWK3_SUPPORT */ 8126 8127 if (flags & BCM_MIRROR_PORT_INGRESS) { 8128 BCM_IF_ERROR_RETURN 8129 (READ_IM_MTP_INDEXm(unit, MEM_BLOCK_ANY, offset, 8130 &im_mtp_index_entry)); 8131 if (soc_IM_MTP_INDEXm_field32_get(unit, 8132 &im_mtp_index_entry, 8133 Tf)) { 8134 mirror_dest->rtag = 8135 soc_IM_MTP_INDEXm_field32_get(unit, 8136 &im_mtp_index_entry, 8137 RTAGf); 8138 } 8139 } 8140 8141 if (flags & BCM_MIRROR_PORT_EGRESS) { 8142 BCM_IF_ERROR_RETURN 8143 (READ_EM_MTP_INDEXm(unit, MEM_BLOCK_ANY, offset, 8144 &em_mtp_index_entry)); 8145 if (soc_EM_MTP_INDEXm_field32_get(unit, 8146 &em_mtp_index_entry, 8147 Tf)) { 8148 mirror_dest->rtag = 8149 soc_EM_MTP_INDEXm_field32_get(unit, 8150 &em_mtp_index_entry, 8151 RTAGf); 8152 } 8153 } 8154 } 8155 8156 return BCM_E_NONE; 8157 } 8158 8159 /* 8160 * Function: 8161 * _bcm_td2_mirror_shared_dest_recover 8162 * Purpose: 8163 * Recover mirror destination for shared-id mirror destination. 8164 * Parameters: 8165 * unit - (IN) BCM device number. 8166 * flag - (IN) Direction flag. 8167 * mir_dest_id - (IN) Mirror dest id. 8168 * dest_flags - (IN) Mirror dest flag. 8169 * mtp_gport - (IN) Mirror dest gport array for mirror dest node. 8170 * mtp_flags - (IN) Mirror dest flags array for mirror dest node. 8171 * Returns: 8172 * BCM_E_XXX 8173 */ 8174 STATIC int 8175 _bcm_td2_mirror_shared_dest_recover(int unit, 8176 int flag, 8177 bcm_gport_t mir_dest_id, 8178 int dest_flags, 8179 int mtp_index, 8180 bcm_gport_t *mtp_gport, 8181 int *mtp_flags) 8182 { 8183 int i, offset = 0; 8184 bcm_mirror_destination_t mir_dest; 8185 egr_im_mtp_index_entry_t egr_mtp_entry; 8186 uint32 profile_index; 8187 uint8 found = FALSE; 8188 uint8 egress = 0; 8189 bcm_gport_t dest_id; 8190 8191 if (!soc_feature(unit, soc_feature_mirror_flexible)) { 8192 return (BCM_E_UNAVAIL); 8193 } 8194 8195 if (!BCM_GPORT_IS_MIRROR(mir_dest_id)) { 8196 return (BCM_E_PARAM); 8197 } 8198 8199 if (NULL == mtp_gport || NULL == mtp_flags) { 8200 return (BCM_E_PARAM); 8201 } 8202 8203 if (flag & BCM_MIRROR_PORT_INGRESS) { 8204 egress = FALSE; 8205 } else if (flag & BCM_MIRROR_PORT_EGRESS) { 8206 egress = TRUE; 8207 } else { 8208 return (BCM_E_PARAM); 8209 } 8210 8211 /* Alloc dest_id first */ 8212 if (!MIRROR_DEST_REF_COUNT(unit, mir_dest_id)) { 8213 bcm_mirror_destination_t_init(&mir_dest); 8214 mir_dest.flags = dest_flags; 8215 mir_dest.flags |= BCM_MIRROR_DEST_WITH_ID; 8216 mir_dest.mirror_dest_id = mir_dest_id; 8217 8218 BCM_IF_ERROR_RETURN( 8219 _bcm_td2_mirror_destination_rtag_recover( 8220 unit, &mir_dest, mtp_index, flag)); 8221 8222 BCM_IF_ERROR_RETURN( 8223 _bcm_esw_mirror_destination_create(unit, &mir_dest)); 8224 } 8225 8226 offset = mtp_index * BCM_SWITCH_TRUNK_MAX_PORTCNT; 8227 for (i = 0; i < BCM_SWITCH_TRUNK_MAX_PORTCNT; i++, offset++) { 8228 bcm_mirror_destination_t_init(&mir_dest); 8229 mir_dest.flags = mtp_flags[offset]; 8230 8231 if (soc_feature(unit, soc_feature_mirror_encap_profile)) { 8232 BCM_IF_ERROR_RETURN 8233 (_bcm_esw_mirror_dest_tunnel_flags_get( 8234 unit, egress, 8235 offset, 8236 &mir_dest.flags, 8237 &mir_dest.flags2)); 8238 } 8239 8240 mir_dest.gport = mtp_gport[offset]; 8241 if (!BCM_GPORT_IS_SET(mir_dest.gport)) { 8242 continue; 8243 } 8244 /* Adapt miror destination gport */ 8245 BCM_IF_ERROR_RETURN( 8246 _bcm_mirror_gport_adapt(unit, &(mir_dest.gport))); 8247 8248 BCM_IF_ERROR_RETURN( 8249 _bcm_td_mirror_destination_pri_recover( 8250 unit, &mir_dest, 8251 offset, flag)); 8252 8253 dest_id = MIRROR_CONFIG_ING_MTP_DEST(unit, mtp_index); 8254 if (!egress) { 8255 BCM_IF_ERROR_RETURN 8256 (soc_mem_read(unit, EGR_IM_MTP_INDEXm, MEM_BLOCK_ANY, 8257 offset, &egr_mtp_entry)); 8258 if (soc_mem_field32_get(unit, EGR_IM_MTP_INDEXm, 8259 &egr_mtp_entry, 8260 MIRROR_ENCAP_ENABLEf)) { 8261 profile_index = 8262 soc_mem_field32_get(unit, EGR_IM_MTP_INDEXm, 8263 &egr_mtp_entry, 8264 MIRROR_ENCAP_INDEXf); 8265 BCM_IF_ERROR_RETURN 8266 (_bcm_egr_mirror_encap_entry_reference( 8267 unit, profile_index)); 8268 /* Tunnel type info recovery */ 8269 BCM_IF_ERROR_RETURN 8270 (_bcm_td_mirror_tunnel_reload(unit, 8271 &mir_dest, 8272 dest_id, 8273 profile_index)); 8274 } 8275 } else { 8276 BCM_IF_ERROR_RETURN 8277 (soc_mem_read(unit, EGR_EM_MTP_INDEXm, MEM_BLOCK_ANY, 8278 offset, &egr_mtp_entry)); 8279 if (soc_mem_field32_get(unit, EGR_EM_MTP_INDEXm, 8280 &egr_mtp_entry, 8281 MIRROR_ENCAP_ENABLEf)) { 8282 profile_index = 8283 soc_mem_field32_get(unit, EGR_EM_MTP_INDEXm, 8284 &egr_mtp_entry, 8285 MIRROR_ENCAP_INDEXf); 8286 BCM_IF_ERROR_RETURN 8287 (_bcm_egr_mirror_encap_entry_reference( 8288 unit, profile_index)); 8289 /* Tunnel type info recovery */ 8290 BCM_IF_ERROR_RETURN 8291 (_bcm_td_mirror_tunnel_reload(unit, 8292 &mir_dest, 8293 dest_id, 8294 profile_index)); 8295 } 8296 } 8297 8298 /* We have scratch memory of the destination IDs */ 8299 mir_dest.mirror_dest_id = mir_dest_id; 8300 mir_dest.flags |= BCM_MIRROR_DEST_WITH_ID | 8301 BCM_MIRROR_DEST_MTP_ADD; 8302 found = FALSE; 8303 BCM_IF_ERROR_RETURN( 8304 _bcm_mirror_dest_mtp_search( 8305 unit, 8306 mir_dest.mirror_dest_id, 8307 mir_dest.gport, 8308 &found)); 8309 if (!found) { 8310 BCM_IF_ERROR_RETURN( 8311 _bcm_esw_mirror_destination_create( 8312 unit, &mir_dest)); 8313 } 8314 } 8315 8316 if(!MIRROR_MTP_METHOD_IS_DIRECTED_FLEXIBLE(unit)) { 8317 MIRROR_CONFIG_SHARED_MTP_DEST(unit, mtp_index) = 8318 mir_dest_id; 8319 MIRROR_CONFIG_SHARED_MTP(unit, mtp_index).egress = 8320 (0 != (flag & BCM_MIRROR_PORT_EGRESS)); 8321 } else { 8322 if (!egress) { 8323 MIRROR_CONFIG_ING_MTP_DEST(unit, mtp_index) = 8324 mir_dest_id; 8325 } else { 8326 MIRROR_CONFIG_EGR_MTP_DEST(unit, mtp_index) = 8327 mir_dest_id; 8328 } 8329 } 8330 8331 return (BCM_E_NONE); 8332 } 8333 8334 #endif /* BCM_TRIDENT2_SUPPORT */ 8335 8336 STATIC int 8337 _bcm_esw_directed_flexible_mirror_recover(int unit) 8338 { 8339 soc_scache_handle_t scache_handle; 8340 int rv, idx, slot; 8341 uint16 recovered_ver, dest_field_bmp; 8342 uint8 *mtp_scache_p = NULL; 8343 _bcm_mirror_dest_config_p mdest = NULL; 8344 8345 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_MIRROR, 0); 8346 rv = _bcm_esw_scache_ptr_get(unit, scache_handle, FALSE, 8347 0, &mtp_scache_p, BCM_WB_DEFAULT_VERSION, 8348 &recovered_ver); 8349 if (BCM_FAILURE(rv)) { 8350 LOG_CLI((BSL_META_U(unit, "mtp_scache error \n"))); 8351 return rv; 8352 } 8353 if (soc_feature(unit, soc_feature_mirror_flexible) && 8354 MIRROR_MTP_METHOD_IS_DIRECTED_FLEXIBLE(unit)) { 8355 if (recovered_ver >= BCM_WB_VERSION_1_1) { 8356 /* Skip ING/EGR mtp destination id */ 8357 mtp_scache_p += sizeof(bcm_gport_t) * (MIRROR_CONFIG(unit)->ing_mtp_count); 8358 mtp_scache_p += sizeof(bcm_gport_t) * (MIRROR_CONFIG(unit)->egr_mtp_count); 8359 if (soc_feature(unit, soc_feature_egr_mirror_true)) { 8360 mtp_scache_p += sizeof(bcm_gport_t) * 8361 (MIRROR_CONFIG(unit)->egr_true_mtp_count); 8362 } 8363 /* Slot-MTP mapping information for respective slot types */ 8364 for (idx = BCM_MTP_SLOT_TYPE_PORT; idx < (BCM_MTP_SLOT_TYPE_SFLOW + 1); idx++) { 8365 for (slot = 0; slot < MIRROR_CONFIG(unit)->mtp_slot_count[idx]; 8366 slot++) { 8367 sal_memcpy(&MIRROR_CONFIG_TYPE_MTP_SLOT(unit, slot, idx), 8368 mtp_scache_p, 8369 sizeof(bcm_gport_t)); 8370 mtp_scache_p += sizeof(bcm_gport_t); 8371 } 8372 } 8373 /* Reference counter for respective slot types */ 8374 for (idx = BCM_MTP_SLOT_TYPE_PORT; idx < (BCM_MTP_SLOT_TYPE_SFLOW + 1); idx++) { 8375 for (slot = 0; slot < MIRROR_CONFIG(unit)->mtp_slot_count[idx]; 8376 slot++) { 8377 sal_memcpy(&MIRROR_CONFIG_TYPE_MTP_REF_COUNT(unit, slot, idx), 8378 mtp_scache_p, 8379 sizeof(int)); 8380 mtp_scache_p += sizeof(int); 8381 } 8382 } 8383 /* BCM_MIRROR_DEST_FIELD flag */ 8384 sal_memcpy(&dest_field_bmp, mtp_scache_p, sizeof(uint16)); 8385 mtp_scache_p += sizeof(uint16); 8386 for (idx = 0; idx < MIRROR_CONFIG(unit)->dest_count; idx++) { 8387 mdest = MIRROR_CONFIG(unit)->dest_arr + idx;; 8388 if (dest_field_bmp & (1 << idx)) { 8389 mdest->mirror_dest.flags |= BCM_MIRROR_DEST_FIELD; 8390 } 8391 } 8392 /* Reference counter for MTP slot */ 8393 for (slot = 0; slot < BCM_MIRROR_MTP_COUNT; slot++) { 8394 sal_memcpy(&MIRROR_CONFIG_MTP_MODE_REF_COUNT(unit, slot), 8395 mtp_scache_p, 8396 sizeof(int)); 8397 mtp_scache_p += sizeof(int); 8398 } 8399 /* Reference counter for ING MTP */ 8400 for (idx = 0; idx < MIRROR_CONFIG(unit)->ing_mtp_count; idx++) { 8401 sal_memcpy(&MIRROR_CONFIG_ING_MTP_REF_COUNT(unit, idx), 8402 mtp_scache_p, sizeof(int)); 8403 mtp_scache_p += sizeof(int); 8404 } 8405 /* Reference counter for EGR MTP */ 8406 for (idx = 0; idx < MIRROR_CONFIG(unit)->egr_mtp_count; idx++) { 8407 sal_memcpy(&MIRROR_CONFIG_EGR_MTP_REF_COUNT(unit, idx), 8408 mtp_scache_p, 8409 sizeof(int)); 8410 mtp_scache_p += sizeof(int); 8411 } 8412 /* Reference counter for destination */ 8413 for (idx = 0; idx < MIRROR_CONFIG(unit)->dest_count; idx++) { 8414 mdest = MIRROR_CONFIG(unit)->dest_arr + idx; 8415 sal_memcpy(&(mdest->ref_count), mtp_scache_p, sizeof(int)); 8416 mtp_scache_p += sizeof(int); 8417 } 8418 /* Port bitmap for MTP slot used */ 8419 for (idx = 0; idx < BCM_MIRROR_MTP_COUNT; idx++) { 8420 sal_memcpy(&MIRROR_CONFIG_PBMP_MTP_SLOT_USED(unit, idx), 8421 mtp_scache_p, 8422 sizeof(bcm_pbmp_t)); 8423 mtp_scache_p += sizeof(bcm_pbmp_t); 8424 } 8425 } 8426 } 8427 return BCM_E_NONE; 8428 } 8429 8430 /* 8431 * Function: 8432 * _bcm_esw_mirror_reload 8433 * Purpose: 8434 * Restores mirroring destination for warm boot recovery 8435 * Parameters: 8436 * unit - (IN) BCM device number. 8437 * directed - (IN) indication if directed mirroring is used. 8438 * Returns: 8439 * BCM_E_XXX 8440 */ 8441 8442 8443 STATIC int 8444 _bcm_esw_mirror_reload(int unit, int directed, uint32 wb_flags) 8445 { 8446 soc_scache_handle_t scache_handle; 8447 uint8 *mtp_scache, *mtp_scache_p = NULL; 8448 int mc_enable, enable, enabled = FALSE; 8449 int idx, port_ix, flags, rv; 8450 bcm_module_t modid = 0; 8451 bcm_gport_t gport; 8452 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_GREYHOUND_SUPPORT) 8453 bcm_gport_t dest_id = 0; 8454 #endif /* BCM_TRIDENT_SUPPORT || BCM_GREYHOUND_SUPPORT */ 8455 bcm_gport_t mtp_gport[3 * BCM_MIRROR_MTP_COUNT] = {0}; 8456 /* Max MTP * mirror types (ING, EGR, TRUE EGR) */ 8457 bcm_mirror_destination_t mirror_dest; 8458 uint32 reg_val = 0; 8459 int stale_scache = FALSE; 8460 #ifdef BCM_TRIUMPH2_SUPPORT 8461 uint32 ms_reg; /* MTP mode register value */ 8462 int mtp_type = 0, mtp_index; 8463 #endif /* BCM_TRIUMPH2_SUPPORT */ 8464 #if defined(BCM_TRIDENT_SUPPORT) 8465 mirror_control_entry_t mc_entry; /* MTP control memory value */ 8466 #endif /* BCM_TRIDENT_SUPPORT */ 8467 bcm_pbmp_t all_pbmp; 8468 uint16 recovered_ver = 0; 8469 uint32 dest_flags[3 * BCM_MIRROR_MTP_COUNT] = {0}; 8470 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_GREYHOUND_SUPPORT) 8471 int max_num_trunk_ports = 0; 8472 int mtp_port_count = 0; 8473 #if defined(BCM_METROLITE_SUPPORT) 8474 uint16 dev_id; 8475 uint8 rev_id; 8476 #endif 8477 #endif /* BCM_TRIDENT_SUPPORT || BCM_GREYHOUND_SUPPORT */ 8478 #ifdef BCM_TRIUMPH2_SUPPORT 8479 uint32 non_flexible_mtp_dest_flags[2 * BCM_MIRROR_MTP_COUNT] = {0}; 8480 #endif /* BCM_TRIUMPH2_SUPPORT */ 8481 int extra_scache_size = 0; 8482 int skip = FALSE; 8483 int cur_td3_flag = 0; 8484 8485 #ifdef BCM_TRIUMPH2_SUPPORT 8486 int shared_mtp_ref_count[BCM_MIRROR_MTP_COUNT] = {0}; 8487 int egr_true_mtp_ref_count[BCM_MIRROR_MTP_COUNT] = {0}; 8488 int mirror_dest_ref_count[3 * BCM_MIRROR_MTP_COUNT] = {0}; 8489 int mirror_config_mode = 0; 8490 #endif /* BCM_TRIUMPH2_SUPPORT */ 8491 #ifdef BCM_TRIDENT2_SUPPORT 8492 bcm_gport_t ing_mtp_dest_gport 8493 [BCM_MIRROR_MTP_COUNT*BCM_SWITCH_TRUNK_MAX_PORTCNT] = {0}; 8494 bcm_gport_t egr_mtp_dest_gport 8495 [BCM_MIRROR_MTP_COUNT*BCM_SWITCH_TRUNK_MAX_PORTCNT] = {0}; 8496 bcm_gport_t shared_mtp_dest_gport 8497 [BCM_MIRROR_MTP_COUNT*BCM_SWITCH_TRUNK_MAX_PORTCNT] = {0}; 8498 bcm_gport_t ing_mtp_dest_flags 8499 [BCM_MIRROR_MTP_COUNT*BCM_SWITCH_TRUNK_MAX_PORTCNT] = {0}; 8500 bcm_gport_t egr_mtp_dest_flags 8501 [BCM_MIRROR_MTP_COUNT*BCM_SWITCH_TRUNK_MAX_PORTCNT] = {0}; 8502 bcm_gport_t shared_mtp_dest_flags 8503 [BCM_MIRROR_MTP_COUNT*BCM_SWITCH_TRUNK_MAX_PORTCNT] = {0}; 8504 #endif /* BCM_TRIDENT2_SUPPORT */ 8505 #ifdef BCM_TOMAHAWK3_SUPPORT 8506 int slot, slot_type; 8507 _bcm_mirror_zero_profile_t 8508 mirror_zero_prof_info[MIRROR_ZERO_PROFILE_INDEX_MAX]; 8509 int index = -1; 8510 soc_profile_mem_t *profile = NULL; 8511 #endif 8512 #ifdef BCM_TRIDENT3_SUPPORT 8513 /* Mirror destination description. */ 8514 _bcm_mirror_dest_config_p mdest; 8515 /* Destination & encapsulation */ 8516 bcm_mirror_destination_t *mirror_dest_p = NULL; 8517 #endif /* BCM_TRIDENT3_SUPPORT */ 8518 #ifdef BCM_XGS12_FABRIC_SUPPORT 8519 if (SOC_IS_XGS12_FABRIC(unit)) { 8520 return _bcm_xgs12_fabric_mirror_reinit(unit); 8521 } 8522 #endif /* BCM_XGS12_FABRIC_SUPPORT */ 8523 8524 BCM_PBMP_CLEAR(all_pbmp); 8525 BCM_PBMP_ASSIGN(all_pbmp, PBMP_ALL(unit)); 8526 #ifdef BCM_KATANA2_SUPPORT 8527 if (SOC_IS_KATANA2(unit) && soc_feature(unit, soc_feature_flex_port)) { 8528 BCM_IF_ERROR_RETURN(_bcm_kt2_flexio_pbmp_update(unit, &all_pbmp)); 8529 } 8530 if (soc_feature(unit, soc_feature_linkphy_coe) || 8531 soc_feature(unit, soc_feature_subtag_coe)) { 8532 _bcm_kt2_subport_pbmp_update(unit, &all_pbmp); 8533 } 8534 #endif 8535 8536 if (SOC_IS_XGS3_SWITCH(unit)) { 8537 PBMP_ITER(all_pbmp, port_ix) { 8538 /* Higig port should never drop directed mirror packets 8539 so setting is always enabled and need not to be considered here*/ 8540 if (IS_ST_PORT(unit, port_ix)) { 8541 continue; 8542 } 8543 #if defined(BCM_TRIDENT_SUPPORT) 8544 if (soc_feature(unit, soc_feature_mirror_control_mem)) { 8545 BCM_IF_ERROR_RETURN 8546 (READ_MIRROR_CONTROLm(unit, MEM_BLOCK_ANY, 8547 port_ix, &mc_entry)); 8548 mc_enable = soc_MIRROR_CONTROLm_field32_get(unit, &mc_entry, 8549 M_ENABLEf); 8550 } else 8551 #endif /* BCM_TRIDENT_SUPPORT */ 8552 { 8553 BCM_IF_ERROR_RETURN 8554 (READ_MIRROR_CONTROLr(unit, port_ix, ®_val)); 8555 mc_enable = soc_reg_field_get(unit, MIRROR_CONTROLr, 8556 reg_val, M_ENABLEf); 8557 } 8558 if (mc_enable) { 8559 enabled = TRUE; 8560 break; 8561 } 8562 } 8563 8564 MIRROR_CONFIG_MODE(unit) = 8565 enabled ? BCM_MIRROR_L2 : BCM_MIRROR_DISABLE; 8566 } 8567 8568 /* Recover stored destination gports, if available */ 8569 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_MIRROR, 0); 8570 rv = _bcm_esw_scache_ptr_get(unit, scache_handle, FALSE, 8571 0, &mtp_scache, BCM_WB_DEFAULT_VERSION, 8572 &recovered_ver); 8573 8574 if (BCM_E_NOT_FOUND == rv) { 8575 mtp_scache = NULL; 8576 } else if (BCM_FAILURE(rv)) { 8577 LOG_CLI((BSL_META_U(unit, 8578 "mtp_scache error \n"))); 8579 return rv; 8580 } else { 8581 mtp_scache_p = mtp_scache; 8582 if (soc_feature(unit, soc_feature_mirror_flexible) && 8583 !MIRROR_MTP_METHOD_IS_DIRECTED_FLEXIBLE(unit)) { 8584 for (idx = 0; idx < BCM_MIRROR_MTP_COUNT; idx++) { 8585 sal_memcpy(&(mtp_gport[idx]), 8586 mtp_scache_p, 8587 sizeof(bcm_gport_t)); 8588 mtp_scache_p += sizeof(bcm_gport_t); 8589 } 8590 } else { 8591 for (idx = 0; idx < MIRROR_CONFIG(unit)->ing_mtp_count; idx++) { 8592 sal_memcpy(&(mtp_gport[idx]), 8593 mtp_scache_p, 8594 sizeof(bcm_gport_t)); 8595 mtp_scache_p += sizeof(bcm_gport_t); 8596 } 8597 8598 for (idx = 0; 8599 idx < MIRROR_CONFIG(unit)->egr_mtp_count; idx++) { 8600 sal_memcpy(&(mtp_gport[idx + BCM_MIRROR_MTP_COUNT]), 8601 mtp_scache_p, 8602 sizeof(bcm_gport_t)); 8603 mtp_scache_p += sizeof(bcm_gport_t); 8604 } 8605 } 8606 #ifdef BCM_TRIUMPH2_SUPPORT 8607 if (soc_feature(unit, soc_feature_egr_mirror_true)) { 8608 for (idx = 0; 8609 idx < MIRROR_CONFIG(unit)->egr_true_mtp_count; idx++) { 8610 sal_memcpy(&(mtp_gport[idx + (2 * BCM_MIRROR_MTP_COUNT)]), 8611 mtp_scache_p, 8612 sizeof(bcm_gport_t)); 8613 mtp_scache_p += sizeof(bcm_gport_t); 8614 } 8615 } 8616 #endif /* BCM_TRIUMPH2_SUPPORT */ 8617 8618 /* Recover destination flags */ 8619 if (soc_feature(unit, soc_feature_mirror_flexible) && 8620 MIRROR_MTP_METHOD_IS_DIRECTED_FLEXIBLE(unit)) { 8621 if (recovered_ver >= BCM_WB_VERSION_1_2) { 8622 int alloc_sz = 0; 8623 8624 BCM_IF_ERROR_RETURN 8625 (_bcm_esw_mirror_scache_version_incremental_size_get(unit, 8626 BCM_WB_VERSION_1_1, 8627 &alloc_sz)); 8628 8629 /* Directed flexible mirror recovery is done later, skip it to recover flags first */ 8630 mtp_scache_p += alloc_sz; 8631 for (idx = 0; idx < MIRROR_CONFIG(unit)->ing_mtp_count; idx++) { 8632 sal_memcpy(&(dest_flags[idx]), 8633 mtp_scache_p, 8634 sizeof(uint32)); 8635 mtp_scache_p += sizeof(uint32); 8636 } 8637 8638 for (idx = 0; 8639 idx < MIRROR_CONFIG(unit)->egr_mtp_count; idx++) { 8640 sal_memcpy(&(dest_flags[idx + BCM_MIRROR_MTP_COUNT]), 8641 mtp_scache_p, 8642 sizeof(uint32)); 8643 mtp_scache_p += sizeof(uint32); 8644 } 8645 8646 #ifdef BCM_TRIUMPH2_SUPPORT 8647 if (soc_feature(unit, soc_feature_egr_mirror_true)) { 8648 for (idx = 0; 8649 idx < MIRROR_CONFIG(unit)->egr_true_mtp_count; idx++) { 8650 sal_memcpy(&(dest_flags[idx + (2 * BCM_MIRROR_MTP_COUNT)]), 8651 mtp_scache_p, 8652 sizeof(uint32)); 8653 mtp_scache_p += sizeof(uint32); 8654 } 8655 } 8656 #endif /* BCM_TRIUMPH2_SUPPORT */ 8657 } else { 8658 int alloc_sz = 0; 8659 BCM_IF_ERROR_RETURN 8660 (_bcm_esw_mirror_scache_version_incremental_size_get(unit, 8661 BCM_WB_VERSION_1_2, 8662 &alloc_sz)); 8663 extra_scache_size += alloc_sz; 8664 } 8665 } 8666 8667 #ifdef BCM_TRIUMPH2_SUPPORT 8668 /* Recover destination flags for non-flexible mtp mirror */ 8669 if (soc_feature(unit, soc_feature_mirror_flexible) && 8670 !MIRROR_MTP_METHOD_IS_DIRECTED_FLEXIBLE(unit)) { 8671 if (recovered_ver >= BCM_WB_VERSION_1_3) { 8672 /* Recover flags of shared mtp destination */ 8673 for (idx = 0; idx < BCM_MIRROR_MTP_COUNT; idx++) { 8674 sal_memcpy(&(non_flexible_mtp_dest_flags[idx]), 8675 mtp_scache_p, 8676 sizeof(uint32)); 8677 mtp_scache_p += sizeof(uint32); 8678 } 8679 8680 /* Recover flags of egress true mtp destination */ 8681 if (soc_feature(unit, soc_feature_egr_mirror_true)) { 8682 for (idx = 0; 8683 idx < MIRROR_CONFIG(unit)->egr_true_mtp_count; idx++) { 8684 sal_memcpy(&(non_flexible_mtp_dest_flags[idx + BCM_MIRROR_MTP_COUNT]), 8685 mtp_scache_p, 8686 sizeof(uint32)); 8687 mtp_scache_p += sizeof(uint32); 8688 } 8689 } 8690 } else { 8691 int alloc_sz = 0; 8692 BCM_IF_ERROR_RETURN 8693 (_bcm_esw_mirror_scache_version_incremental_size_get(unit, 8694 BCM_WB_VERSION_1_3, 8695 &alloc_sz)); 8696 extra_scache_size += alloc_sz; 8697 } 8698 } 8699 #endif /* BCM_TRIUMPH2_SUPPORT */ 8700 8701 #ifdef BCM_TRIUMPH2_SUPPORT 8702 if (soc_feature(unit, soc_feature_mirror_flexible) && 8703 !MIRROR_MTP_METHOD_IS_DIRECTED_FLEXIBLE(unit) && 8704 NULL != mtp_scache_p) { 8705 if (recovered_ver >= BCM_WB_VERSION_1_4) { 8706 /* Recover Shared MTP ref_count */ 8707 for (idx = 0; idx < BCM_MIRROR_MTP_COUNT; idx++) { 8708 sal_memcpy(&(shared_mtp_ref_count[idx]), 8709 mtp_scache_p, 8710 sizeof(int)); 8711 mtp_scache_p += sizeof(int); 8712 } 8713 8714 /* Recover Egress True MTP ref_count */ 8715 if (soc_feature(unit, soc_feature_egr_mirror_true)) { 8716 for (idx = 0; 8717 idx < MIRROR_CONFIG(unit)->egr_true_mtp_count; idx++) { 8718 sal_memcpy(&(egr_true_mtp_ref_count[idx]), 8719 mtp_scache_p, 8720 sizeof(int)); 8721 mtp_scache_p += sizeof(int); 8722 } 8723 } 8724 8725 /* Recover Mirror Destination ref_count */ 8726 for (idx = 0; idx < MIRROR_CONFIG(unit)->dest_count; idx++) { 8727 sal_memcpy(&(mirror_dest_ref_count[idx]), 8728 mtp_scache_p, sizeof(int)); 8729 mtp_scache_p += sizeof(int); 8730 } 8731 8732 /* Recover MIRROR_CONFIG_MODE */ 8733 sal_memcpy(&mirror_config_mode, mtp_scache_p, sizeof(int)); 8734 mtp_scache_p += sizeof(int); 8735 } else { 8736 int alloc_sz = 0; 8737 BCM_IF_ERROR_RETURN 8738 (_bcm_esw_mirror_scache_version_incremental_size_get(unit, 8739 BCM_WB_VERSION_1_4, 8740 &alloc_sz)); 8741 extra_scache_size += alloc_sz; 8742 } 8743 } 8744 #endif 8745 8746 #ifdef BCM_TRIDENT2_SUPPORT 8747 /* Recover MTP destination gport. */ 8748 if (soc_feature(unit, soc_feature_mirror_flexible)) { 8749 if (recovered_ver >= BCM_WB_VERSION_1_5) { 8750 if (MIRROR_MTP_METHOD_IS_DIRECTED_FLEXIBLE(unit)) { 8751 /* Recover Ingress MTP destination gport. */ 8752 for (idx = 0; idx < BCM_SWITCH_TRUNK_MAX_PORTCNT * 8753 MIRROR_CONFIG(unit)->ing_mtp_count; 8754 idx++) { 8755 sal_memcpy(&(ing_mtp_dest_gport[idx]), 8756 mtp_scache_p, 8757 sizeof(bcm_gport_t)); 8758 mtp_scache_p += sizeof(bcm_gport_t); 8759 } 8760 8761 /* Recover Egress MTP destination gport. */ 8762 for (idx = 0; idx < BCM_SWITCH_TRUNK_MAX_PORTCNT * 8763 MIRROR_CONFIG(unit)->egr_mtp_count; 8764 idx++) { 8765 sal_memcpy(&(egr_mtp_dest_gport[idx]), 8766 mtp_scache_p, 8767 sizeof(bcm_gport_t)); 8768 mtp_scache_p += sizeof(bcm_gport_t); 8769 } 8770 8771 /* Recover Ingress MTP destination flags. */ 8772 for (idx = 0; idx < BCM_SWITCH_TRUNK_MAX_PORTCNT * 8773 MIRROR_CONFIG(unit)->ing_mtp_count; 8774 idx++) { 8775 sal_memcpy(&(ing_mtp_dest_flags[idx]), 8776 mtp_scache_p, 8777 sizeof(bcm_gport_t)); 8778 mtp_scache_p += sizeof(bcm_gport_t); 8779 } 8780 8781 /* Recover Egress MTP destination flags. */ 8782 for (idx = 0; idx < BCM_SWITCH_TRUNK_MAX_PORTCNT * 8783 MIRROR_CONFIG(unit)->egr_mtp_count; 8784 idx++) { 8785 sal_memcpy(&(egr_mtp_dest_flags[idx]), 8786 mtp_scache_p, 8787 sizeof(bcm_gport_t)); 8788 mtp_scache_p += sizeof(bcm_gport_t); 8789 } 8790 } else { 8791 /* Recover Shared MTP destination gport. */ 8792 for (idx = 0; idx < BCM_SWITCH_TRUNK_MAX_PORTCNT * 8793 BCM_MIRROR_MTP_COUNT; 8794 idx++) { 8795 sal_memcpy(&(shared_mtp_dest_gport[idx]), 8796 mtp_scache_p, 8797 sizeof(bcm_gport_t)); 8798 mtp_scache_p += sizeof(bcm_gport_t); 8799 } 8800 8801 /* Recover Shared MTP destination flags. */ 8802 for (idx = 0; idx < BCM_SWITCH_TRUNK_MAX_PORTCNT * 8803 BCM_MIRROR_MTP_COUNT; 8804 idx++) { 8805 sal_memcpy(&(shared_mtp_dest_flags[idx]), 8806 mtp_scache_p, 8807 sizeof(bcm_gport_t)); 8808 mtp_scache_p += sizeof(bcm_gport_t); 8809 } 8810 } 8811 } else { 8812 int alloc_sz = 0; 8813 BCM_IF_ERROR_RETURN 8814 (_bcm_esw_mirror_scache_version_incremental_size_get(unit, 8815 BCM_WB_VERSION_1_5, 8816 &alloc_sz)); 8817 extra_scache_size += alloc_sz; 8818 } 8819 } 8820 #endif /* BCM_TRIDENT2_SUPPORT */ 8821 #ifdef BCM_TRIUMPH2_SUPPORT 8822 if (soc_feature(unit, soc_feature_mirror_flexible) && 8823 MIRROR_MTP_METHOD_IS_DIRECTED_FLEXIBLE(unit) && 8824 NULL != mtp_scache_p) { 8825 if (recovered_ver >= BCM_WB_VERSION_1_6) { 8826 /* Recover Egress True MTP ref_count */ 8827 if (soc_feature(unit, soc_feature_egr_mirror_true)) { 8828 for (idx = 0; 8829 idx < MIRROR_CONFIG(unit)->egr_true_mtp_count; idx++) { 8830 sal_memcpy(&(egr_true_mtp_ref_count[idx]), 8831 mtp_scache_p, 8832 sizeof(int)); 8833 mtp_scache_p += sizeof(int); 8834 } 8835 } 8836 } else { 8837 int alloc_sz = 0; 8838 BCM_IF_ERROR_RETURN 8839 (_bcm_esw_mirror_scache_version_incremental_size_get(unit, 8840 BCM_WB_VERSION_1_6, 8841 &alloc_sz)); 8842 extra_scache_size += alloc_sz; 8843 } 8844 } 8845 #endif 8846 if (soc_feature(unit, soc_feature_mirror_flexible) && 8847 NULL != mtp_scache_p) { 8848 int alloc_sz = 0; 8849 8850 skip = FALSE; 8851 cur_td3_flag = 0; 8852 #ifdef BCM_TRIDENT3_SUPPORT 8853 cur_td3_flag = TRUE; 8854 #endif 8855 if (recovered_ver >= BCM_WB_VERSION_1_12) { 8856 if (!(wb_flags & WB_MIRROR_FLAGS_TD3)) { 8857 if (cur_td3_flag) { 8858 BCM_IF_ERROR_RETURN 8859 (_bcm_esw_mirror_scache_version_incremental_size_get( 8860 unit, BCM_WB_VERSION_1_7, &alloc_sz)); 8861 extra_scache_size += alloc_sz; 8862 } 8863 skip = TRUE; 8864 } else { 8865 if (!cur_td3_flag) { 8866 alloc_sz = sizeof(uint32) * BCM_MIRROR_MTP_COUNT; 8867 alloc_sz += sizeof(uint32); 8868 mtp_scache_p += alloc_sz; 8869 skip = TRUE; 8870 } 8871 } 8872 } 8873 if (skip == FALSE) { 8874 #ifdef BCM_TRIDENT3_SUPPORT 8875 if (recovered_ver >= BCM_WB_VERSION_1_7) { 8876 /* recover encap_to_edit_ctrl_id array. */ 8877 sal_memcpy(encap_to_edit_ctrl_id, mtp_scache_p, 8878 sizeof(uint32)*BCM_MIRROR_MTP_COUNT); 8879 mtp_scache_p += (sizeof(uint32)*BCM_MIRROR_MTP_COUNT); 8880 8881 /* recover encap_profile_index_bmap. */ 8882 sal_memcpy(&encap_profile_index_bmap, mtp_scache_p, 8883 sizeof(uint32)); 8884 mtp_scache_p += sizeof(uint32); 8885 } else { 8886 BCM_IF_ERROR_RETURN 8887 (_bcm_esw_mirror_scache_version_incremental_size_get( 8888 unit, BCM_WB_VERSION_1_7, &alloc_sz)); 8889 extra_scache_size += alloc_sz; 8890 } 8891 #endif /* BCM_TRIDENT3_SUPPORT */ 8892 } 8893 } 8894 } 8895 8896 if (soc_feature(unit, soc_feature_mirror_flexible) && 8897 MIRROR_MTP_METHOD_IS_DIRECTED_FLEXIBLE(unit) && 8898 NULL != mtp_scache_p) { 8899 if (recovered_ver >= BCM_WB_VERSION_1_8) { 8900 #if defined(BCM_TOMAHAWK3_SUPPORT) 8901 for (slot_type = BCM_MTP_SLOT_TYPE_INT; 8902 slot_type <= BCM_MTP_SLOT_TYPE_DLB_MONITOR; slot_type++) { 8903 /* Slot-MTP mapping information for respective slot type */ 8904 for (slot = 0; slot < MIRROR_CONFIG(unit)->mtp_slot_count[slot_type]; 8905 slot++) { 8906 sal_memcpy(&MIRROR_CONFIG_TYPE_MTP_SLOT(unit, slot, slot_type), 8907 mtp_scache_p, 8908 sizeof(bcm_gport_t)); 8909 mtp_scache_p += sizeof(bcm_gport_t); 8910 } 8911 /* Reference counter for respective slot type BCM_MTP_SLOT_TYPE_INT */ 8912 for (slot = 0; slot < MIRROR_CONFIG(unit)->mtp_slot_count[slot_type]; 8913 slot++) { 8914 sal_memcpy(&MIRROR_CONFIG_TYPE_MTP_REF_COUNT(unit, slot, slot_type), 8915 mtp_scache_p, 8916 sizeof(int)); 8917 mtp_scache_p += sizeof(int); 8918 } 8919 } 8920 #endif /* BCM_TOMAHAWK3_SUPPORT */ 8921 } else { 8922 int alloc_sz = 0; 8923 BCM_IF_ERROR_RETURN 8924 (_bcm_esw_mirror_scache_version_incremental_size_get(unit, 8925 BCM_WB_VERSION_1_8, 8926 &alloc_sz)); 8927 extra_scache_size += alloc_sz; 8928 } 8929 } 8930 8931 if (soc_feature(unit, soc_feature_th3_style_fp) && 8932 NULL != mtp_scache_p) { 8933 #ifdef BCM_TOMAHAWK3_SUPPORT 8934 if (recovered_ver >= BCM_WB_VERSION_1_9) { 8935 BCM_IF_ERROR_RETURN(_bcm_esw_mirror_zero_profile_get(unit, 8936 &profile)); 8937 if (profile == NULL) { 8938 return (BCM_E_INTERNAL); 8939 } 8940 8941 sal_memcpy(&mirror_zero_prof_info, mtp_scache_p, 8942 (sizeof(_bcm_mirror_zero_profile_t) * 8943 (MIRROR_ZERO_PROFILE_INDEX_MAX))); 8944 mtp_scache_p += (sizeof(_bcm_mirror_zero_profile_t) * 8945 (MIRROR_ZERO_PROFILE_INDEX_MAX)); 8946 for (index = 0; 8947 index <= (MIRROR_ZERO_PROFILE_INDEX_MAX 8948 - MIRROR_ZERO_PROFILE_INDEX_MIN); index++) { 8949 /* Increment the reference count for profile entry. */ 8950 SOC_PROFILE_MEM_REFERENCE(unit, profile, 8951 index, 8952 mirror_zero_prof_info[index].ref_count); 8953 SOC_PROFILE_MEM_ENTRIES_PER_SET(unit, profile, 8954 index, 8955 mirror_zero_prof_info[index].ref_count); 8956 } 8957 8958 } else { 8959 int alloc_sz = 0; 8960 BCM_IF_ERROR_RETURN 8961 (_bcm_esw_mirror_scache_version_incremental_size_get(unit, 8962 BCM_WB_VERSION_1_9, 8963 &alloc_sz)); 8964 extra_scache_size += alloc_sz; 8965 } 8966 #endif 8967 } 8968 8969 8970 #ifdef BCM_TRIUMPH2_SUPPORT 8971 if (soc_feature(unit, soc_feature_mirror_flexible) && 8972 !MIRROR_MTP_METHOD_IS_DIRECTED_FLEXIBLE(unit)) { 8973 BCM_IF_ERROR_RETURN(READ_MIRROR_SELECTr(unit, &ms_reg)); 8974 mtp_type = soc_reg_field_get(unit, MIRROR_SELECTr, ms_reg, MTP_TYPEf); 8975 /* ing_mtp_count works for both ingress and egress in shared mode */ 8976 for (idx = 0; idx < MIRROR_CONFIG(unit)->ing_mtp_count; idx++) { 8977 bcm_mirror_destination_t_init(&mirror_dest); 8978 mirror_dest.flags = non_flexible_mtp_dest_flags[idx]; 8979 flags = (mtp_type & (1 << idx)) ? 8980 BCM_MIRROR_PORT_EGRESS : BCM_MIRROR_PORT_INGRESS; 8981 8982 if (!(mirror_dest.flags & BCM_MIRROR_DEST_ID_SHARE)) { 8983 BCM_IF_ERROR_RETURN 8984 (_bcm_esw_mirror_mtp_to_modport(unit, idx, TRUE, flags, 8985 &modid, &gport)); 8986 8987 if (mirror_dest.flags & BCM_MIRROR_DEST_REPLACE) { 8988 if (BCM_GPORT_IS_SET(gport)) { 8989 mirror_dest.gport = gport; 8990 } else { 8991 _bcm_gport_dest_t gport_st; 8992 gport_st.gport_type = BCM_GPORT_TYPE_MODPORT; 8993 gport_st.modid = 0; 8994 gport_st.port = gport; 8995 BCM_IF_ERROR_RETURN( 8996 _bcm_esw_gport_construct(unit, 8997 &gport_st, 8998 &(mirror_dest.gport))); 8999 } 9000 /* Adapt miror destination gport */ 9001 BCM_IF_ERROR_RETURN( 9002 _bcm_mirror_gport_adapt(unit, &(mirror_dest.gport))); 9003 rv = BCM_E_NOT_FOUND; 9004 } else { 9005 rv = _bcm_esw_mirror_destination_find(unit, gport, 0, 9006 flags, &mirror_dest); 9007 } 9008 if (BCM_E_NOT_FOUND == rv) { 9009 if ((NULL != mtp_scache) && !stale_scache) { 9010 if (BCM_GPORT_IS_MIRROR(mtp_gport[idx])) { 9011 /* We have scratch memory of the destination IDs */ 9012 mirror_dest.mirror_dest_id = mtp_gport[idx]; 9013 mirror_dest.flags |= BCM_MIRROR_DEST_WITH_ID; 9014 if (0 == MIRROR_DEST_REF_COUNT(unit, mirror_dest.mirror_dest_id)) { 9015 BCM_IF_ERROR_RETURN 9016 (_bcm_esw_mirror_destination_create(unit, 9017 &mirror_dest)); 9018 } 9019 } /* Else, we know there isn't an MTP here */ 9020 } else { 9021 BCM_IF_ERROR_RETURN 9022 (_bcm_esw_mirror_destination_create(unit, &mirror_dest)); 9023 } 9024 } else if (BCM_FAILURE(rv)) { 9025 return rv; 9026 } else if ((NULL != mtp_scache) && !stale_scache && 9027 (BCM_GPORT_IS_MIRROR(mtp_gport[idx])) && 9028 (mirror_dest.mirror_dest_id != mtp_gport[idx])) { 9029 /* Warm Boot Level 2, the destination doesn't match! */ 9030 SOC_IF_ERROR_RETURN 9031 (soc_event_generate(unit, SOC_SWITCH_EVENT_STABLE_ERROR, 9032 SOC_STABLE_STALE, 0, 0)); 9033 stale_scache = TRUE; 9034 } 9035 if (BCM_GPORT_IS_MIRROR(mirror_dest.mirror_dest_id)) { 9036 MIRROR_CONFIG_SHARED_MTP_DEST(unit, idx) = 9037 mirror_dest.mirror_dest_id; 9038 if (!directed) { 9039 MIRROR_CONFIG_SHARED_MTP(unit, idx).egress = FALSE; 9040 MIRROR_CONFIG_SHARED_MTP_REF_COUNT(unit, idx)++; 9041 /* Egress update */ 9042 MIRROR_CONFIG_SHARED_MTP_DEST(unit, 9043 BCM_MIRROR_MTP_FLEX_EGRESS_D15_INDEX) = 9044 mirror_dest.mirror_dest_id; 9045 MIRROR_CONFIG_SHARED_MTP(unit, 9046 BCM_MIRROR_MTP_FLEX_EGRESS_D15_INDEX).egress = TRUE; 9047 MIRROR_CONFIG_SHARED_MTP_REF_COUNT(unit, 9048 BCM_MIRROR_MTP_FLEX_EGRESS_D15_INDEX)++; 9049 } else { 9050 MIRROR_CONFIG_SHARED_MTP(unit, idx).egress = 9051 (0 != (flags & BCM_MIRROR_PORT_EGRESS)); 9052 } 9053 } 9054 } 9055 #ifdef BCM_TRIDENT2_SUPPORT 9056 else { 9057 if ((NULL != mtp_scache) && !stale_scache) { 9058 if (BCM_GPORT_IS_MIRROR(mtp_gport[idx])) { 9059 BCM_IF_ERROR_RETURN( 9060 _bcm_td2_mirror_shared_dest_recover( 9061 unit, flags, mtp_gport[idx], 9062 mirror_dest.flags, idx, 9063 shared_mtp_dest_gport, shared_mtp_dest_flags)); 9064 } 9065 } 9066 } 9067 #endif /* BCM_TRIDENT2_SUPPORT */ 9068 } 9069 } else 9070 #endif /* BCM_TRIUMPH2_SUPPORT */ 9071 { 9072 for (idx = 0; idx < MIRROR_CONFIG(unit)->ing_mtp_count; idx++) { 9073 bcm_mirror_destination_t_init(&mirror_dest); 9074 mirror_dest.flags = dest_flags[idx]; 9075 9076 if (!(mirror_dest.flags & BCM_MIRROR_DEST_ID_SHARE)) { 9077 BCM_IF_ERROR_RETURN 9078 (_bcm_esw_mirror_mtp_to_modport(unit, idx, TRUE, 9079 BCM_MIRROR_PORT_INGRESS, &modid, &gport)); 9080 9081 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_GREYHOUND_SUPPORT) 9082 if (soc_feature(unit, soc_feature_mirror_encap_profile)) { 9083 int max_num_trunk_ports; 9084 #ifdef BCM_METROLITE_SUPPORT 9085 if (soc_feature(unit, soc_feature_mirror_four_port_trunk)) { 9086 max_num_trunk_ports = 4; 9087 } else 9088 #endif 9089 { 9090 #ifdef BCM_TOMAHAWK3_SUPPORT 9091 if (SOC_IS_TOMAHAWK3(unit)) { 9092 max_num_trunk_ports = 1; 9093 } else 9094 #endif /* BCM_TOMAHAWK3_SUPPORT */ 9095 { 9096 max_num_trunk_ports = BCM_SWITCH_TRUNK_MAX_PORTCNT; 9097 } 9098 } 9099 9100 BCM_IF_ERROR_RETURN 9101 (_bcm_esw_mirror_dest_tunnel_flags_get( 9102 unit, FALSE, 9103 idx * max_num_trunk_ports, 9104 &mirror_dest.flags, 9105 &mirror_dest.flags2)); 9106 } 9107 #endif 9108 9109 if (BCM_GPORT_IS_SET(gport)) { 9110 mirror_dest.gport = gport; 9111 } else { 9112 _bcm_gport_dest_t gport_st; 9113 gport_st.gport_type = BCM_GPORT_TYPE_MODPORT; 9114 gport_st.modid = 0; 9115 gport_st.port = gport; 9116 BCM_IF_ERROR_RETURN( 9117 _bcm_esw_gport_construct(unit, &gport_st, 9118 &(mirror_dest.gport))); 9119 } 9120 /* Adapt miror destination gport */ 9121 BCM_IF_ERROR_RETURN( 9122 _bcm_mirror_gport_adapt(unit, &(mirror_dest.gport))); 9123 9124 #if defined(BCM_TRIDENT_SUPPORT) 9125 if (soc_feature(unit, soc_feature_mirror_flexible) && 9126 MIRROR_MTP_METHOD_IS_DIRECTED_FLEXIBLE(unit)) { 9127 int max_num_trunk_ports; 9128 #ifdef BCM_METROLITE_SUPPORT 9129 if (soc_feature(unit, soc_feature_mirror_four_port_trunk)) { 9130 max_num_trunk_ports = 4; 9131 } else 9132 #endif 9133 { 9134 #ifdef BCM_TOMAHAWK3_SUPPORT 9135 if (SOC_IS_TOMAHAWK3(unit)) { 9136 max_num_trunk_ports = 1; 9137 } else 9138 #endif /* BCM_TOMAHAWK3_SUPPORT */ 9139 { 9140 max_num_trunk_ports = BCM_SWITCH_TRUNK_MAX_PORTCNT; 9141 } 9142 } 9143 9144 BCM_IF_ERROR_RETURN( 9145 _bcm_td_mirror_destination_pri_recover( 9146 unit, &mirror_dest, 9147 idx * max_num_trunk_ports, 9148 BCM_MIRROR_PORT_INGRESS)); 9149 } 9150 #endif 9151 9152 if ((NULL != mtp_scache) && !stale_scache) { 9153 if (BCM_GPORT_IS_MIRROR(mtp_gport[idx])) { 9154 /* We have scratch memory of the destination IDs */ 9155 mirror_dest.mirror_dest_id = mtp_gport[idx]; 9156 mirror_dest.flags |= BCM_MIRROR_DEST_WITH_ID; 9157 if (0 == MIRROR_DEST_REF_COUNT(unit, mirror_dest.mirror_dest_id)) { 9158 BCM_IF_ERROR_RETURN( 9159 _bcm_esw_mirror_destination_create( 9160 unit, &mirror_dest)); 9161 } 9162 } /* Else, we know there isn't an MTP here */ 9163 } else { 9164 BCM_IF_ERROR_RETURN 9165 (_bcm_esw_mirror_destination_create(unit, &mirror_dest)); 9166 } 9167 9168 9169 if (BCM_GPORT_IS_MIRROR(mirror_dest.mirror_dest_id)) { 9170 MIRROR_CONFIG_ING_MTP_DEST(unit, idx) = 9171 mirror_dest.mirror_dest_id; 9172 if (!directed) { 9173 MIRROR_CONFIG_ING_MTP_REF_COUNT(unit, idx)++; 9174 } 9175 } 9176 } 9177 #ifdef BCM_TRIDENT2_SUPPORT 9178 else { 9179 if ((NULL != mtp_scache) && !stale_scache) { 9180 if (BCM_GPORT_IS_MIRROR(mtp_gport[idx])) { 9181 BCM_IF_ERROR_RETURN( 9182 _bcm_td2_mirror_shared_dest_recover( 9183 unit, BCM_MIRROR_PORT_INGRESS, mtp_gport[idx], 9184 mirror_dest.flags, idx, 9185 ing_mtp_dest_gport, ing_mtp_dest_flags)); 9186 } 9187 } 9188 } 9189 #endif /* BCM_TRIDENT2_SUPPORT */ 9190 } 9191 9192 for (idx = 0; idx < MIRROR_CONFIG(unit)->egr_mtp_count; idx++) { 9193 bcm_mirror_destination_t_init(&mirror_dest); 9194 mirror_dest.flags = dest_flags[idx + BCM_MIRROR_MTP_COUNT]; 9195 9196 if (!(mirror_dest.flags & BCM_MIRROR_DEST_ID_SHARE)) { 9197 BCM_IF_ERROR_RETURN 9198 (_bcm_esw_mirror_mtp_to_modport(unit, idx, TRUE, 9199 BCM_MIRROR_PORT_EGRESS, &modid, &gport)); 9200 9201 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_GREYHOUND_SUPPORT) 9202 if (soc_feature(unit, soc_feature_mirror_encap_profile)) { 9203 int max_num_trunk_ports; 9204 #ifdef BCM_METROLITE_SUPPORT 9205 if (soc_feature(unit, soc_feature_mirror_four_port_trunk)) { 9206 max_num_trunk_ports = 4; 9207 } else 9208 #endif 9209 { 9210 #ifdef BCM_TOMAHAWK3_SUPPORT 9211 if (SOC_IS_TOMAHAWK3(unit)) { 9212 max_num_trunk_ports = 1; 9213 /* We use offset = index below since 9214 * EGR_IM/EM_MTP_INDEX are * 4 entries deep 9215 */ 9216 } else 9217 #endif /* BCM_TOMAHAWK3_SUPPORT */ 9218 { 9219 max_num_trunk_ports = BCM_SWITCH_TRUNK_MAX_PORTCNT; 9220 } 9221 } 9222 9223 BCM_IF_ERROR_RETURN 9224 (_bcm_esw_mirror_dest_tunnel_flags_get( 9225 unit, TRUE, 9226 idx * max_num_trunk_ports, 9227 &mirror_dest.flags, 9228 &mirror_dest.flags2)); 9229 } 9230 #endif 9231 9232 if (BCM_GPORT_IS_SET(gport)) { 9233 mirror_dest.gport = gport; 9234 } else { 9235 _bcm_gport_dest_t gport_st; 9236 gport_st.gport_type = BCM_GPORT_TYPE_MODPORT; 9237 gport_st.modid = 0; 9238 gport_st.port = gport; 9239 BCM_IF_ERROR_RETURN( 9240 _bcm_esw_gport_construct(unit, &gport_st, &(mirror_dest.gport))); 9241 } 9242 /* Adapt miror destination gport */ 9243 BCM_IF_ERROR_RETURN( 9244 _bcm_mirror_gport_adapt(unit, &(mirror_dest.gport))); 9245 9246 #if defined(BCM_TRIDENT_SUPPORT) 9247 if (soc_feature(unit, soc_feature_mirror_flexible) && 9248 MIRROR_MTP_METHOD_IS_DIRECTED_FLEXIBLE(unit)) { 9249 int max_num_trunk_ports; 9250 #ifdef BCM_METROLITE_SUPPORT 9251 if (soc_feature(unit, soc_feature_mirror_four_port_trunk)) { 9252 max_num_trunk_ports = 4; 9253 } else 9254 #endif 9255 { 9256 #ifdef BCM_TOMAHAWK3_SUPPORT 9257 if (SOC_IS_TOMAHAWK3(unit)) { 9258 max_num_trunk_ports = 1; 9259 /* We use offset = index below since 9260 * EGR_IM/EM_MTP_INDEX are * 4 entries deep 9261 */ 9262 } else 9263 #endif /* BCM_TOMAHAWK3_SUPPORT */ 9264 { 9265 max_num_trunk_ports = BCM_SWITCH_TRUNK_MAX_PORTCNT; 9266 } 9267 } 9268 BCM_IF_ERROR_RETURN( 9269 _bcm_td_mirror_destination_pri_recover( 9270 unit, &mirror_dest, 9271 idx * max_num_trunk_ports, 9272 BCM_MIRROR_PORT_EGRESS)); 9273 } 9274 #endif 9275 9276 if ((NULL != mtp_scache) && !stale_scache) { 9277 if (BCM_GPORT_IS_MIRROR(mtp_gport[idx + 9278 BCM_MIRROR_MTP_COUNT])) { 9279 rv = bcm_esw_mirror_destination_get(unit, 9280 mtp_gport[idx + BCM_MIRROR_MTP_COUNT], &mirror_dest); 9281 if (rv == BCM_E_NOT_FOUND) { 9282 /* We have scratch memory of the destination IDs */ 9283 mirror_dest.mirror_dest_id = mtp_gport[idx + 9284 BCM_MIRROR_MTP_COUNT]; 9285 mirror_dest.flags |= BCM_MIRROR_DEST_WITH_ID; 9286 rv = _bcm_esw_mirror_destination_create(unit, 9287 &mirror_dest); 9288 BCM_IF_ERROR_RETURN(rv); 9289 } 9290 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_GREYHOUND_SUPPORT) 9291 if (soc_feature(unit, soc_feature_mirror_encap_profile)) { 9292 if ((mirror_dest.flags & BCM_MIRROR_DEST_TUNNELS) || 9293 (mirror_dest.flags2 & BCM_MIRROR_DEST_FLAGS2_TUNNELS)) { 9294 if (BCM_FAILURE(rv) && (rv != BCM_E_EXISTS)) { 9295 return rv; 9296 } 9297 } else { 9298 if (BCM_FAILURE(rv)) { 9299 return rv; 9300 } 9301 } 9302 } else { 9303 if (BCM_FAILURE(rv)) { 9304 return rv; 9305 } 9306 } 9307 #else 9308 if (BCM_FAILURE(rv)) { 9309 return rv; 9310 } 9311 #endif 9312 } /* Else, we know there isn't an MTP here */ 9313 } else { 9314 BCM_IF_ERROR_RETURN 9315 (_bcm_esw_mirror_destination_create(unit, &mirror_dest)); 9316 } 9317 9318 if (BCM_GPORT_IS_MIRROR(mirror_dest.mirror_dest_id)) { 9319 MIRROR_CONFIG_EGR_MTP_DEST(unit, idx) = 9320 mirror_dest.mirror_dest_id; 9321 if (!directed) { 9322 MIRROR_CONFIG_EGR_MTP_REF_COUNT(unit, idx)++; 9323 } 9324 } 9325 } 9326 #ifdef BCM_TRIDENT2_SUPPORT 9327 else { 9328 if ((NULL != mtp_scache) && !stale_scache) { 9329 if (BCM_GPORT_IS_MIRROR( 9330 mtp_gport[idx + BCM_MIRROR_MTP_COUNT])) { 9331 BCM_IF_ERROR_RETURN( 9332 _bcm_td2_mirror_shared_dest_recover( 9333 unit, BCM_MIRROR_PORT_EGRESS, 9334 mtp_gport[idx + BCM_MIRROR_MTP_COUNT], 9335 mirror_dest.flags, idx, 9336 egr_mtp_dest_gport, egr_mtp_dest_flags)); 9337 } 9338 } 9339 } 9340 #endif /* BCM_TRIDENT2_SUPPORT */ 9341 } 9342 } 9343 #ifdef BCM_TRIUMPH2_SUPPORT 9344 if (soc_feature(unit, soc_feature_egr_mirror_true) && directed) { 9345 for (idx = 0; idx < MIRROR_CONFIG(unit)->egr_true_mtp_count; idx++) { 9346 BCM_IF_ERROR_RETURN 9347 (_bcm_esw_mirror_mtp_to_modport(unit, idx, TRUE, 9348 BCM_MIRROR_PORT_EGRESS_TRUE, &modid, &gport)); 9349 bcm_mirror_destination_t_init(&mirror_dest); 9350 if (soc_feature(unit, soc_feature_mirror_flexible) && 9351 MIRROR_MTP_METHOD_IS_DIRECTED_FLEXIBLE(unit)) { 9352 mirror_dest.flags = dest_flags[idx + (2 * BCM_MIRROR_MTP_COUNT)]; 9353 } else { 9354 mirror_dest.flags = non_flexible_mtp_dest_flags[idx + BCM_MIRROR_MTP_COUNT]; 9355 } 9356 9357 if (BCM_GPORT_IS_SET(gport)) { 9358 mirror_dest.gport = gport; 9359 } else { 9360 _bcm_gport_dest_t gport_st; 9361 gport_st.gport_type = BCM_GPORT_TYPE_MODPORT; 9362 gport_st.modid = 0; 9363 gport_st.port = gport; 9364 BCM_IF_ERROR_RETURN( 9365 _bcm_esw_gport_construct(unit, 9366 &gport_st, 9367 &(mirror_dest.gport))); 9368 } 9369 /* Adapt miror destination gport */ 9370 BCM_IF_ERROR_RETURN( 9371 _bcm_mirror_gport_adapt(unit, &(mirror_dest.gport))); 9372 9373 9374 #if defined(BCM_TRIDENT_SUPPORT) 9375 if (soc_feature(unit, soc_feature_mirror_flexible) && 9376 MIRROR_MTP_METHOD_IS_DIRECTED_FLEXIBLE(unit)) { 9377 int max_num_trunk_ports; 9378 #ifdef BCM_METROLITE_SUPPORT 9379 if (soc_feature(unit, soc_feature_mirror_four_port_trunk)) { 9380 max_num_trunk_ports = 4; 9381 } else 9382 #endif 9383 { 9384 #ifdef BCM_TOMAHAWK3_SUPPORT 9385 if (SOC_IS_TOMAHAWK3(unit)) { 9386 max_num_trunk_ports = 1; 9387 /* We use offset = index below since 9388 * EGR_IM/EM_MTP_INDEX are * 4 entries deep 9389 */ 9390 } else 9391 #endif /* BCM_TOMAHAWK3_SUPPORT */ 9392 { 9393 max_num_trunk_ports = BCM_SWITCH_TRUNK_MAX_PORTCNT; 9394 } 9395 } 9396 9397 BCM_IF_ERROR_RETURN( 9398 _bcm_td_mirror_destination_pri_recover( 9399 unit, &mirror_dest, 9400 idx * max_num_trunk_ports, 9401 BCM_MIRROR_PORT_EGRESS_TRUE)); 9402 } 9403 #endif 9404 if ((NULL != mtp_scache) && !stale_scache) { 9405 if (BCM_GPORT_IS_MIRROR(mtp_gport[idx + 9406 (2 * BCM_MIRROR_MTP_COUNT)])) { 9407 rv = bcm_esw_mirror_destination_get(unit, 9408 mtp_gport[idx + (2 * BCM_MIRROR_MTP_COUNT)], &mirror_dest); 9409 if (rv == BCM_E_NOT_FOUND) { 9410 /* We have scratch memory of the destination IDs */ 9411 mirror_dest.mirror_dest_id = 9412 mtp_gport[idx + (2 * BCM_MIRROR_MTP_COUNT)]; 9413 mirror_dest.flags |= BCM_MIRROR_DEST_WITH_ID; 9414 rv = _bcm_esw_mirror_destination_create(unit, 9415 &mirror_dest); 9416 BCM_IF_ERROR_RETURN(rv); 9417 } 9418 } /* Else, we know there isn't an MTP here */ 9419 } else { 9420 BCM_IF_ERROR_RETURN 9421 (_bcm_esw_mirror_destination_create(unit, 9422 &mirror_dest)); 9423 } 9424 9425 if (BCM_GPORT_IS_MIRROR(mirror_dest.mirror_dest_id)) { 9426 MIRROR_CONFIG_EGR_TRUE_MTP_DEST(unit, idx) = 9427 mirror_dest.mirror_dest_id; 9428 if (!directed) { 9429 MIRROR_CONFIG_EGR_TRUE_MTP_REF_COUNT(unit, idx)++; 9430 } 9431 } 9432 } 9433 } 9434 #endif /* BCM_TRIUMPH2_SUPPORT */ 9435 9436 if (directed) { 9437 #ifdef BCM_TRIUMPH2_SUPPORT 9438 if (soc_feature(unit, soc_feature_mirror_flexible)) { 9439 BCM_IF_ERROR_RETURN(READ_MIRROR_SELECTr(unit, &ms_reg)); 9440 mtp_type = soc_reg_field_get(unit, MIRROR_SELECTr, ms_reg, MTP_TYPEf); 9441 /* In directed flexible mirror, the global MTP ingress or egress 9442 * status is recorded via MIRROR_CONFIG_MTP_MODE_BMP. 9443 * MIRROR_CONFIG_MTP_MODE_BMP(unit) should be recovered 9444 * from register MIRROR_SELECT. 9445 */ 9446 if (MIRROR_MTP_METHOD_IS_DIRECTED_FLEXIBLE(unit)) { 9447 MIRROR_CONFIG_MTP_MODE_BMP(unit) = mtp_type; 9448 } 9449 } 9450 #endif /* BCM_TRIUMPH2_SUPPORT */ 9451 9452 PBMP_ITER(all_pbmp, port_ix) { 9453 #if defined(BCM_TRIDENT_SUPPORT) 9454 if (soc_feature(unit, soc_feature_mirror_control_mem)) { 9455 BCM_IF_ERROR_RETURN 9456 (READ_MIRROR_CONTROLm(unit, MEM_BLOCK_ANY, 9457 port_ix, &mc_entry)); 9458 mc_enable = soc_MIRROR_CONTROLm_field32_get(unit, &mc_entry, 9459 M_ENABLEf); 9460 } else 9461 #endif /* BCM_TRIDENT_SUPPORT */ 9462 { 9463 BCM_IF_ERROR_RETURN 9464 (READ_MIRROR_CONTROLr(unit, port_ix, ®_val)); 9465 mc_enable = soc_reg_field_get(unit, MIRROR_CONTROLr, 9466 reg_val, M_ENABLEf); 9467 } 9468 if (mc_enable) { 9469 #ifdef BCM_TRIUMPH2_SUPPORT 9470 if (soc_feature(unit, soc_feature_mirror_flexible)) { 9471 /* Read ingress mtp enable bitmap for source port. */ 9472 BCM_IF_ERROR_RETURN 9473 (_bcm_esw_mirror_ingress_get(unit, port_ix, &enable)); 9474 for (mtp_index = 0; mtp_index < BCM_MIRROR_MTP_COUNT; 9475 mtp_index++) { 9476 if (enable & (1 << mtp_index)) { 9477 /* Used slot get MTP index*/ 9478 #if defined(BCM_TRIDENT_SUPPORT) 9479 if (soc_feature(unit, 9480 soc_feature_mirror_control_mem)) { 9481 idx = soc_MIRROR_CONTROLm_field32_get(unit, 9482 &mc_entry, 9483 _mtp_index_field[mtp_index]); 9484 } else 9485 #endif /* BCM_TRIDENT_SUPPORT */ 9486 { 9487 idx = soc_reg_field_get(unit, 9488 MIRROR_CONTROLr, reg_val, 9489 _mtp_index_field[mtp_index]); 9490 } 9491 9492 if (!MIRROR_MTP_METHOD_IS_DIRECTED_FLEXIBLE(unit)) { 9493 /* Ingress or egress? */ 9494 if (mtp_type & (1 << mtp_index)) { 9495 /* Ingress mirroring was enabled, but type is 9496 * egress. */ 9497 return BCM_E_INTERNAL; 9498 } else if (TRUE == 9499 MIRROR_CONFIG_SHARED_MTP(unit, idx).egress) { 9500 /* Mismatched ingress/egress settings */ 9501 return BCM_E_INTERNAL; 9502 } else { 9503 /* Ingress */ 9504 MIRROR_CONFIG_SHARED_MTP_REF_COUNT(unit, idx)++; 9505 MIRROR_DEST_REF_COUNT(unit, 9506 MIRROR_CONFIG_SHARED_MTP_DEST(unit, idx))++; 9507 } 9508 } 9509 } 9510 } 9511 /* Read ingress mtp enable bitmap for source port. */ 9512 BCM_IF_ERROR_RETURN 9513 (_bcm_esw_mirror_egress_get(unit, port_ix, &enable)); 9514 for (mtp_index = 0; mtp_index < BCM_MIRROR_MTP_COUNT; 9515 mtp_index++) { 9516 if (enable & (1 << mtp_index)) { 9517 /* Used slot get MTP index*/ 9518 #if defined(BCM_TRIDENT_SUPPORT) 9519 if (soc_feature(unit, 9520 soc_feature_mirror_control_mem)) { 9521 idx = soc_MIRROR_CONTROLm_field32_get(unit, 9522 &mc_entry, 9523 _mtp_index_field[mtp_index]); 9524 } else 9525 #endif /* BCM_TRIDENT_SUPPORT */ 9526 { 9527 idx = soc_reg_field_get(unit, 9528 MIRROR_CONTROLr, reg_val, 9529 _mtp_index_field[mtp_index]); 9530 } 9531 if (!MIRROR_MTP_METHOD_IS_DIRECTED_FLEXIBLE(unit)) { 9532 /* Ingress or egress? */ 9533 if (FALSE == 9534 MIRROR_CONFIG_SHARED_MTP(unit, idx).egress) { 9535 /* Mismatched ingress/egress settings */ 9536 return BCM_E_INTERNAL; 9537 } else if (mtp_type & (1 << mtp_index)) { 9538 /* Egress */ 9539 MIRROR_CONFIG_SHARED_MTP_REF_COUNT(unit, idx)++; 9540 MIRROR_DEST_REF_COUNT(unit, 9541 MIRROR_CONFIG_SHARED_MTP_DEST(unit, idx))++; 9542 } else { 9543 /* Egress mirroring was enabled, but type is 9544 * ingress. */ 9545 return BCM_E_INTERNAL; 9546 } 9547 } 9548 } 9549 } 9550 } else 9551 #endif /* BCM_TRIUMPH2_SUPPORT */ 9552 { 9553 BCM_IF_ERROR_RETURN 9554 (bcm_esw_mirror_ingress_get(unit, port_ix, &enable)); 9555 if (enable) { 9556 idx = soc_reg_field_get(unit, MIRROR_CONTROLr, 9557 reg_val, IM_MTP_INDEXf); 9558 MIRROR_CONFIG_ING_MTP_REF_COUNT(unit, idx)++; 9559 MIRROR_DEST_REF_COUNT(unit, 9560 MIRROR_CONFIG_ING_MTP_DEST(unit, idx))++; 9561 } 9562 BCM_IF_ERROR_RETURN 9563 (_bcm_esw_mirror_egress_get(unit, port_ix, &enable)); 9564 if (enable) { 9565 idx = soc_reg_field_get(unit, MIRROR_CONTROLr, 9566 reg_val, EM_MTP_INDEXf); 9567 MIRROR_CONFIG_EGR_MTP_REF_COUNT(unit, idx)++; 9568 MIRROR_DEST_REF_COUNT(unit, 9569 MIRROR_CONFIG_EGR_MTP_DEST(unit, idx))++; 9570 } 9571 } 9572 } 9573 9574 #ifdef BCM_TRIUMPH2_SUPPORT 9575 if (soc_feature(unit, soc_feature_egr_mirror_true)) { 9576 BCM_IF_ERROR_RETURN 9577 (_bcm_port_mirror_egress_true_enable_get(unit, port_ix, 9578 &enable)); 9579 for (mtp_index = 0; mtp_index < BCM_MIRROR_MTP_COUNT; 9580 mtp_index++) { 9581 if (enable & (1 << mtp_index)) { 9582 /* Egress true mirroring doesn't need mtp_slot 9583 * remapping. */ 9584 MIRROR_CONFIG_EGR_TRUE_MTP_REF_COUNT(unit, 9585 mtp_index)++; 9586 MIRROR_DEST_REF_COUNT(unit, 9587 MIRROR_CONFIG_EGR_TRUE_MTP_DEST(unit, 9588 mtp_index))++; 9589 } 9590 } 9591 } 9592 #endif /* BCM_TRIUMPH2_SUPPORT */ 9593 } 9594 if (soc_feature(unit, soc_feature_mirror_flexible) && 9595 MIRROR_MTP_METHOD_IS_DIRECTED_FLEXIBLE(unit)) { 9596 BCM_IF_ERROR_RETURN(_bcm_esw_directed_flexible_mirror_recover(unit)); 9597 } 9598 /* recover virtual port mtp usage reference counters */ 9599 BCM_IF_ERROR_RETURN(_bcm_mirror_vp_mtp_ref_count_recover(unit)); 9600 9601 /* recover sflow mtp usage reference counters */ 9602 BCM_IF_ERROR_RETURN(_bcm_mirror_sflow_mtp_ref_count_recover(unit)); 9603 9604 #ifdef BCM_TRIUMPH2_SUPPORT 9605 if (soc_feature(unit, soc_feature_mirror_flexible) && 9606 NULL != mtp_scache_p) { 9607 if (!MIRROR_MTP_METHOD_IS_DIRECTED_FLEXIBLE(unit)) { 9608 if (recovered_ver >= BCM_WB_VERSION_1_4) { 9609 _bcm_mirror_dest_config_p mdest = NULL; 9610 /* Recover Shared MTP ref_count */ 9611 for (idx = 0; idx < BCM_MIRROR_MTP_COUNT; idx++) { 9612 MIRROR_CONFIG_SHARED_MTP_REF_COUNT(unit, idx) = 9613 shared_mtp_ref_count[idx]; 9614 } 9615 9616 /* Recover Egress True MTP ref_count */ 9617 if (soc_feature(unit, soc_feature_egr_mirror_true)) { 9618 for (idx = 0; 9619 idx < MIRROR_CONFIG(unit)->egr_true_mtp_count; idx++) { 9620 MIRROR_CONFIG_EGR_TRUE_MTP_REF_COUNT(unit, idx) = 9621 egr_true_mtp_ref_count[idx]; 9622 } 9623 } 9624 9625 /* Recover Mirror Destination ref_count */ 9626 for (idx = 0; idx < MIRROR_CONFIG(unit)->dest_count; idx++) { 9627 mdest = MIRROR_CONFIG(unit)->dest_arr + idx; 9628 mdest->ref_count = mirror_dest_ref_count[idx]; 9629 } 9630 9631 /* Recover MIRROR_CONFIG_MODE */ 9632 MIRROR_CONFIG_MODE(unit) = mirror_config_mode; 9633 } 9634 } else { 9635 /* MIRROR_MTP_METHOD_IS_DIRECTED_FLEXIBLE(unit) */ 9636 /* Recover Egress True MTP ref_count */ 9637 if (soc_feature(unit, soc_feature_egr_mirror_true)) { 9638 if (recovered_ver >= BCM_WB_VERSION_1_6) { 9639 for (idx = 0; 9640 idx < MIRROR_CONFIG(unit)->egr_true_mtp_count; idx++) { 9641 MIRROR_CONFIG_EGR_TRUE_MTP_REF_COUNT(unit, idx) = 9642 egr_true_mtp_ref_count[idx]; 9643 } 9644 } 9645 } 9646 } 9647 } 9648 #endif 9649 9650 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_GREYHOUND_SUPPORT) 9651 /* Recover EGR_MIRROR_ENCAP references from EGR_MTP & 9652 * EGR_PORT tables. */ 9653 if (soc_feature(unit, soc_feature_mirror_encap_profile)) { 9654 egr_im_mtp_index_entry_t egr_mtp_entry; 9655 #ifdef BCM_TRIDENT_SUPPORT 9656 egr_port_entry_t egr_port_entry; 9657 #endif /* BCM_TRIDENT_SUPPORT */ 9658 #ifdef BCM_GREYHOUND_SUPPORT 9659 uint64 reg_val64; 9660 #endif /* BCM_GREYHOUND_SUPPORT */ 9661 uint32 profile_index; 9662 int offset; 9663 bcm_mirror_destination_t *mir_dest; 9664 uint8 done = FALSE; 9665 9666 /* 9667 * EGR_*_MTP_INDEX tables are arranged as blocks of 9668 * BCM_SWITCH_TRUNK_MAX_PORTCNT entries, with 9669 * BCM_MIRROR_MTP_COUNT sets. We only need to check the 9670 * first entry of each block to see if the 9671 * encap enable is set. We track one reference count 9672 * for each set, by each destination type (IM, EM, TRUE EM) 9673 */ 9674 offset = 0; 9675 #ifdef BCM_METROLITE_SUPPORT 9676 if (soc_feature(unit, soc_feature_mirror_four_port_trunk)) { 9677 max_num_trunk_ports = 4; 9678 } else 9679 #endif 9680 max_num_trunk_ports = BCM_SWITCH_TRUNK_MAX_PORTCNT; 9681 9682 #ifdef BCM_TOMAHAWK3_SUPPORT 9683 if (SOC_IS_TOMAHAWK3(unit)) { 9684 max_num_trunk_ports = 1; 9685 /* We use offset = index below since 9686 * EGR_IM/EM_MTP_INDEX are * 4 entries deep 9687 */ 9688 } 9689 #endif /* BCM_TOMAHAWK3_SUPPORT */ 9690 9691 #if defined(BCM_METROLITE_SUPPORT) 9692 /* No of MTP supported for 53460 and 53461 is 9693 * one for ingress and one for egress and 9694 * flexible mirroring is not supported */ 9695 soc_cm_get_id(unit, &dev_id, &rev_id); 9696 if( (dev_id == BCM53460_DEVICE_ID) || 9697 (dev_id == BCM53461_DEVICE_ID) ) { 9698 mtp_port_count = 1; 9699 } else 9700 #endif 9701 mtp_port_count = BCM_MIRROR_MTP_COUNT; 9702 9703 for (mtp_index = 0; mtp_index < mtp_port_count; 9704 mtp_index++, offset += max_num_trunk_ports) { 9705 9706 BCM_IF_ERROR_RETURN 9707 (soc_mem_read(unit, EGR_IM_MTP_INDEXm, MEM_BLOCK_ANY, 9708 offset, &egr_mtp_entry)); 9709 if (soc_mem_field32_get(unit, EGR_IM_MTP_INDEXm, 9710 &egr_mtp_entry, 9711 MIRROR_ENCAP_ENABLEf)) { 9712 profile_index = 9713 soc_mem_field32_get(unit, EGR_IM_MTP_INDEXm, 9714 &egr_mtp_entry, 9715 MIRROR_ENCAP_INDEXf); 9716 BCM_IF_ERROR_RETURN 9717 (_bcm_egr_mirror_encap_entry_reference(unit, 9718 profile_index)); 9719 /* Tunnel type info recovery */ 9720 if (MIRROR_MTP_METHOD_IS_DIRECTED_FLEXIBLE(unit)) { 9721 dest_id = MIRROR_CONFIG_ING_MTP_DEST(unit, mtp_index); 9722 mir_dest = 9723 MIRROR_DEST(unit, 9724 MIRROR_CONFIG_ING_MTP_DEST(unit, mtp_index)); 9725 done = FALSE; 9726 #ifdef BCM_TRIDENT2_SUPPORT 9727 if (soc_feature(unit, soc_feature_mirror_flexible) && 9728 mir_dest->flags & BCM_MIRROR_DEST_ID_SHARE) { 9729 done = TRUE; 9730 } 9731 #endif 9732 if (!done) { 9733 BCM_IF_ERROR_RETURN 9734 (_bcm_td_mirror_tunnel_reload(unit, 9735 mir_dest, 9736 dest_id, 9737 profile_index)); 9738 } 9739 } else { 9740 #ifdef BCM_GREYHOUND_SUPPORT 9741 if (SOC_IS_GREYHOUND(unit) || SOC_IS_GREYHOUND2(unit) 9742 || SOC_IS_HURRICANE3(unit)) { 9743 dest_id = MIRROR_CONFIG_ING_MTP_DEST(unit, 9744 mtp_index); 9745 mir_dest = 9746 MIRROR_DEST(unit, 9747 MIRROR_CONFIG_ING_MTP_DEST(unit, 9748 mtp_index)); 9749 } else 9750 #endif /* BCM_GREYHOUND_SUPPORT */ 9751 { 9752 dest_id = MIRROR_CONFIG_SHARED_MTP_DEST(unit, 9753 mtp_index); 9754 mir_dest = 9755 MIRROR_DEST(unit, 9756 MIRROR_CONFIG_SHARED_MTP_DEST(unit, 9757 mtp_index)); 9758 } 9759 done = FALSE; 9760 #ifdef BCM_TRIDENT2_SUPPORT 9761 if (soc_feature(unit, soc_feature_mirror_flexible) && 9762 mir_dest->flags & BCM_MIRROR_DEST_ID_SHARE) { 9763 done = TRUE; 9764 } 9765 #endif 9766 if (!done) { 9767 BCM_IF_ERROR_RETURN 9768 (_bcm_td_mirror_tunnel_reload(unit, 9769 mir_dest, 9770 dest_id, 9771 profile_index)); 9772 } 9773 } 9774 } 9775 9776 BCM_IF_ERROR_RETURN 9777 (soc_mem_read(unit, EGR_EM_MTP_INDEXm, MEM_BLOCK_ANY, 9778 offset, &egr_mtp_entry)); 9779 if (soc_mem_field32_get(unit, EGR_EM_MTP_INDEXm, 9780 &egr_mtp_entry, 9781 MIRROR_ENCAP_ENABLEf)) { 9782 profile_index = 9783 soc_mem_field32_get(unit, EGR_EM_MTP_INDEXm, 9784 &egr_mtp_entry, 9785 MIRROR_ENCAP_INDEXf); 9786 BCM_IF_ERROR_RETURN 9787 (_bcm_egr_mirror_encap_entry_reference(unit, 9788 profile_index)); 9789 /* Tunnel type info recovery */ 9790 if (MIRROR_MTP_METHOD_IS_DIRECTED_FLEXIBLE(unit)) { 9791 dest_id = MIRROR_CONFIG_EGR_MTP_DEST(unit, mtp_index); 9792 mir_dest = 9793 MIRROR_DEST(unit, 9794 MIRROR_CONFIG_EGR_MTP_DEST(unit, mtp_index)); 9795 9796 done = FALSE; 9797 #ifdef BCM_TRIDENT2_SUPPORT 9798 if (soc_feature(unit, soc_feature_mirror_flexible) && 9799 mir_dest->flags & BCM_MIRROR_DEST_ID_SHARE) { 9800 done = TRUE; 9801 } 9802 #endif 9803 if (!done) { 9804 BCM_IF_ERROR_RETURN 9805 (_bcm_td_mirror_tunnel_reload(unit, 9806 mir_dest, 9807 dest_id, 9808 profile_index)); 9809 } 9810 } else { 9811 #ifdef BCM_GREYHOUND_SUPPORT 9812 if (SOC_IS_GREYHOUND(unit) || SOC_IS_GREYHOUND2(unit) 9813 || SOC_IS_HURRICANE3(unit)) { 9814 dest_id = MIRROR_CONFIG_EGR_MTP_DEST(unit, 9815 mtp_index); 9816 mir_dest = 9817 MIRROR_DEST(unit, 9818 MIRROR_CONFIG_EGR_MTP_DEST(unit, 9819 mtp_index)); 9820 } else 9821 #endif /* BCM_GREYHOUND_SUPPORT */ 9822 { 9823 dest_id = MIRROR_CONFIG_SHARED_MTP_DEST(unit, 9824 mtp_index); 9825 mir_dest = 9826 MIRROR_DEST(unit, 9827 MIRROR_CONFIG_SHARED_MTP_DEST(unit, 9828 mtp_index)); 9829 } 9830 done = FALSE; 9831 #ifdef BCM_TRIDENT2_SUPPORT 9832 if (soc_feature(unit, soc_feature_mirror_flexible) && 9833 mir_dest->flags & BCM_MIRROR_DEST_ID_SHARE) { 9834 done = TRUE; 9835 } 9836 #endif 9837 if (!done) { 9838 BCM_IF_ERROR_RETURN 9839 (_bcm_td_mirror_tunnel_reload(unit, 9840 mir_dest, 9841 dest_id, 9842 profile_index)); 9843 } 9844 } 9845 9846 } 9847 9848 if (soc_feature(unit, soc_feature_egr_mirror_true)) { 9849 BCM_IF_ERROR_RETURN 9850 (soc_mem_read(unit, EGR_EP_REDIRECT_EM_MTP_INDEXm, 9851 MEM_BLOCK_ANY, offset, &egr_mtp_entry)); 9852 if (soc_mem_field32_get(unit, EGR_EP_REDIRECT_EM_MTP_INDEXm, 9853 &egr_mtp_entry, 9854 MIRROR_ENCAP_ENABLEf)) { 9855 profile_index = 9856 soc_mem_field32_get(unit, 9857 EGR_EP_REDIRECT_EM_MTP_INDEXm, 9858 &egr_mtp_entry, 9859 MIRROR_ENCAP_INDEXf); 9860 BCM_IF_ERROR_RETURN 9861 (_bcm_egr_mirror_encap_entry_reference(unit, 9862 profile_index)); 9863 dest_id = MIRROR_CONFIG_EGR_TRUE_MTP_DEST(unit, mtp_index); 9864 mir_dest = 9865 MIRROR_DEST(unit, 9866 MIRROR_CONFIG_EGR_TRUE_MTP_DEST(unit, mtp_index)); 9867 /* Tunnel type info recovery */ 9868 BCM_IF_ERROR_RETURN 9869 (_bcm_td_mirror_tunnel_reload(unit, 9870 mir_dest, 9871 dest_id, 9872 profile_index)); 9873 } 9874 } 9875 } 9876 9877 PBMP_ITER(all_pbmp, port_ix) { 9878 #ifdef BCM_GREYHOUND_SUPPORT 9879 if (SOC_IS_GREYHOUND(unit) || SOC_IS_HURRICANE3(unit) || 9880 SOC_IS_GREYHOUND2(unit)) { 9881 BCM_IF_ERROR_RETURN(READ_EGR_PORT_64r(unit, port_ix, ®_val64)); 9882 9883 if (0 != soc_reg64_field32_get(unit, EGR_PORT_64r, reg_val64, 9884 MIRROR_ENCAP_ENABLEf)) { 9885 profile_index = 9886 soc_reg64_field32_get(unit, EGR_PORT_64r, reg_val64, 9887 MIRROR_ENCAP_INDEXf); 9888 BCM_IF_ERROR_RETURN 9889 (_bcm_egr_mirror_encap_entry_reference(unit, 9890 profile_index)); 9891 } 9892 } else 9893 #endif /* BCM_GREYHOUND_SUPPORT */ 9894 { 9895 #ifdef BCM_TRIDENT_SUPPORT 9896 #ifdef BCM_TRIDENT3_SUPPORT 9897 if (SOC_IS_TRIDENT3X(unit)) { 9898 egr_lport_profile_entry_t egr_lport_profile_entry; 9899 rv = READ_EGR_LPORT_PROFILEm(unit, MEM_BLOCK_ANY, 9900 port_ix, &egr_lport_profile_entry); 9901 if (BCM_SUCCESS(rv) && 9902 (0 != soc_EGR_LPORT_PROFILEm_field32_get(unit, 9903 &egr_lport_profile_entry, 9904 MIRROR_ENCAP_ENABLEf))) { 9905 profile_index = soc_EGR_LPORT_PROFILEm_field32_get( 9906 unit, &egr_lport_profile_entry, 9907 MIRROR_ENCAP_INDEXf); 9908 BCM_IF_ERROR_RETURN 9909 (_bcm_egr_mirror_encap_entry_reference(unit, 9910 profile_index)); 9911 } 9912 } else 9913 #endif /* BCM_TRIDENT3_SUPPORT */ 9914 { 9915 BCM_IF_ERROR_RETURN 9916 (READ_EGR_PORTm(unit, MEM_BLOCK_ANY, port_ix, 9917 &egr_port_entry)); 9918 9919 if (0 != soc_EGR_PORTm_field32_get(unit, &egr_port_entry, 9920 MIRROR_ENCAP_ENABLEf)) { 9921 profile_index = 9922 soc_EGR_PORTm_field32_get(unit, &egr_port_entry, 9923 MIRROR_ENCAP_INDEXf); 9924 BCM_IF_ERROR_RETURN 9925 (_bcm_egr_mirror_encap_entry_reference(unit, 9926 profile_index)); 9927 } 9928 } 9929 #endif /* BCM_TRIDENT_SUPPORT */ 9930 } 9931 } 9932 } 9933 #endif /* BCM_TRIDENT_SUPPORT || BCM_GREYHOUND_SUPPORT */ 9934 9935 #ifdef BCM_FIELD_SUPPORT 9936 if (soc_feature(unit, soc_feature_field)) { 9937 rv = bcm_esw_field_group_traverse(unit, 9938 _bcm_esw_mirror_field_group_reload, 9939 NULL); 9940 if (BCM_FAILURE(rv) && (BCM_E_INIT != rv)) { 9941 return rv; 9942 } 9943 } 9944 #endif /* BCM_FIELD_SUPPORT */ 9945 9946 if (NULL == mtp_scache) { 9947 /* Cleanup unused null destination in Warm Boot Level 1 */ 9948 flags = 0; 9949 BCM_IF_ERROR_RETURN 9950 (_bcm_mirror_gport_construct(unit, 0, 0, 0, &gport)); 9951 rv = _bcm_esw_mirror_destination_find(unit, gport, 0, 9952 flags, &mirror_dest); 9953 if (BCM_E_NOT_FOUND == rv) { 9954 /* Nothing to do */ 9955 } else if (BCM_FAILURE(rv)) { 9956 return rv; 9957 } else if (MIRROR_DEST_REF_COUNT(unit, 9958 mirror_dest.mirror_dest_id) == 1) { 9959 BCM_IF_ERROR_RETURN 9960 (bcm_esw_mirror_destination_destroy(unit, 9961 mirror_dest.mirror_dest_id)); 9962 } 9963 } 9964 } 9965 9966 #ifdef BCM_TRIDENT3_SUPPORT 9967 if(soc_feature(unit, soc_feature_erspan3_support)) { 9968 if (NULL != mtp_scache_p) { 9969 if (recovered_ver >= BCM_WB_VERSION_1_10) { 9970 /* Version_1_10: Recover the GBP SID and gre_seq_num 9971 values that are used for ERSPAN3 */ 9972 for (idx = 0; idx < MIRROR_CONFIG(unit)->dest_count; idx++) { 9973 mdest = MIRROR_CONFIG(unit)->dest_arr + idx; 9974 mirror_dest_p = &mdest->mirror_dest; 9975 sal_memcpy(&mirror_dest_p->erspan_header.gbp_sid, 9976 mtp_scache_p, 9977 sizeof(mirror_dest_p->erspan_header.gbp_sid)); 9978 mtp_scache_p += sizeof(mirror_dest_p->erspan_header.gbp_sid); 9979 } 9980 9981 for (idx = 0; idx < MIRROR_CONFIG(unit)->dest_count; idx++) { 9982 mdest = MIRROR_CONFIG(unit)->dest_arr + idx; 9983 mirror_dest_p = &mdest->mirror_dest; 9984 sal_memcpy(&mirror_dest_p->gre_seq_number, 9985 mtp_scache_p, 9986 sizeof(mirror_dest_p->gre_seq_number)); 9987 mtp_scache_p += sizeof(mirror_dest_p->gre_seq_number); 9988 } 9989 9990 } else { 9991 int alloc_sz = 0; 9992 BCM_IF_ERROR_RETURN 9993 (_bcm_esw_mirror_scache_version_incremental_size_get(unit, 9994 BCM_WB_VERSION_1_10, 9995 &alloc_sz)); 9996 extra_scache_size += alloc_sz; 9997 } 9998 } 9999 } 10000 #endif 10001 10002 if (soc_feature(unit, soc_feature_mirror_encap_profile)) { 10003 int alloc_sz = 0; 10004 10005 skip = FALSE; 10006 cur_td3_flag = 0; 10007 10008 #ifdef BCM_TRIDENT3_SUPPORT 10009 cur_td3_flag = TRUE; 10010 #endif 10011 10012 if (recovered_ver >= BCM_WB_VERSION_1_12) { 10013 if (!(wb_flags & WB_MIRROR_FLAGS_TD3)) { 10014 if (cur_td3_flag) { 10015 BCM_IF_ERROR_RETURN 10016 (_bcm_esw_mirror_scache_version_incremental_size_get( 10017 unit, BCM_WB_VERSION_1_11, &alloc_sz)); 10018 extra_scache_size += alloc_sz; 10019 } 10020 skip = TRUE; 10021 } else { 10022 if (!cur_td3_flag) { 10023 alloc_sz = sizeof(uint32) * (BCM_MIRROR_MTP_COUNT * 3); 10024 mtp_scache_p += alloc_sz; 10025 skip = TRUE; 10026 } 10027 } 10028 } 10029 if (skip == FALSE) { 10030 #ifdef BCM_TRIDENT3_SUPPORT 10031 if (NULL != mtp_scache_p) { 10032 if (recovered_ver >= BCM_WB_VERSION_1_11) { 10033 uint8 *tmp_scache_p; 10034 10035 tmp_scache_p = mtp_scache_p; 10036 /* Version_1_11: Recover the VNID value */ 10037 for (idx = 0; idx < MIRROR_CONFIG(unit)->dest_count;idx++) { 10038 mdest = MIRROR_CONFIG(unit)->dest_arr + idx; 10039 mirror_dest_p = &mdest->mirror_dest; 10040 sal_memcpy(&mirror_dest_p->vni, 10041 tmp_scache_p, 10042 sizeof(mirror_dest_p->vni)); 10043 tmp_scache_p += sizeof(mirror_dest_p->vni); 10044 } 10045 BCM_IF_ERROR_RETURN 10046 (_bcm_esw_mirror_scache_version_incremental_size_get( 10047 unit, BCM_WB_VERSION_1_11, &alloc_sz)); 10048 mtp_scache_p += alloc_sz; 10049 } else { 10050 BCM_IF_ERROR_RETURN 10051 (_bcm_esw_mirror_scache_version_incremental_size_get( 10052 unit, BCM_WB_VERSION_1_11, &alloc_sz)); 10053 extra_scache_size += alloc_sz; 10054 } 10055 } 10056 #endif 10057 } 10058 } 10059 10060 if (extra_scache_size > 0) { 10061 BCM_IF_ERROR_RETURN 10062 (soc_scache_realloc(unit, scache_handle, extra_scache_size)); 10063 } 10064 10065 #if defined (BCM_TOMAHAWK_SUPPORT) 10066 /* Field callback functions for recovering Mirror Destination during warmboot */ 10067 BCM_IF_ERROR_RETURN 10068 (_field_mirror_actions_recover_callback(unit, _bcm_mirror_config[unit])); 10069 #endif 10070 10071 return BCM_E_NONE; 10072 } 10073 10074 /* 10075 * Function: 10076 * _bcm_esw_mirror_sync 10077 * Purpose: 10078 * Stores mirroring destination for warm boot recovery 10079 * Parameters: 10080 * unit - (IN)BCM device number. 10081 * Returns: 10082 * BCM_E_XXX 10083 */ 10084 10085 int 10086 _bcm_esw_mirror_sync(int unit) 10087 { 10088 soc_scache_handle_t scache_handle; 10089 uint8 *mtp_scache; 10090 uint16 dest_field_bmp = 0; 10091 int idx; 10092 int rv; 10093 int size; 10094 uint32 wb_flags; 10095 #ifdef BCM_TOMAHAWK3_SUPPORT 10096 int slot_type; 10097 _bcm_mirror_zero_profile_t 10098 mirror_zero_prof_info[MIRROR_ZERO_PROFILE_INDEX_MAX]; 10099 int index = -1; 10100 int actual_index = -1; 10101 #endif 10102 #ifdef BCM_TRIDENT3_SUPPORT 10103 /* Mirror destination description. */ 10104 _bcm_mirror_dest_config_p mdest; 10105 /* Destination & encapsulation.*/ 10106 bcm_mirror_destination_t *mirror_dest_p; 10107 #endif /* BCM_TRIDENT3_SUPPORT */ 10108 10109 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_MIRROR, 0); 10110 BCM_IF_ERROR_RETURN 10111 (_bcm_esw_scache_ptr_get(unit, scache_handle, FALSE, 10112 0, &mtp_scache, BCM_WB_DEFAULT_VERSION, NULL)); 10113 10114 if (soc_feature(unit, soc_feature_mirror_flexible) && 10115 !MIRROR_MTP_METHOD_IS_DIRECTED_FLEXIBLE(unit)) { 10116 for (idx = 0; idx < BCM_MIRROR_MTP_COUNT; idx++) { 10117 sal_memcpy(mtp_scache, 10118 &(MIRROR_CONFIG_SHARED_MTP_DEST(unit, idx)), 10119 sizeof(bcm_gport_t)); 10120 mtp_scache += sizeof(bcm_gport_t); 10121 } 10122 } else { 10123 for (idx = 0; idx < MIRROR_CONFIG(unit)->ing_mtp_count; idx++) { 10124 sal_memcpy(mtp_scache, 10125 &(MIRROR_CONFIG_ING_MTP_DEST(unit, idx)), 10126 sizeof(bcm_gport_t)); 10127 mtp_scache += sizeof(bcm_gport_t); 10128 } 10129 10130 for (idx = 0; 10131 idx < MIRROR_CONFIG(unit)->egr_mtp_count; idx++) { 10132 sal_memcpy(mtp_scache, 10133 &(MIRROR_CONFIG_EGR_MTP_DEST(unit, idx)), 10134 sizeof(bcm_gport_t)); 10135 mtp_scache += sizeof(bcm_gport_t); 10136 } 10137 } 10138 10139 #ifdef BCM_TRIUMPH2_SUPPORT 10140 if (soc_feature(unit, soc_feature_egr_mirror_true)) { 10141 for (idx = 0; 10142 idx < MIRROR_CONFIG(unit)->egr_true_mtp_count; idx++) { 10143 sal_memcpy(mtp_scache, 10144 &(MIRROR_CONFIG_EGR_TRUE_MTP_DEST(unit, idx)), 10145 sizeof(bcm_gport_t)); 10146 mtp_scache += sizeof(bcm_gport_t); 10147 } 10148 } 10149 #endif /* BCM_TRIUMPH2_SUPPORT */ 10150 /* Version_1_0 -> Version_1_1: 10151 * In directed flexible mirror mode, for each possible mirror entity, 10152 * it has respective mirror slot enable control and slot-MTP mapping 10153 * control. For port mirror, MIRROR field in PORT_TAB memory 10154 * controls if ingress mirror is enabled for a slot for a given port. 10155 * For sflow mirror, MIRROR_ENABLE field in SFLOW_ING_MIRROR_CONFIGr 10156 * control if mirror is enabled on a sflow for a given slot. For FP 10157 * mirror, the MIRROR field in FP_POLICY table play the same role. 10158 * In current implementation, there is no easy way to get the slot 10159 * enable information and slot-MTP mapping information, 10160 * so this information is stored in L2 warmboot. 10161 */ 10162 if (soc_feature(unit, soc_feature_mirror_flexible) && 10163 MIRROR_MTP_METHOD_IS_DIRECTED_FLEXIBLE(unit)) { 10164 _bcm_mirror_dest_config_p mdest = NULL; 10165 int slot_type; 10166 bcm_gport_t dest_id = 0; 10167 uint32 flags = 0; 10168 /* Slot-MTP mapping information for respective slot types */ 10169 for (slot_type = BCM_MTP_SLOT_TYPE_PORT; slot_type < (BCM_MTP_SLOT_TYPE_SFLOW + 1); slot_type++) { 10170 for (idx = 0; idx < MIRROR_CONFIG(unit)->mtp_slot_count[slot_type]; idx++) { 10171 sal_memcpy(mtp_scache, 10172 &MIRROR_CONFIG_TYPE_MTP_SLOT(unit, idx, slot_type), 10173 sizeof(bcm_gport_t)); 10174 mtp_scache += sizeof(bcm_gport_t); 10175 } 10176 } 10177 /* Reference counter for respective slot types . */ 10178 for (slot_type = BCM_MTP_SLOT_TYPE_PORT; slot_type < (BCM_MTP_SLOT_TYPE_SFLOW + 1); slot_type++) { 10179 for (idx = 0; idx < MIRROR_CONFIG(unit)->mtp_slot_count[slot_type]; idx++) { 10180 sal_memcpy(mtp_scache, 10181 &MIRROR_CONFIG_TYPE_MTP_REF_COUNT(unit, idx, slot_type), 10182 sizeof(int)); 10183 mtp_scache += sizeof(int); 10184 } 10185 } 10186 /* It is possible that FP module can create mirror destination implicitly 10187 * when _bcm_esw_mirror_fp_dest_add is called thru mod + port mirror dest. 10188 * In this case, A new destination will be created if there is no 10189 * destination match mod + port mirror dest. And the new destination will 10190 * be set with the flag BCM_MIRROR_DEST_FIELD. 10191 * During warmboot, the flag BCM_MIRROR_DEST_FIELD can not be recovered 10192 * from H/W. 10193 */ 10194 for (idx = 0; idx < MIRROR_CONFIG(unit)->dest_count; idx++) { 10195 mdest = MIRROR_CONFIG(unit)->dest_arr + idx;; 10196 if (mdest->mirror_dest.flags & BCM_MIRROR_DEST_FIELD) { 10197 dest_field_bmp |= (1 << idx); 10198 } 10199 } 10200 sal_memcpy(mtp_scache, &dest_field_bmp, sizeof(uint16)); 10201 mtp_scache += sizeof(uint16); 10202 /* Reference counter for MTP slot */ 10203 for (idx = 0; idx < BCM_MIRROR_MTP_COUNT; idx++) { 10204 sal_memcpy(mtp_scache, 10205 &MIRROR_CONFIG_MTP_MODE_REF_COUNT(unit, idx), 10206 sizeof(int)); 10207 mtp_scache += sizeof(int); 10208 } 10209 /* Reference counter for ING MTP */ 10210 for (idx = 0; idx < MIRROR_CONFIG(unit)->ing_mtp_count; idx++) { 10211 sal_memcpy(mtp_scache, 10212 &MIRROR_CONFIG_ING_MTP_REF_COUNT(unit, idx), 10213 sizeof(int)); 10214 mtp_scache += sizeof(int); 10215 } 10216 /* Reference counter for EGR MTP */ 10217 for (idx = 0; idx < MIRROR_CONFIG(unit)->egr_mtp_count; idx++) { 10218 sal_memcpy(mtp_scache, 10219 &MIRROR_CONFIG_EGR_MTP_REF_COUNT(unit, idx), 10220 sizeof(int)); 10221 mtp_scache += sizeof(int); 10222 } 10223 /* Reference counter for destination */ 10224 for (idx = 0; idx < MIRROR_CONFIG(unit)->dest_count; idx++) { 10225 mdest = MIRROR_CONFIG(unit)->dest_arr + idx; 10226 sal_memcpy(mtp_scache, &(mdest->ref_count), sizeof(int)); 10227 mtp_scache += sizeof(int); 10228 } 10229 /* Port bitmap for MTP slot used */ 10230 for (idx = 0; idx < BCM_MIRROR_MTP_COUNT; idx++) { 10231 sal_memcpy(mtp_scache, 10232 &MIRROR_CONFIG_PBMP_MTP_SLOT_USED(unit, idx), 10233 sizeof(bcm_pbmp_t)); 10234 mtp_scache += sizeof(bcm_pbmp_t); 10235 } 10236 10237 /* Version_1_1 -> Version_1_2: 10238 * The destination flags couldn't be recovered from hardware, so save it 10239 */ 10240 /* Save flags of ING MTP destination */ 10241 for (idx = 0; idx < MIRROR_CONFIG(unit)->ing_mtp_count; idx++) { 10242 dest_id = MIRROR_CONFIG_ING_MTP_DEST(unit, idx); 10243 flags = BCM_GPORT_IS_MIRROR(dest_id) ? 10244 MIRROR_DEST(unit, dest_id)->flags : 0; 10245 sal_memcpy(mtp_scache, 10246 &flags, 10247 sizeof(uint32)); 10248 mtp_scache += sizeof(uint32); 10249 } 10250 /* Save flags for EGR MTP destination */ 10251 for (idx = 0; idx < MIRROR_CONFIG(unit)->egr_mtp_count; idx++) { 10252 dest_id = MIRROR_CONFIG_EGR_MTP_DEST(unit, idx); 10253 flags = BCM_GPORT_IS_MIRROR(dest_id) ? 10254 MIRROR_DEST(unit, dest_id)->flags : 0; 10255 sal_memcpy(mtp_scache, 10256 &flags, 10257 sizeof(uint32)); 10258 mtp_scache += sizeof(uint32); 10259 } 10260 10261 #ifdef BCM_TRIUMPH2_SUPPORT 10262 if (soc_feature(unit, soc_feature_egr_mirror_true)) { 10263 for (idx = 0; 10264 idx < MIRROR_CONFIG(unit)->egr_true_mtp_count; idx++) { 10265 dest_id = MIRROR_CONFIG_EGR_TRUE_MTP_DEST(unit, idx); 10266 flags = BCM_GPORT_IS_MIRROR(dest_id) ? 10267 MIRROR_DEST(unit, dest_id)->flags : 0; 10268 sal_memcpy(mtp_scache, 10269 &flags, 10270 sizeof(uint32)); 10271 mtp_scache += sizeof(uint32); 10272 } 10273 } 10274 #endif /* BCM_TRIUMPH2_SUPPORT */ 10275 } 10276 10277 #ifdef BCM_TRIUMPH2_SUPPORT 10278 /* Version_1_3: Save destination flags for non-flexible mtp mirror case */ 10279 if (soc_feature(unit, soc_feature_mirror_flexible) && 10280 !MIRROR_MTP_METHOD_IS_DIRECTED_FLEXIBLE(unit)) { 10281 bcm_gport_t dest_id = 0; 10282 uint32 flags = 0; 10283 int ref_count = 0; 10284 _bcm_mirror_dest_config_p mdest = NULL; 10285 10286 /* Save flags for Shared MTP destination */ 10287 for (idx = 0; 10288 idx < BCM_MIRROR_MTP_COUNT; idx++) { 10289 dest_id = MIRROR_CONFIG_SHARED_MTP_DEST(unit, idx); 10290 flags = BCM_GPORT_IS_MIRROR(dest_id) ? 10291 MIRROR_DEST(unit, dest_id)->flags : 0; 10292 sal_memcpy(mtp_scache, 10293 &flags, 10294 sizeof(uint32)); 10295 mtp_scache += sizeof(uint32); 10296 } 10297 10298 /* Save flags for egress true MTP destination */ 10299 if (soc_feature(unit, soc_feature_egr_mirror_true)) { 10300 for (idx = 0; 10301 idx < MIRROR_CONFIG(unit)->egr_true_mtp_count; idx++) { 10302 dest_id = MIRROR_CONFIG_EGR_TRUE_MTP_DEST(unit, idx); 10303 flags = BCM_GPORT_IS_MIRROR(dest_id) ? 10304 MIRROR_DEST(unit, dest_id)->flags : 0; 10305 sal_memcpy(mtp_scache, 10306 &flags, 10307 sizeof(uint32)); 10308 mtp_scache += sizeof(uint32); 10309 } 10310 } 10311 10312 /* Version_1_4: 10313 * Save Shared MTP ref_count, Egress True MTP ref_count, 10314 * Mirror Destination ref_count, MIRROR_CONFIG_MODE 10315 */ 10316 /* Save Shared MTP ref_count */ 10317 for (idx = 0; 10318 idx < BCM_MIRROR_MTP_COUNT; idx++) { 10319 ref_count = MIRROR_CONFIG_SHARED_MTP_REF_COUNT(unit, idx); 10320 sal_memcpy(mtp_scache, 10321 &ref_count, 10322 sizeof(int)); 10323 mtp_scache += sizeof(int); 10324 } 10325 10326 /* Save Egress True MTP ref_count */ 10327 if (soc_feature(unit, soc_feature_egr_mirror_true)) { 10328 for (idx = 0; 10329 idx < MIRROR_CONFIG(unit)->egr_true_mtp_count; idx++) { 10330 ref_count = MIRROR_CONFIG_EGR_TRUE_MTP_REF_COUNT(unit, idx); 10331 sal_memcpy(mtp_scache, 10332 &ref_count, 10333 sizeof(int)); 10334 mtp_scache += sizeof(int); 10335 } 10336 } 10337 10338 /* Save Mirror Destination ref_count */ 10339 for (idx = 0; idx < MIRROR_CONFIG(unit)->dest_count; idx++) { 10340 mdest = MIRROR_CONFIG(unit)->dest_arr + idx; 10341 sal_memcpy(mtp_scache, &(mdest->ref_count), sizeof(int)); 10342 mtp_scache += sizeof(int); 10343 } 10344 10345 /* Save MIRROR_CONFIG_MODE */ 10346 sal_memcpy(mtp_scache, &MIRROR_CONFIG_MODE(unit), sizeof(int)); 10347 mtp_scache += sizeof(int); 10348 } 10349 #endif /* BCM_TRIUMPH2_SUPPORT */ 10350 10351 #ifdef BCM_TRIDENT2_SUPPORT 10352 if (soc_feature(unit, soc_feature_mirror_flexible)) { 10353 /* Version_1_5: Save MTP destination gport. */ 10354 bcm_gport_t dest_id = 0; 10355 if (MIRROR_MTP_METHOD_IS_DIRECTED_FLEXIBLE(unit)) { 10356 /* Save Ingress MTP destination gport */ 10357 for (idx = 0; idx < MIRROR_CONFIG(unit)->ing_mtp_count; idx++) { 10358 dest_id = MIRROR_CONFIG_ING_MTP_DEST(unit, idx); 10359 if (BCM_GPORT_IS_MIRROR(dest_id)) { 10360 BCM_IF_ERROR_RETURN( 10361 _bcm_mirror_dest_gport_sync(unit, 10362 dest_id, 10363 mtp_scache)); 10364 } 10365 mtp_scache += sizeof(bcm_gport_t) * 10366 BCM_SWITCH_TRUNK_MAX_PORTCNT; 10367 } 10368 10369 /* Save Egress MTP destination gport */ 10370 for (idx = 0; idx < MIRROR_CONFIG(unit)->egr_mtp_count; idx++) { 10371 dest_id = MIRROR_CONFIG_EGR_MTP_DEST(unit, idx); 10372 if (BCM_GPORT_IS_MIRROR(dest_id)) { 10373 BCM_IF_ERROR_RETURN( 10374 _bcm_mirror_dest_gport_sync(unit, 10375 dest_id, 10376 mtp_scache)); 10377 } 10378 mtp_scache += sizeof(bcm_gport_t) * 10379 BCM_SWITCH_TRUNK_MAX_PORTCNT; 10380 } 10381 10382 /* Save Ingress MTP destination flags */ 10383 for (idx = 0; idx < MIRROR_CONFIG(unit)->ing_mtp_count; idx++) { 10384 dest_id = MIRROR_CONFIG_ING_MTP_DEST(unit, idx); 10385 if (BCM_GPORT_IS_MIRROR(dest_id)) { 10386 BCM_IF_ERROR_RETURN( 10387 _bcm_mirror_dest_flags_sync(unit, 10388 dest_id, 10389 mtp_scache)); 10390 } 10391 mtp_scache += sizeof(uint32) * 10392 BCM_SWITCH_TRUNK_MAX_PORTCNT; 10393 } 10394 10395 /* Save Egress MTP destination flags */ 10396 for (idx = 0; idx < MIRROR_CONFIG(unit)->egr_mtp_count; idx++) { 10397 dest_id = MIRROR_CONFIG_EGR_MTP_DEST(unit, idx); 10398 if (BCM_GPORT_IS_MIRROR(dest_id)) { 10399 BCM_IF_ERROR_RETURN( 10400 _bcm_mirror_dest_flags_sync(unit, 10401 dest_id, 10402 mtp_scache)); 10403 } 10404 mtp_scache += sizeof(uint32) * 10405 BCM_SWITCH_TRUNK_MAX_PORTCNT; 10406 } 10407 } else { 10408 /* Save Shared MTP destination gport */ 10409 for (idx = 0; idx < BCM_MIRROR_MTP_COUNT; idx++) { 10410 dest_id = MIRROR_CONFIG_SHARED_MTP_DEST(unit, idx); 10411 if (BCM_GPORT_IS_MIRROR(dest_id)) { 10412 BCM_IF_ERROR_RETURN( 10413 _bcm_mirror_dest_gport_sync(unit, 10414 dest_id, 10415 mtp_scache)); 10416 } 10417 mtp_scache += sizeof(bcm_gport_t) * 10418 BCM_SWITCH_TRUNK_MAX_PORTCNT; 10419 } 10420 10421 /* Save Shared MTP destination flags */ 10422 for (idx = 0; idx < BCM_MIRROR_MTP_COUNT; idx++) { 10423 dest_id = MIRROR_CONFIG_SHARED_MTP_DEST(unit, idx); 10424 if (BCM_GPORT_IS_MIRROR(dest_id)) { 10425 BCM_IF_ERROR_RETURN( 10426 _bcm_mirror_dest_flags_sync(unit, 10427 dest_id, 10428 mtp_scache)); 10429 } 10430 mtp_scache += sizeof(uint32) * 10431 BCM_SWITCH_TRUNK_MAX_PORTCNT; 10432 } 10433 } 10434 } 10435 #endif /* BCM_TRIDENT2_SUPPORT */ 10436 10437 #ifdef BCM_TRIUMPH2_SUPPORT 10438 /* Version_1_6: Save egress true MTP ref count for DIRECTED_FLEXIBLE */ 10439 if (soc_feature(unit, soc_feature_mirror_flexible) && 10440 MIRROR_MTP_METHOD_IS_DIRECTED_FLEXIBLE(unit)) { 10441 10442 /* Save flags for egress true MTP destination */ 10443 if (soc_feature(unit, soc_feature_egr_mirror_true)) { 10444 int ref_count = 0; 10445 for (idx = 0; 10446 idx < MIRROR_CONFIG(unit)->egr_true_mtp_count; idx++) { 10447 ref_count = MIRROR_CONFIG_EGR_TRUE_MTP_REF_COUNT(unit, idx); 10448 sal_memcpy(mtp_scache, &ref_count, sizeof(int)); 10449 mtp_scache += sizeof(int); 10450 } 10451 } 10452 } 10453 #endif 10454 10455 #ifdef BCM_TRIDENT3_SUPPORT 10456 /* Version_1_7: Save egress true MTP ref count for DIRECTED_FLEXIBLE */ 10457 if (soc_feature(unit, soc_feature_mirror_flexible)) { 10458 /* save encap_to_edit_ctrl_id array. */ 10459 sal_memcpy(mtp_scache, encap_to_edit_ctrl_id, 10460 sizeof(uint32)*BCM_MIRROR_MTP_COUNT); 10461 mtp_scache += (sizeof(uint32)*BCM_MIRROR_MTP_COUNT); 10462 10463 /* save encap_profile_index_bmap. */ 10464 sal_memcpy(mtp_scache, &encap_profile_index_bmap, 10465 sizeof(uint32)); 10466 mtp_scache += sizeof(uint32); 10467 } 10468 #endif 10469 10470 /* Version_1_8: Save info of slot_types - INT, ETRAP, DLB Flow Monitor */ 10471 if (soc_feature(unit, soc_feature_mirror_flexible) && 10472 MIRROR_MTP_METHOD_IS_DIRECTED_FLEXIBLE(unit)) { 10473 #if defined(BCM_TOMAHAWK3_SUPPORT) 10474 for (slot_type = BCM_MTP_SLOT_TYPE_INT; 10475 slot_type <= BCM_MTP_SLOT_TYPE_DLB_MONITOR; slot_type++) { 10476 10477 /* Slot-MTP mapping information for respective slot types */ 10478 for (idx = 0; idx < MIRROR_CONFIG(unit)->mtp_slot_count[slot_type]; idx++) { 10479 sal_memcpy(mtp_scache, 10480 &MIRROR_CONFIG_TYPE_MTP_SLOT(unit, idx, slot_type), 10481 sizeof(bcm_gport_t)); 10482 mtp_scache += sizeof(bcm_gport_t); 10483 } 10484 /* Reference counter for respective slot types. */ 10485 for (idx = 0; idx < MIRROR_CONFIG(unit)->mtp_slot_count[slot_type]; idx++) { 10486 sal_memcpy(mtp_scache, 10487 &MIRROR_CONFIG_TYPE_MTP_REF_COUNT(unit, idx, slot_type), 10488 sizeof(int)); 10489 mtp_scache += sizeof(int); 10490 } 10491 } 10492 #endif /* BCM_TOMAHAWK3_SUPPORT */ 10493 } 10494 10495 /* Version 1_9 : Save Mirror Zero profile and ref_counts */ 10496 if (soc_feature(unit, soc_feature_th3_style_fp)) { 10497 #ifdef BCM_TOMAHAWK3_SUPPORT 10498 actual_index = MIRROR_ZERO_PROFILE_INDEX_MIN; 10499 for (index = 0; 10500 index <= (MIRROR_ZERO_PROFILE_INDEX_MAX 10501 - MIRROR_ZERO_PROFILE_INDEX_MIN); index++) { 10502 mirror_zero_prof_info[index].prof_index = actual_index; 10503 BCM_IF_ERROR_RETURN( 10504 _bcm_esw_mirror_zero_profile_ref_count_get( 10505 unit, actual_index, &(mirror_zero_prof_info[index].ref_count))); 10506 actual_index++; 10507 } 10508 sal_memcpy(mtp_scache, &mirror_zero_prof_info, 10509 (sizeof(_bcm_mirror_zero_profile_t) * 10510 (MIRROR_ZERO_PROFILE_INDEX_MAX))); 10511 mtp_scache += (sizeof(_bcm_mirror_zero_profile_t) * 10512 (MIRROR_ZERO_PROFILE_INDEX_MAX)); 10513 #endif 10514 } 10515 10516 if (soc_feature(unit, soc_feature_erspan3_support)) { 10517 #ifdef BCM_TRIDENT3_SUPPORT 10518 /* Version_1_10: Save the GBP SID and gre_seq_num 10519 values that are used for ERSPAN3 */ 10520 for (idx = 0; idx < MIRROR_CONFIG(unit)->dest_count; idx++) { 10521 mdest = MIRROR_CONFIG(unit)->dest_arr + idx; 10522 mirror_dest_p = &mdest->mirror_dest; 10523 sal_memcpy(mtp_scache, & (mirror_dest_p->erspan_header.gbp_sid), 10524 sizeof(mirror_dest_p->erspan_header.gbp_sid)); 10525 mtp_scache += sizeof(mirror_dest_p->erspan_header.gbp_sid); 10526 } 10527 for (idx = 0; idx < MIRROR_CONFIG(unit)->dest_count; idx++) { 10528 mdest = MIRROR_CONFIG(unit)->dest_arr + idx; 10529 mirror_dest_p = &mdest->mirror_dest; 10530 sal_memcpy(mtp_scache, & (mirror_dest_p->gre_seq_number), 10531 sizeof(mirror_dest_p->gre_seq_number)); 10532 mtp_scache += sizeof(mirror_dest_p->gre_seq_number); 10533 } 10534 #endif 10535 } 10536 10537 #ifdef BCM_TRIDENT3_SUPPORT 10538 if (soc_feature(unit, soc_feature_mirror_encap_profile)) { 10539 uint8 *tmp_scache; 10540 int alloc_sz; 10541 10542 tmp_scache = mtp_scache; 10543 /* Version_1_11: Save VNID value */ 10544 for (idx = 0; idx < MIRROR_CONFIG(unit)->dest_count; idx++) { 10545 mdest = MIRROR_CONFIG(unit)->dest_arr + idx; 10546 mirror_dest_p = &mdest->mirror_dest; 10547 sal_memcpy(tmp_scache, &(mirror_dest_p->vni), 10548 sizeof(mirror_dest_p->vni)); 10549 tmp_scache += sizeof(mirror_dest_p->vni); 10550 } 10551 BCM_IF_ERROR_RETURN 10552 (_bcm_esw_mirror_scache_version_incremental_size_get( 10553 unit, BCM_WB_VERSION_1_11, &alloc_sz)); 10554 mtp_scache += alloc_sz; 10555 } 10556 #endif 10557 10558 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_MIRROR, 1); 10559 rv = _bcm_esw_scache_ptr_get(unit, scache_handle, FALSE, 10560 0, &mtp_scache, BCM_WB_DEFAULT_VERSION, NULL); 10561 if (rv == BCM_E_NOT_FOUND) { 10562 10563 size = sizeof(_bcm_mirror_mtp_method_init[unit]); 10564 size += sizeof(uint32); 10565 /* Scache not created as init was done in warmboot mode */ 10566 BCM_IF_ERROR_RETURN(_bcm_esw_scache_ptr_get(unit, scache_handle, TRUE, 10567 size, 10568 &mtp_scache, 10569 BCM_WB_DEFAULT_VERSION, NULL)); 10570 } 10571 10572 sal_memcpy(mtp_scache, &(_bcm_mirror_mtp_method_init[unit]), 10573 sizeof(_bcm_mirror_mtp_method_init[unit])); 10574 mtp_scache += sizeof(_bcm_mirror_mtp_method_init[unit]); 10575 #ifdef BCM_TRIDENT3_SUPPORT 10576 wb_flags = WB_MIRROR_FLAGS_TD3; 10577 #else 10578 wb_flags = 0; 10579 #endif 10580 sal_memcpy(mtp_scache, &wb_flags, sizeof(uint32)); 10581 mtp_scache += sizeof(uint32); 10582 return BCM_E_NONE; 10583 } 10584 10585 10586 #else 10587 #define _bcm_esw_mirror_reload(unit, directed, wb_flags) (BCM_E_NONE) 10588 #endif /* BCM_WARM_BOOT_SUPPORT */ 10589 10590 #if defined(BCM_TRIDENT_SUPPORT) 10591 /* 10592 * Function: 10593 * _bcm_trident_mirror_egr_dest_get 10594 * Purpose: 10595 * Get destination port bitmap for egress mirroring. 10596 * Parameters: 10597 * unit - (IN) BCM device number. 10598 * port - (IN) port number. 10599 * mtp_index - (IN) mtp index 10600 * dest_bitmap - (OUT) destination port bitmap. 10601 * Returns: 10602 * BCM_E_XXX 10603 */ 10604 STATIC int 10605 _bcm_trident_mirror_egr_dest_get(int unit, bcm_port_t port, int mtp_index, 10606 bcm_pbmp_t *dest_bitmap) 10607 { 10608 emirror_control_entry_t entry; 10609 static const soc_mem_t mem[] = { 10610 EMIRROR_CONTROLm, EMIRROR_CONTROL1m, 10611 EMIRROR_CONTROL2m, EMIRROR_CONTROL3m 10612 }; 10613 10614 if (dest_bitmap == NULL) { 10615 return BCM_E_PARAM; 10616 } 10617 10618 if ((mtp_index < 0) || (mtp_index >= BCM_MIRROR_MTP_COUNT)) { 10619 return BCM_E_PARAM; 10620 } 10621 10622 BCM_IF_ERROR_RETURN 10623 (soc_mem_read(unit, mem[mtp_index], MEM_BLOCK_ANY, port, &entry)); 10624 soc_mem_pbmp_field_get(unit, mem[mtp_index], &entry, BITMAPf, dest_bitmap); 10625 10626 return BCM_E_NONE; 10627 } 10628 10629 /* 10630 * Function: 10631 * _bcm_trident_mirror_egr_dest_set 10632 * Purpose: 10633 * Set destination port bitmap for egress mirroring. 10634 * Parameters: 10635 * unit - (IN) BCM device number. 10636 * port - (IN) port number. 10637 * mtp_index - (IN) mtp index 10638 * dest_bitmap - (IN) destination port bitmap. 10639 * Returns: 10640 * BCM_E_XXX 10641 */ 10642 STATIC int 10643 _bcm_trident_mirror_egr_dest_set(int unit, bcm_port_t port, int mtp_index, 10644 bcm_pbmp_t *dest_bitmap) 10645 { 10646 emirror_control_entry_t entry; 10647 int cpu_hg_index = 0; 10648 10649 static const soc_mem_t mem[] = { 10650 EMIRROR_CONTROLm, EMIRROR_CONTROL1m, 10651 EMIRROR_CONTROL2m, EMIRROR_CONTROL3m 10652 }; 10653 10654 if (dest_bitmap == NULL) { 10655 return BCM_E_PARAM; 10656 } 10657 if ((mtp_index < 0) || (mtp_index >= BCM_MIRROR_MTP_COUNT)) { 10658 return BCM_E_PARAM; 10659 } 10660 10661 /* mtp_index is validated as an egress type previously */ 10662 10663 BCM_IF_ERROR_RETURN 10664 (soc_mem_read(unit, mem[mtp_index], MEM_BLOCK_ANY, port, &entry)); 10665 soc_mem_pbmp_field_set(unit, mem[mtp_index], &entry, 10666 BITMAPf, dest_bitmap); 10667 BCM_IF_ERROR_RETURN 10668 (soc_mem_write(unit, mem[mtp_index], MEM_BLOCK_ANY, port, &entry)); 10669 10670 /* Configure mirroring of CPU Higig packets as well */ 10671 cpu_hg_index = SOC_IS_KATANA2(unit) ? SOC_INFO(unit).cpu_hg_pp_port_index : 10672 SOC_INFO(unit).cpu_hg_index; 10673 #ifdef BCM_TOMAHAWK3_SUPPORT 10674 if (SOC_IS_TOMAHAWK3(unit)) { 10675 /* No higig on TH3, skip programming below */ 10676 cpu_hg_index = -1; 10677 } 10678 #endif /* BCM_TOMAHAWK3_SUPPORT */ 10679 if (IS_CPU_PORT(unit, port) && cpu_hg_index != -1) { 10680 BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem[mtp_index], MEM_BLOCK_ANY, 10681 cpu_hg_index, &entry)); 10682 } 10683 10684 return BCM_E_NONE; 10685 } 10686 #endif /* BCM_TRIDENT_SUPPORT */ 10687 10688 #if defined(BCM_TRIUMPH_SUPPORT) 10689 /* 10690 * Function: 10691 * _bcm_triumph_mirror_egr_dest_get 10692 * Purpose: 10693 * Get destination port bitmap for egress mirroring. 10694 * Parameters: 10695 * unit - (IN) BCM device number. 10696 * port - (IN) port number. 10697 * mtp_index - (IN) mtp index (mtp_slot for flex mirroring) 10698 * dest_bitmap - (OUT) destination port bitmap. 10699 * Returns: 10700 * BCM_E_XXX 10701 */ 10702 STATIC int 10703 _bcm_triumph_mirror_egr_dest_get(int unit, bcm_port_t port, int mtp_index, 10704 bcm_pbmp_t *dest_bitmap) 10705 { 10706 uint32 fval; 10707 uint64 mirror; /* Egress mirror control reg value. */ 10708 static const soc_reg_t reg[] = { 10709 EMIRROR_CONTROL_64r, EMIRROR_CONTROL1_64r, 10710 EMIRROR_CONTROL2_64r, EMIRROR_CONTROL3_64r 10711 }; 10712 #ifdef BCM_GREYHOUND2_SUPPORT 10713 uint64 fval64; 10714 static const soc_reg_t reg_lo[] = { 10715 EMIRROR_CONTROL_LO_64r, INVALIDr, 10716 INVALIDr, INVALIDr 10717 }; 10718 static const soc_reg_t reg_hi[] = { 10719 EMIRROR_CONTROL_HI_64r, INVALIDr, 10720 INVALIDr, INVALIDr 10721 }; 10722 #endif 10723 /* Input parameters check. */ 10724 if (NULL == dest_bitmap) { 10725 return BCM_E_PARAM; 10726 } 10727 if ((mtp_index < 0) || (mtp_index >= BCM_MIRROR_MTP_COUNT)) { 10728 return BCM_E_PARAM; 10729 } 10730 10731 #ifdef BCM_GREYHOUND2_SUPPORT 10732 if(soc_feature(unit, soc_feature_high_portcount_register)){ 10733 BCM_IF_ERROR_RETURN(soc_reg_get(unit, reg_lo[mtp_index], port, 0, &mirror)); 10734 10735 SOC_PBMP_CLEAR(*dest_bitmap); 10736 fval64 = soc_reg64_field_get(unit, reg_lo[mtp_index], mirror, BITMAP_LOf); 10737 SOC_PBMP_WORD_SET(*dest_bitmap, 0, COMPILER_64_LO(fval64)); 10738 SOC_PBMP_WORD_SET(*dest_bitmap, 1, COMPILER_64_HI(fval64)); 10739 BCM_IF_ERROR_RETURN(soc_reg_get(unit, reg_hi[mtp_index], port, 0, &mirror)); 10740 10741 fval64 = soc_reg64_field_get(unit, reg_hi[mtp_index], mirror, BITMAP_LOf); 10742 SOC_PBMP_WORD_SET(*dest_bitmap, 2, COMPILER_64_LO(fval64)); 10743 SOC_PBMP_WORD_SET(*dest_bitmap, 3, COMPILER_64_HI(fval64)); 10744 10745 }else 10746 #endif /*BCM_GREYHOUND2_SUPPORT*/ 10747 { 10748 10749 /* mtp_index is validated as an egress type previously */ 10750 BCM_IF_ERROR_RETURN(soc_reg_get(unit, reg[mtp_index], port, 0, &mirror)); 10751 10752 SOC_PBMP_CLEAR(*dest_bitmap); 10753 fval = soc_reg64_field32_get(unit, reg[mtp_index], mirror, BITMAP_LOf); 10754 SOC_PBMP_WORD_SET(*dest_bitmap, 0, fval); 10755 10756 if (soc_reg_field_valid(unit, reg[mtp_index], BITMAP_HIf)) { 10757 fval = soc_reg64_field32_get(unit, reg[mtp_index], mirror, BITMAP_HIf); 10758 SOC_PBMP_WORD_SET(*dest_bitmap, 1, fval); 10759 } 10760 } 10761 return BCM_E_NONE; 10762 } 10763 10764 /* 10765 * Function: 10766 * _bcm_triumph_mirror_egr_dest_set 10767 * Purpose: 10768 * Set destination port bitmap for egress mirroring. 10769 * Parameters: 10770 * unit - (IN) BCM device number. 10771 * port - (IN) Port number. 10772 * mtp_index - (IN) mtp slot number. 10773 * dest_bitmap - (IN) Destination port bitmap. 10774 * Returns: 10775 * BCM_E_XXX 10776 */ 10777 STATIC int 10778 _bcm_triumph_mirror_egr_dest_set(int unit, bcm_port_t port, int mtp_index, 10779 bcm_pbmp_t *dest_bitmap) 10780 { 10781 static const soc_reg_t reg[] = { 10782 EMIRROR_CONTROL_64r, EMIRROR_CONTROL1_64r, 10783 EMIRROR_CONTROL2_64r, EMIRROR_CONTROL3_64r 10784 }; 10785 static const soc_reg_t hg_reg[] = { 10786 IEMIRROR_CONTROL_64r, IEMIRROR_CONTROL1_64r, 10787 IEMIRROR_CONTROL2_64r, IEMIRROR_CONTROL3_64r 10788 }; 10789 uint32 values[2]; 10790 soc_field_t fields[] = {BITMAP_LOf, BITMAP_HIf}; 10791 int count; 10792 #ifdef BCM_GREYHOUND2_SUPPORT 10793 uint64 mirror, val64; 10794 static const soc_reg_t reg_lo[] = { 10795 EMIRROR_CONTROL_LO_64r, INVALIDr, 10796 INVALIDr, INVALIDr 10797 }; 10798 static const soc_reg_t reg_hi[] = { 10799 EMIRROR_CONTROL_HI_64r, INVALIDr, 10800 INVALIDr, INVALIDr 10801 }; 10802 static const soc_reg_t hg_reg_lo[] = { 10803 IEMIRROR_CONTROL_LO_64r, INVALIDr, 10804 INVALIDr, INVALIDr 10805 }; 10806 static const soc_reg_t hg_reg_hi[] = { 10807 IEMIRROR_CONTROL_HI_64r, INVALIDr, 10808 INVALIDr, INVALIDr 10809 }; 10810 10811 #endif /*BCM_GREYHOUND2_SUPPORT*/ 10812 /* Input parameters check. */ 10813 if (NULL == dest_bitmap) { 10814 return BCM_E_PARAM; 10815 } 10816 if ((mtp_index < 0) || (mtp_index >= BCM_MIRROR_MTP_COUNT)) { 10817 return BCM_E_PARAM; 10818 } 10819 10820 /* mtp_index is validated as an egress type previously */ 10821 if ((mtp_index >= MIRROR_CONFIG(unit)->port_em_mtp_count) && 10822 !(soc_feature(unit, soc_feature_mirror_flexible))) { 10823 /* Out of range */ 10824 return BCM_E_PARAM; 10825 } 10826 #ifdef BCM_GREYHOUND2_SUPPORT 10827 if(soc_feature(unit, soc_feature_high_portcount_register)){ 10828 /*For Register LO*/ 10829 BCM_IF_ERROR_RETURN(READ_EMIRROR_CONTROL_LO_64r(unit, port, &mirror)); 10830 COMPILER_64_SET(val64, SOC_PBMP_WORD_GET(*dest_bitmap, 1), 10831 SOC_PBMP_WORD_GET(*dest_bitmap, 0)); 10832 soc_reg64_field_set(unit, reg_lo[mtp_index], &mirror, 10833 BITMAP_LOf, val64); 10834 BCM_IF_ERROR_RETURN(WRITE_EMIRROR_CONTROL_LO_64r(unit, port, mirror)); 10835 /* Enable mirroring of CPU Higig packets as well */ 10836 if (IS_CPU_PORT(unit, port)) { 10837 COMPILER_64_ZERO(mirror); 10838 BCM_IF_ERROR_RETURN(READ_IEMIRROR_CONTROL_LO_64r(unit, port, &mirror)); 10839 soc_reg64_field_set(unit, hg_reg_lo[mtp_index], &mirror, 10840 BITMAP_LOf, val64); 10841 BCM_IF_ERROR_RETURN(WRITE_IEMIRROR_CONTROL_LO_64r(unit, port, mirror)); 10842 } 10843 /*For Register HI*/ 10844 COMPILER_64_ZERO(mirror); 10845 COMPILER_64_ZERO(val64); 10846 BCM_IF_ERROR_RETURN(READ_EMIRROR_CONTROL_HI_64r(unit, port, &mirror)); 10847 COMPILER_64_SET(val64, SOC_PBMP_WORD_GET(*dest_bitmap, 3), 10848 SOC_PBMP_WORD_GET(*dest_bitmap, 2)); 10849 soc_reg64_field_set(unit, reg_hi[mtp_index], &mirror, 10850 BITMAP_LOf, val64); 10851 BCM_IF_ERROR_RETURN(WRITE_EMIRROR_CONTROL_HI_64r(unit, port, mirror)); 10852 /* Enable mirroring of CPU Higig packets as well */ 10853 if (IS_CPU_PORT(unit, port)) { 10854 COMPILER_64_ZERO(mirror); 10855 BCM_IF_ERROR_RETURN(READ_IEMIRROR_CONTROL_HI_64r(unit, port, &mirror)); 10856 soc_reg64_field_set(unit, hg_reg_hi[mtp_index], &mirror, 10857 BITMAP_LOf, val64); 10858 BCM_IF_ERROR_RETURN(WRITE_IEMIRROR_CONTROL_HI_64r(unit, port, mirror)); 10859 } 10860 }else 10861 #endif /*BCM_GREYHOUND2_SUPPORT*/ 10862 { 10863 values[0] = SOC_PBMP_WORD_GET(*dest_bitmap, 0); 10864 count = 1; 10865 if (soc_reg_field_valid(unit, reg[mtp_index], BITMAP_HIf)) { 10866 values[1] = SOC_PBMP_WORD_GET(*dest_bitmap, 1); 10867 count++; 10868 } 10869 10870 BCM_IF_ERROR_RETURN 10871 (soc_reg_fields32_modify(unit, reg[mtp_index], port, count, 10872 fields, values)); 10873 10874 /* Enable mirroring of CPU Higig packets as well */ 10875 if (IS_CPU_PORT(unit, port)) { 10876 BCM_IF_ERROR_RETURN 10877 (soc_reg_fields32_modify(unit, hg_reg[mtp_index], port, count, 10878 fields, values)); 10879 } 10880 } 10881 return BCM_E_NONE; 10882 } 10883 #endif /* BCM_TRIUMPH_SUPPORT */ 10884 10885 #if defined(BCM_RAPTOR1_SUPPORT) 10886 /* 10887 * Function: 10888 * _bcm_raptor_mirror_egr_dest_get 10889 * Purpose: 10890 * Get destination port bitmap for egress mirroring. 10891 * Parameters: 10892 * unit - (IN)BCM device number. 10893 * port - (IN)port number. 10894 * dest_bitmap - (OUT) destination port bitmap. 10895 * Returns: 10896 * BCM_E_XXX 10897 */ 10898 STATIC int 10899 _bcm_raptor_mirror_egr_dest_get(int unit, bcm_port_t port, 10900 bcm_pbmp_t *dest_bitmap) 10901 { 10902 uint32 mirror; 10903 10904 /* Input parameters check. */ 10905 if (NULL == dest_bitmap) { 10906 return (BCM_E_PARAM); 10907 } 10908 10909 BCM_IF_ERROR_RETURN(READ_EMIRROR_CONTROLr(unit, port, &mirror)); 10910 SOC_PBMP_WORD_SET(*dest_bitmap, 0, 10911 soc_reg_field_get(unit, EMIRROR_CONTROLr, mirror, BITMAPf)); 10912 BCM_IF_ERROR_RETURN(READ_EMIRROR_CONTROL_HIr(unit, port, &mirror)); 10913 SOC_PBMP_WORD_SET(*dest_bitmap, 1, 10914 soc_reg_field_get(unit, EMIRROR_CONTROL_HIr, mirror, BITMAPf)); 10915 10916 return (BCM_E_NONE); 10917 } 10918 10919 10920 /* 10921 * Function: 10922 * _bcm_raptor_mirror_egr_dest_set 10923 * Purpose: 10924 * Set destination port bitmap for egress mirroring. 10925 * Parameters: 10926 * unit - (IN)BCM device number. 10927 * port - (IN)Port number. 10928 * dest_bitmap - (IN)Destination port bitmap. 10929 * Returns: 10930 * BCM_E_XXX 10931 */ 10932 STATIC int 10933 _bcm_raptor_mirror_egr_dest_set(int unit, bcm_port_t port, 10934 bcm_pbmp_t *dest_bitmap) 10935 { 10936 uint32 value; 10937 soc_field_t field = BITMAPf; 10938 10939 /* Input parameters check. */ 10940 if (NULL == dest_bitmap) { 10941 return (BCM_E_PARAM); 10942 } 10943 value = SOC_PBMP_WORD_GET(*dest_bitmap, 0); 10944 10945 BCM_IF_ERROR_RETURN 10946 (soc_reg_fields32_modify(unit, EMIRROR_CONTROLr, port, 10947 1, &field, &value)); 10948 10949 /* Enable mirroring of CPU Higig packets as well */ 10950 if (IS_CPU_PORT(unit, port)) { 10951 BCM_IF_ERROR_RETURN 10952 (soc_reg_fields32_modify(unit, IEMIRROR_CONTROLr, port, 10953 1, &field, &value)); 10954 10955 } 10956 10957 value = SOC_PBMP_WORD_GET(*dest_bitmap, 1); 10958 10959 BCM_IF_ERROR_RETURN 10960 (soc_reg_fields32_modify(unit, EMIRROR_CONTROL_HIr, port, 10961 1, &field, &value)); 10962 10963 /* Enable mirroring of CPU Higig packets as well */ 10964 if (IS_CPU_PORT(unit, port)) { 10965 BCM_IF_ERROR_RETURN 10966 (soc_reg_fields32_modify(unit, IEMIRROR_CONTROL_HIr, port, 10967 1, &field, &value)); 10968 10969 } 10970 return (BCM_E_NONE); 10971 } 10972 10973 #endif /* BCM_RAPTOR_SUPPORT */ 10974 10975 #if defined(BCM_XGS12_FABRIC_SUPPORT) 10976 /* 10977 * Function: 10978 * _bcm_xgs_fabric_mirror_enable_set 10979 * Purpose: 10980 * Enable/disable mirroring on a port & set mirror-to port. 10981 * Parameters: 10982 * unit - BCM device number 10983 * port - port number 10984 * enable - enable mirroring if non-zero 10985 * Returns: 10986 * BCM_E_XXX 10987 */ 10988 STATIC int 10989 _bcm_xgs_fabric_mirror_enable_set(int unit, int port, int enable) 10990 { 10991 pbmp_t ppbm; 10992 int mport; 10993 10994 if (!IS_HG_PORT(unit, port)) { 10995 return (BCM_E_UNAVAIL); 10996 } 10997 10998 /* Clear port when disabling */ 10999 if (enable && MIRROR_CONFIG_ING_MTP_REF_COUNT(unit, 0)) { 11000 BCM_IF_ERROR_RETURN(_bcm_mirror_destination_gport_parse(unit, 11001 MIRROR_CONFIG_ING_MTP_DEST(unit, 0), 11002 NULL , &mport, NULL)); 11003 } else { 11004 mport = 0; 11005 } 11006 11007 SOC_PBMP_CLEAR(ppbm); 11008 if (enable) { 11009 SOC_PBMP_PORT_ADD(ppbm, mport); 11010 } 11011 11012 #ifdef BCM_HERCULES15_SUPPORT 11013 if (SOC_IS_HERCULES15(unit)) { 11014 int m5670; 11015 11016 m5670 = soc_property_get(unit, spn_MIRROR_5670_MODE, 0); 11017 BCM_IF_ERROR_RETURN 11018 (soc_reg_field32_modify(unit, ING_CTRLr, port, 11019 DISABLE_MIRROR_CHANGEf, 11020 (m5670 | !enable) ? 1 : 0)); 11021 } 11022 #endif /* BCM_HERCULES15_SUPPORT */ 11023 BCM_IF_ERROR_RETURN 11024 (WRITE_ING_MIRTOBMAPr(unit, port, 11025 SOC_PBMP_WORD_GET(ppbm, 0))); 11026 return (BCM_E_NONE); 11027 } 11028 #endif /* BCM_XGS12_FABRIC_SUPPORT */ 11029 11030 /* 11031 * Function: 11032 * _bcm_mirror_dest_get_all 11033 * Purpose: 11034 * Get all mirroring destinations. 11035 * Parameters: 11036 * unit - (IN) BCM device number. 11037 * flags - (IN) BCM_MIRROR_PORT_XXX flags. 11038 * mirror_dest_size - (IN) Preallocated mirror_dest array size. 11039 * mirror_dest - (OUT)Filled array of port mirroring destinations 11040 * mirror_dest_count - (OUT)Actual number of mirroring destinations filled. 11041 * Returns: 11042 * BCM_X_XXX 11043 */ 11044 STATIC int 11045 _bcm_mirror_dest_get_all(int unit, uint32 flags, int mirror_dest_size, 11046 bcm_gport_t *mirror_dest, int *mirror_dest_count) 11047 { 11048 int idx = 0; 11049 int index = 0; 11050 11051 /* Input parameters check. */ 11052 if ((NULL == mirror_dest) || (NULL == mirror_dest_count)) { 11053 return (BCM_E_PARAM); 11054 } 11055 #ifdef BCM_TRIUMPH2_SUPPORT 11056 if (soc_feature(unit, soc_feature_mirror_flexible) && 11057 !MIRROR_MTP_METHOD_IS_DIRECTED_FLEXIBLE(unit)) { 11058 /* Copy all used shared mirror destinations. */ 11059 for (idx = 0; idx < BCM_MIRROR_MTP_COUNT; idx++) { 11060 if ((index < mirror_dest_size) && 11061 (MIRROR_CONFIG_SHARED_MTP_REF_COUNT(unit, idx))) { 11062 if ((!(MIRROR_CONFIG_SHARED_MTP(unit, idx).egress) && 11063 (flags & BCM_MIRROR_PORT_INGRESS)) || 11064 (MIRROR_CONFIG_SHARED_MTP(unit, idx).egress && 11065 (flags & BCM_MIRROR_PORT_EGRESS))) { 11066 mirror_dest[index] = 11067 MIRROR_CONFIG_SHARED_MTP_DEST(unit, idx); 11068 index++; 11069 } 11070 } 11071 } 11072 } else { 11073 #endif /* BCM_TRIUMPH2_SUPPORT */ 11074 /* Copy all used ingress mirror destinations. */ 11075 if (flags & BCM_MIRROR_PORT_INGRESS) { 11076 for (idx = 0; idx < MIRROR_CONFIG(unit)->ing_mtp_count; idx++) { 11077 if ((index < mirror_dest_size) && 11078 (MIRROR_CONFIG_ING_MTP_REF_COUNT(unit, idx))) { 11079 mirror_dest[index] = 11080 MIRROR_CONFIG_ING_MTP_DEST(unit, idx); 11081 index++; 11082 } 11083 } 11084 } 11085 11086 /* Copy all used egress mirror destinations. */ 11087 if (flags & BCM_MIRROR_PORT_EGRESS) { 11088 for (idx = 0; idx < MIRROR_CONFIG(unit)->egr_mtp_count; idx++) { 11089 if ((index < mirror_dest_size) && 11090 (MIRROR_CONFIG_EGR_MTP_REF_COUNT(unit, idx))) { 11091 mirror_dest[index] = 11092 MIRROR_CONFIG_EGR_MTP_DEST(unit, idx); 11093 index++; 11094 } 11095 } 11096 } 11097 11098 #ifdef BCM_TRIUMPH2_SUPPORT 11099 } 11100 11101 if (soc_feature(unit, soc_feature_egr_mirror_true)) { 11102 /* Copy all used egress mirror destinations. */ 11103 if (flags & BCM_MIRROR_PORT_EGRESS_TRUE) { 11104 for (idx = 0; 11105 idx < MIRROR_CONFIG(unit)->egr_true_mtp_count; 11106 idx++) { 11107 if ((index < mirror_dest_size) && 11108 (MIRROR_CONFIG_EGR_TRUE_MTP_REF_COUNT(unit, idx))) { 11109 mirror_dest[index] = 11110 MIRROR_CONFIG_EGR_TRUE_MTP_DEST(unit, idx); 11111 index++; 11112 } 11113 } 11114 } 11115 } 11116 #endif /* BCM_TRIUMPH2_SUPPORT */ 11117 11118 *mirror_dest_count = index; 11119 return (BCM_E_NONE); 11120 } 11121 11122 #if defined(BCM_XGS3_SWITCH_SUPPORT) 11123 11124 #if defined(BCM_TRX_SUPPORT) 11125 11126 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_GREYHOUND_SUPPORT) 11127 11128 #if defined(BCM_TOMAHAWK3_SUPPORT) 11129 /* 11130 * Function: 11131 * _bcm_tomahawk3_mirror_ipv6_gre_tunnel_set 11132 * Purpose: 11133 * Prepare IPv6 mirror tunnel encapsulation for Tomahawk3 11134 * Parameters: 11135 * unit - (IN) BCM device number 11136 * mirror_dest - (IN) Mirror destination descriptor 11137 * flags - (IN) Mirror direction flags 11138 * entries - (IN) Pointer to EGR_MIRROR_ENCAP_* entries array 11139 * Returns: 11140 * BCM_E_XXX 11141 */ 11142 STATIC int 11143 _bcm_tomahawk3_mirror_ipv6_gre_tunnel_set(int unit, 11144 bcm_mirror_destination_t *mirror_dest, 11145 int flags, 11146 void **entries) 11147 { 11148 /* SW tunnel encap buffers.*/ 11149 uint32 ip_buffer[_BCM_TH3_MIRROR_V6_GRE_BUFFER_SZ]; 11150 egr_mirror_encap_control_entry_t *control_entry_p; 11151 egr_mirror_encap_data_1_entry_t *data_1_entry_p; 11152 egr_mirror_encap_data_2_entry_t *data_2_entry_p; 11153 uint32 fldval; 11154 int idx; 11155 11156 /* These entries were initialized by the calling function */ 11157 control_entry_p = entries[EGR_MIRROR_ENCAP_ENTRIES_CONTROL]; 11158 data_1_entry_p = entries[EGR_MIRROR_ENCAP_ENTRIES_DATA_1]; 11159 data_2_entry_p = entries[EGR_MIRROR_ENCAP_ENTRIES_DATA_2]; 11160 11161 sal_memset(ip_buffer, 0, 11162 _BCM_TH3_MIRROR_V6_GRE_BUFFER_SZ * sizeof(uint32)); 11163 11164 /* Setup Mirror Control Memory */ 11165 soc_EGR_MIRROR_ENCAP_CONTROLm_field32_set(unit, control_entry_p, 11166 ENTRY_TYPEf, _BCM_TH3_MIRROR_ENCAP_TYPE_ERSPAN_V6); 11167 11168 /* coverity[result_independent_of_operands] */ 11169 if (BCM_VLAN_VALID(BCM_VLAN_CTRL_ID(mirror_dest->vlan_id))) { 11170 soc_EGR_MIRROR_ENCAP_CONTROLm_field32_set(unit, control_entry_p, 11171 ENCAP_SPAN__ADD_OUTER_VLANf, 1); 11172 } 11173 11174 if (mirror_dest->flags & BCM_MIRROR_DEST_PAYLOAD_UNTAGGED) { 11175 soc_EGR_MIRROR_ENCAP_CONTROLm_field32_set(unit, control_entry_p, 11176 ENCAP_SPAN__UNTAG_PAYLOADf, 1); 11177 } 11178 11179 /* Set mirror tunnel DA SA */ 11180 soc_mem_mac_addr_set(unit, EGR_MIRROR_ENCAP_DATA_2m, 11181 data_2_entry_p, ERSPAN_V6__ERSPAN_HEADER_DAf, 11182 mirror_dest->dst_mac); 11183 soc_mem_mac_addr_set(unit, EGR_MIRROR_ENCAP_DATA_2m, 11184 data_2_entry_p, ERSPAN_V6__ERSPAN_HEADER_SAf, 11185 mirror_dest->src_mac); 11186 11187 /* Set tpid & vlan id */ 11188 /* coverity[result_independent_of_operands] */ 11189 if (BCM_VLAN_VALID(BCM_VLAN_CTRL_ID(mirror_dest->vlan_id))) { 11190 fldval = (((uint32)mirror_dest->tpid << 16) | 11191 (uint32)mirror_dest->vlan_id); 11192 } else { 11193 fldval = 0; 11194 /* keep the consistent data between software and hardware */ 11195 mirror_dest->tpid = 0; 11196 mirror_dest->vlan_id = 0; 11197 } 11198 11199 soc_EGR_MIRROR_ENCAP_DATA_2m_field32_set(unit, data_2_entry_p, 11200 ERSPAN_V6__ERSPAN_HEADER_VLAN_TAGf, fldval); 11201 11202 /* Set ether type to IPv6 */ 11203 soc_EGR_MIRROR_ENCAP_DATA_2m_field32_set(unit, data_2_entry_p, 11204 ERSPAN_V6__ERSPAN_HEADER_ETYPEf, 0x86DD); 11205 11206 /* keep the consistent data between software and hardware */ 11207 mirror_dest->gre_protocol = 11208 (0 != mirror_dest->gre_protocol) ? mirror_dest->gre_protocol : 0x88BE; 11209 11210 /* Set protocol to given value, or default GRE protocol value */ 11211 soc_EGR_MIRROR_ENCAP_DATA_1m_field32_set(unit, data_1_entry_p, 11212 ERSPAN_V6__ERSPAN_HEADER_GREf, 11213 mirror_dest->gre_protocol); 11214 /* 11215 * Set IPv6 header 11216 */ 11217 idx = 9; 11218 11219 /* Flow label (20 bits) */ 11220 ip_buffer[idx] = (uint32)(mirror_dest->flow_label & 0xFFFFF); 11221 /* Header version */ 11222 ip_buffer[idx] |= (uint32)(0x6 << 28); 11223 /* Traffic class */ 11224 ip_buffer[idx--] |= (uint32)(mirror_dest->tos << 20); 11225 11226 /* Hop limit */ 11227 ip_buffer[idx] = (uint32)(mirror_dest->ttl); 11228 11229 /* Next header is GRE (protocol number 47/0x2F) */ 11230 ip_buffer[idx--] |= (uint32)(0x2F << 8); 11231 11232 /* IP addresses are copied the way they appear in src6_addr/dst6_addr 11233 * fields (no byte reversing happens) 11234 */ 11235 /* Copy source IP address */ 11236 _BCM_TH3_IP6_ADDR_COPY_TO(ip_buffer[idx], mirror_dest->src6_addr); 11237 idx--; 11238 11239 _BCM_TH3_IP6_ADDR_COPY_TO(ip_buffer[idx], mirror_dest->src6_addr + 4); 11240 idx--; 11241 11242 _BCM_TH3_IP6_ADDR_COPY_TO(ip_buffer[idx], mirror_dest->src6_addr + 8); 11243 idx--; 11244 11245 _BCM_TH3_IP6_ADDR_COPY_TO(ip_buffer[idx], mirror_dest->src6_addr + 12); 11246 idx--; 11247 11248 /* Copy destination IP address */ 11249 _BCM_TH3_IP6_ADDR_COPY_TO(ip_buffer[idx], mirror_dest->dst6_addr); 11250 idx--; 11251 11252 _BCM_TH3_IP6_ADDR_COPY_TO(ip_buffer[idx], mirror_dest->dst6_addr + 4); 11253 idx--; 11254 11255 _BCM_TH3_IP6_ADDR_COPY_TO(ip_buffer[idx], mirror_dest->dst6_addr + 8); 11256 idx--; 11257 11258 _BCM_TH3_IP6_ADDR_COPY_TO(ip_buffer[idx], mirror_dest->dst6_addr + 12); 11259 idx--; 11260 11261 soc_EGR_MIRROR_ENCAP_DATA_1m_field_set(unit, data_1_entry_p, 11262 ERSPAN_V6__ERSPAN_HEADER_V6f, ip_buffer); 11263 11264 /* Profile entries will be committed to HW by the calling function. */ 11265 11266 return (BCM_E_NONE); 11267 } 11268 #endif /* BCM_TOMAHAWK3_SUPPORT */ 11269 11270 /* 11271 * Function: 11272 * _bcm_trident_mirror_l2_tunnel_set 11273 * Purpose: 11274 * Prepare & write L2 mirror tunnel encapsulation on Trident. 11275 * Parameters: 11276 * unit - (IN) BCM device number 11277 * mirror_dest - (IN) Mirror destination descriptor. 11278 * flags - (IN) Mirror direction flags. 11279 * entries - (IN) Pointer to EGR_MIRROR_ENCAP_* entries array 11280 * Returns: 11281 * BCM_E_XXX 11282 */ 11283 STATIC int 11284 _bcm_trident_mirror_l2_tunnel_set(int unit, 11285 bcm_mirror_destination_t *mirror_dest, 11286 int flags, void **entries) 11287 { 11288 uint32 hw_buffer; /* HW buffer. */ 11289 egr_mirror_encap_control_entry_t *control_entry_p; 11290 egr_mirror_encap_data_1_entry_t *data_1_entry_p; 11291 11292 /* These entries were initialized by the calling function */ 11293 control_entry_p = entries[EGR_MIRROR_ENCAP_ENTRIES_CONTROL]; 11294 data_1_entry_p = entries[EGR_MIRROR_ENCAP_ENTRIES_DATA_1]; 11295 11296 /* Outer vlan tag. */ 11297 hw_buffer = (((uint32)mirror_dest->tpid << 16) | 11298 (uint32)mirror_dest->vlan_id); 11299 11300 /* Setup Mirror Control Memory */ 11301 soc_EGR_MIRROR_ENCAP_CONTROLm_field32_set(unit, control_entry_p, 11302 ENTRY_TYPEf, BCM_TD_MIRROR_ENCAP_TYPE_RSPAN); 11303 11304 if (SOC_MEM_FIELD_VALID(unit, EGR_MIRROR_ENCAP_CONTROLm, 11305 RSPAN__ADD_OPTIONAL_HEADERf)) { 11306 soc_EGR_MIRROR_ENCAP_CONTROLm_field32_set(unit, control_entry_p, 11307 RSPAN__ADD_OPTIONAL_HEADERf, 11308 BCM_TD_MIRROR_HEADER_ONLY); 11309 } 11310 11311 if (soc_feature(unit, soc_feature_trill)) { 11312 soc_EGR_MIRROR_ENCAP_CONTROLm_field32_set(unit, control_entry_p, 11313 RSPAN__ADD_TRILL_OUTER_VLANf, 0); 11314 } 11315 11316 /* Setup Mirror Data 1 Memory */ 11317 soc_EGR_MIRROR_ENCAP_DATA_1m_field32_set(unit, data_1_entry_p, 11318 RSPAN__RSPAN_VLAN_TAGf, hw_buffer); 11319 11320 /* Profile entries will be committed to HW by the calling function. */ 11321 11322 return (BCM_E_NONE); 11323 } 11324 11325 11326 /* 11327 * Function: 11328 * _bcm_trident_mirror_ipv4_gre_tunnel_set 11329 * Purpose: 11330 * Prepare IPv4 mirror tunnel encapsulation for Trident. 11331 * Parameters: 11332 * unit - (IN) BCM device number 11333 * mirror_dest - (IN) Mirror destination descriptor. 11334 * flags - (IN) Mirror direction flags. 11335 * entries - (IN) Pointer to EGR_MIRROR_ENCAP_* entries array 11336 * Returns: 11337 * BCM_E_XXX 11338 */ 11339 STATIC int 11340 _bcm_trident_mirror_ipv4_gre_tunnel_set(int unit, 11341 bcm_mirror_destination_t *mirror_dest, 11342 int flags, 11343 void **entries) 11344 { 11345 /*SW tunnel encap buffers.*/ 11346 uint32 ip_buffer[_BCM_TD_MIRROR_V4_GRE_BUFFER_SZ]; 11347 egr_mirror_encap_control_entry_t *control_entry_p; 11348 egr_mirror_encap_data_1_entry_t *data_1_entry_p; 11349 uint32 fldval; 11350 int idx; /* Headers offset iterator. */ 11351 11352 if (mirror_dest->df > 1) { 11353 return (BCM_E_PARAM); 11354 } 11355 11356 /* These entries were initialized by the calling function */ 11357 control_entry_p = entries[EGR_MIRROR_ENCAP_ENTRIES_CONTROL]; 11358 data_1_entry_p = entries[EGR_MIRROR_ENCAP_ENTRIES_DATA_1]; 11359 11360 sal_memset(ip_buffer, 0, 11361 _BCM_TD_MIRROR_V4_GRE_BUFFER_SZ * sizeof(uint32)); 11362 11363 /* Setup Mirror Control Memory */ 11364 soc_EGR_MIRROR_ENCAP_CONTROLm_field32_set(unit, control_entry_p, 11365 ENTRY_TYPEf, BCM_TD_MIRROR_ENCAP_TYPE_ERSPAN); 11366 11367 #ifdef BCM_TOMAHAWK3_SUPPORT 11368 if (SOC_IS_TOMAHAWK3(unit)) { 11369 /* coverity[result_independent_of_operands] */ 11370 if (BCM_VLAN_VALID(BCM_VLAN_CTRL_ID(mirror_dest->vlan_id))) { 11371 soc_EGR_MIRROR_ENCAP_CONTROLm_field32_set(unit, control_entry_p, 11372 ENCAP_SPAN__ADD_OUTER_VLANf, 1); 11373 } 11374 11375 if (mirror_dest->flags & BCM_MIRROR_DEST_PAYLOAD_UNTAGGED) { 11376 soc_EGR_MIRROR_ENCAP_CONTROLm_field32_set(unit, control_entry_p, 11377 ENCAP_SPAN__UNTAG_PAYLOADf, 1); 11378 } 11379 } else 11380 #endif /* BCM_TOMAHAWK3_SUPPORT */ 11381 { 11382 soc_EGR_MIRROR_ENCAP_CONTROLm_field32_set(unit, control_entry_p, 11383 ERSPAN__ADD_OPTIONAL_HEADERf, 11384 BCM_TD_MIRROR_HEADER_ONLY); 11385 11386 /* coverity[result_independent_of_operands] */ 11387 if (BCM_VLAN_VALID(BCM_VLAN_CTRL_ID(mirror_dest->vlan_id))) { 11388 soc_EGR_MIRROR_ENCAP_CONTROLm_field32_set(unit, control_entry_p, 11389 ERSPAN__ADD_ERSPAN_OUTER_VLANf, 1); 11390 } 11391 11392 if (mirror_dest->flags & BCM_MIRROR_DEST_PAYLOAD_UNTAGGED) { 11393 soc_EGR_MIRROR_ENCAP_CONTROLm_field32_set(unit, control_entry_p, 11394 ERSPAN__UNTAG_PAYLOADf, 1); 11395 } 11396 } 11397 11398 /* 11399 * Set mirror tunnel DA SA. 11400 */ 11401 11402 soc_mem_mac_addr_set(unit, EGR_MIRROR_ENCAP_DATA_1m, 11403 data_1_entry_p, ERSPAN__ERSPAN_HEADER_DAf, 11404 mirror_dest->dst_mac); 11405 soc_mem_mac_addr_set(unit, EGR_MIRROR_ENCAP_DATA_1m, 11406 data_1_entry_p, ERSPAN__ERSPAN_HEADER_SAf, 11407 mirror_dest->src_mac); 11408 11409 /* Set tpid & vlan id. */ 11410 /* coverity[result_independent_of_operands] */ 11411 if (BCM_VLAN_VALID(BCM_VLAN_CTRL_ID(mirror_dest->vlan_id))) { 11412 fldval = (((uint32)mirror_dest->tpid << 16) | 11413 (uint32)mirror_dest->vlan_id); 11414 } else { 11415 fldval = 0; 11416 /* keep the consistent data between software and hardware */ 11417 mirror_dest->tpid = 0; 11418 mirror_dest->vlan_id = 0; 11419 } 11420 soc_EGR_MIRROR_ENCAP_DATA_1m_field32_set(unit, data_1_entry_p, 11421 ERSPAN__ERSPAN_HEADER_VLAN_TAGf, fldval); 11422 11423 /* Set ether type to ip. 0x800 */ 11424 soc_EGR_MIRROR_ENCAP_DATA_1m_field32_set(unit, data_1_entry_p, 11425 ERSPAN__ERSPAN_HEADER_ETYPEf, 0x800); 11426 11427 /* keep the consistent data between software and hardware */ 11428 mirror_dest->gre_protocol = 11429 (0 != mirror_dest->gre_protocol) ? mirror_dest->gre_protocol : 0x88be; 11430 11431 /* Set protocol to given value, or default of GRE. 0x88be */ 11432 soc_EGR_MIRROR_ENCAP_DATA_1m_field32_set(unit, data_1_entry_p, 11433 ERSPAN__ERSPAN_HEADER_GREf, 11434 mirror_dest->gre_protocol); 11435 /* 11436 * Set IPv4 header. 11437 */ 11438 /* Version + 5 word no options length. + Tos */ 11439 /* Length, Id, Flags, Fragmentation offset. */ 11440 idx = 4; 11441 11442 ip_buffer[idx--] |= ((uint32)(0x45 << 24) | 11443 (uint32)((mirror_dest->tos) << 16)); 11444 11445 /* Do not fragment bit */ 11446 ip_buffer[idx--] |= (uint32)((mirror_dest->df) << 14); 11447 /* Ttl, Protocol (GRE 0x2f)*/ 11448 ip_buffer[idx--] = (((uint32)mirror_dest->ttl << 24) | (0x2f << 16)); 11449 11450 /* Src Ip. */ 11451 ip_buffer[idx--] = mirror_dest->src_addr; 11452 11453 /* Dst Ip. */ 11454 ip_buffer[idx] = mirror_dest->dst_addr; 11455 11456 soc_EGR_MIRROR_ENCAP_DATA_1m_field_set(unit, data_1_entry_p, 11457 ERSPAN__ERSPAN_HEADER_V4f, ip_buffer); 11458 11459 /* Profile entries will be committed to HW by the calling function. */ 11460 11461 return (BCM_E_NONE); 11462 } 11463 11464 #if defined(BCM_TOMAHAWK_SUPPORT) 11465 /* 11466 * Function: 11467 * _bcm_tomahawk_mirror_sflow_tunnel_set 11468 * Purpose: 11469 * Prepare sFlow mirror tunnel encapsulation for Trident. 11470 * Parameters: 11471 * unit - (IN) BCM device number 11472 * bcm_mirror_destination_t - (IN) Mirror destination descriptor. 11473 * flags - (IN) Mirror direction flags. 11474 * entries - (IN) Pointer to EGR_MIRROR_ENCAP_* entries array 11475 * Returns: 11476 * BCM_E_XXX 11477 */ 11478 STATIC int 11479 _bcm_tomahawk_mirror_sflow_tunnel_set(int unit, 11480 bcm_mirror_destination_t *mirror_dest, 11481 int flags, 11482 void **entries) 11483 { 11484 /*SW tunnel encap buffers.*/ 11485 uint32 ip_buffer[_BCM_TD_MIRROR_V4_GRE_BUFFER_SZ]; 11486 egr_mirror_encap_control_entry_t *control_entry_p; 11487 egr_mirror_encap_data_1_entry_t *data_1_entry_p; 11488 uint32 fldval; 11489 int idx; /* Headers offset iterator. */ 11490 11491 if (!soc_feature(unit, soc_feature_sflow_ing_mirror)) { 11492 return BCM_E_UNAVAIL; 11493 } 11494 11495 if (mirror_dest->df > 1) { 11496 return (BCM_E_PARAM); 11497 } 11498 11499 /* These entries were initialized by the calling function */ 11500 control_entry_p = entries[EGR_MIRROR_ENCAP_ENTRIES_CONTROL]; 11501 data_1_entry_p = entries[EGR_MIRROR_ENCAP_ENTRIES_DATA_1]; 11502 11503 if (control_entry_p == NULL || data_1_entry_p == NULL) { 11504 return BCM_E_INTERNAL; 11505 } 11506 11507 sal_memset(ip_buffer, 0, 11508 _BCM_TD_MIRROR_V4_GRE_BUFFER_SZ * sizeof(uint32)); 11509 11510 /* Setup Mirror Control Memory */ 11511 soc_EGR_MIRROR_ENCAP_CONTROLm_field32_set(unit, control_entry_p, 11512 ENTRY_TYPEf, BCM_TD_MIRROR_ENCAP_TYPE_SFLOW); 11513 11514 /* Program field only if it is valid (For TH3 it is not valid) */ 11515 if (SOC_MEM_FIELD_VALID(unit, EGR_MIRROR_ENCAP_CONTROLm, 11516 SFLOW__ADD_OPTIONAL_HEADERf)) { 11517 soc_EGR_MIRROR_ENCAP_CONTROLm_field32_set(unit, control_entry_p, 11518 SFLOW__ADD_OPTIONAL_HEADERf, 11519 BCM_TD_MIRROR_HEADER_ONLY); 11520 } 11521 11522 if ((BCM_VLAN_CTRL_ID(mirror_dest->vlan_id)) > 0) { 11523 /* Program field only if it is valid (For TH3 it is not valid) */ 11524 if (SOC_MEM_FIELD_VALID(unit, EGR_MIRROR_ENCAP_CONTROLm, 11525 SFLOW__ADD_SFLOW_OUTER_VLANf)) { 11526 soc_EGR_MIRROR_ENCAP_CONTROLm_field32_set(unit, control_entry_p, 11527 SFLOW__ADD_SFLOW_OUTER_VLANf, 1); 11528 } 11529 } 11530 11531 if (mirror_dest->flags & BCM_MIRROR_DEST_PAYLOAD_UNTAGGED) { 11532 soc_EGR_MIRROR_ENCAP_CONTROLm_field32_set(unit, control_entry_p, 11533 SFLOW__UNTAG_PAYLOADf, 1); 11534 } 11535 11536 /* 11537 * Set mirror tunnel DA SA. 11538 */ 11539 11540 soc_mem_mac_addr_set(unit, EGR_MIRROR_ENCAP_DATA_1m, 11541 data_1_entry_p, SFLOW__SFLOW_HEADER_DAf, 11542 mirror_dest->dst_mac); 11543 soc_mem_mac_addr_set(unit, EGR_MIRROR_ENCAP_DATA_1m, 11544 data_1_entry_p, SFLOW__SFLOW_HEADER_SAf, 11545 mirror_dest->src_mac); 11546 11547 /* Set tpid & vlan id. */ 11548 if ((BCM_VLAN_CTRL_ID(mirror_dest->vlan_id) > 0)) { 11549 fldval = (((uint32)mirror_dest->tpid << 16) | 11550 (uint32)mirror_dest->vlan_id); 11551 } else { 11552 fldval = 0; 11553 /* keep the consistent data between software and hardware */ 11554 mirror_dest->tpid = 0; 11555 mirror_dest->vlan_id = 0; 11556 } 11557 soc_EGR_MIRROR_ENCAP_DATA_1m_field32_set(unit, data_1_entry_p, 11558 SFLOW__SFLOW_HEADER_VLAN_TAGf, fldval); 11559 11560 /* Set ether type to ip. 0x800 */ 11561 soc_EGR_MIRROR_ENCAP_DATA_1m_field32_set(unit, data_1_entry_p, 11562 SFLOW__SFLOW_HEADER_ETYPEf, 0x800); 11563 11564 /* 11565 * Set IPv4 header. 11566 */ 11567 /* Version + 5 word no options length. + Tos */ 11568 /* Length, Id, Flags, Fragmentation offset. */ 11569 idx = 4; 11570 11571 ip_buffer[idx--] |= ((uint32)(0x45 << 24) | 11572 (uint32)((mirror_dest->tos) << 16)); 11573 11574 /* Do not fragment bit */ 11575 ip_buffer[idx--] |= (uint32)((mirror_dest->df) << 14); 11576 /* TTL, Protocol UDP */ 11577 ip_buffer[idx--] = (((uint32)mirror_dest->ttl << 24) | (0x11 << 16)); 11578 11579 /* Src IP. */ 11580 ip_buffer[idx--] = mirror_dest->src_addr; 11581 11582 /* Dst IP. */ 11583 ip_buffer[idx] = mirror_dest->dst_addr; 11584 11585 soc_EGR_MIRROR_ENCAP_DATA_1m_field_set(unit, data_1_entry_p, 11586 SFLOW__SFLOW_HEADER_V4f, ip_buffer); 11587 11588 /* UDP header */ 11589 idx = 1; 11590 ip_buffer[idx--] = ((uint32)(mirror_dest->udp_src_port << 16) | 11591 (uint32)(mirror_dest->udp_dst_port)); 11592 ip_buffer[0] = 0; 11593 soc_EGR_MIRROR_ENCAP_DATA_1m_field_set(unit, data_1_entry_p, 11594 SFLOW__SFLOW_HEADER_UDPf, ip_buffer); 11595 return (BCM_E_NONE); 11596 } 11597 #endif 11598 11599 /* 11600 * Function: 11601 * _bcm_trident_mirror_trill_tunnel_set 11602 * Purpose: 11603 * Prepare Trill mirror tunnel encapsulation for Trident. 11604 * Parameters: 11605 * unit - (IN) BCM device number 11606 * mirror_dest - (IN) Mirror destination descriptor. 11607 * flags - (IN) Mirror direction flags. 11608 * entries - (IN) Pointer to EGR_MIRROR_ENCAP_* entries array 11609 * Returns: 11610 * BCM_E_XXX 11611 */ 11612 STATIC int 11613 _bcm_trident_mirror_trill_tunnel_set(int unit, 11614 bcm_mirror_destination_t *mirror_dest, 11615 int flags, 11616 void **entries) 11617 { 11618 /*SW tunnel encap buffer.*/ 11619 uint32 trill_buffer[_BCM_TD_MIRROR_V4_GRE_BUFFER_SZ]; 11620 /* index to end of TRILL portion of buffer */ 11621 int idx = _BCM_TD_MIRROR_TRILL_BUFFER_SZ - 1; 11622 egr_mirror_encap_control_entry_t *control_entry_p; 11623 egr_mirror_encap_data_2_entry_t *data_2_entry_p; 11624 11625 /* These entries were initialized by the calling function */ 11626 control_entry_p = entries[EGR_MIRROR_ENCAP_ENTRIES_CONTROL]; 11627 data_2_entry_p = entries[EGR_MIRROR_ENCAP_ENTRIES_DATA_2]; 11628 11629 sal_memset(trill_buffer, 0, 11630 _BCM_TD_MIRROR_V4_GRE_BUFFER_SZ * sizeof(uint32)); 11631 11632 trill_buffer[idx--] = ((uint32)(BCM_TD_MIRROR_TRILL_VERSION << 11633 BCM_TD_MIRROR_TRILL_VERSION_OFFSET) | 11634 (uint32)(mirror_dest->trill_hopcount << 11635 BCM_TD_MIRROR_TRILL_HOPCOUNT_OFFSET) | 11636 (uint32)(mirror_dest->trill_src_name)); 11637 trill_buffer[idx] = ((uint32)(mirror_dest->trill_dst_name << 11638 BCM_TD_MIRROR_TRILL_DEST_NAME_OFFSET)); 11639 11640 soc_EGR_MIRROR_ENCAP_DATA_2m_field_set(unit, data_2_entry_p, 11641 HEADER_DATAf, trill_buffer); 11642 11643 /* sFlow, ERSPAN and RSPAN use the same field and encoding. */ 11644 soc_EGR_MIRROR_ENCAP_CONTROLm_field32_set(unit, control_entry_p, 11645 ERSPAN__ADD_OPTIONAL_HEADERf, 11646 BCM_TD_MIRROR_HEADER_TRILL); 11647 11648 return (BCM_E_NONE); 11649 } 11650 11651 /* 11652 * Function: 11653 * _bcm_trident_mirror_niv_tunnel_set 11654 * Purpose: 11655 * Prepare NIV mirror tunnel encapsulation for Trident. 11656 * Parameters: 11657 * unit - (IN) BCM device number 11658 * mirror_dest - (IN) Mirror destination descriptor. 11659 * flags - (IN) Mirror direction flags. 11660 * entries - (IN) Pointer to EGR_MIRROR_ENCAP_* entries array 11661 * Returns: 11662 * BCM_E_XXX 11663 */ 11664 STATIC int 11665 _bcm_trident_mirror_niv_tunnel_set(int unit, 11666 bcm_mirror_destination_t *mirror_dest, 11667 int flags, 11668 void **entries) 11669 { 11670 /*SW tunnel encap buffers.*/ 11671 uint32 niv_buffer; 11672 egr_mirror_encap_control_entry_t *control_entry_p; 11673 egr_mirror_encap_data_2_entry_t *data_2_entry_p; 11674 11675 /* These entries were initialized by the calling function */ 11676 control_entry_p = entries[EGR_MIRROR_ENCAP_ENTRIES_CONTROL]; 11677 data_2_entry_p = entries[EGR_MIRROR_ENCAP_ENTRIES_DATA_2]; 11678 11679 niv_buffer = 0; 11680 niv_buffer = ((uint32) mirror_dest->niv_src_vif) & \ 11681 _BCM_TD_MIRROR_NIV_SRC_VIF_MASK; 11682 if (mirror_dest->niv_flags & BCM_MIRROR_NIV_LOOP) { 11683 niv_buffer |= _BCM_TD_MIRROR_NIV_LOOP_BIT; 11684 } 11685 niv_buffer |= ((uint32) mirror_dest->niv_dst_vif << 11686 _BCM_TD_MIRROR_NIV_DST_VIF_OFFSET); 11687 11688 soc_EGR_MIRROR_ENCAP_DATA_2m_field32_set(unit, data_2_entry_p, 11689 VNTAG_HEADERf, niv_buffer); 11690 11691 /* ERSPAN and RSPAN use the same field and encoding. */ 11692 soc_EGR_MIRROR_ENCAP_CONTROLm_field32_set(unit, control_entry_p, 11693 ERSPAN__ADD_OPTIONAL_HEADERf, 11694 BCM_TD_MIRROR_HEADER_VNTAG); 11695 11696 return (BCM_E_NONE); 11697 } 11698 11699 #endif 11700 11701 /* 11702 * Function: 11703 * _bcm_mirror_etag_tunnel_set 11704 * Purpose: 11705 * Prepare ETAG mirror tunnel encapsulation. 11706 * Parameters: 11707 * unit - (IN) BCM device number 11708 * mirror_dest - (IN) Mirror destination descriptor. 11709 * flags - (IN) Mirror direction flags. 11710 * entries - (IN) Pointer to EGR_MIRROR_ENCAP_* entries array 11711 * Returns: 11712 * BCM_E_XXX 11713 */ 11714 STATIC int 11715 _bcm_mirror_etag_tunnel_set(int unit, 11716 bcm_mirror_destination_t *mirror_dest, 11717 int flags, 11718 void **entries) 11719 { 11720 /*SW tunnel encap buffers.*/ 11721 uint32 etag_buffer; 11722 egr_mirror_encap_control_entry_t *control_entry_p; 11723 egr_mirror_encap_data_2_entry_t *data_2_entry_p; 11724 11725 /* These entries were initialized by the calling function */ 11726 control_entry_p = entries[BCM_EGR_MIRROR_ENCAP_ENTRIES_CONTROL]; 11727 data_2_entry_p = entries[BCM_EGR_MIRROR_ENCAP_ENTRIES_DATA_2]; 11728 11729 etag_buffer = 0; 11730 11731 etag_buffer |= ((uint32) mirror_dest->etag_src_vid & _BCM_MIRROR_ETAG_SRC_VID_MASK) 11732 << _BCM_MIRROR_ETAG_SRC_VID_OFFSET; 11733 etag_buffer |= (uint32) mirror_dest->etag_dst_vid & _BCM_MIRROR_ETAG_DST_VID_MASK; 11734 11735 soc_EGR_MIRROR_ENCAP_DATA_2m_field32_set(unit, data_2_entry_p, 11736 HEADER_DATAf, etag_buffer); 11737 11738 /* ERSPAN and RSPAN use the same field and encoding. */ 11739 soc_EGR_MIRROR_ENCAP_CONTROLm_field32_set(unit, control_entry_p, 11740 ERSPAN__ADD_OPTIONAL_HEADERf, 11741 BCM_MIRROR_HEADER_ETAG); 11742 11743 return (BCM_E_NONE); 11744 } 11745 11746 11747 /* 11748 * Function: 11749 * _bcm_trx_mirror_egr_erspan_write 11750 * Purpose: 11751 * Program HW buffer. 11752 * Parameters: 11753 * unit - (IN) BCM device number. 11754 * index - (IN) Mtp index. 11755 * buffer - (IN) Tunnel encapsulation buffer. 11756 * flags - (IN) Mirror direction flags. 11757 * Returns: 11758 * BCM_E_XXX 11759 */ 11760 STATIC int 11761 _bcm_trx_mirror_egr_erspan_write(int unit, int index, uint32 *buffer, int flags) 11762 { 11763 bcm_mirror_destination_t *mirror_dest;/* Destination & encapsulation. */ 11764 _bcm_mtp_config_p mtp_cfg; /* MTP configuration. */ 11765 egr_erspan_entry_t hw_buf; /* Hw table buffer */ 11766 11767 #if defined(BCM_TRIUMPH2_SUPPORT) 11768 uint32 erspan_enable; 11769 #endif 11770 11771 /* Get mtp configuration structure by direction & index. */ 11772 mtp_cfg = MIRROR_CONFIG_MTP(unit, index, flags); 11773 11774 /* Advance index according to flags. */ 11775 if (flags & BCM_MIRROR_PORT_EGRESS) { 11776 index += 4; 11777 } else if (flags & BCM_MIRROR_PORT_EGRESS_TRUE) { /* True Egress */ 11778 index += 8; 11779 } 11780 11781 mirror_dest = MIRROR_DEST(unit, mtp_cfg->dest_id); 11782 11783 /* Reset hw buffer. */ 11784 sal_memset(&hw_buf, 0, sizeof(egr_erspan_entry_t)); 11785 11786 #if defined(BCM_TRIUMPH2_SUPPORT) 11787 BCM_IF_ERROR_RETURN 11788 (soc_mem_read(unit, EGR_ERSPANm, MEM_BLOCK_ALL, index, &hw_buf)); 11789 11790 soc_EGR_ERSPANm_field_get(unit, &hw_buf, ERSPAN_ENABLEf, &erspan_enable); 11791 /* If there is a replace flag, check if the entry exsits in the memory. 11792 If no entry is found, return SOC_E_NOT_FOUND*/ 11793 if ((mirror_dest->flags) & BCM_MIRROR_DEST_REPLACE) { 11794 if ((MIRROR_DEST_REF_COUNT(unit, mtp_cfg->dest_id) == 0) || 11795 (erspan_enable == 0)) { 11796 return SOC_E_NOT_FOUND; 11797 } 11798 } 11799 #endif 11800 11801 /* Enable tunneling for mtp . */ 11802 soc_mem_field32_set(unit, EGR_ERSPANm, &hw_buf, ERSPAN_ENABLEf, 1); 11803 11804 /* Set untag payload flag. */ 11805 if (mirror_dest->flags & BCM_MIRROR_DEST_PAYLOAD_UNTAGGED) { 11806 soc_EGR_ERSPANm_field32_set(unit, &hw_buf, UNTAG_PAYLOADf, 1); 11807 } 11808 11809 /* Set tunnel header.. */ 11810 /* coverity[result_independent_of_operands] */ 11811 if (BCM_VLAN_VALID(BCM_VLAN_CTRL_ID(mirror_dest->vlan_id))) { 11812 soc_EGR_ERSPANm_field32_set(unit, &hw_buf, USE_TAGGED_HEADERf, 1); 11813 soc_EGR_ERSPANm_field_set(unit, &hw_buf, HEADER_TAGGEDf, buffer); 11814 } else { 11815 soc_EGR_ERSPANm_field_set(unit, &hw_buf, HEADER_UNTAGGEDf, buffer); 11816 } 11817 11818 /* Write buffer to hw. */ 11819 BCM_IF_ERROR_RETURN 11820 (soc_mem_write(unit, EGR_ERSPANm, MEM_BLOCK_ALL, index, &hw_buf)); 11821 11822 return (BCM_E_NONE); 11823 } 11824 11825 /* 11826 * Function: 11827 * _bcm_trx_mirror_ipv4_gre_tunnel_set 11828 * Purpose: 11829 * Prepare IPv4 mirror tunnel encapsulation. 11830 * Parameters: 11831 * unit - (IN) BCM device number 11832 * index - (IN) Mtp index. 11833 * flags - (IN) Mirror direction flags. 11834 * Returns: 11835 * BCM_E_XXX 11836 */ 11837 STATIC int 11838 _bcm_trx_mirror_ipv4_gre_tunnel_set(int unit, int index, int flags) 11839 { 11840 bcm_mirror_destination_t *mirror_dest;/* Destination & encapsulation. */ 11841 uint32 buffer[_BCM_TRX_MIRROR_TUNNEL_BUFFER_SZ];/*SW tunnel encap buffer.*/ 11842 _bcm_mtp_config_p mtp_cfg; /* Mtp configuration. . */ 11843 int idx; /* Headers offset iterator. */ 11844 11845 /* Get mtp configuration structure by direction & index. */ 11846 mtp_cfg = MIRROR_CONFIG_MTP(unit, index, flags); 11847 11848 mirror_dest = MIRROR_DEST(unit, mtp_cfg->dest_id); 11849 11850 sal_memset(buffer, 0, _BCM_TRX_MIRROR_TUNNEL_BUFFER_SZ * sizeof(uint32)); 11851 11852 /* 11853 * L2 Header. 11854 */ 11855 /* coverity[result_independent_of_operands] */ 11856 idx = BCM_VLAN_VALID(BCM_VLAN_CTRL_ID(mirror_dest->vlan_id)) ? 10 : 9; 11857 11858 /* Destination mac address. */ 11859 buffer[idx--] = (((uint32)(mirror_dest->dst_mac)[0]) << 8 | \ 11860 ((uint32)(mirror_dest->dst_mac)[1])); 11861 11862 buffer[idx--] = (((uint32)(mirror_dest->dst_mac)[2]) << 24 | \ 11863 ((uint32)(mirror_dest->dst_mac)[3]) << 16 | \ 11864 ((uint32)(mirror_dest->dst_mac)[4]) << 8 | \ 11865 ((uint32)(mirror_dest->dst_mac)[5])); 11866 11867 /* Source mac address. */ 11868 buffer[idx--] = (((uint32)(mirror_dest->src_mac)[0]) << 24 | \ 11869 ((uint32)(mirror_dest->src_mac)[1]) << 16 | \ 11870 ((uint32)(mirror_dest->src_mac)[2]) << 8 | \ 11871 ((uint32)(mirror_dest->src_mac)[3])); 11872 11873 buffer[idx] = (((uint32)(mirror_dest->src_mac)[4]) << 24 | \ 11874 ((uint32)(mirror_dest->src_mac)[5]) << 16); 11875 11876 /* Set tpid & vlan id. */ 11877 /* coverity[result_independent_of_operands] */ 11878 if (BCM_VLAN_VALID(BCM_VLAN_CTRL_ID(mirror_dest->vlan_id))) { 11879 /* Tpid. */ 11880 buffer[idx--] |= (((uint32)(mirror_dest->tpid >> 8)) << 8 | \ 11881 ((uint32)(mirror_dest->tpid & 0xff))); 11882 11883 /* Priority, Cfi, Vlan id. */ 11884 buffer[idx] = (((uint32)(mirror_dest->vlan_id >> 8)) << 24 | \ 11885 ((uint32)(mirror_dest->vlan_id & 0xff) << 16)); 11886 } 11887 11888 /* Set ether type to ip. 0x800 */ 11889 buffer[idx--] |= (uint32)(0x08 << 8); 11890 11891 /* 11892 * IPv4 header. 11893 */ 11894 /* Version + 5 word no options length. + Tos */ 11895 /* Length, Id, Flags, Fragmentation offset. */ 11896 buffer[idx--] |= ((uint32)(0x45 << 24) | \ 11897 (uint32)(mirror_dest->tos) << 16); 11898 11899 idx--; 11900 /* Ttl, Protocol (GRE 0x2f)*/ 11901 buffer[idx--] = (((uint32)mirror_dest->ttl << 24) | (0x2f << 16)); 11902 11903 /* Src Ip. */ 11904 buffer[idx--] = mirror_dest->src_addr; 11905 11906 /* Dst Ip. */ 11907 buffer[idx--] = mirror_dest->dst_addr; 11908 11909 /* 11910 * Gre header. 11911 */ 11912 11913 /* Protocol. 0x88be */ 11914 buffer[idx] = (0 != mirror_dest->gre_protocol) ? 11915 mirror_dest->gre_protocol : 0x88be; 11916 11917 /* swap byte in tunnel buffer. */ 11918 /* _shr_bit_rev8(buffer[idx]); */ 11919 11920 BCM_IF_ERROR_RETURN 11921 (_bcm_trx_mirror_egr_erspan_write(unit, index, (uint32 *)buffer, flags)); 11922 11923 return (BCM_E_NONE); 11924 } 11925 11926 /* 11927 * Function: 11928 * _bcm_trx_mirror_rspan_write 11929 * Purpose: 11930 * Prepare & write L2 mirror tunnel encapsulation. 11931 * Parameters: 11932 * unit - (IN) BCM device number 11933 * index - (IN) Mtp index. 11934 * port- (IN) 11935 * flags - (IN) Mirror direction flags. 11936 * Returns: 11937 * BCM_E_XXX 11938 */ 11939 STATIC int 11940 _bcm_trx_mirror_rspan_write(int unit, int index, bcm_port_t port, int flags) 11941 { 11942 bcm_mirror_destination_t *mirror_dest;/* Destination & encapsulation. */ 11943 _bcm_mtp_config_p mtp_cfg; /* Mtp configuration. */ 11944 uint32 hw_buffer; /* HW buffer. */ 11945 11946 11947 /* Get mtp configuration structure by direction & index. */ 11948 mtp_cfg = MIRROR_CONFIG_MTP(unit, index, flags); 11949 11950 mirror_dest = MIRROR_DEST(unit, mtp_cfg->dest_id); 11951 11952 /* Outer vlan tag. */ 11953 hw_buffer = (((uint32)mirror_dest->tpid << 16) | 11954 (uint32)mirror_dest->vlan_id); 11955 11956 BCM_IF_ERROR_RETURN(soc_reg_field32_modify(unit, EGR_RSPAN_VLAN_TAGr, 11957 port, TAGf, hw_buffer)); 11958 return (BCM_E_NONE); 11959 } 11960 11961 /* 11962 * Function: 11963 * _bcm_trx_mirror_l2_tunnel_set 11964 * Purpose: 11965 * Programm mirror L2 tunnel 11966 * Parameters: 11967 * unit - (IN) BCM device number 11968 * index - (IN) Mtp index. 11969 * trunk_arr - (IN) Mirror destinations array. 11970 * flags - (IN) Mirror direction flags. 11971 * Returns: 11972 * BCM_E_XXX 11973 */ 11974 STATIC int 11975 _bcm_trx_mirror_l2_tunnel_set(int unit, int index, 11976 bcm_gport_t *trunk_arr, int flags) 11977 { 11978 bcm_module_t my_modid; /* Local modid. */ 11979 int idx; /* Trunk members iteration index. */ 11980 bcm_module_t mod_out; /* Hw mapped modid. */ 11981 bcm_port_t port_out; /* Hw mapped port number. */ 11982 bcm_module_t modid; /* Application space modid. */ 11983 bcm_port_t port; /* Application space port number. */ 11984 11985 /* Input parameters check. */ 11986 if (NULL == trunk_arr) { 11987 return (BCM_E_PARAM); 11988 } 11989 11990 /* Get local base module id. */ 11991 BCM_IF_ERROR_RETURN (bcm_esw_stk_my_modid_get(unit, &my_modid)); 11992 11993 for (idx = 0; idx < BCM_SWITCH_TRUNK_MAX_PORTCNT; idx++) { 11994 modid = BCM_GPORT_MODPORT_MODID_GET(trunk_arr[idx]); 11995 port = BCM_GPORT_MODPORT_PORT_GET(trunk_arr[idx]); 11996 BCM_IF_ERROR_RETURN 11997 (_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_SET, modid, port, 11998 &mod_out, &port_out)); 11999 if (mod_out != my_modid) { 12000 /* Not a local front-panel port. 12001 * Use bcm_mirror_vlan_set for remote ports. */ 12002 return BCM_E_PARAM; 12003 } 12004 12005 if (0 == IS_E_PORT(unit, port_out)) { 12006 /* Not a local front-panel port. 12007 * Use bcm_mirror_vlan_set for remote ports. */ 12008 return BCM_E_PARAM; 12009 } 12010 12011 BCM_IF_ERROR_RETURN 12012 (_bcm_trx_mirror_rspan_write(unit, index, port_out, flags)); 12013 } 12014 12015 return (BCM_E_NONE); 12016 } 12017 12018 #ifdef BCM_TOMAHAWK3_SUPPORT 12019 /* 12020 * Function: 12021 * _bcm_tomahawk3_mirror_encap_type_get 12022 * Purpose: 12023 * Generate hardware encapsulation type based on flags passed by application 12024 * Parameters: 12025 * unit - (IN) BCM device number 12026 * mirror_dest - (IN) Mirror destination structure 12027 * encap_type - (OUT) Value for encapsulation type to be programmed in h/w 12028 * Returns: 12029 * BCM_E_XXX 12030 */ 12031 STATIC int 12032 _bcm_tomahawk3_mirror_encap_type_get(bcm_mirror_destination_t *mirror_dest, 12033 uint32 *encap_type) 12034 { 12035 *encap_type = _BCM_TH3_MIRROR_ENCAP_TYPE_NONE; /* Default value */ 12036 12037 if (mirror_dest->flags & BCM_MIRROR_DEST_TUNNEL_SFLOW) { 12038 if (mirror_dest->flags & BCM_MIRROR_DEST_TUNNEL_WITH_SEQ) { 12039 *encap_type = (mirror_dest->version == 4) ? 12040 _BCM_TH3_MIRROR_ENCAP_TYPE_SFLOW_SEQ : 12041 _BCM_TH3_MIRROR_ENCAP_TYPE_SFLOW_V6_SEQ; 12042 } else { 12043 *encap_type = (mirror_dest->version == 4) ? 12044 _BCM_TH3_MIRROR_ENCAP_TYPE_SFLOW : 12045 _BCM_TH3_MIRROR_ENCAP_TYPE_SFLOW_V6; 12046 } 12047 12048 return BCM_E_NONE; 12049 } else { 12050 if (mirror_dest->flags & BCM_MIRROR_DEST_TUNNEL_PSAMP) { 12051 if (mirror_dest->flags2 & BCM_MIRROR_DEST_FLAGS2_PSAMP_FORMAT_2) { 12052 *encap_type = (mirror_dest->version == 4) ? 12053 _BCM_TH3_MIRROR_ENCAP_TYPE_PSAMP_FORMAT_2 : 12054 _BCM_TH3_MIRROR_ENCAP_TYPE_PSAMP_FORMAT_2_V6; 12055 } else { 12056 *encap_type = (mirror_dest->version == 4) ? 12057 _BCM_TH3_MIRROR_ENCAP_TYPE_PSAMP : 12058 _BCM_TH3_MIRROR_ENCAP_TYPE_PSAMP_V6; 12059 } 12060 12061 return BCM_E_NONE; 12062 } 12063 } 12064 12065 if (mirror_dest->flags & BCM_MIRROR_DEST_TUNNEL_IP_GRE) { 12066 *encap_type = (mirror_dest->version == 4) ? 12067 _BCM_TH3_MIRROR_ENCAP_TYPE_ERSPAN : 12068 _BCM_TH3_MIRROR_ENCAP_TYPE_ERSPAN_V6; 12069 return BCM_E_NONE; 12070 } 12071 12072 if (mirror_dest->flags & BCM_MIRROR_DEST_TUNNEL_L2) { 12073 *encap_type = _BCM_TH3_MIRROR_ENCAP_TYPE_RSPAN; 12074 } 12075 12076 /* If no flags are specified, _BCM_TH3_MIRROR_ENCAP_TYPE_NONE is returned, 12077 * and memories are programmed as mentioned in ARCHTH3-444 12078 */ 12079 12080 return BCM_E_NONE; 12081 } 12082 12083 /* 12084 * Function: 12085 * _bcm_tomahawk3_mirror_ipv4_header_create 12086 * Purpose: 12087 * Generate IPv4 header based on parameters passed by application 12088 * Parameters: 12089 * mirror_dest - (IN) Mirror destination structure 12090 * ip_buffer - (OUT) Buffer which holds generated IPv4 header 12091 * buffer_size - (IN) Size of 'ip_buffer' array 12092 * Returns: 12093 * BCM_E_XXX 12094 */ 12095 STATIC int 12096 _bcm_tomahawk3_mirror_ipv4_header_create(bcm_mirror_destination_t *mirror_dest, 12097 uint32 *ip_buffer, 12098 int buffer_size) 12099 { 12100 int idx; 12101 12102 if (buffer_size < _BCM_TH3_MIRROR_V4_BUFFER_SZ) { 12103 return BCM_E_INTERNAL; 12104 } 12105 12106 /* Set IPv4 header */ 12107 /* Version + 5 word no options length. + TOS */ 12108 /* Length, Id, Flags, Fragmentation offset. */ 12109 idx = 4; 12110 12111 ip_buffer[idx--] |= ((uint32)(0x45 << 24) | 12112 (uint32)((mirror_dest->tos) << 16)); 12113 12114 /* Do not fragment bit */ 12115 ip_buffer[idx--] |= (uint32)((mirror_dest->df) << 14); 12116 12117 /* TTL, Protocol UDP (0x11/17) */ 12118 ip_buffer[idx--] = (((uint32)mirror_dest->ttl << 24) | (0x11 << 16)); 12119 12120 /* Src IP */ 12121 ip_buffer[idx--] = mirror_dest->src_addr; 12122 12123 /* Dst IP */ 12124 ip_buffer[idx] = mirror_dest->dst_addr; 12125 12126 return BCM_E_NONE; 12127 } 12128 12129 /* 12130 * Function: 12131 * _bcm_tomahawk3_mirror_ipv6_header_create 12132 * Purpose: 12133 * Generate IPv6 header based on parameters passed by application 12134 * Parameters: 12135 * mirror_dest - (IN) Mirror destination structure 12136 * ip_buffer - (OUT) Buffer which holds generated IPv6 header 12137 * buffer_size - (IN) Size of 'ip_buffer' array 12138 * Returns: 12139 * BCM_E_XXX 12140 */ 12141 STATIC int 12142 _bcm_tomahawk3_mirror_ipv6_header_create(bcm_mirror_destination_t *mirror_dest, 12143 uint32 *ip_buffer, 12144 int buffer_size) 12145 { 12146 int idx; 12147 12148 if (buffer_size < _BCM_TH3_MIRROR_V6_BUFFER_SZ) { 12149 return BCM_E_INTERNAL; 12150 } 12151 12152 /* 12153 * Set IPv6 header 12154 */ 12155 idx = 9; 12156 12157 /* Flow label (20 bits) */ 12158 ip_buffer[idx] = (uint32)(mirror_dest->flow_label & 0xFFFFF); 12159 /* Header version */ 12160 ip_buffer[idx] |= (uint32)(0x6 << 28); 12161 /* Traffic class */ 12162 ip_buffer[idx--] |= (uint32)(mirror_dest->tos << 20); 12163 12164 /* Hop limit */ 12165 ip_buffer[idx] = (uint32)(mirror_dest->ttl); 12166 12167 /* Next header is UDP (protocol number 17/0x11) */ 12168 ip_buffer[idx--] |= (uint32)(0x11 << 8); 12169 12170 /* IP addresses are copied the way they appear in src6_addr/dst6_addr 12171 * fields (no byte reversing happens) 12172 */ 12173 /* Copy source IP address */ 12174 _BCM_TH3_IP6_ADDR_COPY_TO(ip_buffer[idx], mirror_dest->src6_addr); 12175 idx--; 12176 12177 _BCM_TH3_IP6_ADDR_COPY_TO(ip_buffer[idx], mirror_dest->src6_addr + 4); 12178 idx--; 12179 12180 _BCM_TH3_IP6_ADDR_COPY_TO(ip_buffer[idx], mirror_dest->src6_addr + 8); 12181 idx--; 12182 12183 _BCM_TH3_IP6_ADDR_COPY_TO(ip_buffer[idx], mirror_dest->src6_addr + 12); 12184 idx--; 12185 12186 /* Copy destination IP address */ 12187 _BCM_TH3_IP6_ADDR_COPY_TO(ip_buffer[idx], mirror_dest->dst6_addr); 12188 idx--; 12189 12190 _BCM_TH3_IP6_ADDR_COPY_TO(ip_buffer[idx], mirror_dest->dst6_addr + 4); 12191 idx--; 12192 12193 _BCM_TH3_IP6_ADDR_COPY_TO(ip_buffer[idx], mirror_dest->dst6_addr + 8); 12194 idx--; 12195 12196 _BCM_TH3_IP6_ADDR_COPY_TO(ip_buffer[idx], mirror_dest->dst6_addr + 12); 12197 idx--; 12198 12199 return BCM_E_NONE; 12200 } 12201 12202 /* 12203 * Function: 12204 * _bcm_tomahawk3_mirror_udp_header_create 12205 * Purpose: 12206 * Generate UDP header based on parameters passed by application 12207 * Parameters: 12208 * mirror_dest - (IN) Mirror destination structure 12209 * udp_buffer - (OUT) Buffer which holds generated UDP header 12210 * buffer_size - (IN) Size of 'ip_buffer' array 12211 * Returns: 12212 * BCM_E_XXX 12213 */ 12214 STATIC int 12215 _bcm_tomahawk3_mirror_udp_header_create(bcm_mirror_destination_t *mirror_dest, 12216 uint32 *udp_buffer, 12217 int buffer_size) 12218 { 12219 int idx; 12220 12221 if (buffer_size < _BCM_TH3_MIRROR_UDP_BUFFER_SZ) { 12222 return BCM_E_INTERNAL; 12223 } 12224 12225 /* UDP header */ 12226 idx = 1; 12227 udp_buffer[idx--] = ((uint32)(mirror_dest->udp_src_port << 16) | 12228 (uint32)(mirror_dest->udp_dst_port)); 12229 udp_buffer[0] = 0; 12230 12231 return BCM_E_NONE; 12232 } 12233 12234 /* 12235 * Function: 12236 * _bcm_tomahawk3_mirror_sflow_psamp_v6_tunnel_set 12237 * Purpose: 12238 * This function creates a IPv6-based SFLOW or PSAMP tunnel headers based on 12239 * parameters passed by application 12240 * Parameters: 12241 * unit - (IN) BCM device number 12242 * mirror_dest - (IN) Mirror destination structure 12243 * flags - (IN) Flags specifying any actions/operations to be applied 12244 * for mirrored packets flowing through the tunnel 12245 * entries - (OUT) Buffer which holds values for encap control, encap 12246 * data1 and encap data2; these values are programmed 12247 * in to the corresponding memories 12248 * Returns: 12249 * BCM_E_XXX 12250 */ 12251 STATIC int 12252 _bcm_tomahawk3_mirror_sflow_psamp_v6_tunnel_set(int unit, 12253 bcm_mirror_destination_t *mirror_dest, 12254 int flags, 12255 void **entries) 12256 { 12257 uint32 ip_buffer[_BCM_TH3_MIRROR_V6_BUFFER_SZ]; 12258 egr_mirror_encap_control_entry_t *control_entry_p; 12259 egr_mirror_encap_data_1_entry_t *data_1_entry_p; 12260 egr_mirror_encap_data_2_entry_t *data_2_entry_p; 12261 uint32 fldval; 12262 uint32 encap_type; 12263 12264 if (!soc_feature(unit, soc_feature_sflow_ing_mirror)) { 12265 return BCM_E_UNAVAIL; 12266 } 12267 12268 if (mirror_dest->df > 1) { 12269 return (BCM_E_PARAM); 12270 } 12271 12272 /* These entries were initialized by the calling function */ 12273 control_entry_p = entries[EGR_MIRROR_ENCAP_ENTRIES_CONTROL]; 12274 data_1_entry_p = entries[EGR_MIRROR_ENCAP_ENTRIES_DATA_1]; 12275 data_2_entry_p = entries[EGR_MIRROR_ENCAP_ENTRIES_DATA_2]; 12276 12277 sal_memset(ip_buffer, 0, 12278 _BCM_TH3_MIRROR_V6_BUFFER_SZ * sizeof(uint32)); 12279 12280 /* Setup Mirror Control Memory */ 12281 if (_bcm_tomahawk3_mirror_encap_type_get(mirror_dest, 12282 &encap_type) == BCM_E_NONE) { 12283 soc_EGR_MIRROR_ENCAP_CONTROLm_field32_set(unit, control_entry_p, 12284 ENTRY_TYPEf, encap_type); 12285 } 12286 12287 /* coverity[result_independent_of_operands] */ 12288 if (BCM_VLAN_VALID(BCM_VLAN_CTRL_ID(mirror_dest->vlan_id))) { 12289 soc_EGR_MIRROR_ENCAP_CONTROLm_field32_set(unit, control_entry_p, 12290 ENCAP_SPAN__ADD_OUTER_VLANf, 1); 12291 } 12292 12293 if (mirror_dest->flags & BCM_MIRROR_DEST_PAYLOAD_UNTAGGED) { 12294 soc_EGR_MIRROR_ENCAP_CONTROLm_field32_set(unit, control_entry_p, 12295 ENCAP_SPAN__UNTAG_PAYLOADf, 1); 12296 } 12297 12298 if ((encap_type == _BCM_TH3_MIRROR_ENCAP_TYPE_SFLOW_V6) || 12299 (encap_type == _BCM_TH3_MIRROR_ENCAP_TYPE_SFLOW_V6_SEQ)) { 12300 /* Set mirror tunnel DA SA */ 12301 soc_mem_mac_addr_set(unit, EGR_MIRROR_ENCAP_DATA_2m, 12302 data_2_entry_p, SFLOW_V6__SFLOW_HEADER_DAf, 12303 mirror_dest->dst_mac); 12304 soc_mem_mac_addr_set(unit, EGR_MIRROR_ENCAP_DATA_2m, 12305 data_2_entry_p, SFLOW_V6__SFLOW_HEADER_SAf, 12306 mirror_dest->src_mac); 12307 12308 /* Set tpid & vlan id */ 12309 /* coverity[result_independent_of_operands] */ 12310 if (BCM_VLAN_VALID(BCM_VLAN_CTRL_ID(mirror_dest->vlan_id))) { 12311 fldval = (((uint32)mirror_dest->tpid << 16) | 12312 (uint32)mirror_dest->vlan_id); 12313 } else { 12314 fldval = 0; 12315 /* keep consistent data between software and hardware */ 12316 mirror_dest->tpid = 0; 12317 mirror_dest->vlan_id = 0; 12318 } 12319 12320 /* Note we are setting vlan tag below, even if 12321 * BCM_MIRROR_DEST_PAYLOAD_UNTAGGED is not set. This is same as in 12322 * legacy code 12323 */ 12324 soc_EGR_MIRROR_ENCAP_DATA_2m_field32_set(unit, data_2_entry_p, 12325 SFLOW_V6__SFLOW_HEADER_VLAN_TAGf, fldval); 12326 12327 /* Set ether type to IPv6 */ 12328 soc_EGR_MIRROR_ENCAP_DATA_2m_field32_set(unit, data_2_entry_p, 12329 SFLOW_V6__SFLOW_HEADER_ETYPEf, 0x86DD); 12330 12331 /* Set up IPv6 header */ 12332 BCM_IF_ERROR_RETURN(_bcm_tomahawk3_mirror_ipv6_header_create( 12333 mirror_dest, ip_buffer, 12334 _BCM_TH3_MIRROR_V6_BUFFER_SZ)); 12335 12336 soc_EGR_MIRROR_ENCAP_DATA_1m_field_set(unit, data_1_entry_p, 12337 SFLOW_V6__SFLOW_HEADER_V6f, 12338 ip_buffer); 12339 12340 sal_memset(ip_buffer, 0, 12341 _BCM_TH3_MIRROR_V6_BUFFER_SZ * sizeof(uint32)); 12342 12343 /* Set up UDP header */ 12344 BCM_IF_ERROR_RETURN(_bcm_tomahawk3_mirror_udp_header_create(mirror_dest, 12345 ip_buffer, _BCM_TH3_MIRROR_UDP_BUFFER_SZ)); 12346 12347 soc_EGR_MIRROR_ENCAP_DATA_1m_field_set(unit, data_1_entry_p, 12348 SFLOW_V6__SFLOW_HEADER_UDPf, 12349 ip_buffer); 12350 } 12351 12352 if ((encap_type == _BCM_TH3_MIRROR_ENCAP_TYPE_PSAMP_V6) || 12353 (encap_type == _BCM_TH3_MIRROR_ENCAP_TYPE_PSAMP_FORMAT_2_V6)) { 12354 12355 /* Set observation domain and template id */ 12356 soc_EGR_MIRROR_ENCAP_DATA_2m_field32_set(unit, data_2_entry_p, 12357 PSAMP_V6__OBSERVATION_IDf, 12358 mirror_dest->observation_domain); 12359 soc_EGR_MIRROR_ENCAP_DATA_2m_field32_set(unit, data_2_entry_p, 12360 PSAMP_V6__TEMPLATE_IDf, 12361 (uint32)mirror_dest->template_id); 12362 12363 /* Set mirror tunnel DA SA */ 12364 soc_mem_mac_addr_set(unit, EGR_MIRROR_ENCAP_DATA_2m, 12365 data_2_entry_p, PSAMP_V6__PSAMP_HEADER_DAf, 12366 mirror_dest->dst_mac); 12367 soc_mem_mac_addr_set(unit, EGR_MIRROR_ENCAP_DATA_2m, 12368 data_2_entry_p, PSAMP_V6__PSAMP_HEADER_SAf, 12369 mirror_dest->src_mac); 12370 12371 /* Set tpid & vlan id */ 12372 /* coverity[result_independent_of_operands] */ 12373 if (BCM_VLAN_VALID(BCM_VLAN_CTRL_ID(mirror_dest->vlan_id))) { 12374 fldval = (((uint32)mirror_dest->tpid << 16) | 12375 (uint32)mirror_dest->vlan_id); 12376 } else { 12377 fldval = 0; 12378 /* keep consistent data between software and hardware */ 12379 mirror_dest->tpid = 0; 12380 mirror_dest->vlan_id = 0; 12381 } 12382 12383 /* Note we are setting vlan tag below, even if 12384 * BCM_MIRROR_DEST_PAYLOAD_UNTAGGED is not set. This is same as in 12385 * legacy code 12386 */ 12387 soc_EGR_MIRROR_ENCAP_DATA_2m_field32_set(unit, data_2_entry_p, 12388 PSAMP_V6__PSAMP_HEADER_VLAN_TAGf, fldval); 12389 12390 /* Set ether type to IPv6 */ 12391 soc_EGR_MIRROR_ENCAP_DATA_2m_field32_set(unit, data_2_entry_p, 12392 PSAMP_V6__PSAMP_HEADER_ETYPEf, 0x86DD); 12393 12394 /* Set up IPv6 header */ 12395 BCM_IF_ERROR_RETURN(_bcm_tomahawk3_mirror_ipv6_header_create( 12396 mirror_dest, ip_buffer, 12397 _BCM_TH3_MIRROR_V6_BUFFER_SZ)); 12398 12399 soc_EGR_MIRROR_ENCAP_DATA_1m_field_set(unit, data_1_entry_p, 12400 PSAMP_V6__PSAMP_HEADER_V6f, ip_buffer); 12401 12402 sal_memset(ip_buffer, 0, 12403 _BCM_TH3_MIRROR_V6_BUFFER_SZ * sizeof(uint32)); 12404 12405 /* Set up UDP header */ 12406 BCM_IF_ERROR_RETURN(_bcm_tomahawk3_mirror_udp_header_create(mirror_dest, 12407 ip_buffer, _BCM_TH3_MIRROR_UDP_BUFFER_SZ)); 12408 12409 soc_EGR_MIRROR_ENCAP_DATA_1m_field_set(unit, data_1_entry_p, 12410 PSAMP_V6__PSAMP_HEADER_UDPf, ip_buffer); 12411 } 12412 12413 /* Profile entries will be committed to HW by the calling function. */ 12414 12415 return (BCM_E_NONE); 12416 } 12417 12418 /* 12419 * Function: 12420 * _bcm_tomahawk3_mirror_sflow_psamp_v4_tunnel_set 12421 * Purpose: 12422 * This function creates a IPv4-based SFLOW or PSAMP tunnel headers based on 12423 * parameters passed by application 12424 * Parameters: 12425 * unit - (IN) BCM device number 12426 * mirror_dest - (IN) Mirror destination structure 12427 * flags - (IN) Flags specifying any actions/operations to be applied 12428 * for mirrored packets flowing through the tunnel 12429 * entries - (OUT) Buffer which holds values for encap control, encap 12430 * data1 and encap data2; these values are programmed 12431 * in to the corresponding memories 12432 * Returns: 12433 * BCM_E_XXX 12434 */ 12435 STATIC 12436 int _bcm_tomahawk3_mirror_sflow_psamp_v4_tunnel_set(int unit, 12437 bcm_mirror_destination_t *mirror_dest, 12438 int flags, 12439 void **entries) 12440 { 12441 uint32 ip_buffer[_BCM_TH3_MIRROR_V4_BUFFER_SZ]; 12442 egr_mirror_encap_control_entry_t *control_entry_p; 12443 egr_mirror_encap_data_1_entry_t *data_1_entry_p; 12444 egr_mirror_encap_data_2_entry_t *data_2_entry_p; 12445 uint32 encap_type; 12446 uint32 fldval; 12447 12448 if (!soc_feature(unit, soc_feature_sflow_ing_mirror)) { 12449 return BCM_E_UNAVAIL; 12450 } 12451 12452 if (mirror_dest->df > 1) { 12453 return (BCM_E_PARAM); 12454 } 12455 12456 /* These entries were initialized by the calling function */ 12457 control_entry_p = entries[EGR_MIRROR_ENCAP_ENTRIES_CONTROL]; 12458 data_1_entry_p = entries[EGR_MIRROR_ENCAP_ENTRIES_DATA_1]; 12459 data_2_entry_p = entries[EGR_MIRROR_ENCAP_ENTRIES_DATA_2]; 12460 12461 if (control_entry_p == NULL || data_1_entry_p == NULL) { 12462 return BCM_E_INTERNAL; 12463 } 12464 12465 sal_memset(ip_buffer, 0, 12466 _BCM_TH3_MIRROR_V4_BUFFER_SZ * sizeof(uint32)); 12467 12468 /* Setup Mirror Control Memory */ 12469 if (_bcm_tomahawk3_mirror_encap_type_get(mirror_dest, 12470 &encap_type) == BCM_E_NONE) { 12471 soc_EGR_MIRROR_ENCAP_CONTROLm_field32_set(unit, control_entry_p, 12472 ENTRY_TYPEf, encap_type); 12473 } 12474 12475 /* coverity[result_independent_of_operands] */ 12476 if (BCM_VLAN_VALID(BCM_VLAN_CTRL_ID(mirror_dest->vlan_id))) { 12477 soc_EGR_MIRROR_ENCAP_CONTROLm_field32_set(unit, control_entry_p, 12478 ENCAP_SPAN__ADD_OUTER_VLANf, 1); 12479 } 12480 12481 if (mirror_dest->flags & BCM_MIRROR_DEST_PAYLOAD_UNTAGGED) { 12482 soc_EGR_MIRROR_ENCAP_CONTROLm_field32_set(unit, control_entry_p, 12483 ENCAP_SPAN__UNTAG_PAYLOADf, 1); 12484 } 12485 12486 if ((encap_type == _BCM_TH3_MIRROR_ENCAP_TYPE_PSAMP) || 12487 (encap_type == _BCM_TH3_MIRROR_ENCAP_TYPE_PSAMP_FORMAT_2)) { 12488 12489 /* Set observation domain and template id */ 12490 soc_EGR_MIRROR_ENCAP_DATA_2m_field32_set(unit, data_2_entry_p, 12491 PSAMP__OBSERVATION_IDf, 12492 mirror_dest->observation_domain); 12493 soc_EGR_MIRROR_ENCAP_DATA_2m_field32_set(unit, data_2_entry_p, 12494 PSAMP__TEMPLATE_IDf, 12495 (uint32)mirror_dest->template_id); 12496 12497 /* Set mirror tunnel DA SA */ 12498 soc_mem_mac_addr_set(unit, EGR_MIRROR_ENCAP_DATA_1m, 12499 data_1_entry_p, PSAMP__PSAMP_HEADER_DAf, 12500 mirror_dest->dst_mac); 12501 soc_mem_mac_addr_set(unit, EGR_MIRROR_ENCAP_DATA_1m, 12502 data_1_entry_p, PSAMP__PSAMP_HEADER_SAf, 12503 mirror_dest->src_mac); 12504 12505 /* Set tpid & vlan id */ 12506 if ((BCM_VLAN_CTRL_ID(mirror_dest->vlan_id) > 0)) { 12507 fldval = (((uint32)mirror_dest->tpid << 16) | 12508 (uint32)mirror_dest->vlan_id); 12509 } else { 12510 fldval = 0; 12511 /* Keep consistent data between software and hardware */ 12512 mirror_dest->tpid = 0; 12513 mirror_dest->vlan_id = 0; 12514 } 12515 12516 soc_EGR_MIRROR_ENCAP_DATA_1m_field32_set(unit, data_1_entry_p, 12517 PSAMP__PSAMP_HEADER_VLAN_TAGf, 12518 fldval); 12519 12520 /* Set ether type to IP (0x800) */ 12521 soc_EGR_MIRROR_ENCAP_DATA_1m_field32_set(unit, data_1_entry_p, 12522 PSAMP__PSAMP_HEADER_ETYPEf, 12523 0x800); 12524 12525 /* Set up IPv4 header */ 12526 BCM_IF_ERROR_RETURN(_bcm_tomahawk3_mirror_ipv4_header_create( 12527 mirror_dest, ip_buffer, 12528 _BCM_TH3_MIRROR_V4_BUFFER_SZ)); 12529 12530 soc_EGR_MIRROR_ENCAP_DATA_1m_field_set(unit, data_1_entry_p, 12531 PSAMP__PSAMP_HEADER_V4f, ip_buffer); 12532 12533 sal_memset(ip_buffer, 0, 12534 _BCM_TH3_MIRROR_V4_BUFFER_SZ * sizeof(uint32)); 12535 12536 /* Set up UDP header */ 12537 BCM_IF_ERROR_RETURN(_bcm_tomahawk3_mirror_udp_header_create( 12538 mirror_dest, ip_buffer, 12539 _BCM_TH3_MIRROR_UDP_BUFFER_SZ)); 12540 12541 soc_EGR_MIRROR_ENCAP_DATA_1m_field_set(unit, data_1_entry_p, 12542 PSAMP__PSAMP_HEADER_UDPf, ip_buffer); 12543 } 12544 12545 if ((encap_type == _BCM_TH3_MIRROR_ENCAP_TYPE_SFLOW) || 12546 (encap_type == _BCM_TH3_MIRROR_ENCAP_TYPE_SFLOW_SEQ)) { 12547 /* Set mirror tunnel DA SA */ 12548 soc_mem_mac_addr_set(unit, EGR_MIRROR_ENCAP_DATA_1m, 12549 data_1_entry_p, SFLOW__SFLOW_HEADER_DAf, 12550 mirror_dest->dst_mac); 12551 soc_mem_mac_addr_set(unit, EGR_MIRROR_ENCAP_DATA_1m, 12552 data_1_entry_p, SFLOW__SFLOW_HEADER_SAf, 12553 mirror_dest->src_mac); 12554 12555 /* Set tpid & vlan id */ 12556 if ((BCM_VLAN_CTRL_ID(mirror_dest->vlan_id) > 0)) { 12557 fldval = (((uint32)mirror_dest->tpid << 16) | 12558 (uint32)mirror_dest->vlan_id); 12559 } else { 12560 fldval = 0; 12561 /* Keep consistent data between software and hardware */ 12562 mirror_dest->tpid = 0; 12563 mirror_dest->vlan_id = 0; 12564 } 12565 12566 soc_EGR_MIRROR_ENCAP_DATA_1m_field32_set(unit, data_1_entry_p, 12567 SFLOW__SFLOW_HEADER_VLAN_TAGf, fldval); 12568 12569 /* Set ether type to IP (0x800) */ 12570 soc_EGR_MIRROR_ENCAP_DATA_1m_field32_set(unit, data_1_entry_p, 12571 SFLOW__SFLOW_HEADER_ETYPEf, 0x800); 12572 12573 /* Set up IPv4 header */ 12574 BCM_IF_ERROR_RETURN(_bcm_tomahawk3_mirror_ipv4_header_create( 12575 mirror_dest, ip_buffer, 12576 _BCM_TH3_MIRROR_V4_BUFFER_SZ)); 12577 12578 soc_EGR_MIRROR_ENCAP_DATA_1m_field_set(unit, data_1_entry_p, 12579 SFLOW__SFLOW_HEADER_V4f, 12580 ip_buffer); 12581 12582 sal_memset(ip_buffer, 0, 12583 _BCM_TH3_MIRROR_V4_BUFFER_SZ * sizeof(uint32)); 12584 12585 /* Set up UDP header */ 12586 BCM_IF_ERROR_RETURN(_bcm_tomahawk3_mirror_udp_header_create( 12587 mirror_dest, ip_buffer, 12588 _BCM_TH3_MIRROR_UDP_BUFFER_SZ)); 12589 12590 soc_EGR_MIRROR_ENCAP_DATA_1m_field_set(unit, data_1_entry_p, 12591 SFLOW__SFLOW_HEADER_UDPf, 12592 ip_buffer); 12593 } 12594 12595 return (BCM_E_NONE); 12596 } 12597 12598 /* 12599 * Function: 12600 * _bcm_tomahawk3_mirror_sflow_psamp_seq_num_set 12601 * Purpose: 12602 * This function programs EGR_MIRROR_SEQ memory with sequence number passed 12603 * by caller 12604 * Parameters: 12605 * unit - (IN) BCM device number 12606 * index - (IN) MTP index 12607 * profile_index - (IN) Encap profile index where the entry needs to be 12608 * written in h/w 12609 * flags - (IN) Flags specifying direction (ingress/egress) 12610 * seq_num - (IN) The sequence number to be programmed 12611 * Returns: 12612 * BCM_E_XXX 12613 */ 12614 STATIC 12615 int _bcm_tomahawk3_mirror_sflow_psamp_seq_num_set(int unit, int index, 12616 int profile_index, int flags, 12617 uint32 seq_num) 12618 { 12619 _bcm_mtp_config_p mtp_cfg; 12620 bcm_gport_t mirror_dest; 12621 bcm_module_t modid; 12622 bcm_port_t port; 12623 bcm_trunk_t tgid; 12624 int id; 12625 int pipe; 12626 soc_info_t *si = &SOC_INFO(unit); 12627 soc_mem_t mem; 12628 egr_mirror_seq_entry_t entry; 12629 int rv; 12630 12631 12632 mtp_cfg = MIRROR_CONFIG_MTP(unit, index, flags); 12633 mirror_dest = MIRROR_DEST_GPORT(unit, mtp_cfg->dest_id); 12634 12635 BCM_IF_ERROR_RETURN(_bcm_esw_gport_resolve(unit, mirror_dest, &modid, &port, 12636 &tgid, &id)); 12637 12638 if (!SOC_MODID_ADDRESSABLE(unit, modid)) { 12639 return (BCM_E_BADID); 12640 } 12641 if (!SOC_PORT_ADDRESSABLE(unit, port)) { 12642 return (BCM_E_PORT); 12643 } 12644 12645 if (si->port_pipe[port] == -1) { 12646 return BCM_E_PORT; 12647 } 12648 12649 /* Bcmsim implements EGR_MIRROR_SEQ as a 'global' memory, that is, not as a 12650 * pipe dependent memory 12651 */ 12652 if (SAL_BOOT_BCMSIM) { 12653 mem = EGR_MIRROR_SEQm; 12654 } else { 12655 pipe = si->port_pipe[port]; 12656 12657 if ((pipe < 0) || (pipe > (NUM_PIPE(unit) - 1))) { 12658 return SOC_E_INTERNAL; 12659 } 12660 12661 mem = SOC_MEM_UNIQUE_ACC(unit, EGR_MIRROR_SEQm)[pipe]; 12662 } 12663 12664 if ((profile_index < soc_mem_index_min(unit, mem)) || 12665 (profile_index > soc_mem_index_max(unit, mem))) { 12666 return SOC_E_PARAM; 12667 } 12668 12669 sal_memset((void *)&entry, 0, sizeof(egr_mirror_seq_entry_t)); 12670 12671 soc_mem_field32_set(unit, mem, &entry, SEQ_NUMf, seq_num); 12672 12673 soc_mem_lock(unit, mem); 12674 rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, profile_index, (void *)&entry); 12675 soc_mem_unlock(unit, mem); 12676 12677 return (rv); 12678 } 12679 12680 /* 12681 * Function: 12682 * _bcm_tomahawk3_mirror_sflow_psamp_user_meta_data_set 12683 * Purpose: 12684 * This function programs EGR_MIRROR_USER_META_DATA memory with user defined 12685 * information when a Sflow with seq number or psamp format2 tunnel is 12686 * created 12687 * Parameters: 12688 * unit - (IN) BCM device number 12689 * index - (IN) MTP index 12690 * profile_index - (IN) Encap profile index where the entry needs to be 12691 * written in h/w 12692 * flags - (IN) Flags specifying direction (ingress/egress) 12693 * Returns: 12694 * BCM_E_XXX 12695 */ 12696 STATIC 12697 int _bcm_tomahawk3_mirror_sflow_psamp_user_meta_data_set(int unit, int index, 12698 int profile_index, int flags) 12699 { 12700 bcm_mirror_destination_t *mirror_dest; 12701 _bcm_mtp_config_p mtp_cfg; 12702 egr_mirror_user_meta_data_entry_t entry; 12703 soc_mem_t mem = EGR_MIRROR_USER_META_DATAm; 12704 int rv; 12705 12706 12707 mtp_cfg = MIRROR_CONFIG_MTP(unit, index, flags); 12708 mirror_dest = MIRROR_DEST(unit, mtp_cfg->dest_id); 12709 12710 if ((profile_index < soc_mem_index_min(unit, mem)) || 12711 (profile_index > soc_mem_index_max(unit, mem))) { 12712 return SOC_E_PARAM; 12713 } 12714 12715 mem = EGR_MIRROR_USER_META_DATAm; 12716 12717 sal_memset((void *)&entry, 0, sizeof(egr_mirror_user_meta_data_entry_t)); 12718 12719 soc_mem_field32_set(unit, mem, &entry, USER_META_OR_CLASS_IDf, 12720 mirror_dest->meta_data_type); 12721 12722 /* Program USER_META_DATA only if meta_data_type passed by appl is 3 */ 12723 if (mirror_dest->meta_data_type == bcmMirrorPsampFmt2HeaderUserMeta) { 12724 soc_mem_field32_set(unit, mem, &entry, USER_META_DATAf, 12725 mirror_dest->meta_data); 12726 } 12727 12728 soc_mem_lock(unit, mem); 12729 rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, profile_index, (void *)&entry); 12730 soc_mem_unlock(unit, mem); 12731 12732 return (rv); 12733 } 12734 12735 /* 12736 * Function: 12737 * _bcm_tomahawk3_egr_mirror_truncation_update 12738 * Purpose: 12739 * This function programs truncation setting into EGR_IM/EM_MTP_INDEX memory 12740 * Parameters: 12741 * unit - (IN) BCM device number 12742 * index - (IN) MTP index 12743 * truncate - (IN) Encoding for truncation type 12744 * BCM_MIRROR_PAYLOAD_TRUNCATE, or 12745 * BCM_MIRROR_PAYLOAD_TRUNCATE_AND_ZERO 12746 * flags - (IN) Flags specifying direction (ingress/egress) 12747 * Returns: 12748 * BCM_E_XXX 12749 */ 12750 STATIC 12751 int _bcm_tomahawk3_egr_mirror_truncation_update(int unit, int index, 12752 int truncate, int flags) 12753 { 12754 if (truncate > BCM_MIRROR_PAYLOAD_TRUNCATE_AND_ZERO) { 12755 return BCM_E_PARAM; 12756 } 12757 12758 if (flags & BCM_MIRROR_PORT_INGRESS) { 12759 BCM_IF_ERROR_RETURN(soc_mem_field32_modify(unit, EGR_IM_MTP_INDEXm, 12760 index, TRUNCATE_MIRROR_COPYf, 12761 truncate)); 12762 } 12763 12764 if (flags & BCM_MIRROR_PORT_EGRESS) { 12765 /* Payload zeroing is supported only on ingress */ 12766 if (truncate == BCM_MIRROR_PAYLOAD_TRUNCATE_AND_ZERO) { 12767 return BCM_E_CONFIG; 12768 } 12769 12770 BCM_IF_ERROR_RETURN(soc_mem_field32_modify(unit, EGR_EM_MTP_INDEXm, 12771 index, TRUNCATE_MIRROR_COPYf, 12772 truncate)); 12773 } 12774 12775 return BCM_E_NONE; 12776 } 12777 12778 /* 12779 * Function: 12780 * _bcm_tomahawk3_mirror_non_tunnel_config_set 12781 * Purpose: 12782 * This function programs hardware for processing non tunneled mirrored 12783 * packets to which payload zeroing or truncating can be applied 12784 * Parameters: 12785 * unit - (IN) BCM device number 12786 * index - (IN) Mtp index 12787 * flags - (IN) Mirror direction flags 12788 * Returns: 12789 * BCM_E_XXX 12790 */ 12791 STATIC int 12792 _bcm_tomahawk3_mirror_non_tunnel_config_set(int unit, int index, int flags) 12793 { 12794 bcm_mirror_destination_t *mirror_dest; 12795 _bcm_mtp_config_p mtp_cfg; 12796 int rv = BCM_E_NONE; 12797 12798 egr_mirror_encap_control_entry_t control_entry; 12799 egr_mirror_encap_data_1_entry_t data_1_entry; 12800 egr_mirror_encap_data_2_entry_t data_2_entry; 12801 void *entries[EGR_MIRROR_ENCAP_ENTRIES_NUM]; 12802 uint32 profile_index; 12803 int max_num_trunk_ports = 0; 12804 int offset = 0; 12805 12806 sal_memset(&control_entry, 0, sizeof(control_entry)); 12807 sal_memset(&data_1_entry, 0, sizeof(data_1_entry)); 12808 sal_memset(&data_2_entry, 0, sizeof(data_2_entry)); 12809 12810 entries[EGR_MIRROR_ENCAP_ENTRIES_CONTROL] = &control_entry; 12811 entries[EGR_MIRROR_ENCAP_ENTRIES_DATA_1] = &data_1_entry; 12812 entries[EGR_MIRROR_ENCAP_ENTRIES_DATA_2] = &data_2_entry; 12813 12814 /* Get mtp configuration structure by direction & index. */ 12815 mtp_cfg = MIRROR_CONFIG_MTP(unit, index, flags); 12816 12817 mirror_dest = MIRROR_DEST(unit, mtp_cfg->dest_id); 12818 12819 /* Set entry type to reserved value of 0xF (ARCHTH3-444) */ 12820 soc_EGR_MIRROR_ENCAP_CONTROLm_field32_set(unit, 12821 entries[EGR_MIRROR_ENCAP_ENTRIES_CONTROL], 12822 ENTRY_TYPEf, 12823 _BCM_TH3_MIRROR_ENCAP_TYPE_NONE); 12824 12825 /* Remove the previous profile index if any */ 12826 if (BCM_SUCCESS(rv) && (mirror_dest->flags & BCM_MIRROR_DEST_REPLACE)) { 12827 uint32 old_profile_index = -1; 12828 int profile_ref_count = 0; 12829 egr_im_mtp_index_entry_t egr_im_mtp_index_entry; 12830 egr_em_mtp_index_entry_t egr_em_mtp_index_entry; 12831 12832 max_num_trunk_ports = 1; 12833 12834 /* We use offset = index below since 12835 * EGR_IM/EM_MTP_INDEX are * 4 entries deep 12836 */ 12837 12838 offset = index * max_num_trunk_ports; 12839 12840 if (flags & BCM_MIRROR_PORT_INGRESS) { 12841 rv = READ_EGR_IM_MTP_INDEXm(unit, MEM_BLOCK_ANY, offset, 12842 &egr_im_mtp_index_entry); 12843 if (BCM_SUCCESS(rv) && 12844 (0 != soc_EGR_IM_MTP_INDEXm_field32_get(unit, 12845 &egr_im_mtp_index_entry, 12846 MIRROR_ENCAP_ENABLEf))) { 12847 old_profile_index = 12848 soc_EGR_IM_MTP_INDEXm_field32_get(unit, 12849 &egr_im_mtp_index_entry, 12850 MIRROR_ENCAP_INDEXf); 12851 12852 } 12853 } 12854 12855 if (flags & BCM_MIRROR_PORT_EGRESS && BCM_SUCCESS(rv)) { 12856 rv = READ_EGR_EM_MTP_INDEXm(unit, MEM_BLOCK_ANY, offset, 12857 &egr_em_mtp_index_entry); 12858 if (BCM_SUCCESS(rv) && 12859 (0 != soc_EGR_EM_MTP_INDEXm_field32_get(unit, 12860 &egr_em_mtp_index_entry, 12861 MIRROR_ENCAP_ENABLEf))) { 12862 old_profile_index = 12863 soc_EGR_EM_MTP_INDEXm_field32_get(unit, 12864 &egr_em_mtp_index_entry, 12865 MIRROR_ENCAP_INDEXf); 12866 12867 } 12868 } 12869 12870 if (-1 != old_profile_index) { 12871 BCM_IF_ERROR_RETURN 12872 (_bcm_egr_mirror_encap_entry_ref_get(unit, 12873 old_profile_index, 12874 &profile_ref_count)); 12875 if (profile_ref_count != 0) { 12876 rv = _bcm_egr_mirror_encap_entry_delete(unit, 12877 old_profile_index); 12878 } 12879 } 12880 } 12881 12882 if (BCM_SUCCESS(rv)) { 12883 rv = _bcm_egr_mirror_encap_entry_add(unit, entries, &profile_index); 12884 } 12885 12886 if (soc_feature(unit, soc_feature_mirror_control_mem)) { 12887 if (BCM_SUCCESS(rv)) { 12888 /* Supply the correct profile index to the selected MTPs */ 12889 if (flags & BCM_MIRROR_PORT_INGRESS) { 12890 BCM_IF_ERROR_RETURN 12891 (soc_mem_field32_modify(unit, EGR_IM_MTP_INDEXm, index, 12892 MIRROR_ENCAP_ENABLEf, 1)); 12893 BCM_IF_ERROR_RETURN 12894 (soc_mem_field32_modify(unit, EGR_IM_MTP_INDEXm, 12895 index, MIRROR_ENCAP_INDEXf, 12896 profile_index)); 12897 } 12898 12899 /* EGR_EM_MTP_INDEX has same layout as EGR_IM_MTP_INDEX */ 12900 if (flags & BCM_MIRROR_PORT_EGRESS) { 12901 BCM_IF_ERROR_RETURN 12902 (soc_mem_field32_modify(unit, EGR_EM_MTP_INDEXm, index, 12903 MIRROR_ENCAP_ENABLEf, 1)); 12904 BCM_IF_ERROR_RETURN 12905 (soc_mem_field32_modify(unit, EGR_EM_MTP_INDEXm, 12906 index, MIRROR_ENCAP_INDEXf, 12907 profile_index)); 12908 } 12909 } 12910 } 12911 12912 return (rv); 12913 } 12914 #endif /* BCM_TOMAHAWK3_SUPPORT */ 12915 12916 #ifdef BCM_TOMAHAWK_SUPPORT 12917 /* 12918 * Function: 12919 * _bcm_mirror_sflow_tunnel_set 12920 * Purpose: 12921 * Prepare sFlow mirror tunnel encapsulation. 12922 * Parameters: 12923 * unit - (IN) BCM device number 12924 * index - (IN) Mtp index. 12925 * trunk_arr - (IN) Mirror destinations array. 12926 * flags - (IN) Mirror direction flags. 12927 * Returns: 12928 * BCM_E_XXX 12929 */ 12930 STATIC int 12931 _bcm_mirror_sflow_tunnel_set(int unit, int index, 12932 bcm_gport_t *trunk_arr, int flags) 12933 { 12934 bcm_mirror_destination_t *mirror_dest; /* Destination & Encapsulation.*/ 12935 _bcm_mtp_config_p mtp_cfg; /* MTP configuration . */ 12936 int rv = BCM_E_NONE; /* Operation return status. */ 12937 egr_mirror_encap_control_entry_t control_entry; 12938 egr_mirror_encap_data_1_entry_t data_1_entry; 12939 egr_mirror_encap_data_2_entry_t data_2_entry; 12940 void *entries[EGR_MIRROR_ENCAP_ENTRIES_NUM]; 12941 uint32 profile_index; 12942 12943 sal_memset(&control_entry, 0, sizeof(control_entry)); 12944 sal_memset(&data_1_entry, 0, sizeof(data_1_entry)); 12945 sal_memset(&data_2_entry, 0, sizeof(data_2_entry)); 12946 12947 entries[EGR_MIRROR_ENCAP_ENTRIES_CONTROL] = &control_entry; 12948 entries[EGR_MIRROR_ENCAP_ENTRIES_DATA_1] = &data_1_entry; 12949 entries[EGR_MIRROR_ENCAP_ENTRIES_DATA_2] = &data_2_entry; 12950 12951 /* Get mtp configuration structure by direction & index. */ 12952 mtp_cfg = MIRROR_CONFIG_MTP(unit, index, flags); 12953 12954 mirror_dest = MIRROR_DEST(unit, mtp_cfg->dest_id); 12955 12956 /* Configure sFlow headers */ 12957 rv = _bcm_tomahawk_mirror_sflow_tunnel_set(unit, mirror_dest, flags, entries); 12958 12959 if (BCM_SUCCESS(rv)) { 12960 rv = _bcm_egr_mirror_encap_entry_add(unit, entries, &profile_index); 12961 } 12962 12963 if (BCM_SUCCESS(rv)) { 12964 /* Supply the correct profile index to the selected MTPs */ 12965 rv = _bcm_egr_mirror_encap_entry_mtp_update(unit, index, 12966 profile_index, flags); 12967 } 12968 12969 return rv; 12970 } 12971 #endif /* BCM_TOMAHAWK_SUPPORT */ 12972 12973 #ifdef BCM_TRIDENT2_SUPPORT 12974 /* Set mirror tunnel for a shared-id mirror destination. */ 12975 #ifdef BCM_TOMAHAWK3_SUPPORT 12976 /* This function is only called if BCM_MIRROR_DEST_ID_SHARE is set. For TH3, it 12977 * will not be used 12978 */ 12979 #endif /* BCM_TOMAHAWK3_SUPPORT */ 12980 STATIC int 12981 _bcm_td2_mirror_shared_dest_tunnel_set(int unit, int index, 12982 bcm_gport_t *trunk_arr, int flags, 12983 bcm_gport_t mir_dest_id, int is_eport) 12984 { 12985 int rv = BCM_E_NONE; 12986 bcm_mirror_destination_t mirror_dest_node; /* Destination node */ 12987 uint32 prof_idx[BCM_SWITCH_TRUNK_MAX_PORTCNT] = {-1,-1,-1,-1,-1,-1,-1,-1}; 12988 egr_im_mtp_index_entry_t egr_im_mtp_index_entry; 12989 egr_em_mtp_index_entry_t egr_em_mtp_index_entry; 12990 egr_ep_redirect_em_mtp_index_entry_t egr_em_redirect_mtp_index_entry; 12991 egr_mirror_encap_control_entry_t control_entry; 12992 egr_mirror_encap_data_1_entry_t data_1_entry; 12993 egr_mirror_encap_data_2_entry_t data_2_entry; 12994 void *entries[EGR_MIRROR_ENCAP_ENTRIES_NUM]; 12995 int update_eme = FALSE; /* EGR_MIRROR_ENCAP_* pointers */ 12996 int max_num_trunk_ports = 0; 12997 int offset = 0; 12998 bcm_gport_t mir_dest_gport_array[BCM_SWITCH_TRUNK_MAX_PORTCNT] = {0}; 12999 int mir_dest_gport_count = 0, i, id; 13000 bcm_trunk_t trunk = BCM_TRUNK_INVALID; 13001 bcm_module_t modid = 0; 13002 bcm_port_t port = -1; 13003 uint32 old_profile_index = -1; 13004 int profile_ref_count = 0; 13005 13006 if (NULL == trunk_arr || !BCM_GPORT_IS_MIRROR(mir_dest_id)) { 13007 return (BCM_E_PARAM); 13008 } 13009 13010 sal_memset(&control_entry, 0, sizeof(control_entry)); 13011 sal_memset(&data_1_entry, 0, sizeof(data_1_entry)); 13012 sal_memset(&data_2_entry, 0, sizeof(data_2_entry)); 13013 13014 entries[EGR_MIRROR_ENCAP_ENTRIES_CONTROL] = &control_entry; 13015 entries[EGR_MIRROR_ENCAP_ENTRIES_DATA_1] = &data_1_entry; 13016 entries[EGR_MIRROR_ENCAP_ENTRIES_DATA_2] = &data_2_entry; 13017 13018 BCM_IF_ERROR_RETURN( 13019 _bcm_mirror_dest_mtp_gport_get(unit, 13020 mir_dest_id, 13021 mir_dest_gport_array, 13022 &mir_dest_gport_count)); 13023 13024 if (mir_dest_gport_count <= 0) { 13025 return (BCM_E_INIT); 13026 } 13027 13028 max_num_trunk_ports = BCM_SWITCH_TRUNK_MAX_PORTCNT; 13029 offset = index * max_num_trunk_ports; 13030 13031 /* Remove the previous profile index if any */ 13032 for (i = 0; i < max_num_trunk_ports; i++, offset++) { 13033 sal_memset(&egr_im_mtp_index_entry, 0, 13034 sizeof(egr_im_mtp_index_entry_t)); 13035 sal_memset(&egr_em_mtp_index_entry, 0, 13036 sizeof(egr_em_mtp_index_entry_t)); 13037 sal_memset(&egr_em_redirect_mtp_index_entry, 0, 13038 sizeof(egr_ep_redirect_em_mtp_index_entry_t)); 13039 old_profile_index = -1; 13040 profile_ref_count = 0; 13041 13042 if (flags & BCM_MIRROR_PORT_INGRESS) { 13043 rv = READ_EGR_IM_MTP_INDEXm(unit, MEM_BLOCK_ANY, offset, 13044 &egr_im_mtp_index_entry); 13045 if (BCM_SUCCESS(rv) && 13046 (0 != soc_EGR_IM_MTP_INDEXm_field32_get( 13047 unit, 13048 &egr_im_mtp_index_entry, 13049 MIRROR_ENCAP_ENABLEf))) { 13050 old_profile_index = soc_EGR_IM_MTP_INDEXm_field32_get( 13051 unit, 13052 &egr_im_mtp_index_entry, 13053 MIRROR_ENCAP_INDEXf); 13054 } 13055 } 13056 13057 if (flags & BCM_MIRROR_PORT_EGRESS && BCM_SUCCESS(rv)) { 13058 rv = READ_EGR_EM_MTP_INDEXm(unit, MEM_BLOCK_ANY, offset, 13059 &egr_em_mtp_index_entry); 13060 if (BCM_SUCCESS(rv) && 13061 (0 != soc_EGR_EM_MTP_INDEXm_field32_get( 13062 unit, 13063 &egr_em_mtp_index_entry, 13064 MIRROR_ENCAP_ENABLEf))) { 13065 old_profile_index = soc_EGR_EM_MTP_INDEXm_field32_get( 13066 unit, 13067 &egr_em_mtp_index_entry, 13068 MIRROR_ENCAP_INDEXf); 13069 } 13070 } 13071 13072 if (-1 != old_profile_index) { 13073 BCM_IF_ERROR_RETURN 13074 (_bcm_egr_mirror_encap_entry_ref_get(unit, 13075 old_profile_index, 13076 &profile_ref_count)); 13077 if (profile_ref_count != 0) { 13078 rv = _bcm_egr_mirror_encap_entry_delete(unit, 13079 old_profile_index); 13080 } 13081 } 13082 } 13083 13084 for (i = 0; i < max_num_trunk_ports; i++) { 13085 sal_memset(&mirror_dest_node, 0, sizeof(bcm_mirror_destination_t)); 13086 sal_memset(&control_entry, 0, sizeof(control_entry)); 13087 sal_memset(&data_1_entry, 0, sizeof(data_1_entry)); 13088 sal_memset(&data_2_entry, 0, sizeof(data_2_entry)); 13089 13090 BCM_IF_ERROR_RETURN( 13091 _bcm_mirror_dest_mtp_get(unit, 13092 mir_dest_id, 13093 trunk_arr[i], 13094 &mirror_dest_node)); 13095 if (!((mirror_dest_node.flags & BCM_MIRROR_DEST_TUNNELS) || 13096 (mirror_dest_node.flags2 & BCM_MIRROR_DEST_FLAGS2_TUNNELS))) { 13097 continue; 13098 } 13099 13100 #if defined(BCM_TRIDENT3_SUPPORT) 13101 if (mirror_dest_node.flags2 & BCM_MIRROR_DEST_FLAGS2_TUNNEL_VXLAN) { 13102 if (soc_feature(unit, soc_feature_mirror_encap_profile)) { 13103 if (!(flags & BCM_MIRROR_PORT_INGRESS)){ 13104 rv = BCM_E_UNAVAIL; 13105 } else if (SOC_IS_TRIDENT3X(unit)) { 13106 rv = _bcm_td3_mirror_vxlan_tunnel_set(unit, index, 13107 flags, entries, is_eport); 13108 update_eme = TRUE; 13109 } 13110 } 13111 } else 13112 #endif /* BCM_TRIDENT3_SUPPORT */ 13113 if (mirror_dest_node.flags & BCM_MIRROR_DEST_TUNNEL_IP_GRE) { 13114 if (4 == mirror_dest_node.version) { 13115 if (soc_feature(unit, soc_feature_mirror_encap_profile)) { 13116 #if defined(BCM_TRIDENT3_SUPPORT) 13117 if (SOC_IS_TRIDENT3X(unit)) { 13118 rv = _bcm_td3_mirror_ipv4_gre_tunnel_set( 13119 unit, 13120 index, 13121 flags, 13122 mirror_dest_node.flags, 13123 entries, 13124 is_eport); 13125 } else 13126 #endif /* BCM_TRIDENT3_SUPPORT */ 13127 { 13128 rv = _bcm_trident_mirror_ipv4_gre_tunnel_set( 13129 unit, 13130 &mirror_dest_node, 13131 flags, 13132 entries); 13133 } 13134 update_eme = TRUE; 13135 } 13136 } else { 13137 rv = (BCM_E_UNAVAIL); 13138 } 13139 } else if (mirror_dest_node.flags & BCM_MIRROR_DEST_TUNNEL_SFLOW) { 13140 #if defined(BCM_TOMAHAWK_SUPPORT) 13141 #if defined(BCM_TRIDENT3_SUPPORT) 13142 if (SOC_IS_TRIDENT3X(unit)) { 13143 rv = _bcm_trident3_mirror_sflow_tunnel_set(unit, index, 13144 flags, mirror_dest_node.flags, entries, 13145 is_eport); 13146 } else 13147 #endif /* BCM_TRIDENT3_SUPPORT */ 13148 { 13149 rv = _bcm_tomahawk_mirror_sflow_tunnel_set(unit, 13150 &mirror_dest_node, 13151 flags, 13152 entries); 13153 } 13154 update_eme = TRUE; 13155 #else 13156 rv = BCM_E_UNAVAIL; 13157 #endif 13158 } else if (mirror_dest_node.flags & BCM_MIRROR_DEST_TUNNEL_PSAMP) { 13159 #if defined(BCM_TRIDENT3_SUPPORT) 13160 if (!(flags & BCM_MIRROR_PORT_INGRESS)){ 13161 rv = BCM_E_UNAVAIL; 13162 } else if (SOC_IS_TRIDENT3X(unit)) { 13163 rv = _bcm_td3_mirror_psamp_tunnel_set(unit, index, 13164 flags, mirror_dest_node.flags, entries, 13165 is_eport); 13166 } 13167 update_eme = TRUE; 13168 #endif /* BCM_TRIDENT3_SUPPORT */ 13169 } 13170 13171 if (BCM_SUCCESS(rv) && 13172 (mirror_dest_node.flags & BCM_MIRROR_DEST_TUNNEL_L2)) { 13173 if (soc_feature(unit, soc_feature_mirror_encap_profile)) { 13174 #if defined(BCM_TRIDENT3_SUPPORT) 13175 if (SOC_IS_TRIDENT3X(unit)) { 13176 if (update_eme == FALSE) { 13177 rv = _bcm_td3_mirror_l2_tunnel_set(unit, 13178 index, flags, entries, 0); 13179 } 13180 } else 13181 #endif /* BCM_TRIDENT3_SUPPORT */ 13182 { 13183 rv = _bcm_trident_mirror_l2_tunnel_set(unit, 13184 &mirror_dest_node, 13185 flags, 13186 entries); 13187 } 13188 update_eme = TRUE; 13189 } 13190 } 13191 if (BCM_SUCCESS(rv) && 13192 (mirror_dest_node.flags & BCM_MIRROR_DEST_TUNNEL_TRILL)) { 13193 #if defined(BCM_TRIDENT3_SUPPORT) 13194 if (SOC_IS_TRIDENT3X(unit)) { 13195 if (update_eme == FALSE) { 13196 rv = _bcm_td3_mirror_trill_tunnel_set(unit, index, flags, entries); 13197 } 13198 } else 13199 #endif /* BCM_TRIDENT3_SUPPORT */ 13200 { 13201 rv = _bcm_trident_mirror_trill_tunnel_set(unit, 13202 &mirror_dest_node, 13203 flags, 13204 entries); 13205 } 13206 update_eme = TRUE; 13207 } 13208 if (BCM_SUCCESS(rv) && 13209 (mirror_dest_node.flags & BCM_MIRROR_DEST_TUNNEL_NIV)) { 13210 #if defined(BCM_TRIDENT3_SUPPORT) 13211 if (SOC_IS_TRIDENT3X(unit)) { 13212 if (update_eme == FALSE) { 13213 rv = _bcm_td3_mirror_niv_tunnel_set(unit, index, flags, 13214 entries, is_eport); 13215 } 13216 } else 13217 #endif /* BCM_TRIDENT3_SUPPORT */ 13218 { 13219 rv = _bcm_trident_mirror_niv_tunnel_set(unit, 13220 &mirror_dest_node, 13221 flags, 13222 entries); 13223 } 13224 update_eme = TRUE; 13225 } 13226 if (BCM_SUCCESS(rv) && 13227 (mirror_dest_node.flags & BCM_MIRROR_DEST_TUNNEL_ETAG)) { 13228 if(soc_feature(unit, soc_feature_port_extension)) { 13229 #if defined(BCM_TRIDENT3_SUPPORT) 13230 if (SOC_IS_TRIDENT3X(unit)) { 13231 if (update_eme == FALSE) { 13232 rv = _bcm_td3_mirror_etag_tunnel_set(unit, index, flags, 13233 entries, is_eport); 13234 } 13235 } else 13236 #endif /* BCM_TRIDENT3_SUPPORT */ 13237 { 13238 rv = _bcm_mirror_etag_tunnel_set(unit, 13239 &mirror_dest_node, 13240 flags, 13241 entries); 13242 } 13243 update_eme = TRUE; 13244 } 13245 } 13246 if (BCM_SUCCESS(rv) && update_eme) { 13247 rv = _bcm_egr_mirror_encap_entry_add(unit, entries, prof_idx+i); 13248 } 13249 } 13250 13251 offset = index * max_num_trunk_ports; 13252 for (i = 0; i < max_num_trunk_ports; i++, offset++) { 13253 BCM_IF_ERROR_RETURN(_bcm_esw_gport_resolve( 13254 unit, trunk_arr[i], &modid, &port, &trunk, &id)); 13255 if (prof_idx[i] != -1) { 13256 if (flags & BCM_MIRROR_PORT_INGRESS) { 13257 BCM_IF_ERROR_RETURN 13258 (soc_mem_field32_modify(unit, 13259 EGR_IM_MTP_INDEXm, 13260 offset, 13261 MIRROR_ENCAP_ENABLEf, 1)); 13262 13263 BCM_IF_ERROR_RETURN 13264 (soc_mem_field32_modify(unit, 13265 EGR_IM_MTP_INDEXm, 13266 offset, 13267 MIRROR_ENCAP_INDEXf, 13268 prof_idx[i])); 13269 } 13270 /* EGR_EM_MTP_INDEX has same layout as EGR_IM_MTP_INDEX */ 13271 if (flags & BCM_MIRROR_PORT_EGRESS) { 13272 #ifdef BCM_TOMAHAWK_SUPPORT 13273 if (SOC_INFO(unit).th_tflow_enabled == 1) { 13274 /* Enable encap only for sFlow tunnel header on LB port */ 13275 if (BCM_PBMP_MEMBER(PBMP_LB(unit), port)) { 13276 BCM_IF_ERROR_RETURN 13277 (soc_mem_field32_modify(unit, 13278 EGR_IM_MTP_INDEXm, 13279 offset, 13280 MIRROR_ENCAP_ENABLEf, 13281 1)); 13282 BCM_IF_ERROR_RETURN 13283 (soc_mem_field32_modify(unit, 13284 EGR_IM_MTP_INDEXm, 13285 offset, 13286 MIRROR_ENCAP_INDEXf, 13287 prof_idx[i])); 13288 } 13289 13290 } else 13291 #endif /* BCM_TOMAHAWK_SUPPORT */ 13292 { 13293 BCM_IF_ERROR_RETURN 13294 (soc_mem_field32_modify(unit, 13295 EGR_EM_MTP_INDEXm, 13296 offset, 13297 MIRROR_ENCAP_ENABLEf, 13298 1)); 13299 BCM_IF_ERROR_RETURN 13300 (soc_mem_field32_modify(unit, 13301 EGR_EM_MTP_INDEXm, 13302 offset, 13303 MIRROR_ENCAP_INDEXf, 13304 prof_idx[i])); 13305 } 13306 } 13307 } 13308 } 13309 13310 return (BCM_E_NONE); 13311 } 13312 #endif /* BCM_TRIDENT2_SUPPORT */ 13313 13314 /* 13315 * Function: 13316 * _bcm_trx_mirror_tunnel_set 13317 * Purpose: 13318 * Initialize mirror tunnel 13319 * Parameters: 13320 * unit - (IN) BCM device number 13321 * index - (IN) Mtp index. 13322 * trunk_arr - (IN) 13323 * flags - (IN) Mirror direction flags. 13324 * Returns: 13325 * BCM_E_XXX 13326 */ 13327 STATIC int 13328 _bcm_trx_mirror_tunnel_set(int unit, int index, 13329 bcm_gport_t *trunk_arr, int flags, int 13330 is_eport) 13331 { 13332 bcm_mirror_destination_t *mirror_dest; /* Destination & Encapsulation.*/ 13333 _bcm_mtp_config_p mtp_cfg; /* MTP configuration . */ 13334 int rv = BCM_E_NONE; /* Operation return status. */ 13335 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_GREYHOUND_SUPPORT) 13336 egr_mirror_encap_control_entry_t control_entry; 13337 egr_mirror_encap_data_1_entry_t data_1_entry; 13338 egr_mirror_encap_data_2_entry_t data_2_entry; 13339 void *entries[EGR_MIRROR_ENCAP_ENTRIES_NUM]; 13340 uint32 profile_index; 13341 int update_eme = FALSE; /* EGR_MIRROR_ENCAP_* pointers */ 13342 int max_num_trunk_ports = 0; 13343 int offset = 0; 13344 13345 #if defined(BCM_TRIDENT3_SUPPORT) 13346 egr_mirror_table_entry_t table_entry; 13347 13348 if (SOC_IS_TRIDENT3X(unit)){ 13349 sal_memset(&table_entry, 0, sizeof(table_entry)); 13350 13351 entries[EGR_MIRROR_TABLE_ENTRIES] = &table_entry; 13352 } else 13353 #endif /* BCM_TRIDENT3_SUPPORT */ 13354 { 13355 sal_memset(&control_entry, 0, sizeof(control_entry)); 13356 sal_memset(&data_1_entry, 0, sizeof(data_1_entry)); 13357 sal_memset(&data_2_entry, 0, sizeof(data_2_entry)); 13358 13359 entries[EGR_MIRROR_ENCAP_ENTRIES_CONTROL] = &control_entry; 13360 entries[EGR_MIRROR_ENCAP_ENTRIES_DATA_1] = &data_1_entry; 13361 entries[EGR_MIRROR_ENCAP_ENTRIES_DATA_2] = &data_2_entry; 13362 } 13363 #endif /* TRIDENT || GREYHOUND */ 13364 /* Get mtp configuration structure by direction & index. */ 13365 mtp_cfg = MIRROR_CONFIG_MTP(unit, index, flags); 13366 13367 mirror_dest = MIRROR_DEST(unit, mtp_cfg->dest_id); 13368 13369 #ifdef BCM_TRIDENT2_SUPPORT 13370 if (mirror_dest->flags & BCM_MIRROR_DEST_ID_SHARE) { 13371 return _bcm_td2_mirror_shared_dest_tunnel_set(unit, index, 13372 trunk_arr, flags, 13373 mtp_cfg->dest_id, 0); 13374 } 13375 #endif /* BCM_TRIDENT2_SUPPORT */ 13376 13377 #if defined(BCM_TRIDENT3_SUPPORT) 13378 if (mirror_dest->flags2 & BCM_MIRROR_DEST_FLAGS2_TUNNEL_VXLAN) { 13379 if (soc_feature(unit, soc_feature_mirror_encap_profile)) { 13380 if (SOC_IS_TRIDENT3X(unit)) { 13381 rv = _bcm_td3_mirror_vxlan_tunnel_set(unit, index, 13382 flags, entries, is_eport); 13383 update_eme = TRUE; 13384 } 13385 } 13386 } else if (mirror_dest->flags2 & (BCM_MIRROR_DEST_FLAGS2_IFA | 13387 BCM_MIRROR_DEST_FLAGS2_INT_PROBE)) { 13388 if (soc_feature(unit, soc_feature_mirror_encap_profile)) { 13389 if (!(flags & BCM_MIRROR_PORT_INGRESS)){ 13390 rv = BCM_E_UNAVAIL; 13391 } else if (SOC_IS_TRIDENT3X(unit)) { 13392 rv = _bcm_td3_mirror_int_probe_set(unit, index, 13393 flags, entries, is_eport); 13394 update_eme = TRUE; 13395 } 13396 } 13397 } else 13398 #endif /* BCM_TRIDENT3_SUPPORT */ 13399 if (mirror_dest->flags & BCM_MIRROR_DEST_TUNNEL_IP_GRE) { 13400 if (4 == mirror_dest->version) { 13401 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_GREYHOUND_SUPPORT) 13402 if (soc_feature(unit, soc_feature_mirror_encap_profile)) { 13403 #if defined(BCM_TRIDENT3_SUPPORT) 13404 if (SOC_IS_TRIDENT3X(unit)) { 13405 rv = _bcm_td3_mirror_ipv4_gre_tunnel_set(unit, index, 13406 flags, mirror_dest->flags, 13407 entries,is_eport); 13408 } else 13409 #endif /* BCM_TRIDENT3_SUPPORT */ 13410 { 13411 rv = _bcm_trident_mirror_ipv4_gre_tunnel_set(unit, mirror_dest, 13412 flags, entries); 13413 } 13414 update_eme = TRUE; 13415 } else 13416 #endif /* TRIDENT || GREYHOUND */ 13417 { 13418 rv = _bcm_trx_mirror_ipv4_gre_tunnel_set(unit, index, flags); 13419 } 13420 } else { 13421 #ifdef BCM_TOMAHAWK3_SUPPORT 13422 if (SOC_IS_TOMAHAWK3(unit)) { 13423 if (6 == mirror_dest->version) { 13424 rv = _bcm_tomahawk3_mirror_ipv6_gre_tunnel_set(unit, 13425 mirror_dest, flags, entries); 13426 13427 update_eme = TRUE; 13428 13429 } else { 13430 rv = BCM_E_UNAVAIL; 13431 } 13432 } else 13433 #endif /* BCM_TOMAHAWK3_SUPPORT */ 13434 #ifdef BCM_TRIDENT3_SUPPORT 13435 if (SOC_IS_TRIDENT3X(unit)) { 13436 if (6 == mirror_dest->version) { 13437 rv = _bcm_td3_mirror_ipv6_gre_tunnel_set(unit, index, 13438 flags, mirror_dest->flags, 13439 entries,is_eport); 13440 update_eme = TRUE; 13441 13442 } else { 13443 rv = BCM_E_UNAVAIL; 13444 } 13445 } else 13446 #endif /* BCM_TRIDENT3_SUPPORT */ 13447 rv = (BCM_E_UNAVAIL); 13448 } 13449 } else if (mirror_dest->flags & BCM_MIRROR_DEST_TUNNEL_PSAMP) { 13450 #if defined(BCM_TRIDENT3_SUPPORT) 13451 if (!(flags & BCM_MIRROR_PORT_INGRESS)){ 13452 rv = BCM_E_UNAVAIL; 13453 } else if (SOC_IS_TRIDENT3X(unit)) { 13454 rv = _bcm_td3_mirror_psamp_tunnel_set(unit, index, 13455 flags, mirror_dest->flags, entries, 13456 is_eport); 13457 } 13458 update_eme = TRUE; 13459 #endif /* BCM_TRIDENT3_SUPPORT */ 13460 #if defined(BCM_TOMAHAWK3_SUPPORT) 13461 if (SOC_IS_TOMAHAWK3(unit)) { 13462 if (mirror_dest->version == 4) { 13463 rv = _bcm_tomahawk3_mirror_sflow_psamp_v4_tunnel_set(unit, 13464 mirror_dest, flags, entries); 13465 } else { 13466 rv = _bcm_tomahawk3_mirror_sflow_psamp_v6_tunnel_set(unit, 13467 mirror_dest, flags, entries); 13468 } 13469 } 13470 update_eme = TRUE; 13471 #endif /* BCM_TOMAHAWK3_SUPPORT */ 13472 } else if (mirror_dest->flags & BCM_MIRROR_DEST_TUNNEL_SFLOW) { 13473 #if defined(BCM_TOMAHAWK_SUPPORT) 13474 #if defined(BCM_TRIDENT3_SUPPORT) 13475 if (SOC_IS_TRIDENT3X(unit)) { 13476 rv = _bcm_trident3_mirror_sflow_tunnel_set(unit, index, 13477 flags, mirror_dest->flags, entries, 13478 is_eport); 13479 } else 13480 #endif /* BCM_TRIDENT3_SUPPORT */ 13481 { 13482 #ifdef BCM_TOMAHAWK3_SUPPORT 13483 if (SOC_IS_TOMAHAWK3(unit)) { 13484 if (mirror_dest->version == 4) { 13485 rv = _bcm_tomahawk3_mirror_sflow_psamp_v4_tunnel_set(unit, 13486 mirror_dest, flags, entries); 13487 } else { 13488 rv = _bcm_tomahawk3_mirror_sflow_psamp_v6_tunnel_set(unit, 13489 mirror_dest, flags, entries); 13490 } 13491 } else 13492 #endif /* BCM_TOMAHAWK3_SUPPORT */ 13493 { 13494 rv = _bcm_tomahawk_mirror_sflow_tunnel_set(unit, mirror_dest, 13495 flags, entries); 13496 } 13497 } 13498 update_eme = TRUE; 13499 #else 13500 rv = BCM_E_UNAVAIL; 13501 #endif 13502 } 13503 13504 13505 if (BCM_SUCCESS(rv) && 13506 (0 != (mirror_dest->flags & BCM_MIRROR_DEST_TUNNEL_L2))) { 13507 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_GREYHOUND_SUPPORT) 13508 if (soc_feature(unit, soc_feature_mirror_encap_profile)) { 13509 #if defined(BCM_TRIDENT3_SUPPORT) 13510 if (SOC_IS_TRIDENT3X(unit)) { 13511 if (update_eme == FALSE) { 13512 rv = _bcm_td3_mirror_l2_tunnel_set(unit, 13513 index, flags, entries, is_eport); 13514 } 13515 } else 13516 #endif /* BCM_TRIDENT3_SUPPORT */ 13517 { 13518 rv = _bcm_trident_mirror_l2_tunnel_set(unit, mirror_dest, 13519 flags, entries); 13520 } 13521 update_eme = TRUE; 13522 } else 13523 #endif /* TRIDENT || GREYHOUND */ 13524 { 13525 rv = _bcm_trx_mirror_l2_tunnel_set(unit, index, trunk_arr, flags); 13526 } 13527 } 13528 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_GREYHOUND_SUPPORT) 13529 /* 13530 * Note: Trill and NIV features are checked when the mirror 13531 * destination is created. Thus, the flags will not be 13532 * set on a device which doesn't support the feature. 13533 */ 13534 if (BCM_SUCCESS(rv) && 13535 (0 != (mirror_dest->flags & BCM_MIRROR_DEST_TUNNEL_TRILL))) { 13536 #if defined(BCM_TRIDENT3_SUPPORT) 13537 if (SOC_IS_TRIDENT3X(unit)) { 13538 if (update_eme == FALSE) { 13539 rv = _bcm_td3_mirror_trill_tunnel_set(unit, index, flags, entries); 13540 } 13541 } else 13542 #endif /* BCM_TRIDENT3_SUPPORT */ 13543 { 13544 rv = _bcm_trident_mirror_trill_tunnel_set(unit, mirror_dest, 13545 flags, entries); 13546 } 13547 update_eme = TRUE; 13548 } 13549 if (BCM_SUCCESS(rv) && 13550 (0 != (mirror_dest->flags & BCM_MIRROR_DEST_TUNNEL_NIV))) { 13551 #if defined(BCM_TRIDENT3_SUPPORT) 13552 if (SOC_IS_TRIDENT3X(unit)) { 13553 if (update_eme == FALSE) { 13554 rv = _bcm_td3_mirror_niv_tunnel_set(unit, index, flags, entries, 13555 is_eport); 13556 } 13557 } else 13558 #endif /* BCM_TRIDENT3_SUPPORT */ 13559 { 13560 rv = _bcm_trident_mirror_niv_tunnel_set(unit, mirror_dest, 13561 flags, entries); 13562 } 13563 update_eme = TRUE; 13564 } 13565 13566 if (BCM_SUCCESS(rv) && 13567 (0 != (mirror_dest->flags & BCM_MIRROR_DEST_TUNNEL_ETAG))) { 13568 if(soc_feature(unit, soc_feature_port_extension)) { 13569 #if defined(BCM_TRIDENT3_SUPPORT) 13570 if (SOC_IS_TRIDENT3X(unit)) { 13571 if (update_eme == FALSE) { 13572 rv = _bcm_td3_mirror_etag_tunnel_set(unit, index, flags, entries, 13573 is_eport); 13574 } 13575 } else 13576 #endif /* BCM_TRIDENT3_SUPPORT */ 13577 { 13578 rv = _bcm_mirror_etag_tunnel_set(unit, mirror_dest, 13579 flags, entries); 13580 } 13581 update_eme = TRUE; 13582 } 13583 } 13584 13585 /* Remove the previous profile index if any */ 13586 if (BCM_SUCCESS(rv) && update_eme && 13587 (mirror_dest->flags & BCM_MIRROR_DEST_REPLACE)) { 13588 uint32 old_profile_index = -1; 13589 int profile_ref_count = 0; 13590 egr_im_mtp_index_entry_t egr_im_mtp_index_entry; 13591 egr_em_mtp_index_entry_t egr_em_mtp_index_entry; 13592 #if defined(BCM_TRIDENT_SUPPORT) 13593 egr_ep_redirect_em_mtp_index_entry_t egr_em_redirect_mtp_index_entry; 13594 #endif /* TRIDENT */ 13595 #ifdef BCM_METROLITE_SUPPORT 13596 if (soc_feature(unit, soc_feature_mirror_four_port_trunk)) { 13597 max_num_trunk_ports = 4; 13598 } else 13599 #endif 13600 max_num_trunk_ports = BCM_SWITCH_TRUNK_MAX_PORTCNT; 13601 13602 #ifdef BCM_TOMAHAWK3_SUPPORT 13603 if (SOC_IS_TOMAHAWK3(unit)) { 13604 max_num_trunk_ports = 1; 13605 /* We use offset = index below since 13606 * EGR_IM/EM_MTP_INDEX are * 4 entries deep 13607 */ 13608 } 13609 #endif /* BCM_TOMAHAWK3_SUPPORT */ 13610 13611 offset = index * max_num_trunk_ports; 13612 13613 if (flags & BCM_MIRROR_PORT_INGRESS) { 13614 if (mirror_dest->flags2 & BCM_MIRROR_DEST_FLAGS2_IFA) { 13615 rv = READ_EGR_EM_MTP_INDEXm(unit, MEM_BLOCK_ANY, offset, 13616 &egr_im_mtp_index_entry); 13617 } else { 13618 rv = READ_EGR_IM_MTP_INDEXm(unit, MEM_BLOCK_ANY, offset, 13619 &egr_im_mtp_index_entry); 13620 } 13621 13622 if (BCM_SUCCESS(rv) && 13623 (0 != soc_EGR_IM_MTP_INDEXm_field32_get(unit, 13624 &egr_im_mtp_index_entry, 13625 MIRROR_ENCAP_ENABLEf))) { 13626 old_profile_index = 13627 soc_EGR_IM_MTP_INDEXm_field32_get(unit, 13628 &egr_im_mtp_index_entry, 13629 MIRROR_ENCAP_INDEXf); 13630 13631 } 13632 } 13633 13634 if (flags & BCM_MIRROR_PORT_EGRESS && BCM_SUCCESS(rv)) { 13635 rv = READ_EGR_EM_MTP_INDEXm(unit, MEM_BLOCK_ANY, offset, 13636 &egr_em_mtp_index_entry); 13637 if (BCM_SUCCESS(rv) && 13638 (0 != soc_EGR_EM_MTP_INDEXm_field32_get(unit, 13639 &egr_em_mtp_index_entry, 13640 MIRROR_ENCAP_ENABLEf))) { 13641 old_profile_index = 13642 soc_EGR_EM_MTP_INDEXm_field32_get(unit, 13643 &egr_em_mtp_index_entry, 13644 MIRROR_ENCAP_INDEXf); 13645 13646 } 13647 } 13648 13649 #if defined(BCM_TRIDENT_SUPPORT) 13650 if (flags & BCM_MIRROR_PORT_EGRESS_TRUE && BCM_SUCCESS(rv)) { 13651 rv = READ_EGR_EP_REDIRECT_EM_MTP_INDEXm(unit, MEM_BLOCK_ANY, offset, 13652 &egr_em_redirect_mtp_index_entry); 13653 if (BCM_SUCCESS(rv) && 13654 (0 != soc_EGR_EP_REDIRECT_EM_MTP_INDEXm_field32_get(unit, 13655 &egr_em_redirect_mtp_index_entry, 13656 MIRROR_ENCAP_ENABLEf))) { 13657 old_profile_index = 13658 soc_EGR_EP_REDIRECT_EM_MTP_INDEXm_field32_get(unit, 13659 &egr_em_redirect_mtp_index_entry, 13660 MIRROR_ENCAP_INDEXf); 13661 13662 } 13663 } 13664 #endif /* TRIDENT */ 13665 13666 if (-1 != old_profile_index) { 13667 BCM_IF_ERROR_RETURN 13668 (_bcm_egr_mirror_encap_entry_ref_get(unit, 13669 old_profile_index, 13670 &profile_ref_count)); 13671 if (profile_ref_count != 0) { 13672 #if defined(BCM_TRIDENT3_SUPPORT) 13673 if (SOC_IS_TRIDENT3X(unit)) { 13674 rv = _bcm_td3_egr_mirror_table_entry_delete(unit, 13675 old_profile_index); 13676 } else 13677 #endif /* BCM_TRIDENT3_SUPPORT */ 13678 { 13679 rv = _bcm_egr_mirror_encap_entry_delete(unit, 13680 old_profile_index); 13681 } 13682 } 13683 } 13684 } 13685 13686 if (BCM_SUCCESS(rv) && update_eme) { 13687 #if defined(BCM_TRIDENT3_SUPPORT) 13688 if (SOC_IS_TRIDENT3X(unit)) { 13689 rv = _bcm_td3_egr_mirror_table_entry_add(unit, entries, &profile_index); 13690 } else 13691 #endif 13692 { 13693 rv = _bcm_egr_mirror_encap_entry_add(unit, entries, &profile_index); 13694 } 13695 } 13696 13697 #if defined(BCM_TRIDENT_SUPPORT) 13698 if (soc_feature(unit, soc_feature_mirror_control_mem)) { 13699 if (BCM_SUCCESS(rv) && update_eme) { 13700 /* Supply the correct profile index to the selected MTPs */ 13701 rv = _bcm_egr_mirror_encap_entry_mtp_enable(unit, index, 13702 trunk_arr, flags); 13703 } 13704 } 13705 #endif 13706 13707 if (BCM_SUCCESS(rv) && update_eme) { 13708 /* Supply the correct profile index to the selected MTPs */ 13709 #ifdef BCM_TRIDENT3_SUPPORT 13710 if (SOC_IS_TRIDENT3X(unit)) { 13711 rv = _bcm_td3_egr_mirror_encap_entry_mtp_update(unit, index, 13712 profile_index, flags, trunk_arr, is_eport); 13713 } else 13714 #endif 13715 { 13716 rv = _bcm_egr_mirror_encap_entry_mtp_update(unit, index, 13717 profile_index, flags); 13718 } 13719 #if defined(BCM_TOMAHAWK3_SUPPORT) 13720 if (SOC_IS_TOMAHAWK3(unit)) { 13721 /* If sequence number is specified, use the value from 13722 * mirror destination structure 13723 */ 13724 if ((mirror_dest->flags & BCM_MIRROR_DEST_TUNNEL_PSAMP) || 13725 ((mirror_dest->flags & BCM_MIRROR_DEST_TUNNEL_SFLOW) && 13726 (mirror_dest->flags & BCM_MIRROR_DEST_TUNNEL_WITH_SEQ))) { 13727 rv = _bcm_tomahawk3_mirror_sflow_psamp_seq_num_set(unit, index, 13728 profile_index, flags, mirror_dest->initial_seq_number); 13729 } 13730 13731 /* Program user meta data information for psamp fmt2, or 13732 * sflow with seq number hdr 13733 */ 13734 if (((mirror_dest->flags & BCM_MIRROR_DEST_TUNNEL_PSAMP) && 13735 (mirror_dest->flags2 & BCM_MIRROR_DEST_FLAGS2_PSAMP_FORMAT_2)) 13736 || 13737 ((mirror_dest->flags & BCM_MIRROR_DEST_TUNNEL_SFLOW) && 13738 (mirror_dest->flags & BCM_MIRROR_DEST_TUNNEL_WITH_SEQ))) { 13739 rv = _bcm_tomahawk3_mirror_sflow_psamp_user_meta_data_set(unit, 13740 index, profile_index, flags); 13741 } 13742 } 13743 13744 #endif /* BCM_TOMAHAWK3_SUPPORT */ 13745 } 13746 #endif /* TRIDENT || GREYHOUND */ 13747 13748 return (rv); 13749 } 13750 #endif /* BCM_TRX_SUPPORT */ 13751 13752 13753 #if defined(BCM_TRIDENT_SUPPORT) 13754 /* 13755 * Function: 13756 * _bcm_trident_mtp_init 13757 * Purpose: 13758 * Initialize mirror target port for TRIDENT devices. 13759 * Parameters: 13760 * unit - (IN)BCM device number 13761 * index - (IN)Mtp index. 13762 * trunk_arr - (IN)Trunk members array. 13763 * flags - (IN)Filled entry flags(BCM_MIRROR_PORT_INGRESS/EGRESS 13764 * or both. In case both flags are specied 13765 * ingress & egress configuration is assumed to be 13766 * idential. 13767 * Returns: 13768 * BCM_E_XXX 13769 */ 13770 STATIC int 13771 _bcm_trident_mtp_init(int unit, int index, bcm_gport_t *trunk_arr, int flags) 13772 { 13773 bcm_gport_t mirror_dest; 13774 bcm_port_t port_out; 13775 bcm_module_t mod_out; 13776 _bcm_mtp_config_p mtp_cfg; 13777 int offset; 13778 int idx, id, isLocal; 13779 bcm_trunk_t trunk = BCM_TRUNK_INVALID; 13780 bcm_module_t modid = 0; 13781 bcm_port_t port = -1; 13782 im_mtp_index_entry_t mtp_entry, *mtp; 13783 uint32 egr_mtp; 13784 int member_count = 0, rtag, encap_index; 13785 uint32 replace_flag = 0; 13786 egr_im_mtp_index_entry_t egr_mtp_index_entry; 13787 int max_num_trunk_ports = 0; 13788 #ifdef BCM_TRIDENT2_SUPPORT 13789 int mir_dest_flag = 0; 13790 #endif /* BCM_TRIDENT2_SUPPORT */ 13791 int is_eport = FALSE; 13792 #ifdef BCM_TRIDENT3_SUPPORT 13793 int istrunk_local = FALSE; 13794 int istrunk_remote = FALSE; 13795 #endif 13796 int is_local_modid = 0; 13797 13798 /* HW does not store the trunk ID here, so during Warm Boot 13799 * we must take a mod,port and reverse map it to the trunk 13800 * This will work because we will have the T bit to indicate 13801 * a trunk, and the trunk module recovery takes place before 13802 * mirror, so the reverse mapping is available in SW. */ 13803 static const soc_field_t port_field[] = { 13804 PORT_NUM_0f, PORT_NUM_1f, PORT_NUM_2f, PORT_NUM_3f, 13805 PORT_NUM_4f, PORT_NUM_5f, PORT_NUM_6f, PORT_NUM_7f}; 13806 static const soc_field_t module_field[] = { 13807 MODULE_ID_0f, MODULE_ID_1f, MODULE_ID_2f, MODULE_ID_3f, 13808 MODULE_ID_4f, MODULE_ID_5f, MODULE_ID_6f, MODULE_ID_7f}; 13809 13810 mtp = &mtp_entry; 13811 13812 /* Input parameters check */ 13813 if (NULL == trunk_arr) { 13814 return (BCM_E_PARAM); 13815 } 13816 13817 13818 /* Get mtp configuration structure by direction & index. */ 13819 mtp_cfg = MIRROR_CONFIG_MTP(unit, index, flags); 13820 sal_memset(mtp, 0, sizeof(*mtp)); 13821 13822 /* Parse destination trunk / port & module. */ 13823 mirror_dest = MIRROR_DEST_GPORT(unit, mtp_cfg->dest_id); 13824 #ifdef BCM_TRIDENT2_SUPPORT 13825 mir_dest_flag = (MIRROR_DEST(unit, mtp_cfg->dest_id))->flags; 13826 #endif /* BCM_TRIDENT2_SUPPORT */ 13827 13828 #ifdef BCM_TOMAHAWK3_SUPPORT 13829 if (SOC_IS_TOMAHAWK3(unit)) { 13830 /* Mirroring on trunk not supported */ 13831 if (BCM_GPORT_IS_TRUNK(mirror_dest)) { 13832 return (BCM_E_UNAVAIL); 13833 } 13834 13835 /* Check added here since h/w programming happens in this function */ 13836 if (flags & BCM_MIRROR_PORT_EGRESS) { 13837 /* Payload zeroing is supported only on ingress */ 13838 if ((MIRROR_DEST(unit, mtp_cfg->dest_id))->truncate == 13839 BCM_MIRROR_PAYLOAD_TRUNCATE_AND_ZERO) { 13840 return BCM_E_CONFIG; 13841 } 13842 } 13843 } 13844 #endif /* BCM_TOMAHAWK3_SUPPORT */ 13845 13846 if (BCM_GPORT_IS_TRUNK(mirror_dest)) { 13847 trunk = BCM_GPORT_TRUNK_GET(mirror_dest); 13848 BCM_IF_ERROR_RETURN 13849 (_bcm_trunk_id_validate(unit, trunk)); 13850 BCM_IF_ERROR_RETURN 13851 (_bcm_esw_trunk_active_member_get(unit, trunk, NULL, 0, NULL, 13852 &member_count)); 13853 BCM_IF_ERROR_RETURN 13854 (_bcm_esw_trunk_rtag_get(unit, trunk, &rtag)); 13855 13856 if (member_count > BCM_TD_MIRROR_TRUNK_MAX_PORTCNT) { 13857 member_count = BCM_TD_MIRROR_TRUNK_MAX_PORTCNT; 13858 } 13859 soc_IM_MTP_INDEXm_field32_set(unit, mtp, Tf, 1); 13860 13861 if (0 == member_count) { 13862 port = SOC_PORT_ADDR_MAX(unit); 13863 while (0 <= port) { 13864 if (!SOC_PORT_VALID(unit, port)) { 13865 /* Found invalid port, use as black hole */ 13866 break; 13867 } 13868 port--; 13869 } 13870 if (port < 0) { 13871 /* Couldn't find an usused port, give up on empty trunk */ 13872 return BCM_E_PORT; 13873 } 13874 13875 /* Get local modid. */ 13876 BCM_IF_ERROR_RETURN(_bcm_esw_local_modid_get(unit, &modid)); 13877 13878 soc_IM_MTP_INDEXm_field32_set(unit, mtp, COUNTf, 0); 13879 soc_IM_MTP_INDEXm_field32_set(unit, mtp, RTAGf, 0); 13880 13881 soc_IM_MTP_INDEXm_field32_set(unit, mtp, 13882 module_field[0], modid); 13883 soc_IM_MTP_INDEXm_field32_set(unit, mtp, 13884 port_field[0], port); 13885 13886 /* Cache trunk ID for Warm Boot */ 13887 #ifdef BCM_METROLITE_SUPPORT 13888 if (SOC_IS_METROLITE(unit)) { 13889 soc_IM_MTP_INDEXm_field32_set(unit, mtp, 13890 port_field[3], trunk); 13891 } else 13892 #endif 13893 { 13894 soc_IM_MTP_INDEXm_field32_set(unit, mtp, 13895 port_field[7], trunk); 13896 } 13897 } else { 13898 /* If RTAG isn't RTAG7, then we must fill out all of the 13899 * trunk destination modport slots. */ 13900 soc_IM_MTP_INDEXm_field32_set(unit, mtp, COUNTf, 13901 (member_count - 1)); 13902 soc_IM_MTP_INDEXm_field32_set(unit, mtp, RTAGf, rtag); 13903 #ifdef BCM_METROLITE_SUPPORT 13904 if (soc_feature(unit, soc_feature_mirror_four_port_trunk)) { 13905 max_num_trunk_ports = 4; 13906 } else 13907 #endif 13908 max_num_trunk_ports = BCM_TD_MIRROR_TRUNK_MAX_PORTCNT; 13909 for (idx = 0; idx < max_num_trunk_ports; idx++) { 13910 /* trunk variable will not be used from this point, 13911 * OK to update */ 13912 if ((7 == rtag) && (idx == member_count)) { 13913 break; 13914 } 13915 BCM_IF_ERROR_RETURN 13916 (_bcm_esw_gport_resolve(unit, 13917 trunk_arr[idx % member_count], 13918 &modid, &port, &trunk, &id)); 13919 #if defined(BCM_HGPROXY_COE_SUPPORT) 13920 if (soc_feature(unit, soc_feature_hgproxy_subtag_coe) && 13921 BCM_GPORT_IS_SET(trunk_arr[idx % member_count]) && 13922 _BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT (unit, 13923 trunk_arr[idx % member_count])) { 13924 } else 13925 #endif 13926 #if defined(BCM_KATANA2_SUPPORT) 13927 if (BCM_GPORT_IS_SET(trunk_arr[idx % member_count]) && 13928 _BCM_KT2_GPORT_IS_LINKPHY_OR_SUBTAG_SUBPORT_GPORT (unit, 13929 trunk_arr[idx % member_count])) { 13930 } else 13931 #endif 13932 { 13933 if ((-1 != id) || (BCM_TRUNK_INVALID != trunk)) { 13934 return BCM_E_PARAM; 13935 } 13936 } 13937 13938 soc_IM_MTP_INDEXm_field32_set(unit, mtp, 13939 module_field[idx], modid); 13940 soc_IM_MTP_INDEXm_field32_set(unit, mtp, 13941 port_field[idx], port); 13942 13943 } 13944 } 13945 13946 } 13947 #ifdef BCM_TRIDENT2_SUPPORT 13948 else if (mir_dest_flag & BCM_MIRROR_DEST_ID_SHARE) { 13949 bcm_gport_t mir_dest_gport_array[BCM_SWITCH_TRUNK_MAX_PORTCNT] = {0}; 13950 int mir_dest_gport_count = 0; 13951 13952 #ifdef BCM_TOMAHAWK3_SUPPORT 13953 if (SOC_IS_TOMAHAWK3(unit)) { 13954 /* No programming required. All fields, except PORT_NUM, 13955 * removed from IM_MTP_INDEX 13956 */ 13957 } else 13958 #endif /* BCM_TOMAHAWK3_SUPPORT */ 13959 { 13960 BCM_IF_ERROR_RETURN( 13961 _bcm_mirror_dest_mtp_gport_get(unit, 13962 mtp_cfg->dest_id, 13963 mir_dest_gport_array, 13964 &mir_dest_gport_count)); 13965 if (mir_dest_gport_count <= 0) { 13966 return (BCM_E_INIT); 13967 } 13968 rtag = (MIRROR_DEST(unit, mtp_cfg->dest_id))->rtag; 13969 soc_IM_MTP_INDEXm_field32_set(unit, mtp, Tf, 1); 13970 soc_IM_MTP_INDEXm_field32_set(unit, mtp, COUNTf, 13971 (mir_dest_gport_count - 1)); 13972 soc_IM_MTP_INDEXm_field32_set(unit, mtp, RTAGf, rtag); 13973 13974 max_num_trunk_ports = BCM_TD_MIRROR_TRUNK_MAX_PORTCNT; 13975 for (idx = 0; idx < max_num_trunk_ports; idx++) { 13976 BCM_IF_ERROR_RETURN 13977 (_bcm_esw_gport_resolve(unit, 13978 trunk_arr[idx], 13979 &modid, &port, &trunk, &id)); 13980 13981 BCM_IF_ERROR_RETURN 13982 (_bcm_esw_modid_is_local(unit, modid, &isLocal)); 13983 if (TRUE == isLocal) { 13984 BCM_IF_ERROR_RETURN( 13985 _bcm_esw_stk_modmap_map(unit,BCM_STK_MODMAP_SET, modid, 13986 port, &modid, &port)); 13987 } 13988 13989 soc_IM_MTP_INDEXm_field32_set(unit, mtp, module_field[idx], 13990 modid); 13991 soc_IM_MTP_INDEXm_field32_set(unit, mtp, port_field[idx], port); 13992 } 13993 } 13994 } 13995 #endif /* BCM_TRIDENT2_SUPPORT */ 13996 else { 13997 BCM_IF_ERROR_RETURN 13998 (_bcm_esw_gport_resolve(unit, mirror_dest, 13999 &modid, &port, &trunk, &id)); 14000 BCM_IF_ERROR_RETURN 14001 (_bcm_esw_modid_is_local(unit, modid, &isLocal)); 14002 if (TRUE == isLocal) { 14003 BCM_IF_ERROR_RETURN( 14004 _bcm_esw_stk_modmap_map(unit,BCM_STK_MODMAP_SET, modid, port, 14005 &modid, &port)); 14006 } 14007 14008 #ifdef BCM_TOMAHAWK3_SUPPORT 14009 if (SOC_IS_TOMAHAWK3(unit)) { 14010 soc_IM_MTP_INDEXm_field32_set(unit, mtp, PORT_NUMf, port); 14011 } else 14012 #endif /* BCM_TOMAHAWK3_SUPPORT */ 14013 { 14014 soc_IM_MTP_INDEXm_field32_set(unit, mtp, Tf, 0); 14015 soc_IM_MTP_INDEXm_field32_set(unit, mtp, COUNTf, 0); 14016 soc_IM_MTP_INDEXm_field32_set(unit, mtp, MODULE_IDf, modid); 14017 soc_IM_MTP_INDEXm_field32_set(unit, mtp, PORT_NUMf, port); 14018 } 14019 14020 #if defined(BCM_TRIDENT2PLUS_SUPPORT) || defined(BCM_TRIDENT3_SUPPORT) 14021 if (soc_feature(unit, soc_feature_hgproxy_subtag_coe) && 14022 _bcm_xgs5_subport_coe_mod_port_local(unit, modid, port)) { 14023 int local_port = 0; 14024 int mod_port_index = 0; 14025 modport_map_subport_mirror_entry_t subport_m_entry; 14026 soc_mem_t mems[] = {MODPORT_MAP_SUBPORT_M0m, MODPORT_MAP_SUBPORT_M1m, 14027 MODPORT_MAP_SUBPORT_M2m, MODPORT_MAP_SUBPORT_M3m}; 14028 14029 BCM_IF_ERROR_RETURN( 14030 _bcmi_coe_subport_mod_port_physical_port_get( 14031 unit, modid, port, &local_port)); 14032 14033 BCM_IF_ERROR_RETURN( 14034 _bcm_esw_src_mod_port_table_index_get(unit, modid, port, &mod_port_index)); 14035 14036 sal_memset(&subport_m_entry, 0, sizeof(subport_m_entry)); 14037 soc_mem_field32_set(unit, mems[index], &subport_m_entry, ENABLEf, 1); 14038 soc_mem_field32_set(unit, mems[index], &subport_m_entry, DESTf, local_port); 14039 14040 SOC_IF_ERROR_RETURN( 14041 soc_mem_write(unit, mems[index], MEM_BLOCK_ALL, 14042 mod_port_index, &subport_m_entry)); 14043 } 14044 #endif /* BCM_TRIDENT2PLUS_SUPPORT || BCM_TRIDENT3_SUPPORT */ 14045 } 14046 14047 /* HW write. based on mirrored traffic direction. */ 14048 if (flags & BCM_MIRROR_PORT_INGRESS) { 14049 BCM_IF_ERROR_RETURN 14050 (soc_mem_write(unit, IM_MTP_INDEXm, MEM_BLOCK_ALL, index, mtp)); 14051 } 14052 14053 /* EM_MTP_INDEX has same layout as IM_MTP_INDEX */ 14054 if (flags & BCM_MIRROR_PORT_EGRESS) { 14055 BCM_IF_ERROR_RETURN 14056 (soc_mem_write(unit, EM_MTP_INDEXm, MEM_BLOCK_ALL, index, mtp)); 14057 } 14058 14059 #ifdef BCM_TRIUMPH3_SUPPORT 14060 /* EP_REDIRECT_EM_MTP_INDEX has same layout as IM_MTP_INDEX */ 14061 if (flags & BCM_MIRROR_PORT_EGRESS_TRUE) { 14062 ep_redirect_em_mtp_index_entry_t ep_mtp_entry; 14063 14064 #ifdef BCM_TOMAHAWK3_SUPPORT 14065 /* True egress mirroring not supported */ 14066 if (SOC_IS_TOMAHAWK3(unit)) { 14067 return BCM_E_UNAVAIL; 14068 } 14069 #endif /* BCM_TOMAHAWK3_SUPPORT */ 14070 sal_memset(&ep_mtp_entry, 0, sizeof(ep_mtp_entry)); 14071 14072 soc_EP_REDIRECT_EM_MTP_INDEXm_field32_set(unit, &ep_mtp_entry, 14073 Tf, soc_IM_MTP_INDEXm_field32_get(unit, mtp, Tf)); 14074 soc_EP_REDIRECT_EM_MTP_INDEXm_field32_set(unit, &ep_mtp_entry, 14075 COUNTf,soc_IM_MTP_INDEXm_field32_get(unit, mtp,COUNTf)); 14076 soc_EP_REDIRECT_EM_MTP_INDEXm_field32_set(unit, &ep_mtp_entry, 14077 RTAGf,soc_IM_MTP_INDEXm_field32_get(unit, mtp,RTAGf)); 14078 soc_EP_REDIRECT_EM_MTP_INDEXm_field32_set(unit, &ep_mtp_entry, 14079 MODULE_IDf, 14080 soc_IM_MTP_INDEXm_field32_get(unit, mtp, MODULE_IDf)); 14081 soc_EP_REDIRECT_EM_MTP_INDEXm_field32_set(unit, &ep_mtp_entry, 14082 PORT_NUMf, 14083 soc_IM_MTP_INDEXm_field32_get(unit, mtp, PORT_NUMf)); 14084 14085 for (idx = 0; idx < max_num_trunk_ports; idx++) { 14086 soc_EP_REDIRECT_EM_MTP_INDEXm_field32_set(unit, &ep_mtp_entry, 14087 module_field[idx], 14088 soc_IM_MTP_INDEXm_field32_get(unit, mtp, module_field[idx])); 14089 soc_EP_REDIRECT_EM_MTP_INDEXm_field32_set(unit, &ep_mtp_entry, 14090 port_field[idx], 14091 soc_IM_MTP_INDEXm_field32_get(unit, mtp, port_field[idx])); 14092 } 14093 BCM_IF_ERROR_RETURN 14094 (soc_mem_write(unit, EP_REDIRECT_EM_MTP_INDEXm, 14095 MEM_BLOCK_ALL, index, &ep_mtp_entry)); 14096 } 14097 #endif /* BCM_TRIUMPH2_SUPPORT */ 14098 14099 #ifdef BCM_TRIDENT2_SUPPORT 14100 if (mir_dest_flag & BCM_MIRROR_DEST_ID_SHARE) { 14101 bcm_mirror_destination_t mirror_dest; 14102 soc_mem_t mem; 14103 14104 #ifdef BCM_TOMAHAWK3_SUPPORT 14105 if (SOC_IS_TOMAHAWK3(unit)) { 14106 /* No programming required, since mirror on trunks is not supported, 14107 * and all fields below (priority, dst port, etc. have been 14108 * removed) 14109 */ 14110 } else 14111 #endif /* BCM_TOMAHAWK3_SUPPORT */ 14112 { 14113 max_num_trunk_ports = BCM_SWITCH_TRUNK_MAX_PORTCNT; 14114 offset = index * max_num_trunk_ports; 14115 14116 for (idx = 0; idx < max_num_trunk_ports; idx++, offset++) { 14117 egr_mtp = 0; 14118 sal_memset(&mirror_dest, 0x0, sizeof(bcm_mirror_destination_t)); 14119 BCM_IF_ERROR_RETURN( 14120 _bcm_mirror_dest_mtp_get(unit, 14121 mtp_cfg->dest_id, 14122 trunk_arr[idx], 14123 &mirror_dest)); 14124 14125 if (flags & BCM_MIRROR_PORT_INGRESS) { 14126 mem = EGR_IM_MTP_INDEXm; 14127 } else if (flags & BCM_MIRROR_PORT_EGRESS) { 14128 mem = EGR_EM_MTP_INDEXm; 14129 } else { 14130 return BCM_E_CONFIG; 14131 } 14132 14133 BCM_IF_ERROR_RETURN( 14134 soc_mem_read(unit, mem, MEM_BLOCK_ANY, offset, &egr_mtp)); 14135 BCM_IF_ERROR_RETURN(_bcm_esw_gport_resolve(unit, 14136 trunk_arr[idx], 14137 &modid, 14138 &port, 14139 &trunk, 14140 &id)); 14141 BCM_IF_ERROR_RETURN( 14142 _bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_SET, modid, port, 14143 &mod_out, &port_out)); 14144 BCM_IF_ERROR_RETURN 14145 (_bcm_esw_modid_is_local(unit, mod_out, &is_local_modid)); 14146 if (is_local_modid) { 14147 is_eport = IS_E_PORT(unit, port)? TRUE: FALSE; 14148 #ifdef BCM_TRIDENT3_SUPPORT 14149 if (is_eport) { 14150 istrunk_local = TRUE; 14151 } else { 14152 istrunk_remote = TRUE; 14153 } 14154 #endif 14155 } else { 14156 is_eport = FALSE; 14157 #ifdef BCM_TRIDENT3_SUPPORT 14158 istrunk_remote = TRUE; 14159 #endif 14160 } 14161 14162 soc_EGR_IM_MTP_INDEXm_field32_set(unit, &egr_mtp, 14163 MTP_DST_PORTf, port_out); 14164 soc_EGR_IM_MTP_INDEXm_field32_set(unit, &egr_mtp, 14165 MTP_DST_MODIDf, mod_out); 14166 14167 if (mirror_dest.flags & BCM_MIRROR_DEST_INT_PRI_SET) { 14168 soc_EGR_IM_MTP_INDEXm_field32_set(unit, &egr_mtp, 14169 CHANGE_INT_PRIf, 1); 14170 soc_EGR_IM_MTP_INDEXm_field32_set(unit, &egr_mtp, 14171 NEW_INT_PRIf, 14172 mirror_dest.int_pri); 14173 } 14174 /* HW write. based on mirrored traffic direction. */ 14175 if (flags & BCM_MIRROR_PORT_INGRESS) { 14176 BCM_IF_ERROR_RETURN 14177 (soc_mem_write(unit, EGR_IM_MTP_INDEXm, MEM_BLOCK_ALL, 14178 offset, &egr_mtp)); 14179 } 14180 14181 /* EGR_EM_MTP_INDEX has same layout as EGR_IM_MTP_INDEX */ 14182 if (flags & BCM_MIRROR_PORT_EGRESS) { 14183 #ifdef BCM_TOMAHAWK_SUPPORT 14184 if (SOC_INFO(unit).th_tflow_enabled == 1) { 14185 BCM_IF_ERROR_RETURN 14186 (soc_mem_write(unit, EGR_IM_MTP_INDEXm, MEM_BLOCK_ALL, 14187 offset, &egr_mtp)); 14188 } else 14189 #endif /* BCM_TOMAHAWK_SUPPORT */ 14190 { 14191 BCM_IF_ERROR_RETURN 14192 (soc_mem_write(unit, EGR_EM_MTP_INDEXm, MEM_BLOCK_ALL, 14193 offset, &egr_mtp)); 14194 } 14195 } 14196 } 14197 14198 #ifdef BCM_TRIDENT3_SUPPORT 14199 if (SOC_IS_TRIDENT3X(unit) && (TRUE == istrunk_local) && 14200 (TRUE == istrunk_remote)) { 14201 BCM_IF_ERROR_RETURN 14202 (_bcm_trx_mirror_tunnel_set(unit, index, trunk_arr,flags, 1)); 14203 BCM_IF_ERROR_RETURN 14204 (_bcm_trx_mirror_tunnel_set(unit, index, trunk_arr,flags, 0)); 14205 } else 14206 #endif 14207 { 14208 BCM_IF_ERROR_RETURN 14209 (_bcm_trx_mirror_tunnel_set(unit, index, trunk_arr, flags, is_eport)); 14210 } 14211 14212 } 14213 14214 return (BCM_E_NONE); 14215 } 14216 #endif /* BCM_TRIDENT2_SUPPORT */ 14217 14218 if (BCM_GPORT_IS_TRUNK(mirror_dest) && (0 == member_count)) { 14219 /* Traffic shouldn't proceed, don't configure other elements */ 14220 return BCM_E_NONE; 14221 } 14222 14223 replace_flag = (MIRROR_DEST(unit, mtp_cfg->dest_id))->flags; 14224 encap_index = index; 14225 14226 #ifdef BCM_METROLITE_SUPPORT 14227 if (soc_feature(unit, soc_feature_mirror_four_port_trunk)) { 14228 max_num_trunk_ports = 4; 14229 } else 14230 #endif 14231 max_num_trunk_ports = BCM_SWITCH_TRUNK_MAX_PORTCNT; 14232 #ifdef BCM_TOMAHAWK3_SUPPORT 14233 if (SOC_IS_TOMAHAWK3(unit)) { 14234 max_num_trunk_ports = 1; 14235 /* We use offset = index below since EGR_IM/EM_MTP_INDEX are 14236 * 4 entries deep 14237 */ 14238 } 14239 #endif /* BCM_TOMAHAWK3_SUPPORT */ 14240 offset = index * max_num_trunk_ports; 14241 14242 for (idx = 0; idx < max_num_trunk_ports; idx++, offset++) { 14243 egr_mtp = 0; 14244 BCM_IF_ERROR_RETURN(_bcm_esw_gport_resolve( 14245 unit, trunk_arr[idx],&modid,&port,&trunk, &id)); 14246 BCM_IF_ERROR_RETURN 14247 (_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_SET, modid, port, 14248 &mod_out, &port_out)); 14249 14250 /* The fields below are absent on TH3 device, hence validity check */ 14251 if (SOC_MEM_FIELD_VALID(unit, EGR_IM_MTP_INDEXm, MTP_DST_PORTf) && 14252 SOC_MEM_FIELD_VALID(unit, EGR_IM_MTP_INDEXm, MTP_DST_MODIDf)) { 14253 soc_EGR_IM_MTP_INDEXm_field32_set(unit, &egr_mtp, 14254 MTP_DST_PORTf, port_out); 14255 soc_EGR_IM_MTP_INDEXm_field32_set(unit, &egr_mtp, 14256 MTP_DST_MODIDf, mod_out); 14257 } 14258 14259 BCM_IF_ERROR_RETURN 14260 (_bcm_esw_modid_is_local(unit, mod_out, &is_local_modid)); 14261 if (is_local_modid) { 14262 is_eport = IS_E_PORT(unit, port)? TRUE: FALSE; 14263 #ifdef BCM_TRIDENT3_SUPPORT 14264 if (is_eport) { 14265 istrunk_local = TRUE; 14266 } else { 14267 istrunk_remote = TRUE; 14268 } 14269 #endif 14270 } else { 14271 is_eport = FALSE; 14272 #ifdef BCM_TRIDENT3_SUPPORT 14273 istrunk_remote = TRUE; 14274 #endif 14275 } 14276 14277 if (MIRROR_DEST_IS_TUNNEL(unit, mtp_cfg->dest_id)) { 14278 if (replace_flag & BCM_MIRROR_DEST_REPLACE) { 14279 soc_mem_t mem; 14280 14281 if (flags & BCM_MIRROR_PORT_INGRESS) { 14282 if ((MIRROR_DEST(unit, mtp_cfg->dest_id)->flags2) & 14283 BCM_MIRROR_DEST_FLAGS2_IFA) { 14284 mem = EGR_EM_MTP_INDEXm; 14285 } else { 14286 mem = EGR_IM_MTP_INDEXm; 14287 } 14288 } else if (flags & BCM_MIRROR_PORT_EGRESS) { 14289 mem = EGR_EM_MTP_INDEXm; 14290 } else if (flags & BCM_MIRROR_PORT_EGRESS_TRUE) { 14291 mem = EGR_EP_REDIRECT_EM_MTP_INDEXm; 14292 } else { 14293 return BCM_E_CONFIG; 14294 } 14295 14296 BCM_IF_ERROR_RETURN 14297 (soc_mem_read(unit, mem, MEM_BLOCK_ANY, offset, 14298 &egr_mtp_index_entry)); 14299 if (1 == soc_mem_field32_get(unit, mem, 14300 &egr_mtp_index_entry, 14301 MIRROR_ENCAP_ENABLEf)) { 14302 encap_index = soc_mem_field32_get(unit, mem, 14303 &egr_mtp_index_entry, 14304 MIRROR_ENCAP_INDEXf); 14305 soc_EGR_IM_MTP_INDEXm_field32_set(unit, &egr_mtp, 14306 MIRROR_ENCAP_ENABLEf, 1); 14307 } 14308 } 14309 soc_EGR_IM_MTP_INDEXm_field32_set(unit, &egr_mtp, 14310 MIRROR_ENCAP_INDEXf, encap_index); 14311 } 14312 14313 #ifdef BCM_TOMAHAWK_SUPPORT 14314 if ((SOC_INFO(unit).th_tflow_enabled == 1) 14315 && (flags & BCM_MIRROR_PORT_EGRESS)) { 14316 soc_EGR_IM_MTP_INDEXm_field32_set(unit, &egr_mtp, 14317 MIRROR_ENCAP_INDEXf, encap_index); 14318 } 14319 #endif /* BCM_TOMAHAWK_SUPPORT */ 14320 14321 if ((MIRROR_DEST(unit, mtp_cfg->dest_id))->flags 14322 & (BCM_MIRROR_DEST_INT_PRI_SET)) { 14323 /* For TH3, CHANGE_INT_PRIf, NEW_INT_PRIf are not valid */ 14324 if ((SOC_MEM_FIELD_VALID(unit, EGR_IM_MTP_INDEXm, CHANGE_INT_PRIf)) 14325 && 14326 (SOC_MEM_FIELD_VALID(unit, EGR_IM_MTP_INDEXm, NEW_INT_PRIf))) { 14327 soc_EGR_IM_MTP_INDEXm_field32_set(unit, &egr_mtp, 14328 CHANGE_INT_PRIf, 1); 14329 soc_EGR_IM_MTP_INDEXm_field32_set(unit, &egr_mtp, 14330 NEW_INT_PRIf, 14331 (MIRROR_DEST(unit, mtp_cfg->dest_id))->int_pri); 14332 } 14333 } 14334 /* HW write. based on mirrored traffic direction. */ 14335 if (flags & BCM_MIRROR_PORT_INGRESS) { 14336 if ((MIRROR_DEST(unit, mtp_cfg->dest_id)->flags2) & 14337 BCM_MIRROR_DEST_FLAGS2_IFA) { 14338 BCM_IF_ERROR_RETURN 14339 (soc_mem_write(unit, EGR_EM_MTP_INDEXm, MEM_BLOCK_ALL, 14340 offset, &egr_mtp)); 14341 } else { 14342 BCM_IF_ERROR_RETURN 14343 (soc_mem_write(unit, EGR_IM_MTP_INDEXm, MEM_BLOCK_ALL, 14344 offset, &egr_mtp)); 14345 } 14346 } 14347 14348 /* EGR_EM_MTP_INDEX has same layout as EGR_IM_MTP_INDEX */ 14349 if (flags & BCM_MIRROR_PORT_EGRESS) { 14350 #ifdef BCM_TOMAHAWK_SUPPORT 14351 if (SOC_INFO(unit).th_tflow_enabled == 1) { 14352 BCM_IF_ERROR_RETURN 14353 (soc_mem_write(unit, EGR_IM_MTP_INDEXm, MEM_BLOCK_ALL, 14354 offset, &egr_mtp)); 14355 } else 14356 #endif /* BCM_TOMAHAWK_SUPPORT */ 14357 { 14358 BCM_IF_ERROR_RETURN 14359 (soc_mem_write(unit, EGR_EM_MTP_INDEXm, MEM_BLOCK_ALL, 14360 offset, &egr_mtp)); 14361 } 14362 } 14363 14364 /* EGR_EP_REDIRECT_EM_MTP_INDEX has same layout as 14365 * EGR_IM_MTP_INDEX */ 14366 if (soc_feature(unit, soc_feature_egr_mirror_true) && 14367 (flags & BCM_MIRROR_PORT_EGRESS_TRUE)) { 14368 BCM_IF_ERROR_RETURN 14369 (soc_mem_write(unit, EGR_EP_REDIRECT_EM_MTP_INDEXm, 14370 MEM_BLOCK_ALL, offset, &egr_mtp)); 14371 } 14372 } 14373 14374 if (MIRROR_DEST_IS_TUNNEL(unit, mtp_cfg->dest_id)) { 14375 #ifdef BCM_TRIDENT3_SUPPORT 14376 if (SOC_IS_TRIDENT3X(unit) && (TRUE == istrunk_local) && 14377 (TRUE == istrunk_remote)) { 14378 BCM_IF_ERROR_RETURN 14379 (_bcm_trx_mirror_tunnel_set(unit, index, trunk_arr,flags, 1)); 14380 BCM_IF_ERROR_RETURN 14381 (_bcm_trx_mirror_tunnel_set(unit, index, trunk_arr,flags, 0)); 14382 } else 14383 #endif 14384 { 14385 BCM_IF_ERROR_RETURN 14386 (_bcm_trx_mirror_tunnel_set(unit, index, trunk_arr, flags, 14387 is_eport)); 14388 } 14389 } else { 14390 #if defined(BCM_TRIDENT3_SUPPORT) 14391 if (SOC_IS_TRIDENT3(unit)) { 14392 BCM_IF_ERROR_RETURN(_bcm_td3_mirror_non_tunnel_truncate_set(unit, index, 14393 trunk_arr, flags)); 14394 } 14395 #endif 14396 } 14397 14398 #if defined(BCM_TOMAHAWK3_SUPPORT) 14399 if (SOC_IS_TOMAHAWK3(unit)) { 14400 /* Work around for applying payload zeroing or truncation to 14401 * non-tunneled mirrored packets (ARCHTH3-444) 14402 */ 14403 if ((!(MIRROR_DEST_IS_TUNNEL(unit, mtp_cfg->dest_id))) && 14404 ((MIRROR_DEST(unit, mtp_cfg->dest_id))->truncate != 14405 BCM_MIRROR_PAYLOAD_DO_NOT_TRUNCATE) && 14406 ((MIRROR_DEST(unit, mtp_cfg->dest_id))->truncate <= 14407 BCM_MIRROR_PAYLOAD_TRUNCATE_AND_ZERO)) { 14408 BCM_IF_ERROR_RETURN 14409 (_bcm_tomahawk3_mirror_non_tunnel_config_set(unit, index, flags)); 14410 } 14411 14412 /* Update truncation setting */ 14413 BCM_IF_ERROR_RETURN(_bcm_tomahawk3_egr_mirror_truncation_update(unit, 14414 index, 14415 (MIRROR_DEST(unit, mtp_cfg->dest_id))->truncate, 14416 flags)); 14417 } 14418 #endif /* BCM_TOMAHAWK3_SUPPORT */ 14419 14420 return (BCM_E_NONE); 14421 } 14422 14423 /* 14424 * Function: 14425 * _bcm_td_mtp_reset 14426 * Purpose: 14427 * Reset mirror target port for TRIDENT devices. 14428 * Parameters: 14429 * unit - (IN)BCM device number 14430 * index - (IN)Mtp index. 14431 * flags - (IN)Filled entry flags(BCM_MIRROR_PORT_INGRESS/EGRESS 14432 * Returns: 14433 * BCM_E_XXX 14434 */ 14435 STATIC int 14436 _bcm_td_mtp_reset(int unit, int index, int flags) 14437 { 14438 int offset; 14439 int idx, encap_present; 14440 uint32 mtp[SOC_MAX_MEM_BYTES/4]; 14441 uint32 mirror_select, mtp_type, encap_index = 0; 14442 #ifdef BCM_TRIDENT2_SUPPORT 14443 _bcm_mtp_config_p mtp_cfg; /* MTP configuration. */ 14444 bcm_mirror_destination_t *mirror_dest; /* Destination & Encapsulation.*/ 14445 int profile_ref_count = 0; 14446 #endif /* BCM_TRIDENT2_SUPPORT */ 14447 egr_im_mtp_index_entry_t entry; 14448 int max_num_trunk_ports = 0; 14449 soc_mem_t mem; 14450 14451 sal_memset(mtp, 0, sizeof(mtp)); 14452 14453 #ifdef BCM_TRIDENT2_SUPPORT 14454 mtp_cfg = MIRROR_CONFIG_MTP(unit, index, flags); 14455 mirror_dest = MIRROR_DEST(unit, mtp_cfg->dest_id); 14456 #endif /* BCM_TRIDENT2_SUPPORT */ 14457 14458 /* HW write. based on mirrored traffic direction. */ 14459 if (flags & BCM_MIRROR_PORT_INGRESS) { 14460 BCM_IF_ERROR_RETURN 14461 (soc_mem_write(unit, IM_MTP_INDEXm, MEM_BLOCK_ALL, index, mtp)); 14462 } 14463 14464 /* EM_MTP_INDEX has same layout as IM_MTP_INDEX */ 14465 if (flags & BCM_MIRROR_PORT_EGRESS) { 14466 BCM_IF_ERROR_RETURN 14467 (soc_mem_write(unit, EM_MTP_INDEXm, MEM_BLOCK_ALL, index, mtp)); 14468 } 14469 14470 #ifdef BCM_TRIUMPH3_SUPPORT 14471 /* EP_REDIRECT_EM_MTP_INDEX has same layout as IM_MTP_INDEX */ 14472 if (flags & BCM_MIRROR_PORT_EGRESS_TRUE) { 14473 BCM_IF_ERROR_RETURN 14474 (soc_mem_write(unit, EP_REDIRECT_EM_MTP_INDEXm, 14475 MEM_BLOCK_ALL, index, &mtp)); 14476 } 14477 #endif /* BCM_TRIUMPH2_SUPPORT */ 14478 14479 /* Reset MTP_SELECT register to 0 */ 14480 if (soc_feature(unit, soc_feature_mirror_flexible) && 14481 !MIRROR_MTP_METHOD_IS_DIRECTED_FLEXIBLE(unit)) { 14482 BCM_IF_ERROR_RETURN(READ_MIRROR_SELECTr(unit, &mirror_select)); 14483 mtp_type = soc_reg_field_get(unit, MIRROR_SELECTr, 14484 mirror_select, MTP_TYPEf); 14485 mtp_type &= ~(1 << index); 14486 soc_reg_field_set(unit, MIRROR_SELECTr, &mirror_select, 14487 MTP_TYPEf, mtp_type); 14488 BCM_IF_ERROR_RETURN(WRITE_MIRROR_SELECTr(unit, mirror_select)); 14489 } 14490 14491 #ifdef BCM_TRIDENT2_SUPPORT 14492 if (mirror_dest->flags & BCM_MIRROR_DEST_ID_SHARE) { 14493 max_num_trunk_ports = BCM_SWITCH_TRUNK_MAX_PORTCNT; 14494 offset = index * max_num_trunk_ports; 14495 sal_memset(mtp, 0, sizeof(mtp)); 14496 14497 for (idx = 0; idx < max_num_trunk_ports; idx++, offset++) { 14498 /* HW write. based on mirrored traffic direction. */ 14499 if (flags & BCM_MIRROR_PORT_INGRESS) { 14500 BCM_IF_ERROR_RETURN 14501 (soc_mem_read(unit, EGR_IM_MTP_INDEXm, MEM_BLOCK_ANY, 14502 offset, &entry)); 14503 if (soc_mem_field32_get(unit, EGR_IM_MTP_INDEXm, 14504 &entry, MIRROR_ENCAP_ENABLEf)) { 14505 encap_index = 14506 soc_mem_field32_get(unit, EGR_IM_MTP_INDEXm, 14507 &entry, MIRROR_ENCAP_INDEXf); 14508 } 14509 14510 BCM_IF_ERROR_RETURN 14511 (soc_mem_write(unit, EGR_IM_MTP_INDEXm, MEM_BLOCK_ALL, 14512 offset, mtp)); 14513 } 14514 14515 /* EGR_EM_MTP_INDEX has same layout as EGR_IM_MTP_INDEX */ 14516 if (flags & BCM_MIRROR_PORT_EGRESS) { 14517 #ifdef BCM_TOMAHAWK_SUPPORT 14518 if (SOC_INFO(unit).th_tflow_enabled == 1) { 14519 BCM_IF_ERROR_RETURN 14520 (soc_mem_read(unit, EGR_IM_MTP_INDEXm, MEM_BLOCK_ANY, 14521 offset, &entry)); 14522 if (soc_mem_field32_get(unit, EGR_IM_MTP_INDEXm, 14523 &entry, MIRROR_ENCAP_ENABLEf)) { 14524 encap_index = 14525 soc_mem_field32_get(unit, EGR_IM_MTP_INDEXm, 14526 &entry, MIRROR_ENCAP_INDEXf); 14527 } 14528 } else 14529 #endif /* BCM_TOMAHAWK_SUPPORT */ 14530 { 14531 BCM_IF_ERROR_RETURN 14532 (soc_mem_read(unit, EGR_EM_MTP_INDEXm, MEM_BLOCK_ANY, 14533 offset, &entry)); 14534 if (soc_mem_field32_get(unit, EGR_EM_MTP_INDEXm, 14535 &entry, MIRROR_ENCAP_ENABLEf)) { 14536 encap_index = 14537 soc_mem_field32_get(unit, EGR_EM_MTP_INDEXm, 14538 &entry, MIRROR_ENCAP_INDEXf); 14539 } 14540 } 14541 14542 #ifdef BCM_TOMAHAWK_SUPPORT 14543 if (SOC_INFO(unit).th_tflow_enabled == 1) { 14544 BCM_IF_ERROR_RETURN 14545 (soc_mem_write(unit, EGR_IM_MTP_INDEXm, MEM_BLOCK_ALL, 14546 offset, mtp)); 14547 } else 14548 #endif /* BCM_TOMAHAWK_SUPPORT */ 14549 { 14550 BCM_IF_ERROR_RETURN 14551 (soc_mem_write(unit, EGR_EM_MTP_INDEXm, MEM_BLOCK_ALL, 14552 offset, mtp)); 14553 } 14554 } 14555 14556 BCM_IF_ERROR_RETURN 14557 (_bcm_egr_mirror_encap_entry_ref_get(unit, 14558 encap_index, 14559 &profile_ref_count)); 14560 if (profile_ref_count != 0) { 14561 BCM_IF_ERROR_RETURN 14562 (_bcm_egr_mirror_encap_entry_delete(unit, encap_index)); 14563 } 14564 } 14565 return (BCM_E_NONE); 14566 } 14567 #endif /* BCM_TRIDENT2_SUPPORT */ 14568 14569 encap_present = FALSE; 14570 #ifdef BCM_METROLITE_SUPPORT 14571 if (soc_feature(unit, soc_feature_mirror_four_port_trunk)) { 14572 max_num_trunk_ports = 4; 14573 } else 14574 #endif 14575 max_num_trunk_ports = BCM_SWITCH_TRUNK_MAX_PORTCNT; 14576 14577 #ifdef BCM_TOMAHAWK3_SUPPORT 14578 if (SOC_IS_TOMAHAWK3(unit)) { 14579 max_num_trunk_ports = 1; 14580 /* We use offset = index below since EGR_IM/EM_MTP_INDEX are 14581 * 4 entries deep 14582 */ 14583 } 14584 #endif /* BCM_TOMAHAWK3_SUPPORT */ 14585 14586 offset = index * max_num_trunk_ports; 14587 14588 sal_memset(mtp, 0, sizeof(mtp)); 14589 14590 for (idx = 0; idx < max_num_trunk_ports; idx++, offset++) { 14591 /* HW write. based on mirrored traffic direction. */ 14592 if (flags & BCM_MIRROR_PORT_INGRESS) { 14593 #ifdef BCM_TRIDENT3_SUPPORT 14594 if ((MIRROR_DEST(unit, mtp_cfg->dest_id)->flags2) & 14595 BCM_MIRROR_DEST_FLAGS2_IFA) { 14596 mem = EGR_EM_MTP_INDEXm; 14597 } else 14598 #endif 14599 { 14600 mem = EGR_IM_MTP_INDEXm; 14601 } 14602 14603 if ((0 == idx) && !encap_present) { 14604 BCM_IF_ERROR_RETURN 14605 (soc_mem_read(unit, mem, MEM_BLOCK_ANY, 14606 offset, &entry)); 14607 if (soc_mem_field32_get(unit, mem, 14608 &entry, MIRROR_ENCAP_ENABLEf)) { 14609 encap_index = 14610 soc_mem_field32_get(unit, mem, 14611 &entry, MIRROR_ENCAP_INDEXf); 14612 encap_present = TRUE; 14613 } 14614 } 14615 14616 BCM_IF_ERROR_RETURN 14617 (soc_mem_write(unit, mem, MEM_BLOCK_ALL, 14618 offset, mtp)); 14619 } 14620 14621 /* EGR_EM_MTP_INDEX has same layout as EGR_IM_MTP_INDEX */ 14622 if (flags & BCM_MIRROR_PORT_EGRESS) { 14623 if ((0 == idx) && !encap_present) { 14624 #ifdef BCM_TOMAHAWK_SUPPORT 14625 if (SOC_INFO(unit).th_tflow_enabled == 1) { 14626 BCM_IF_ERROR_RETURN 14627 (soc_mem_read(unit, EGR_IM_MTP_INDEXm, MEM_BLOCK_ANY, 14628 offset, &entry)); 14629 if (soc_mem_field32_get(unit, EGR_IM_MTP_INDEXm, 14630 &entry, MIRROR_ENCAP_ENABLEf)) { 14631 encap_index = 14632 soc_mem_field32_get(unit, EGR_IM_MTP_INDEXm, 14633 &entry, MIRROR_ENCAP_INDEXf); 14634 encap_present = TRUE; 14635 } 14636 } else 14637 #endif /* BCM_TOMAHAWK_SUPPORT */ 14638 { 14639 BCM_IF_ERROR_RETURN 14640 (soc_mem_read(unit, EGR_EM_MTP_INDEXm, MEM_BLOCK_ANY, 14641 offset, &entry)); 14642 if (soc_mem_field32_get(unit, EGR_EM_MTP_INDEXm, 14643 &entry, MIRROR_ENCAP_ENABLEf)) { 14644 encap_index = 14645 soc_mem_field32_get(unit, EGR_EM_MTP_INDEXm, 14646 &entry, MIRROR_ENCAP_INDEXf); 14647 encap_present = TRUE; 14648 } 14649 } 14650 } 14651 14652 #ifdef BCM_TOMAHAWK_SUPPORT 14653 if (SOC_INFO(unit).th_tflow_enabled == 1) { 14654 BCM_IF_ERROR_RETURN 14655 (soc_mem_write(unit, EGR_IM_MTP_INDEXm, MEM_BLOCK_ALL, 14656 offset, mtp)); 14657 } else 14658 #endif /* BCM_TOMAHAWK_SUPPORT */ 14659 { 14660 BCM_IF_ERROR_RETURN 14661 (soc_mem_write(unit, EGR_EM_MTP_INDEXm, MEM_BLOCK_ALL, 14662 offset, mtp)); 14663 } 14664 } 14665 14666 /* EP_REDIRECT_EM_MTP_INDEX has same layout as IM_MTP_INDEX */ 14667 if (flags & BCM_MIRROR_PORT_EGRESS_TRUE) { 14668 if ((0 == idx) && !encap_present) { 14669 BCM_IF_ERROR_RETURN 14670 (soc_mem_read(unit, EGR_EP_REDIRECT_EM_MTP_INDEXm, 14671 MEM_BLOCK_ANY, offset, &entry)); 14672 if (soc_mem_field32_get(unit, EGR_EP_REDIRECT_EM_MTP_INDEXm, 14673 &entry, MIRROR_ENCAP_ENABLEf)) { 14674 encap_index = 14675 soc_mem_field32_get(unit, 14676 EGR_EP_REDIRECT_EM_MTP_INDEXm, 14677 &entry, MIRROR_ENCAP_INDEXf); 14678 encap_present = TRUE; 14679 } 14680 } 14681 BCM_IF_ERROR_RETURN 14682 (soc_mem_write(unit, EGR_EP_REDIRECT_EM_MTP_INDEXm, 14683 MEM_BLOCK_ALL, offset, mtp)); 14684 } 14685 } 14686 14687 /* At most one of the direction flags is true, and the whole 14688 * set of trunk block copies are identical. We need only 14689 * one delete of our reference to the profile table. 14690 */ 14691 if (encap_present) { 14692 BCM_IF_ERROR_RETURN 14693 (_bcm_egr_mirror_encap_entry_delete(unit, encap_index)); 14694 } 14695 14696 return (BCM_E_NONE); 14697 } 14698 14699 #endif /* BCM_TRIDENT_SUPPORT */ 14700 14701 14702 #if defined(BCM_FIREBOLT_SUPPORT) 14703 /* 14704 * Function: 14705 * _bcm_fbx_mtp_init 14706 * Purpose: 14707 * Initialize mirror target port for FBX devices. 14708 * Parameters: 14709 * unit - (IN)BCM device number 14710 * index - (IN)Mtp index. 14711 * trunk_arr - (IN)Trunk members array. 14712 * flags - (IN)Filled entry flags(BCM_MIRROR_PORT_INGRESS/EGRESS 14713 * or both. In case both flags are specied 14714 * ingress & egress configuration is assumed to be 14715 * idential. 14716 * Returns: 14717 * BCM_E_XXX 14718 */ 14719 STATIC int 14720 _bcm_fbx_mtp_init(int unit, int index, bcm_gport_t *trunk_arr, int flags) 14721 { 14722 bcm_gport_t mirror_dest; 14723 bcm_port_t port_out; 14724 bcm_module_t mod_out; 14725 _bcm_mtp_config_p mtp_cfg; 14726 int offset; 14727 int idx, id; 14728 bcm_trunk_t trunk = BCM_TRUNK_INVALID; 14729 bcm_module_t modid = 0; 14730 bcm_port_t port = -1; 14731 uint32 mtp = 0; 14732 int isLocal; 14733 int member_count = 0; 14734 #ifdef BCM_GREYHOUND_SUPPORT 14735 int encap_index; 14736 uint32 replace_flag = 0; 14737 egr_im_mtp_index_entry_t egr_mtp_index_entry; 14738 #endif /* BCM_GREYHOUND_SUPPORT */ 14739 14740 /* Input parameters check */ 14741 if (NULL == trunk_arr) { 14742 return (BCM_E_PARAM); 14743 } 14744 14745 /* Get mtp configuration structure by direction & index. */ 14746 mtp_cfg = MIRROR_CONFIG_MTP(unit, index, flags); 14747 14748 /* Parse destination trunk / port & module. */ 14749 mirror_dest = MIRROR_DEST_GPORT(unit, mtp_cfg->dest_id); 14750 if (BCM_GPORT_IS_TRUNK(mirror_dest)) { 14751 trunk = BCM_GPORT_TRUNK_GET(mirror_dest); 14752 /* Get active trunk members*/ 14753 BCM_IF_ERROR_RETURN 14754 (_bcm_trunk_id_validate(unit, trunk)); 14755 BCM_IF_ERROR_RETURN 14756 (_bcm_esw_trunk_active_member_get(unit, trunk, NULL, 14757 0, NULL, &member_count)); 14758 } else { 14759 /* If MODPORT GPORT provided resolve already had happened */ 14760 if (BCM_GPORT_IS_MODPORT(mirror_dest)) { 14761 modid = BCM_GPORT_MODPORT_MODID_GET(mirror_dest); 14762 port = BCM_GPORT_MODPORT_PORT_GET(mirror_dest); 14763 } else { 14764 BCM_IF_ERROR_RETURN( 14765 _bcm_esw_gport_resolve(unit, mirror_dest, &modid, 14766 &port, &trunk, &id)); 14767 if (BCM_TRUNK_INVALID != trunk || id != -1) { 14768 return BCM_E_PORT; 14769 } 14770 } 14771 BCM_IF_ERROR_RETURN( 14772 _bcm_esw_modid_is_local(unit, modid, &isLocal)); 14773 if (TRUE == isLocal) { 14774 BCM_IF_ERROR_RETURN( 14775 _bcm_esw_stk_modmap_map(unit,BCM_STK_MODMAP_SET, modid, port, 14776 &modid, &port)); 14777 } 14778 } 14779 14780 /* Hw buffer preparation. */ 14781 if (soc_feature(unit, soc_feature_trunk_group_overlay)) { 14782 if (BCM_GPORT_IS_TRUNK(mirror_dest)) { 14783 soc_IM_MTP_INDEXm_field32_set(unit, &mtp, Tf, 1); 14784 soc_IM_MTP_INDEXm_field32_set(unit, &mtp, TGIDf, trunk); 14785 } else { 14786 soc_IM_MTP_INDEXm_field32_set(unit, &mtp, MODULE_IDf, modid); 14787 soc_IM_MTP_INDEXm_field32_set(unit, &mtp, PORT_NUMf, port); 14788 } 14789 } else { 14790 if (BCM_GPORT_IS_TRUNK(mirror_dest)) { 14791 modid = BCM_TRUNK_TO_MODIDf(unit, trunk); 14792 port = BCM_TRUNK_TO_TGIDf(unit, trunk); 14793 } 14794 soc_IM_MTP_INDEXm_field32_set(unit, &mtp, MODULE_IDf, modid); 14795 soc_IM_MTP_INDEXm_field32_set(unit, &mtp, PORT_TGIDf, port); 14796 } 14797 14798 /* HW write. based on mirrored traffic direction. */ 14799 if (flags & BCM_MIRROR_PORT_INGRESS) { 14800 BCM_IF_ERROR_RETURN 14801 (soc_mem_write(unit, IM_MTP_INDEXm, MEM_BLOCK_ALL, index, &mtp)); 14802 } 14803 14804 /* EM_MTP_INDEX has same layout as IM_MTP_INDEX */ 14805 if (flags & BCM_MIRROR_PORT_EGRESS) { 14806 BCM_IF_ERROR_RETURN 14807 (soc_mem_write(unit, EM_MTP_INDEXm, MEM_BLOCK_ALL, index, &mtp)); 14808 } 14809 14810 #ifdef BCM_TRIUMPH2_SUPPORT 14811 /* EP_REDIRECT_EM_MTP_INDEX has same layout as IM_MTP_INDEX */ 14812 if (flags & BCM_MIRROR_PORT_EGRESS_TRUE) { 14813 BCM_IF_ERROR_RETURN 14814 (soc_mem_write(unit, EP_REDIRECT_EM_MTP_INDEXm, 14815 MEM_BLOCK_ALL, index, &mtp)); 14816 } 14817 #endif /* BCM_TRIUMPH2_SUPPORT */ 14818 14819 if (BCM_GPORT_IS_TRUNK(mirror_dest) && (0 == member_count)) { 14820 /* Traffic shouldn't proceed, don't configure other elements */ 14821 return BCM_E_NONE; 14822 } 14823 14824 #ifdef BCM_GREYHOUND_SUPPORT 14825 replace_flag = (MIRROR_DEST(unit, mtp_cfg->dest_id))->flags; 14826 encap_index = index; 14827 #endif /* BCM_GREYHOUND_SUPPORT */ 14828 14829 offset = index * BCM_SWITCH_TRUNK_MAX_PORTCNT; 14830 for (idx = 0; idx < BCM_SWITCH_TRUNK_MAX_PORTCNT; idx++, offset++) { 14831 mtp = 0; 14832 if (BCM_GPORT_IS_MODPORT(trunk_arr[idx])) { 14833 modid = BCM_GPORT_MODPORT_MODID_GET(trunk_arr[idx]); 14834 port = BCM_GPORT_MODPORT_PORT_GET(trunk_arr[idx]); 14835 } else { 14836 BCM_IF_ERROR_RETURN( 14837 _bcm_esw_gport_resolve(unit, trunk_arr[idx], &modid, 14838 &port, &trunk, &id)); 14839 if (BCM_TRUNK_INVALID != trunk || id != -1) { 14840 return BCM_E_PORT; 14841 } 14842 } 14843 BCM_IF_ERROR_RETURN 14844 (_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_SET, modid, port, 14845 &mod_out, &port_out)); 14846 14847 soc_EGR_IM_MTP_INDEXm_field32_set(unit, &mtp, MTP_DST_PORTf, port_out); 14848 soc_EGR_IM_MTP_INDEXm_field32_set(unit, &mtp, MTP_DST_MODIDf, mod_out); 14849 14850 #ifdef BCM_GREYHOUND_SUPPORT 14851 if (soc_feature(unit, soc_feature_mirror_encap_profile) && 14852 (MIRROR_DEST_IS_TUNNEL(unit, mtp_cfg->dest_id))) { 14853 soc_EGR_IM_MTP_INDEXm_field32_set(unit, &mtp, 14854 MIRROR_ENCAP_ENABLEf, 1); 14855 if (replace_flag & BCM_MIRROR_DEST_REPLACE) { 14856 soc_mem_t mem; 14857 14858 if (flags & BCM_MIRROR_PORT_INGRESS) { 14859 mem = EGR_IM_MTP_INDEXm; 14860 } else if (flags & BCM_MIRROR_PORT_EGRESS) { 14861 mem = EGR_EM_MTP_INDEXm; 14862 } else { 14863 return BCM_E_CONFIG; 14864 } 14865 14866 BCM_IF_ERROR_RETURN 14867 (soc_mem_read(unit, mem, MEM_BLOCK_ANY, offset, 14868 &egr_mtp_index_entry)); 14869 if (1 == soc_mem_field32_get(unit, mem, 14870 &egr_mtp_index_entry, 14871 MIRROR_ENCAP_ENABLEf)) { 14872 encap_index = soc_mem_field32_get(unit, mem, 14873 &egr_mtp_index_entry, 14874 MIRROR_ENCAP_INDEXf); 14875 14876 } 14877 } 14878 soc_EGR_IM_MTP_INDEXm_field32_set(unit, &mtp, 14879 MIRROR_ENCAP_INDEXf, encap_index); 14880 } 14881 #endif /* BCM_GREYHOUND_SUPPORT */ 14882 14883 /* HW write. based on mirrored traffic direction. */ 14884 if (flags & BCM_MIRROR_PORT_INGRESS) { 14885 BCM_IF_ERROR_RETURN 14886 (soc_mem_write(unit, EGR_IM_MTP_INDEXm, MEM_BLOCK_ALL, 14887 offset, &mtp)); 14888 } 14889 14890 /* EGR_EM_MTP_INDEX has same layout as EGR_IM_MTP_INDEX */ 14891 if (flags & BCM_MIRROR_PORT_EGRESS) { 14892 BCM_IF_ERROR_RETURN 14893 (soc_mem_write(unit, EGR_EM_MTP_INDEXm, MEM_BLOCK_ALL, 14894 offset, &mtp)); 14895 } 14896 14897 #ifdef BCM_TRIUMPH2_SUPPORT 14898 /* EGR_EP_REDIRECT_EM_MTP_INDEX has same layout as others */ 14899 if (flags & BCM_MIRROR_PORT_EGRESS_TRUE) { 14900 BCM_IF_ERROR_RETURN 14901 (soc_mem_write(unit, EGR_EP_REDIRECT_EM_MTP_INDEXm, 14902 MEM_BLOCK_ALL, offset, &mtp)); 14903 } 14904 #endif /* BCM_TRIUMPH2_SUPPORT */ 14905 } 14906 14907 #if defined(BCM_TRX_SUPPORT) 14908 if((MIRROR_DEST(unit, mtp_cfg->dest_id))->flags || 14909 (MIRROR_DEST(unit, mtp_cfg->dest_id))->flags2) { 14910 BCM_IF_ERROR_RETURN(_bcm_trx_mirror_tunnel_set(unit, index, 14911 trunk_arr, flags, 0)); 14912 } 14913 #endif /* BCM_TRX_SUPPORT */ 14914 14915 return (BCM_E_NONE); 14916 } 14917 14918 /* 14919 * Function: 14920 * _bcm_fbx_mtp_reset 14921 * Purpose: 14922 * Reset mirror target port for FBX devices. 14923 * Parameters: 14924 * unit - (IN)BCM device number 14925 * index - (IN)Mtp index. 14926 * flags - (IN)Filled entry flags(BCM_MIRROR_PORT_INGRESS/EGRESS 14927 * Returns: 14928 * BCM_E_XXX 14929 */ 14930 STATIC int 14931 _bcm_fbx_mtp_reset(int unit, int index, int flags) 14932 { 14933 int offset; 14934 int idx; 14935 uint32 mtp = 0; 14936 uint32 mirror_select, mtp_type; 14937 #ifdef BCM_GREYHOUND_SUPPORT 14938 egr_im_mtp_index_entry_t entry; 14939 int encap_present = 0; 14940 uint32 encap_index = 0; 14941 #endif 14942 /* HW write. based on mirrored traffic direction. */ 14943 if (flags & BCM_MIRROR_PORT_INGRESS) { 14944 BCM_IF_ERROR_RETURN 14945 (soc_mem_write(unit, IM_MTP_INDEXm, MEM_BLOCK_ALL, index, &mtp)); 14946 } 14947 14948 /* EM_MTP_INDEX has same layout as IM_MTP_INDEX */ 14949 if (flags & BCM_MIRROR_PORT_EGRESS) { 14950 BCM_IF_ERROR_RETURN 14951 (soc_mem_write(unit, EM_MTP_INDEXm, MEM_BLOCK_ALL, index, &mtp)); 14952 } 14953 14954 #ifdef BCM_TRIUMPH2_SUPPORT 14955 /* EP_REDIRECT_EM_MTP_INDEX has same layout as IM_MTP_INDEX */ 14956 if (flags & BCM_MIRROR_PORT_EGRESS_TRUE) { 14957 BCM_IF_ERROR_RETURN 14958 (soc_mem_write(unit, EP_REDIRECT_EM_MTP_INDEXm, 14959 MEM_BLOCK_ALL, index, &mtp)); 14960 } 14961 #endif /* BCM_TRIUMPH2_SUPPORT */ 14962 14963 /* Reset MTP_SELECT register to 0 if exists */ 14964 if (SOC_REG_FIELD_VALID(unit, MIRROR_SELECTr, MTP_TYPEf)) { 14965 BCM_IF_ERROR_RETURN(READ_MIRROR_SELECTr(unit, &mirror_select)); 14966 mtp_type = soc_reg_field_get(unit, MIRROR_SELECTr, 14967 mirror_select, MTP_TYPEf); 14968 mtp_type &= ~(1 << index); 14969 soc_reg_field_set(unit, MIRROR_SELECTr, &mirror_select, 14970 MTP_TYPEf, mtp_type); 14971 BCM_IF_ERROR_RETURN(WRITE_MIRROR_SELECTr( unit, mirror_select)); 14972 } 14973 14974 14975 #ifdef BCM_TRX_SUPPORT 14976 if (SOC_MEM_IS_VALID(unit, EGR_ERSPANm)) { 14977 egr_erspan_entry_t hw_buf; 14978 int egr_idx; 14979 14980 /* Reset hw buffer. */ 14981 sal_memset(&hw_buf, 0, sizeof(egr_erspan_entry_t)); 14982 14983 /* Get egr_erspan index by direction */ 14984 if (flags & BCM_MIRROR_PORT_INGRESS) { 14985 egr_idx = index; 14986 } else if (flags & BCM_MIRROR_PORT_EGRESS) { 14987 egr_idx = index + 4; 14988 } else { /* True Egress */ 14989 egr_idx = index + 8; 14990 } 14991 BCM_IF_ERROR_RETURN( 14992 soc_mem_write(unit, EGR_ERSPANm, MEM_BLOCK_ALL, 14993 egr_idx, &hw_buf)); 14994 } 14995 #endif /* BCM_TRX_SUPPORT */ 14996 14997 offset = index * BCM_SWITCH_TRUNK_MAX_PORTCNT; 14998 for (idx = 0; idx < BCM_SWITCH_TRUNK_MAX_PORTCNT; idx++, offset++) { 14999 mtp = 0; 15000 15001 /* HW write. based on mirrored traffic direction. */ 15002 if (flags & BCM_MIRROR_PORT_INGRESS) { 15003 #ifdef BCM_GREYHOUND_SUPPORT 15004 if (soc_feature(unit, soc_feature_mirror_encap_profile)) { 15005 if ((0 == idx) && !encap_present) { 15006 BCM_IF_ERROR_RETURN 15007 (soc_mem_read(unit, EGR_IM_MTP_INDEXm, MEM_BLOCK_ANY, 15008 offset, &entry)); 15009 if (soc_mem_field32_get(unit, EGR_IM_MTP_INDEXm, 15010 &entry, MIRROR_ENCAP_ENABLEf)) { 15011 encap_index = 15012 soc_mem_field32_get(unit, EGR_IM_MTP_INDEXm, 15013 &entry, MIRROR_ENCAP_INDEXf); 15014 encap_present = TRUE; 15015 } 15016 } 15017 } 15018 #endif /* BCM_GREYHOUND_SUPPORT */ 15019 BCM_IF_ERROR_RETURN 15020 (soc_mem_write(unit, EGR_IM_MTP_INDEXm, MEM_BLOCK_ALL, 15021 offset, &mtp)); 15022 } 15023 15024 /* EGR_EM_MTP_INDEX has same layout as EGR_IM_MTP_INDEX */ 15025 if (flags & BCM_MIRROR_PORT_EGRESS) { 15026 #ifdef BCM_GREYHOUND_SUPPORT 15027 if (soc_feature(unit, soc_feature_mirror_encap_profile)) { 15028 if ((0 == idx) && !encap_present) { 15029 BCM_IF_ERROR_RETURN 15030 (soc_mem_read(unit, EGR_EM_MTP_INDEXm, MEM_BLOCK_ANY, 15031 offset, &entry)); 15032 if (soc_mem_field32_get(unit, EGR_EM_MTP_INDEXm, 15033 &entry, MIRROR_ENCAP_ENABLEf)) { 15034 encap_index = 15035 soc_mem_field32_get(unit, EGR_EM_MTP_INDEXm, 15036 &entry, MIRROR_ENCAP_INDEXf); 15037 encap_present = TRUE; 15038 } 15039 } 15040 } 15041 #endif /* BCM_GREYHOUND_SUPPORT */ 15042 BCM_IF_ERROR_RETURN 15043 (soc_mem_write(unit, EGR_EM_MTP_INDEXm, MEM_BLOCK_ALL, 15044 offset, &mtp)); 15045 } 15046 15047 #ifdef BCM_TRIUMPH2_SUPPORT 15048 /* EGR_EP_REDIRECT_EM_MTP_INDEX has same layout as others */ 15049 if (flags & BCM_MIRROR_PORT_EGRESS_TRUE) { 15050 BCM_IF_ERROR_RETURN 15051 (soc_mem_write(unit, EGR_EP_REDIRECT_EM_MTP_INDEXm, 15052 MEM_BLOCK_ALL, offset, &mtp)); 15053 } 15054 #endif /* BCM_TRIUMPH2_SUPPORT */ 15055 } 15056 15057 /* At most one of the direction flags is true, and the whole 15058 * set of trunk block copies are identical. We need only 15059 * one delete of our reference to the profile table. 15060 */ 15061 #ifdef BCM_GREYHOUND_SUPPORT 15062 if (soc_feature(unit, soc_feature_mirror_encap_profile)) { 15063 if (encap_present) { 15064 BCM_IF_ERROR_RETURN 15065 (_bcm_egr_mirror_encap_entry_delete(unit, encap_index)); 15066 } 15067 } 15068 #endif /* BCM_GREYHOUND_SUPPORT */ 15069 return (BCM_E_NONE); 15070 } 15071 #endif /* BCM_FIREBOLT_SUPPORT */ 15072 15073 /* 15074 * Function: 15075 * _bcm_xgs3_mtp_reset 15076 * Purpose: 15077 * Reset mirror target port for XGS3 devices. 15078 * Parameters: 15079 * unit - (IN)BCM device number 15080 * index - (IN)Mtp index. 15081 * flags - (IN)Filled entry flags(BCM_MIRROR_PORT_INGRESS/EGRESS 15082 * Returns: 15083 * BCM_E_XXX 15084 */ 15085 STATIC int 15086 _bcm_xgs3_mtp_reset(int unit, int index, int flags) 15087 { 15088 int rv = BCM_E_UNAVAIL; /* Operation return status. */ 15089 #if defined(BCM_TRIDENT_SUPPORT) 15090 if (soc_feature(unit, soc_feature_mirror_control_mem)) { 15091 return _bcm_td_mtp_reset(unit, index, flags); 15092 } 15093 #endif 15094 #if defined(BCM_FIREBOLT_SUPPORT) 15095 if (SOC_IS_FBX(unit)) { 15096 rv = _bcm_fbx_mtp_reset(unit, index, flags); 15097 } 15098 #endif /* BCM_FIREBOLT_SUPPORT */ 15099 return rv; 15100 } 15101 15102 15103 /* 15104 * Function: 15105 * _bcm_xgs3_mtp_init 15106 * Purpose: 15107 * Initialize mirror target port for XGS3 devices. 15108 * Parameters: 15109 * unit - (IN)BCM device number 15110 * index - (IN)Mtp index. 15111 * flags - (IN)Filled entry flags(BCM_MIRROR_PORT_INGRESS/EGRESS 15112 * or both. In case both flags are specied 15113 * ingress & egress configuration is assumed to be 15114 * idential. 15115 * Returns: 15116 * BCM_E_XXX 15117 */ 15118 STATIC int 15119 _bcm_xgs3_mtp_init(int unit, int index, int flags) 15120 { 15121 _bcm_mtp_config_p mtp_cfg; 15122 /* Initialized to 0's to turn off false coverity alarm */ 15123 bcm_gport_t gport[BCM_SWITCH_TRUNK_MAX_PORTCNT] = {0}; 15124 bcm_gport_t mirror_dest; 15125 int idx; 15126 int rv = BCM_E_UNAVAIL; 15127 int active_member_count = 0; 15128 bcm_trunk_member_t active_member_array[BCM_SWITCH_TRUNK_MAX_PORTCNT]; 15129 #ifdef BCM_TRIDENT2_SUPPORT 15130 int mir_dest_flag = 0; 15131 #endif /* BCM_TRIDENT2_SUPPORT */ 15132 15133 mtp_cfg = MIRROR_CONFIG_MTP(unit, index, flags); 15134 15135 /* Destination port/trunk id validation. */ 15136 mirror_dest = MIRROR_DEST_GPORT(unit, mtp_cfg->dest_id); 15137 #ifdef BCM_TRIDENT2_SUPPORT 15138 mir_dest_flag = (MIRROR_DEST(unit, mtp_cfg->dest_id))->flags; 15139 #endif /* BCM_TRIDENT2_SUPPORT */ 15140 #ifdef BCM_TOMAHAWK3_SUPPORT 15141 if (SOC_IS_TOMAHAWK3(unit)) { 15142 /* Precautionary check to make sure mirroring port is not a trunk */ 15143 if (BCM_GPORT_IS_TRUNK(mirror_dest)) { 15144 return BCM_E_UNAVAIL; 15145 } 15146 } 15147 #endif /* BCM_TOMAHAWK3_SUPPORT */ 15148 15149 if (BCM_GPORT_IS_TRUNK(mirror_dest)) { 15150 rv = _bcm_trunk_id_validate(unit, BCM_GPORT_TRUNK_GET(mirror_dest)); 15151 if (BCM_FAILURE(rv)) { 15152 return (BCM_E_PORT); 15153 } 15154 15155 /* get only active trunk members and the count */ 15156 rv = _bcm_esw_trunk_active_member_get(unit, 15157 BCM_GPORT_TRUNK_GET(mirror_dest), 15158 NULL, 15159 BCM_SWITCH_TRUNK_MAX_PORTCNT, 15160 active_member_array, 15161 &active_member_count); 15162 if (BCM_FAILURE(rv)) { 15163 return (BCM_E_PORT); 15164 } 15165 15166 if (0 < active_member_count) { 15167 /* Fill gport array with trunk member ports. */ 15168 for (idx = 0; idx < BCM_SWITCH_TRUNK_MAX_PORTCNT; idx++) { 15169 gport[idx] = 15170 active_member_array[idx % active_member_count].gport; 15171 } 15172 } /* else must pass along the trunk ID for zero member trunks */ 15173 } 15174 #ifdef BCM_TRIDENT2_SUPPORT 15175 else if(mir_dest_flag & BCM_MIRROR_DEST_ID_SHARE) { 15176 bcm_gport_t mir_dest_gport_array[BCM_SWITCH_TRUNK_MAX_PORTCNT] = {0}; 15177 int mir_dest_gport_count = 0; 15178 bcm_module_t modid; 15179 bcm_port_t port; 15180 bcm_trunk_t tgid; 15181 int id; 15182 15183 BCM_IF_ERROR_RETURN( 15184 _bcm_mirror_dest_mtp_gport_get(unit, 15185 mtp_cfg->dest_id, 15186 mir_dest_gport_array, 15187 &mir_dest_gport_count)); 15188 if (mir_dest_gport_count <= 0) { 15189 return BCM_E_INIT; 15190 } 15191 15192 /* Check ports are valid */ 15193 for (idx = 0; idx < mir_dest_gport_count; idx++) { 15194 BCM_IF_ERROR_RETURN( 15195 _bcm_esw_gport_resolve(unit, mir_dest_gport_array[idx], 15196 &modid, &port, &tgid, &id)); 15197 15198 if ((-1 != id) || (BCM_TRUNK_INVALID != tgid)) { 15199 return BCM_E_PORT; 15200 } 15201 if (!SOC_MODID_ADDRESSABLE(unit, modid)) { 15202 return (BCM_E_BADID); 15203 } 15204 if (!SOC_PORT_ADDRESSABLE(unit, port)) { 15205 return (BCM_E_PORT); 15206 } 15207 } 15208 15209 /* Fill gport array with destination port */ 15210 for (idx = 0; idx < BCM_SWITCH_TRUNK_MAX_PORTCNT; idx++) { 15211 gport[idx] = 15212 mir_dest_gport_array[idx % mir_dest_gport_count]; 15213 } 15214 } 15215 #endif /* BCM_TRIDENT2_SUPPORT */ 15216 else { 15217 bcm_module_t modid; 15218 bcm_port_t port; 15219 bcm_trunk_t tgid; 15220 int id; 15221 15222 BCM_IF_ERROR_RETURN( 15223 _bcm_esw_gport_resolve(unit, mirror_dest, &modid, 15224 &port, &tgid, &id)); 15225 15226 #if defined(BCM_HGPROXY_COE_SUPPORT) 15227 if (soc_feature(unit, soc_feature_hgproxy_subtag_coe) && 15228 BCM_GPORT_IS_SET(mirror_dest) && 15229 _BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT (unit, 15230 mirror_dest)) { 15231 } else 15232 #endif 15233 15234 #if defined(BCM_KATANA2_SUPPORT) 15235 if (BCM_GPORT_IS_SET(mirror_dest) && 15236 _BCM_KT2_GPORT_IS_LINKPHY_OR_SUBTAG_SUBPORT_GPORT (unit, 15237 mirror_dest)) { 15238 } else 15239 #endif 15240 { 15241 if ((-1 != id) || (BCM_TRUNK_INVALID != tgid)) { 15242 return BCM_E_PORT; 15243 } 15244 } 15245 15246 if (!SOC_MODID_ADDRESSABLE(unit, modid)) { 15247 return (BCM_E_BADID); 15248 } 15249 if (!SOC_PORT_ADDRESSABLE(unit, port)) { 15250 return (BCM_E_PORT); 15251 } 15252 #ifdef BCM_TOMAHAWK3_SUPPORT 15253 /* For Tomahawk3, EGR_IM_MTP_INDEX, EGR_EM_MTP_INDEX only have 4 entries 15254 * deep, one per MTP (as opposed to 32 entries, 8 per MTP in other 15255 * devices). We will use gport[0] only in _bcm_trident_mtp_init 15256 */ 15257 #endif /* BCM_TOMAHAWK3_SUPPORT */ 15258 15259 /* Fill gport array with destination port only. */ 15260 for (idx = 0; idx < BCM_SWITCH_TRUNK_MAX_PORTCNT; idx++) { 15261 gport[idx] = mirror_dest; 15262 } 15263 } 15264 #if defined(BCM_TRIDENT_SUPPORT) 15265 if (soc_feature(unit, soc_feature_mirror_control_mem)) { 15266 return _bcm_trident_mtp_init(unit, index, gport, flags); 15267 } 15268 #endif 15269 #if defined(BCM_FIREBOLT_SUPPORT) 15270 if (SOC_IS_FBX(unit)) { 15271 rv = _bcm_fbx_mtp_init(unit, index, gport, flags); 15272 } 15273 #endif /* BCM_FIREBOLT_SUPPORT */ 15274 return rv; 15275 } 15276 15277 #if defined(BCM_TRIUMPH2_SUPPORT) || defined(BCM_TRIDENT_SUPPORT) 15278 /* 15279 * Function: 15280 * _bcm_tr2_mirror_trunk_update 15281 * Description: 15282 * Update mtp programming based on trunk port membership. 15283 * Parameters: 15284 * unit - (IN) BCM device number 15285 * tid - (IN) Trunk id. 15286 * Returns: 15287 * BCM_E_XXX 15288 */ 15289 STATIC int 15290 _bcm_tr2_mirror_trunk_update(int unit, bcm_trunk_t tid) 15291 { 15292 int idx; /* Mtp iteration index. */ 15293 bcm_gport_t gport; /* Mirror destination. */ 15294 bcm_gport_t mirror_dest_id; /* Mirror destination. */ 15295 int rv = BCM_E_NONE; /* Operation return status. */ 15296 int egress; /* Mirror ingress/egres */ 15297 15298 /* Initilize mirror destination. */ 15299 BCM_GPORT_TRUNK_SET(gport, tid); 15300 15301 MIRROR_LOCK(unit); 15302 /* Ingress mirroring destions update */ 15303 if (soc_feature(unit, soc_feature_mirror_flexible) && 15304 !MIRROR_MTP_METHOD_IS_DIRECTED_FLEXIBLE(unit)) { 15305 for (idx = 0; idx < BCM_MIRROR_MTP_COUNT; idx++) { 15306 if (MIRROR_CONFIG_SHARED_MTP_REF_COUNT(unit, idx)) { 15307 mirror_dest_id = MIRROR_CONFIG_SHARED_MTP_DEST(unit, idx); 15308 egress = MIRROR_CONFIG_SHARED_MTP(unit, idx).egress; 15309 if (MIRROR_DEST_GPORT(unit, mirror_dest_id) == gport) { 15310 rv = _bcm_xgs3_mtp_init(unit, idx, (TRUE == egress) ? 15311 BCM_MIRROR_PORT_EGRESS : 15312 BCM_MIRROR_PORT_INGRESS); 15313 if (BCM_FAILURE(rv)) { 15314 break; 15315 } 15316 } 15317 } 15318 } 15319 } else { 15320 /* Check all used ingress mirror destinations. */ 15321 for (idx = 0; idx < MIRROR_CONFIG(unit)->ing_mtp_count; idx++) { 15322 if (MIRROR_CONFIG_ING_MTP_REF_COUNT(unit, idx)) { 15323 mirror_dest_id = MIRROR_CONFIG_ING_MTP_DEST(unit, idx); 15324 if (MIRROR_DEST_GPORT(unit, mirror_dest_id) == gport) { 15325 rv = _bcm_xgs3_mtp_init(unit, idx, 15326 BCM_MIRROR_PORT_INGRESS); 15327 if (BCM_FAILURE(rv)) { 15328 break; 15329 } 15330 } 15331 } 15332 } 15333 15334 if (BCM_SUCCESS(rv)) { 15335 /* Check all used egress mirror destinations. */ 15336 for (idx = 0; idx < MIRROR_CONFIG(unit)->egr_mtp_count; idx++) { 15337 if (MIRROR_CONFIG_EGR_MTP_REF_COUNT(unit, idx)) { 15338 mirror_dest_id = MIRROR_CONFIG_EGR_MTP_DEST(unit, idx); 15339 if (MIRROR_DEST_GPORT(unit, mirror_dest_id) == gport) { 15340 rv = _bcm_xgs3_mtp_init(unit, idx, 15341 BCM_MIRROR_PORT_EGRESS); 15342 if (BCM_FAILURE(rv)) { 15343 break; 15344 } 15345 } 15346 } 15347 } 15348 } 15349 } 15350 15351 /* True egress mirroring destinations update */ 15352 if (BCM_SUCCESS(rv) && 15353 soc_feature(unit, soc_feature_egr_mirror_true)) { 15354 for (idx = 0; idx < MIRROR_CONFIG(unit)->egr_true_mtp_count; idx++) { 15355 if (MIRROR_CONFIG_EGR_TRUE_MTP_REF_COUNT(unit, idx)) { 15356 mirror_dest_id = MIRROR_CONFIG_EGR_TRUE_MTP_DEST(unit, idx); 15357 if (MIRROR_DEST_GPORT(unit, mirror_dest_id) == gport) { 15358 rv = _bcm_xgs3_mtp_init(unit, idx, 15359 BCM_MIRROR_PORT_EGRESS_TRUE); 15360 if (BCM_FAILURE(rv)) { 15361 break; 15362 } 15363 } 15364 } 15365 } 15366 } 15367 15368 MIRROR_UNLOCK(unit); 15369 return (rv); 15370 } 15371 #endif /* BCM_TRIUMPH2_SUPPORT || BCM_TRIDENT_SUPPORT */ 15372 15373 /* 15374 * Function: 15375 * _bcm_xgs3_mirror_trunk_update 15376 * Description: 15377 * Update mtp programming based on trunk port membership. 15378 * Parameters: 15379 * unit - (IN) BCM device number 15380 * tid - (IN) Trunk id. 15381 * Returns: 15382 * BCM_E_XXX 15383 */ 15384 int 15385 _bcm_xgs3_mirror_trunk_update(int unit, bcm_trunk_t tid) 15386 { 15387 int idx; /* Mtp iteration index. */ 15388 bcm_gport_t gport; /* Mirror destination. */ 15389 bcm_gport_t mirror_dest_id; /* Mirror destination. */ 15390 int rv = BCM_E_NONE; /* Operation return status. */ 15391 15392 /* Check if mirroring enabled on the device. */ 15393 if (!MIRROR_INIT(unit)) { 15394 return BCM_E_INIT; 15395 } 15396 #if defined(BCM_TRIUMPH2_SUPPORT) || defined(BCM_TRIDENT_SUPPORT) 15397 if (soc_feature(unit, soc_feature_mirror_flexible)) { 15398 return _bcm_tr2_mirror_trunk_update(unit, tid); 15399 } 15400 #endif /* BCM_TRIUMPH2_SUPPORT */ 15401 15402 /* Initilize mirror destination. */ 15403 BCM_GPORT_TRUNK_SET(gport, tid); 15404 15405 MIRROR_LOCK(unit); 15406 /* Ingress mirroring destions update */ 15407 for (idx = 0; idx < MIRROR_CONFIG(unit)->ing_mtp_count; idx++) { 15408 if (MIRROR_CONFIG_ING_MTP_REF_COUNT(unit, idx)) { 15409 mirror_dest_id = MIRROR_CONFIG_ING_MTP_DEST(unit, idx); 15410 if (MIRROR_DEST_GPORT(unit, mirror_dest_id) == gport) { 15411 rv = _bcm_xgs3_mtp_init(unit, idx, BCM_MIRROR_PORT_INGRESS); 15412 if (BCM_FAILURE(rv)) { 15413 MIRROR_UNLOCK(unit); 15414 return (rv); 15415 } 15416 } 15417 } 15418 } 15419 15420 /* Egress mirroring destinations update */ 15421 for (idx = 0; idx < MIRROR_CONFIG(unit)->egr_mtp_count; idx++) { 15422 if (MIRROR_CONFIG_EGR_MTP_REF_COUNT(unit, idx)) { 15423 mirror_dest_id = MIRROR_CONFIG_EGR_MTP_DEST(unit, idx); 15424 if (MIRROR_DEST_GPORT(unit, mirror_dest_id) == gport) { 15425 rv = _bcm_xgs3_mtp_init(unit, idx, BCM_MIRROR_PORT_EGRESS); 15426 if (BCM_FAILURE(rv)) { 15427 break; 15428 } 15429 } 15430 } 15431 } 15432 15433 MIRROR_UNLOCK(unit); 15434 return (rv); 15435 } 15436 15437 /* 15438 * Function: 15439 * _bcm_tr2_mirror_ingress_mtp_reserve 15440 * Description: 15441 * Reserve a mirror-to port for Triumph2 like devices 15442 * Parameters: 15443 * unit - (IN) BCM device number 15444 * dest_id - (IN) Mirror destination id. 15445 * index_used - (OUT) MTP index reserved 15446 * Returns: 15447 * BCM_E_XXX 15448 * Notes: 15449 * If the a mirror-to port is reserved more than once 15450 * (without being unreserved) then the same MTP index 15451 * will be returned for each call. 15452 */ 15453 STATIC int 15454 _bcm_tr2_mirror_ingress_mtp_reserve(int unit, bcm_gport_t dest_id, 15455 int *index_used) 15456 { 15457 int rv; 15458 int idx = _BCM_MIRROR_INVALID_MTP; 15459 int rspan = FALSE; 15460 uint32 flags = 0; 15461 #if defined(BCM_TRIDENT_SUPPORT) 15462 bcm_mirror_destination_t mdest; /* Mirror destination info. */ 15463 #endif /* BCM_TRIDENT_SUPPORT */ 15464 15465 #if defined(BCM_TRIDENT_SUPPORT) 15466 if (soc_feature(unit, soc_feature_mirror_encap_profile)) { 15467 15468 /* Get mirror destination descriptor. */ 15469 BCM_IF_ERROR_RETURN 15470 (bcm_esw_mirror_destination_get(unit, dest_id, &mdest)); 15471 15472 rspan = (0 != (mdest.flags & BCM_MIRROR_DEST_TUNNEL_L2)); 15473 flags = mdest.flags; 15474 } 15475 #endif /* BCM_TRIDENT_SUPPORT */ 15476 15477 /* Look for existing MTP in use */ 15478 rv = _bcm_tr2_mirror_shared_mtp_match(unit, dest_id, FALSE, &idx); 15479 if (BCM_SUCCESS(rv)) { 15480 #ifdef BCM_TRIDENT2_SUPPORT 15481 if (flags & BCM_MIRROR_DEST_ID_SHARE) { 15482 /* 15483 * Add MTP ref_count here and ref_count can be adjusted later. 15484 * No matter update or add, always refresh H/W. 15485 */ 15486 MIRROR_CONFIG_SHARED_MTP_REF_COUNT(unit, idx)++; 15487 } else 15488 #endif /* BCM_TRIDENT2_SUPPORT */ 15489 { 15490 MIRROR_CONFIG_SHARED_MTP_REF_COUNT(unit, idx)++; 15491 if (!(flags & BCM_MIRROR_DEST_REPLACE)) { 15492 *index_used = idx; 15493 return (rv); 15494 } 15495 } 15496 } 15497 15498 if (idx == _BCM_MIRROR_INVALID_MTP) { 15499 /* Reserve free index */ 15500 for (idx = 0; idx < BCM_MIRROR_MTP_COUNT; idx++) { 15501 if (0 == MIRROR_CONFIG_SHARED_MTP_REF_COUNT(unit, idx)) { 15502 if (soc_feature(unit, soc_feature_mirror_rspan_no_mtp0) && 15503 rspan && (0 == idx)) { 15504 /* Do not use MTP 0 for RSPAN on Trident 15505 * and later devices */ 15506 continue; 15507 } 15508 break; 15509 } 15510 } 15511 } 15512 15513 if (idx < BCM_MIRROR_MTP_COUNT) { 15514 if (BCM_FAILURE(rv)) { 15515 /* Mark mtp as used. */ 15516 MIRROR_CONFIG_SHARED_MTP_DEST(unit, idx) = dest_id; 15517 MIRROR_CONFIG_SHARED_MTP_REF_COUNT(unit, idx)++; 15518 MIRROR_CONFIG_SHARED_MTP(unit, idx).egress = FALSE; 15519 MIRROR_DEST_REF_COUNT(unit, dest_id)++; 15520 } 15521 15522 /* Write MTP registers */ 15523 rv = _bcm_xgs3_mtp_init(unit, idx, BCM_MIRROR_PORT_INGRESS); 15524 if (BCM_FAILURE(rv)) { 15525 MIRROR_CONFIG_SHARED_MTP_DEST(unit, idx) = BCM_GPORT_INVALID; 15526 MIRROR_CONFIG_SHARED_MTP_REF_COUNT(unit, idx) = 0; 15527 if (MIRROR_DEST_REF_COUNT(unit, dest_id) > 0) { 15528 MIRROR_DEST_REF_COUNT(unit, dest_id)--; 15529 } 15530 } else { 15531 if (SOC_REG_FIELD_VALID(unit, MIRROR_SELECTr, MTP_TYPEf)) { 15532 uint32 rval, fval; 15533 BCM_IF_ERROR_RETURN(READ_MIRROR_SELECTr(unit, &rval)); 15534 fval = soc_reg_field_get(unit, MIRROR_SELECTr, rval, MTP_TYPEf); 15535 fval &= ~(1 << idx); 15536 soc_reg_field_set(unit, MIRROR_SELECTr, &rval, MTP_TYPEf, fval); 15537 BCM_IF_ERROR_RETURN(WRITE_MIRROR_SELECTr(unit, rval)); 15538 if (SOC_REG_FIELD_VALID(unit, EGR_MIRROR_SELECTr, MTP_TYPEf)) { 15539 #if defined(BCM_TRIDENT3_SUPPORT) 15540 if (mdest.flags2 & BCM_MIRROR_DEST_FLAGS2_IFA) { 15541 /* special handling, set egress mirroring in egress */ 15542 BCM_IF_ERROR_RETURN(READ_EGR_MIRROR_SELECTr(unit, &rval)); 15543 fval = soc_reg_field_get(unit, EGR_MIRROR_SELECTr, rval, 15544 MTP_TYPEf); 15545 fval |= (1 << idx); 15546 soc_reg_field_set(unit, MIRROR_SELECTr, &rval, MTP_TYPEf, 15547 fval); 15548 } 15549 #endif 15550 BCM_IF_ERROR_RETURN(WRITE_EGR_MIRROR_SELECTr(unit, rval)); 15551 } 15552 } 15553 15554 } 15555 *index_used = idx; 15556 } else { 15557 rv = BCM_E_RESOURCE; 15558 } 15559 return (rv); 15560 } 15561 15562 /* 15563 * Function: 15564 * _bcm_xgs3_mirror_ingress_mtp_reserve 15565 * Description: 15566 * Reserve a mirror-to port 15567 * Parameters: 15568 * unit - (IN) BCM device number 15569 * dest_id - (IN) Mirror destination id. 15570 * index_used - (OUT) MTP index reserved 15571 * Returns: 15572 * BCM_E_XXX 15573 * Notes: 15574 * If the a mirror-to port is reserved more than once 15575 * (without being unreserved) then the same MTP index 15576 * will be returned for each call. 15577 */ 15578 STATIC int 15579 _bcm_xgs3_mirror_ingress_mtp_reserve(int unit, bcm_gport_t dest_id, 15580 int *index_used) 15581 { 15582 int rv; /* Operation return status. */ 15583 int idx = _BCM_MIRROR_INVALID_MTP; /* Mtp iteration index. */ 15584 int rspan = FALSE; 15585 uint32 flags = 0; 15586 bcm_mirror_destination_t mdest; /* Mirror destination info. */ 15587 15588 /* Input parameters check. */ 15589 if (NULL == index_used) { 15590 return (BCM_E_PARAM); 15591 } 15592 15593 if (soc_feature(unit, soc_feature_mirror_flexible) && 15594 !MIRROR_MTP_METHOD_IS_DIRECTED_FLEXIBLE(unit)) { 15595 return _bcm_tr2_mirror_ingress_mtp_reserve(unit, dest_id, index_used); 15596 } 15597 /* Get mirror destination descriptor. */ 15598 BCM_IF_ERROR_RETURN 15599 (bcm_esw_mirror_destination_get(unit, dest_id, &mdest)); 15600 flags = mdest.flags; 15601 15602 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_GREYHOUND_SUPPORT) 15603 if (soc_feature(unit, soc_feature_mirror_encap_profile)) { 15604 rspan = (0 != (mdest.flags & BCM_MIRROR_DEST_TUNNEL_L2)); 15605 } 15606 #endif /* BCM_TRIDENT_SUPPORT || BCM_GREYHOUND_SUPPORT */ 15607 15608 /* Look for existing MTP in use */ 15609 rv = _bcm_esw_mirror_ingress_mtp_match(unit, dest_id, &idx); 15610 if (BCM_SUCCESS(rv)) { 15611 #ifdef BCM_TRIDENT2_SUPPORT 15612 if (flags & BCM_MIRROR_DEST_ID_SHARE) { 15613 /* 15614 * Add MTP ref_count here and ref_count can be adjusted later. 15615 * No matter update or add, always refresh H/W. 15616 */ 15617 MIRROR_CONFIG_ING_MTP_REF_COUNT(unit, idx)++; 15618 } else 15619 #endif /* BCM_TRIDENT2_SUPPORT */ 15620 { 15621 MIRROR_CONFIG_ING_MTP_REF_COUNT(unit, idx)++; 15622 if (!(flags & BCM_MIRROR_DEST_REPLACE)) { 15623 *index_used = idx; 15624 return (rv); 15625 } 15626 } 15627 } 15628 15629 if (idx == _BCM_MIRROR_INVALID_MTP) { 15630 /* Reserve free index */ 15631 for (idx = 0; idx < MIRROR_CONFIG(unit)->ing_mtp_count; idx++) { 15632 if (0 == MIRROR_CONFIG_ING_MTP_REF_COUNT(unit, idx)) { 15633 if (soc_feature(unit, soc_feature_mirror_rspan_no_mtp0) && 15634 rspan && (0 == idx)) { 15635 /* Do not use MTP 0 for RSPAN on Trident 15636 * and later devices */ 15637 continue; 15638 } 15639 break; 15640 } 15641 } 15642 } 15643 15644 if (idx < MIRROR_CONFIG(unit)->ing_mtp_count) { 15645 if (BCM_FAILURE(rv)) { 15646 /* Mark mtp as used. */ 15647 MIRROR_CONFIG_ING_MTP_DEST(unit, idx) = dest_id; 15648 MIRROR_CONFIG_ING_MTP_REF_COUNT(unit, idx)++; 15649 MIRROR_DEST_REF_COUNT(unit, dest_id)++; 15650 } 15651 15652 /* Write MTP registers */ 15653 rv = _bcm_xgs3_mtp_init(unit, idx, BCM_MIRROR_PORT_INGRESS); 15654 if (BCM_FAILURE(rv)) { 15655 MIRROR_CONFIG_ING_MTP_DEST(unit, idx) = BCM_GPORT_INVALID; 15656 MIRROR_CONFIG_ING_MTP_REF_COUNT(unit, idx) = 0; 15657 if (MIRROR_DEST_REF_COUNT(unit, dest_id) > 0) { 15658 MIRROR_DEST_REF_COUNT(unit, dest_id)--; 15659 } 15660 } 15661 *index_used = idx; 15662 } else { 15663 rv = BCM_E_RESOURCE; 15664 } 15665 15666 return (rv); 15667 } 15668 15669 /* 15670 * Function: 15671 * _bcm_tr2_mirror_egress_mtp_reserve 15672 * Description: 15673 * Reserve a mirror-to port for Triumph2 like devices 15674 * Parameters: 15675 * unit - (IN) BCM device number 15676 * dest_id - (IN) Mirror destination id. 15677 * is_port - (IN) Reservation is for port based mirror 15678 * index_used - (OUT) MTP index reserved 15679 * Returns: 15680 * BCM_E_XXX 15681 * Notes: 15682 * If the a mirror-to port is reserved more than once 15683 * (without being unreserved) then the same MTP index 15684 * will be returned for each call. 15685 */ 15686 STATIC int 15687 _bcm_tr2_mirror_egress_mtp_reserve(int unit, bcm_gport_t dest_id, 15688 int is_port, int *index_used) 15689 { 15690 int port_limit = 0; 15691 int rv; 15692 int idx = _BCM_MIRROR_INVALID_MTP; 15693 int rspan = FALSE; 15694 uint32 flags = 0; 15695 15696 #if defined(BCM_TRIDENT_SUPPORT) 15697 if (soc_feature(unit, soc_feature_mirror_encap_profile)) { 15698 bcm_mirror_destination_t mdest; /* Mirror destination info. */ 15699 15700 /* Get mirror destination descriptor. */ 15701 BCM_IF_ERROR_RETURN 15702 (bcm_esw_mirror_destination_get(unit, dest_id, &mdest)); 15703 15704 rspan = (0 != (mdest.flags & BCM_MIRROR_DEST_TUNNEL_L2)); 15705 flags = mdest.flags; 15706 } 15707 #endif /* BCM_TRIDENT_SUPPORT */ 15708 15709 /* Look for existing MTP in use */ 15710 rv = _bcm_tr2_mirror_shared_mtp_match(unit, dest_id, TRUE, &idx); 15711 if (BCM_SUCCESS(rv)) { 15712 #ifdef BCM_TRIDENT2_SUPPORT 15713 if (flags & BCM_MIRROR_DEST_ID_SHARE) { 15714 /* 15715 * Add MTP ref_count here and ref_count can be adjusted later. 15716 * No matter update or add, always refresh H/W. 15717 */ 15718 if (is_port) { 15719 MIRROR_CONFIG_SHARED_MTP_REF_COUNT(unit, idx)++; 15720 } else { 15721 MIRROR_CONFIG_SHARED_MTP_REF_COUNT(unit, idx) += 15722 (1 << BCM_MIRROR_MTP_REF_FP_OFFSET); 15723 } 15724 } else 15725 #endif /* BCM_TRIDENT2_SUPPORT */ 15726 { 15727 if (is_port) { 15728 MIRROR_CONFIG_SHARED_MTP_REF_COUNT(unit, idx)++; 15729 } else { 15730 MIRROR_CONFIG_SHARED_MTP_REF_COUNT(unit, idx) += 15731 (1 << BCM_MIRROR_MTP_REF_FP_OFFSET); 15732 } 15733 if (!(flags & BCM_MIRROR_DEST_REPLACE)) { 15734 *index_used = idx; 15735 return (rv); 15736 } 15737 } 15738 } 15739 15740 if (idx == _BCM_MIRROR_INVALID_MTP) { 15741 /* Reserve free index */ 15742 if (MIRROR_CONFIG(unit)->port_em_mtp_count > 1) { 15743 for (idx = 0; idx < BCM_MIRROR_MTP_COUNT; idx++) { 15744 if (is_port && 15745 (MIRROR_CONFIG_SHARED_MTP_REF_COUNT(unit, idx) & 15746 BCM_MIRROR_MTP_REF_PORT_MASK) && 15747 (TRUE == MIRROR_CONFIG_SHARED_MTP(unit, idx).egress)) { 15748 port_limit++; 15749 if (port_limit > MIRROR_CONFIG(unit)->port_em_mtp_count) { 15750 return (BCM_E_RESOURCE); 15751 } 15752 } 15753 if (0 == MIRROR_CONFIG_SHARED_MTP_REF_COUNT(unit, idx)) { 15754 if (soc_feature(unit, soc_feature_mirror_rspan_no_mtp0) && 15755 rspan && (0 == idx)) { 15756 /* Do not use MTP 0 for RSPAN on Trident 15757 * and later devices */ 15758 continue; 15759 } 15760 break; 15761 } 15762 } 15763 } else { 15764 /* Not directed mirroring mode */ 15765 if (0 != MIRROR_CONFIG_SHARED_MTP_REF_COUNT(unit, 15766 BCM_MIRROR_MTP_FLEX_EGRESS_D15_INDEX)) { 15767 return (BCM_E_RESOURCE); 15768 } else { 15769 idx = BCM_MIRROR_MTP_FLEX_EGRESS_D15_INDEX; 15770 } 15771 } 15772 } 15773 15774 if (idx < BCM_MIRROR_MTP_COUNT) { 15775 if (BCM_FAILURE(rv)) { 15776 /* Mark mtp as used. */ 15777 MIRROR_CONFIG_SHARED_MTP_DEST(unit, idx) = dest_id; 15778 if (is_port) { 15779 MIRROR_CONFIG_SHARED_MTP_REF_COUNT(unit, idx)++; 15780 } else { 15781 MIRROR_CONFIG_SHARED_MTP_REF_COUNT(unit, idx) += 15782 (1 << BCM_MIRROR_MTP_REF_FP_OFFSET); 15783 } 15784 MIRROR_CONFIG_SHARED_MTP(unit, idx).egress = TRUE; 15785 MIRROR_DEST_REF_COUNT(unit, dest_id)++; 15786 } 15787 15788 /* Write MTP registers */ 15789 rv = _bcm_xgs3_mtp_init(unit, idx, BCM_MIRROR_PORT_EGRESS); 15790 if (BCM_FAILURE(rv)) { 15791 MIRROR_CONFIG_SHARED_MTP_DEST(unit, idx) = BCM_GPORT_INVALID; 15792 MIRROR_CONFIG_SHARED_MTP_REF_COUNT(unit, idx) = 0; 15793 if (MIRROR_DEST_REF_COUNT(unit, dest_id) > 0) { 15794 MIRROR_DEST_REF_COUNT(unit, dest_id)--; 15795 } 15796 } else { 15797 if (SOC_REG_FIELD_VALID(unit, MIRROR_SELECTr, MTP_TYPEf)) { 15798 uint32 rval, fval; 15799 BCM_IF_ERROR_RETURN(READ_MIRROR_SELECTr(unit, &rval)); 15800 fval = soc_reg_field_get(unit, MIRROR_SELECTr, rval, MTP_TYPEf); 15801 fval |= (1 << idx); 15802 soc_reg_field_set(unit, MIRROR_SELECTr, &rval, MTP_TYPEf, fval); 15803 BCM_IF_ERROR_RETURN(WRITE_MIRROR_SELECTr(unit, rval)); 15804 #ifdef BCM_TOMAHAWK_SUPPORT 15805 if (SOC_INFO(unit).th_tflow_enabled == 1) { 15806 /* All MTPs in the EGR_MIRROR_SELECT control 15807 * should be configured as ingress. 15808 */ 15809 rval = 0; 15810 } 15811 #endif /* BCM_TOMAHAWK_SUPPORT */ 15812 if (SOC_REG_FIELD_VALID(unit, EGR_MIRROR_SELECTr, MTP_TYPEf)) { 15813 BCM_IF_ERROR_RETURN(WRITE_EGR_MIRROR_SELECTr(unit, rval)); 15814 } 15815 } 15816 15817 } 15818 *index_used = idx; 15819 } else { 15820 rv = BCM_E_RESOURCE; 15821 } 15822 return (rv); 15823 } 15824 15825 /* 15826 * Function: 15827 * _bcm_xgs3_mirror_egress_mtp_reserve 15828 * Description: 15829 * Reserve a mirror-to port 15830 * Parameters: 15831 * unit - (IN) BCM device number 15832 * dest_id - (IN) Mirror destination id. 15833 * is_port - (IN) Reservation is for port based mirror 15834 * index_used - (OUT) MTP index reserved 15835 * Returns: 15836 * BCM_E_XXX 15837 * Notes: 15838 * If the a mirror-to port is reserved more than once 15839 * (without being unreserved) then the same MTP index 15840 * will be returned for each call. 15841 */ 15842 STATIC int 15843 _bcm_xgs3_mirror_egress_mtp_reserve(int unit, bcm_gport_t dest_id, int is_port, 15844 int *index_used) 15845 { 15846 int rv; /* Operation return status.*/ 15847 int idx = _BCM_MIRROR_INVALID_MTP; /* Mtp iteration index. */ 15848 int port_limit = 0; /* How many mtp in use by port based mirroring */ 15849 int rspan = FALSE; 15850 uint32 flags = 0; 15851 bcm_mirror_destination_t mdest; /* Mirror destination info. */ 15852 15853 /* Input parameters check. */ 15854 if (NULL == index_used) { 15855 return (BCM_E_PARAM); 15856 } 15857 15858 if (soc_feature(unit, soc_feature_mirror_flexible) && 15859 !MIRROR_MTP_METHOD_IS_DIRECTED_FLEXIBLE(unit)) { 15860 return _bcm_tr2_mirror_egress_mtp_reserve(unit, dest_id, is_port, 15861 index_used); 15862 } 15863 15864 /* Get mirror destination descriptor. */ 15865 BCM_IF_ERROR_RETURN 15866 (bcm_esw_mirror_destination_get(unit, dest_id, &mdest)); 15867 flags = mdest.flags; 15868 15869 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_GREYHOUND_SUPPORT) 15870 if (soc_feature(unit, soc_feature_mirror_encap_profile)) { 15871 rspan = (0 != (mdest.flags & BCM_MIRROR_DEST_TUNNEL_L2)); 15872 } 15873 #endif /* BCM_TRIDENT_SUPPORT || BCM_GREYHOUND_SUPPORT */ 15874 15875 /* Look for existing MTP in use */ 15876 rv = _bcm_esw_mirror_egress_mtp_match(unit, dest_id, &idx); 15877 if (BCM_SUCCESS(rv)) { 15878 #ifdef BCM_TRIDENT2_SUPPORT 15879 if (flags & BCM_MIRROR_DEST_ID_SHARE) { 15880 /* 15881 * Add MTP ref_count here and ref_count can be adjusted later. 15882 * No matter update or add, always refresh H/W. 15883 */ 15884 if (is_port) { 15885 MIRROR_CONFIG_EGR_MTP_REF_COUNT(unit, idx)++; 15886 } else { 15887 MIRROR_CONFIG_EGR_MTP_REF_COUNT(unit, idx) += 15888 (1 << BCM_MIRROR_MTP_REF_FP_OFFSET); 15889 } 15890 } else 15891 #endif /* BCM_TRIDENT2_SUPPORT */ 15892 { 15893 if (is_port) { 15894 MIRROR_CONFIG_EGR_MTP_REF_COUNT(unit, idx)++; 15895 } else { 15896 MIRROR_CONFIG_EGR_MTP_REF_COUNT(unit, idx) += 15897 (1 << BCM_MIRROR_MTP_REF_FP_OFFSET); 15898 } 15899 if (!(flags & BCM_MIRROR_DEST_REPLACE)) { 15900 *index_used = idx; 15901 return (rv); 15902 } 15903 } 15904 } 15905 15906 if (idx == _BCM_MIRROR_INVALID_MTP) { 15907 /* Reserve free index */ 15908 for (idx = 0; idx < MIRROR_CONFIG(unit)->egr_mtp_count; idx++) { 15909 if (is_port && 15910 (MIRROR_CONFIG_EGR_MTP_REF_COUNT(unit, idx) & 15911 BCM_MIRROR_MTP_REF_PORT_MASK)) { 15912 port_limit++; 15913 if (port_limit > MIRROR_CONFIG(unit)->port_em_mtp_count) { 15914 return (BCM_E_RESOURCE); 15915 } 15916 } 15917 if (0 == MIRROR_CONFIG_EGR_MTP_REF_COUNT(unit, idx)) { 15918 if (soc_feature(unit, soc_feature_mirror_rspan_no_mtp0) && 15919 rspan && (0 == idx)) { 15920 /* Do not use MTP 0 for RSPAN on Trident 15921 * and later devices */ 15922 continue; 15923 } 15924 break; 15925 } 15926 } 15927 } 15928 15929 if (idx < MIRROR_CONFIG(unit)->egr_mtp_count) { 15930 if (BCM_FAILURE(rv)) { 15931 /* Mark mtp as used. */ 15932 MIRROR_CONFIG_EGR_MTP_DEST(unit, idx) = dest_id; 15933 MIRROR_CONFIG_EGR_MTP(unit, idx).egress = 1; 15934 if (is_port) { 15935 MIRROR_CONFIG_EGR_MTP_REF_COUNT(unit, idx)++; 15936 } else { 15937 MIRROR_CONFIG_EGR_MTP_REF_COUNT(unit, idx) += 15938 (1 << BCM_MIRROR_MTP_REF_FP_OFFSET); 15939 } 15940 MIRROR_DEST_REF_COUNT(unit, dest_id)++; 15941 } 15942 15943 /* Write MTP registers */ 15944 rv = _bcm_xgs3_mtp_init(unit, idx, BCM_MIRROR_PORT_EGRESS); 15945 if (BCM_FAILURE(rv)) { 15946 MIRROR_CONFIG_EGR_MTP_DEST(unit, idx) = BCM_GPORT_INVALID; 15947 MIRROR_CONFIG_EGR_MTP_REF_COUNT(unit, idx) = 0; 15948 if (MIRROR_DEST_REF_COUNT(unit, dest_id) > 0) { 15949 MIRROR_DEST_REF_COUNT(unit, dest_id)--; 15950 } 15951 } 15952 *index_used = idx; 15953 } else { 15954 rv = BCM_E_RESOURCE; 15955 } 15956 15957 return (rv); 15958 } 15959 15960 #ifdef BCM_TRIUMPH2_SUPPORT 15961 /* 15962 * Function: 15963 * _bcm_xgs3_mirror_egress_true_mtp_reserve 15964 * Description: 15965 * Reserve a mirror-to port 15966 * Parameters: 15967 * unit - (IN) BCM device number 15968 * dest_id - (IN) Mirror destination id. 15969 * index_used - (OUT) MTP index reserved 15970 * Returns: 15971 * BCM_E_XXX 15972 * Notes: 15973 * If the a mirror-to port is reserved more than once 15974 * (without being unreserved) then the same MTP index 15975 * will be returned for each call. 15976 */ 15977 STATIC int 15978 _bcm_xgs3_mirror_egress_true_mtp_reserve(int unit, bcm_gport_t dest_id, 15979 int *index_used) 15980 { 15981 int rv; /* Operation return status.*/ 15982 int idx = _BCM_MIRROR_INVALID_MTP; /* Mtp iteration index. */ 15983 int rspan = FALSE; 15984 uint32 flags = 0; 15985 bcm_mirror_destination_t mdest; /* Mirror destination info. */ 15986 15987 /* Input parameters check. */ 15988 if (NULL == index_used) { 15989 return (BCM_E_PARAM); 15990 } 15991 15992 /* Get mirror destination descriptor. */ 15993 BCM_IF_ERROR_RETURN 15994 (bcm_esw_mirror_destination_get(unit, dest_id, &mdest)); 15995 flags = mdest.flags; 15996 15997 #if defined(BCM_TRIDENT_SUPPORT) 15998 if (soc_feature(unit, soc_feature_mirror_encap_profile)) { 15999 rspan = (0 != (mdest.flags & BCM_MIRROR_DEST_TUNNEL_L2)); 16000 } 16001 #endif /* BCM_TRIDENT_SUPPORT */ 16002 16003 /* Look for existing MTP in use */ 16004 rv = _bcm_esw_mirror_egress_true_mtp_match(unit, dest_id, &idx); 16005 if (BCM_SUCCESS(rv)) { 16006 MIRROR_CONFIG_EGR_TRUE_MTP_REF_COUNT(unit, idx)++; 16007 if (!(flags & BCM_MIRROR_DEST_REPLACE)) { 16008 *index_used = idx; 16009 return (rv); 16010 } 16011 } 16012 16013 if (idx == _BCM_MIRROR_INVALID_MTP) { 16014 /* Reserve free index */ 16015 for (idx = 0; idx < MIRROR_CONFIG(unit)->egr_true_mtp_count; idx++) { 16016 if (0 == MIRROR_CONFIG_EGR_TRUE_MTP_REF_COUNT(unit, idx)) { 16017 if (soc_feature(unit, soc_feature_mirror_rspan_no_mtp0) && 16018 rspan && (0 == idx)) { 16019 /* Do not use MTP 0 for RSPAN on Trident 16020 * and later devices */ 16021 continue; 16022 } 16023 break; 16024 } 16025 } 16026 } 16027 16028 if ((idx < MIRROR_CONFIG(unit)->egr_true_mtp_count) || 16029 (SOC_IS_APOLLO(unit) && 16030 soc_feature(unit, soc_feature_ipfix_flow_mirror) && 16031 (MIRROR_CONFIG(unit)->egr_true_mtp_count == 0))) { 16032 if ((rv == BCM_E_NOT_FOUND) && (MIRROR_CONFIG_EGR_TRUE_MTP_REF_COUNT(unit, idx) != 0)) { 16033 MIRROR_CONFIG_EGR_TRUE_MTP_REF_COUNT(unit, idx) = 0; 16034 } 16035 16036 if (BCM_FAILURE(rv)) { 16037 /* Mark mtp as used. */ 16038 MIRROR_CONFIG_EGR_TRUE_MTP_DEST(unit, idx) = dest_id; 16039 MIRROR_CONFIG_EGR_TRUE_MTP_REF_COUNT(unit, idx)++; 16040 MIRROR_DEST_REF_COUNT(unit, dest_id)++; 16041 } 16042 16043 /* Write MTP registers */ 16044 rv = _bcm_xgs3_mtp_init(unit, idx, BCM_MIRROR_PORT_EGRESS_TRUE); 16045 if (BCM_FAILURE(rv)) { 16046 MIRROR_CONFIG_EGR_TRUE_MTP_DEST(unit, idx) = BCM_GPORT_INVALID; 16047 MIRROR_CONFIG_EGR_TRUE_MTP_REF_COUNT(unit, idx) = 0; 16048 if (MIRROR_DEST_REF_COUNT(unit, dest_id) > 0) { 16049 MIRROR_DEST_REF_COUNT(unit, dest_id)--; 16050 } 16051 } 16052 *index_used = idx; 16053 } else { 16054 rv = BCM_E_RESOURCE; 16055 } 16056 16057 return (rv); 16058 } 16059 #endif /* BCM_TRIUMPH2_SUPPORT */ 16060 16061 /* 16062 * Function: 16063 * _bcm_tr2_mirror_ingress_mtp_unreserve 16064 * Description: 16065 * Free ingress mirror-to port for Triumph_2 like devices 16066 * Parameters: 16067 * unit - (IN) BCM device number 16068 * mtp_index - (IN) MTP index. 16069 * egress - (IN) Ingress/Egress indication 16070 * is_port - (IN) Port based mirrorring indication 16071 * Returns: 16072 * BCM_E_XXX 16073 * Notes: 16074 * Mtp index completely freed only when reference count gets to 0. 16075 */ 16076 STATIC int 16077 _bcm_tr2_mirror_mtp_unreserve(int unit, int mtp_index, int egress, int is_port) 16078 { 16079 int rv = BCM_E_NONE; /* Operation return status.*/ 16080 bcm_gport_t mirror_dest; /* Mirror destination id. */ 16081 16082 /* Input parameters check. */ 16083 if ((mtp_index < 0) || (mtp_index >= BCM_MIRROR_MTP_COUNT)) { 16084 return (BCM_E_PARAM); 16085 } 16086 16087 /* If MTP is not in use - do nothing */ 16088 if (0 == MIRROR_CONFIG_SHARED_MTP_REF_COUNT(unit, mtp_index)) { 16089 return (rv); 16090 } 16091 16092 /* Decrement mtp index reference count. */ 16093 if ((MIRROR_CONFIG_SHARED_MTP_REF_COUNT(unit, mtp_index) > 0) && 16094 (egress == MIRROR_CONFIG_SHARED_MTP(unit, mtp_index).egress)) { 16095 if (is_port) { 16096 MIRROR_CONFIG_SHARED_MTP_REF_COUNT(unit, mtp_index)--; 16097 } else { 16098 MIRROR_CONFIG_SHARED_MTP_REF_COUNT(unit, mtp_index) -= (1 << BCM_MIRROR_MTP_REF_FP_OFFSET); 16099 } 16100 } 16101 16102 if (0 == MIRROR_CONFIG_SHARED_MTP_REF_COUNT(unit, mtp_index)) { 16103 /* Write MTP registers */ 16104 mirror_dest = MIRROR_CONFIG_SHARED_MTP_DEST(unit, mtp_index); 16105 rv = _bcm_xgs3_mtp_reset(unit, mtp_index, egress ? BCM_MIRROR_PORT_EGRESS : BCM_MIRROR_PORT_INGRESS); 16106 MIRROR_CONFIG_SHARED_MTP_DEST(unit, mtp_index) = BCM_GPORT_INVALID; 16107 if (MIRROR_DEST_REF_COUNT(unit, mirror_dest) > 0) { 16108 MIRROR_DEST_REF_COUNT(unit, mirror_dest)--; 16109 } 16110 } 16111 return (rv); 16112 } 16113 16114 16115 /* 16116 * Function: 16117 * _bcm_xgs3_mirror_ingress_mtp_unreserve 16118 * Description: 16119 * Free ingress mirror-to port 16120 * Parameters: 16121 * unit - (IN) BCM device number 16122 * mtp_index - (IN) MTP index. 16123 * Returns: 16124 * BCM_E_XXX 16125 * Notes: 16126 * Mtp index completely freed only when reference count gets to 0. 16127 */ 16128 STATIC int 16129 _bcm_xgs3_mirror_ingress_mtp_unreserve(int unit, int mtp_index) 16130 { 16131 int rv = BCM_E_NONE; /* Operation return status.*/ 16132 bcm_gport_t mirror_dest; /* Mirror destination id. */ 16133 16134 if (soc_feature(unit, soc_feature_mirror_flexible) && 16135 !MIRROR_MTP_METHOD_IS_DIRECTED_FLEXIBLE(unit)) { 16136 return _bcm_tr2_mirror_mtp_unreserve(unit, mtp_index, FALSE, TRUE); 16137 } 16138 16139 /* Input parameters check. */ 16140 if (mtp_index >= MIRROR_CONFIG(unit)->ing_mtp_count) { 16141 return (BCM_E_PARAM); 16142 } 16143 16144 /* If MTP is not in use - do nothing */ 16145 if (0 == MIRROR_CONFIG_ING_MTP_REF_COUNT(unit, mtp_index)) { 16146 return (rv); 16147 } 16148 16149 16150 /* Decrement mtp index reference count. */ 16151 if (MIRROR_CONFIG_ING_MTP_REF_COUNT(unit, mtp_index) > 0) { 16152 MIRROR_CONFIG_ING_MTP_REF_COUNT(unit, mtp_index)--; 16153 } 16154 16155 if (0 == MIRROR_CONFIG_ING_MTP_REF_COUNT(unit, mtp_index)) { 16156 /* Write MTP registers */ 16157 mirror_dest = MIRROR_CONFIG_ING_MTP_DEST(unit, mtp_index); 16158 rv = _bcm_xgs3_mtp_reset(unit, mtp_index, BCM_MIRROR_PORT_INGRESS); 16159 MIRROR_CONFIG_ING_MTP_DEST(unit, mtp_index) = BCM_GPORT_INVALID; 16160 if (MIRROR_DEST_REF_COUNT(unit, mirror_dest) > 0) { 16161 MIRROR_DEST_REF_COUNT(unit, mirror_dest)--; 16162 } 16163 } 16164 return (rv); 16165 } 16166 16167 /* 16168 * Function: 16169 * _bcm_xgs3_mirror_egress_mtp_unreserve 16170 * Description: 16171 * Free egress mirror-to port 16172 * Parameters: 16173 * unit - (IN) BCM device number 16174 * mtp_index - (IN) MTP index. 16175 * is_port - (IN) Port based mirror indication. 16176 * Returns: 16177 * BCM_E_XXX 16178 * Notes: 16179 * Mtp index completely freed only when reference count gets to 0. 16180 */ 16181 STATIC int 16182 _bcm_xgs3_mirror_egress_mtp_unreserve(int unit, int mtp_index, int is_port) 16183 { 16184 int rv = BCM_E_NONE; /* Operation return status.*/ 16185 bcm_gport_t mirror_dest; /* Mirror destination id. */ 16186 16187 if (soc_feature(unit, soc_feature_mirror_flexible) && 16188 !MIRROR_MTP_METHOD_IS_DIRECTED_FLEXIBLE(unit)) { 16189 return _bcm_tr2_mirror_mtp_unreserve(unit, mtp_index, TRUE, is_port); 16190 } 16191 16192 /* Input parameters check. */ 16193 if (mtp_index >= MIRROR_CONFIG(unit)->egr_mtp_count) { 16194 return (BCM_E_PARAM); 16195 } 16196 16197 if (0 == MIRROR_CONFIG_EGR_MTP_REF_COUNT(unit, mtp_index)) { 16198 return (rv); 16199 } 16200 16201 /* Decrement mtp index reference count. */ 16202 if (MIRROR_CONFIG_EGR_MTP_REF_COUNT(unit, mtp_index) > 0) { 16203 if (is_port) { 16204 MIRROR_CONFIG_EGR_MTP_REF_COUNT(unit, mtp_index)--; 16205 } else { 16206 MIRROR_CONFIG_EGR_MTP_REF_COUNT(unit, mtp_index) -= (1 << BCM_MIRROR_MTP_REF_FP_OFFSET); 16207 } 16208 } 16209 16210 16211 if (0 == MIRROR_CONFIG_EGR_MTP_REF_COUNT(unit, mtp_index)) { 16212 /* Write MTP registers */ 16213 mirror_dest = MIRROR_CONFIG_EGR_MTP_DEST(unit, mtp_index); 16214 rv = _bcm_xgs3_mtp_reset(unit, mtp_index, BCM_MIRROR_PORT_EGRESS); 16215 MIRROR_CONFIG_EGR_MTP_DEST(unit, mtp_index) = BCM_GPORT_INVALID; 16216 if (MIRROR_DEST_REF_COUNT(unit, mirror_dest) > 0) { 16217 MIRROR_DEST_REF_COUNT(unit, mirror_dest)--; 16218 } 16219 } 16220 return (rv); 16221 } 16222 16223 #ifdef BCM_TRIUMPH2_SUPPORT 16224 /* 16225 * Function: 16226 * _bcm_xgs3_mirror_egress_true_mtp_unreserve 16227 * Description: 16228 * Free egress mirror-to port 16229 * Parameters: 16230 * unit - (IN) BCM device number 16231 * mtp_index - (IN) MTP index. 16232 * Returns: 16233 * BCM_E_XXX 16234 * Notes: 16235 * Mtp index completely freed only when reference count gets to 0. 16236 */ 16237 STATIC int 16238 _bcm_xgs3_mirror_egress_true_mtp_unreserve(int unit, int mtp_index) 16239 { 16240 int rv = BCM_E_NONE; /* Operation return status.*/ 16241 bcm_gport_t mirror_dest; /* Mirror destination id. */ 16242 16243 /* Input parameters check. */ 16244 if (mtp_index >= MIRROR_CONFIG(unit)->egr_true_mtp_count) { 16245 if (!(SOC_IS_APOLLO(unit) && 16246 (MIRROR_CONFIG(unit)->egr_true_mtp_count == 0) && 16247 soc_feature(unit, soc_feature_ipfix_flow_mirror))) { 16248 return (BCM_E_PARAM); 16249 } 16250 } 16251 16252 if (0 == MIRROR_CONFIG_EGR_TRUE_MTP_REF_COUNT(unit, mtp_index)) { 16253 return (rv); 16254 } 16255 16256 /* Decrement mtp index reference count. */ 16257 if (MIRROR_CONFIG_EGR_TRUE_MTP_REF_COUNT(unit, mtp_index) > 0) { 16258 MIRROR_CONFIG_EGR_TRUE_MTP_REF_COUNT(unit, mtp_index)--; 16259 } 16260 16261 16262 if (0 == MIRROR_CONFIG_EGR_TRUE_MTP_REF_COUNT(unit, mtp_index)) { 16263 /* Write MTP registers */ 16264 mirror_dest = MIRROR_CONFIG_EGR_TRUE_MTP_DEST(unit, mtp_index); 16265 rv = _bcm_xgs3_mtp_reset(unit, mtp_index, BCM_MIRROR_PORT_EGRESS_TRUE); 16266 MIRROR_CONFIG_EGR_TRUE_MTP_DEST(unit, mtp_index) = BCM_GPORT_INVALID; 16267 if (MIRROR_DEST_REF_COUNT(unit, mirror_dest) > 0) { 16268 MIRROR_DEST_REF_COUNT(unit, mirror_dest)--; 16269 } 16270 } 16271 return (rv); 16272 } 16273 #endif /* BCM_TRIUMPH2_SUPPORT */ 16274 16275 /* 16276 * Function: 16277 * _bcm_xgs3_mirror_mtp_reserve 16278 * Description: 16279 * Reserve a mirror-to port 16280 * Parameters: 16281 * unit - (IN) BCM device number 16282 * dest_port - (IN) Mirror destination gport. 16283 * flags - (IN) Mirrored traffic direction. 16284 * index_used - (OUT) MTP index reserved 16285 * Returns: 16286 * BCM_E_XXX 16287 * Notes: 16288 * If the a mirror-to port is reserved more than once 16289 * (without being unreserved) then the same MTP index 16290 * will be returned for each call. 16291 * Direction should be INGRESS, EGRESS, or EGRESS_TRUE. 16292 */ 16293 STATIC int 16294 _bcm_xgs3_mirror_mtp_reserve(int unit, bcm_gport_t gport, 16295 uint32 flags, int *index_used) 16296 { 16297 /* Input parameters check. */ 16298 if (NULL == index_used) { 16299 return (BCM_E_PARAM); 16300 } 16301 16302 /* Allocate & initialize mtp based on mirroring direction. */ 16303 if (flags & BCM_MIRROR_PORT_INGRESS) { 16304 return _bcm_xgs3_mirror_ingress_mtp_reserve(unit, gport, index_used); 16305 } else if (flags & BCM_MIRROR_PORT_EGRESS) { 16306 return _bcm_xgs3_mirror_egress_mtp_reserve(unit, gport, TRUE, index_used); 16307 #ifdef BCM_TRIUMPH2_SUPPORT 16308 } else if (flags & BCM_MIRROR_PORT_EGRESS_TRUE) { 16309 return _bcm_xgs3_mirror_egress_true_mtp_reserve(unit, gport, 16310 index_used); 16311 #endif /* BCM_TRIUMPH2_SUPPORT */ 16312 } 16313 return (BCM_E_PARAM); 16314 } 16315 16316 16317 /* 16318 * Function: 16319 * _bcm_xgs3_mirror_mtp_unreserve 16320 * Description: 16321 * Free a mirror-to port 16322 * Parameters: 16323 * unit - (IN) BCM device number 16324 * mtp_index - (IN) MTP index. 16325 * is_port - (IN) Port based mirror indication. 16326 * flags - (IN) Mirrored traffic direction. 16327 * Returns: 16328 * BCM_E_XXX 16329 */ 16330 STATIC int 16331 _bcm_xgs3_mirror_mtp_unreserve(int unit, int mtp_index, int is_port, 16332 uint32 flags) 16333 { 16334 16335 /* Free & reset mtp based on mirroring direction. */ 16336 if (flags & BCM_MIRROR_PORT_INGRESS) { 16337 return _bcm_xgs3_mirror_ingress_mtp_unreserve(unit, mtp_index); 16338 } else if (flags & BCM_MIRROR_PORT_EGRESS) { 16339 return _bcm_xgs3_mirror_egress_mtp_unreserve(unit, mtp_index, is_port); 16340 #ifdef BCM_TRIUMPH2_SUPPORT 16341 } else if (flags & BCM_MIRROR_PORT_EGRESS_TRUE) { 16342 return _bcm_xgs3_mirror_egress_true_mtp_unreserve(unit, mtp_index); 16343 #endif /* BCM_TRIUMPH2_SUPPORT */ 16344 } 16345 return (BCM_E_PARAM); 16346 } 16347 16348 #ifdef BCM_TRIUMPH2_SUPPORT 16349 16350 /* 16351 * Function: 16352 * _bcm_xgs3_mtp_slot_port_indexes_get 16353 * Purpose: 16354 * Retrieve port MTP indexes in MTP slots 16355 * Parameters: 16356 * unit - (IN) BCM device number. 16357 * port - (IN) Local mirror port 16358 * mtp_indexes - (OUT) MTP index in MTP slots for the given port 16359 * Returns: 16360 * BCM_X_XXX 16361 */ 16362 STATIC int 16363 _bcm_xgs3_mtp_slot_port_indexes_get(int unit, bcm_port_t port, 16364 uint32 mtp_indexes[BCM_MIRROR_MTP_COUNT]) 16365 { 16366 uint32 mc_val; 16367 mirror_control_entry_t mc_entry; 16368 int mtp_slot; 16369 int vp = VP_PORT_INVALID; 16370 bcm_module_t mod_out; 16371 bcm_trunk_t tgid_out; 16372 int num_local_ports = 0; 16373 16374 if (BCM_GPORT_IS_SET(port)) { 16375 BCM_IF_ERROR_RETURN( 16376 _bcm_esw_gport_resolve(unit, port, &mod_out, 16377 &port, &tgid_out, &vp)); 16378 16379 if (BCM_TRUNK_INVALID != tgid_out) { 16380 BCM_IF_ERROR_RETURN( 16381 _bcm_esw_trunk_local_members_get(unit, tgid_out, 1, 16382 &port, &num_local_ports)); 16383 } 16384 } 16385 16386 /* Read mirror control structure to get programmed mtp indexes. */ 16387 if (soc_feature(unit, soc_feature_mirror_control_mem)) { 16388 BCM_IF_ERROR_RETURN 16389 (READ_MIRROR_CONTROLm(unit, MEM_BLOCK_ANY, port, &mc_entry)); 16390 BCM_MIRROR_MTP_ITER(MIRROR_CONFIG_MTP_DEV_MASK(unit), mtp_slot) { 16391 mtp_indexes[mtp_slot] = 16392 soc_mem_field32_get(unit, MIRROR_CONTROLm, &mc_entry, 16393 _mtp_index_field[mtp_slot]); 16394 } 16395 } else { 16396 BCM_IF_ERROR_RETURN(READ_MIRROR_CONTROLr(unit, port, &mc_val)); 16397 BCM_MIRROR_MTP_ITER(MIRROR_CONFIG_MTP_DEV_MASK(unit), mtp_slot) { 16398 mtp_indexes[mtp_slot] = 16399 soc_reg_field_get(unit, MIRROR_CONTROLr, mc_val, 16400 _mtp_index_field[mtp_slot]); 16401 } 16402 } 16403 16404 return BCM_E_NONE; 16405 } 16406 16407 /* 16408 * Function: 16409 * _bcm_xgs3_mtp_slot_port_index_set 16410 * Purpose: 16411 * Set a port's MTP index in the given MTP slot 16412 * Parameters: 16413 * unit - (IN) BCM device number. 16414 * port - (IN) Local mirror port 16415 * mtp_slot - (IN) MTP slot in which to install the MTP index. 16416 * mtp_index - (IN) HW mtp index. 16417 * Returns: 16418 * BCM_X_XXX 16419 */ 16420 STATIC int 16421 _bcm_xgs3_mtp_slot_port_index_set(int unit, bcm_port_t port, 16422 int mtp_slot, int mtp_index) 16423 { 16424 uint32 mc_val; 16425 int cpu_hg_index = 0; 16426 mirror_control_entry_t mc_entry; 16427 int vp = VP_PORT_INVALID; 16428 bcm_module_t mod_out; 16429 bcm_trunk_t tgid_out = BCM_TRUNK_INVALID; 16430 bcm_port_t local_ports[SOC_MAX_NUM_PORTS]; 16431 int num_local_ports = 0; 16432 int port_index = 0; 16433 16434 if (BCM_GPORT_IS_SET(port)) { 16435 BCM_IF_ERROR_RETURN( 16436 _bcm_esw_gport_resolve(unit, port, &mod_out, 16437 &port, &tgid_out, &vp)); 16438 } 16439 16440 if (BCM_TRUNK_INVALID != tgid_out) { 16441 BCM_IF_ERROR_RETURN( 16442 _bcm_esw_trunk_local_members_get(unit, tgid_out, 16443 SOC_MAX_NUM_PORTS, 16444 local_ports, 16445 &num_local_ports)); 16446 } else { 16447 local_ports[0] = port; 16448 num_local_ports = 1; 16449 } 16450 16451 16452 /* Non-UC fields are only needed for egress mirroring, 16453 * but configuring them unconditionally will 16454 * simplify logic without changing device behavior. */ 16455 for (port_index = 0; port_index < num_local_ports; port_index++) { 16456 port = local_ports[port_index]; 16457 if (soc_feature(unit, soc_feature_mirror_control_mem)) { 16458 BCM_IF_ERROR_RETURN 16459 (READ_MIRROR_CONTROLm(unit, MEM_BLOCK_ANY, port, &mc_entry)); 16460 soc_mem_field32_set(unit, MIRROR_CONTROLm, &mc_entry, 16461 _mtp_index_field[mtp_slot], mtp_index); 16462 soc_mem_field32_set(unit, MIRROR_CONTROLm, &mc_entry, 16463 _non_uc_mtp_index_field[mtp_slot], mtp_index); 16464 BCM_IF_ERROR_RETURN 16465 (WRITE_MIRROR_CONTROLm(unit, MEM_BLOCK_ANY, port, &mc_entry)); 16466 16467 cpu_hg_index = SOC_IS_KATANA2(unit) ? 16468 SOC_INFO(unit).cpu_hg_pp_port_index : 16469 SOC_INFO(unit).cpu_hg_index; 16470 #ifdef BCM_TOMAHAWK3_SUPPORT 16471 if (SOC_IS_TOMAHAWK3(unit)) { 16472 /* No higig on TH3, skip programming below */ 16473 cpu_hg_index = -1; 16474 } 16475 #endif /* BCM_TOMAHAWK3_SUPPORT */ 16476 if (IS_CPU_PORT(unit, port) && cpu_hg_index != -1) { 16477 BCM_IF_ERROR_RETURN(READ_MIRROR_CONTROLm(unit, MEM_BLOCK_ANY, 16478 cpu_hg_index, &mc_entry)); 16479 soc_mem_field32_set(unit, MIRROR_CONTROLm, &mc_entry, 16480 _mtp_index_field[mtp_slot], mtp_index); 16481 soc_mem_field32_set(unit, MIRROR_CONTROLm, &mc_entry, 16482 _non_uc_mtp_index_field[mtp_slot], mtp_index); 16483 BCM_IF_ERROR_RETURN(WRITE_MIRROR_CONTROLm(unit, MEM_BLOCK_ANY, 16484 cpu_hg_index, &mc_entry)); 16485 } 16486 } else { 16487 BCM_IF_ERROR_RETURN(READ_MIRROR_CONTROLr(unit, port, &mc_val)); 16488 soc_reg_field_set(unit, MIRROR_CONTROLr, &mc_val, 16489 _mtp_index_field[mtp_slot], mtp_index); 16490 soc_reg_field_set(unit, MIRROR_CONTROLr, &mc_val, 16491 _non_uc_mtp_index_field[mtp_slot], mtp_index); 16492 BCM_IF_ERROR_RETURN(WRITE_MIRROR_CONTROLr(unit, port, mc_val)); 16493 16494 if (IS_CPU_PORT(unit, port)) { 16495 BCM_IF_ERROR_RETURN(READ_IMIRROR_CONTROLr(unit, port, &mc_val)); 16496 soc_reg_field_set(unit, IMIRROR_CONTROLr, &mc_val, 16497 _mtp_index_field[mtp_slot], mtp_index); 16498 soc_reg_field_set(unit, IMIRROR_CONTROLr, &mc_val, 16499 _non_uc_mtp_index_field[mtp_slot], mtp_index); 16500 BCM_IF_ERROR_RETURN(WRITE_IMIRROR_CONTROLr(unit, port, mc_val)); 16501 } 16502 } 16503 } 16504 16505 return BCM_E_NONE; 16506 } 16507 16508 /* 16509 * Function: 16510 * _bcm_xgs3_mtp_index_port_slot_get 16511 * Purpose: 16512 * Get a port's MTP slot for the given MTP index 16513 * Parameters: 16514 * unit - (IN) BCM device number. 16515 * port - (IN) Local mirror port 16516 * enables - (IN) Bitmap of port's enables 16517 * egress - (IN) Ingress/Egress indication 16518 * mtp_index - (IN) HW mtp index. 16519 * slot_type - (IN) mtp slot types for port,FP, SFLOW, etc. 16520 * mtp_slot_p - (OUT) MTP slot of the MTP index on the port. 16521 * Returns: 16522 * BCM_X_XXX 16523 */ 16524 STATIC int 16525 _bcm_xgs3_mtp_index_port_slot_get(int unit, bcm_port_t port, 16526 uint32 enables, int egress, 16527 int mtp_index, int slot_type, int *mtp_slot_p) 16528 { 16529 int mtp_slot, mtp_bit; /* MTP type value & bitmap */ 16530 uint32 index_val[BCM_MIRROR_MTP_COUNT] = {0}; 16531 16532 /* Verify we are still coherent */ 16533 if (egress) { 16534 if (enables != (enables & MIRROR_CONFIG_MTP_MODE_BMP(unit))) { 16535 /* Out of sync! */ 16536 return BCM_E_INTERNAL; 16537 } 16538 } else { 16539 if (enables != (enables & ~MIRROR_CONFIG_MTP_MODE_BMP(unit))) { 16540 /* Out of sync! */ 16541 return BCM_E_INTERNAL; 16542 } 16543 } 16544 16545 /* The enables are of MTP slots, but we have the MTP index 16546 * Determine which slot has the index */ 16547 16548 if (slot_type == BCM_MTP_SLOT_TYPE_PORT) { 16549 /* Read mirror control structure to get programmed mtp slots. */ 16550 BCM_IF_ERROR_RETURN 16551 (_bcm_xgs3_mtp_slot_port_indexes_get(unit, port, index_val)); 16552 } else { 16553 /* retrieve from software records. Should be in sync with hardware */ 16554 BCM_MIRROR_MTP_ITER(MIRROR_CONFIG_MTP_DEV_MASK(unit), mtp_slot) { 16555 index_val[mtp_slot] = 16556 MIRROR_CONFIG_TYPE_MTP_SLOT(unit, mtp_slot, slot_type); 16557 } 16558 } 16559 16560 BCM_MIRROR_MTP_ITER(MIRROR_CONFIG_MTP_DEV_MASK(unit), mtp_slot) { 16561 mtp_bit = 1 << mtp_slot; 16562 /* Check if MTP slot is enabled on port */ 16563 if (!(enables & mtp_bit)) { 16564 continue; 16565 } 16566 16567 if (mtp_index == index_val[mtp_slot]) { 16568 *mtp_slot_p = mtp_slot; 16569 return BCM_E_NONE; 16570 } 16571 } 16572 16573 return BCM_E_NOT_FOUND; 16574 } 16575 16576 /* 16577 * Function: 16578 * _bcm_tr2_mirror_mtp_slot_update 16579 * Description: 16580 * Write the MTP_TYPE data for the MTP slot configuration 16581 * when it is changed. 16582 * Parameters: 16583 * unit - (IN) BCM device number. 16584 * Returns: 16585 * BCM_E_XXX 16586 */ 16587 STATIC int 16588 _bcm_tr2_mirror_mtp_slot_update(int unit) 16589 { 16590 uint32 ms_reg; /* MTP mode register value */ 16591 16592 BCM_IF_ERROR_RETURN(READ_MIRROR_SELECTr(unit, &ms_reg)); 16593 soc_reg_field_set(unit, MIRROR_SELECTr, &ms_reg, MTP_TYPEf, 16594 MIRROR_CONFIG_MTP_MODE_BMP(unit)); 16595 BCM_IF_ERROR_RETURN(WRITE_MIRROR_SELECTr(unit, ms_reg)); 16596 BCM_IF_ERROR_RETURN(WRITE_EGR_MIRROR_SELECTr(unit, ms_reg)); 16597 16598 return BCM_E_NONE; 16599 } 16600 16601 /* 16602 * Function: 16603 * _bcm_xgs3_mtp_type_slot_reserve 16604 * Purpose: 16605 * Record used MTP slots forPort/ FP/IPFIX usage. 16606 * Parameters: 16607 * unit - (IN) BCM device number. 16608 * flags - (IN) BCM_MIRROR_PORT_XXX flags. 16609 * port_enables - (IN) Bitmap of port's enables (Port only) 16610 * port - (IN) Local mirror port (Port only) 16611 * mtp_type - (IN) Port/FP/IPFIX. 16612 * mtp_index - (IN) Allocated hw mtp index. 16613 * mtp_slot_p - (OUT) MTP slot in which to install the MTP index. 16614 * Returns: 16615 * BCM_X_XXX 16616 */ 16617 STATIC int 16618 _bcm_xgs3_mtp_type_slot_reserve(int unit, uint32 flags, uint32 port_enables, 16619 bcm_port_t port, int mtp_type, 16620 int mtp_index, int *mtp_slot_p) 16621 { 16622 int mtp_slot, mtp_bit, free_ptr = -1, free_slot = -1; 16623 int egress = FALSE; 16624 int port_mirror; 16625 bcm_port_t port_ix; 16626 uint32 index_val[BCM_MIRROR_MTP_COUNT]; 16627 bcm_pbmp_t all_pbmp; 16628 int vp = VP_PORT_INVALID; 16629 bcm_module_t mod_out; 16630 bcm_trunk_t tgid_out; 16631 bcm_port_t local_port; 16632 int mtp_type_tmp; 16633 int slot_is_occupied = FALSE; 16634 _bcm_mtp_config_p mtp_cfg; 16635 16636 if (BCM_GPORT_IS_SET(port)) { 16637 BCM_IF_ERROR_RETURN( 16638 _bcm_esw_gport_resolve(unit, port, &mod_out, 16639 &local_port, &tgid_out, &vp)); 16640 } else { 16641 local_port = port; 16642 } 16643 16644 if (flags & BCM_MIRROR_PORT_EGRESS) { 16645 egress = TRUE; 16646 } 16647 16648 port_mirror = (mtp_type == BCM_MTP_SLOT_TYPE_PORT); 16649 if (port_mirror) { 16650 /* Read mirror control structure to get programmed mtp indexes. */ 16651 BCM_IF_ERROR_RETURN 16652 (_bcm_xgs3_mtp_slot_port_indexes_get(unit, port, index_val)); 16653 } 16654 16655 BCM_MIRROR_MTP_ITER(MIRROR_CONFIG_MTP_DEV_MASK(unit), mtp_slot) { 16656 mtp_bit = 1 << mtp_slot; 16657 if (egress) { 16658 if (!(MIRROR_CONFIG_MTP_MODE_BMP(unit) & mtp_bit)) { 16659 if (MIRROR_CONFIG_MTP_MODE_REF_COUNT(unit, 16660 mtp_slot) == 0) { 16661 /* MTP Container is undecided, note for later */ 16662 if (free_ptr < 0) { 16663 /* Record unallocated MTP container */ 16664 free_ptr = mtp_slot; 16665 } 16666 } /* Else, container already used for ingress mirrors */ 16667 continue; 16668 } else { 16669 /* Already an egress slot, is it the same MTP? */ 16670 if (port_mirror && (mtp_index != index_val[mtp_slot])) { 16671 /* No, keep searching */ 16672 continue; 16673 } 16674 } 16675 } else { 16676 if (MIRROR_CONFIG_MTP_MODE_BMP(unit) & mtp_bit) { 16677 /* Slot configured for egress mirroring, skip */ 16678 continue; 16679 } 16680 } 16681 16682 /* To check if this slot is occupied by other type source */ 16683 for (mtp_type_tmp = BCM_MTP_SLOT_TYPE_PORT; 16684 mtp_type_tmp < BCM_MTP_SLOT_TYPES; 16685 mtp_type_tmp++) { 16686 if (mtp_type_tmp == mtp_type) { 16687 continue; 16688 } 16689 16690 if (MIRROR_CONFIG_TYPE_MTP_REF_COUNT(unit, mtp_slot, mtp_type_tmp)) { 16691 slot_is_occupied = TRUE; 16692 break; 16693 } 16694 } 16695 if (slot_is_occupied) { 16696 slot_is_occupied = FALSE; 16697 continue; 16698 } 16699 if (port_mirror) { 16700 if (!(port_enables & mtp_bit)) { /* Slot unused on this port */ 16701 if ((flags & BCM_MIRROR_PORT_INGRESS) && 16702 BCM_PBMP_MEMBER( 16703 MIRROR_CONFIG_PBMP_MTP_SLOT_USED(unit, mtp_slot), 16704 local_port)) { 16705 /* The slost is used by the vp created on the port, skip */ 16706 continue; 16707 } 16708 16709 if (free_slot < 0) { 16710 /* Record free slot */ 16711 free_slot = mtp_slot; 16712 } 16713 } else { 16714 /* Check if mtp is already installed. */ 16715 if (mtp_index == index_val[mtp_slot]) { 16716 /* Match - return mtp_slot */ 16717 *mtp_slot_p = mtp_slot; 16718 return BCM_E_EXISTS; 16719 } 16720 } 16721 } else { 16722 if (MIRROR_CONFIG_TYPE_MTP_REF_COUNT(unit, mtp_slot, mtp_type)) { 16723 if (MIRROR_CONFIG_TYPE_MTP_SLOT(unit, mtp_slot, 16724 mtp_type) == mtp_index) { 16725 /* Match - return mtp_slot */ 16726 *mtp_slot_p = mtp_slot; 16727 MIRROR_CONFIG_TYPE_MTP_REF_COUNT(unit, mtp_slot, 16728 mtp_type)++; 16729 MIRROR_CONFIG_MTP_MODE_REF_COUNT(unit, mtp_slot)++; 16730 return BCM_E_NONE; 16731 } 16732 } else { /* Slot unused on this port */ 16733 if (free_slot < 0) { 16734 /* Record free slot */ 16735 free_slot = mtp_slot; 16736 } 16737 } 16738 } 16739 } 16740 16741 /* Use previous allocated slot if available. Otherwise use unallocated 16742 * MTP continaner. If neither, we're out of resources. */ 16743 if (free_slot < 0) { 16744 if (free_ptr < 0) { 16745 return BCM_E_RESOURCE; 16746 } else { 16747 free_slot = free_ptr; 16748 } 16749 } 16750 16751 mtp_slot = free_slot; 16752 mtp_bit = 1 << free_slot; 16753 16754 /* Record references and new MTP mode allocation if necessary */ 16755 if (egress && !(MIRROR_CONFIG_MTP_MODE_BMP(unit) & mtp_bit)) { 16756 /* Update MTP_MODE */ 16757 MIRROR_CONFIG_MTP_MODE_BMP(unit) |= mtp_bit; 16758 } 16759 BCM_IF_ERROR_RETURN(_bcm_tr2_mirror_mtp_slot_update(unit)); 16760 16761 /* special handling for IFA to set egress type in EGR_MIRROR_SELECTr */ 16762 if (flags & BCM_MIRROR_PORT_INGRESS) { 16763 mtp_cfg = MIRROR_CONFIG_MTP(unit, mtp_index, BCM_MIRROR_PORT_INGRESS); 16764 if ((MIRROR_DEST(unit, mtp_cfg->dest_id)->flags2) & 16765 BCM_MIRROR_DEST_FLAGS2_IFA) { 16766 BCM_IF_ERROR_RETURN(soc_reg_field32_modify(unit, EGR_MIRROR_SELECTr, 16767 REG_PORT_ANY, MTP_TYPEf, 16768 MIRROR_CONFIG_MTP_MODE_BMP(unit) | mtp_bit)); 16769 } 16770 } 16771 16772 MIRROR_CONFIG_MTP_MODE_REF_COUNT(unit, mtp_slot)++; 16773 16774 BCM_PBMP_CLEAR(all_pbmp); 16775 BCM_PBMP_ASSIGN(all_pbmp, PBMP_ALL(unit)); 16776 #ifdef BCM_KATANA2_SUPPORT 16777 if (SOC_IS_KATANA2(unit) && soc_feature(unit, soc_feature_flex_port)) { 16778 BCM_IF_ERROR_RETURN(_bcm_kt2_flexio_pbmp_update(unit, &all_pbmp)); 16779 } 16780 if (soc_feature(unit, soc_feature_linkphy_coe) || 16781 soc_feature(unit, soc_feature_subtag_coe)) { 16782 _bcm_kt2_subport_pbmp_update(unit, &all_pbmp); 16783 } 16784 #endif 16785 16786 if (port_mirror) { 16787 if (egress) { 16788 /* Must set all ports for egress mirroring */ 16789 PBMP_ITER(all_pbmp, port_ix) { 16790 BCM_IF_ERROR_RETURN 16791 (_bcm_xgs3_mtp_slot_port_index_set(unit, port_ix, 16792 mtp_slot, mtp_index)); 16793 } 16794 } else { 16795 /* Only this port for ingress mirroring */ 16796 BCM_IF_ERROR_RETURN 16797 (_bcm_xgs3_mtp_slot_port_index_set(unit, port, 16798 mtp_slot, mtp_index)); 16799 } 16800 BCM_PBMP_PORT_ADD(MIRROR_CONFIG_PBMP_MTP_SLOT_USED(unit, mtp_slot), 16801 local_port); 16802 } else { 16803 MIRROR_CONFIG_TYPE_MTP_SLOT(unit, mtp_slot, mtp_type) = mtp_index; 16804 } 16805 MIRROR_CONFIG_TYPE_MTP_REF_COUNT(unit, mtp_slot, mtp_type)++; 16806 16807 /* This configures the mirror behavior, but the enables are set in 16808 * the calling functions. */ 16809 *mtp_slot_p = mtp_slot; 16810 16811 return BCM_E_NONE; 16812 } 16813 16814 /* 16815 * Function: 16816 * _bcm_xgs3_mtp_type_slot_unreserve 16817 * Purpose: 16818 * Clear a used MTP slot for Port/FP/IPFIX usage. 16819 * Parameters: 16820 * unit - (IN) BCM device number. 16821 * flags - (IN) BCM_MIRROR_PORT_XXX flags. 16822 * port_enables - (IN) Bitmap of port's enables (Port only) 16823 * port - (IN) Local mirror port (Port only) 16824 * mtp_type - (IN) Port/FP/IPFIX. 16825 * mtp_index - (IN) Allocated hw mtp index. 16826 * Returns: 16827 * BCM_X_XXX 16828 */ 16829 STATIC int 16830 _bcm_xgs3_mtp_type_slot_unreserve(int unit, uint32 flags, 16831 bcm_port_t port, int mtp_type, 16832 int mtp_index) 16833 { 16834 int comb_enables; 16835 int mtp_slot, mtp_bit; 16836 int egress = FALSE; 16837 bcm_port_t port_ix; 16838 int port_mirror; 16839 uint32 index_val[BCM_MIRROR_MTP_COUNT]; 16840 int vp = VP_PORT_INVALID; 16841 bcm_module_t mod_out; 16842 bcm_trunk_t tgid_out; 16843 bcm_port_t local_port; 16844 16845 if (BCM_GPORT_IS_SET(port)) { 16846 BCM_IF_ERROR_RETURN( 16847 _bcm_esw_gport_resolve(unit, port, &mod_out, 16848 &local_port, &tgid_out, &vp)); 16849 } else { 16850 local_port = port; 16851 } 16852 16853 if (flags & BCM_MIRROR_PORT_EGRESS) { 16854 egress = TRUE; 16855 } 16856 16857 port_mirror = (mtp_type == BCM_MTP_SLOT_TYPE_PORT); 16858 if (port_mirror) { 16859 /* Read mirror control structure to get programmed mtp indexes. */ 16860 BCM_IF_ERROR_RETURN 16861 (_bcm_xgs3_mtp_slot_port_indexes_get(unit, port, index_val)); 16862 } 16863 16864 /* Make an effective enable bitmap for "in use" */ 16865 comb_enables = 0; 16866 BCM_MIRROR_MTP_ITER(MIRROR_CONFIG_MTP_DEV_MASK(unit), mtp_slot) { 16867 if (MIRROR_CONFIG_TYPE_MTP_REF_COUNT(unit, mtp_slot, mtp_type)) { 16868 comb_enables |= (1 << mtp_slot); 16869 } 16870 } 16871 16872 if (egress) { 16873 comb_enables &= MIRROR_CONFIG_MTP_MODE_BMP(unit); 16874 /* Only egress slots */ 16875 } else { 16876 comb_enables &= ~MIRROR_CONFIG_MTP_MODE_BMP(unit); 16877 /* Only ingress slots */ 16878 } 16879 16880 BCM_MIRROR_MTP_ITER(MIRROR_CONFIG_MTP_DEV_MASK(unit), mtp_slot) { 16881 mtp_bit = 1 << mtp_slot; 16882 if (!(comb_enables & mtp_bit)) { 16883 continue; 16884 } 16885 16886 if (port_mirror) { 16887 if (index_val[mtp_slot] == mtp_index) { 16888 /* Removed mtp was found -> disable it. */ 16889 16890 /* Calling function should have already disabled 16891 * ipipe mirroring on port. */ 16892 16893 /* Reset ipipe mirroring mtp index. */ 16894 if (!egress) { 16895 BCM_IF_ERROR_RETURN 16896 (_bcm_xgs3_mtp_slot_port_index_set(unit, port, 16897 mtp_slot, 0)); 16898 } 16899 16900 if (MIRROR_CONFIG_MTP_MODE_REF_COUNT(unit, mtp_slot) > 0) { 16901 MIRROR_CONFIG_MTP_MODE_REF_COUNT(unit, mtp_slot)--; 16902 } 16903 if (egress) { 16904 if (!(MIRROR_CONFIG_MTP_MODE_REF_COUNT(unit, 16905 mtp_slot))) { 16906 /* Free MTP_MODE */ 16907 MIRROR_CONFIG_MTP_MODE_BMP(unit) &= ~mtp_bit; 16908 16909 /* Must clear all ports for egress mirroring */ 16910 PBMP_ALL_ITER(unit, port_ix) { 16911 BCM_IF_ERROR_RETURN 16912 (_bcm_xgs3_mtp_slot_port_index_set(unit, port_ix, 16913 mtp_slot,0)); 16914 } 16915 BCM_IF_ERROR_RETURN 16916 (_bcm_tr2_mirror_mtp_slot_update(unit)); 16917 } 16918 } 16919 if (MIRROR_CONFIG_TYPE_MTP_REF_COUNT(unit, mtp_slot, 16920 mtp_type) > 0) { 16921 MIRROR_CONFIG_TYPE_MTP_REF_COUNT(unit, mtp_slot, 16922 mtp_type)--; 16923 } 16924 16925 BCM_PBMP_PORT_REMOVE( 16926 MIRROR_CONFIG_PBMP_MTP_SLOT_USED(unit, mtp_slot), 16927 local_port); 16928 break; 16929 } 16930 } else { 16931 if (MIRROR_CONFIG_TYPE_MTP_SLOT(unit, mtp_slot, 16932 mtp_type) == mtp_index) { 16933 /* Found! */ 16934 if (MIRROR_CONFIG_MTP_MODE_REF_COUNT(unit, mtp_slot) > 0) { 16935 MIRROR_CONFIG_MTP_MODE_REF_COUNT(unit, mtp_slot)--; 16936 } 16937 if (egress && 16938 !(MIRROR_CONFIG_MTP_MODE_REF_COUNT(unit, 16939 mtp_slot))) { 16940 /* Free MTP_MODE */ 16941 MIRROR_CONFIG_MTP_MODE_BMP(unit) &= ~mtp_bit; 16942 16943 BCM_IF_ERROR_RETURN 16944 (_bcm_tr2_mirror_mtp_slot_update(unit)); 16945 } 16946 16947 if (MIRROR_CONFIG_TYPE_MTP_REF_COUNT(unit, mtp_slot, 16948 mtp_type) > 0) { 16949 MIRROR_CONFIG_TYPE_MTP_REF_COUNT(unit, mtp_slot, 16950 mtp_type)--; 16951 } 16952 if (0 == MIRROR_CONFIG_TYPE_MTP_REF_COUNT(unit, mtp_slot, 16953 mtp_type)) { 16954 MIRROR_CONFIG_TYPE_MTP_SLOT(unit, mtp_slot, 16955 mtp_type) = 0; 16956 } 16957 break; 16958 } 16959 } 16960 } 16961 return BCM_E_NONE; 16962 } 16963 16964 /* 16965 * Function: 16966 * _bcm_tr2_mirror_ipipe_egress_mtp_install 16967 * Description: 16968 * Install IPIPE egress reserved mtp index into 16969 * mirror control register. 16970 * Parameters: 16971 * unit - (IN) BCM device number. 16972 * port - (IN) Mirror source gport. 16973 * mtp_index - (IN) Mirror to port index. 16974 * Returns: 16975 * BCM_E_XXX 16976 */ 16977 STATIC int 16978 _bcm_tr2_mirror_ipipe_egress_mtp_install(int unit, bcm_port_t port, 16979 int mtp_index) 16980 { 16981 int enable; /* Used mtp bit map. */ 16982 int mtp_slot; /* MTP type value */ 16983 16984 BCM_IF_ERROR_RETURN(_bcm_esw_mirror_egress_get(unit, port, &enable)); 16985 16986 if (MIRROR_MTP_METHOD_IS_DIRECTED_FLEXIBLE(unit)) { 16987 BCM_IF_ERROR_RETURN 16988 (_bcm_xgs3_mtp_type_slot_reserve(unit, 16989 BCM_MIRROR_PORT_EGRESS, 16990 enable, port, 16991 BCM_MTP_SLOT_TYPE_PORT, 16992 mtp_index, &mtp_slot)); 16993 } else { 16994 /* Otherwise the slot and index is 1-1 */ 16995 mtp_slot = mtp_index; 16996 } 16997 16998 /* if mtp is enabled on port - inform caller */ 16999 if (enable & (1 << mtp_slot)) { 17000 return (BCM_E_EXISTS); 17001 } 17002 17003 /* Update egress enables */ 17004 enable |= (1 << mtp_slot); 17005 BCM_IF_ERROR_RETURN(_bcm_esw_mirror_egress_set(unit, port, enable)); 17006 17007 return (BCM_E_NONE); 17008 } 17009 17010 /* 17011 * Function: 17012 * _bcm_tr2_mirror_egress_true_mtp_install 17013 * Description: 17014 * Install egress true mirroring reserved mtp index into 17015 * mirror control register. 17016 * Parameters: 17017 * unit - (IN) BCM device number. 17018 * port - (IN) Mirror source gport. 17019 * mtp_index - (IN) Mirror to port index. 17020 * Returns: 17021 * BCM_E_XXX 17022 */ 17023 STATIC int 17024 _bcm_tr2_mirror_egress_true_mtp_install(int unit, bcm_port_t port, 17025 int mtp_index) 17026 { 17027 int enable; /* Used mtp bit map. */ 17028 17029 /* Read mtp egress true mtp enable bitmap for source port. */ 17030 BCM_IF_ERROR_RETURN 17031 (_bcm_port_mirror_egress_true_enable_get(unit, port, &enable)); 17032 17033 if (!(enable & (1 << mtp_index))) { 17034 enable |= (1 << mtp_index); 17035 BCM_IF_ERROR_RETURN 17036 (_bcm_port_mirror_egress_true_enable_set(unit, port, enable)); 17037 } else { 17038 /* GNATS: Nothing to do? Ref counts? */ 17039 } 17040 17041 return BCM_E_NONE; 17042 } 17043 17044 /* 17045 * Function: 17046 * _bcm_tr2_mirror_port_ipipe_dest_get 17047 * Description: 17048 * Get IPIPE ingress/egress mirroring destinations for the 17049 * specific port. 17050 * Parameters: 17051 * unit - (IN) BCM device number. 17052 * port - (IN) Mirror source gport. 17053 * array_sz - (IN) Sizeof dest_array parameter. 17054 * dest_array - (OUT) Mirror to port array. 17055 * egress - (IN) (TRUE/FALSE) Egress mirror. 17056 * Returns: 17057 * BCM_E_XXX 17058 */ 17059 STATIC int 17060 _bcm_tr2_mirror_port_ipipe_dest_get(int unit, bcm_port_t port, 17061 int array_sz, bcm_gport_t *dest_array, 17062 int egress, int vp) 17063 { 17064 int index; /* Destination iteration index. */ 17065 int mtp_index; /* MTP index */ 17066 int mtp_slot, mtp_bit; /* MTP type value & bitmap */ 17067 int comb_enables; /* Combined port/MTP type enable bits */ 17068 int flexible_mtp; /* MTP type reconfig permitted */ 17069 uint32 index_val[BCM_MIRROR_MTP_COUNT]; 17070 17071 flexible_mtp = MIRROR_MTP_METHOD_IS_DIRECTED_FLEXIBLE(unit); 17072 17073 /* Fold together the port enables and the MTP direction */ 17074 if (egress) { 17075 if (vp != VP_PORT_INVALID) { 17076 BCM_IF_ERROR_RETURN(_bcm_tr2_mirror_dvp_enable_get(unit, vp, 17077 &comb_enables)); 17078 } else { 17079 /* Read mtp egress mtp enable bitmap for source port. */ 17080 BCM_IF_ERROR_RETURN 17081 (_bcm_esw_mirror_egress_get(unit, port, &comb_enables)); 17082 } 17083 if (flexible_mtp) { 17084 comb_enables &= MIRROR_CONFIG_MTP_MODE_BMP(unit); 17085 } 17086 } else { 17087 if (vp != VP_PORT_INVALID) { 17088 BCM_IF_ERROR_RETURN(_bcm_tr2_mirror_svp_enable_get(unit, vp, 17089 &comb_enables)); 17090 } else { 17091 /* Read mtp ingress mtp enable bitmap for source port. */ 17092 BCM_IF_ERROR_RETURN 17093 (_bcm_esw_mirror_ingress_get(unit, port, &comb_enables)); 17094 } 17095 if (flexible_mtp) { 17096 comb_enables &= ~MIRROR_CONFIG_MTP_MODE_BMP(unit); 17097 } 17098 } 17099 17100 if (!comb_enables) { 17101 return (BCM_E_NONE); 17102 } 17103 17104 if (vp != VP_PORT_INVALID) { 17105 if (BCM_GPORT_IS_TRUNK(port)) { 17106 bcm_trunk_t tid = 0; 17107 bcm_port_t local_member; 17108 int local_member_count; 17109 tid = BCM_GPORT_TRUNK_GET(port); 17110 BCM_IF_ERROR_RETURN(_bcm_esw_trunk_local_members_get(unit, tid, 17111 1, &local_member, &local_member_count)); 17112 port = local_member; 17113 } else { 17114 BCM_IF_ERROR_RETURN(bcm_esw_port_local_get(unit, port, &port)); 17115 } 17116 } 17117 17118 #ifdef BCM_TRIDENT2PLUS_SUPPORT 17119 if (soc_feature(unit, soc_feature_hgproxy_subtag_coe) && 17120 _BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, port)) { 17121 BCM_IF_ERROR_RETURN( 17122 _bcmi_coe_subport_physical_port_get(unit, port, &port)); 17123 } 17124 #endif 17125 17126 /* Read mirror control structure to get programmed mtp indexes. */ 17127 BCM_IF_ERROR_RETURN 17128 (_bcm_xgs3_mtp_slot_port_indexes_get(unit, port, index_val)); 17129 17130 index = 0; 17131 /* Read mirror control register to compare programmed mtp indexes. */ 17132 BCM_MIRROR_MTP_ITER(MIRROR_CONFIG_MTP_DEV_MASK(unit), mtp_slot) { 17133 mtp_bit = 1 << mtp_slot; 17134 /* Check if MTP slot is enabled on port */ 17135 if (!(comb_enables & mtp_bit)) { 17136 continue; 17137 } 17138 17139 /* MTP index is enabled and direction matches */ 17140 mtp_index = index_val[mtp_slot]; 17141 17142 if (flexible_mtp) { 17143 if (egress) { 17144 dest_array[index] = 17145 MIRROR_CONFIG_EGR_MTP_DEST(unit, mtp_index); 17146 } else { 17147 dest_array[index] = 17148 MIRROR_CONFIG_ING_MTP_DEST(unit, mtp_index); 17149 } 17150 } else { 17151 /* Validate MTP index direction matches for shared mode */ 17152 if (MIRROR_CONFIG_SHARED_MTP(unit, mtp_index).egress != egress) { 17153 continue; 17154 } 17155 17156 dest_array[index] = 17157 MIRROR_CONFIG_SHARED_MTP_DEST(unit, mtp_index); 17158 } 17159 index++; 17160 } 17161 return (BCM_E_NONE); 17162 } 17163 17164 /* 17165 * Function: 17166 * _bcm_tr2_mirror_port_egress_true_dest_get 17167 * Description: 17168 * Get IP ingress/egress mirroring destinations for the specific port. 17169 * Parameters: 17170 * unit - (IN) BCM device number. 17171 * port - (IN) Mirror source gport. 17172 * array_sz - (IN) Sizeof dest_array parameter. 17173 * dest_array - (OUT) Mirror to port array. 17174 * Returns: 17175 * BCM_E_XXX 17176 */ 17177 STATIC int 17178 _bcm_tr2_mirror_port_egress_true_dest_get(int unit, bcm_port_t port, 17179 int array_sz, 17180 bcm_gport_t *dest_array) 17181 { 17182 int enable; /* Mirror enable bitmap. */ 17183 int index; /* Destination iteration index.*/ 17184 int mtp_index; 17185 17186 /* Input parameters check. */ 17187 if ((NULL == dest_array) || (0 == array_sz)) { 17188 return (BCM_E_PARAM); 17189 } 17190 17191 /* Reset destination array. */ 17192 for (index = 0; index < array_sz; index ++) { 17193 dest_array[index] = BCM_GPORT_INVALID; 17194 } 17195 17196 /* Read mtp egress true mtp enable bitmap for source port. */ 17197 BCM_IF_ERROR_RETURN 17198 (_bcm_port_mirror_egress_true_enable_get(unit, port, &enable)); 17199 17200 if (!enable) { 17201 return (BCM_E_NONE); 17202 } 17203 17204 index = 0; 17205 17206 /* Egress true mirroring uses 1-1 MTP index to slot mapping */ 17207 for (mtp_index = 0; mtp_index < BCM_MIRROR_MTP_COUNT; mtp_index++) { 17208 if (enable & (1 << mtp_index)) { 17209 dest_array[index] = 17210 MIRROR_CONFIG_EGR_TRUE_MTP_DEST(unit, mtp_index); 17211 index++; 17212 } 17213 } 17214 17215 return (BCM_E_NONE); 17216 } 17217 17218 /* 17219 * Function: 17220 * _bcm_tr2_mirror_ipipe_egress_mtp_uninstall 17221 * Description: 17222 * Reset IPIPE egress reserved mtp index from 17223 * mirror control register. 17224 * Parameters: 17225 * unit - (IN) BCM device number. 17226 * port - (IN) Mirror source gport. 17227 * mtp_index - (IN) Mirror to port index. 17228 * Returns: 17229 * BCM_E_XXX 17230 */ 17231 STATIC int 17232 _bcm_tr2_mirror_ipipe_egress_mtp_uninstall(int unit, bcm_port_t port, 17233 int mtp_index) 17234 { 17235 int enable; /* Used mtp bit map. */ 17236 int mtp_slot; /* MTP type value */ 17237 17238 BCM_IF_ERROR_RETURN(_bcm_esw_mirror_egress_get(unit, port, &enable)); 17239 17240 if (MIRROR_MTP_METHOD_IS_DIRECTED_FLEXIBLE(unit)) { 17241 BCM_IF_ERROR_RETURN 17242 (_bcm_xgs3_mtp_index_port_slot_get(unit, port, enable, TRUE, 17243 mtp_index, BCM_MTP_SLOT_TYPE_PORT, &mtp_slot)); 17244 } else { 17245 /* Otherwise the slot and index is 1-1 */ 17246 mtp_slot = mtp_index; 17247 } 17248 17249 /* if mtp is not enabled on port - do nothing */ 17250 if (!(enable & (1 << mtp_slot))) { 17251 return (BCM_E_NOT_FOUND); 17252 } 17253 17254 /* Update egress enables */ 17255 enable &= ~(1 << mtp_slot); 17256 BCM_IF_ERROR_RETURN(_bcm_esw_mirror_egress_set(unit, port, enable)); 17257 17258 if (MIRROR_MTP_METHOD_IS_DIRECTED_FLEXIBLE(unit)) { 17259 BCM_IF_ERROR_RETURN 17260 (_bcm_xgs3_mtp_type_slot_unreserve(unit, 17261 BCM_MIRROR_PORT_EGRESS, 17262 port, 17263 BCM_MTP_SLOT_TYPE_PORT, 17264 mtp_index)); 17265 17266 } 17267 return (BCM_E_NONE); 17268 } 17269 17270 /* 17271 * Function: 17272 * _bcm_tr2_mirror_egress_true_mtp_uninstall 17273 * Description: 17274 * Uninstall egress true mirroring reserved mtp index from 17275 * mirror control register. 17276 * Parameters: 17277 * unit - (IN) BCM device number. 17278 * port - (IN) Mirror source gport. 17279 * mtp_index - (IN) Mirror to port index. 17280 * Returns: 17281 * BCM_E_XXX 17282 */ 17283 STATIC int 17284 _bcm_tr2_mirror_egress_true_mtp_uninstall(int unit, bcm_port_t port, 17285 int mtp_index) 17286 { 17287 int enable; /* Used mtp bit map. */ 17288 int rv = BCM_E_NOT_FOUND; /* Operation return status. */ 17289 17290 /* Read mtp egress true mtp enable bitmap for source port. */ 17291 BCM_IF_ERROR_RETURN 17292 (_bcm_port_mirror_egress_true_enable_get(unit, port, &enable)); 17293 17294 if ((enable & (1 << mtp_index))) { 17295 enable &= ~(1 << mtp_index); 17296 rv =_bcm_port_mirror_egress_true_enable_set(unit, port, enable); 17297 } 17298 17299 return rv; 17300 } 17301 #endif /* BCM_TRIUMPH2_SUPPORT */ 17302 17303 /* 17304 * Function: 17305 * _bcm_xgs3_mirror_ingress_mtp_install 17306 * Description: 17307 * Install ingress reserved mtp index into 17308 * mirror control register. 17309 * Parameters: 17310 * unit - (IN) BCM device number. 17311 * port - (IN) Mirror source gport. 17312 * mtp_index - (IN) Mirror to port index. 17313 * Returns: 17314 * BCM_E_XXX 17315 */ 17316 STATIC int 17317 _bcm_xgs3_mirror_ingress_mtp_install(int unit, bcm_port_t port, 17318 int mtp_index) 17319 { 17320 uint32 reg_val; /* MTP control register value. */ 17321 int enable = 0; /* Used mtp bit map. */ 17322 int rv = BCM_E_RESOURCE; /* Operation return status. */ 17323 int hw_mtp; /* Hw installed mtp index. */ 17324 int mtp_slot_check = 0; /* MTP Slot map status. */ 17325 int orig_enable_mtp_map = 0; /* Original Ingress enable */ 17326 int flags = 0; /* Slot Check Flag */ 17327 17328 /* Read mtp ingress mtp enable bitmap for source port. */ 17329 BCM_IF_ERROR_RETURN(_bcm_esw_mirror_ingress_get(unit, port, &enable)); 17330 17331 #ifdef BCM_TRIUMPH2_SUPPORT 17332 if (soc_feature(unit, soc_feature_mirror_flexible)) { 17333 int mtp_slot; /* MTP type value */ 17334 17335 if (MIRROR_MTP_METHOD_IS_DIRECTED_FLEXIBLE(unit)) { 17336 BCM_IF_ERROR_RETURN 17337 (_bcm_xgs3_mtp_type_slot_reserve(unit, 17338 BCM_MIRROR_PORT_INGRESS, 17339 enable, port, 17340 BCM_MTP_SLOT_TYPE_PORT, 17341 mtp_index, &mtp_slot)); 17342 } else { 17343 /* Otherwise the slot and index is 1-1 */ 17344 mtp_slot = mtp_index; 17345 } 17346 17347 /* if mtp is enabled on port - inform caller */ 17348 if (enable & (1 << mtp_slot)) { 17349 return (BCM_E_EXISTS); 17350 } 17351 17352 /* Enable mirroring on the port. */ 17353 enable |= (1 << mtp_slot); 17354 return _bcm_esw_mirror_ingress_set(unit, port, enable); 17355 } 17356 #endif /* BCM_TRIUMPH2_SUPPORT */ 17357 17358 /* Check if slot container are occupied earlier by other module , ignore if not set*/ 17359 if (MIRROR_SWITCH_IS_EXCLUSIVE(unit)) { 17360 orig_enable_mtp_map = enable; 17361 flags = _BCM_MIRROR_SLOT_INGRESS | _BCM_MIRROR_SLOT_PORT; 17362 BCM_IF_ERROR_RETURN 17363 (_bcm_esw_mtp_slot_valid_get(unit, 17364 flags, 17365 &mtp_slot_check)); 17366 enable = enable | mtp_slot_check; 17367 } 17368 17369 /* Read mirror control register to compare programmed mtp indexes. */ 17370 BCM_IF_ERROR_RETURN(READ_MIRROR_CONTROLr(unit, port, ®_val)); 17371 17372 if (!(enable & BCM_MIRROR_MTP_ONE)) { 17373 /* Mtp one is available */ 17374 soc_reg_field_set(unit, MIRROR_CONTROLr, ®_val, 17375 IM_MTP_INDEXf, mtp_index); 17376 17377 /* Retreive orig enable on port */ 17378 if (MIRROR_SWITCH_IS_EXCLUSIVE(unit)) { 17379 enable = orig_enable_mtp_map; 17380 MIRROR_CONFIG_ING_MTP_SLOT_OWNER 17381 (unit, _BCM_MIRROR_SLOT_CONT0) 17382 |= _BCM_MIRROR_SLOT_OWNER_PORT; 17383 MIRROR_CONFIG_ING_MTP_SLOT_REF 17384 (unit, _BCM_MIRROR_SLOT_CONT0)++; 17385 } 17386 17387 /* Set mtp index in Mirror control. */ 17388 BCM_IF_ERROR_RETURN(WRITE_MIRROR_CONTROLr(unit, port, reg_val)); 17389 17390 /* Enable ingress mirroring on the port. */ 17391 enable |= BCM_MIRROR_MTP_ONE; 17392 BCM_IF_ERROR_RETURN 17393 (_bcm_esw_mirror_ingress_set(unit, port, enable)); 17394 if (IS_HG_PORT(unit, port)) { 17395 BCM_IF_ERROR_RETURN 17396 (soc_reg_field32_modify(unit, IMIRROR_CONTROLr, 17397 port, IM_MTP_INDEXf, 17398 mtp_index)); 17399 } 17400 rv = (BCM_E_NONE); 17401 } else { 17402 /* Mtp one is in use */ 17403 /* Check if mtp is already installed. */ 17404 hw_mtp = soc_reg_field_get(unit, MIRROR_CONTROLr, reg_val, 17405 IM_MTP_INDEXf); 17406 if (mtp_index == hw_mtp) { 17407 rv = (BCM_E_EXISTS); 17408 } 17409 } 17410 17411 #if defined(BCM_TRX_SUPPORT) 17412 if (SOC_IS_TRX(unit) && BCM_FAILURE(rv) && 17413 soc_reg_field_valid(unit, MIRROR_CONTROLr, IM_MTP_INDEX1f)) { 17414 if (!(enable & BCM_MIRROR_MTP_TWO)) { 17415 /* Mtp two is available */ 17416 soc_reg_field_set(unit, MIRROR_CONTROLr, ®_val, 17417 IM_MTP_INDEX1f, mtp_index); 17418 17419 /* Retreive orig enable on port */ 17420 if (MIRROR_SWITCH_IS_EXCLUSIVE(unit)) { 17421 enable = orig_enable_mtp_map; 17422 MIRROR_CONFIG_ING_MTP_SLOT_OWNER 17423 (unit, _BCM_MIRROR_SLOT_CONT1) 17424 |= _BCM_MIRROR_SLOT_OWNER_PORT; 17425 MIRROR_CONFIG_ING_MTP_SLOT_REF 17426 (unit, _BCM_MIRROR_SLOT_CONT1)++; 17427 } 17428 17429 /* Set mtp index in Mirror control. */ 17430 BCM_IF_ERROR_RETURN(WRITE_MIRROR_CONTROLr(unit, port, reg_val)); 17431 17432 /* Enable ingress mirroring on the port. */ 17433 enable |= BCM_MIRROR_MTP_TWO; 17434 BCM_IF_ERROR_RETURN 17435 (_bcm_esw_mirror_ingress_set(unit, port, enable)); 17436 if (IS_HG_PORT(unit, port)) { 17437 BCM_IF_ERROR_RETURN 17438 (soc_reg_field32_modify(unit, IMIRROR_CONTROLr, 17439 port, IM_MTP_INDEX1f, 17440 mtp_index)); 17441 } 17442 rv = (BCM_E_NONE); 17443 } else { 17444 /* Mtp two is in use */ 17445 /* Check if mtp is already installed. */ 17446 hw_mtp = soc_reg_field_get(unit, MIRROR_CONTROLr,reg_val, 17447 IM_MTP_INDEX1f); 17448 if (mtp_index == hw_mtp) { 17449 rv = (BCM_E_EXISTS); 17450 } 17451 } 17452 } 17453 #endif /* BCM_TRX_SUPPORT */ 17454 return (rv); 17455 } 17456 17457 /* 17458 * Function: 17459 * _bcm_xgs3_mirror_egress_mtp_install 17460 * Description: 17461 * Install egress reserved mtp index into 17462 * mirror control register. 17463 * Parameters: 17464 * unit - (IN) BCM device number. 17465 * port - (IN) Mirror source gport. 17466 * mtp_index - (IN) Mirror to port index. 17467 * Returns: 17468 * BCM_E_XXX 17469 */ 17470 STATIC int 17471 _bcm_xgs3_mirror_egress_mtp_install(int unit, bcm_port_t port, int mtp_index) 17472 { 17473 uint32 reg_val; /* MTP control register value. */ 17474 int enable = 0; /* Used mtp bit map. */ 17475 int port_enable = 0; /* This port's enabled mtp bit map.*/ 17476 int hw_mtp; /* Hw installed mtp index. */ 17477 int rv = BCM_E_RESOURCE; /* Operation return status. */ 17478 uint32 values[2]; 17479 soc_field_t fields[2] = {EM_MTP_INDEXf, NON_UC_EM_MTP_INDEXf}; 17480 bcm_port_t port_iterator; 17481 int mtp_slot_check = 0; /* MTP Slot map status. */ 17482 int orig_enable_mtp_map = 0; /* Original Egress enable */ 17483 int flags = 0; /* Slot Check Flag */ 17484 int use_cont_two = 0; /* mirror container 2 flag */ 17485 17486 #ifdef BCM_TRIUMPH2_SUPPORT 17487 if (soc_feature(unit, soc_feature_mirror_flexible)) { 17488 return _bcm_tr2_mirror_ipipe_egress_mtp_install(unit, port, 17489 mtp_index); 17490 } 17491 #endif /* BCM_TRIUMPH2_SUPPORT */ 17492 17493 values[0] = values[1] = mtp_index; 17494 17495 /* Read mtp egress mtp enable bitmap for source port. */ 17496 BCM_IF_ERROR_RETURN 17497 (_bcm_esw_mirror_egress_get(unit, port, &port_enable)); 17498 /* Read mtp egress mtp enable bitmap for any ports. */ 17499 BCM_IF_ERROR_RETURN 17500 (_bcm_esw_mirror_egress_get(unit, BCM_GPORT_INVALID, &enable)); 17501 17502 /* Check if slot container are occupied earlier by other module , ignore if not set*/ 17503 if (MIRROR_SWITCH_IS_EXCLUSIVE(unit)) { 17504 orig_enable_mtp_map = enable; 17505 flags = _BCM_MIRROR_SLOT_EGRESS | _BCM_MIRROR_SLOT_PORT; 17506 BCM_IF_ERROR_RETURN 17507 (_bcm_esw_mtp_slot_valid_get(unit, 17508 flags, 17509 &mtp_slot_check)); 17510 enable = enable | mtp_slot_check; 17511 } 17512 17513 /* Read mirror control register to compare programmed mtp indexes. */ 17514 BCM_IF_ERROR_RETURN(READ_MIRROR_CONTROLr(unit, port, ®_val)); 17515 17516 /* First check if container two is enabled and have same mtp index to install. 17517 * If yes then skip container one */ 17518 #if defined(BCM_TRX_SUPPORT) 17519 if (SOC_IS_TRX(unit) && 17520 soc_reg_field_valid(unit, MIRROR_CONTROLr, EM_MTP_INDEX1f)) { 17521 if (enable & BCM_MIRROR_MTP_TWO) { 17522 hw_mtp = soc_reg_field_get(unit, MIRROR_CONTROLr, reg_val, 17523 EM_MTP_INDEX1f); 17524 if (mtp_index == hw_mtp) { 17525 use_cont_two = 1; 17526 } 17527 } 17528 } 17529 #endif 17530 17531 if (!use_cont_two) { 17532 if (!(enable & BCM_MIRROR_MTP_ONE)) { 17533 /* Mtp one is available */ 17534 17535 /* Retreive orig enable on port */ 17536 if (MIRROR_SWITCH_IS_EXCLUSIVE(unit)) { 17537 enable = orig_enable_mtp_map; 17538 MIRROR_CONFIG_EGR_MTP_SLOT_OWNER 17539 (unit, _BCM_MIRROR_SLOT_CONT0) 17540 |= _BCM_MIRROR_SLOT_OWNER_PORT; 17541 MIRROR_CONFIG_EGR_MTP_SLOT_REF 17542 (unit, _BCM_MIRROR_SLOT_CONT0)++; 17543 } 17544 17545 /* Set all ingress ports to know the MTP index for the 17546 * egress port to be mirrored. */ 17547 PBMP_ALL_ITER(unit, port_iterator) { 17548 BCM_IF_ERROR_RETURN 17549 (soc_reg_fields32_modify(unit, MIRROR_CONTROLr, 17550 port_iterator, 2, fields, values)); 17551 } 17552 /* Also enable the CPU's HG flow */ 17553 BCM_IF_ERROR_RETURN 17554 (soc_reg_fields32_modify(unit, IMIRROR_CONTROLr, 17555 CMIC_PORT(unit), 2, fields, values)); 17556 17557 /* Enable egress mirroring. */ 17558 port_enable |= BCM_MIRROR_MTP_ONE; 17559 BCM_IF_ERROR_RETURN 17560 (_bcm_esw_mirror_egress_set(unit, port, port_enable)); 17561 17562 rv = (BCM_E_NONE); 17563 } else { 17564 /* Mtp one is in use */ 17565 /* Check if mtp is already installed on this port. */ 17566 hw_mtp = soc_reg_field_get (unit, MIRROR_CONTROLr, reg_val, 17567 EM_MTP_INDEXf); 17568 17569 if (mtp_index == hw_mtp) { 17570 if (port_enable & BCM_MIRROR_MTP_ONE) { 17571 rv = (BCM_E_EXISTS); 17572 } else { 17573 /* MTP one already configured the correct MTP on other ports. 17574 * This port must be enabled for it. */ 17575 port_enable |= BCM_MIRROR_MTP_ONE; 17576 BCM_IF_ERROR_RETURN 17577 (_bcm_esw_mirror_egress_set(unit, port, port_enable)); 17578 rv = (BCM_E_NONE); 17579 } 17580 } 17581 } 17582 } 17583 17584 #if defined(BCM_TRX_SUPPORT) 17585 if (SOC_IS_TRX(unit) && BCM_FAILURE(rv) && 17586 soc_reg_field_valid(unit, MIRROR_CONTROLr, EM_MTP_INDEX1f)) { 17587 if (!(enable & BCM_MIRROR_MTP_TWO)) { 17588 /* Mtp two is available */ 17589 17590 /* Retreive orig enable on port */ 17591 if (MIRROR_SWITCH_IS_EXCLUSIVE(unit)) { 17592 enable = orig_enable_mtp_map; 17593 MIRROR_CONFIG_EGR_MTP_SLOT_OWNER 17594 (unit, _BCM_MIRROR_SLOT_CONT1) 17595 |= _BCM_MIRROR_SLOT_OWNER_PORT; 17596 MIRROR_CONFIG_EGR_MTP_SLOT_REF 17597 (unit, _BCM_MIRROR_SLOT_CONT1)++; 17598 } 17599 17600 /* Set all ingress ports to know the MTP index for the 17601 * egress port to be mirrored. */ 17602 fields[0] = EM_MTP_INDEX1f; 17603 fields[1] = NON_UC_EM_MTP_INDEX1f; 17604 PBMP_ALL_ITER(unit, port_iterator) { 17605 BCM_IF_ERROR_RETURN 17606 (soc_reg_fields32_modify(unit, MIRROR_CONTROLr, 17607 port_iterator, 17608 2, fields, values)); 17609 } 17610 /* Also enable the CPU's HG flow */ 17611 BCM_IF_ERROR_RETURN 17612 (soc_reg_fields32_modify(unit, IMIRROR_CONTROLr, 17613 CMIC_PORT(unit), 17614 2, fields, values)); 17615 17616 /* Enable ingress mirroring on the port. */ 17617 port_enable |= BCM_MIRROR_MTP_TWO; 17618 BCM_IF_ERROR_RETURN 17619 (_bcm_esw_mirror_egress_set(unit, port, port_enable)); 17620 17621 rv = (BCM_E_NONE); 17622 } else { 17623 /* Mtp one is in use */ 17624 /* Check if mtp is already installed on this port. */ 17625 hw_mtp = soc_reg_field_get(unit, MIRROR_CONTROLr, reg_val, 17626 EM_MTP_INDEX1f); 17627 if (mtp_index == hw_mtp) { 17628 if (port_enable & BCM_MIRROR_MTP_TWO) { 17629 rv = (BCM_E_EXISTS); 17630 } else { 17631 /* MTP one already configured the correct MTP 17632 * on other ports. 17633 * This port must be enabled for it. */ 17634 port_enable |= BCM_MIRROR_MTP_TWO; 17635 BCM_IF_ERROR_RETURN 17636 (_bcm_esw_mirror_egress_set(unit, port, 17637 port_enable)); 17638 rv = (BCM_E_NONE); 17639 } 17640 } 17641 } 17642 } 17643 #endif /* BCM_TRX_SUPPORT */ 17644 return (rv); 17645 } 17646 17647 /* 17648 * Function: 17649 * _bcm_xgs3_mirror_port_ingress_dest_get 17650 * Description: 17651 * Get ingress mirroring destinations for the specific port 17652 * Parameters: 17653 * unit - (IN) BCM device number. 17654 * port - (IN) Mirror source gport. 17655 * array_sz - (IN) Sizeof dest_array parameter. 17656 * dest_array - (OUT) Mirror to port array. 17657 * Returns: 17658 * BCM_E_XXX 17659 */ 17660 STATIC int 17661 _bcm_xgs3_mirror_port_ingress_dest_get(int unit, bcm_port_t port, 17662 int array_sz, bcm_gport_t *dest_array, int vp) 17663 { 17664 uint32 mtp_value; /* MTP index value. */ 17665 uint32 reg_val; /* MTP control register value. */ 17666 int enable; /* Mirror enable bitmap. */ 17667 int index; /* Destination iteration index.*/ 17668 17669 /* Input parameters check. */ 17670 if ((NULL == dest_array) || (0 == array_sz)) { 17671 return (BCM_E_PARAM); 17672 } 17673 17674 /* Reset destination array. */ 17675 for (index = 0; index < array_sz; index ++) { 17676 dest_array[index] = BCM_GPORT_INVALID; 17677 } 17678 17679 #ifdef BCM_TRIUMPH2_SUPPORT 17680 if (soc_feature(unit, soc_feature_mirror_flexible)) { 17681 return _bcm_tr2_mirror_port_ipipe_dest_get(unit, port, array_sz, 17682 dest_array, FALSE, vp); 17683 } 17684 #endif /* BCM_TRIUMPH2_SUPPORT */ 17685 17686 17687 /* Read mtp ingress mtp enable bitmap for source port. */ 17688 BCM_IF_ERROR_RETURN(_bcm_esw_mirror_ingress_get(unit, port, &enable)); 17689 17690 if (!enable) { 17691 return (BCM_E_NONE); 17692 } 17693 17694 /* Read mirror control register to compare programmed mtp indexes. */ 17695 BCM_IF_ERROR_RETURN(READ_MIRROR_CONTROLr(unit, port, ®_val)); 17696 17697 index = 0; 17698 17699 if (enable & BCM_MIRROR_MTP_ONE) { 17700 /* Mtp one is in use */ 17701 mtp_value = soc_reg_field_get(unit, MIRROR_CONTROLr, 17702 reg_val, IM_MTP_INDEXf); 17703 17704 dest_array[index] = MIRROR_CONFIG_ING_MTP_DEST(unit, mtp_value); 17705 index++; 17706 } 17707 17708 #if defined(BCM_TRX_SUPPORT) 17709 if (SOC_IS_TRX(unit) && (index < array_sz) ){ 17710 if (enable & BCM_MIRROR_MTP_TWO) { 17711 /* Mtp two is in use */ 17712 mtp_value = soc_reg_field_get(unit, MIRROR_CONTROLr, 17713 reg_val, IM_MTP_INDEX1f); 17714 17715 dest_array[index] = MIRROR_CONFIG_ING_MTP_DEST(unit, mtp_value); 17716 index++; 17717 } 17718 } 17719 #endif /* BCM_TRX_SUPPORT */ 17720 return (BCM_E_NONE); 17721 } 17722 17723 17724 /* 17725 * Function: 17726 * _bcm_xgs3_mirror_port_egress_dest_get 17727 * Description: 17728 * Get egress mirroring destinations for the specific port 17729 * Parameters: 17730 * unit - (IN) BCM device number. 17731 * port - (IN) Mirror source gport. 17732 * array_sz - (IN) Sizeof dest_array parameter. 17733 * dest_array - (OUT) Mirror to port array. 17734 * Returns: 17735 * BCM_E_XXX 17736 */ 17737 STATIC int 17738 _bcm_xgs3_mirror_port_egress_dest_get(int unit, bcm_port_t port, int array_sz, 17739 bcm_gport_t *dest_array, int vp) 17740 { 17741 uint32 mtp_value; /* MTP index value. */ 17742 uint32 reg_val; /* MTP control register value. */ 17743 int enable; /* Mirror enable bitmap. */ 17744 int index; /* Destination iteration index.*/ 17745 17746 /* Input parameters check. */ 17747 if ((NULL == dest_array) || (0 == array_sz)) { 17748 return (BCM_E_PARAM); 17749 } 17750 17751 /* Reset destination array. */ 17752 for (index = 0; index < array_sz; index ++) { 17753 dest_array[index] = BCM_GPORT_INVALID; 17754 } 17755 17756 #ifdef BCM_TRIUMPH2_SUPPORT 17757 if (soc_feature(unit, soc_feature_mirror_flexible)) { 17758 return _bcm_tr2_mirror_port_ipipe_dest_get(unit, port, array_sz, 17759 dest_array, TRUE, vp); 17760 } 17761 #endif /* BCM_TRIUMPH2_SUPPORT */ 17762 17763 /* Read mtp ingress mtp enable enable bitmap for source port. */ 17764 BCM_IF_ERROR_RETURN(_bcm_esw_mirror_egress_get(unit, port, &enable)); 17765 17766 if (!enable) { 17767 return (BCM_E_NONE); 17768 } 17769 17770 /* Read mirror control register to compare programmed mtp indexes. */ 17771 BCM_IF_ERROR_RETURN(READ_MIRROR_CONTROLr(unit, port, ®_val)); 17772 17773 index = 0; 17774 17775 if (enable & BCM_MIRROR_MTP_ONE) { 17776 /* Mtp one is in use */ 17777 mtp_value = soc_reg_field_get(unit, MIRROR_CONTROLr, 17778 reg_val, EM_MTP_INDEXf); 17779 17780 dest_array[index] = MIRROR_CONFIG_EGR_MTP_DEST(unit, mtp_value); 17781 index++; 17782 } 17783 17784 #if defined(BCM_TRX_SUPPORT) 17785 if (SOC_IS_TRX(unit) && (index < array_sz) ){ 17786 if (enable & BCM_MIRROR_MTP_TWO) { 17787 /* Mtp two is in use */ 17788 mtp_value = soc_reg_field_get(unit, MIRROR_CONTROLr, 17789 reg_val, EM_MTP_INDEX1f); 17790 17791 dest_array[index] = MIRROR_CONFIG_EGR_MTP_DEST(unit, mtp_value); 17792 index++; 17793 } 17794 } 17795 #endif /* BCM_TRX_SUPPORT */ 17796 return (BCM_E_NONE); 17797 } 17798 17799 /* 17800 * Function: 17801 * _bcm_xgs3_mirror_ingress_mtp_uninstall 17802 * Description: 17803 * Reset ingress reserved mtp index from 17804 * mirror control register. 17805 * Parameters: 17806 * unit - (IN) BCM device number. 17807 * port - (IN) Mirror source gport. 17808 * mtp_index - (IN) Mirror to port index. 17809 * Returns: 17810 * BCM_E_XXX 17811 */ 17812 STATIC int 17813 _bcm_xgs3_mirror_ingress_mtp_uninstall(int unit, bcm_port_t port, int mtp_index) 17814 { 17815 int mtp_value; /* MTP index value. */ 17816 uint32 reg_val; /* MTP control register value. */ 17817 int enable; /* Mirror enable bitmap. */ 17818 int rv = BCM_E_NOT_FOUND; /* Operation return status. */ 17819 17820 /* Read mtp ingress mtp enable enable bitmap for source port. */ 17821 BCM_IF_ERROR_RETURN(_bcm_esw_mirror_ingress_get(unit, port, &enable)); 17822 17823 #ifdef BCM_TRIUMPH2_SUPPORT 17824 if (soc_feature(unit, soc_feature_mirror_flexible)) { 17825 int mtp_slot; /* MTP type value */ 17826 17827 if (MIRROR_MTP_METHOD_IS_DIRECTED_FLEXIBLE(unit)) { 17828 BCM_IF_ERROR_RETURN 17829 (_bcm_xgs3_mtp_index_port_slot_get(unit, port, 17830 enable, FALSE, 17831 mtp_index, BCM_MTP_SLOT_TYPE_PORT, &mtp_slot)); 17832 } else { 17833 mtp_slot = mtp_index; 17834 } 17835 17836 if (enable & (1 << mtp_slot)) { 17837 enable &= ~(1 << mtp_slot); 17838 BCM_IF_ERROR_RETURN 17839 (_bcm_esw_mirror_ingress_set(unit, port, enable)); 17840 rv = BCM_E_NONE; 17841 } 17842 17843 if (BCM_SUCCESS(rv) && 17844 MIRROR_MTP_METHOD_IS_DIRECTED_FLEXIBLE(unit)) { 17845 BCM_IF_ERROR_RETURN 17846 (_bcm_xgs3_mtp_type_slot_unreserve(unit, 17847 BCM_MIRROR_PORT_INGRESS, 17848 port, 17849 BCM_MTP_SLOT_TYPE_PORT, 17850 mtp_index)); 17851 17852 } 17853 return rv; 17854 } 17855 #endif /* BCM_TRIUMPH2_SUPPORT */ 17856 17857 if (enable) { 17858 /* Read mirror control register to compare programmed mtp indexes. */ 17859 BCM_IF_ERROR_RETURN(READ_MIRROR_CONTROLr(unit, port, ®_val)); 17860 } 17861 17862 if (enable & BCM_MIRROR_MTP_ONE) { 17863 /* Mtp one is in use */ 17864 mtp_value = soc_reg_field_get(unit, MIRROR_CONTROLr, 17865 reg_val, IM_MTP_INDEXf); 17866 17867 if (mtp_value == mtp_index) { 17868 /* Removed mtp was found -> disable it. */ 17869 17870 if (MIRROR_SWITCH_IS_EXCLUSIVE(unit)) { 17871 if(MIRROR_CONFIG_ING_MTP_SLOT_REF 17872 (unit, _BCM_MIRROR_SLOT_CONT0)) 17873 MIRROR_CONFIG_ING_MTP_SLOT_REF 17874 (unit, _BCM_MIRROR_SLOT_CONT0)--; 17875 17876 if(MIRROR_CONFIG_ING_MTP_SLOT_REF 17877 (unit, _BCM_MIRROR_SLOT_CONT0) == 0) 17878 MIRROR_CONFIG_ING_MTP_SLOT_OWNER 17879 (unit, _BCM_MIRROR_SLOT_CONT0) 17880 &= ~(_BCM_MIRROR_SLOT_OWNER_PORT); 17881 } 17882 17883 /* Disable ingress mirroring on port. */ 17884 enable &= ~BCM_MIRROR_MTP_ONE; 17885 BCM_IF_ERROR_RETURN 17886 (_bcm_esw_mirror_ingress_set(unit, port, enable)); 17887 17888 /* Reset ingress mirroring mtp index. */ 17889 BCM_IF_ERROR_RETURN 17890 (soc_reg_field32_modify(unit, MIRROR_CONTROLr, 17891 port, IM_MTP_INDEXf, 0)); 17892 17893 if (IS_HG_PORT(unit, port)) { 17894 BCM_IF_ERROR_RETURN 17895 (soc_reg_field32_modify(unit, IMIRROR_CONTROLr, 17896 port, IM_MTP_INDEXf, 0)); 17897 } 17898 rv = (BCM_E_NONE); 17899 } 17900 } 17901 17902 #if defined(BCM_TRX_SUPPORT) 17903 if (SOC_IS_TRX(unit) && BCM_FAILURE(rv)){ 17904 if (enable & BCM_MIRROR_MTP_TWO) { 17905 /* Mtp one is in use */ 17906 mtp_value = soc_reg_field_get(unit, MIRROR_CONTROLr, 17907 reg_val, IM_MTP_INDEX1f); 17908 17909 if (mtp_value == mtp_index) { 17910 /* Removed mtp was found -> disable it. */ 17911 17912 if (MIRROR_SWITCH_IS_EXCLUSIVE(unit)) { 17913 if(MIRROR_CONFIG_ING_MTP_SLOT_REF 17914 (unit, _BCM_MIRROR_SLOT_CONT1)) 17915 MIRROR_CONFIG_ING_MTP_SLOT_REF 17916 (unit, _BCM_MIRROR_SLOT_CONT1)--; 17917 17918 if(MIRROR_CONFIG_ING_MTP_SLOT_REF 17919 (unit, _BCM_MIRROR_SLOT_CONT1) == 0) 17920 MIRROR_CONFIG_ING_MTP_SLOT_OWNER 17921 (unit, _BCM_MIRROR_SLOT_CONT1) 17922 &= ~(_BCM_MIRROR_SLOT_OWNER_PORT); 17923 } 17924 17925 /* Disable ingress mirroring on port. */ 17926 enable &= ~BCM_MIRROR_MTP_TWO; 17927 BCM_IF_ERROR_RETURN 17928 (_bcm_esw_mirror_ingress_set(unit, port, enable)); 17929 17930 /* Reset ingress mirroring mtp index. */ 17931 BCM_IF_ERROR_RETURN 17932 (soc_reg_field32_modify(unit, MIRROR_CONTROLr, 17933 port, IM_MTP_INDEX1f, 0)); 17934 17935 if (IS_HG_PORT(unit, port)) { 17936 BCM_IF_ERROR_RETURN 17937 (soc_reg_field32_modify(unit, IMIRROR_CONTROLr, 17938 port, IM_MTP_INDEX1f, 0)); 17939 } 17940 rv = (BCM_E_NONE); 17941 } 17942 } 17943 } 17944 #endif /* BCM_TRX_SUPPORT */ 17945 return (rv); 17946 } 17947 17948 /* 17949 * Function: 17950 * _bcm_xgs3_mirror_egress_mtp_uninstall 17951 * Description: 17952 * Reset egress reserved mtp index from 17953 * mirror control register. 17954 * Parameters: 17955 * unit - (IN) BCM device number. 17956 * port - (IN) Mirror source gport. 17957 * mtp_index - (IN) Mirror to port index. 17958 * Returns: 17959 * BCM_E_XXX 17960 */ 17961 STATIC int 17962 _bcm_xgs3_mirror_egress_mtp_uninstall(int unit, bcm_port_t port, 17963 int mtp_index) 17964 { 17965 int mtp_value; /* MTP index value. */ 17966 uint32 reg_val; /* MTP control register value. */ 17967 int enable; /* Mirror enable bitmap. */ 17968 int port_enable; /* This port's enabled mtp bit map.*/ 17969 int rv = BCM_E_NOT_FOUND; /* Operation return status. */ 17970 uint32 values[2] = {0, 0}; 17971 soc_field_t fields[2] = {EM_MTP_INDEXf, NON_UC_EM_MTP_INDEXf}; 17972 bcm_port_t port_iterator; 17973 17974 #ifdef BCM_TRIUMPH2_SUPPORT 17975 if (soc_feature(unit, soc_feature_mirror_flexible)) { 17976 return _bcm_tr2_mirror_ipipe_egress_mtp_uninstall(unit, port, 17977 mtp_index); 17978 } 17979 #endif /* BCM_TRIUMPH2_SUPPORT */ 17980 17981 /* Read mtp egress mtp enable bitmap for source port. */ 17982 BCM_IF_ERROR_RETURN 17983 (_bcm_esw_mirror_egress_get(unit, port, &port_enable)); 17984 17985 if (port_enable) { 17986 /* Read mirror control register to compare programmed mtp indexes. */ 17987 BCM_IF_ERROR_RETURN(READ_MIRROR_CONTROLr(unit, port, ®_val)); 17988 } 17989 17990 if (port_enable & BCM_MIRROR_MTP_ONE) { 17991 /* Mtp one is in use */ 17992 mtp_value = soc_reg_field_get(unit, MIRROR_CONTROLr, 17993 reg_val, EM_MTP_INDEXf); 17994 17995 if (mtp_value == mtp_index) { 17996 /* Removed mtp was found -> disable it. */ 17997 17998 if (MIRROR_SWITCH_IS_EXCLUSIVE(unit)) { 17999 if(MIRROR_CONFIG_EGR_MTP_SLOT_REF 18000 (unit, _BCM_MIRROR_SLOT_CONT0)) 18001 MIRROR_CONFIG_EGR_MTP_SLOT_REF 18002 (unit, _BCM_MIRROR_SLOT_CONT0)--; 18003 18004 if(MIRROR_CONFIG_EGR_MTP_SLOT_REF 18005 (unit, _BCM_MIRROR_SLOT_CONT0) == 0) 18006 MIRROR_CONFIG_EGR_MTP_SLOT_OWNER 18007 (unit, _BCM_MIRROR_SLOT_CONT0) 18008 &= ~(_BCM_MIRROR_SLOT_OWNER_PORT); 18009 } 18010 18011 /* Disable egress mirroring. */ 18012 port_enable &= ~BCM_MIRROR_MTP_ONE; 18013 BCM_IF_ERROR_RETURN 18014 (_bcm_esw_mirror_egress_set(unit, port, port_enable)); 18015 18016 /* Read mtp egress mtp enable bitmap for all ports. */ 18017 BCM_IF_ERROR_RETURN 18018 (_bcm_esw_mirror_egress_get(unit, BCM_GPORT_INVALID, 18019 &enable)); 18020 18021 if (0 == (enable & BCM_MIRROR_MTP_ONE)) { 18022 /* This egress MTP is no longer in use by any port. 18023 * Reset egress mirroring mtp index. */ 18024 PBMP_ALL_ITER(unit, port_iterator) { 18025 BCM_IF_ERROR_RETURN 18026 (soc_reg_fields32_modify(unit, MIRROR_CONTROLr, 18027 port_iterator, 18028 2, fields, values)); 18029 } 18030 /* Also enable the CPU's HG flow */ 18031 BCM_IF_ERROR_RETURN 18032 (soc_reg_fields32_modify(unit, IMIRROR_CONTROLr, 18033 CMIC_PORT(unit), 18034 2, fields, values)); 18035 } 18036 18037 rv = (BCM_E_NONE); 18038 } 18039 } 18040 18041 #if defined(BCM_TRX_SUPPORT) 18042 if (SOC_IS_TRX(unit) && BCM_FAILURE(rv)){ 18043 if (port_enable & BCM_MIRROR_MTP_TWO) { 18044 /* Mtp two is in use */ 18045 mtp_value = soc_reg_field_get(unit, MIRROR_CONTROLr, 18046 reg_val, EM_MTP_INDEX1f); 18047 18048 if (mtp_value == mtp_index) { 18049 /* Removed mtp was found -> disable it. */ 18050 18051 if (MIRROR_SWITCH_IS_EXCLUSIVE(unit)) { 18052 if(MIRROR_CONFIG_EGR_MTP_SLOT_REF 18053 (unit, _BCM_MIRROR_SLOT_CONT1)) 18054 MIRROR_CONFIG_EGR_MTP_SLOT_REF 18055 (unit, _BCM_MIRROR_SLOT_CONT1)--; 18056 18057 if(MIRROR_CONFIG_EGR_MTP_SLOT_REF 18058 (unit, _BCM_MIRROR_SLOT_CONT1) == 0) 18059 MIRROR_CONFIG_EGR_MTP_SLOT_OWNER 18060 (unit, _BCM_MIRROR_SLOT_CONT1) 18061 &= ~(_BCM_MIRROR_SLOT_OWNER_PORT); 18062 } 18063 18064 /* Disable ingress mirroring. */ 18065 port_enable &= ~BCM_MIRROR_MTP_TWO; 18066 BCM_IF_ERROR_RETURN 18067 (_bcm_esw_mirror_egress_set(unit, port, port_enable)); 18068 18069 /* Read mtp egress mtp enable bitmap for all ports. */ 18070 BCM_IF_ERROR_RETURN 18071 (_bcm_esw_mirror_egress_get(unit, BCM_GPORT_INVALID, 18072 &enable)); 18073 18074 if (0 == (enable & BCM_MIRROR_MTP_TWO)) { 18075 /* This egress MTP is no longer in use by any port. 18076 * Reset egress mirroring mtp index. */ 18077 fields[0] = EM_MTP_INDEX1f; 18078 fields[1] = NON_UC_EM_MTP_INDEX1f; 18079 PBMP_ALL_ITER(unit, port_iterator) { 18080 BCM_IF_ERROR_RETURN 18081 (soc_reg_fields32_modify(unit, MIRROR_CONTROLr, 18082 port_iterator, 18083 2, fields, values)); 18084 } 18085 /* Also enable the CPU's HG flow */ 18086 BCM_IF_ERROR_RETURN 18087 (soc_reg_fields32_modify(unit, IMIRROR_CONTROLr, 18088 CMIC_PORT(unit), 18089 2, fields, values)); 18090 } 18091 18092 rv = (BCM_E_NONE); 18093 } 18094 } 18095 } 18096 #endif /* BCM_TRX_SUPPORT */ 18097 return (rv); 18098 } 18099 18100 18101 /* 18102 * Function: 18103 * _bcm_xgs3_mirror_enable_set 18104 * Purpose: 18105 * Enable/disable mirroring on a port. 18106 * Parameters: 18107 * unit - BCM device number 18108 * port - port number 18109 * enable - enable mirroring if non-zero 18110 * Returns: 18111 * BCM_E_XXX 18112 */ 18113 STATIC int 18114 _bcm_xgs3_mirror_enable_set(int unit, int port, int enable) 18115 { 18116 int cpu_hg_index = 0; 18117 18118 /* Higig port should never drop directed mirror packets */ 18119 if (IS_ST_PORT(unit, port) && !MIRROR_MTP_METHOD_IS_NON_DIRECTED(unit)) { 18120 enable = 1; 18121 } 18122 18123 if (soc_feature(unit, soc_feature_mirror_control_mem)) { 18124 BCM_IF_ERROR_RETURN 18125 (soc_mem_field32_modify(unit, MIRROR_CONTROLm, port, M_ENABLEf, 18126 enable)); 18127 18128 cpu_hg_index = SOC_IS_KATANA2(unit) ? 18129 SOC_INFO(unit).cpu_hg_pp_port_index : 18130 SOC_INFO(unit).cpu_hg_index; 18131 #ifdef BCM_TOMAHAWK3_SUPPORT 18132 if (SOC_IS_TOMAHAWK3(unit)) { 18133 /* No higig on TH3, skip programming below */ 18134 cpu_hg_index = -1; 18135 } 18136 #endif /* BCM_TOMAHAWK3_SUPPORT */ 18137 if (IS_CPU_PORT(unit, port) && cpu_hg_index != -1) { 18138 BCM_IF_ERROR_RETURN(soc_mem_field32_modify(unit, MIRROR_CONTROLm, 18139 cpu_hg_index, M_ENABLEf, enable)); 18140 } 18141 } else { 18142 BCM_IF_ERROR_RETURN 18143 (soc_reg_field32_modify(unit, MIRROR_CONTROLr, port, M_ENABLEf, 18144 enable)); 18145 /* Enable mirroring of CPU Higig packets as well */ 18146 if (IS_CPU_PORT(unit, port)) { 18147 BCM_IF_ERROR_RETURN 18148 (soc_reg_field32_modify(unit, IMIRROR_CONTROLr, port, 18149 M_ENABLEf, enable)); 18150 } 18151 } 18152 return (BCM_E_NONE); 18153 } 18154 /* 18155 * Function: 18156 * bcm_xgs3_mirror_egress_path_set 18157 * Description: 18158 * Set egress mirror packet path for stack ring 18159 * Parameters: 18160 * unit - (IN) BCM device number 18161 * modid - (IN) Destination module ID (of mirror-to port) 18162 * port - (IN) Stack port for egress mirror packet 18163 * Returns: 18164 * BCM_E_XXX 18165 * Notes: 18166 * This function should only be used for XGS3 devices stacked 18167 * in a ring configuration with fabric devices that may block 18168 * egress mirror packets when the mirror-to port is on a 18169 * different device than the egress port being mirrored. 18170 * Currently the only such fabric device is BCM5675 rev A0. 18171 */ 18172 int 18173 bcm_xgs3_mirror_egress_path_set(int unit, bcm_module_t modid, bcm_port_t port) 18174 { 18175 alternate_emirror_bitmap_entry_t egr_bmp; 18176 18177 if (!soc_feature(unit, soc_feature_egr_mirror_path)) { 18178 return (BCM_E_UNAVAIL); 18179 } 18180 18181 if ( !SOC_MODID_ADDRESSABLE(unit, modid)){ 18182 return (BCM_E_BADID); 18183 } 18184 if (!IS_ST_PORT(unit, port)) { 18185 return (BCM_E_PORT); 18186 } 18187 18188 BCM_IF_ERROR_RETURN(soc_mem_read(unit, ALTERNATE_EMIRROR_BITMAPm, 18189 MEM_BLOCK_ANY, modid, &egr_bmp)); 18190 #ifdef BCM_TRIUMPH2_SUPPORT 18191 if (SOC_IS_TRIUMPH2(unit) || SOC_IS_APOLLO(unit) || 18192 SOC_IS_VALKYRIE2(unit) ) { 18193 soc_field_t bmapf, bmapf_zero; 18194 uint32 shift; 18195 18196 if (port < 32) { 18197 bmapf = BITMAP_LOf; 18198 bmapf_zero = BITMAP_HIf; 18199 shift = port; 18200 } else { 18201 bmapf = BITMAP_HIf; 18202 bmapf_zero = BITMAP_LOf; 18203 shift = port - 32; 18204 } 18205 soc_ALTERNATE_EMIRROR_BITMAPm_field32_set(unit, &egr_bmp, 18206 bmapf, 1 << shift); 18207 soc_ALTERNATE_EMIRROR_BITMAPm_field32_set(unit, &egr_bmp, 18208 bmapf_zero, 0); 18209 } else 18210 #endif /* BCM_TRIUMPH2_SUPPORT */ 18211 #if defined(BCM_TRIUMPH3_SUPPORT) 18212 if (SOC_IS_TRIUMPH3(unit)) { 18213 soc_field_t bmap_w[] = {BITMAP_W0f, BITMAP_W1f}; 18214 /* index will identicate which field to program with correct value */ 18215 int index = (port < 32) ? 0 : 1; 18216 uint32 shift = (port < 32) ? port : port - 32; 18217 int i; 18218 18219 for (i = 0; i < COUNTOF(bmap_w); i++) { 18220 if (index == i) { 18221 soc_ALTERNATE_EMIRROR_BITMAPm_field32_set(unit, &egr_bmp, 18222 bmap_w[i], 1 << shift); 18223 } else { 18224 soc_ALTERNATE_EMIRROR_BITMAPm_field32_set(unit, &egr_bmp, 18225 bmap_w[i], 0); 18226 } 18227 } 18228 18229 } else 18230 #endif /* BCM_TRIDENT_SUPPORT */ 18231 #if defined(BCM_TRIDENT_SUPPORT) 18232 if (SOC_IS_TD_TT(unit)) { 18233 soc_field_t bmap_w[] = {BITMAP_W0f, BITMAP_W1f, BITMAP_W2f}; 18234 /* index will identicate which field to program with correct value */ 18235 int index = ((port < 32) ? 0 : ((port < 64) ? 1 : 2)); 18236 uint32 shift = ((port < 32) ? port : ((port < 64) ? (port - 32) : (port - 64) )); 18237 int i; 18238 18239 for (i = 0; i < COUNTOF(bmap_w); i++) { 18240 if (index == i) { 18241 soc_ALTERNATE_EMIRROR_BITMAPm_field32_set(unit, &egr_bmp, 18242 bmap_w[i], 1 << shift); 18243 } else { 18244 soc_ALTERNATE_EMIRROR_BITMAPm_field32_set(unit, &egr_bmp, 18245 bmap_w[i], 0); 18246 } 18247 } 18248 18249 } else 18250 #endif /* BCM_TRIDENT_SUPPORT */ 18251 #ifdef BCM_KATANA_SUPPORT 18252 if (SOC_IS_KATANAX(unit) ) { 18253 soc_field_t bmapf, bmapf_zero; 18254 uint32 shift; 18255 18256 if (port < 32) { 18257 bmapf = BITMAP_W0f; 18258 bmapf_zero = BITMAP_W1f; 18259 shift = port; 18260 } else { 18261 bmapf = BITMAP_W1f; 18262 bmapf_zero = BITMAP_W0f; 18263 shift = port - 32; 18264 } 18265 soc_ALTERNATE_EMIRROR_BITMAPm_field32_set(unit, &egr_bmp, 18266 bmapf, 1 << shift); 18267 soc_ALTERNATE_EMIRROR_BITMAPm_field32_set(unit, &egr_bmp, 18268 bmapf_zero, 0); 18269 } else 18270 #endif /* BCM_KATANA_SUPPORT */ 18271 { 18272 18273 #if defined(BCM_FIREBOLT_SUPPORT) 18274 if (SOC_IS_FBX(unit)) { 18275 port -= SOC_HG_OFFSET(unit); 18276 soc_ALTERNATE_EMIRROR_BITMAPm_field32_set(unit, &egr_bmp, 18277 BITMAPf, 1 << port); 18278 } 18279 #endif /* BCM_FIREBOLT_SUPPORT */ 18280 } 18281 BCM_IF_ERROR_RETURN(soc_mem_write(unit, ALTERNATE_EMIRROR_BITMAPm, 18282 MEM_BLOCK_ALL, modid, &egr_bmp)); 18283 return (BCM_E_NONE); 18284 } 18285 18286 /* 18287 * Function: 18288 * bcm_xgs3_mirror_egress_path_get 18289 * Description: 18290 * Get egress mirror packet path for stack ring 18291 * Parameters: 18292 * unit - (IN) BCM device number 18293 * modid - (IN) Destination module ID (of mirror-to port) 18294 * port - (OUT)Stack port for egress mirror packet 18295 * Returns: 18296 * BCM_E_XXX 18297 * Notes: 18298 * See bcm_mirror_alt_egress_pbmp_set for more details. 18299 */ 18300 int 18301 bcm_xgs3_mirror_egress_path_get(int unit, bcm_module_t modid, bcm_port_t *port) 18302 { 18303 alternate_emirror_bitmap_entry_t egr_bmp; 18304 uint32 val, p, start = 0; 18305 18306 if (NULL == port) { 18307 return (BCM_E_PARAM); 18308 } 18309 18310 if (!soc_feature(unit, soc_feature_egr_mirror_path)) { 18311 return (BCM_E_UNAVAIL); 18312 } 18313 if (!SOC_MODID_ADDRESSABLE(unit, modid)) { 18314 return (BCM_E_BADID); 18315 } 18316 18317 BCM_IF_ERROR_RETURN(soc_mem_read(unit, ALTERNATE_EMIRROR_BITMAPm, 18318 MEM_BLOCK_ANY, modid, &egr_bmp)); 18319 #ifdef BCM_TRIUMPH2_SUPPORT 18320 if (SOC_IS_TRIUMPH2(unit) || SOC_IS_APOLLO(unit) || 18321 SOC_IS_VALKYRIE2(unit)) { 18322 val = soc_ALTERNATE_EMIRROR_BITMAPm_field32_get(unit, &egr_bmp, BITMAP_LOf); 18323 if (val == 0) { 18324 val = soc_ALTERNATE_EMIRROR_BITMAPm_field32_get(unit, &egr_bmp, 18325 BITMAP_HIf); 18326 start = 32; 18327 } 18328 } else 18329 #endif /* BCM_TRIUMPH2_SUPPORT */ 18330 #if defined(BCM_TRIDENT_SUPPORT) 18331 if (SOC_IS_TD_TT(unit) || SOC_IS_TRIUMPH3(unit)) { 18332 val = soc_ALTERNATE_EMIRROR_BITMAPm_field32_get(unit, &egr_bmp, 18333 BITMAP_W0f); 18334 if (val == 0) { 18335 val = soc_ALTERNATE_EMIRROR_BITMAPm_field32_get(unit, &egr_bmp, 18336 BITMAP_W1f); 18337 start = 32; 18338 } 18339 if (val == 0) { 18340 val = soc_ALTERNATE_EMIRROR_BITMAPm_field32_get(unit, &egr_bmp, 18341 BITMAP_W2f); 18342 start = 64; 18343 } 18344 } else 18345 #endif /* BCM_TRIDENT_SUPPORT */ 18346 #ifdef BCM_KATANA_SUPPORT 18347 if (SOC_IS_KATANAX(unit) ) { 18348 val = soc_ALTERNATE_EMIRROR_BITMAPm_field32_get(unit, &egr_bmp, BITMAP_W0f); 18349 if (val == 0) { 18350 val = soc_ALTERNATE_EMIRROR_BITMAPm_field32_get(unit, &egr_bmp, 18351 BITMAP_W1f); 18352 start = 32; 18353 } 18354 } else 18355 #endif /* BCM_TRIUMPH2_SUPPORT */ 18356 { 18357 val = soc_ALTERNATE_EMIRROR_BITMAPm_field32_get(unit, &egr_bmp, BITMAPf); 18358 } 18359 start --; 18360 18361 if (val == 0) { 18362 /* Return default egress port */ 18363 return bcm_esw_topo_port_get(unit, modid, port); 18364 } 18365 for (p = start; val; p++) { 18366 val >>= 1; 18367 } 18368 if (SOC_IS_FBX(unit) && !SOC_IS_TRIUMPH2(unit) && 18369 !SOC_IS_APOLLO(unit) && !SOC_IS_VALKYRIE2(unit) 18370 && !(SOC_IS_TD_TT(unit) || SOC_IS_TRIUMPH3(unit)) && 18371 !(SOC_IS_KATANAX(unit))) { 18372 p += SOC_HG_OFFSET(unit); 18373 } 18374 *port = p; 18375 18376 return (BCM_E_NONE); 18377 } 18378 18379 /* 18380 * Function: 18381 * _bcm_xgs3_mirror_egr_dest_get 18382 * Purpose: 18383 * Get destination port bitmap for egress mirroring. 18384 * Parameters: 18385 * unit - (IN) BCM device number. 18386 * port - (IN) port number. 18387 * mtp_index - (IN) mtp index 18388 * dest_bitmap - (OUT) destination port bitmap. 18389 * Returns: 18390 * BCM_E_XXX 18391 */ 18392 STATIC int 18393 _bcm_xgs3_mirror_egr_dest_get(int unit, bcm_port_t port, int mtp_index, 18394 bcm_pbmp_t *dest_bitmap) 18395 { 18396 uint32 fval, mirror; 18397 static const soc_reg_t reg[] = { 18398 EMIRROR_CONTROLr, EMIRROR_CONTROL1r 18399 }; 18400 #ifdef BCM_GREYHOUND2_SUPPORT 18401 uint64 fval64, mirror64; 18402 static const soc_reg_t reg_lo[] = { 18403 EMIRROR_CONTROL_LO_64r, INVALIDr, 18404 INVALIDr, INVALIDr 18405 }; 18406 static const soc_reg_t reg_hi[] = { 18407 EMIRROR_CONTROL_HI_64r, INVALIDr, 18408 INVALIDr, INVALIDr 18409 }; 18410 #endif /*BCM_GREYHOUND2_SUPPORT*/ 18411 /* Input parameters check. */ 18412 if (NULL == dest_bitmap) { 18413 return BCM_E_PARAM; 18414 } 18415 18416 if ((mtp_index < 0) || 18417 (mtp_index >= MIRROR_CONFIG(unit)->port_em_mtp_count)) { 18418 return BCM_E_PARAM; 18419 } 18420 #ifdef BCM_GREYHOUND2_SUPPORT 18421 if(soc_feature(unit, soc_feature_high_portcount_register)){ 18422 BCM_IF_ERROR_RETURN(soc_reg_get(unit, reg_lo[mtp_index], port, 0, &mirror64)); 18423 18424 SOC_PBMP_CLEAR(*dest_bitmap); 18425 fval64 = soc_reg64_field_get(unit, reg_lo[mtp_index], mirror64, BITMAP_LOf); 18426 SOC_PBMP_WORD_SET(*dest_bitmap, 0, COMPILER_64_LO(fval64)); 18427 SOC_PBMP_WORD_SET(*dest_bitmap, 1, COMPILER_64_HI(fval64)); 18428 18429 BCM_IF_ERROR_RETURN(soc_reg_get(unit, reg_hi[mtp_index], port, 0, &mirror64)); 18430 18431 fval64 = soc_reg64_field_get(unit, reg_hi[mtp_index], mirror64, BITMAP_LOf); 18432 SOC_PBMP_WORD_SET(*dest_bitmap, 2, COMPILER_64_LO(fval64)); 18433 SOC_PBMP_WORD_SET(*dest_bitmap, 3, COMPILER_64_HI(fval64)); 18434 18435 }else 18436 #endif /*BCM_GREYHOUND2_SUPPORT*/ 18437 { 18438 BCM_IF_ERROR_RETURN(soc_reg32_get(unit, reg[mtp_index], port, 0, &mirror)); 18439 18440 SOC_PBMP_CLEAR(*dest_bitmap); 18441 fval = soc_reg_field_get(unit, reg[mtp_index], mirror, BITMAPf); 18442 SOC_PBMP_WORD_SET(*dest_bitmap, 0, fval); 18443 } 18444 18445 return BCM_E_NONE; 18446 } 18447 18448 /* 18449 * Function: 18450 * _bcm_xgs3_mirror_egr_dest_set 18451 * Purpose: 18452 * Set destination port bitmap for egress mirroring. 18453 * Parameters: 18454 * unit - (IN) BCM device number. 18455 * port - (IN) Port number. 18456 * mtp_index - (IN) mtp index. 18457 * dest_bitmap - (IN) Destination port bitmap. 18458 * Returns: 18459 * BCM_E_XXX 18460 */ 18461 STATIC int 18462 _bcm_xgs3_mirror_egr_dest_set(int unit, bcm_port_t port, int mtp_index, 18463 bcm_pbmp_t *dest_bitmap) 18464 { 18465 uint32 value; 18466 soc_field_t field = BITMAPf; 18467 18468 static const soc_reg_t reg[] = { 18469 EMIRROR_CONTROLr, EMIRROR_CONTROL1r 18470 }; 18471 static const soc_reg_t hg_reg[] = { 18472 IEMIRROR_CONTROLr, IEMIRROR_CONTROL1r 18473 }; 18474 #ifdef BCM_GREYHOUND2_SUPPORT 18475 uint64 mirror, val64; 18476 static const soc_reg_t reg_lo[] = { 18477 EMIRROR_CONTROL_LO_64r, INVALIDr, 18478 INVALIDr, INVALIDr 18479 }; 18480 static const soc_reg_t reg_hi[] = { 18481 EMIRROR_CONTROL_HI_64r, INVALIDr, 18482 INVALIDr, INVALIDr 18483 }; 18484 static const soc_reg_t hg_reg_lo[] = { 18485 IEMIRROR_CONTROL_LO_64r, INVALIDr, 18486 INVALIDr, INVALIDr 18487 }; 18488 static const soc_reg_t hg_reg_hi[] = { 18489 IEMIRROR_CONTROL_HI_64r, INVALIDr, 18490 INVALIDr, INVALIDr 18491 }; 18492 #endif /*BCM_GREYHOUND2_SUPPORT*/ 18493 /* Input parameters checks. */ 18494 if (NULL == dest_bitmap) { 18495 return BCM_E_PARAM; 18496 } 18497 if ((mtp_index < 0) || 18498 (mtp_index >= MIRROR_CONFIG(unit)->port_em_mtp_count)) { 18499 return BCM_E_PARAM; 18500 } 18501 #ifdef BCM_GREYHOUND2_SUPPORT 18502 if(soc_feature(unit, soc_feature_high_portcount_register)){ 18503 /* For Register LO */ 18504 BCM_IF_ERROR_RETURN(READ_EMIRROR_CONTROL_LO_64r(unit, port, &mirror)); 18505 COMPILER_64_SET(val64, SOC_PBMP_WORD_GET(*dest_bitmap, 1), 18506 SOC_PBMP_WORD_GET(*dest_bitmap, 0)); 18507 soc_reg64_field_set(unit, reg_lo[mtp_index], &mirror, 18508 BITMAP_LOf, val64); 18509 BCM_IF_ERROR_RETURN(WRITE_EMIRROR_CONTROL_LO_64r(unit, port, mirror)); 18510 /* Enable mirroring of CPU Higig packets as well */ 18511 if (IS_CPU_PORT(unit, port)) { 18512 COMPILER_64_ZERO(mirror); 18513 BCM_IF_ERROR_RETURN(READ_IEMIRROR_CONTROL_LO_64r(unit, port, &mirror)); 18514 soc_reg64_field_set(unit, hg_reg_lo[mtp_index], &mirror, 18515 BITMAP_LOf, val64); 18516 BCM_IF_ERROR_RETURN(WRITE_IEMIRROR_CONTROL_LO_64r(unit, port, mirror)); 18517 } 18518 /* For Register HI */ 18519 COMPILER_64_ZERO(mirror); 18520 COMPILER_64_ZERO(val64); 18521 BCM_IF_ERROR_RETURN(READ_EMIRROR_CONTROL_HI_64r(unit, port, &mirror)); 18522 COMPILER_64_SET(val64, SOC_PBMP_WORD_GET(*dest_bitmap, 3), 18523 SOC_PBMP_WORD_GET(*dest_bitmap, 2)); 18524 soc_reg64_field_set(unit, reg_hi[mtp_index], &mirror, 18525 BITMAP_LOf, val64); 18526 BCM_IF_ERROR_RETURN(WRITE_EMIRROR_CONTROL_HI_64r(unit, port, mirror)); 18527 /* Enable mirroring of CPU Higig packets as well */ 18528 if (IS_CPU_PORT(unit, port)) { 18529 COMPILER_64_ZERO(mirror); 18530 BCM_IF_ERROR_RETURN(READ_IEMIRROR_CONTROL_HI_64r(unit, port, &mirror)); 18531 soc_reg64_field_set(unit, hg_reg_hi[mtp_index], &mirror, 18532 BITMAP_LOf, val64); 18533 BCM_IF_ERROR_RETURN(WRITE_IEMIRROR_CONTROL_HI_64r(unit, port, mirror)); 18534 } 18535 }else 18536 #endif /*BCM_GREYHOUND2_SUPPORT*/ 18537 { 18538 value = SOC_PBMP_WORD_GET(*dest_bitmap, 0); 18539 18540 BCM_IF_ERROR_RETURN 18541 (soc_reg_fields32_modify(unit, reg[mtp_index], 18542 port, 1, &field, &value)); 18543 18544 /* Enable mirroring of CPU Higig packets as well */ 18545 if (IS_CPU_PORT(unit, port)) { 18546 BCM_IF_ERROR_RETURN 18547 (soc_reg_fields32_modify(unit, hg_reg[mtp_index], 18548 port, 1, &field, &value)); 18549 } 18550 } 18551 return BCM_E_NONE; 18552 } 18553 18554 #endif /* BCM_XGS3_SWITCH_SUPPORT */ 18555 18556 /* 18557 * Function: 18558 * _bcm_esw_mirror_egr_dest_set 18559 * Purpose: 18560 * Set destination port bitmap for egress mirroring. 18561 * Parameters: 18562 * unit - (IN) BCM device number 18563 * port - (IN) Port number 18564 * mtp_index - (IN) mtp index. 18565 * dest_bitmap - (IN) destination port bitmap 18566 * Returns: 18567 * BCM_E_XXX 18568 */ 18569 STATIC int 18570 _bcm_esw_mirror_egr_dest_set(int unit, bcm_port_t port, int mtp_index, 18571 bcm_pbmp_t *dest_bitmap) 18572 { 18573 int rv; 18574 18575 /* Input parameters check */ 18576 if (NULL == dest_bitmap) { 18577 return (BCM_E_PARAM); 18578 } 18579 if ((mtp_index < 0) || (mtp_index >= BCM_MIRROR_MTP_COUNT)) { 18580 return BCM_E_PARAM; 18581 } 18582 18583 #if defined(BCM_TRIDENT_SUPPORT) 18584 if (soc_feature(unit, soc_feature_mirror_control_mem)) { 18585 rv = _bcm_trident_mirror_egr_dest_set(unit, port, mtp_index, dest_bitmap); 18586 } else 18587 #endif /* BCM_TRIDENT_SUPPORT */ 18588 18589 #if defined(BCM_TRIUMPH_SUPPORT) 18590 if (SOC_IS_TR_VL(unit)) { 18591 rv = _bcm_triumph_mirror_egr_dest_set(unit, port, mtp_index, dest_bitmap); 18592 } else 18593 #endif /* BCM_TRIUMPH_SUPPORT */ 18594 18595 #if defined(BCM_RAPTOR1_SUPPORT) 18596 if (SOC_IS_RAPTOR(unit)) { 18597 rv = _bcm_raptor_mirror_egr_dest_set(unit, port, dest_bitmap); 18598 } else 18599 #endif /* BCM_RAPTOR1_SUPPORT */ 18600 18601 #ifdef BCM_XGS3_SWITCH_SUPPORT 18602 if (SOC_IS_XGS3_SWITCH(unit)) { 18603 rv = _bcm_xgs3_mirror_egr_dest_set(unit, port, mtp_index, dest_bitmap); 18604 } else 18605 #endif /* BCM_XGS3_SWITCH_SUPPORT */ 18606 { 18607 rv = BCM_E_UNAVAIL; 18608 } 18609 18610 return (rv); 18611 } 18612 18613 18614 /* 18615 * Function: 18616 * _bcm_esw_mirror_egr_dest_get 18617 * Purpose: 18618 * Get destination port bitmap for egress mirroring. 18619 * Parameters: 18620 * unit - (IN) BCM device number. 18621 * port - (IN) Port number. 18622 * mtp_index - (IN) mtp index. 18623 * dest_bitmap - (OUT) destination port bitmap. 18624 * Returns: 18625 * BCM_E_XXX 18626 */ 18627 STATIC int 18628 _bcm_esw_mirror_egr_dest_get(int unit, bcm_port_t port, int mtp_index, 18629 bcm_pbmp_t *dest_bitmap) 18630 { 18631 int rv; 18632 18633 /* Input parameters check */ 18634 if (NULL == dest_bitmap) { 18635 return (BCM_E_PARAM); 18636 } 18637 18638 SOC_PBMP_CLEAR(*dest_bitmap); 18639 18640 #if defined(BCM_TRIDENT_SUPPORT) 18641 if (soc_feature(unit, soc_feature_mirror_control_mem)) { 18642 rv = _bcm_trident_mirror_egr_dest_get(unit, port, mtp_index, dest_bitmap); 18643 } else 18644 #endif /* BCM_TRIDENT_SUPPORT */ 18645 18646 #if defined(BCM_TRIUMPH_SUPPORT) 18647 if (SOC_IS_TR_VL(unit)) { 18648 rv = _bcm_triumph_mirror_egr_dest_get(unit, port, mtp_index, dest_bitmap); 18649 } else 18650 #endif /* BCM_TRIUMPH_SUPPORT */ 18651 18652 #if defined(BCM_RAPTOR1_SUPPORT) 18653 if (SOC_IS_RAPTOR(unit)) { 18654 rv = _bcm_raptor_mirror_egr_dest_get(unit, port, dest_bitmap); 18655 } else 18656 #endif /* BCM_RAPTOR1_SUPPORT */ 18657 18658 #ifdef BCM_XGS3_SWITCH_SUPPORT 18659 if (SOC_IS_XGS3_SWITCH(unit)) { 18660 rv = _bcm_xgs3_mirror_egr_dest_get(unit, port, mtp_index, dest_bitmap); 18661 } else 18662 #endif /* BCM_XGS3_SWITCH_SUPPORT */ 18663 { 18664 rv = BCM_E_UNAVAIL; 18665 } 18666 18667 return (rv); 18668 } 18669 18670 /* 18671 * Function: 18672 * _bcm_esw_mirror_egress_get 18673 * Description: 18674 * Get the mirroring per egress enabled/disabled status 18675 * Parameters: 18676 * unit - (IN) BCM device number 18677 * port - (IN) The port to check 18678 * enable - (OUT) Place to store boolean return value for on/off 18679 * Returns: 18680 * BCM_E_XXX 18681 */ 18682 STATIC int 18683 _bcm_esw_mirror_egress_get(int unit, bcm_port_t port, int *enable) 18684 { 18685 bcm_port_t port_iterator; 18686 bcm_pbmp_t dest_bitmap; 18687 int value = 0; 18688 int mtp_slot, mtp_bit; /* MTP type value & bitmap */ 18689 int vp = VP_PORT_INVALID; 18690 int status = 0; 18691 bcm_module_t mod_out; 18692 bcm_trunk_t tgid_out; 18693 18694 /* mtp_slot == mtp_index unless directed flexible mirroring is used */ 18695 if (BCM_GPORT_IS_SET(port)) { 18696 BCM_IF_ERROR_RETURN( 18697 _bcm_esw_gport_resolve(unit, port, &mod_out, 18698 &port, &tgid_out, &vp)); 18699 } 18700 18701 /* Get destination port bitmap from first valid port. */ 18702 PBMP_ALL_ITER(unit, port_iterator) { 18703 BCM_MIRROR_MTP_ITER(MIRROR_CONFIG_MTP_DEV_MASK(unit), mtp_slot) { 18704 mtp_bit = 1 << mtp_slot; 18705 18706 /* Skip if not egress configured MTP */ 18707 if (!SOC_WARM_BOOT(unit) && /* Else reloading info */ 18708 soc_feature(unit, soc_feature_mirror_flexible)) { 18709 if (!MIRROR_MTP_METHOD_IS_DIRECTED_FLEXIBLE(unit)) { 18710 if (!MIRROR_CONFIG_SHARED_MTP(unit, mtp_slot).egress) { 18711 continue; 18712 } 18713 } else { 18714 if (!(MIRROR_CONFIG_MTP_MODE_BMP(unit) & mtp_bit)) { 18715 continue; 18716 } 18717 } 18718 } 18719 18720 if (vp != VP_PORT_INVALID) { 18721 BCM_IF_ERROR_RETURN( 18722 _bcm_tr2_mirror_dvp_enable_get(unit, vp, &status)); 18723 if (status & mtp_bit) { 18724 value |= mtp_bit; 18725 } 18726 } else { 18727 BCM_IF_ERROR_RETURN 18728 (_bcm_esw_mirror_egr_dest_get(unit, port_iterator, mtp_slot, 18729 &dest_bitmap)); 18730 if (BCM_GPORT_INVALID == port) { 18731 /* Get the full EM enable status */ 18732 if (SOC_PBMP_NOT_NULL(dest_bitmap)) { 18733 value |= mtp_bit; 18734 } 18735 } else { 18736 if (SOC_PBMP_MEMBER(dest_bitmap, port)) { 18737 value |= mtp_bit; 18738 } 18739 } 18740 } 18741 } 18742 /* Only care about finding one valid port worth of info */ 18743 break; 18744 } 18745 18746 *enable = value; 18747 return BCM_E_NONE; 18748 } 18749 18750 18751 /* 18752 * Function: 18753 * _bcm_esw_mirror_egress_set 18754 * Description: 18755 * Enable or disable mirroring per egress 18756 * Parameters: 18757 * unit - (IN) BCM device number 18758 * port - (IN) The port to affect 18759 * enable - (IN) Boolean value for on/off 18760 * Returns: 18761 * BCM_E_XXX 18762 * Notes: 18763 * Mirroring must also be globally enabled. 18764 */ 18765 STATIC int 18766 _bcm_esw_mirror_egress_set(int unit, bcm_port_t port, int enable) 18767 { 18768 bcm_port_t port_iterator; 18769 bcm_pbmp_t dest_bitmap, all_pbmp; 18770 int mtp_slot, mtp_bit; /* MTP type value & bitmap */ 18771 int vp = VP_PORT_INVALID; 18772 int status; 18773 bcm_module_t mod_out; 18774 bcm_trunk_t tgid_out; 18775 18776 /* mtp_slot == mtp_index unless directed flexible mirroring is used */ 18777 if (BCM_GPORT_IS_SET(port)) { 18778 BCM_IF_ERROR_RETURN( 18779 _bcm_esw_gport_resolve(unit, port, &mod_out, 18780 &port, &tgid_out, &vp)); 18781 } 18782 18783 BCM_PBMP_CLEAR(all_pbmp); 18784 BCM_PBMP_ASSIGN(all_pbmp, PBMP_ALL(unit)); 18785 #ifdef BCM_KATANA2_SUPPORT 18786 if (SOC_IS_KATANA2(unit) && soc_feature(unit, soc_feature_flex_port)) { 18787 BCM_IF_ERROR_RETURN(_bcm_kt2_flexio_pbmp_update(unit, &all_pbmp)); 18788 } 18789 if (soc_feature(unit, soc_feature_linkphy_coe) || 18790 soc_feature(unit, soc_feature_subtag_coe)) { 18791 _bcm_kt2_subport_pbmp_update(unit, &all_pbmp); 18792 } 18793 #endif 18794 18795 PBMP_ITER(all_pbmp, port_iterator) { 18796 BCM_MIRROR_MTP_ITER(MIRROR_CONFIG_MTP_DEV_MASK(unit), mtp_slot) { 18797 mtp_bit = 1 << mtp_slot; 18798 18799 /* Skip if not egress configured MTP */ 18800 if (!SOC_WARM_BOOT(unit) && /* Else reloading info */ 18801 soc_feature(unit, soc_feature_mirror_flexible)) { 18802 if (!MIRROR_MTP_METHOD_IS_DIRECTED_FLEXIBLE(unit)) { 18803 if (!MIRROR_CONFIG_SHARED_MTP(unit, mtp_slot).egress) { 18804 continue; 18805 } 18806 } else { 18807 if (!(MIRROR_CONFIG_MTP_MODE_BMP(unit) & mtp_bit)) { 18808 continue; 18809 } 18810 } 18811 } 18812 18813 if (vp != VP_PORT_INVALID) { 18814 BCM_IF_ERROR_RETURN( 18815 _bcm_tr2_mirror_dvp_enable_get(unit, vp, &status)); 18816 if (enable & mtp_bit) { 18817 status |= mtp_bit; 18818 } else { 18819 status &= ~mtp_bit; 18820 } 18821 BCM_IF_ERROR_RETURN( 18822 _bcm_tr2_mirror_dvp_enable_set(unit, vp, status)); 18823 } else { 18824 18825 BCM_IF_ERROR_RETURN 18826 (_bcm_esw_mirror_egr_dest_get(unit, port_iterator, mtp_slot, 18827 &dest_bitmap)); 18828 18829 /* Update egress destination bitmap. */ 18830 if (enable & mtp_bit) { 18831 SOC_PBMP_PORT_ADD(dest_bitmap, port); 18832 } else { 18833 SOC_PBMP_PORT_REMOVE(dest_bitmap, port); 18834 } 18835 18836 /* Write egress destination bitmap from each local port. */ 18837 BCM_IF_ERROR_RETURN 18838 (_bcm_esw_mirror_egr_dest_set(unit, port_iterator, mtp_slot, 18839 &dest_bitmap)); 18840 } 18841 } 18842 } 18843 18844 return BCM_E_NONE; 18845 } 18846 18847 /* 18848 * Function: 18849 * _bcm_esw_directed_mirroring_get 18850 * Purpose: 18851 * Check if directed mirroring is enabled on the chip. 18852 * Parameters: 18853 * unit - (IN) BCM device number. 18854 * enable - (OUT)Directed mirror enabled. 18855 * Returns: 18856 * BCM_E_XXX 18857 */ 18858 STATIC int 18859 _bcm_esw_directed_mirroring_get(int unit, int *enable) 18860 { 18861 int rv = BCM_E_NONE; /* Operation return status. */ 18862 18863 /* Input parameters check. */ 18864 if (NULL == enable) { 18865 return (BCM_E_PARAM); 18866 } 18867 18868 /* Read switch control to check if directed mirroring is enabled.*/ 18869 rv = bcm_esw_switch_control_get(unit, bcmSwitchDirectedMirroring, enable); 18870 if (BCM_E_UNAVAIL == rv) { 18871 *enable = FALSE; 18872 rv = BCM_E_NONE; 18873 } 18874 return (rv); 18875 } 18876 18877 18878 /* 18879 * Function: 18880 * _bcm_esw_mirror_mtp_reserve 18881 * Description: 18882 * Reserve a mirror-to port 18883 * Parameters: 18884 * unit - (IN) BCM device number 18885 * dest_id - (IN) Mirror destination id. 18886 * flags - (IN) Mirrored traffic direction. 18887 * index_used - (OUT) MTP index reserved 18888 * Returns: 18889 * BCM_E_XXX 18890 * Notes: 18891 * If the a mirror-to port is reserved more than once 18892 * (without being unreserved) then the same MTP index 18893 * will be returned for each call. 18894 * Direction should be INGRESS, EGRESS, or EGRESS_TRUE. 18895 */ 18896 int 18897 _bcm_esw_mirror_mtp_reserve(int unit, bcm_gport_t dest_id, 18898 uint32 flags, int *index_used) 18899 { 18900 int rv = BCM_E_RESOURCE; /* Operation return status. */ 18901 18902 /* Input parameters check. */ 18903 if (NULL == index_used) { 18904 return (BCM_E_PARAM); 18905 } 18906 18907 /* Allocate MTP index for mirror destination. */ 18908 #if defined(BCM_XGS3_SWITCH_SUPPORT) 18909 if (SOC_IS_XGS3_SWITCH(unit)) { 18910 rv = _bcm_xgs3_mirror_mtp_reserve(unit, dest_id, flags, index_used); 18911 } else 18912 #endif 18913 { 18914 *index_used = 0; 18915 /* If mirroring is already in use -> 18916 make sure destination is identical, increment reference count.*/ 18917 if (MIRROR_CONFIG_ING_MTP_REF_COUNT(unit, 0)) { 18918 /* Mirror destination match. check. */ 18919 if (MIRROR_CONFIG_ING_MTP_DEST(unit, 0) == dest_id) { 18920 MIRROR_CONFIG_ING_MTP_REF_COUNT(unit, 0)++; 18921 rv = BCM_E_NONE; 18922 } 18923 } else { /* Mirroring not in use. */ 18924 MIRROR_CONFIG_ING_MTP_DEST(unit, 0) = dest_id; 18925 MIRROR_CONFIG_ING_MTP_REF_COUNT(unit, 0)++; 18926 MIRROR_DEST_REF_COUNT(unit, dest_id)++; 18927 rv = BCM_E_NONE; 18928 } 18929 18930 /* Ingress & Egress mtp are identical for xgs devices. */ 18931 if (BCM_SUCCESS(rv)) { 18932 MIRROR_CONFIG_EGR_MTP(unit, 0) = MIRROR_CONFIG_ING_MTP(unit, 0); 18933 } 18934 } 18935 return (rv); 18936 } 18937 18938 18939 /* 18940 * Function: 18941 * _bcm_esw_mirror_mtp_unreserve 18942 * Description: 18943 * Free mirror-to port 18944 * Parameters: 18945 * unit - (IN) BCM device number. 18946 * mtp_index - (IN) MTP index. 18947 * is_port - (IN) Port based mirror indication. 18948 * flags - (IN) Mirrored traffic direction. 18949 * Returns: 18950 * BCM_E_XXX 18951 */ 18952 int 18953 _bcm_esw_mirror_mtp_unreserve(int unit, int mtp_index, int is_port, 18954 uint32 flags) 18955 { 18956 bcm_gport_t mirror_dest; 18957 int rv = BCM_E_NONE; 18958 18959 /* Free MTP index for mirror destination. */ 18960 #if defined(BCM_XGS3_SWITCH_SUPPORT) 18961 if (SOC_IS_XGS3_SWITCH(unit)) { 18962 BCM_IF_ERROR_RETURN 18963 (_bcm_xgs3_mirror_mtp_unreserve(unit, mtp_index, is_port, flags)); 18964 } else 18965 #endif 18966 { 18967 /* Decrement reference counter & reset dest port */ 18968 /* if destination is no longer in use. */ 18969 if (MIRROR_CONFIG_ING_MTP_REF_COUNT(unit, 0) > 0) { 18970 MIRROR_CONFIG_ING_MTP_REF_COUNT(unit, 0)--; 18971 if (0 == MIRROR_CONFIG_ING_MTP_REF_COUNT(unit, 0)) { 18972 mirror_dest = MIRROR_CONFIG_ING_MTP_DEST(unit, 0); 18973 MIRROR_CONFIG_ING_MTP_DEST(unit, 0)= BCM_GPORT_INVALID; 18974 if (MIRROR_DEST_REF_COUNT(unit, mirror_dest) > 0) { 18975 MIRROR_DEST_REF_COUNT(unit, mirror_dest)--; 18976 } 18977 } 18978 MIRROR_CONFIG_EGR_MTP(unit, 0) = MIRROR_CONFIG_ING_MTP(unit, 0); 18979 } 18980 } 18981 return rv; 18982 } 18983 /* 18984 * Function: 18985 * _bcm_esw_mirror_deinit 18986 * Purpose: 18987 * Internal routine used to free mirror software module. 18988 * control structures. 18989 * Parameters: 18990 * unit - (IN) BCM device number. 18991 * cfg_ptr - (IN) Pointer to config structure. 18992 * Returns: 18993 * BCM_E_XXX 18994 */ 18995 STATIC int 18996 _bcm_esw_mirror_deinit(int unit, _bcm_mirror_config_p *cfg_ptr) 18997 { 18998 _bcm_mirror_config_p ptr; 18999 int mtp_type; 19000 19001 /* Sanity checks. */ 19002 if (!SOC_UNIT_VALID(unit)) { 19003 return BCM_E_UNIT; 19004 } 19005 19006 #ifdef BCM_TRIDENT3_SUPPORT 19007 if (NULL != EGR_MIRROR_TABLE(unit)) { 19008 BCM_IF_ERROR_RETURN 19009 (soc_profile_mem_destroy(unit, EGR_MIRROR_TABLE(unit))); 19010 sal_free(EGR_MIRROR_TABLE(unit)); 19011 EGR_MIRROR_TABLE(unit) = NULL; 19012 } 19013 if (NULL != EGR_SEQ_NUMBER_PROFILE(unit)) { 19014 BCM_IF_ERROR_RETURN 19015 (soc_profile_mem_destroy(unit, EGR_SEQ_NUMBER_PROFILE(unit))); 19016 sal_free(EGR_SEQ_NUMBER_PROFILE(unit)); 19017 EGR_SEQ_NUMBER_PROFILE(unit) = NULL; 19018 } 19019 #endif /* BCM_TRIDENT3_SUPPORT */ 19020 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_GREYHOUND_SUPPORT) 19021 if (NULL != EGR_MIRROR_ENCAP(unit)) { 19022 BCM_IF_ERROR_RETURN 19023 (soc_profile_mem_destroy(unit, EGR_MIRROR_ENCAP(unit))); 19024 sal_free(EGR_MIRROR_ENCAP(unit)); 19025 EGR_MIRROR_ENCAP(unit) = NULL; 19026 } 19027 #endif /* BCM_TRIDENT_SUPPORT || BCM_GREYHOUND_SUPPORT */ 19028 19029 /* If mirror config was not allocated we are done. */ 19030 if (NULL == cfg_ptr) { 19031 return (BCM_E_PARAM); 19032 } 19033 19034 ptr = *cfg_ptr; 19035 if (NULL == ptr) { 19036 return (BCM_E_NONE); 19037 } 19038 19039 /* Free mirror destination information. */ 19040 if (NULL != ptr->dest_arr) { 19041 #ifdef BCM_TRIDENT2_SUPPORT 19042 BCM_IF_ERROR_RETURN(_bcm_mirror_dest_array_mtp_free(unit, ptr)); 19043 #endif /* BCM_TRIDENT2_SUPPORT */ 19044 sal_free(ptr->dest_arr); 19045 ptr->dest_arr = NULL; 19046 } 19047 19048 /* Free egress true mtp information. */ 19049 if (NULL != ptr->egr_true_mtp) { 19050 sal_free(ptr->egr_true_mtp); 19051 ptr->egr_true_mtp = NULL; 19052 } 19053 19054 /* Free MTP types records. */ 19055 for (mtp_type = BCM_MTP_SLOT_TYPE_PORT; 19056 mtp_type < BCM_MTP_SLOT_TYPES; mtp_type++) { 19057 if (NULL != ptr->mtp_slot[mtp_type]) { 19058 sal_free(ptr->mtp_slot[mtp_type]); 19059 } 19060 } 19061 19062 /* Free Legacy Ingress Slot Container */ 19063 if (NULL != ptr->ing_slot_container) { 19064 sal_free(ptr->ing_slot_container); 19065 ptr->ing_slot_container = NULL; 19066 } 19067 19068 /* Free Legacy Egress Slot Container */ 19069 if (NULL != ptr->egr_slot_container) { 19070 sal_free(ptr->egr_slot_container); 19071 ptr->egr_slot_container = NULL; 19072 } 19073 19074 /* Free egress mtp information. */ 19075 if (NULL != ptr->egr_mtp) { 19076 sal_free(ptr->egr_mtp); 19077 ptr->egr_mtp = NULL; 19078 } 19079 19080 /* Free ingress mtp information. */ 19081 if (NULL != ptr->ing_mtp) { 19082 sal_free(ptr->ing_mtp); 19083 ptr->ing_mtp = NULL; 19084 } 19085 19086 /* Free shared mtp information. */ 19087 if (NULL != ptr->shared_mtp) { 19088 sal_free(ptr->shared_mtp); 19089 ptr->shared_mtp = NULL; 19090 } 19091 19092 /* Destroy protection mutex. */ 19093 if (NULL != ptr->mutex) { 19094 sal_mutex_destroy(ptr->mutex); 19095 ptr->mutex = NULL; 19096 } 19097 19098 #if defined (BCM_TOMAHAWK3_SUPPORT) 19099 if (SOC_IS_TOMAHAWK3(unit)) { 19100 BCM_IF_ERROR_RETURN 19101 (soc_profile_mem_destroy(unit, &ptr->mirror_zeroing_profile)); 19102 } 19103 #endif 19104 19105 /* Free module configuration structue. */ 19106 sal_free(ptr); 19107 *cfg_ptr = NULL; 19108 return BCM_E_NONE; 19109 } 19110 19111 /* 19112 * Function: 19113 * _bcm_esw_mirror_enable_set 19114 * Purpose: 19115 * Enable/disable mirroring on a port 19116 * Parameters: 19117 * unit - BCM device number 19118 * port - port number 19119 * enable - enable mirroring if non-zero 19120 * Returns: 19121 * BCM_E_XXX 19122 * Notes: 19123 * For non-XGS3 devices this function will also set the 19124 * mirror-to port. 19125 */ 19126 int 19127 _bcm_esw_mirror_enable_set(int unit, int port, int enable) 19128 { 19129 #if defined(BCM_XGS3_SWITCH_SUPPORT) 19130 if (SOC_IS_XGS3_SWITCH(unit)) { 19131 return _bcm_xgs3_mirror_enable_set(unit, port, enable); 19132 } 19133 #endif /* BCM_XGS3_SWITCH_SUPPORT */ 19134 19135 #if defined(BCM_XGS12_FABRIC_SUPPORT) 19136 if (SOC_IS_XGS12_FABRIC(unit)) { 19137 return _bcm_xgs_fabric_mirror_enable_set(unit, port, enable); 19138 } 19139 #endif /* BCM_XGS12_FABRIC_SUPPORT */ 19140 return BCM_E_UNAVAIL; 19141 } 19142 19143 /* 19144 * Function: 19145 * _bcm_esw_mirror_mode_set 19146 * Description: 19147 * Enable or disable mirroring. Will wait for bcm_esw_mirror_to_set 19148 * to be called to actually do the enable if needed. 19149 * Parameters: 19150 * unit - (IN) BCM device number 19151 * mode - (IN) One of BCM_MIRROR_(DISABLE|L2|L2_L3) 19152 * Returns: 19153 * BCM_E_XXX 19154 */ 19155 STATIC int 19156 _bcm_esw_mirror_mode_set(int unit, int mode) 19157 { 19158 int menable; /* Enable mirroring flag. */ 19159 int port; /* Port iterator. */ 19160 int omode; /* Original mirroring mode. */ 19161 #if defined (BCM_XGS3_SWITCH_SUPPORT) 19162 int enable; /* By direction mirror enable. */ 19163 #endif /* BCM_XGS3_SWITCH_SUPPORT */ 19164 int rv = BCM_E_UNAVAIL; /* Operation return status. */ 19165 bcm_pbmp_t all_pbmp; 19166 #if defined BCM_KATANA2_SUPPORT 19167 int min_subport = SOC_INFO(unit).pp_port_index_min; 19168 #endif 19169 19170 /* Preserve original module configuration. */ 19171 omode = MIRROR_CONFIG_MODE(unit); 19172 19173 /* Update module mode. */ 19174 MIRROR_CONFIG_MODE(unit) = mode; 19175 menable = (BCM_MIRROR_DISABLE != mode) ? TRUE : FALSE; 19176 19177 if (!menable) { 19178 /* If mirroring was originally off - we are done. */ 19179 if (!SOC_IS_XGS12_FABRIC(unit) && (omode == BCM_MIRROR_DISABLE)) { 19180 return (BCM_E_NONE); 19181 } 19182 } 19183 19184 /* Wait for mirror_to_set() */ 19185 if (soc_feature(unit, soc_feature_mirror_flexible) && 19186 !MIRROR_MTP_METHOD_IS_DIRECTED_FLEXIBLE(unit)) { 19187 if ((BCM_GPORT_INVALID == MIRROR_CONFIG_SHARED_MTP_DEST(unit, 0)) && 19188 !SOC_IS_XGS12_FABRIC(unit)) { 19189 return (BCM_E_NONE); 19190 } 19191 } else { 19192 if ((BCM_GPORT_INVALID == MIRROR_CONFIG_ING_MTP_DEST(unit, 0)) && 19193 !SOC_IS_XGS12_FABRIC(unit)) { 19194 return (BCM_E_NONE); 19195 } 19196 } 19197 19198 BCM_PBMP_CLEAR(all_pbmp); 19199 BCM_PBMP_ASSIGN(all_pbmp, PBMP_ALL(unit)); 19200 #ifdef BCM_KATANA2_SUPPORT 19201 if (SOC_IS_KATANA2(unit) && soc_feature(unit, soc_feature_flex_port)) { 19202 BCM_IF_ERROR_RETURN(_bcm_kt2_flexio_pbmp_update(unit, &all_pbmp)); 19203 } 19204 if (soc_feature(unit, soc_feature_linkphy_coe) || 19205 soc_feature(unit, soc_feature_subtag_coe)) { 19206 _bcm_kt2_subport_pbmp_update(unit, &all_pbmp); 19207 } 19208 #endif 19209 19210 #if defined(BCM_XGS3_SWITCH_SUPPORT) 19211 if (SOC_IS_XGS3_SWITCH(unit)) { 19212 PBMP_ITER(all_pbmp, port) { 19213 /* Skip special ports (loopback port, etc.) */ 19214 #if defined(BCM_KATANA2_SUPPORT) 19215 if ((soc_feature(unit, soc_feature_linkphy_coe) || 19216 soc_feature(unit, soc_feature_subtag_coe)) && 19217 (port >= min_subport)) { 19218 } else 19219 #endif 19220 if (!IS_PORT(unit, port) && !IS_CPU_PORT(unit, port)) { 19221 continue; 19222 } 19223 19224 rv = bcm_esw_mirror_ingress_get(unit, port, &enable); 19225 if (BCM_FAILURE(rv)) { 19226 break; 19227 } 19228 if (enable) { 19229 rv = _bcm_xgs3_mirror_ingress_mtp_install(unit, port, 0); 19230 if (BCM_E_EXISTS == rv) { 19231 /* Configured from a previous mode. */ 19232 rv = BCM_E_NONE; 19233 } else if (BCM_FAILURE(rv)) { 19234 break; 19235 } 19236 } 19237 19238 rv = bcm_esw_mirror_egress_get(unit, port, &enable); 19239 if (BCM_FAILURE(rv)) { 19240 break; 19241 } 19242 19243 if (enable) { 19244 rv = _bcm_xgs3_mirror_egress_mtp_install(unit, port, 0); 19245 if (BCM_E_EXISTS == rv) { 19246 /* Configured from a previous mode. */ 19247 rv = BCM_E_NONE; 19248 } else if (BCM_FAILURE(rv)) { 19249 break; 19250 } 19251 } 19252 19253 rv = _bcm_esw_mirror_enable_set(unit, port, menable); 19254 if (BCM_FAILURE(rv)) { 19255 break; 19256 } 19257 } 19258 } else 19259 #endif /* BCM_XGS3_SWITCH_SUPPORT */ 19260 19261 #if defined(BCM_XGS_SWITCH_SUPPORT) 19262 if (SOC_IS_XGS_SWITCH(unit)) { 19263 PBMP_ITER(all_pbmp, port) { 19264 /* Skip special ports (loopback port, etc.) */ 19265 #if defined(BCM_KATANA2_SUPPORT) 19266 if ((soc_feature(unit, soc_feature_linkphy_coe) || 19267 soc_feature(unit, soc_feature_subtag_coe)) && 19268 (port >= min_subport)) { 19269 } else 19270 #endif 19271 if (!IS_PORT(unit, port) && !IS_CPU_PORT(unit, port)) { 19272 continue; 19273 } 19274 19275 rv = _bcm_esw_mirror_enable_set(unit, port, menable); 19276 if (BCM_FAILURE(rv)) { 19277 break; 19278 } 19279 } 19280 } else 19281 #endif /* BCM_XGS_SWITCH_SUPPORT */ 19282 19283 #if defined(BCM_XGS_FABRIC_SUPPORT) 19284 if (SOC_IS_XGS_FABRIC(unit)) { 19285 PBMP_ST_ITER(unit, port) { 19286 rv = _bcm_esw_mirror_enable_set(unit, port, menable); 19287 if (BCM_FAILURE(rv)) { 19288 break; 19289 } 19290 } 19291 } else 19292 #endif /* BCM_XGS_FABRIC_SUPPORT */ 19293 { 19294 rv = BCM_E_UNAVAIL; 19295 } 19296 return (rv); 19297 } 19298 19299 /* 19300 * Function: 19301 * _bcm_esw_mirror_hw_clear 19302 * Purpose: 19303 * Clear hw registers/tables & disable mirroring on the device. 19304 * Parameters: 19305 * unit - (IN) BCM device number. 19306 * Returns: 19307 * BCM_E_XXX 19308 */ 19309 STATIC int 19310 _bcm_esw_mirror_hw_clear(int unit) 19311 { 19312 #if defined(BCM_XGS3_SWITCH_SUPPORT) 19313 int port; /* Port iteration index. */ 19314 bcm_pbmp_t pbmp, all_pbmp; 19315 int mtp_index; /* MTP itteration index */ 19316 #if defined(BCM_TRIUMPH2_SUPPORT) 19317 mirror_control_entry_t mc_entry; /* MTP control memory value (Trident) */ 19318 uint32 mc_reg; /* MTP control register value. */ 19319 int mtp_type_undir = FALSE; /* MTP_TYPE set for undirected mode */ 19320 int cpu_hg_index = 0; 19321 #endif /* BCM_TRIUMPH2_SUPPORT */ 19322 19323 if (SOC_IS_XGS3_SWITCH(unit)) { 19324 /* Stacking ports should never drop directed mirror packets */ 19325 /* Other ports should default to no mirroring */ 19326 BCM_PBMP_CLEAR(all_pbmp); 19327 BCM_PBMP_ASSIGN(all_pbmp, PBMP_ALL(unit)); 19328 #ifdef BCM_KATANA2_SUPPORT 19329 if (SOC_IS_KATANA2(unit) && soc_feature(unit, soc_feature_flex_port)) { 19330 BCM_IF_ERROR_RETURN(_bcm_kt2_flexio_pbmp_update(unit, &all_pbmp)); 19331 } 19332 if (soc_feature(unit, soc_feature_linkphy_coe) || 19333 soc_feature(unit, soc_feature_subtag_coe)) { 19334 _bcm_kt2_subport_pbmp_update(unit, &all_pbmp); 19335 } 19336 #endif 19337 19338 #if defined(BCM_TRIUMPH2_SUPPORT) 19339 /* Initialize default mirror control settings */ 19340 if (soc_feature(unit, soc_feature_mirror_flexible) || 19341 (soc_feature(unit, soc_feature_egr_mirror_true))) { 19342 if (soc_feature(unit, soc_feature_mirror_control_mem)) { 19343 sal_memset(&mc_entry, 0, sizeof(mc_entry)); 19344 for (mtp_index = 0; mtp_index < BCM_MIRROR_MTP_COUNT; 19345 mtp_index++) { 19346 soc_mem_field32_set(unit, MIRROR_CONTROLm, &mc_entry, 19347 _mtp_index_field[mtp_index], 19348 mtp_index); 19349 soc_mem_field32_set(unit, MIRROR_CONTROLm, &mc_entry, 19350 _non_uc_mtp_index_field[mtp_index], 19351 mtp_index); 19352 } 19353 } else { 19354 mc_reg = 0; 19355 for (mtp_index = 0; mtp_index < BCM_MIRROR_MTP_COUNT; 19356 mtp_index++) { 19357 soc_reg_field_set(unit, MIRROR_CONTROLr, &mc_reg, 19358 _mtp_index_field[mtp_index], 19359 mtp_index); 19360 soc_reg_field_set(unit, MIRROR_CONTROLr, &mc_reg, 19361 _non_uc_mtp_index_field[mtp_index], 19362 mtp_index); 19363 } 19364 } 19365 } 19366 19367 if (soc_feature(unit, soc_feature_mirror_flexible)) { 19368 if (MIRROR_MTP_METHOD_IS_NON_DIRECTED(unit)) { 19369 /* Draco 1.5 mirroring mode. */ 19370 mtp_type_undir = TRUE; 19371 MIRROR_CONFIG_SHARED_MTP(unit, 19372 BCM_MIRROR_MTP_FLEX_EGRESS_D15_INDEX).egress = TRUE; 19373 } 19374 } 19375 19376 #endif /* BCM_TRIUMPH2_SUPPORT */ 19377 19378 PBMP_ITER(all_pbmp, port) { 19379 #if defined(BCM_TRIUMPH2_SUPPORT) 19380 /* Set up standard settings for flexible mirroring. */ 19381 if (soc_feature(unit, soc_feature_mirror_flexible) || 19382 (soc_feature(unit, soc_feature_egr_mirror_true) && 19383 IS_LB_PORT(unit, port))) { 19384 19385 /* Set MTP mapping to 1-1 for flexible mirroring, 19386 or egress true mirroring LB port */ 19387 if (soc_feature(unit, soc_feature_mirror_control_mem)) { 19388 BCM_IF_ERROR_RETURN 19389 (WRITE_MIRROR_CONTROLm(unit, MEM_BLOCK_ANY, 19390 port, &mc_entry)); 19391 cpu_hg_index = SOC_IS_KATANA2(unit) ? 19392 SOC_INFO(unit).cpu_hg_pp_port_index : 19393 SOC_INFO(unit).cpu_hg_index; 19394 #ifdef BCM_TOMAHAWK3_SUPPORT 19395 if (SOC_IS_TOMAHAWK3(unit)) { 19396 /* No higig on TH3, skip programming below */ 19397 cpu_hg_index = -1; 19398 } 19399 #endif /* BCM_TOMAHAWK3_SUPPORT */ 19400 if (IS_CPU_PORT(unit, port) && cpu_hg_index != -1) { 19401 BCM_IF_ERROR_RETURN 19402 (WRITE_MIRROR_CONTROLm(unit, MEM_BLOCK_ANY, 19403 cpu_hg_index, &mc_entry)); 19404 } 19405 } else { 19406 BCM_IF_ERROR_RETURN 19407 (WRITE_MIRROR_CONTROLr(unit, port, mc_reg)); 19408 if (IS_CPU_PORT(unit, port)) { 19409 BCM_IF_ERROR_RETURN 19410 (WRITE_IMIRROR_CONTROLr(unit, port, mc_reg)); 19411 } 19412 } 19413 } 19414 #endif /* BCM_TRIUMPH2_SUPPORT */ 19415 19416 /* Reset global mirror enable bit after the mirror control 19417 * register is handled. */ 19418 BCM_IF_ERROR_RETURN 19419 (_bcm_esw_mirror_enable_set(unit, port, 19420 IS_ST_PORT(unit, port) ? 1 : 0)); 19421 19422 /* Disable ingress mirroring. */ 19423 BCM_IF_ERROR_RETURN(_bcm_esw_mirror_ingress_set(unit, port, 0)); 19424 19425 /* Disable egress mirroring for all MTP indexes */ 19426 SOC_PBMP_CLEAR(pbmp); 19427 19428 for (mtp_index = 0; mtp_index < BCM_MIRROR_MTP_COUNT; mtp_index++) { 19429 (void)(_bcm_esw_mirror_egr_dest_set(unit, port, mtp_index, 19430 &pbmp)); 19431 } 19432 19433 #ifdef BCM_FIREBOLT_SUPPORT 19434 /* Clear RSPAN settings */ 19435 if (SOC_REG_IS_VALID(unit, EGR_RSPAN_VLAN_TAGr)) { 19436 BCM_IF_ERROR_RETURN(WRITE_EGR_RSPAN_VLAN_TAGr(unit, port, 0)); 19437 } 19438 #endif /* BCM_FIREBOLT_SUPPORT */ 19439 } 19440 19441 if (SOC_MEM_IS_VALID(unit, IM_MTP_INDEXm)) { 19442 BCM_IF_ERROR_RETURN 19443 (soc_mem_clear(unit, IM_MTP_INDEXm, COPYNO_ALL, 0)); 19444 } 19445 if (SOC_MEM_IS_VALID(unit, EM_MTP_INDEXm)) { 19446 BCM_IF_ERROR_RETURN 19447 (soc_mem_clear(unit, EM_MTP_INDEXm, COPYNO_ALL, 0)); 19448 } 19449 #if defined(BCM_TRIUMPH2_SUPPORT) 19450 if (SOC_MEM_IS_VALID(unit, EP_REDIRECT_EM_MTP_INDEXm)) { 19451 BCM_IF_ERROR_RETURN 19452 (soc_mem_clear(unit, EP_REDIRECT_EM_MTP_INDEXm, 19453 COPYNO_ALL, 0)); 19454 } 19455 if (SOC_MEM_IS_VALID(unit, EGR_EP_REDIRECT_EM_MTP_INDEXm)) { 19456 BCM_IF_ERROR_RETURN 19457 (soc_mem_clear(unit, EGR_EP_REDIRECT_EM_MTP_INDEXm, 19458 COPYNO_ALL, 0)); 19459 } 19460 /* Clear settings of mirror_to_pbmp_set */ 19461 #ifdef BCM_GREYHOUND2_SUPPORT 19462 if(soc_feature(unit, soc_feature_high_portcount_register)){ 19463 uint64 val64, mirror; 19464 COMPILER_64_ZERO(val64); 19465 PBMP_ALL_ITER(unit, port) { 19466 BCM_IF_ERROR_RETURN(READ_IMIRROR_BITMAP_LOr(unit, port, &mirror)); 19467 soc_reg64_field_set(unit, IMIRROR_BITMAP_LOr, &mirror, 19468 BITMAPf, val64); 19469 BCM_IF_ERROR_RETURN(WRITE_IMIRROR_BITMAP_LOr(unit, port, mirror)); 19470 19471 } 19472 PBMP_ALL_ITER(unit, port) { 19473 BCM_IF_ERROR_RETURN(READ_IMIRROR_BITMAP_HIr(unit, port, &mirror)); 19474 soc_reg64_field_set(unit, IMIRROR_BITMAP_HIr, &mirror, 19475 BITMAPf, val64); 19476 BCM_IF_ERROR_RETURN(WRITE_IMIRROR_BITMAP_HIr(unit, port, mirror)); 19477 } 19478 }else 19479 #endif /*BCM_GREYHOUND2_SUPPORT*/ 19480 if (SOC_REG_IS_VALID(unit, IMIRROR_BITMAP_64r)) { 19481 uint32 values[2]; 19482 soc_field_t fields[] = {BITMAP_LOf, BITMAP_HIf}; 19483 values[0] = values[1] = 0; 19484 PBMP_ALL_ITER(unit, port) { 19485 BCM_IF_ERROR_RETURN 19486 (soc_reg_fields32_modify(unit, IMIRROR_BITMAP_64r, port, 19487 2, fields, values)); 19488 } 19489 } else 19490 #endif /* BCM_TRIUMPH2_SUPPORT */ 19491 if (SOC_REG_IS_VALID(unit, IMIRROR_BITMAPr)) { 19492 PBMP_ALL_ITER(unit, port) { 19493 BCM_IF_ERROR_RETURN(WRITE_IMIRROR_BITMAPr(unit, port, 0)); 19494 } 19495 } 19496 #if defined(BCM_TRX_SUPPORT) 19497 if (SOC_MEM_IS_VALID(unit, EGR_ERSPANm)) { 19498 BCM_IF_ERROR_RETURN 19499 (soc_mem_clear(unit, EGR_ERSPANm, COPYNO_ALL, 0)); 19500 } 19501 #endif /* BCM_TRX_SUPPORT */ 19502 #if defined(BCM_TRIDENT_SUPPORT) 19503 if (soc_feature(unit, soc_feature_mirror_control_mem)) { 19504 int i; 19505 soc_mem_t td_tt_mem_arr[] = { EMIRROR_CONTROLm, EMIRROR_CONTROL1m, 19506 EMIRROR_CONTROL2m, EMIRROR_CONTROL3m, 19507 #if defined(BCM_TRIDENT3_SUPPORT) 19508 /* The following are added in Trident3 */ 19509 EGR_MIRROR_TABLEm, 19510 FLEX_EDITOR_MIRROR_ENCAP_0_PROFILE_1_TABLEm, 19511 FLEX_EDITOR_MIRROR_ENCAP_0_PROFILE_2_TABLEm, 19512 FLEX_EDITOR_MIRROR_ENCAP_0_PROFILE_3_TABLEm, 19513 #else /* BCM_TRIDENT3_SUPPORT */ 19514 /* The following are removed in Trident3 */ 19515 EGR_MIRROR_ENCAP_CONTROLm, 19516 EGR_MIRROR_ENCAP_DATA_1m, 19517 EGR_MIRROR_ENCAP_DATA_2m 19518 #endif /* !BCM_TRIDENT3_SUPPORT */ 19519 }; 19520 19521 /* Clear all valid memories upon init */ 19522 for (i = 0; i < COUNTOF(td_tt_mem_arr); i++) { 19523 if (SOC_MEM_IS_VALID(unit, td_tt_mem_arr[i])) { 19524 BCM_IF_ERROR_RETURN 19525 (soc_mem_clear(unit, td_tt_mem_arr[i], COPYNO_ALL, 0)); 19526 } 19527 } 19528 19529 if (SOC_MEM_IS_VALID(unit, IMIRROR_BITMAPm)) { 19530 imirror_bitmap_entry_t entry; 19531 19532 /* Clear settings of mirror_to_pbmp_set */ 19533 sal_memset(&entry, 0, sizeof(imirror_bitmap_entry_t)); 19534 PBMP_ALL_ITER(unit, port) { 19535 BCM_IF_ERROR_RETURN 19536 (WRITE_IMIRROR_BITMAPm(unit, MEM_BLOCK_ANY, port, 19537 &entry)); 19538 } 19539 } 19540 } 19541 #endif /* BCM_TRIDENT_SUPPORT */ 19542 19543 #if defined(BCM_GREYHOUND_SUPPORT) 19544 if (SOC_IS_GREYHOUND(unit) || SOC_IS_HURRICANE3(unit) || 19545 SOC_IS_GREYHOUND2(unit)) { 19546 int j; 19547 soc_mem_t gh_mem_arr[] = { EGR_MIRROR_ENCAP_CONTROLm, 19548 EGR_MIRROR_ENCAP_DATA_1m, EGR_MIRROR_ENCAP_DATA_2m }; 19549 19550 /* Clear all valid memories upon init */ 19551 for (j = 0; j < COUNTOF(gh_mem_arr); j++) { 19552 if (SOC_MEM_IS_VALID(unit, gh_mem_arr[j])) { 19553 BCM_IF_ERROR_RETURN 19554 (soc_mem_clear(unit, gh_mem_arr[j], COPYNO_ALL, 0)); 19555 } 19556 } 19557 } 19558 #endif /* BCM_GREYHOUND_SUPPORT */ 19559 19560 #if defined(BCM_TRIUMPH2_SUPPORT) 19561 /* Clear settings of mirror_select register */ 19562 if (SOC_REG_IS_VALID(unit, MIRROR_SELECTr)) { 19563 BCM_IF_ERROR_RETURN( 19564 soc_reg_field32_modify(unit, MIRROR_SELECTr, REG_PORT_ANY, 19565 MTP_TYPEf, mtp_type_undir ? 19566 BCM_MIRROR_MTP_FLEX_EGRESS_D15: 0x0)); 19567 } 19568 #endif /* BCM_TRIUMPH2_SUPPORT */ 19569 19570 /* Mirror is disabled by default on the switch. */ 19571 MIRROR_CONFIG_MODE(unit) = BCM_MIRROR_DISABLE; 19572 19573 } else 19574 #endif /* BCM_XGS3_SWITCH_SUPPORT */ 19575 { 19576 BCM_IF_ERROR_RETURN 19577 (_bcm_esw_mirror_mode_set(unit, BCM_MIRROR_DISABLE)); 19578 } 19579 return (BCM_E_NONE); 19580 } 19581 19582 /* 19583 * Function: 19584 * _bcm_esw_mirror_stk_update 19585 * Description: 19586 * Stack callback to re-program path for mirror-to-port when 19587 * there is an alternate path available to the unit on which 19588 * MTP is present. 19589 * Parameters: 19590 * unit - (IN)BCM device number 19591 * modid - (IN)Module id. 19592 * port - (IN) 19593 * pbmp - (IN) 19594 * Returns: 19595 * BCM_E_XXX 19596 */ 19597 int 19598 _bcm_esw_mirror_stk_update(int unit, bcm_module_t modid, bcm_port_t port, 19599 bcm_pbmp_t pbmp) 19600 { 19601 /* Initialization check. */ 19602 if (!MIRROR_INIT(unit)) { 19603 return (BCM_E_INIT); 19604 } 19605 19606 /* Input parameters check. */ 19607 if (!SOC_PORT_VALID(unit, port)) { 19608 return (BCM_E_PORT); 19609 } 19610 19611 if (SOC_PBMP_IS_NULL(pbmp)) { 19612 return (BCM_E_NONE); 19613 } 19614 19615 #ifdef BCM_HERCULES_SUPPORT 19616 if (SOC_IS_HERCULES(unit) || SOC_IS_HERCULES15(unit)) { 19617 bcm_port_t hg_port; 19618 bcm_pbmp_t uc_pbmp, mir_pbmp; 19619 19620 BCM_IF_ERROR_RETURN 19621 (bcm_esw_stk_ucbitmap_get(unit, port, modid, &uc_pbmp)); 19622 19623 PBMP_HG_ITER(unit, hg_port) { 19624 uint32 mirbmap, old_bmap; 19625 19626 BCM_IF_ERROR_RETURN (READ_ING_MIRTOBMAPr(unit, hg_port, &mirbmap)); 19627 old_bmap = mirbmap; 19628 SOC_PBMP_CLEAR(mir_pbmp); 19629 SOC_PBMP_WORD_SET(mir_pbmp, 0, mirbmap); 19630 19631 if (SOC_PBMP_EQ(mir_pbmp, uc_pbmp)) { 19632 soc_reg_field_set(unit, ING_MIRTOBMAPr, &mirbmap, BMAPf, 19633 SOC_PBMP_WORD_GET(pbmp, 0)); 19634 if (old_bmap != mirbmap) { 19635 BCM_IF_ERROR_RETURN 19636 (WRITE_ING_MIRTOBMAPr(unit, hg_port, mirbmap)); 19637 } 19638 } 19639 } 19640 } 19641 #endif 19642 return (BCM_E_NONE); 19643 } 19644 19645 STATIC int 19646 _bcm_esw_mirror_port_dest_mtp_ref_adjust(int unit, bcm_port_t port, 19647 int flags, int mtp_index, 19648 bcm_gport_t mirror_dest) 19649 { 19650 int rv; 19651 bcm_mirror_destination_t mdest; /* Mirror destination. */ 19652 uint8 skip = TRUE; 19653 19654 /* The device which doesn't support flexible mirror need not adjust */ 19655 if (!soc_feature(unit, soc_feature_mirror_flexible)) { 19656 return BCM_E_NONE; 19657 } 19658 19659 /* Get mirror destination descriptor. */ 19660 BCM_IF_ERROR_RETURN 19661 (bcm_esw_mirror_destination_get(unit, mirror_dest, &mdest)); 19662 19663 #ifdef BCM_TRIDENT2_SUPPORT 19664 if (mdest.flags & BCM_MIRROR_DEST_ID_SHARE) { 19665 skip = FALSE; 19666 } 19667 #endif /* BCM_TRIDENT2_SUPPORT */ 19668 19669 if (mdest.flags & BCM_MIRROR_DEST_REPLACE) { 19670 skip = FALSE; 19671 } 19672 19673 /* Only mirror destination with replace flag need adjust */ 19674 if (skip) { 19675 return BCM_E_NONE; 19676 } 19677 19678 if (MIRROR_MTP_METHOD_IS_DIRECTED_FLEXIBLE(unit)) { 19679 if (flags & BCM_MIRROR_PORT_INGRESS) { 19680 rv = _bcm_esw_mirror_port_dest_search(unit, port, 19681 BCM_MIRROR_PORT_INGRESS, 19682 mirror_dest); 19683 /* The ref_count of mtp_index for same src_port doesn't need to get increased twice */ 19684 if ((rv == BCM_E_EXISTS) && 19685 (MIRROR_CONFIG_ING_MTP_DEST(unit, mtp_index) == mirror_dest)) { 19686 MIRROR_CONFIG_ING_MTP_REF_COUNT(unit, mtp_index)--; 19687 } 19688 } 19689 19690 if (flags & BCM_MIRROR_PORT_EGRESS) { 19691 rv = _bcm_esw_mirror_port_dest_search(unit, port, 19692 BCM_MIRROR_PORT_EGRESS, 19693 mirror_dest); 19694 if ((rv == BCM_E_EXISTS) && 19695 (MIRROR_CONFIG_EGR_MTP_DEST(unit, mtp_index) == mirror_dest)) { 19696 MIRROR_CONFIG_EGR_MTP_REF_COUNT(unit, mtp_index)--; 19697 } 19698 } 19699 19700 if (flags & BCM_MIRROR_PORT_EGRESS_TRUE) { 19701 rv = _bcm_esw_mirror_port_dest_search(unit, port, 19702 BCM_MIRROR_PORT_EGRESS_TRUE, 19703 mirror_dest); 19704 if ((rv == BCM_E_EXISTS) && 19705 (MIRROR_CONFIG_EGR_TRUE_MTP_DEST(unit, mtp_index) == mirror_dest)) { 19706 MIRROR_CONFIG_EGR_TRUE_MTP_REF_COUNT(unit, mtp_index)--; 19707 } 19708 } 19709 } else { 19710 if (flags & BCM_MIRROR_PORT_INGRESS) { 19711 rv = _bcm_esw_mirror_port_dest_search(unit, port, 19712 BCM_MIRROR_PORT_INGRESS, 19713 mirror_dest); 19714 /* The ref_count of mtp_index for same src_port doesn't need to get increased twice */ 19715 if ((rv == BCM_E_EXISTS) && 19716 (MIRROR_CONFIG_SHARED_MTP(unit, mtp_index).egress == FALSE) && 19717 (MIRROR_CONFIG_SHARED_MTP_DEST(unit, mtp_index) == mirror_dest)) { 19718 MIRROR_CONFIG_SHARED_MTP_REF_COUNT(unit, mtp_index)--; 19719 } 19720 } 19721 19722 if (flags & BCM_MIRROR_PORT_EGRESS) { 19723 rv = _bcm_esw_mirror_port_dest_search(unit, port, 19724 BCM_MIRROR_PORT_EGRESS, 19725 mirror_dest); 19726 if ((rv == BCM_E_EXISTS) && 19727 (MIRROR_CONFIG_SHARED_MTP(unit, mtp_index).egress == TRUE) && 19728 (MIRROR_CONFIG_SHARED_MTP_DEST(unit, mtp_index) == mirror_dest)) { 19729 MIRROR_CONFIG_SHARED_MTP_REF_COUNT(unit, mtp_index)--; 19730 } 19731 } 19732 19733 if (flags & BCM_MIRROR_PORT_EGRESS_TRUE) { 19734 rv = _bcm_esw_mirror_port_dest_search(unit, port, 19735 BCM_MIRROR_PORT_EGRESS_TRUE, 19736 mirror_dest); 19737 if ((rv == BCM_E_EXISTS) && 19738 (MIRROR_CONFIG_EGR_TRUE_MTP_DEST(unit, mtp_index) == mirror_dest)) { 19739 MIRROR_CONFIG_EGR_TRUE_MTP_REF_COUNT(unit, mtp_index)--; 19740 } 19741 } 19742 } 19743 19744 return BCM_E_NONE; 19745 } 19746 19747 /* 19748 * Function: 19749 * _bcm_esw_mirror_port_ingress_dest_add 19750 * Purpose: 19751 * Add ingress mirroring destination to a port. 19752 * Parameters: 19753 * unit - (IN) BCM device number. 19754 * port - (IN) Port mirrored port. 19755 * mirror_dest - (IN) Mirroring destination gport. 19756 * Returns: 19757 * BCM_X_XXX 19758 */ 19759 STATIC int 19760 _bcm_esw_mirror_port_ingress_dest_add(int unit, bcm_port_t port, 19761 bcm_gport_t mirror_dest) 19762 { 19763 int mtp_index; /* Mirror to port index. */ 19764 int rv; /* Operation return status. */ 19765 19766 /* Allocate MTP index for mirror destination. */ 19767 rv = _bcm_esw_mirror_mtp_reserve(unit, mirror_dest, 19768 BCM_MIRROR_PORT_INGRESS, &mtp_index); 19769 /* Check for mtp allocation failure. */ 19770 if (BCM_FAILURE(rv)) { 19771 return (rv); 19772 } 19773 19774 if ((-1 != port) && 19775 (BCM_GPORT_IS_SET(port) || SOC_PORT_VALID(unit, port))) { 19776 #if defined(BCM_XGS3_SWITCH_SUPPORT) 19777 if (SOC_IS_XGS3_SWITCH(unit)) { 19778 BCM_IF_ERROR_RETURN 19779 (_bcm_esw_mirror_port_dest_mtp_ref_adjust(unit, port, 19780 BCM_MIRROR_PORT_INGRESS, 19781 mtp_index, 19782 mirror_dest)); 19783 rv = _bcm_xgs3_mirror_ingress_mtp_install(unit, port, mtp_index); 19784 if (BCM_E_EXISTS == rv) { 19785 rv = BCM_E_NONE; 19786 } 19787 } else 19788 #endif /* BCM_XGS3_SWITCH_SUPPORT */ 19789 { 19790 rv = bcm_esw_mirror_ingress_set(unit, port, TRUE); 19791 } 19792 19793 /* Check for mtp enable failure. */ 19794 if (BCM_FAILURE(rv)) { 19795 _bcm_esw_mirror_mtp_unreserve(unit, mtp_index, TRUE, 19796 BCM_MIRROR_PORT_INGRESS); 19797 } 19798 } 19799 return (rv); 19800 } 19801 19802 /* 19803 * Function: 19804 * _bcm_esw_mirror_port_egress_dest_add 19805 * Purpose: 19806 * Add egress mirroring destination to a port. 19807 * Parameters: 19808 * unit - (IN) BCM device number. 19809 * port - (IN) Port mirrored port. 19810 * mirror_dest - (IN) Mirroring destination gport. 19811 * Returns: 19812 * BCM_X_XXX 19813 */ 19814 STATIC int 19815 _bcm_esw_mirror_port_egress_dest_add(int unit, bcm_port_t port, 19816 bcm_gport_t mirror_dest) 19817 { 19818 int mtp_index; /* Mirror to port index. */ 19819 int rv; /* Operation return status. */ 19820 19821 /* Allocate MTP index for mirror destination. */ 19822 rv = _bcm_esw_mirror_mtp_reserve(unit, mirror_dest, 19823 BCM_MIRROR_PORT_EGRESS, &mtp_index); 19824 /* Check for mtp allocation failure. */ 19825 if (BCM_FAILURE(rv)) { 19826 return (rv); 19827 } 19828 19829 /* Enable MTP index on mirror source port */ 19830 if ((-1 != port) && 19831 (BCM_GPORT_IS_SET(port) || SOC_PORT_VALID(unit, port))) { 19832 #if defined(BCM_XGS3_SWITCH_SUPPORT) 19833 if (SOC_IS_XGS3_SWITCH(unit)) { 19834 BCM_IF_ERROR_RETURN 19835 (_bcm_esw_mirror_port_dest_mtp_ref_adjust(unit, port, 19836 BCM_MIRROR_PORT_EGRESS, 19837 mtp_index, 19838 mirror_dest)); 19839 /* Enable MTP index on mirror source port */ 19840 rv = _bcm_xgs3_mirror_egress_mtp_install(unit, port, mtp_index); 19841 if (BCM_E_EXISTS == rv) { 19842 rv = BCM_E_NONE; 19843 } 19844 } else 19845 #endif /* BCM_XGS3_SWITCH_SUPPORT */ 19846 { 19847 rv = bcm_esw_mirror_egress_set(unit, port, TRUE); 19848 } 19849 19850 /* Check for mtp enable failure. */ 19851 if (BCM_FAILURE(rv)) { 19852 _bcm_esw_mirror_mtp_unreserve(unit, mtp_index, TRUE, 19853 BCM_MIRROR_PORT_EGRESS); 19854 } 19855 } 19856 19857 return (rv); 19858 } 19859 19860 /* 19861 * Function: 19862 * _bcm_esw_mtp_slot_valid_get 19863 * Purpose: 19864 * Check for slot used/unused status in TRX devices not supporting 19865 * flexible mirroring. 19866 * Parameters: 19867 * unit - (IN) BCM device number. 19868 * flags - (IN) _BCM_MIRROR_SLOT_XXX flags. 19869 * mtp_slot_status - (OUT) Allocated slot container status. 19870 * Returns: 19871 * BCM_X_XXX 19872 * Notes: 19873 * Should not be called for devices supporting flexible mirroriing. 19874 */ 19875 int 19876 _bcm_esw_mtp_slot_valid_get(int unit, uint32 flags, int *mtp_slot_status) 19877 { 19878 int mtp_slot = 0, mtp_map = 0; 19879 19880 /* Null Param Check */ 19881 if (mtp_slot_status == NULL) { 19882 return BCM_E_PARAM; 19883 } 19884 19885 /* Initialization check */ 19886 if (!MIRROR_INIT(unit)) { 19887 return (BCM_E_INIT); 19888 } 19889 19890 /* Check for Slot Container valid status */ 19891 if (flags & _BCM_MIRROR_SLOT_INGRESS) { 19892 BCM_MIRROR_MTP_ITER(MIRROR_CONFIG_MTP_DEV_MASK(unit), mtp_slot) { 19893 mtp_map = 1 << mtp_slot; 19894 if (flags & _BCM_MIRROR_SLOT_PORT) { 19895 if(MIRROR_CONFIG_ING_MTP_SLOT_OWNER 19896 (unit, mtp_slot) & _BCM_MIRROR_SLOT_OWNER_FP) { 19897 *mtp_slot_status |= mtp_map; 19898 } 19899 } else if (flags & _BCM_MIRROR_SLOT_FP) { 19900 if (MIRROR_CONFIG_ING_MTP_SLOT_OWNER 19901 (unit, mtp_slot) & _BCM_MIRROR_SLOT_OWNER_PORT) { 19902 *mtp_slot_status |= mtp_map; 19903 } 19904 } else { 19905 /* No other flag is supported */ 19906 return BCM_E_PARAM; 19907 } 19908 } 19909 } else if (flags & _BCM_MIRROR_SLOT_EGRESS) { 19910 BCM_MIRROR_MTP_ITER(MIRROR_CONFIG_MTP_DEV_MASK(unit), mtp_slot) { 19911 mtp_map = 1 << mtp_slot; 19912 if (flags & _BCM_MIRROR_SLOT_PORT) { 19913 if (MIRROR_CONFIG_EGR_MTP_SLOT_OWNER 19914 (unit, mtp_slot) & _BCM_MIRROR_SLOT_OWNER_FP) { 19915 *mtp_slot_status |= mtp_map; 19916 } else if (MIRROR_CONFIG_EGR_MTP_SLOT_OWNER 19917 (unit, mtp_slot) & _BCM_MIRROR_SLOT_OWNER_PORT) { 19918 /* Egress Slot Container within port are exclusive */ 19919 *mtp_slot_status |= mtp_map; 19920 } 19921 } else if(flags & _BCM_MIRROR_SLOT_FP) { 19922 if (MIRROR_CONFIG_EGR_MTP_SLOT_OWNER 19923 (unit, mtp_slot) & _BCM_MIRROR_SLOT_OWNER_PORT) { 19924 *mtp_slot_status |= mtp_map; 19925 } 19926 } else { 19927 /* No other flag is supported */ 19928 return BCM_E_PARAM; 19929 } 19930 } 19931 } else { 19932 /* No other flag is supported */ 19933 return BCM_E_PARAM; 19934 } 19935 return BCM_E_NONE; 19936 } 19937 19938 #if defined(BCM_TRIUMPH2_SUPPORT) 19939 /* 19940 * Function: 19941 * _bcm_esw_mirror_port_egress_true_dest_add 19942 * Purpose: 19943 * Add egress_true mirroring destination to a port. 19944 * Parameters: 19945 * unit - (IN) BCM device number. 19946 * port - (IN) Port mirrored port. 19947 * mirror_dest - (IN) Mirroring destination gport. 19948 * Returns: 19949 * BCM_X_XXX 19950 */ 19951 STATIC int 19952 _bcm_esw_mirror_port_egress_true_dest_add(int unit, bcm_port_t port, 19953 bcm_gport_t mirror_dest) 19954 { 19955 int mtp_index; /* Mirror to port index. */ 19956 int rv; /* Operation return status. */ 19957 19958 /* Allocate MTP index for mirror destination. */ 19959 if (MIRROR_CONFIG(unit)->egr_true_mtp_count == 0) { 19960 return BCM_E_RESOURCE; 19961 } 19962 19963 rv = _bcm_esw_mirror_mtp_reserve(unit, mirror_dest, 19964 BCM_MIRROR_PORT_EGRESS_TRUE, 19965 &mtp_index); 19966 /* Check for mtp allocation failure. */ 19967 if (BCM_FAILURE(rv)) { 19968 return (rv); 19969 } 19970 19971 /* Enable MTP index on mirror source port */ 19972 if ((-1 != port) && SOC_PORT_VALID(unit, port)) { 19973 BCM_IF_ERROR_RETURN 19974 (_bcm_esw_mirror_port_dest_mtp_ref_adjust(unit, port, 19975 BCM_MIRROR_PORT_EGRESS_TRUE, 19976 mtp_index, 19977 mirror_dest)); 19978 /* Enable MTP index on mirror source port */ 19979 rv = _bcm_tr2_mirror_egress_true_mtp_install(unit, port, mtp_index); 19980 if (rv == BCM_E_EXISTS) { 19981 rv = BCM_E_NONE; 19982 } 19983 19984 /* Check for mtp enable failure. */ 19985 if (BCM_FAILURE(rv)) { 19986 _bcm_esw_mirror_mtp_unreserve(unit, mtp_index, TRUE, 19987 BCM_MIRROR_PORT_EGRESS_TRUE); 19988 } 19989 } 19990 19991 return (rv); 19992 } 19993 #endif /* BCM_TRIUMPH2_SUPPORT */ 19994 19995 /* 19996 * Function: 19997 * _bcm_esw_mirror_stacking_dest_update 19998 * Purpose: 19999 * Update mirror_to bitmap for a system when stacking is enabled 20000 * Parameters: 20001 * unit - (IN) BCM device number. 20002 * port - (IN) Port mirrored port. 20003 * mirror_dest - (IN) Mirroring destination gport. 20004 * Returns: 20005 * BCM_X_XXX 20006 */ 20007 STATIC int 20008 _bcm_esw_mirror_stacking_dest_update(int unit, bcm_port_t port, 20009 bcm_gport_t mirror_dest) 20010 { 20011 int rv = BCM_E_NONE; 20012 bcm_module_t mymodid; /* Local module id. */ 20013 bcm_module_t rem_modid; /* Remote module id. */ 20014 bcm_port_t port_num; /* Port number to get to rem_modid. */ 20015 bcm_pbmp_t pbmp; /* Mirror destination bitmap. */ 20016 uint32 mirbmap; /* Word 0 of mirror destination bitmap. */ 20017 int idx; /* Trunk members iterator. */ 20018 int is_local_modid; /* Check for local trunk port */ 20019 20020 #ifdef BCM_TOMAHAWK3_SUPPORT 20021 /* Stacking, Higig, mirror to LAG are not supported on TH3. 20022 * Also, IMIRROR_BITMAPm has been removed from TH3, so we do not take any 20023 * action. This check is added here so that no (incorrect) h/w programming 20024 * will happen if any other caller invokes this function directly 20025 */ 20026 if (SOC_IS_TOMAHAWK3(unit)) { 20027 return BCM_E_NONE; 20028 } 20029 #endif /* BCM_TOMAHAWK3_SUPPORT */ 20030 20031 if (SOC_IS_TD2_TT2(unit)) { 20032 imirror_bitmap_entry_t entry; 20033 sal_memset(&entry, 0, sizeof(entry)); 20034 20035 if (mirror_dest != BCM_GPORT_INVALID) { 20036 if (BCM_GPORT_IS_TRUNK(mirror_dest)) { 20037 soc_mem_field32_set(unit, IMIRROR_BITMAPm, &entry, 20038 HG_TRUNK_IDf, 20039 BCM_GPORT_TRUNK_GET(mirror_dest)); 20040 soc_mem_field32_set(unit, IMIRROR_BITMAPm, &entry, ISTRUNKf, 20041 1); 20042 soc_mem_field32_set(unit, IMIRROR_BITMAPm, &entry, ENABLEf, 1); 20043 } else { 20044 rem_modid = BCM_GPORT_MODPORT_MODID_GET(mirror_dest); 20045 BCM_IF_ERROR_RETURN 20046 (_bcm_esw_modid_is_local(unit, rem_modid, 20047 &is_local_modid)); 20048 if (!is_local_modid) { 20049 BCM_IF_ERROR_RETURN 20050 (bcm_esw_stk_modport_get(unit, rem_modid, 20051 &port_num)); 20052 soc_mem_field32_set(unit, IMIRROR_BITMAPm, &entry, 20053 EGRESS_PORTf, port_num); 20054 soc_mem_field32_set(unit, IMIRROR_BITMAPm, &entry, ENABLEf, 20055 1); 20056 } 20057 } 20058 } 20059 BCM_IF_ERROR_RETURN 20060 (soc_mem_write(unit, IMIRROR_BITMAPm, MEM_BLOCK_ANY, port, 20061 &entry)); 20062 if (IS_CPU_PORT(unit, port) && SOC_INFO(unit).cpu_hg_index != -1) { 20063 BCM_IF_ERROR_RETURN 20064 (soc_mem_write(unit, IMIRROR_BITMAPm, MEM_BLOCK_ANY, 20065 SOC_INFO(unit).cpu_hg_index, &entry)); 20066 } 20067 return BCM_E_NONE; 20068 } 20069 20070 /* Clear destination pbmp. */ 20071 BCM_PBMP_CLEAR(pbmp); 20072 mirbmap = 0; 20073 20074 /* 20075 * Clear mirrorto bitmap if devices are not in draco mode 20076 * or mirroring is off. 20077 */ 20078 if (MIRROR_MTP_METHOD_IS_NON_DIRECTED(unit) && 20079 (BCM_GPORT_INVALID != mirror_dest)) { 20080 BCM_IF_ERROR_RETURN(_bcm_esw_local_modid_get(unit, &mymodid)); 20081 20082 if (BCM_GPORT_IS_TRUNK(mirror_dest)) { 20083 int member_count; 20084 bcm_trunk_member_t *member_array = NULL; 20085 bcm_module_t mod_out; 20086 bcm_port_t port_out; 20087 bcm_trunk_t tgid_out; 20088 int id_out; 20089 20090 /* Get trunk member port/module pairs. */ 20091 BCM_IF_ERROR_RETURN 20092 (bcm_esw_trunk_get(unit, BCM_GPORT_TRUNK_GET(mirror_dest), 20093 NULL, 0, NULL, &member_count)); 20094 if (member_count > 0) { 20095 member_array = sal_alloc(sizeof(bcm_trunk_member_t) * member_count, 20096 "trunk member array"); 20097 if (NULL == member_array) { 20098 return BCM_E_MEMORY; 20099 } 20100 rv = bcm_esw_trunk_get(unit, BCM_GPORT_TRUNK_GET(mirror_dest), 20101 NULL, member_count, member_array, &member_count); 20102 if (BCM_FAILURE(rv)) { 20103 sal_free(member_array); 20104 return rv; 20105 } 20106 } 20107 20108 /* Fill pbmp with trunk members from other modules . */ 20109 for (idx = 0; idx < member_count; idx++) { 20110 rv = _bcm_esw_gport_resolve(unit, member_array[idx].gport, 20111 &mod_out, &port_out, &tgid_out, &id_out); 20112 if (BCM_FAILURE(rv) || (-1 != tgid_out) || (-1 != id_out)) { 20113 sal_free(member_array); 20114 return rv; 20115 } 20116 rv = _bcm_esw_modid_is_local(unit, mod_out, &is_local_modid); 20117 if (BCM_FAILURE(rv)) { 20118 sal_free(member_array); 20119 return rv; 20120 } 20121 if (!is_local_modid) { 20122 rv = bcm_esw_stk_modport_get(unit, mod_out, &port_num); 20123 if (BCM_FAILURE(rv)) { 20124 sal_free(member_array); 20125 return rv; 20126 } 20127 /* Set local port used to reach remote module to pbmp. */ 20128 BCM_PBMP_PORT_SET(pbmp, port_num); 20129 } 20130 } 20131 20132 if (NULL != member_array) { 20133 sal_free(member_array); 20134 } 20135 } else { 20136 rem_modid = BCM_GPORT_MODPORT_MODID_GET(mirror_dest); 20137 BCM_IF_ERROR_RETURN( 20138 _bcm_esw_modid_is_local(unit, rem_modid, &is_local_modid)); 20139 if (!is_local_modid) { 20140 BCM_IF_ERROR_RETURN(bcm_esw_stk_modport_get(unit, rem_modid, 20141 &port_num)); 20142 /* Set local port used to reach remote module to pbmp. */ 20143 BCM_PBMP_PORT_SET(pbmp, port_num); 20144 } 20145 } 20146 20147 mirbmap = SOC_PBMP_WORD_GET(pbmp, 0); 20148 if (SOC_IS_FBX(unit)) { 20149 mirbmap >>= SOC_HG_OFFSET(unit); 20150 } 20151 } 20152 #if defined(BCM_HERCULES_SUPPORT) 20153 if (SOC_IS_HERCULES(unit)) { 20154 return WRITE_ING_MIRTOBMAPr(unit, port, mirbmap); 20155 } 20156 #endif /* BCM_HERCULES_SUPPORT */ 20157 #if defined(BCM_XGS3_SWITCH_SUPPORT) 20158 if (soc_feature(unit, soc_feature_egr_mirror_path)) { 20159 #ifdef BCM_TRIDENT_SUPPORT 20160 if (soc_feature(unit, soc_feature_mirror_control_mem)) { 20161 imirror_bitmap_entry_t entry; 20162 20163 BCM_IF_ERROR_RETURN(soc_mem_read(unit, IMIRROR_BITMAPm, 20164 MEM_BLOCK_ALL, port, &entry)); 20165 soc_mem_pbmp_field_set(unit, IMIRROR_BITMAPm, &entry, BITMAPf, &pbmp); 20166 BCM_IF_ERROR_RETURN(soc_mem_write(unit, IMIRROR_BITMAPm, 20167 MEM_BLOCK_ANY, port, &entry)); 20168 if (IS_CPU_PORT(unit, port) && 20169 (SOC_INFO(unit).cpu_hg_index != -1)) { 20170 BCM_IF_ERROR_RETURN 20171 (soc_mem_write(unit, IMIRROR_BITMAPm, MEM_BLOCK_ANY, 20172 SOC_INFO(unit).cpu_hg_index, &entry)); 20173 } 20174 } else 20175 #endif 20176 #ifdef BCM_TRIUMPH2_SUPPORT 20177 if (SOC_IS_TRIUMPH2(unit) || SOC_IS_APOLLO(unit) || 20178 SOC_IS_VALKYRIE2(unit)) { 20179 uint32 values[2]; 20180 soc_field_t fields[] = {BITMAP_LOf, BITMAP_HIf}; 20181 values[0] = SOC_PBMP_WORD_GET(pbmp, 0); 20182 values[1] = SOC_PBMP_WORD_GET(pbmp, 1); 20183 BCM_IF_ERROR_RETURN 20184 (soc_reg_fields32_modify(unit, IMIRROR_BITMAP_64r, port, 20185 2, fields, values)); 20186 } else 20187 #endif /* BCM_TRIUMPH2_SUPPORT */ 20188 { 20189 #ifdef BCM_GREYHOUND2_SUPPORT 20190 if(soc_feature(unit, soc_feature_high_portcount_register)){ 20191 uint64 mirbmap64; 20192 COMPILER_64_ZERO(mirbmap64); 20193 BCM_IF_ERROR_RETURN(WRITE_IMIRROR_BITMAP_LOr(unit, port, mirbmap64)); 20194 BCM_IF_ERROR_RETURN(WRITE_IMIRROR_BITMAP_HIr(unit, port, mirbmap64)); 20195 return (BCM_E_NONE); 20196 }else 20197 #endif /* BCM_GREYHOUND2_SUPPORT */ 20198 { 20199 return WRITE_IMIRROR_BITMAPr(unit, port, mirbmap); 20200 } 20201 } 20202 } 20203 #endif /* BCM_XGS3_SWITCH_SUPPORT */ 20204 return (BCM_E_NONE); 20205 } 20206 20207 /* 20208 * Function: 20209 * _bcm_esw_mirror_port_ingress_dest_delete 20210 * Purpose: 20211 * Delete ingress mirroring destination from a port. 20212 * Parameters: 20213 * unit - (IN) BCM device number. 20214 * port - (IN) Port mirrored port. 20215 * mirror_dest - (IN) Mirroring destination gport. 20216 * Returns: 20217 * BCM_X_XXX 20218 */ 20219 STATIC int 20220 _bcm_esw_mirror_port_ingress_dest_delete(int unit, bcm_port_t port, 20221 bcm_gport_t mirror_dest) 20222 { 20223 int enable; /* Mirror enable check. */ 20224 int mtp_index; /* Mirror to port index. */ 20225 int rv; /* Operation return status. */ 20226 20227 /* Look for used MTP index */ 20228 if (soc_feature(unit, soc_feature_mirror_flexible) && 20229 !MIRROR_MTP_METHOD_IS_DIRECTED_FLEXIBLE(unit)) { 20230 rv = _bcm_tr2_mirror_shared_mtp_match(unit, mirror_dest, FALSE, 20231 &mtp_index); 20232 } else { 20233 rv = _bcm_esw_mirror_ingress_mtp_match(unit, mirror_dest, &mtp_index); 20234 } 20235 if (BCM_FAILURE(rv)) { 20236 return (BCM_E_NOT_FOUND); 20237 } 20238 20239 if ((-1 != port) && 20240 (BCM_GPORT_IS_SET(port) || SOC_PORT_VALID(unit, port))) { 20241 #if defined(BCM_XGS3_SWITCH_SUPPORT) 20242 if (SOC_IS_XGS3_SWITCH(unit)) { 20243 /* Enable MTP index on mirror source port */ 20244 BCM_IF_ERROR_RETURN 20245 (_bcm_xgs3_mirror_ingress_mtp_uninstall(unit, port, mtp_index)); 20246 } else 20247 #endif /* BCM_XGS3_SWITCH_SUPPORT */ 20248 { 20249 20250 BCM_IF_ERROR_RETURN(bcm_esw_mirror_ingress_get(unit, port, &enable)); 20251 if (!enable) { 20252 return (BCM_E_NOT_FOUND); 20253 } 20254 BCM_IF_ERROR_RETURN(bcm_esw_mirror_ingress_set(unit, port, FALSE)); 20255 } 20256 } 20257 20258 /* Free MTP index for mirror destination. */ 20259 rv = _bcm_esw_mirror_mtp_unreserve(unit, mtp_index, TRUE, 20260 BCM_MIRROR_PORT_INGRESS); 20261 BCM_IF_ERROR_RETURN(rv); 20262 20263 #ifdef BCM_TRIDENT3_SUPPORT 20264 if (SOC_IS_TRIDENT3X(unit)) { 20265 if (1 >= MIRROR_DEST_REF_COUNT(unit, mirror_dest)) { 20266 BCM_IF_ERROR_RETURN(_bcm_td3_mirror_encap_profile_index_clear(unit, 20267 BCM_GPORT_MIRROR_GET(mirror_dest))); 20268 } 20269 } 20270 #endif /* BCM_TRIDENT3_SUPPORT */ 20271 20272 return BCM_E_NONE; 20273 } 20274 20275 /* 20276 * Function: 20277 * _bcm_esw_mirror_port_egress_dest_delete 20278 * Purpose: 20279 * Delete egress mirroring destination from a port. 20280 * Parameters: 20281 * unit - (IN) BCM device number. 20282 * port - (IN) Port mirrored port. 20283 * mirror_dest - (IN) Mirroring destination gport. 20284 * Returns: 20285 * BCM_X_XXX 20286 */ 20287 STATIC int 20288 _bcm_esw_mirror_port_egress_dest_delete(int unit, bcm_port_t port, 20289 bcm_gport_t mirror_dest) 20290 { 20291 int enable; /* Mirror enable check. */ 20292 int mtp_index; /* Mirror to port index. */ 20293 int rv; /* Operation return status. */ 20294 20295 /* Look for used MTP index */ 20296 if (soc_feature(unit, soc_feature_mirror_flexible) && 20297 !MIRROR_MTP_METHOD_IS_DIRECTED_FLEXIBLE(unit)) { 20298 rv = _bcm_tr2_mirror_shared_mtp_match(unit, mirror_dest, TRUE, 20299 &mtp_index); 20300 } else { 20301 rv = _bcm_esw_mirror_egress_mtp_match(unit, mirror_dest, &mtp_index); 20302 } 20303 20304 if (BCM_FAILURE(rv)) { 20305 return (BCM_E_NOT_FOUND); 20306 } 20307 20308 if ((-1 != port) && 20309 (BCM_GPORT_IS_SET(port) || SOC_PORT_VALID(unit, port))) { 20310 #if defined(BCM_XGS3_SWITCH_SUPPORT) 20311 if (SOC_IS_XGS3_SWITCH(unit)) { 20312 /* Enable MTP index on mirror source port */ 20313 BCM_IF_ERROR_RETURN 20314 (_bcm_xgs3_mirror_egress_mtp_uninstall(unit, port, mtp_index)); 20315 } else 20316 #endif /* BCM_XGS3_SWITCH_SUPPORT */ 20317 { 20318 BCM_IF_ERROR_RETURN(bcm_esw_mirror_egress_get(unit, port, &enable)); 20319 if (!enable) { 20320 return (BCM_E_NONE); 20321 } 20322 BCM_IF_ERROR_RETURN(bcm_esw_mirror_egress_set(unit, port, FALSE)); 20323 } 20324 } 20325 20326 /* Free MTP index for mirror destination. */ 20327 rv = _bcm_esw_mirror_mtp_unreserve(unit, mtp_index, TRUE, 20328 BCM_MIRROR_PORT_EGRESS); 20329 BCM_IF_ERROR_RETURN(rv); 20330 20331 #ifdef BCM_TRIDENT3_SUPPORT 20332 if (SOC_IS_TRIDENT3X(unit)) { 20333 if (1 >= MIRROR_DEST_REF_COUNT(unit, mirror_dest)) { 20334 BCM_IF_ERROR_RETURN(_bcm_td3_mirror_encap_profile_index_clear(unit, 20335 BCM_GPORT_MIRROR_GET(mirror_dest))); 20336 } 20337 } 20338 #endif /* BCM_TRIDENT3_SUPPORT */ 20339 20340 return BCM_E_NONE; 20341 } 20342 20343 #ifdef BCM_TRIUMPH2_SUPPORT 20344 /* 20345 * Function: 20346 * _bcm_esw_mirror_port_egress_true_dest_delete 20347 * Purpose: 20348 * Delete egress true mirroring destination from a port. 20349 * Parameters: 20350 * unit - (IN) BCM device number. 20351 * port - (IN) Port mirrored port. 20352 * mirror_dest - (IN) Mirroring destination gport. 20353 * Returns: 20354 * BCM_X_XXX 20355 */ 20356 STATIC int 20357 _bcm_esw_mirror_port_egress_true_dest_delete(int unit, bcm_port_t port, 20358 bcm_gport_t mirror_dest) 20359 { 20360 int mtp_index; /* Mirror to port index. */ 20361 int rv; /* Operation return status. */ 20362 20363 if (MIRROR_CONFIG(unit)->egr_true_mtp_count == 0) { 20364 return BCM_E_NOT_FOUND; 20365 } 20366 20367 /* Look for used MTP index */ 20368 rv = _bcm_esw_mirror_egress_true_mtp_match(unit, mirror_dest, 20369 &mtp_index); 20370 if (BCM_FAILURE(rv)) { 20371 return (BCM_E_NOT_FOUND); 20372 } 20373 20374 /* Disable MTP index on mirror source port */ 20375 if ((-1 != port) && SOC_PORT_VALID(unit, port)) { 20376 /* Enable MTP index on mirror source port */ 20377 BCM_IF_ERROR_RETURN 20378 (_bcm_tr2_mirror_egress_true_mtp_uninstall(unit, port, 20379 mtp_index)); 20380 } 20381 20382 /* Free MTP index for mirror destination. */ 20383 rv = _bcm_esw_mirror_mtp_unreserve(unit, mtp_index, TRUE, 20384 BCM_MIRROR_PORT_EGRESS_TRUE); 20385 BCM_IF_ERROR_RETURN(rv); 20386 20387 #ifdef BCM_TRIDENT3_SUPPORT 20388 if (SOC_IS_TRIDENT3X(unit)) { 20389 if (1 >= MIRROR_DEST_REF_COUNT(unit, mirror_dest)) { 20390 BCM_IF_ERROR_RETURN(_bcm_td3_mirror_encap_profile_index_clear(unit, 20391 BCM_GPORT_MIRROR_GET(mirror_dest))); 20392 } 20393 } 20394 #endif /* BCM_TRIDENT3_SUPPORT */ 20395 20396 return BCM_E_NONE; 20397 20398 } 20399 #endif /* BCM_TRIUMPH2_SUPPORT */ 20400 20401 #if defined(BCM_FIELD_SUPPORT) && defined(BCM_XGS3_SWITCH_SUPPORT) 20402 /* 20403 * Function: 20404 * _bcm_esw_mirror_fp_dest_add 20405 * Purpose: 20406 * Add mirroring destination to field processor module. 20407 * Parameters: 20408 * unit - (IN) BCM device number. 20409 * modid - (IN) Mirroring destination module. 20410 * port - (IN) Mirroring destination port or GPORT. 20411 * flags - (IN) BCM_MIRROR_PORT_XXX flags. 20412 * mtp_index - (OUT) Allocated hw mtp index. 20413 * Returns: 20414 * BCM_X_XXX 20415 */ 20416 int 20417 _bcm_esw_mirror_fp_dest_add(int unit, int modid, int port, 20418 uint32 flags, int *mtp_index) 20419 { 20420 bcm_mirror_destination_t mirror_dest; /* Mirror destination. */ 20421 bcm_gport_t mirror_dest_id; /* Mirror destination id. */ 20422 int rv = BCM_E_NONE; /* Operation return status. */ 20423 uint32 destroy_flag = FALSE; /* mirror destination destroy */ 20424 20425 /* At least one packet direction must be specified. */ 20426 if (!(flags & (BCM_MIRROR_PORT_INGRESS | BCM_MIRROR_PORT_EGRESS | 20427 BCM_MIRROR_PORT_EGRESS_TRUE))) { 20428 return (BCM_E_PARAM); 20429 } 20430 20431 /* Can't reserve multiple types of mtp in 1 shot. */ 20432 if (((flags & BCM_MIRROR_PORT_INGRESS) && 20433 (flags & (BCM_MIRROR_PORT_EGRESS | BCM_MIRROR_PORT_EGRESS_TRUE))) || 20434 ((flags & BCM_MIRROR_PORT_EGRESS) && 20435 (flags & BCM_MIRROR_PORT_EGRESS_TRUE))) { 20436 return (BCM_E_PARAM); 20437 } 20438 20439 if (!soc_feature(unit, soc_feature_egr_mirror_true) && 20440 (flags & BCM_MIRROR_PORT_EGRESS_TRUE)) { 20441 return (BCM_E_PARAM); 20442 } 20443 20444 /* Initialization check */ 20445 if (!MIRROR_INIT(unit)) { 20446 return (BCM_E_INIT); 20447 } 20448 20449 /* Create traditional mirror destination. */ 20450 bcm_mirror_destination_t_init(&mirror_dest); 20451 20452 if ((flags & BCM_MIRROR_PORT_EGRESS_TRUE) && 20453 MIRROR_MTP_METHOD_IS_NON_DIRECTED(unit)) { 20454 return (BCM_E_CONFIG); 20455 } 20456 20457 MIRROR_LOCK(unit); 20458 20459 if (BCM_GPORT_IS_MIRROR(port)) { 20460 rv = bcm_esw_mirror_destination_get(unit, port, &mirror_dest); 20461 } else { 20462 rv = _bcm_esw_mirror_destination_find(unit, port, modid, flags, &mirror_dest); 20463 if (BCM_E_NOT_FOUND == rv) { 20464 mirror_dest.flags |= BCM_MIRROR_DEST_FIELD; 20465 rv = _bcm_esw_mirror_destination_create(unit, &mirror_dest); 20466 destroy_flag = TRUE; 20467 } 20468 } 20469 if (BCM_FAILURE(rv)) { 20470 MIRROR_UNLOCK(unit); 20471 return rv; 20472 } 20473 mirror_dest_id = mirror_dest.mirror_dest_id; 20474 /* Single mirroring destination for ingress & egress. */ 20475 if (MIRROR_MTP_METHOD_IS_NON_DIRECTED(unit)) { 20476 if (BCM_GPORT_IS_TRUNK(mirror_dest.gport)) { 20477 if (destroy_flag) { 20478 (void)bcm_esw_mirror_destination_destroy(unit, 20479 mirror_dest.mirror_dest_id); 20480 } 20481 MIRROR_UNLOCK(unit); 20482 return (BCM_E_UNAVAIL); 20483 } 20484 20485 if (soc_feature(unit, soc_feature_mirror_flexible)) { 20486 if (MIRROR_CONFIG_SHARED_MTP_REF_COUNT(unit, 0) && 20487 MIRROR_CONFIG_SHARED_MTP_DEST(unit, 0) != mirror_dest_id) { 20488 if (destroy_flag) { 20489 (void)bcm_esw_mirror_destination_destroy(unit, 20490 mirror_dest.mirror_dest_id); 20491 } 20492 MIRROR_UNLOCK(unit); 20493 return (BCM_E_RESOURCE); 20494 } 20495 } else { 20496 if (MIRROR_CONFIG_ING_MTP_REF_COUNT(unit, 0)) { 20497 if ((MIRROR_CONFIG_ING_MTP_DEST(unit, 0) != mirror_dest_id) && 20498 (MIRROR_CONFIG_EGR_MTP_DEST(unit, 0) != mirror_dest_id)) { 20499 if (destroy_flag) { 20500 (void)bcm_esw_mirror_destination_destroy(unit, 20501 mirror_dest.mirror_dest_id); 20502 } 20503 MIRROR_UNLOCK(unit); 20504 return (BCM_E_RESOURCE); 20505 } 20506 } 20507 } 20508 } 20509 20510 20511 /* Reserve & initialize mtp index based on traffic direction. */ 20512 if (flags & BCM_MIRROR_PORT_INGRESS) { 20513 rv = _bcm_xgs3_mirror_ingress_mtp_reserve(unit, mirror_dest_id, 20514 mtp_index); 20515 } else if (flags & BCM_MIRROR_PORT_EGRESS) { 20516 rv = _bcm_xgs3_mirror_egress_mtp_reserve(unit, mirror_dest_id, 20517 FALSE, mtp_index); 20518 #ifdef BCM_TRIUMPH2_SUPPORT 20519 } else if (flags & BCM_MIRROR_PORT_EGRESS_TRUE) { 20520 if (MIRROR_CONFIG(unit)->egr_true_mtp_count > 0) { 20521 rv = _bcm_xgs3_mirror_egress_true_mtp_reserve(unit, mirror_dest_id, 20522 mtp_index); 20523 } else { 20524 rv = BCM_E_RESOURCE; 20525 } 20526 #endif /* BCM_TRIUMPH2_SUPPORT */ 20527 } 20528 20529 #ifdef BCM_TRIUMPH2_SUPPORT 20530 /* MTP slot reservation for FP's */ 20531 if (BCM_SUCCESS(rv) && 20532 soc_feature(unit, soc_feature_mirror_flexible) && 20533 MIRROR_MTP_METHOD_IS_DIRECTED_FLEXIBLE(unit)) { 20534 int mtp_slot; /* Flexible mirroring slot */ 20535 20536 /* Determine a usable MTP slot for this FP entry */ 20537 if (0 == (flags & BCM_MIRROR_PORT_EGRESS_TRUE)) { 20538 rv = _bcm_xgs3_mtp_type_slot_reserve(unit, flags, 20539 0, 0, /* Unused */ 20540 BCM_MTP_SLOT_TYPE_FP, 20541 *mtp_index, &mtp_slot); 20542 if (BCM_SUCCESS(rv)) { 20543 *mtp_index |= (mtp_slot << BCM_MIRROR_MTP_FLEX_SLOT_SHIFT); 20544 } 20545 } else { 20546 /* Egress true uses 1-1 mapping */ 20547 *mtp_index |= (*mtp_index << BCM_MIRROR_MTP_FLEX_SLOT_SHIFT); 20548 } 20549 } 20550 #endif /* BCM_TRIUMPH2_SUPPORT */ 20551 20552 /* Enable mirroring on a port. */ 20553 if (BCM_SUCCESS(rv)) { 20554 if(!SOC_IS_XGS3_SWITCH(unit) || 20555 (BCM_MIRROR_DISABLE == MIRROR_CONFIG_MODE(unit))) { 20556 rv = _bcm_esw_mirror_enable(unit); 20557 MIRROR_CONFIG_MODE(unit) = BCM_MIRROR_L2; 20558 } 20559 } 20560 20561 if (BCM_FAILURE(rv) && destroy_flag) { 20562 (void)bcm_esw_mirror_destination_destroy(unit, mirror_dest.mirror_dest_id); 20563 } 20564 MIRROR_UNLOCK(unit); 20565 return (rv); 20566 } 20567 20568 /* 20569 * Function: 20570 * _bcm_esw_mirror_fp_dest_delete 20571 * Purpose: 20572 * Delete fp mirroring destination. 20573 * Parameters: 20574 * unit - (IN) BCM device number. 20575 * mtp_index - (IN) Mirror destination index. 20576 * flags - (IN) Mirror direction flags. 20577 * Returns: 20578 * BCM_X_XXX 20579 * Notes: 20580 */ 20581 int 20582 _bcm_esw_mirror_fp_dest_delete(int unit, int mtp_index, uint32 flags) 20583 { 20584 int rv = BCM_E_NONE; /* Operation return status. */ 20585 bcm_mirror_destination_t mirror_dest; /* Mirror destination. */ 20586 bcm_gport_t mirror_dest_id; /* Mirror destination id. */ 20587 20588 mirror_dest_id = BCM_GPORT_INVALID; 20589 20590 /* Input parameters check. */ 20591 /* At least one packet direction must be specified. */ 20592 if (!(flags & (BCM_MIRROR_PORT_INGRESS | BCM_MIRROR_PORT_EGRESS | 20593 BCM_MIRROR_PORT_EGRESS_TRUE))) { 20594 return (BCM_E_PARAM); 20595 } 20596 20597 /* Can't reserve multiple types of mtp in 1 shot. */ 20598 if (((flags & BCM_MIRROR_PORT_INGRESS) && 20599 (flags & (BCM_MIRROR_PORT_EGRESS | BCM_MIRROR_PORT_EGRESS_TRUE))) || 20600 ((flags & BCM_MIRROR_PORT_EGRESS) && 20601 (flags & BCM_MIRROR_PORT_EGRESS_TRUE))) { 20602 return (BCM_E_PARAM); 20603 } 20604 20605 if (!soc_feature(unit, soc_feature_egr_mirror_true) && 20606 (flags & BCM_MIRROR_PORT_EGRESS_TRUE)) { 20607 return (BCM_E_PARAM); 20608 } 20609 20610 /* Initialization check. */ 20611 if (0 == MIRROR_INIT(unit)) { 20612 return BCM_E_INIT; 20613 } 20614 20615 MIRROR_LOCK(unit); 20616 20617 /* shifting the mtp_index back since flexible slot shift was done 20618 * prior to this 20619 */ 20620 if (soc_feature(unit, soc_feature_mirror_flexible) && 20621 MIRROR_MTP_METHOD_IS_DIRECTED_FLEXIBLE(unit)) { 20622 mtp_index &= BCM_MIRROR_MTP_FLEX_SLOT_MASK; 20623 } 20624 20625 if (flags & BCM_MIRROR_PORT_EGRESS_TRUE) { 20626 mirror_dest_id = MIRROR_CONFIG_EGR_TRUE_MTP_DEST(unit, mtp_index); 20627 if (MIRROR_CONFIG(unit)->egr_true_mtp_count == 0) { 20628 rv = BCM_E_PARAM; 20629 } 20630 } else { 20631 if (soc_feature(unit, soc_feature_mirror_flexible) && 20632 !MIRROR_MTP_METHOD_IS_DIRECTED_FLEXIBLE(unit)) { 20633 mirror_dest_id = 20634 MIRROR_CONFIG_SHARED_MTP_DEST(unit, mtp_index); 20635 } else { 20636 if (flags & BCM_MIRROR_PORT_EGRESS) { 20637 mirror_dest_id = MIRROR_CONFIG_EGR_MTP_DEST(unit, mtp_index); 20638 } else if (flags & BCM_MIRROR_PORT_INGRESS) { 20639 mirror_dest_id = MIRROR_CONFIG_ING_MTP_DEST(unit, mtp_index); 20640 } else { 20641 rv = BCM_E_PARAM; 20642 } 20643 20644 #ifdef BCM_TRIUMPH2_SUPPORT 20645 if (BCM_SUCCESS(rv) && 20646 soc_feature(unit, soc_feature_mirror_flexible) && 20647 MIRROR_MTP_METHOD_IS_DIRECTED_FLEXIBLE(unit)) { 20648 rv = _bcm_xgs3_mtp_type_slot_unreserve(unit, flags, 20649 0, /* Unused */ 20650 BCM_MTP_SLOT_TYPE_FP, 20651 mtp_index); 20652 } 20653 #endif /* BCM_TRIUMPH2_SUPPORT */ 20654 } 20655 } 20656 20657 if (mirror_dest_id == BCM_GPORT_INVALID) { 20658 rv = _bcm_esw_mirror_mtp_unreserve(unit, mtp_index, FALSE, flags); 20659 MIRROR_UNLOCK(unit); 20660 return rv; 20661 } 20662 20663 /* Get mirror destination descriptor. */ 20664 if (BCM_SUCCESS(rv)) { 20665 rv = bcm_esw_mirror_destination_get(unit, mirror_dest_id, 20666 &mirror_dest); 20667 } 20668 20669 /* Free MTP index for mirror destination. */ 20670 if (BCM_SUCCESS(rv)) { 20671 rv = _bcm_esw_mirror_mtp_unreserve(unit, mtp_index, FALSE, flags); 20672 #ifdef BCM_TRIDENT3_SUPPORT 20673 /* Clear Tunnel information */ 20674 if (BCM_SUCCESS(rv)) { 20675 if (SOC_IS_TRIDENT3X(unit)) { 20676 if (1 >= MIRROR_DEST_REF_COUNT(unit, mirror_dest.mirror_dest_id)) { 20677 BCM_IF_ERROR_RETURN( 20678 _bcm_td3_mirror_encap_profile_index_clear(unit, 20679 BCM_GPORT_MIRROR_GET(mirror_dest.mirror_dest_id))); 20680 } 20681 } 20682 } 20683 #endif /* BCM_TRIDENT3_SUPPORT */ 20684 } 20685 20686 /* Destroy mirror destination if it was created by fp action add. */ 20687 if (BCM_SUCCESS(rv)) { 20688 if ((mirror_dest.flags & BCM_MIRROR_DEST_FIELD) && 20689 (1 >= MIRROR_DEST_REF_COUNT(unit, mirror_dest.mirror_dest_id))) { 20690 rv = bcm_esw_mirror_destination_destroy(unit, 20691 mirror_dest.mirror_dest_id); 20692 } 20693 } 20694 20695 MIRROR_UNLOCK(unit); 20696 return(rv); 20697 } 20698 20699 /* 20700 * Function: 20701 * _bcm_esw_mirror_fp_slot_add_ref 20702 * Purpose: 20703 * Add FP Slot Reference in TRX devices not supporting 20704 * flexible mirroring. 20705 * Parameters: 20706 * unit - (IN) BCM device number. 20707 * flags - (IN) _BCM_MIRROR_SLOT_XXX flags. 20708 * mtp_slot - (IN) MTP Slot Container. 20709 * Returns: 20710 * BCM_X_XXX 20711 * Notes: 20712 * Should not be called for devices supporting flexible mirroriing. 20713 */ 20714 int 20715 _bcm_esw_mirror_fp_slot_add_ref(int unit, uint32 flags, uint32 mtp_slot) 20716 { 20717 /* Initialization check */ 20718 if (!MIRROR_INIT(unit)) { 20719 return (BCM_E_INIT); 20720 } 20721 20722 if (MIRROR_SWITCH_IS_EXCLUSIVE(unit)) { 20723 20724 /* Take Mirror Lock */ 20725 MIRROR_LOCK(unit); 20726 20727 /* At least one of valid flag should be set */ 20728 if (!(flags & (_BCM_MIRROR_SLOT_FP | _BCM_MIRROR_SLOT_INGRESS | 20729 _BCM_MIRROR_SLOT_EGRESS))) { 20730 return (BCM_E_PARAM); 20731 } 20732 20733 /* Request cannot come from port */ 20734 if (flags & _BCM_MIRROR_SLOT_PORT) { 20735 return (BCM_E_PARAM); 20736 } 20737 20738 /* Ingress Slot Reserve From FP module */ 20739 if ((flags & _BCM_MIRROR_SLOT_INGRESS) && (flags & _BCM_MIRROR_SLOT_FP)) { 20740 MIRROR_CONFIG_ING_MTP_SLOT_REF(unit, mtp_slot)++; 20741 if (MIRROR_CONFIG_ING_MTP_SLOT_REF(unit, mtp_slot)) { 20742 MIRROR_CONFIG_ING_MTP_SLOT_OWNER(unit, mtp_slot) |= 20743 _BCM_MIRROR_SLOT_OWNER_FP; 20744 } 20745 } 20746 20747 /* Egress Slot Reserve From FP module */ 20748 if ((flags & _BCM_MIRROR_SLOT_EGRESS) && (flags & _BCM_MIRROR_SLOT_FP)) { 20749 MIRROR_CONFIG_EGR_MTP_SLOT_REF(unit, mtp_slot)++; 20750 if (MIRROR_CONFIG_EGR_MTP_SLOT_REF(unit, mtp_slot)) { 20751 MIRROR_CONFIG_EGR_MTP_SLOT_OWNER(unit, mtp_slot) |= 20752 _BCM_MIRROR_SLOT_OWNER_FP; 20753 } 20754 } 20755 20756 /* Release Mirror Lock */ 20757 MIRROR_UNLOCK(unit); 20758 } 20759 return BCM_E_NONE; 20760 } 20761 20762 /* 20763 * Function: 20764 * _bcm_esw_mirror_fp_slot_del_ref 20765 * Purpose: 20766 * Delete FP Slot Reference in TRX devices not supporting 20767 * flexible mirroring. 20768 * Parameters: 20769 * unit - (IN) BCM device number. 20770 * flags - (IN) _BCM_MIRROR_SLOT_XXX flags. 20771 * mtp_slot_map - (IN) MTP_SLOT_MAP. 20772 * Returns: 20773 * BCM_X_XXX 20774 * Notes: 20775 * Should not be called for devices supporting flexible mirroriing. 20776 */ 20777 int 20778 _bcm_esw_mirror_fp_slot_del_ref(int unit, uint32 flags, uint32 mtp_slot_map) 20779 { 20780 int mtp_slot = 0; 20781 20782 /* Initialization check */ 20783 if (!MIRROR_INIT(unit)) { 20784 return (BCM_E_INIT); 20785 } 20786 20787 if (MIRROR_SWITCH_IS_EXCLUSIVE(unit)) { 20788 20789 /* Take Mirror Lock */ 20790 MIRROR_LOCK(unit); 20791 20792 /* At least one of valid flag should be set */ 20793 if (!(flags & (_BCM_MIRROR_SLOT_FP | _BCM_MIRROR_SLOT_INGRESS | 20794 _BCM_MIRROR_SLOT_EGRESS))) { 20795 return (BCM_E_PARAM); 20796 } 20797 20798 /* Request cannot come from port */ 20799 if (flags & _BCM_MIRROR_SLOT_PORT) { 20800 return (BCM_E_PARAM); 20801 } 20802 20803 /* Ingress Slot Release From FP module */ 20804 if ((flags & _BCM_MIRROR_SLOT_INGRESS) && (flags & _BCM_MIRROR_SLOT_FP)) { 20805 if (mtp_slot_map & 0x1) { 20806 mtp_slot = 0; 20807 if (MIRROR_CONFIG_ING_MTP_SLOT_REF(unit, mtp_slot)) { 20808 MIRROR_CONFIG_ING_MTP_SLOT_REF(unit, mtp_slot)--; 20809 if (MIRROR_CONFIG_ING_MTP_SLOT_REF(unit, mtp_slot) == 0) { 20810 MIRROR_CONFIG_ING_MTP_SLOT_OWNER(unit, mtp_slot) &= 20811 ~(_BCM_MIRROR_SLOT_OWNER_FP); 20812 } 20813 } 20814 } 20815 if (mtp_slot_map & 0x2) { 20816 mtp_slot = 1; 20817 if (MIRROR_CONFIG_ING_MTP_SLOT_REF(unit, mtp_slot)) { 20818 MIRROR_CONFIG_ING_MTP_SLOT_REF(unit, mtp_slot)--; 20819 if (MIRROR_CONFIG_ING_MTP_SLOT_REF(unit, mtp_slot) == 0) { 20820 MIRROR_CONFIG_ING_MTP_SLOT_OWNER(unit, mtp_slot) &= 20821 ~(_BCM_MIRROR_SLOT_OWNER_FP); 20822 } 20823 } 20824 } 20825 } 20826 20827 /* Egress Slot Release From FP module */ 20828 if ((flags & _BCM_MIRROR_SLOT_EGRESS) && (flags & _BCM_MIRROR_SLOT_FP)) { 20829 if (mtp_slot_map & 0x1) { 20830 mtp_slot = 0; 20831 if (MIRROR_CONFIG_EGR_MTP_SLOT_REF(unit, mtp_slot)) { 20832 MIRROR_CONFIG_EGR_MTP_SLOT_REF(unit, mtp_slot)--; 20833 if (MIRROR_CONFIG_EGR_MTP_SLOT_REF(unit, mtp_slot) == 0) { 20834 MIRROR_CONFIG_EGR_MTP_SLOT_OWNER(unit, mtp_slot) &= 20835 ~(_BCM_MIRROR_SLOT_OWNER_FP); 20836 } 20837 } 20838 } 20839 if (mtp_slot_map & 0x2) { 20840 mtp_slot = 1; 20841 if (MIRROR_CONFIG_EGR_MTP_SLOT_REF(unit, mtp_slot)) { 20842 MIRROR_CONFIG_EGR_MTP_SLOT_REF(unit, mtp_slot)--; 20843 if (MIRROR_CONFIG_EGR_MTP_SLOT_REF(unit, mtp_slot) == 0) { 20844 MIRROR_CONFIG_EGR_MTP_SLOT_OWNER(unit, mtp_slot) &= 20845 ~(_BCM_MIRROR_SLOT_OWNER_FP); 20846 } 20847 } 20848 } 20849 } 20850 /* Release Mirror Lock */ 20851 MIRROR_UNLOCK(unit); 20852 } 20853 return BCM_E_NONE; 20854 } 20855 20856 #endif /* BCM_FIELD_SUPPORT && BCM_XGS3_SWITCH_SUPPORT */ 20857 20858 /* 20859 * Function: 20860 * _bcm_esw_mirror_enable 20861 * Purpose: 20862 * Set mirror enable = TRUE on all ports. 20863 * Parameters: 20864 * unit - (IN) BCM device number 20865 * Returns: 20866 * BCM_E_XXX 20867 * Notes: 20868 * When egress or fp mirroring is enabled, we need to enable 20869 * mirroring on all ports even if mirroring is only explicitely 20870 * enabled on a single port. This function ensures that the mirror 20871 * enable bit is toggled correctly on all ports, when 20872 * bcm_mirror_port_dest_xxx style apis are used by application. 20873 */ 20874 STATIC int 20875 _bcm_esw_mirror_enable(int unit) 20876 { 20877 bcm_port_t port; 20878 bcm_pbmp_t all_pbmp; 20879 20880 BCM_PBMP_CLEAR(all_pbmp); 20881 BCM_PBMP_ASSIGN(all_pbmp, PBMP_ALL(unit)); 20882 #ifdef BCM_KATANA2_SUPPORT 20883 if (SOC_IS_KATANA2(unit) && soc_feature(unit, soc_feature_flex_port)) { 20884 BCM_IF_ERROR_RETURN(_bcm_kt2_flexio_pbmp_update(unit, &all_pbmp)); 20885 } 20886 if (soc_feature(unit, soc_feature_linkphy_coe) || 20887 soc_feature(unit, soc_feature_subtag_coe)) { 20888 _bcm_kt2_subport_pbmp_update(unit, &all_pbmp); 20889 } 20890 #endif 20891 PBMP_ITER(all_pbmp, port) { 20892 BCM_IF_ERROR_RETURN(_bcm_esw_mirror_enable_set(unit, port, TRUE)); 20893 } 20894 return (BCM_E_NONE); 20895 } 20896 20897 /* 20898 * Function: 20899 * _bcm_esw_mirror_port_dest_search 20900 * Purpose: 20901 * Search to see if the the given port, destination exists. 20902 * Parameters: 20903 * unit - (IN) BCM device number 20904 * port - (IN) Port mirrored port. 20905 * flags - (IN) BCM_MIRROR_PORT_XXX flags. 20906 * mirror_dest - (IN) Mirroring destination gport. 20907 * Returns: 20908 * BCM_E_XXX 20909 * Notes: 20910 * This should be called with only one of the 20911 * INGRESS/EGRESS/TRUE_EGRESS flags set. 20912 */ 20913 STATIC int 20914 _bcm_esw_mirror_port_dest_search(int unit, bcm_port_t port, 20915 uint32 flags, bcm_gport_t mirror_dest) 20916 { 20917 bcm_gport_t mirror_dest_list[BCM_MIRROR_MTP_COUNT]; 20918 int mirror_dest_count, mtp; 20919 20920 BCM_IF_ERROR_RETURN 20921 (bcm_esw_mirror_port_dest_get(unit, port, flags, 20922 BCM_MIRROR_MTP_COUNT, 20923 mirror_dest_list, &mirror_dest_count)); 20924 20925 for (mtp = 0; mtp < mirror_dest_count; mtp++) { 20926 if (mirror_dest_list[mtp] == mirror_dest) { 20927 return BCM_E_EXISTS; 20928 } 20929 } 20930 20931 return BCM_E_NOT_FOUND; 20932 } 20933 20934 #ifdef BCM_TRIDENT_SUPPORT 20935 STATIC int 20936 _bcm_esw_mirror_egr_port_encap_clear(int unit, bcm_port_t port) 20937 { 20938 int rv = BCM_E_NONE; 20939 #ifdef BCM_TRIDENT3_SUPPORT 20940 if (SOC_IS_TRIDENT3X(unit)) { 20941 egr_lport_profile_entry_t egr_lport_profile_entry; 20942 /* Remove the previous profile index if any */ 20943 rv = READ_EGR_LPORT_PROFILEm(unit, MEM_BLOCK_ANY, port, 20944 &egr_lport_profile_entry); 20945 if (BCM_SUCCESS(rv)) { 20946 soc_EGR_LPORT_PROFILEm_field32_set(unit, &egr_lport_profile_entry, 20947 MIRROR_ENCAP_ENABLEf, 0); 20948 soc_EGR_LPORT_PROFILEm_field32_set(unit, &egr_lport_profile_entry, 20949 MIRROR_ENCAP_INDEXf, 0); 20950 rv = WRITE_EGR_LPORT_PROFILEm(unit, MEM_BLOCK_ANY, port, 20951 &egr_lport_profile_entry); 20952 } 20953 } else 20954 #endif /* BCM_TRIDENT3_SUPPORT */ 20955 { 20956 egr_port_entry_t egr_port_entry; 20957 rv = READ_EGR_PORTm (unit, MEM_BLOCK_ANY, port, &egr_port_entry); 20958 20959 if (BCM_SUCCESS(rv)) { 20960 soc_EGR_PORTm_field32_set(unit, &egr_port_entry, 20961 MIRROR_ENCAP_ENABLEf, 0); 20962 soc_EGR_PORTm_field32_set(unit, &egr_port_entry, 20963 MIRROR_ENCAP_INDEXf, 0); 20964 rv = WRITE_EGR_PORTm(unit, MEM_BLOCK_ANY, port, &egr_port_entry); 20965 } 20966 } 20967 return (BCM_E_NONE); 20968 } 20969 #endif /* BCM_TRIDENT_SUPPORT */ 20970 20971 20972 /* 20973 * Function: 20974 * bcm_esw_mirror_deinit 20975 * Purpose: 20976 * Deinitialize mirror software module. 20977 * Parameters: 20978 * unit - (IN) BCM device number. 20979 * Returns: 20980 * BCM_E_XXX 20981 */ 20982 int 20983 bcm_esw_mirror_deinit(int unit) 20984 { 20985 #ifdef BCM_SHADOW_SUPPORT 20986 if (soc_feature(unit, soc_feature_no_mirror)) { 20987 return BCM_E_NONE; 20988 } 20989 #endif 20990 /* Call internal sw structures clean up routine. */ 20991 return _bcm_esw_mirror_deinit(unit, &MIRROR_CONFIG(unit)); 20992 } 20993 20994 /* 20995 * Function: 20996 * bcm_esw_mirror_init 20997 * Purpose: 20998 * Initialize mirror software system. 20999 * Parameters: 21000 * unit - (IN) BCM device number. 21001 * Returns: 21002 * BCM_E_XXX 21003 */ 21004 int 21005 bcm_esw_mirror_init(int unit) 21006 { 21007 _bcm_mirror_config_p mirror_cfg_ptr;/* Mirror module config structue. */ 21008 bcm_mirror_destination_t *mdest; /* Mirror destinations iterator. */ 21009 int directed; /* Directed mirroring enable. */ 21010 int alloc_sz; /* Memory allocation size. */ 21011 int idx; /* MTP iteration index. */ 21012 int rv; /* Operation return status. */ 21013 #if defined(BCM_METROLITE_SUPPORT) 21014 uint16 dev_id; 21015 uint8 rev_id; 21016 #endif 21017 #ifdef BCM_WARM_BOOT_SUPPORT 21018 uint8 *mtp_scache; 21019 int mtp_num; /* Maximum number of MTP dests */ 21020 uint8 *mirror_method_scache; 21021 soc_scache_handle_t scache_handle; /* SCache reference number */ 21022 #if defined(BCM_TOMAHAWK3_SUPPORT) 21023 int num_slot_types; 21024 #endif /* BCM_TOMAHAWK3_SUPPORT */ 21025 uint32 wb_mirror_flags; 21026 #endif /* BCM_WARM_BOOT_SUPPORT */ 21027 #if defined(BCM_TOMAHAWK3_SUPPORT) 21028 soc_mem_t mem; 21029 int entry_words; 21030 int index_min = -1; 21031 int index_max = -1; 21032 #endif 21033 #if defined (BCM_TRIDENT3_SUPPORT) 21034 void *seq_entries[1]; 21035 uint32 profile_idx; 21036 egr_sequence_number_profile_entry_t seq_num_profile_entry[1]; 21037 #endif 21038 21039 #ifdef BCM_SHADOW_SUPPORT 21040 if (soc_feature(unit, soc_feature_no_mirror)) { 21041 return BCM_E_NONE; 21042 } 21043 #endif 21044 21045 /* Deinitialize the module if it was previously initialized. */ 21046 if (NULL != MIRROR_CONFIG(unit)) { 21047 _bcm_esw_mirror_deinit(unit, &MIRROR_CONFIG(unit)); 21048 } 21049 21050 /* Allocate mirror config structure. */ 21051 alloc_sz = sizeof(_bcm_mirror_config_t); 21052 mirror_cfg_ptr = sal_alloc(alloc_sz, "Mirror module"); 21053 if (NULL == mirror_cfg_ptr) { 21054 return (BCM_E_MEMORY); 21055 } 21056 sal_memset(mirror_cfg_ptr, 0, alloc_sz); 21057 21058 rv = _bcm_esw_directed_mirroring_get(unit, &directed); 21059 if (BCM_FAILURE(rv)) { 21060 _bcm_esw_mirror_deinit(unit, &mirror_cfg_ptr); 21061 return(BCM_E_INTERNAL); 21062 } 21063 #if defined(BCM_METROLITE_SUPPORT) 21064 soc_cm_get_id(unit, &dev_id, &rev_id); 21065 #endif 21066 #ifdef BCM_WARM_BOOT_SUPPORT 21067 if (SOC_WARM_BOOT(unit)) { 21068 rv = _bcm_esw_mirror_method_reinit(unit, &wb_mirror_flags); 21069 if (BCM_FAILURE(rv)) { 21070 _bcm_esw_mirror_deinit(unit, &mirror_cfg_ptr); 21071 return(rv); 21072 } 21073 } 21074 #endif 21075 if (directed) { 21076 if (soc_feature(unit, soc_feature_mirror_flexible)) { 21077 if (_bcm_mirror_mtp_method_init[unit] == 21078 BCM_MIRROR_MTP_METHOD_DIRECTED_FLEXIBLE) { 21079 mirror_cfg_ptr->mtp_method = 21080 BCM_MIRROR_MTP_METHOD_DIRECTED_FLEXIBLE; 21081 } else { 21082 mirror_cfg_ptr->mtp_method = 21083 BCM_MIRROR_MTP_METHOD_DIRECTED_LOCKED; 21084 } 21085 } else { 21086 mirror_cfg_ptr->mtp_method = 21087 BCM_MIRROR_MTP_METHOD_DIRECTED_LOCKED; 21088 } 21089 } else { 21090 mirror_cfg_ptr->mtp_method = BCM_MIRROR_MTP_METHOD_NON_DIRECTED; 21091 } 21092 _bcm_mirror_mtp_method_init[unit] = 21093 mirror_cfg_ptr->mtp_method; 21094 21095 21096 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_GREYHOUND_SUPPORT) 21097 if (soc_feature(unit, soc_feature_mirror_encap_profile)) { 21098 soc_mem_t mem; 21099 #ifdef BCM_TRIDENT3_SUPPORT 21100 soc_mem_t mems[4]; 21101 int mem_words[4]; 21102 #else /* BCM_TRIDENT3_SUPPORT */ 21103 soc_mem_t mems[3]; 21104 int mem_words[3]; 21105 #endif /* !BCM_TRIDENT3_SUPPORT */ 21106 int mems_cnt; 21107 #ifdef BCM_GREYHOUND_SUPPORT 21108 uint64 reg_val; 21109 #endif /* BCM_GREYHOUND_SUPPORT */ 21110 int port; 21111 bcm_pbmp_t all_pbmp; 21112 21113 mem = EGR_MIRROR_ENCAP_CONTROLm; 21114 if (SOC_MEM_IS_VALID(unit, mem)) { 21115 if (NULL == EGR_MIRROR_ENCAP(unit)) { 21116 EGR_MIRROR_ENCAP(unit) = 21117 sal_alloc(sizeof(soc_profile_mem_t), 21118 "EGR_MIRROR_ENCAP Profile Mems"); 21119 if (NULL == EGR_MIRROR_ENCAP(unit)) { 21120 _bcm_esw_mirror_deinit(unit, &mirror_cfg_ptr); 21121 return BCM_E_MEMORY; 21122 } 21123 soc_profile_mem_t_init(EGR_MIRROR_ENCAP(unit)); 21124 21125 mems_cnt = 0; 21126 mems[mems_cnt] = mem; 21127 mem_words[mems_cnt] = 21128 sizeof(egr_mirror_encap_control_entry_t) / 21129 sizeof(uint32); 21130 mems_cnt++; 21131 21132 mem = EGR_MIRROR_ENCAP_DATA_1m; 21133 if (SOC_MEM_IS_VALID(unit, mem)) { 21134 mems[mems_cnt] = mem; 21135 mem_words[mems_cnt] = 21136 sizeof(egr_mirror_encap_data_1_entry_t) / 21137 sizeof(uint32); 21138 mems_cnt++; 21139 } 21140 21141 mem = EGR_MIRROR_ENCAP_DATA_2m; 21142 if (SOC_MEM_IS_VALID(unit, mem)) { 21143 mems[mems_cnt] = mem; 21144 mem_words[mems_cnt] = 21145 sizeof(egr_mirror_encap_data_2_entry_t) / 21146 sizeof(uint32); 21147 mems_cnt++; 21148 } 21149 rv = soc_profile_mem_create(unit, mems, mem_words, 21150 mems_cnt, 21151 EGR_MIRROR_ENCAP(unit)); 21152 if (rv < 0) { 21153 _bcm_esw_mirror_deinit(unit, &mirror_cfg_ptr); 21154 return rv; 21155 } 21156 21157 BCM_PBMP_CLEAR(all_pbmp); 21158 BCM_PBMP_ASSIGN(all_pbmp, PBMP_ALL(unit)); 21159 #ifdef BCM_KATANA2_SUPPORT 21160 if (SOC_IS_KATANA2(unit) && 21161 soc_feature(unit, soc_feature_flex_port)) { 21162 BCM_IF_ERROR_RETURN( 21163 _bcm_kt2_flexio_pbmp_update(unit, &all_pbmp)); 21164 } 21165 if (soc_feature(unit, soc_feature_linkphy_coe) || 21166 soc_feature(unit, soc_feature_subtag_coe)) { 21167 _bcm_kt2_subport_pbmp_update(unit, &all_pbmp); 21168 } 21169 #endif 21170 PBMP_ITER(all_pbmp, port) { /* Intialize the Encap index */ 21171 #ifdef BCM_GREYHOUND_SUPPORT 21172 if (SOC_IS_GREYHOUND(unit) || SOC_IS_HURRICANE3(unit) || 21173 SOC_IS_GREYHOUND2(unit)) { 21174 rv = READ_EGR_PORT_64r(unit, port, ®_val); 21175 21176 if (BCM_SUCCESS(rv)) { 21177 soc_reg64_field32_set(unit, EGR_PORT_64r, ®_val, 21178 MIRROR_ENCAP_ENABLEf, 0); 21179 soc_reg64_field32_set(unit, EGR_PORT_64r, ®_val, 21180 MIRROR_ENCAP_INDEXf, 0); 21181 rv = WRITE_EGR_PORT_64r(unit, port, reg_val); 21182 } 21183 } else 21184 #endif /* BCM_GREYHOUND_SUPPORT */ 21185 { 21186 #ifdef BCM_TRIDENT_SUPPORT 21187 rv = _bcm_esw_mirror_egr_port_encap_clear(unit, port); 21188 #endif /* BCM_TRIDENT_SUPPORT */ 21189 } 21190 } 21191 } 21192 } 21193 #ifdef BCM_TRIDENT3_SUPPORT 21194 mem = EGR_MIRROR_TABLEm; 21195 if (SOC_MEM_IS_VALID(unit, mem)) { 21196 if (NULL == EGR_MIRROR_TABLE(unit)) { 21197 EGR_MIRROR_TABLE(unit) = 21198 sal_alloc(sizeof(soc_profile_mem_t), 21199 "EGR_MIRROR_TABLE Profile Mems"); 21200 if (NULL == EGR_MIRROR_TABLE(unit)) { 21201 _bcm_esw_mirror_deinit(unit, &mirror_cfg_ptr); 21202 return BCM_E_MEMORY; 21203 } 21204 soc_profile_mem_t_init(EGR_MIRROR_TABLE(unit)); 21205 21206 mems_cnt = 0; 21207 mems[mems_cnt] = mem; 21208 mem_words[mems_cnt] = sizeof(egr_mirror_table_entry_t)/sizeof(uint32); 21209 mems_cnt++; 21210 21211 rv = soc_profile_mem_create(unit, mems, mem_words, 21212 mems_cnt, EGR_MIRROR_TABLE(unit)); 21213 if (rv < 0) { 21214 _bcm_esw_mirror_deinit(unit, &mirror_cfg_ptr); 21215 return rv; 21216 } 21217 21218 BCM_PBMP_CLEAR(all_pbmp); 21219 BCM_PBMP_ASSIGN(all_pbmp, PBMP_ALL(unit)); 21220 PBMP_ITER(all_pbmp, port) { /* Intialize the Encap index */ 21221 rv = _bcm_esw_mirror_egr_port_encap_clear(unit, port); 21222 } 21223 } 21224 } 21225 mem = EGR_SEQUENCE_NUMBER_PROFILEm; 21226 if (SOC_MEM_IS_VALID(unit, mem)) { 21227 if (NULL == EGR_SEQ_NUMBER_PROFILE(unit)) { 21228 int entry_idxmin[1], entry_idxmax[1]; 21229 int support_idx; 21230 21231 EGR_SEQ_NUMBER_PROFILE(unit) = 21232 sal_alloc(sizeof(soc_profile_mem_t), 21233 "EGR_SEQUENCE_NUMBER Profile"); 21234 if (NULL == EGR_SEQ_NUMBER_PROFILE(unit)) { 21235 _bcm_esw_mirror_deinit(unit, &mirror_cfg_ptr); 21236 return BCM_E_MEMORY; 21237 } 21238 soc_profile_mem_t_init(EGR_SEQ_NUMBER_PROFILE(unit)); 21239 mems_cnt = 0; 21240 mems[mems_cnt] = mem; 21241 mem_words[mems_cnt] = sizeof(egr_sequence_number_profile_entry_t)/ 21242 sizeof(uint32); 21243 mems_cnt++; 21244 entry_idxmin[0] = soc_mem_index_min(unit, mem); 21245 /*Index 6&7 is configured by CANCUN for MPLS/IP Tunnel*/ 21246 entry_idxmax[0] = soc_mem_index_max(unit, mem) - 2; 21247 /*index 4&5 can't be used because SEQ_NUM_PROFILE_INDEX has only 2 bit*/ 21248 support_idx = (1 << soc_mem_field_length(unit, EGR_MIRROR_TABLEm, SEQ_NUM_PROFILE_INDEXf))-1; 21249 if (entry_idxmax[0] > support_idx) { 21250 entry_idxmax[0] = support_idx; 21251 } 21252 21253 rv = soc_profile_mem_index_create(unit, mems, mem_words, 21254 entry_idxmin, entry_idxmax, NULL, mems_cnt, 21255 EGR_SEQ_NUMBER_PROFILE(unit)); 21256 if (rv < 0) { 21257 _bcm_esw_mirror_deinit(unit, &mirror_cfg_ptr); 21258 return rv; 21259 } 21260 21261 sal_memset(&seq_num_profile_entry[0], 0, 21262 sizeof(seq_num_profile_entry[0])); 21263 seq_entries[0] = &seq_num_profile_entry[0]; 21264 rv = soc_profile_mem_add(unit, 21265 EGR_SEQ_NUMBER_PROFILE(unit), seq_entries, 1, 21266 &profile_idx); 21267 if (rv < 0) { 21268 _bcm_esw_mirror_deinit(unit, &mirror_cfg_ptr); 21269 return rv; 21270 } 21271 } 21272 } 21273 #endif /* BCM_TRIDENT3_SUPPORT */ 21274 } 21275 #endif /* BCM_TRIDENT_SUPPORT || BCM_GREYHOUND_SUPPORT */ 21276 21277 21278 #ifdef BCM_TRIUMPH2_SUPPORT 21279 if (soc_feature(unit, soc_feature_egr_mirror_true)) { 21280 mirror_cfg_ptr->egr_true_mtp_count = BCM_MIRROR_MTP_COUNT; 21281 } 21282 #endif /* BCM_TRIUMPH2_SUPPORT */ 21283 #if defined(BCM_METROLITE_SUPPORT) 21284 /* No of MTP supported for 53460 and 53461 is 21285 * one for ingress and one for egress and 21286 * flexible mirroring is not supported */ 21287 if( (dev_id == BCM53460_DEVICE_ID) || 21288 (dev_id == BCM53461_DEVICE_ID) ) { 21289 mirror_cfg_ptr->egr_mtp_count = 1; 21290 mirror_cfg_ptr->ing_mtp_count = 1; 21291 } else 21292 #endif 21293 { 21294 mirror_cfg_ptr->egr_mtp_count = BCM_MIRROR_MTP_COUNT; 21295 mirror_cfg_ptr->ing_mtp_count = BCM_MIRROR_MTP_COUNT; 21296 } 21297 21298 #ifdef BCM_WARM_BOOT_SUPPORT 21299 /* Determine maximum number used in any config */ 21300 mtp_num = 21301 mirror_cfg_ptr->egr_mtp_count + mirror_cfg_ptr->ing_mtp_count; 21302 #ifdef BCM_TRIUMPH2_SUPPORT 21303 if (soc_feature(unit, soc_feature_egr_mirror_true)) { 21304 mtp_num += mirror_cfg_ptr->egr_true_mtp_count; 21305 } 21306 #endif /* BCM_TRIUMPH2_SUPPORT */ 21307 21308 alloc_sz = sizeof(bcm_gport_t) * mtp_num; 21309 if (soc_feature(unit, soc_feature_mirror_flexible) && 21310 (mirror_cfg_ptr->mtp_method == BCM_MIRROR_MTP_METHOD_DIRECTED_FLEXIBLE)) { 21311 /* Slot-MTP mapping information for respective slot types */ 21312 alloc_sz += (sizeof(bcm_gport_t) * BCM_MIRROR_MTP_COUNT) * (BCM_MTP_SLOT_TYPE_SFLOW + 1); 21313 /* Reference counter for respective slot types */ 21314 alloc_sz += (sizeof(int) * BCM_MIRROR_MTP_COUNT) * (BCM_MTP_SLOT_TYPE_SFLOW + 1); 21315 /* BCM_MIRROR_DEST_FIELD flag */ 21316 alloc_sz += sizeof(uint16); 21317 /* Reference counter for MTP slot */ 21318 alloc_sz += sizeof(int) * BCM_MIRROR_MTP_COUNT; 21319 /* For ING MTP reference counter */ 21320 alloc_sz += sizeof(int) * (mirror_cfg_ptr->ing_mtp_count); 21321 /* For ING MTP reference counter */ 21322 alloc_sz += sizeof(int) * (mirror_cfg_ptr->egr_mtp_count); 21323 /* For destination reference counter */ 21324 alloc_sz += sizeof(int) * (mirror_cfg_ptr->egr_mtp_count + 21325 mirror_cfg_ptr->ing_mtp_count); 21326 #ifdef BCM_TRIUMPH2_SUPPORT 21327 if (soc_feature(unit, soc_feature_egr_mirror_true)) { 21328 alloc_sz += sizeof(int) * mirror_cfg_ptr->egr_true_mtp_count; 21329 } 21330 #endif /* BCM_TRIUMPH2_SUPPORT */ 21331 /* For pbmp_mtp_slot_used */ 21332 alloc_sz += sizeof(bcm_pbmp_t) * BCM_MIRROR_MTP_COUNT; 21333 /* For ING MTP destination flags */ 21334 alloc_sz += sizeof(uint32) * (mirror_cfg_ptr->ing_mtp_count); 21335 /* For ING MTP destination flags */ 21336 alloc_sz += sizeof(uint32) * (mirror_cfg_ptr->egr_mtp_count); 21337 #ifdef BCM_TRIUMPH2_SUPPORT 21338 if (soc_feature(unit, soc_feature_egr_mirror_true)) { 21339 alloc_sz += sizeof(uint32) * (mirror_cfg_ptr->egr_true_mtp_count); 21340 } 21341 #endif /* BCM_TRIUMPH2_SUPPORT */ 21342 #ifdef BCM_TRIDENT3_SUPPORT 21343 if (soc_feature(unit, soc_feature_mirror_flexible)) { 21344 /* alloc encap_to_edit_ctrl_id array. */ 21345 alloc_sz += (sizeof(uint32)*BCM_MIRROR_MTP_COUNT); 21346 /* alloc encap_profile_index_bmap. */ 21347 alloc_sz += sizeof(uint32); 21348 } 21349 #endif /* BCM_TRIDENT3_SUPPORT */ 21350 } 21351 21352 /* For non-flexible mtp destination flags */ 21353 #ifdef BCM_TRIUMPH2_SUPPORT 21354 if (soc_feature(unit, soc_feature_mirror_flexible) && 21355 (mirror_cfg_ptr->mtp_method != BCM_MIRROR_MTP_METHOD_DIRECTED_FLEXIBLE)) { 21356 /* For Shared MTP destination flags */ 21357 alloc_sz += sizeof(uint32) * BCM_MIRROR_MTP_COUNT; 21358 /* For egress true MTP destination flags */ 21359 if (soc_feature(unit, soc_feature_egr_mirror_true)) { 21360 alloc_sz += sizeof(uint32) * (mirror_cfg_ptr->egr_true_mtp_count); 21361 } 21362 /* For Shared MTP ref_count */ 21363 alloc_sz += sizeof(int) * BCM_MIRROR_MTP_COUNT; 21364 /* For Egress True MTP ref_count */ 21365 if (soc_feature(unit, soc_feature_egr_mirror_true)) { 21366 alloc_sz += sizeof(int) * (mirror_cfg_ptr->egr_true_mtp_count); 21367 } 21368 /* For Mirror Destination ref_count */ 21369 alloc_sz += sizeof(int) * BCM_MIRROR_MTP_COUNT; 21370 if (soc_feature(unit, soc_feature_egr_mirror_true)) { 21371 alloc_sz += sizeof(int) * (mirror_cfg_ptr->egr_true_mtp_count); 21372 } 21373 /* For MIRROR_CONFIG_MODE */ 21374 alloc_sz += sizeof(int); 21375 } 21376 #endif /* BCM_TRIUMPH2_SUPPORT */ 21377 21378 #ifdef BCM_TRIDENT2_SUPPORT 21379 if (soc_feature(unit, soc_feature_mirror_flexible)) { 21380 if (mirror_cfg_ptr->mtp_method == 21381 BCM_MIRROR_MTP_METHOD_DIRECTED_FLEXIBLE) { 21382 /* For Ingress,Egress MTP destination gport */ 21383 alloc_sz += sizeof(bcm_gport_t) * BCM_SWITCH_TRUNK_MAX_PORTCNT * 21384 (mirror_cfg_ptr->ing_mtp_count + 21385 mirror_cfg_ptr->egr_mtp_count); 21386 /* For Ingress,Egress MTP destination flags */ 21387 alloc_sz += sizeof(uint32) * BCM_SWITCH_TRUNK_MAX_PORTCNT * 21388 (mirror_cfg_ptr->ing_mtp_count + 21389 mirror_cfg_ptr->egr_mtp_count); 21390 } else { 21391 /* For Shared MTP destination gport */ 21392 alloc_sz += sizeof(bcm_gport_t) * BCM_SWITCH_TRUNK_MAX_PORTCNT * 21393 BCM_MIRROR_MTP_COUNT; 21394 /* For Shared MTP destination flags */ 21395 alloc_sz += sizeof(uint32) * BCM_SWITCH_TRUNK_MAX_PORTCNT * 21396 BCM_MIRROR_MTP_COUNT; 21397 } 21398 } 21399 #endif /* BCM_TRIDENT2_SUPPORT */ 21400 21401 #ifdef BCM_TRIUMPH2_SUPPORT 21402 if (soc_feature(unit, soc_feature_mirror_flexible) && 21403 (mirror_cfg_ptr->mtp_method == BCM_MIRROR_MTP_METHOD_DIRECTED_FLEXIBLE)) { 21404 /* Egr True MTP Ref Count */ 21405 if (soc_feature(unit, soc_feature_egr_mirror_true)) { 21406 alloc_sz += sizeof(uint32) * (mirror_cfg_ptr->egr_true_mtp_count); 21407 } 21408 } 21409 #endif 21410 21411 #ifdef BCM_TRIDENT3_SUPPORT 21412 /* BCM_WB_VERSION_1_7 */ 21413 if (soc_feature(unit, soc_feature_mirror_flexible)) { 21414 /* encap_to_edit_ctrl_id */ 21415 alloc_sz += sizeof(uint32) * (BCM_MIRROR_MTP_COUNT); 21416 /* encap_to_edit_ctrl_id_bmap */ 21417 alloc_sz += sizeof(uint32); 21418 } 21419 #endif /* BCM_TRIDENT3_SUPPORT */ 21420 21421 /* BCM_WB_VERSION_1_8 */ 21422 if (soc_feature(unit, soc_feature_mirror_flexible) && 21423 (mirror_cfg_ptr->mtp_method == BCM_MIRROR_MTP_METHOD_DIRECTED_FLEXIBLE)) { 21424 21425 #if defined(BCM_TOMAHAWK3_SUPPORT) 21426 /* INT, ETRAP, DLB Flow Monitoring */ 21427 num_slot_types = 3; 21428 21429 /* Slot-MTP mapping information for respective slot type */ 21430 alloc_sz += sizeof(bcm_gport_t) * BCM_MIRROR_MTP_COUNT * num_slot_types; 21431 /* Reference counter for respective slot type */ 21432 alloc_sz += sizeof(int) * BCM_MIRROR_MTP_COUNT * num_slot_types; 21433 #endif /* BCM_TOMAHAWK3_SUPPORT */ 21434 } 21435 21436 /* BCM_WB_VERSION_1_9 */ 21437 if (soc_feature(unit, soc_feature_th3_style_fp)) { 21438 #ifdef BCM_TOMAHAWK3_SUPPORT 21439 alloc_sz += (sizeof(_bcm_mirror_zero_profile_t) * MIRROR_ZERO_PROFILE_INDEX_MAX); 21440 #endif 21441 } 21442 21443 /* BCM_WB_VERSION_1_10 */ 21444 if (soc_feature(unit, soc_feature_erspan3_support)) { 21445 #ifdef BCM_TRIDENT3_SUPPORT 21446 alloc_sz += ((sizeof(uint32) + sizeof(uint16)) * (BCM_MIRROR_MTP_COUNT * 3)); 21447 #endif 21448 } 21449 21450 /* BCM_WB_VERSION_1_11 */ 21451 if (soc_feature(unit, soc_feature_mirror_encap_profile)) { 21452 #ifdef BCM_TRIDENT3_SUPPORT 21453 alloc_sz += ((sizeof(uint32)) * (BCM_MIRROR_MTP_COUNT * 3)); 21454 #endif 21455 } 21456 21457 SOC_SCACHE_HANDLE_SET(scache_handle, 21458 unit, BCM_MODULE_MIRROR, 0); 21459 rv = _bcm_esw_scache_ptr_get(unit, scache_handle, 21460 (0 == SOC_WARM_BOOT(unit)), 21461 alloc_sz, 21462 &mtp_scache, BCM_WB_DEFAULT_VERSION, NULL); 21463 if (BCM_FAILURE(rv) && (rv != BCM_E_NOT_FOUND)) { 21464 _bcm_esw_mirror_deinit(unit, &mirror_cfg_ptr); 21465 return rv; 21466 } 21467 /* Allocate space for mirror_method */ 21468 alloc_sz = sizeof(_bcm_mirror_mtp_method_init[unit]); 21469 21470 /* BCM_WB_VERSION_1_12: allocate the td3 flag */ 21471 alloc_sz += sizeof(uint32); 21472 SOC_SCACHE_HANDLE_SET(scache_handle, 21473 unit, BCM_MODULE_MIRROR, 1); 21474 SOC_SCACHE_MODULE_MAX_PARTITIONS_SET(unit, BCM_MODULE_MIRROR, 1); 21475 rv = _bcm_esw_scache_ptr_get(unit, scache_handle, 21476 (0 == SOC_WARM_BOOT(unit)), 21477 alloc_sz, 21478 &mirror_method_scache, BCM_WB_DEFAULT_VERSION, NULL); 21479 if (BCM_FAILURE(rv) && (rv != BCM_E_NOT_FOUND)) { 21480 _bcm_esw_mirror_deinit(unit, &mirror_cfg_ptr); 21481 return rv; 21482 } 21483 #endif /* BCM_WARM_BOOT_SUPPORT */ 21484 21485 if (!directed) { 21486 #ifdef BCM_TRIUMPH2_SUPPORT 21487 if (soc_feature(unit, soc_feature_egr_mirror_true)) { 21488 mirror_cfg_ptr->egr_true_mtp_count = 0; 21489 } 21490 #endif /* BCM_TRIUMPH2_SUPPORT */ 21491 mirror_cfg_ptr->egr_mtp_count = 1; 21492 mirror_cfg_ptr->ing_mtp_count = 1; 21493 } else if (!soc_feature(unit, soc_feature_mirror_flexible) 21494 && SOC_IS_TRX(unit)) { 21495 /* Limited egress mirroring bitmap registers */ 21496 mirror_cfg_ptr->egr_mtp_count = 2; 21497 21498 if (SOC_IS_ENDURO(unit)) { 21499 /* Limited ingress mirroring bitmap registers */ 21500 mirror_cfg_ptr->ing_mtp_count = 2; 21501 } 21502 } 21503 21504 if (!directed || soc_feature(unit, soc_feature_mirror_flexible)) { 21505 mirror_cfg_ptr->port_em_mtp_count = mirror_cfg_ptr->egr_mtp_count; 21506 mirror_cfg_ptr->port_im_mtp_count = mirror_cfg_ptr->ing_mtp_count; 21507 } else { 21508 if (SOC_IS_TRX(unit) && !SOC_IS_HURRICANEX(unit) && 21509 !SOC_IS_GREYHOUND(unit) && !SOC_IS_GREYHOUND2(unit)) { 21510 mirror_cfg_ptr->port_em_mtp_count = 2; 21511 mirror_cfg_ptr->port_im_mtp_count = 2; 21512 } else { 21513 mirror_cfg_ptr->port_em_mtp_count = 1; 21514 mirror_cfg_ptr->port_im_mtp_count = 1; 21515 } 21516 } 21517 if (!directed) { 21518 if (soc_feature(unit, soc_feature_mirror_flexible)) { 21519 mirror_cfg_ptr->mtp_dev_mask = (BCM_MIRROR_MTP_ONE | 21520 BCM_MIRROR_MTP_THREE); 21521 } else { 21522 /* Only one MTP permitted in non-directed mode */ 21523 mirror_cfg_ptr->mtp_dev_mask = BCM_XGS3_MIRROR_MTP_MASK; 21524 } 21525 } else if (soc_feature(unit, soc_feature_mirror_flexible)) { 21526 mirror_cfg_ptr->mtp_dev_mask = BCM_TR2_MIRROR_MTP_MASK; 21527 } else if (SOC_IS_HURRICANEX(unit) || SOC_IS_GREYHOUND(unit) || 21528 SOC_IS_GREYHOUND2(unit)) { 21529 mirror_cfg_ptr->mtp_dev_mask = BCM_XGS3_MIRROR_MTP_MASK; 21530 } else if (SOC_IS_TRX(unit)) { 21531 mirror_cfg_ptr->mtp_dev_mask = BCM_TRX_MIRROR_MTP_MASK; 21532 } else { 21533 mirror_cfg_ptr->mtp_dev_mask = BCM_XGS3_MIRROR_MTP_MASK; 21534 } 21535 #if defined(BCM_METROLITE_SUPPORT) 21536 if( (dev_id == BCM53460_DEVICE_ID) || 21537 (dev_id == BCM53461_DEVICE_ID) ) { 21538 mirror_cfg_ptr->egr_mtp_count =1; 21539 mirror_cfg_ptr->ing_mtp_count = 1; 21540 mirror_cfg_ptr->port_em_mtp_count = 1; 21541 mirror_cfg_ptr->port_im_mtp_count = 1; 21542 mirror_cfg_ptr->mtp_dev_mask = BCM_XGS3_MIRROR_MTP_MASK; 21543 } 21544 #endif 21545 /* Allocate mirror destinations structure. */ 21546 if (!directed) { 21547 mirror_cfg_ptr->dest_count = 1; 21548 } else if (soc_feature(unit, soc_feature_mirror_flexible) && 21549 (BCM_MIRROR_MTP_METHOD_DIRECTED_LOCKED == 21550 mirror_cfg_ptr->mtp_method)) { 21551 mirror_cfg_ptr->dest_count = BCM_MIRROR_MTP_COUNT; 21552 } else { 21553 mirror_cfg_ptr->dest_count = 21554 (mirror_cfg_ptr->egr_mtp_count + mirror_cfg_ptr->ing_mtp_count); 21555 } 21556 #ifdef BCM_TRIUMPH2_SUPPORT 21557 if (soc_feature(unit, soc_feature_egr_mirror_true) && (directed)) { 21558 mirror_cfg_ptr->dest_count += mirror_cfg_ptr->egr_true_mtp_count; 21559 } 21560 #endif /* BCM_TRIUMPH2_SUPPORT */ 21561 alloc_sz = 21562 mirror_cfg_ptr->dest_count * sizeof(_bcm_mirror_dest_config_t); 21563 21564 mirror_cfg_ptr->dest_arr = sal_alloc(alloc_sz, "Mirror destinations"); 21565 if (NULL == mirror_cfg_ptr->dest_arr) { 21566 _bcm_esw_mirror_deinit(unit, &mirror_cfg_ptr); 21567 return (BCM_E_MEMORY); 21568 } 21569 sal_memset(mirror_cfg_ptr->dest_arr, 0, alloc_sz); 21570 for (idx = 0; idx < mirror_cfg_ptr->dest_count; idx++) { 21571 mdest = &mirror_cfg_ptr->dest_arr[idx].mirror_dest; 21572 BCM_GPORT_MIRROR_SET(mdest->mirror_dest_id, idx); 21573 } 21574 21575 /* Allocate mirror destinations structure. */ 21576 if (soc_feature(unit, soc_feature_mirror_flexible) && 21577 (BCM_MIRROR_MTP_METHOD_DIRECTED_FLEXIBLE != 21578 mirror_cfg_ptr->mtp_method)) { 21579 alloc_sz = BCM_MIRROR_MTP_COUNT * sizeof(_bcm_mtp_config_t); 21580 mirror_cfg_ptr->shared_mtp = sal_alloc(alloc_sz, "Shared MTP indexes"); 21581 if (NULL == mirror_cfg_ptr->shared_mtp) { 21582 _bcm_esw_mirror_deinit(unit, &mirror_cfg_ptr); 21583 return (BCM_E_MEMORY); 21584 } 21585 sal_memset(mirror_cfg_ptr->shared_mtp, 0, alloc_sz); 21586 } else { 21587 /* Allocate egress mirror destinations structure. */ 21588 alloc_sz = mirror_cfg_ptr->egr_mtp_count * sizeof(_bcm_mtp_config_t); 21589 mirror_cfg_ptr->egr_mtp = sal_alloc(alloc_sz, "Egress MTP indexes"); 21590 if (NULL == mirror_cfg_ptr->egr_mtp) { 21591 _bcm_esw_mirror_deinit(unit, &mirror_cfg_ptr); 21592 return (BCM_E_MEMORY); 21593 } 21594 sal_memset(mirror_cfg_ptr->egr_mtp, 0, alloc_sz); 21595 21596 /* Allocate ingress mirror destinations structure. */ 21597 alloc_sz = mirror_cfg_ptr->ing_mtp_count * sizeof(_bcm_mtp_config_t); 21598 mirror_cfg_ptr->ing_mtp = sal_alloc(alloc_sz, "Ingress MTP indexes"); 21599 if (NULL == mirror_cfg_ptr->ing_mtp) { 21600 _bcm_esw_mirror_deinit(unit, &mirror_cfg_ptr); 21601 return (BCM_E_MEMORY); 21602 } 21603 sal_memset(mirror_cfg_ptr->ing_mtp, 0, alloc_sz); 21604 } 21605 21606 #ifdef BCM_TRIUMPH2_SUPPORT 21607 if (soc_feature(unit, soc_feature_egr_mirror_true)) { 21608 /* Allocate egress true mirror destinations structure. */ 21609 alloc_sz = 21610 mirror_cfg_ptr->egr_true_mtp_count * sizeof(_bcm_mtp_config_t); 21611 mirror_cfg_ptr->egr_true_mtp = sal_alloc(alloc_sz, 21612 "Egress true MTP indexes"); 21613 if (NULL == mirror_cfg_ptr->egr_true_mtp) { 21614 _bcm_esw_mirror_deinit(unit, &mirror_cfg_ptr); 21615 return (BCM_E_MEMORY); 21616 } 21617 sal_memset(mirror_cfg_ptr->egr_true_mtp, 0, alloc_sz); 21618 } 21619 21620 if (soc_feature(unit, soc_feature_mirror_flexible) && 21621 (BCM_MIRROR_MTP_METHOD_DIRECTED_FLEXIBLE == 21622 mirror_cfg_ptr->mtp_method)) { 21623 int mtp_type; 21624 21625 for (mtp_type = BCM_MTP_SLOT_TYPE_PORT; 21626 mtp_type < BCM_MTP_SLOT_TYPES; mtp_type++) { 21627 /* Allocate MTP types records. */ 21628 mirror_cfg_ptr->mtp_slot_count[mtp_type] = 4; 21629 21630 alloc_sz = mirror_cfg_ptr->mtp_slot_count[mtp_type] * 21631 sizeof(_bcm_mtp_config_t); 21632 mirror_cfg_ptr->mtp_slot[mtp_type] = sal_alloc(alloc_sz, 21633 "Typed MTP indexes"); 21634 if (NULL == mirror_cfg_ptr->mtp_slot[mtp_type]) { 21635 _bcm_esw_mirror_deinit(unit, &mirror_cfg_ptr); 21636 return (BCM_E_MEMORY); 21637 } 21638 sal_memset(mirror_cfg_ptr->mtp_slot[mtp_type], 0, alloc_sz); 21639 } 21640 } 21641 #endif /* BCM_TRIUMPH2_SUPPORT */ 21642 21643 /* Ingress/Egress Slot Reference Containers for devices 21644 not supporting flex mirroring */ 21645 if(_bcm_switch_mirror_exclusive_config[unit] == _BCM_SWITCH_MIRROR_EXCLUSIVE) { 21646 int mtp_slot_cnt = 0; 21647 int mtp_slot = 0; 21648 21649 /* Count Number of Slot Container */ 21650 BCM_MIRROR_MTP_ITER(mirror_cfg_ptr->mtp_dev_mask, mtp_slot) { 21651 mtp_slot_cnt++; 21652 } 21653 21654 /* Allocate Ing/Egr Slot Ref Containers */ 21655 alloc_sz = mtp_slot_cnt * sizeof(_bcm_mtp_slot_config_t); 21656 21657 mirror_cfg_ptr->ing_slot_container = 21658 sal_alloc(alloc_sz, "Ingress Slot Container"); 21659 21660 mirror_cfg_ptr->egr_slot_container = 21661 sal_alloc(alloc_sz, "Egress Slot Container"); 21662 21663 if ((NULL == mirror_cfg_ptr->ing_slot_container) || 21664 (NULL == mirror_cfg_ptr->egr_slot_container)) { 21665 _bcm_esw_mirror_deinit(unit, &mirror_cfg_ptr); 21666 return (BCM_E_MEMORY); 21667 } 21668 sal_memset(mirror_cfg_ptr->ing_slot_container, 0, alloc_sz); 21669 sal_memset(mirror_cfg_ptr->egr_slot_container, 0, alloc_sz); 21670 } 21671 21672 #ifdef BCM_TOMAHAWK3_SUPPORT 21673 if (soc_feature(unit, soc_feature_th3_style_fp)) { 21674 21675 mem = EGR_MIRROR_ZERO_OFFSET_PROFILEm; 21676 21677 soc_profile_mem_t_init(&mirror_cfg_ptr->mirror_zeroing_profile); 21678 /* Determine redirection profile entry size in number of words. */ 21679 entry_words = sizeof(egr_mirror_zero_offset_profile_entry_t) 21680 / sizeof(uint32); 21681 21682 index_min = MIRROR_ZERO_PROFILE_INDEX_MIN; 21683 index_max = MIRROR_ZERO_PROFILE_INDEX_MAX; 21684 /* Create the redirection profile table. */ 21685 rv = soc_profile_mem_index_create(unit, &mem, &entry_words, 21686 &index_min, &index_max, NULL, 1, 21687 &mirror_cfg_ptr->mirror_zeroing_profile); 21688 21689 if (BCM_FAILURE(rv)) { 21690 LOG_ERROR(BSL_LS_BCM_MIRROR, (BSL_META_U(unit, 21691 "Error: Egr Mirror Zero profile creation failed.=%d\n"), 21692 rv)); 21693 _bcm_esw_mirror_deinit(unit, &mirror_cfg_ptr); 21694 return (rv); 21695 } 21696 } 21697 #endif 21698 21699 /* Create protection mutex. */ 21700 mirror_cfg_ptr->mutex = sal_mutex_create("Meter module mutex"); 21701 if (NULL == mirror_cfg_ptr->mutex) { 21702 _bcm_esw_mirror_deinit(unit, &mirror_cfg_ptr); 21703 return (BCM_E_MEMORY); 21704 } 21705 21706 /* Take protection mutex for initial state setting & hw clear. */ 21707 sal_mutex_take(mirror_cfg_ptr->mutex, sal_mutex_FOREVER); 21708 21709 MIRROR_CONFIG(unit) = mirror_cfg_ptr; 21710 21711 #ifdef BCM_WARM_BOOT_SUPPORT 21712 if (SOC_WARM_BOOT(unit)) { 21713 /* Reload mirror configuration info from HW */ 21714 rv = _bcm_esw_mirror_reload(unit, directed, wb_mirror_flags); 21715 } else 21716 #endif /* BCM_WARM_BOOT_SUPPORT */ 21717 { 21718 #ifdef BCM_TRIDENT3_SUPPORT 21719 if (SOC_IS_TRIDENT3X(unit)) { 21720 /* Setup the profile index variables */ 21721 encap_profile_index_bmap=0x00; 21722 memset(&encap_to_edit_ctrl_id, 0, sizeof(encap_to_edit_ctrl_id)); 21723 } 21724 #endif /* BCM_TRIDENT3_SUPPORT */ 21725 /* Clear memories/registers. */ 21726 rv = _bcm_esw_mirror_hw_clear(unit); 21727 21728 #ifdef BCM_TRIDENT3_SUPPORT 21729 if (SOC_IS_TRIDENT3X(unit)) { 21730 /* initialize the mirror HG tag configuration based on Cancun */ 21731 SOC_IF_ERROR_RETURN(soc_cancun_app_dest_entry_set(unit, 21732 EGR_HG_MIRROR_EDIT_CTRL_IDr, 21733 0, INVALIDf, 21734 CANCUN_APP__EGR_HG_MIRROR_EDIT_CTRL_ID__INGRESS_MIRROR_HG_UNTAG, 21735 0)); 21736 SOC_IF_ERROR_RETURN(soc_cancun_app_dest_entry_set(unit, 21737 EGR_HG_MIRROR_EDIT_CTRL_IDr, 21738 0, INVALIDf, 21739 CANCUN_APP__EGR_HG_MIRROR_EDIT_CTRL_ID__INGRESS_MIRROR_HG_TAG, 21740 0)); 21741 } 21742 #endif /* BCM_TRIDENT3_SUPPORT */ 21743 21744 #ifdef BCM_TOMAHAWK3_SUPPORT 21745 if (SOC_IS_TOMAHAWK3(unit)) { 21746 /* Initialize ipfix version for Psamp */ 21747 if (BCM_SUCCESS(rv)) { 21748 uint32 regval = 0; 21749 21750 soc_reg_field_set(unit, EGR_MIRROR_ENCAP_PSAMPr, ®val, 21751 IPFIX_VERSIONf, (uint32)0xA); 21752 21753 rv = soc_reg32_set(unit, EGR_MIRROR_ENCAP_PSAMPr, REG_PORT_ANY, 21754 0, regval); 21755 } 21756 } 21757 #endif /* BCM_TOMAHAWK3_SUPPORT */ 21758 } 21759 21760 if (BCM_FAILURE(rv)) { 21761 MIRROR_UNLOCK(unit); 21762 _bcm_esw_mirror_deinit(unit, &mirror_cfg_ptr); 21763 MIRROR_CONFIG(unit) = NULL; 21764 return (BCM_E_FAIL); 21765 } 21766 21767 MIRROR_UNLOCK(unit); 21768 21769 return (BCM_E_NONE); 21770 } 21771 21772 /* 21773 * Function: 21774 * _bcmi_esw_mirror_flex_port_init 21775 * Purpose: 21776 * Initialize mirror configuration on a port which is 21777 * being added/removed(flexing) in the runtime. 21778 * Parameters: 21779 * unit - (IN) BCM device number. 21780 * port - local port number 21781 * enable - TRUE when adding a port, FALSE when removing a port 21782 * Returns: 21783 * BCM_E_XXX 21784 * Note: 21785 * apply the same code to both port attach and detach 21786 * attach: have a default state for mirror packet encap configuration 21787 * detach: clear to prevent misleading warmboot during hardware recovery 21788 */ 21789 21790 STATIC int 21791 _bcmi_esw_mirror_flex_port_init (int unit, bcm_port_t port, int enable) 21792 { 21793 #if defined(BCM_TRIUMPH2_SUPPORT) 21794 mirror_control_entry_t mc_entry; 21795 uint32 mc_reg; 21796 #endif /* BCM_TRIUMPH2_SUPPORT */ 21797 int mtp_index; 21798 bcm_pbmp_t pbmp; 21799 int mode; /* mirroring mode. */ 21800 int rv = BCM_E_NONE; 21801 21802 #if defined(BCM_TRIUMPH2_SUPPORT) 21803 /* Initialize default mirror control settings */ 21804 if (soc_feature(unit, soc_feature_mirror_flexible) || 21805 (soc_feature(unit, soc_feature_egr_mirror_true))) { 21806 if (soc_feature(unit, soc_feature_mirror_control_mem)) { 21807 sal_memset(&mc_entry, 0, sizeof(mc_entry)); 21808 for (mtp_index = 0; mtp_index < BCM_MIRROR_MTP_COUNT; 21809 mtp_index++) { 21810 soc_mem_field32_set(unit, MIRROR_CONTROLm, &mc_entry, 21811 _mtp_index_field[mtp_index], 21812 enable? mtp_index : 0); 21813 soc_mem_field32_set(unit, MIRROR_CONTROLm, &mc_entry, 21814 _non_uc_mtp_index_field[mtp_index], 21815 enable? mtp_index: 0); 21816 } 21817 } else { 21818 mc_reg = 0; 21819 for (mtp_index = 0; mtp_index < BCM_MIRROR_MTP_COUNT; 21820 mtp_index++) { 21821 soc_reg_field_set(unit, MIRROR_CONTROLr, &mc_reg, 21822 _mtp_index_field[mtp_index], 21823 enable? mtp_index: 0); 21824 soc_reg_field_set(unit, MIRROR_CONTROLr, &mc_reg, 21825 _non_uc_mtp_index_field[mtp_index], 21826 enable? mtp_index: 0); 21827 } 21828 } 21829 } 21830 21831 /* Set up standard settings for flexible mirroring. */ 21832 if (soc_feature(unit, soc_feature_mirror_flexible)) { 21833 /* Set MTP mapping to 1-1 for flexible mirroring */ 21834 if (soc_feature(unit, soc_feature_mirror_control_mem)) { 21835 BCM_IF_ERROR_RETURN(WRITE_MIRROR_CONTROLm(unit, MEM_BLOCK_ANY, 21836 port, &mc_entry)); 21837 } else { 21838 BCM_IF_ERROR_RETURN(WRITE_MIRROR_CONTROLr(unit, port, mc_reg)); 21839 } 21840 } 21841 #endif /* BCM_TRIUMPH2_SUPPORT */ 21842 21843 /* Reset global mirror enable bit after the mirror control 21844 * register is handled. */ 21845 mode = MIRROR_CONFIG_MODE(unit); 21846 if (enable) { 21847 BCM_IF_ERROR_RETURN(_bcm_esw_mirror_enable_set(unit, port, 21848 IS_ST_PORT(unit, port) ? 1 : 21849 ((BCM_MIRROR_DISABLE != mode) ? 1 : 0))); 21850 } else { 21851 BCM_IF_ERROR_RETURN(_bcm_esw_mirror_enable_set(unit, port, 0)); 21852 } 21853 21854 /* Disable ingress mirroring. */ 21855 BCM_IF_ERROR_RETURN(_bcm_esw_mirror_ingress_set(unit, port, 0)); 21856 21857 /* Disable egress mirroring for all MTP indexes */ 21858 SOC_PBMP_CLEAR(pbmp); 21859 21860 for (mtp_index = 0; mtp_index < BCM_MIRROR_MTP_COUNT; mtp_index++) { 21861 (void)(_bcm_esw_mirror_egr_dest_set(unit, port, mtp_index, 21862 &pbmp)); 21863 } 21864 21865 #ifdef BCM_FIREBOLT_SUPPORT 21866 /* Clear RSPAN settings */ 21867 if (SOC_REG_IS_VALID(unit, EGR_RSPAN_VLAN_TAGr)) { 21868 BCM_IF_ERROR_RETURN(WRITE_EGR_RSPAN_VLAN_TAGr(unit, port, 0)); 21869 } 21870 #endif /* BCM_FIREBOLT_SUPPORT */ 21871 21872 #if defined(BCM_TRIUMPH2_SUPPORT) 21873 /* Clear settings of mirror_to_pbmp_set */ 21874 #ifdef BCM_GREYHOUND2_SUPPORT 21875 if (soc_feature (unit, soc_feature_high_portcount_register)){ 21876 uint64 val64; 21877 COMPILER_64_ZERO(val64); 21878 BCM_IF_ERROR_RETURN(WRITE_IMIRROR_BITMAP_LOr(unit, port, val64)); 21879 BCM_IF_ERROR_RETURN(WRITE_IMIRROR_BITMAP_HIr(unit, port, val64)); 21880 }else 21881 #endif /*BCM_GREYHOUND2_SUPPORT*/ 21882 if (SOC_REG_IS_VALID(unit, IMIRROR_BITMAP_64r)) { 21883 uint32 values[2]; 21884 soc_field_t fields[] = {BITMAP_LOf, BITMAP_HIf}; 21885 values[0] = values[1] = 0; 21886 BCM_IF_ERROR_RETURN(soc_reg_fields32_modify(unit, 21887 IMIRROR_BITMAP_64r, port, 2, fields, values)); 21888 } else if (SOC_REG_IS_VALID(unit, IMIRROR_BITMAPr)) { 21889 BCM_IF_ERROR_RETURN(WRITE_IMIRROR_BITMAPr(unit, port, 0)); 21890 } 21891 21892 #endif /* BCM_TRIUMPH2_SUPPORT */ 21893 21894 #if defined(BCM_TRIDENT_SUPPORT) 21895 if (soc_feature(unit, soc_feature_mirror_control_mem)) { 21896 /* For TH3, IMIRROR_BITMAP is not present */ 21897 if (SOC_MEM_IS_VALID(unit, IMIRROR_BITMAPm)) { 21898 imirror_bitmap_entry_t entry; 21899 21900 /* Clear settings of mirror_to_pbmp_set */ 21901 sal_memset(&entry, 0, sizeof(imirror_bitmap_entry_t)); 21902 BCM_IF_ERROR_RETURN(WRITE_IMIRROR_BITMAPm(unit, MEM_BLOCK_ANY, 21903 port, &entry)); 21904 } 21905 } 21906 if (soc_feature(unit, soc_feature_mirror_encap_profile)) { 21907 rv = _bcm_esw_mirror_egr_port_encap_clear(unit, port); 21908 } 21909 #endif /* BCM_TRIDENT_SUPPORT */ 21910 return rv; 21911 21912 } 21913 21914 /* 21915 * Function: 21916 * bcmi_esw_mirror_port_attach 21917 * Purpose: 21918 * initialize the mirror per-port configuration in the runtime. 21919 * Parameters: 21920 * unit - (IN) BCM device number. 21921 * port - local port number 21922 * Returns: 21923 * BCM_E_XXX 21924 */ 21925 21926 int 21927 bcmi_esw_mirror_port_attach (int unit, bcm_port_t port) 21928 { 21929 return _bcmi_esw_mirror_flex_port_init(unit,port,TRUE); 21930 } 21931 21932 /* 21933 * Function: 21934 * bcmi_esw_mirror_port_dettach 21935 * Purpose: 21936 * clear the mirror per-port configuration. 21937 * Parameters: 21938 * unit - (IN) BCM device number. 21939 * port - local port number 21940 * Returns: 21941 * BCM_E_XXX 21942 */ 21943 21944 int 21945 bcmi_esw_mirror_port_detach (int unit, bcm_port_t port) 21946 { 21947 return _bcmi_esw_mirror_flex_port_init(unit,port,FALSE); 21948 } 21949 21950 /* 21951 * Function: 21952 * bcm_esw_mirror_mode_set 21953 * Description: 21954 * Enable or disable mirroring. Will wait for bcm_esw_mirror_to_set 21955 * to be called to actually do the enable if needed. 21956 * Parameters: 21957 * unit - (IN) BCM device number 21958 * mode - (IN) One of BCM_MIRROR_(DISABLE|L2|L2_L3) 21959 * Returns: 21960 * BCM_E_XXX 21961 */ 21962 int 21963 bcm_esw_mirror_mode_set(int unit, int mode) 21964 { 21965 int rv = BCM_E_UNAVAIL; /* Operation return status. */ 21966 21967 /* Initialization check */ 21968 if (0 == MIRROR_INIT(unit)) { 21969 return (BCM_E_INIT); 21970 } 21971 21972 /* Input parameters check. */ 21973 if ((BCM_MIRROR_L2 != mode) && 21974 (BCM_MIRROR_L2_L3 != mode) && 21975 (BCM_MIRROR_DISABLE != mode)) { 21976 return (BCM_E_PARAM); 21977 } 21978 21979 if (MIRROR_MTP_METHOD_IS_DIRECTED_FLEXIBLE(unit)) { 21980 /* Not supported for flexible MTP mode */ 21981 return (BCM_E_CONFIG); 21982 } 21983 21984 MIRROR_LOCK(unit); 21985 rv = _bcm_esw_mirror_mode_set(unit, mode); 21986 MIRROR_UNLOCK(unit); 21987 return (rv); 21988 } 21989 21990 /* 21991 * Function: 21992 * bcm_esw_mirror_mode_get 21993 * Description: 21994 * Get mirror mode. (L2/L2_L3/DISABLED). 21995 * Parameters: 21996 * unit - BCM device number 21997 * mode - (OUT) One of BCM_MIRROR_(DISABLE|L2|L2_L3) 21998 * Returns: 21999 * BCM_E_XXX 22000 */ 22001 int 22002 bcm_esw_mirror_mode_get(int unit, int *mode) 22003 { 22004 /* Initialization check */ 22005 if (0 == MIRROR_INIT(unit)) { 22006 return BCM_E_INIT; 22007 } 22008 22009 /* Input parameters check. */ 22010 if (NULL == mode) { 22011 return BCM_E_PARAM; 22012 } 22013 MIRROR_LOCK(unit); 22014 *mode = MIRROR_CONFIG_MODE(unit); 22015 MIRROR_UNLOCK(unit); 22016 22017 return (BCM_E_NONE); 22018 } 22019 22020 /* 22021 * Function: 22022 * bcm_esw_mirror_to_set 22023 * Description: 22024 * Set the mirror-to port for all mirroring, enabling mirroring 22025 * if a mode has previously been set. 22026 * Parameters: 22027 * unit - (IN) BCM device number 22028 * port - (IN) The port to mirror all ingress/egress selections to 22029 * Returns: 22030 * BCM_E_XXX 22031 * Notes: 22032 * When mirroring to a remote unit, the mirror-to port 22033 * should be the appropriate stack port on the local unit. 22034 * This will return BCM_E_CONFIG if the unit is configured for, 22035 * or only supports directed mirroring. 22036 */ 22037 int 22038 bcm_esw_mirror_to_set(int unit, bcm_port_t port) 22039 { 22040 bcm_mirror_destination_t mirror_dest; /* Destination port/trunk. */ 22041 int rv; /* Operation return status. */ 22042 int mod_out, port_out; /* Module and port for mapping */ 22043 bcm_gport_t gport; /* Local gport operations */ 22044 22045 /* Initialization check. */ 22046 if (0 == MIRROR_INIT(unit)) { 22047 return BCM_E_INIT; 22048 } 22049 22050 gport = port; 22051 if (BCM_GPORT_IS_SET(gport)) { 22052 BCM_IF_ERROR_RETURN(bcm_esw_port_local_get(unit, gport, &port)); 22053 } 22054 /* Input parameters check. */ 22055 if (!SOC_PORT_VALID(unit, port)) { 22056 return (BCM_E_PORT); 22057 } 22058 22059 bcm_mirror_destination_t_init(&mirror_dest); 22060 22061 if (!MIRROR_MTP_METHOD_IS_NON_DIRECTED(unit)) { 22062 return (BCM_E_CONFIG); 22063 } 22064 22065 if (BCM_GPORT_IS_SET(gport)) { 22066 mirror_dest.gport = gport; 22067 } else { 22068 BCM_IF_ERROR_RETURN(bcm_esw_port_gport_get(unit, port, &gport)); 22069 BCM_IF_ERROR_RETURN( 22070 _bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET, 22071 SOC_GPORT_MODPORT_MODID_GET(gport), 22072 SOC_GPORT_MODPORT_PORT_GET(gport), 22073 &mod_out, &port_out)); 22074 BCM_IF_ERROR_RETURN( 22075 _bcm_mirror_gport_construct(unit, port_out, mod_out, 0, 22076 &(mirror_dest.gport))); 22077 } 22078 22079 /* Create traditional mirror destination. */ 22080 BCM_GPORT_MIRROR_SET(mirror_dest.mirror_dest_id, 0); 22081 mirror_dest.flags = BCM_MIRROR_DEST_WITH_ID | BCM_MIRROR_DEST_REPLACE; 22082 22083 MIRROR_LOCK(unit); 22084 22085 rv = bcm_esw_mirror_destination_create(unit, &mirror_dest); 22086 if (BCM_FAILURE(rv)) { 22087 MIRROR_UNLOCK(unit); 22088 return (rv); 22089 } 22090 22091 if (soc_feature(unit, soc_feature_mirror_flexible)) { 22092 /* Ingress */ 22093 MIRROR_CONFIG_SHARED_MTP_DEST(unit, 0) = mirror_dest.mirror_dest_id; 22094 MIRROR_CONFIG_SHARED_MTP_REF_COUNT(unit, 0) = 1; 22095 /* Egress */ 22096 MIRROR_CONFIG_SHARED_MTP_DEST(unit, 22097 BCM_MIRROR_MTP_FLEX_EGRESS_D15_INDEX) = 22098 mirror_dest.mirror_dest_id; 22099 MIRROR_CONFIG_SHARED_MTP_REF_COUNT(unit, 22100 BCM_MIRROR_MTP_FLEX_EGRESS_D15_INDEX) = 1; 22101 } else { 22102 MIRROR_CONFIG_ING_MTP_DEST(unit, 0) = mirror_dest.mirror_dest_id; 22103 MIRROR_CONFIG_ING_MTP_REF_COUNT(unit, 0) = 1; 22104 } 22105 22106 #ifdef BCM_XGS3_SWITCH_SUPPORT 22107 if (SOC_IS_XGS3_SWITCH(unit)) { 22108 /* Ingress & Egress configuration is identical. */ 22109 if (soc_feature(unit, soc_feature_mirror_flexible)) { 22110 /* For non-directed flexible mirroring, we use MTP 0 for 22111 * the ingress and MTP 2 for the egress. */ 22112 rv = _bcm_xgs3_mtp_init(unit, 0, BCM_MIRROR_PORT_INGRESS); 22113 rv = _bcm_xgs3_mtp_init(unit, 22114 BCM_MIRROR_MTP_FLEX_EGRESS_D15_INDEX, 22115 BCM_MIRROR_PORT_EGRESS); 22116 } else { 22117 MIRROR_CONFIG_EGR_MTP(unit, 0) = MIRROR_CONFIG_ING_MTP(unit, 0); 22118 /* Write MTP registers */ 22119 rv = _bcm_xgs3_mtp_init(unit, 0, (BCM_MIRROR_PORT_EGRESS | 22120 BCM_MIRROR_PORT_INGRESS)); 22121 } 22122 if (BCM_FAILURE(rv)) { 22123 MIRROR_UNLOCK(unit); 22124 return (rv); 22125 } 22126 } 22127 #endif /* BCM_XGS3_SWITCH_SUPPORT */ 22128 rv = bcm_esw_mirror_mode_set(unit, MIRROR_CONFIG_MODE(unit)); 22129 MIRROR_UNLOCK(unit); 22130 return (rv); 22131 } 22132 22133 /* 22134 * Function: 22135 * bcm_esw_mirror_to_get 22136 * Description: 22137 * Get the mirror-to port for all mirroring 22138 * Parameters: 22139 * unit - (IN) BCM device number 22140 * port - (OUT) The port to mirror all ingress/egress selections to 22141 * Returns: 22142 * BCM_E_XXX 22143 */ 22144 int 22145 bcm_esw_mirror_to_get(int unit, bcm_port_t *port) 22146 { 22147 uint32 flags; /* Mirror destination flags. */ 22148 int rv; /* Operation return status */ 22149 int isGport; /* Indicator on which format to return port */ 22150 bcm_module_t mymodid, modid; /* module id to construct a gport */ 22151 bcm_gport_t gport = BCM_GPORT_INVALID; 22152 int mod_out, port_out; /* To do a modmap mapping */ 22153 int mirror_cnt = 0; 22154 _bcm_mtp_config_p mtp_cfg; 22155 22156 /* Initialization check. */ 22157 if (0 == MIRROR_INIT(unit)) { 22158 return BCM_E_INIT; 22159 } 22160 22161 /* Input parameters check. */ 22162 if (NULL == port) { 22163 return (BCM_E_PARAM); 22164 } 22165 22166 flags = 0; 22167 BCM_IF_ERROR_RETURN( 22168 bcm_esw_stk_my_modid_get(unit, &mymodid)); 22169 22170 MIRROR_LOCK(unit); 22171 22172 if (soc_feature(unit, soc_feature_mirror_flexible)) { 22173 mtp_cfg = &MIRROR_CONFIG_SHARED_MTP(unit, 0); 22174 if (mtp_cfg != NULL) { 22175 mirror_cnt = MIRROR_CONFIG_SHARED_MTP_REF_COUNT(unit, 0); 22176 gport = MIRROR_CONFIG_SHARED_MTP_DEST(unit, 0); 22177 } 22178 } else { 22179 mtp_cfg = &MIRROR_CONFIG_ING_MTP(unit, 0); 22180 if (mtp_cfg != NULL) { 22181 mirror_cnt = MIRROR_CONFIG_ING_MTP_REF_COUNT(unit, 0); 22182 gport = MIRROR_CONFIG_ING_MTP_DEST(unit, 0); 22183 } 22184 } 22185 22186 if (mirror_cnt) { 22187 rv = _bcm_mirror_destination_gport_parse(unit, gport ,&modid, 22188 port, &flags); 22189 } else { 22190 *port = -1; 22191 modid = mymodid; 22192 rv = BCM_E_NONE; 22193 } 22194 MIRROR_UNLOCK(unit); 22195 if (BCM_FAILURE(rv)) { 22196 return (rv); 22197 } 22198 22199 if (flags & BCM_MIRROR_PORT_DEST_TRUNK) { 22200 return (BCM_E_CONFIG); 22201 } 22202 22203 BCM_IF_ERROR_RETURN 22204 (bcm_esw_switch_control_get(unit, bcmSwitchUseGport, &isGport)); 22205 if (isGport) { 22206 BCM_IF_ERROR_RETURN 22207 (_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET, mymodid, *port, 22208 &mod_out, &port_out)); 22209 BCM_IF_ERROR_RETURN 22210 (_bcm_mirror_gport_construct(unit, port_out, mod_out, 22211 flags, port)); 22212 } else if (*port != -1) { 22213 BCM_GPORT_MODPORT_SET(gport, modid, *port); 22214 BCM_IF_ERROR_RETURN 22215 (bcm_esw_port_local_get(unit, gport, port)); 22216 } 22217 22218 return (BCM_E_NONE); 22219 } 22220 22221 /* 22222 * Function: 22223 * bcm_esw_mirror_ingress_set 22224 * Description: 22225 * Enable or disable mirroring per ingress 22226 * Parameters: 22227 * unit - (IN) BCM device number 22228 * port - (IN) The port to affect 22229 * enable - (IN) Boolean value for on/off 22230 * Returns: 22231 * BCM_E_XXX 22232 * Notes: 22233 * Mirroring must also be globally enabled. 22234 */ 22235 int 22236 bcm_esw_mirror_ingress_set(int unit, bcm_port_t port, int enable) 22237 { 22238 /* Initialization check. */ 22239 if (0 == MIRROR_INIT(unit)) { 22240 return BCM_E_INIT; 22241 } 22242 if (BCM_GPORT_IS_SET(port)) { 22243 BCM_IF_ERROR_RETURN(bcm_esw_port_local_get(unit, port, &port)); 22244 } 22245 22246 /* Input parameters check. */ 22247 if (!SOC_PORT_VALID(unit, port)) { 22248 return (BCM_E_PORT); 22249 } 22250 22251 if (IS_CPU_PORT(unit, port) && 22252 !soc_feature(unit, soc_feature_cpuport_mirror)) { 22253 return (BCM_E_PORT); 22254 } 22255 22256 /* Set ingress mirroring enable in port table. */ 22257 return _bcm_esw_mirror_ingress_set(unit, port, 22258 ((enable) ? BCM_MIRROR_MTP_ONE : (0))); 22259 22260 } 22261 22262 /* 22263 * Function: 22264 * bcm_esw_mirror_ingress_get 22265 * Description: 22266 * Get the mirroring per ingress enabled/disabled status 22267 * Parameters: 22268 * unit - (IN) BCM device number 22269 * port - (IN) The port to check 22270 * enable - (OUT) Place to store boolean return value for on/off 22271 * Returns: 22272 * BCM_E_XXX 22273 */ 22274 int 22275 bcm_esw_mirror_ingress_get(int unit, bcm_port_t port, int *enable) 22276 { 22277 /* Initialization check. */ 22278 if (0 == MIRROR_INIT(unit)) { 22279 return BCM_E_INIT; 22280 } 22281 22282 /* Input parameters check. */ 22283 if (NULL == enable) { 22284 return (BCM_E_PARAM); 22285 } 22286 22287 if (BCM_GPORT_IS_SET(port)) { 22288 BCM_IF_ERROR_RETURN(bcm_esw_port_local_get(unit, port, &port)); 22289 } 22290 22291 if (!SOC_PORT_VALID(unit, port)) { 22292 return (BCM_E_PORT); 22293 } 22294 22295 if (IS_CPU_PORT(unit, port) && 22296 !soc_feature(unit, soc_feature_cpuport_mirror)) { 22297 return (BCM_E_PORT); 22298 } 22299 22300 /* Get ingress mirroring enable from port table. */ 22301 return _bcm_esw_mirror_ingress_get(unit, port, enable); 22302 } 22303 22304 /* 22305 * Function: 22306 * bcm_esw_mirror_egress_set 22307 * Description: 22308 * Enable or disable mirroring per egress 22309 * Parameters: 22310 * unit - (IN) BCM device number 22311 * port - (IN) The port to affect 22312 * enable - (IN) Boolean value for on/off 22313 * Returns: 22314 * BCM_E_XXX 22315 * Notes: 22316 * Mirroring must also be globally enabled. 22317 */ 22318 int 22319 bcm_esw_mirror_egress_set(int unit, bcm_port_t port, int enable) 22320 { 22321 22322 int rv; 22323 22324 /* Initialization check. */ 22325 if (0 == MIRROR_INIT(unit)) { 22326 return BCM_E_INIT; 22327 } 22328 22329 if (BCM_GPORT_IS_SET(port)) { 22330 BCM_IF_ERROR_RETURN(bcm_esw_port_local_get(unit, port, &port)); 22331 } 22332 22333 /* Input parameters check. */ 22334 if (!SOC_PORT_VALID(unit, port)) { 22335 return BCM_E_PORT; 22336 } 22337 22338 if (IS_CPU_PORT(unit, port) && 22339 !soc_feature(unit, soc_feature_cpuport_mirror)) { 22340 return BCM_E_PORT; 22341 } 22342 22343 MIRROR_LOCK(unit); 22344 22345 #ifdef BCM_TRIUMPH2_SUPPORT 22346 if (soc_feature(unit, soc_feature_mirror_flexible)) { 22347 /* Enable third MTP for egress since this is for single MTP mode */ 22348 if (MIRROR_MTP_METHOD_IS_DIRECTED_FLEXIBLE(unit)) { 22349 /* Update MTP_MODE */ 22350 MIRROR_CONFIG_MTP_MODE_BMP(unit) |= 22351 BCM_MIRROR_MTP_FLEX_EGRESS_D15; 22352 22353 rv = _bcm_tr2_mirror_mtp_slot_update(unit); 22354 if (BCM_FAILURE(rv)) { 22355 MIRROR_UNLOCK(unit); 22356 return (rv); 22357 } 22358 } else { 22359 MIRROR_CONFIG_SHARED_MTP(unit, 22360 BCM_MIRROR_MTP_FLEX_EGRESS_D15_INDEX).egress = TRUE; 22361 } 22362 rv = _bcm_esw_mirror_egress_set(unit, port, 22363 (enable) ? BCM_MIRROR_MTP_FLEX_EGRESS_D15 : (0)); 22364 } else 22365 #endif /* BCM_TRIUMPH2_SUPPORT */ 22366 { 22367 rv = _bcm_esw_mirror_egress_set(unit, port, 22368 (enable) ? BCM_MIRROR_MTP_ONE : (0)); 22369 } 22370 22371 MIRROR_UNLOCK(unit); 22372 return (rv); 22373 } 22374 22375 /* 22376 * Function: 22377 * bcm_esw_mirror_egress_get 22378 * Description: 22379 * Get the mirroring per egress enabled/disabled status 22380 * Parameters: 22381 * unit - (IN) BCM device number 22382 * port - (IN) The port to check 22383 * enable - (OUT) Place to store boolean return value for on/off 22384 * Returns: 22385 * BCM_E_XXX 22386 */ 22387 int 22388 bcm_esw_mirror_egress_get(int unit, bcm_port_t port, int *enable) 22389 { 22390 int rv; 22391 22392 /* Initialization check. */ 22393 if (0 == MIRROR_INIT(unit)) { 22394 return BCM_E_INIT; 22395 } 22396 22397 /* Input parameters check. */ 22398 if (NULL == enable) { 22399 return (BCM_E_PARAM); 22400 } 22401 22402 if (BCM_GPORT_IS_SET(port)) { 22403 BCM_IF_ERROR_RETURN(bcm_esw_port_local_get(unit, port, &port)); 22404 } 22405 22406 if (!SOC_PORT_VALID(unit, port)) { 22407 return (BCM_E_PORT); 22408 } 22409 22410 if (IS_CPU_PORT(unit, port) && 22411 !soc_feature(unit, soc_feature_cpuport_mirror)) { 22412 return (BCM_E_PORT); 22413 } 22414 22415 MIRROR_LOCK(unit); 22416 rv = _bcm_esw_mirror_egress_get(unit, port, enable); 22417 MIRROR_UNLOCK(unit); 22418 *enable = *enable ? 1 : 0; 22419 return (rv); 22420 } 22421 22422 /* 22423 * Function: 22424 * bcm_esw_mirror_to_pbmp_set 22425 * Description: 22426 * Set the mirror-to port bitmap for mirroring on a given port. 22427 * Parameters: 22428 * unit - (IN) BCM device number 22429 * port - (IN) The port to affect 22430 * pbmp - (IN) The port bitmap of mirrored to ports for this port. 22431 * Returns: 22432 * BCM_E_XXX 22433 * Notes: 22434 * This API interface is only supported on XGS fabric devices and 22435 * production versions of XGS3 switch devices. For XGS3 devices 22436 * this function is normally only used when the XGS3 device is 22437 * stacked in a ring configuration with BCM567x fabric devices. 22438 */ 22439 int 22440 bcm_esw_mirror_to_pbmp_set(int unit, bcm_port_t port, pbmp_t pbmp) 22441 { 22442 #if defined(BCM_KATANA2_SUPPORT) 22443 int min_subport = SOC_INFO(unit).pp_port_index_min; 22444 #endif 22445 /* Initialization check. */ 22446 if (0 == MIRROR_INIT(unit)) { 22447 return BCM_E_INIT; 22448 } 22449 22450 #ifdef BCM_TOMAHAWK3_SUPPORT 22451 /* Stacking is not supported on TH3 */ 22452 if (SOC_IS_TOMAHAWK3(unit)) { 22453 return (BCM_E_UNAVAIL); 22454 } 22455 #endif /* BCM_TOMAHAWK3_SUPPORT */ 22456 22457 if (BCM_GPORT_IS_SET(port)) { 22458 BCM_IF_ERROR_RETURN(bcm_esw_port_local_get(unit, port, &port)); 22459 } 22460 /* Input parameters check. */ 22461 #if defined(BCM_KATANA2_SUPPORT) 22462 if ((soc_feature(unit, soc_feature_linkphy_coe) || 22463 soc_feature(unit, soc_feature_subtag_coe)) && 22464 (port >= min_subport)) { 22465 } else 22466 #endif 22467 if (!IS_PORT(unit, port) || !SOC_PORT_VALID(unit, port)) { 22468 return BCM_E_PORT; 22469 } 22470 22471 #if defined(BCM_HERCULES_SUPPORT) 22472 if (SOC_IS_HERCULES(unit)) { 22473 MIRROR_CONFIG_MODE(unit) = BCM_MIRROR_L2; 22474 return WRITE_ING_MIRTOBMAPr(unit, port, SOC_PBMP_WORD_GET(pbmp, 0)); 22475 } 22476 #endif /* BCM_HERCULES_SUPPORT */ 22477 #if defined(BCM_XGS3_SWITCH_SUPPORT) 22478 if (soc_feature(unit, soc_feature_egr_mirror_path)) { 22479 int mport; 22480 22481 /* Both ingress and egress ports must be stack ports */ 22482 if (!IS_ST_PORT(unit, port)) { 22483 return (BCM_E_PORT); 22484 } 22485 22486 PBMP_ITER(pbmp, mport) { 22487 if (!IS_ST_PORT(unit, mport)) { 22488 return (BCM_E_PORT); 22489 } 22490 } 22491 22492 #ifdef BCM_TRIDENT2_SUPPORT 22493 if (SOC_IS_TD2_TT2(unit)) { 22494 imirror_bitmap_entry_t entry; 22495 int egr_port; 22496 22497 sal_memset(&entry, 0, sizeof(entry)); 22498 22499 PBMP_ITER(pbmp, egr_port) { 22500 soc_mem_field32_set(unit, IMIRROR_BITMAPm, &entry, 22501 EGRESS_PORTf, egr_port); 22502 soc_mem_field32_set(unit, IMIRROR_BITMAPm, &entry, ENABLEf, 22503 1); 22504 break; 22505 } 22506 BCM_IF_ERROR_RETURN 22507 (soc_mem_write(unit, IMIRROR_BITMAPm, MEM_BLOCK_ANY, port, 22508 &entry)); 22509 if (IS_CPU_PORT(unit, port) && SOC_INFO(unit).cpu_hg_index != -1) { 22510 BCM_IF_ERROR_RETURN 22511 (soc_mem_write(unit, IMIRROR_BITMAPm, MEM_BLOCK_ANY, 22512 SOC_INFO(unit).cpu_hg_index, &entry)); 22513 } 22514 return BCM_E_NONE; 22515 } 22516 #endif /* BCM_TRIDENT2_SUPPORT */ 22517 22518 #ifdef BCM_TRIDENT_SUPPORT 22519 if (soc_feature(unit, soc_feature_mirror_control_mem)) { 22520 imirror_bitmap_entry_t entry; 22521 soc_mem_pbmp_field_set(unit, IMIRROR_BITMAPm, &entry, BITMAPf, 22522 &pbmp); 22523 return (WRITE_IMIRROR_BITMAPm(unit, MEM_BLOCK_ANY, port, &entry)); 22524 } else 22525 #endif /* BCM_TRIDENT_SUPPORT */ 22526 #ifdef BCM_TRIUMPH2_SUPPORT 22527 22528 #ifdef BCM_GREYHOUND2_SUPPORT 22529 if(soc_feature (unit, soc_feature_high_portcount_register)){ 22530 uint64 mirror64, val64; 22531 BCM_IF_ERROR_RETURN(READ_IMIRROR_BITMAP_LOr(unit, port, &mirror64)); 22532 COMPILER_64_SET(val64, SOC_PBMP_WORD_GET(pbmp, 1), 22533 SOC_PBMP_WORD_GET(pbmp, 0)); 22534 soc_reg64_field_set(unit, IMIRROR_BITMAP_LOr, &mirror64, 22535 BITMAPf, val64); 22536 BCM_IF_ERROR_RETURN(WRITE_IMIRROR_BITMAP_LOr(unit, port, mirror64)); 22537 22538 COMPILER_64_ZERO(mirror64); 22539 COMPILER_64_ZERO(val64); 22540 BCM_IF_ERROR_RETURN(READ_IMIRROR_BITMAP_HIr(unit, port, &mirror64)); 22541 COMPILER_64_SET(val64, SOC_PBMP_WORD_GET(pbmp, 3), 22542 SOC_PBMP_WORD_GET(pbmp, 2)); 22543 soc_reg64_field_set(unit, IMIRROR_BITMAP_HIr, &mirror64, 22544 BITMAPf, val64); 22545 BCM_IF_ERROR_RETURN(WRITE_IMIRROR_BITMAP_HIr(unit, port, mirror64)); 22546 return (BCM_E_NONE); 22547 }else 22548 #endif /*BCM_GREYHOUND2_SUPPORT*/ 22549 if (SOC_REG_IS_VALID(unit, IMIRROR_BITMAP_64r)) { 22550 uint32 values[2]; 22551 soc_field_t fields[] = {BITMAP_LOf, BITMAP_HIf}; 22552 22553 values[0] = SOC_PBMP_WORD_GET(pbmp, 0); 22554 values[1] = SOC_PBMP_WORD_GET(pbmp, 1); 22555 return soc_reg_fields32_modify(unit, IMIRROR_BITMAP_64r, port, 22556 2, fields, values); 22557 } else 22558 #endif /* BCM_TRIUMPH2_SUPPORT */ 22559 { 22560 uint32 mirbmap; 22561 22562 mirbmap = SOC_PBMP_WORD_GET(pbmp, 0); 22563 if (SOC_IS_FBX(unit)) { 22564 mirbmap >>= SOC_HG_OFFSET(unit); 22565 } 22566 return WRITE_IMIRROR_BITMAPr(unit, port, mirbmap); 22567 } 22568 } 22569 #endif /* BCM_XGS3_SWITCH_SUPPORT */ 22570 return (BCM_E_UNAVAIL); 22571 } 22572 22573 /* 22574 * Function: 22575 * bcm_esw_mirror_to_pbmp_get 22576 * Description: 22577 * Get the mirror-to port bitmap for mirroring on the 22578 * specified port. 22579 * Parameters: 22580 * unit - (IN) BCM device number 22581 * port - (IN) The port to mirror all ingress/egress selections to 22582 * pbmp - (OUT) The port bitmap of mirror-to ports for this port. 22583 * Returns: 22584 * BCM_E_XXX 22585 */ 22586 int 22587 bcm_esw_mirror_to_pbmp_get(int unit, bcm_port_t port, pbmp_t *pbmp) 22588 { 22589 #if defined(BCM_KATANA2_SUPPORT) 22590 int min_subport = SOC_INFO(unit).pp_port_index_min; 22591 #endif 22592 /* Initialization check. */ 22593 if (0 == MIRROR_INIT(unit)) { 22594 return BCM_E_INIT; 22595 } 22596 22597 #ifdef BCM_TOMAHAWK3_SUPPORT 22598 /* Stacking is not supported, and IMIRROR_BITMAPm is 22599 * not implemented on TH3 22600 */ 22601 if (SOC_IS_TOMAHAWK3(unit)) { 22602 SOC_PBMP_CLEAR(*pbmp); 22603 /* IMIRROR_BITMAPm is not implemented */ 22604 return (BCM_E_UNAVAIL); 22605 } 22606 #endif /* BCM_TOMAHAWK3_SUPPORT */ 22607 22608 if (BCM_GPORT_IS_SET(port)) { 22609 BCM_IF_ERROR_RETURN(bcm_esw_port_local_get(unit, port, &port)); 22610 } 22611 22612 /* Input parameters check. */ 22613 #if defined(BCM_KATANA2_SUPPORT) 22614 if ((soc_feature(unit, soc_feature_linkphy_coe) || 22615 soc_feature(unit, soc_feature_subtag_coe)) && 22616 (port >= min_subport)) { 22617 } else 22618 #endif 22619 if (!IS_PORT(unit, port) || !SOC_PORT_VALID(unit, port)) { 22620 return BCM_E_PORT; 22621 } 22622 22623 #if defined(BCM_HERCULES_SUPPORT) 22624 if (SOC_IS_HERCULES(unit)) { 22625 int rv; 22626 uint32 mirbmap; 22627 22628 rv = READ_ING_MIRTOBMAPr(unit, port, &mirbmap); 22629 SOC_PBMP_CLEAR(*pbmp); 22630 SOC_PBMP_WORD_SET(*pbmp, 0, mirbmap); 22631 return rv; 22632 } 22633 #endif /* BCM_HERCULES_SUPPORT */ 22634 22635 #ifdef BCM_XGS3_SWITCH_SUPPORT 22636 if (soc_feature(unit, soc_feature_egr_mirror_path)) { 22637 int rv; 22638 22639 #ifdef BCM_TRIDENT2_SUPPORT 22640 if (SOC_IS_TD2_TT2(unit)) { 22641 imirror_bitmap_entry_t entry; 22642 int egr_port, tgid; 22643 int member_count; 22644 bcm_trunk_member_t *member_array = NULL; 22645 bcm_module_t mod_out; 22646 bcm_port_t port_out; 22647 bcm_trunk_t tgid_out; 22648 int id_out; 22649 int idx; 22650 int is_local_modid; 22651 22652 BCM_IF_ERROR_RETURN 22653 (READ_IMIRROR_BITMAPm(unit, MEM_BLOCK_ANY, port, &entry)); 22654 BCM_PBMP_CLEAR(*pbmp); 22655 if (!soc_mem_field32_get(unit, IMIRROR_BITMAPm, &entry, ENABLEf)) { 22656 return BCM_E_NONE; 22657 } 22658 if (soc_mem_field32_get(unit, IMIRROR_BITMAPm, &entry, ISTRUNKf)) { 22659 tgid = soc_mem_field32_get(unit, IMIRROR_BITMAPm, &entry, 22660 HG_TRUNK_IDf); 22661 22662 /* Get trunk member port/module pairs. */ 22663 BCM_IF_ERROR_RETURN 22664 (bcm_esw_trunk_get(unit, tgid, NULL, 0, NULL, 22665 &member_count)); 22666 if (member_count > 0) { 22667 member_array = 22668 sal_alloc(sizeof(bcm_trunk_member_t) * member_count, 22669 "trunk member array"); 22670 if (NULL == member_array) { 22671 return BCM_E_MEMORY; 22672 } 22673 rv = bcm_esw_trunk_get(unit, tgid, NULL, member_count, 22674 member_array, &member_count); 22675 if (BCM_FAILURE(rv)) { 22676 sal_free(member_array); 22677 return rv; 22678 } 22679 } 22680 22681 /* Fill pbmp with trunk members from other modules . */ 22682 for (idx = 0; idx < member_count; idx++) { 22683 rv = _bcm_esw_gport_resolve(unit, member_array[idx].gport, 22684 &mod_out, &port_out, 22685 &tgid_out, &id_out); 22686 if (BCM_FAILURE(rv) || -1 != tgid_out || -1 != id_out) { 22687 sal_free(member_array); 22688 return rv; 22689 } 22690 rv = _bcm_esw_modid_is_local(unit, mod_out, 22691 &is_local_modid); 22692 if (BCM_FAILURE(rv)) { 22693 sal_free(member_array); 22694 return rv; 22695 } 22696 if (!is_local_modid) { 22697 rv = bcm_esw_stk_modport_get(unit, mod_out, &egr_port); 22698 if (BCM_FAILURE(rv)) { 22699 sal_free(member_array); 22700 return rv; 22701 } 22702 BCM_PBMP_PORT_ADD(*pbmp, egr_port); 22703 } 22704 } 22705 sal_free(member_array); 22706 } else { 22707 egr_port = soc_mem_field32_get(unit, IMIRROR_BITMAPm, &entry, 22708 EGRESS_PORTf); 22709 BCM_PBMP_PORT_SET(*pbmp, egr_port); 22710 } 22711 return BCM_E_NONE; 22712 } 22713 #endif /* BCM_TRIDENT2_SUPPORT */ 22714 22715 #ifdef BCM_TRIDENT_SUPPORT 22716 if (soc_feature(unit, soc_feature_mirror_control_mem)) { 22717 imirror_bitmap_entry_t entry; 22718 BCM_IF_ERROR_RETURN 22719 (READ_IMIRROR_BITMAPm(unit, MEM_BLOCK_ANY, port, &entry)); 22720 soc_mem_pbmp_field_get(unit, IMIRROR_BITMAPm, &entry, BITMAPf, 22721 pbmp); 22722 rv = BCM_E_NONE; 22723 } else 22724 #endif /* BCM_TRIDENT_SUPPORT */ 22725 #ifdef BCM_TRIUMPH2_SUPPORT 22726 22727 #ifdef BCM_GREYHOUND2_SUPPORT 22728 if (soc_feature (unit, soc_feature_high_portcount_register)){ 22729 uint64 mirror64, val64; 22730 BCM_IF_ERROR_RETURN(soc_reg_get(unit, IMIRROR_BITMAP_LOr, port, 0, &mirror64)); 22731 SOC_PBMP_CLEAR(*pbmp); 22732 val64 = soc_reg64_field_get(unit, IMIRROR_BITMAP_LOr, mirror64, BITMAPf); 22733 SOC_PBMP_WORD_SET(*pbmp, 0, COMPILER_64_LO(val64)); 22734 SOC_PBMP_WORD_SET(*pbmp, 1, COMPILER_64_HI(val64)); 22735 22736 COMPILER_64_ZERO(mirror64); 22737 COMPILER_64_ZERO(val64); 22738 BCM_IF_ERROR_RETURN(soc_reg_get(unit, IMIRROR_BITMAP_HIr, port, 0, &mirror64)); 22739 val64 = soc_reg64_field_get(unit, IMIRROR_BITMAP_HIr, mirror64, BITMAPf); 22740 SOC_PBMP_WORD_SET(*pbmp, 2, COMPILER_64_LO(val64)); 22741 SOC_PBMP_WORD_SET(*pbmp, 3, COMPILER_64_HI(val64)); 22742 rv = BCM_E_NONE; 22743 }else 22744 #endif /*BCM_GREYHOUND2_SUPPORT*/ 22745 if (SOC_REG_IS_VALID(unit, IMIRROR_BITMAP_64r)) { 22746 uint64 mirbmap64; 22747 rv = READ_IMIRROR_BITMAP_64r(unit, port, &mirbmap64); 22748 SOC_PBMP_CLEAR(*pbmp); 22749 SOC_PBMP_WORD_SET(*pbmp, 0, 22750 soc_reg64_field32_get(unit, IMIRROR_BITMAP_64r, 22751 mirbmap64, BITMAP_LOf)); 22752 SOC_PBMP_WORD_SET(*pbmp, 1, 22753 soc_reg64_field32_get(unit, IMIRROR_BITMAP_64r, 22754 mirbmap64, BITMAP_HIf)); 22755 } else 22756 #endif /* BCM_TRIUMPH2_SUPPORT */ 22757 { 22758 uint32 mirbmap; 22759 22760 rv = READ_IMIRROR_BITMAPr(unit, port, &mirbmap); 22761 if (SOC_IS_FBX(unit)) { 22762 mirbmap <<= SOC_HG_OFFSET(unit); 22763 } 22764 SOC_PBMP_CLEAR(*pbmp); 22765 SOC_PBMP_WORD_SET(*pbmp, 0, mirbmap); 22766 } 22767 return rv; 22768 } 22769 #endif 22770 return (BCM_E_UNAVAIL); 22771 } 22772 22773 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_GREYHOUND_SUPPORT) 22774 /* 22775 * Function: 22776 * _bcm_trident_mirror_vlan_set 22777 * Description: 22778 * Set VLAN for egressing mirrored packets on a port (RSPAN) 22779 * This will support the legacy mode where RSPAN is a per-egress-port 22780 * property. 22781 * Parameters: 22782 * unit - (IN) Bcm device number. 22783 * port - (IN) Mirror-to port to set (-1 for all ports). 22784 * tpid - (IN) Tag protocol id (0 to disable). 22785 * vlan - (IN) Virtual lan number (0 to disable). 22786 * Returns: 22787 * BCM_E_XXX 22788 */ 22789 STATIC int 22790 _bcm_trident_mirror_vlan_set(int unit, bcm_port_t port, 22791 uint16 tpid, uint16 vlan) 22792 { 22793 int rv = BCM_E_NONE; 22794 uint32 profile_index, old_profile_index = 0; 22795 uint32 hw_buffer; 22796 egr_mirror_encap_control_entry_t control_entry; 22797 egr_mirror_encap_data_1_entry_t data_1_entry; 22798 egr_mirror_encap_data_2_entry_t data_2_entry; 22799 #ifdef BCM_TRIDENT_SUPPORT 22800 egr_port_entry_t egr_port_entry; 22801 #endif /* BCM_TRIDENT_SUPPORT */ 22802 #ifdef BCM_GREYHOUND_SUPPORT 22803 uint64 reg_val; 22804 #endif /* BCM_GREYHOUND_SUPPORT */ 22805 void *entries[EGR_MIRROR_ENCAP_ENTRIES_NUM]; 22806 22807 hw_buffer = (uint32)(tpid << 16) | vlan; 22808 22809 if (0 != hw_buffer) { 22810 sal_memset(&control_entry, 0, sizeof(control_entry)); 22811 sal_memset(&data_1_entry, 0, sizeof(data_1_entry)); 22812 sal_memset(&data_2_entry, 0, sizeof(data_2_entry)); 22813 22814 entries[0] = &control_entry; 22815 entries[1] = &data_1_entry; 22816 entries[2] = &data_2_entry; 22817 22818 /* Setup Mirror Control Memory */ 22819 soc_EGR_MIRROR_ENCAP_CONTROLm_field32_set(unit, &control_entry, 22820 ENTRY_TYPEf, BCM_TD_MIRROR_ENCAP_TYPE_RSPAN); 22821 22822 /* Program field only if it is valid (For TH3 it is not valid) */ 22823 if (SOC_MEM_FIELD_VALID(unit, EGR_MIRROR_ENCAP_CONTROLm, 22824 RSPAN__ADD_OPTIONAL_HEADERf)) { 22825 soc_EGR_MIRROR_ENCAP_CONTROLm_field32_set(unit, &control_entry, 22826 RSPAN__ADD_OPTIONAL_HEADERf, BCM_TD_MIRROR_HEADER_ONLY); 22827 } 22828 22829 /* Setup Mirror Data 1 Memory */ 22830 soc_EGR_MIRROR_ENCAP_DATA_1m_field32_set(unit, &data_1_entry, 22831 RSPAN__RSPAN_VLAN_TAGf, hw_buffer); 22832 22833 rv = _bcm_egr_mirror_encap_entry_add(unit, entries, &profile_index); 22834 22835 if (BCM_SUCCESS(rv)) { 22836 #ifdef BCM_GREYHOUND_SUPPORT 22837 if (SOC_IS_GREYHOUND(unit) || SOC_IS_HURRICANE3(unit) || 22838 SOC_IS_GREYHOUND2(unit)) { 22839 /* Remove the previous profile index if any */ 22840 rv = READ_EGR_PORT_64r(unit, port, ®_val); 22841 22842 old_profile_index = -1; 22843 if (BCM_SUCCESS(rv) && 22844 (0 != soc_reg64_field32_get(unit, EGR_PORT_64r, reg_val, 22845 MIRROR_ENCAP_ENABLEf))) { 22846 old_profile_index = 22847 soc_reg64_field32_get(unit, EGR_PORT_64r, reg_val, 22848 MIRROR_ENCAP_INDEXf); 22849 } 22850 22851 /* Supply the correct profile index to the egress port */ 22852 soc_reg64_field32_set(unit, EGR_PORT_64r, ®_val, 22853 MIRROR_ENCAP_ENABLEf, 1); 22854 soc_reg64_field32_set(unit, EGR_PORT_64r, ®_val, 22855 MIRROR_ENCAP_INDEXf, profile_index); 22856 rv = WRITE_EGR_PORT_64r(unit, port, reg_val); 22857 } else 22858 #endif /* BCM_GREYHOUND_SUPPORT */ 22859 { 22860 #ifdef BCM_TRIDENT_SUPPORT 22861 /* Remove the previous profile index if any */ 22862 rv = READ_EGR_PORTm(unit, MEM_BLOCK_ANY, port, &egr_port_entry); 22863 22864 old_profile_index = -1; 22865 if (BCM_SUCCESS(rv) && 22866 (0 != soc_EGR_PORTm_field32_get(unit, &egr_port_entry, 22867 MIRROR_ENCAP_ENABLEf))) { 22868 old_profile_index = 22869 soc_EGR_PORTm_field32_get(unit, &egr_port_entry, 22870 MIRROR_ENCAP_INDEXf); 22871 } 22872 22873 /* Supply the correct profile index to the egress port */ 22874 soc_EGR_PORTm_field32_set(unit, &egr_port_entry, 22875 MIRROR_ENCAP_ENABLEf, 1); 22876 soc_EGR_PORTm_field32_set(unit, &egr_port_entry, 22877 MIRROR_ENCAP_INDEXf, profile_index); 22878 rv = WRITE_EGR_PORTm(unit, MEM_BLOCK_ANY, port, &egr_port_entry); 22879 22880 #endif /* BCM_TRIDENT_SUPPORT */ 22881 } 22882 22883 if (BCM_SUCCESS(rv) && (-1 != old_profile_index)) { 22884 rv = _bcm_egr_mirror_encap_entry_delete(unit, 22885 old_profile_index); 22886 } 22887 } 22888 } else { 22889 #ifdef BCM_GREYHOUND_SUPPORT 22890 if (SOC_IS_GREYHOUND(unit) || SOC_IS_HURRICANE3(unit) || 22891 SOC_IS_GREYHOUND2(unit)) { 22892 rv = READ_EGR_PORT_64r(unit, port, ®_val); 22893 22894 if (BCM_SUCCESS(rv) && 22895 (0 != soc_reg64_field32_get(unit, EGR_PORT_64r, reg_val, 22896 MIRROR_ENCAP_ENABLEf))) { 22897 old_profile_index = 22898 soc_reg64_field32_get(unit, EGR_PORT_64r, reg_val, 22899 MIRROR_ENCAP_INDEXf); 22900 soc_reg64_field32_set(unit, EGR_PORT_64r, ®_val, 22901 MIRROR_ENCAP_ENABLEf, 0); 22902 soc_reg64_field32_set(unit, EGR_PORT_64r, ®_val, 22903 MIRROR_ENCAP_INDEXf, 0); 22904 rv = WRITE_EGR_PORT_64r(unit, port, reg_val); 22905 22906 if (BCM_SUCCESS(rv)) { 22907 rv = _bcm_egr_mirror_encap_entry_delete(unit, 22908 old_profile_index); 22909 } 22910 } /* Else do nothing */ 22911 } else 22912 #endif /* BCM_GREYHOUND_SUPPORT */ 22913 { 22914 #ifdef BCM_TRIDENT_SUPPORT 22915 rv = READ_EGR_PORTm(unit, MEM_BLOCK_ANY, port, &egr_port_entry); 22916 22917 if (BCM_SUCCESS(rv) && 22918 (0 != soc_EGR_PORTm_field32_get(unit, &egr_port_entry, 22919 MIRROR_ENCAP_ENABLEf))) { 22920 old_profile_index = 22921 soc_EGR_PORTm_field32_get(unit, &egr_port_entry, 22922 MIRROR_ENCAP_INDEXf); 22923 soc_EGR_PORTm_field32_set(unit, &egr_port_entry, 22924 MIRROR_ENCAP_ENABLEf, 0); 22925 soc_EGR_PORTm_field32_set(unit, &egr_port_entry, 22926 MIRROR_ENCAP_INDEXf, 0); 22927 rv = WRITE_EGR_PORTm(unit, MEM_BLOCK_ANY, port, &egr_port_entry); 22928 22929 if (BCM_SUCCESS(rv)) { 22930 rv = _bcm_egr_mirror_encap_entry_delete(unit, 22931 old_profile_index); 22932 } 22933 } /* Else do nothing */ 22934 #endif /* BCM_TRIDENT_SUPPORT */ 22935 } 22936 } 22937 22938 return rv; 22939 } 22940 22941 /* 22942 * Function: 22943 * _bcm_trident_mirror_vlan_get 22944 * Description: 22945 * Get VLAN for egressing mirrored packets on a port (RSPAN) 22946 * This will support the legacy mode where RSPAN is a per-egress-port 22947 * property. 22948 * Parameters: 22949 * unit - (IN) Bcm device number. 22950 * port - (IN) Mirror-to port to set (-1 for all ports). 22951 * tpid - (OUT) Tag protocol id (0 to disable). 22952 * vlan - (OUT) Virtual lan number (0 to disable). 22953 * Returns: 22954 * BCM_E_XXX 22955 */ 22956 STATIC int 22957 _bcm_trident_mirror_vlan_get(int unit, bcm_port_t port, 22958 uint16 *tpid, uint16 *vlan) 22959 { 22960 uint32 profile_index = 0; 22961 uint32 hw_buffer; 22962 egr_mirror_encap_control_entry_t control_entry; 22963 egr_mirror_encap_data_1_entry_t data_1_entry; 22964 egr_mirror_encap_data_2_entry_t data_2_entry; 22965 #ifdef BCM_TRIDENT_SUPPORT 22966 egr_port_entry_t egr_port_entry; 22967 #endif /* BCM_TRIDENT_SUPPORT */ 22968 #ifdef BCM_GREYHOUND_SUPPORT 22969 uint64 reg_val; 22970 #endif /* BCM_GREYHOUND_SUPPORT */ 22971 void *entries[EGR_MIRROR_ENCAP_ENTRIES_NUM]; 22972 22973 #ifdef BCM_GREYHOUND_SUPPORT 22974 if (SOC_IS_GREYHOUND(unit) || SOC_IS_HURRICANE3(unit) || 22975 SOC_IS_GREYHOUND2(unit)) { 22976 BCM_IF_ERROR_RETURN(READ_EGR_PORT_64r(unit, port, ®_val)); 22977 22978 if (0 == soc_reg64_field32_get(unit, EGR_PORT_64r, reg_val, 22979 MIRROR_ENCAP_ENABLEf)) { 22980 return BCM_E_NOT_FOUND; 22981 } 22982 22983 profile_index = 22984 soc_reg64_field32_get(unit, EGR_PORT_64r, reg_val, 22985 MIRROR_ENCAP_INDEXf); 22986 } else 22987 #endif /* BCM_GREYHOUND_SUPPORT */ 22988 { 22989 #ifdef BCM_TRIDENT_SUPPORT 22990 BCM_IF_ERROR_RETURN 22991 (READ_EGR_PORTm(unit, MEM_BLOCK_ANY, port, &egr_port_entry)); 22992 22993 if (0 == soc_EGR_PORTm_field32_get(unit, &egr_port_entry, 22994 MIRROR_ENCAP_ENABLEf)) { 22995 return BCM_E_NOT_FOUND; 22996 } 22997 22998 profile_index = 22999 soc_EGR_PORTm_field32_get(unit, &egr_port_entry, 23000 MIRROR_ENCAP_INDEXf); 23001 #endif /* BCM_TRIDENT_SUPPORT */ 23002 } 23003 23004 entries[0] = &control_entry; 23005 entries[1] = &data_1_entry; 23006 entries[2] = &data_2_entry; 23007 BCM_IF_ERROR_RETURN 23008 (soc_profile_mem_get(unit, EGR_MIRROR_ENCAP(unit), 23009 profile_index, 1, entries)); 23010 23011 23012 if (soc_EGR_MIRROR_ENCAP_CONTROLm_field32_get(unit, &control_entry, 23013 ENTRY_TYPEf) != BCM_TD_MIRROR_ENCAP_TYPE_RSPAN) { 23014 return BCM_E_CONFIG; 23015 } 23016 23017 /* RSPAN recovery */ 23018 hw_buffer = 23019 soc_EGR_MIRROR_ENCAP_DATA_1m_field32_get(unit, &data_1_entry, 23020 RSPAN__RSPAN_VLAN_TAGf); 23021 23022 *vlan = (bcm_vlan_t) (hw_buffer & 0xffff); 23023 *tpid = (uint16) ((hw_buffer >> 16) & 0xffff); 23024 23025 return BCM_E_NONE; 23026 } 23027 #endif /* BCM_TRIDENT_SUPPORT || BCM_GREYHOUND_SUPPORT */ 23028 23029 /* 23030 * Function: 23031 * bcm_esw_mirror_vlan_set 23032 * Description: 23033 * Set VLAN for egressing mirrored packets on a port (RSPAN) 23034 * Parameters: 23035 * unit - (IN) Bcm device number. 23036 * port - (IN) Mirror-to port to set (-1 for all ports). 23037 * tpid - (IN) Tag protocol id (0 to disable). 23038 * vlan - (IN) Virtual lan number (0 to disable). 23039 * Returns: 23040 * BCM_E_XXX 23041 */ 23042 int 23043 bcm_esw_mirror_vlan_set(int unit, bcm_port_t port, 23044 uint16 tpid, uint16 vlan) 23045 { 23046 int rv; 23047 23048 /* Initialization check. */ 23049 if (0 == MIRROR_INIT(unit)) { 23050 return BCM_E_INIT; 23051 } 23052 23053 /* Vlan id range check. */ 23054 if (!BCM_VLAN_VALID(vlan) && vlan != BCM_VLAN_NONE) { 23055 return (BCM_E_PARAM); 23056 } 23057 23058 23059 if (BCM_GPORT_IS_SET(port)) { 23060 BCM_IF_ERROR_RETURN(bcm_esw_port_local_get(unit, port, &port)); 23061 } 23062 23063 if(!SOC_PORT_VALID(unit, port)) { 23064 return (BCM_E_PORT); 23065 } 23066 23067 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_GREYHOUND_SUPPORT) 23068 if (soc_feature(unit, soc_feature_mirror_encap_profile)) { 23069 #ifdef BCM_TRIDENT3_SUPPORT 23070 if (SOC_IS_TRIDENT3X(unit)) { 23071 rv = _bcm_td3_mirror_vlan_set(unit, port, tpid, vlan); 23072 } else 23073 #endif /* BCM_TRIDENT3_SUPPORT */ 23074 { 23075 rv = _bcm_trident_mirror_vlan_set(unit, port, tpid, vlan); 23076 } 23077 } else 23078 #endif /* BCM_TRIDENT_SUPPORT || BCM_GREYHOUND_SUPPORT */ 23079 #ifdef BCM_FIREBOLT_SUPPORT 23080 if (SOC_IS_FBX(unit)) { 23081 rv = WRITE_EGR_RSPAN_VLAN_TAGr(unit, port, (tpid << 16) | vlan); 23082 } else 23083 #endif /* BCM_FIREBOLT_SUPPORT */ 23084 { 23085 rv = BCM_E_UNAVAIL; 23086 } 23087 return (rv); 23088 } 23089 23090 /* 23091 * Function: 23092 * bcm_esw_mirror_vlan_get 23093 * Description: 23094 * Get VLAN for egressing mirrored packets on a port (RSPAN) 23095 * Parameters: 23096 * unit - (IN) BCM device number 23097 * port - (IN) Mirror-to port for which to get tag info 23098 * tpid - (OUT) tag protocol id 23099 * vlan - (OUT) virtual lan number 23100 * Returns: 23101 * BCM_E_XXX 23102 */ 23103 int 23104 bcm_esw_mirror_vlan_get(int unit, bcm_port_t port, 23105 uint16 *tpid, uint16 *vlan) 23106 { 23107 int rv; 23108 23109 /* Initialization check. */ 23110 if (0 == MIRROR_INIT(unit)) { 23111 return BCM_E_INIT; 23112 } 23113 23114 /* Input parameters check. */ 23115 if ((NULL == tpid) || (NULL == vlan)) { 23116 return (BCM_E_PARAM); 23117 } 23118 23119 if (BCM_GPORT_IS_SET(port)) { 23120 BCM_IF_ERROR_RETURN(bcm_esw_port_local_get(unit, port, &port)); 23121 } 23122 23123 if(!SOC_PORT_VALID(unit, port)) { 23124 return (BCM_E_PORT); 23125 } 23126 23127 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_GREYHOUND_SUPPORT) 23128 if (soc_feature(unit, soc_feature_mirror_encap_profile)) { 23129 #ifdef BCM_TRIDENT3_SUPPORT 23130 if (SOC_IS_TRIDENT3X(unit)) { 23131 rv = _bcm_td3_mirror_vlan_get(unit, port, tpid, vlan); 23132 } else 23133 #endif /* BCM_TRIDENT3_SUPPORT */ 23134 { 23135 rv = _bcm_trident_mirror_vlan_get(unit, port, tpid, vlan); 23136 } 23137 } else 23138 #endif /* BCM_TRIDENT_SUPPORT || BCM_GREYHOUND_SUPPORT */ 23139 #ifdef BCM_FIREBOLT_SUPPORT 23140 if (SOC_IS_FBX(unit)) { 23141 uint32 rspan; 23142 23143 BCM_IF_ERROR_RETURN(READ_EGR_RSPAN_VLAN_TAGr(unit, port, &rspan)); 23144 *tpid = (rspan >> 16); 23145 *vlan = (rspan & 0xFFF); 23146 23147 rv = BCM_E_NONE; 23148 } else 23149 #endif /* BCM_FIREBOLT_SUPPORT */ 23150 { 23151 rv = BCM_E_UNAVAIL; 23152 } 23153 return (rv); 23154 } 23155 23156 /* 23157 * Function: 23158 * bcm_esw_mirror_egress_path_set 23159 * Description: 23160 * Set egress mirror packet path for stack ring 23161 * Parameters: 23162 * unit - (IN) BCM device number 23163 * modid - (IN) Destination module ID (of mirror-to port) 23164 * port - (IN) Stack port for egress mirror packet 23165 * Returns: 23166 * BCM_E_XXX 23167 * Notes: 23168 * This function should only be used for XGS3 devices stacked 23169 * in a ring configuration with fabric devices that may block 23170 * egress mirror packets when the mirror-to port is on a 23171 * different device than the egress port being mirrored. 23172 * Currently the only such fabric device is BCM5675 rev A0. 23173 */ 23174 int 23175 bcm_esw_mirror_egress_path_set(int unit, bcm_module_t modid, bcm_port_t port) 23176 { 23177 /* Initialization check. */ 23178 if (0 == MIRROR_INIT(unit)) { 23179 return BCM_E_INIT; 23180 } 23181 23182 /* Input validation */ 23183 if (!SOC_MODID_ADDRESSABLE(unit, modid)) { 23184 return BCM_E_BADID; 23185 } 23186 23187 if (BCM_GPORT_IS_SET(port)) { 23188 bcm_module_t tmp_modid; 23189 int isLocal; 23190 23191 BCM_IF_ERROR_RETURN( 23192 _bcm_mirror_gport_resolve(unit, port, &port, &tmp_modid)); 23193 BCM_IF_ERROR_RETURN(_bcm_esw_modid_is_local(unit, tmp_modid, &isLocal)); 23194 23195 if (TRUE != isLocal) { 23196 return BCM_E_PORT; 23197 } 23198 23199 } else { 23200 /* Actuall physical port passed */ 23201 if (!SOC_PORT_VALID(unit, port) || 23202 !SOC_PORT_ADDRESSABLE(unit, port)) { 23203 return BCM_E_PORT; 23204 } 23205 } 23206 23207 #ifdef BCM_XGS3_SWITCH_SUPPORT 23208 if (SOC_IS_XGS3_SWITCH(unit)) { 23209 return bcm_xgs3_mirror_egress_path_set(unit, modid, port); 23210 } 23211 #endif /* BCM_XGS3_SWITCH_SUPPORT */ 23212 23213 return (BCM_E_UNAVAIL); 23214 } 23215 23216 /* 23217 * Function: 23218 * bcm_esw_mirror_egress_path_get 23219 * Description: 23220 * Get egress mirror packet path for stack ring 23221 * Parameters: 23222 * unit - (IN) BCM device number 23223 * modid - (IN) Destination module ID (of mirror-to port) 23224 * port - (OUT)Stack port for egress mirror packet 23225 * Returns: 23226 * BCM_E_XXX 23227 * Notes: 23228 * See bcm_mirror_alt_egress_pbmp_set for more details. 23229 */ 23230 int 23231 bcm_esw_mirror_egress_path_get(int unit, bcm_module_t modid, bcm_port_t *port) 23232 { 23233 #ifdef BCM_XGS3_SWITCH_SUPPORT 23234 int rv, isGport; 23235 bcm_module_t mod_out; 23236 bcm_port_t port_out; 23237 #endif /* BCM_XGS3_SWITCH_SUPPORT */ 23238 23239 /* Initialization check. */ 23240 if (0 == MIRROR_INIT(unit)) { 23241 return BCM_E_INIT; 23242 } 23243 23244 /* Input parameters check. */ 23245 if (NULL == port) { 23246 return (BCM_E_PARAM); 23247 } 23248 23249 #ifdef BCM_XGS3_SWITCH_SUPPORT 23250 if (SOC_IS_XGS3_SWITCH(unit)) { 23251 rv = bcm_xgs3_mirror_egress_path_get(unit, modid, port); 23252 23253 if (BCM_FAILURE(rv)) { 23254 return rv; 23255 } 23256 BCM_IF_ERROR_RETURN( 23257 bcm_esw_switch_control_get(unit, bcmSwitchUseGport, &isGport)); 23258 if (isGport) { 23259 BCM_IF_ERROR_RETURN( 23260 _bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET, modid, *port, 23261 &mod_out, &port_out)); 23262 BCM_IF_ERROR_RETURN( 23263 _bcm_mirror_gport_construct(unit, port_out, mod_out, 0, port)); 23264 } else { 23265 BCM_IF_ERROR_RETURN( 23266 _bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_SET, modid, *port, 23267 &mod_out, port)); 23268 } 23269 23270 return (BCM_E_NONE); 23271 } 23272 #endif /* BCM_XGS3_SWITCH_SUPPORT */ 23273 23274 return (BCM_E_UNAVAIL); 23275 } 23276 23277 23278 /* 23279 * Function: 23280 * bcm_esw_mirror_port_set 23281 * Description: 23282 * Set mirroring configuration for a port 23283 * Parameters: 23284 * unit - BCM device number 23285 * port - port to configure 23286 * dest_mod - module id of mirror-to port 23287 * (-1 for local port) 23288 * dest_port - mirror-to port ( can be gport or mirror_gport) 23289 * flags - BCM_MIRROR_PORT_* flags 23290 * Returns: 23291 * BCM_E_XXX 23292 * Notes: 23293 * Setting BCM_MIRROR_PORT_ENABLE without setting _INGRESS or 23294 * _EGRESS allows the port to participate in bcm_l2_cache matches 23295 * with the BCM_L2_CACHE_MIRROR bit set, and to participate in 23296 * bcm_field lookups with the mirror action set. 23297 * 23298 * If bcmSwitchDirectedMirroring is disabled for the unit and 23299 * dest_mod is non-negative, then the dest_mod path is looked 23300 * up using bcm_topo_port_get. 23301 * If bcmSwitchDirectedMirroring is enabled for the unit and 23302 * dest_mod is negative, then the local unit's modid is used 23303 * as the dest_mod. 23304 */ 23305 int 23306 bcm_esw_mirror_port_set(int unit, bcm_port_t port, 23307 bcm_module_t dest_mod, bcm_port_t dest_port, 23308 uint32 flags) 23309 { 23310 int rv; /* Operation return status. */ 23311 bcm_mirror_destination_t mirror_dest; /* Mirror destination. */ 23312 uint32 destroy_flag = FALSE; /* mirror dest destroy */ 23313 23314 #ifdef BCM_KATANA2_SUPPORT 23315 bcm_port_t pport; 23316 bcm_subport_config_t config; 23317 bcm_subport_group_config_t gconfig; 23318 if (SOC_IS_KATANA2(unit)) { 23319 if (soc_property_get(unit, spn_MMU_MULTI_PACKETS_PER_CELL, 0)) { 23320 if (_BCM_KT2_GPORT_IS_LINKPHY_OR_SUBTAG_SUBPORT_GPORT (unit, dest_port)){ 23321 BCM_IF_ERROR_RETURN(bcm_esw_subport_port_get(unit, dest_port, &config)); 23322 BCM_IF_ERROR_RETURN(bcm_esw_subport_group_get(unit, config.group, &gconfig)); 23323 pport = gconfig.port; 23324 } else { 23325 pport = dest_port; 23326 } 23327 23328 if (SOC_PBMP_MEMBER(PBMP_EXT_MEM (unit), pport)) { 23329 return BCM_E_PORT; 23330 } 23331 } 23332 } 23333 #endif 23334 /* Initialization check. */ 23335 if (0 == MIRROR_INIT(unit)) { 23336 return BCM_E_INIT; 23337 } 23338 23339 #ifdef BCM_TOMAHAWK3_SUPPORT 23340 if (SOC_IS_TOMAHAWK3(unit)) { 23341 /* Destination port cannot be trunk. Also true egr mirroring not 23342 * supported 23343 */ 23344 if ((flags & BCM_MIRROR_PORT_DEST_TRUNK) || 23345 (flags & BCM_MIRROR_PORT_EGRESS_TRUE)) { 23346 return BCM_E_UNAVAIL; 23347 } 23348 23349 /* MTP cannot be trunk */ 23350 if (BCM_GPORT_IS_TRUNK(dest_port)) { 23351 return BCM_E_UNAVAIL; 23352 } 23353 } 23354 #endif /* BCM_TOMAHAWK3_SUPPORT */ 23355 23356 if (BCM_GPORT_IS_SET(port)) { 23357 #ifdef BCM_TRIDENT2PLUS_SUPPORT 23358 if (soc_feature(unit, soc_feature_hgproxy_subtag_coe) && 23359 _BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, port)) { 23360 } else 23361 #endif 23362 { 23363 BCM_IF_ERROR_RETURN(bcm_esw_port_local_get(unit, port, &port)); 23364 } 23365 } 23366 23367 /* Input parameters check */ 23368 if (!soc_feature(unit, soc_feature_egr_mirror_true) && 23369 (flags & BCM_MIRROR_PORT_EGRESS_TRUE)) { 23370 return (BCM_E_PARAM); 23371 } 23372 23373 /* If mirroring is completely disabled, remove all mirror destinations */ 23374 if (flags == 0 && dest_mod == -1 && dest_port == -1) { 23375 flags = BCM_MIRROR_PORT_INGRESS | BCM_MIRROR_PORT_EGRESS; 23376 if (soc_feature(unit, soc_feature_egr_mirror_true)) { 23377 flags |= BCM_MIRROR_PORT_EGRESS_TRUE; 23378 } 23379 return bcm_esw_mirror_port_dest_delete_all(unit, port, flags); 23380 } 23381 23382 /* Create traditional mirror destination. */ 23383 bcm_mirror_destination_t_init(&mirror_dest); 23384 23385 MIRROR_LOCK(unit); 23386 if (BCM_GPORT_IS_MIRROR(dest_port)) { 23387 rv = bcm_esw_mirror_destination_get(unit, dest_port, &mirror_dest); 23388 } else { 23389 rv = _bcm_esw_mirror_destination_find(unit, dest_port, dest_mod, flags, &mirror_dest); 23390 if (BCM_E_NOT_FOUND == rv) { 23391 if ((flags & (BCM_MIRROR_PORT_INGRESS | BCM_MIRROR_PORT_EGRESS)) | 23392 (soc_feature(unit, soc_feature_egr_mirror_true) && 23393 (flags & BCM_MIRROR_PORT_EGRESS_TRUE))) { 23394 rv = _bcm_esw_mirror_destination_create(unit, &mirror_dest); 23395 destroy_flag = TRUE; 23396 } else { 23397 MIRROR_UNLOCK(unit); 23398 return (BCM_E_NONE); 23399 } 23400 } 23401 } 23402 if (BCM_FAILURE(rv)) { 23403 MIRROR_UNLOCK(unit); 23404 return rv; 23405 } 23406 23407 /* Enable/Disable ingress mirroring. */ 23408 if (flags & BCM_MIRROR_PORT_INGRESS) { 23409 rv = bcm_esw_mirror_port_dest_add(unit, port, BCM_MIRROR_PORT_INGRESS, 23410 mirror_dest.mirror_dest_id); 23411 if (BCM_E_EXISTS == rv) { 23412 /* Since this function is set, not add, it is sufficient if 23413 * the destination already exists. Clear the error. */ 23414 rv = BCM_E_NONE; 23415 } 23416 } else { 23417 rv = bcm_esw_mirror_port_dest_delete(unit, port, BCM_MIRROR_PORT_INGRESS, 23418 mirror_dest.mirror_dest_id); 23419 if (BCM_E_NOT_FOUND == rv) { 23420 /* There is no clean way to identify delete. -> 23421 if destination is not found assume success. */ 23422 rv = BCM_E_NONE; 23423 } 23424 } 23425 23426 if (BCM_FAILURE(rv)) { 23427 /* Delete unused mirror destination. */ 23428 if (destroy_flag) { 23429 (void)bcm_esw_mirror_destination_destroy(unit, mirror_dest.mirror_dest_id); 23430 } 23431 MIRROR_UNLOCK(unit); 23432 return (rv); 23433 } 23434 23435 /* Enable/Disable egress mirroring. */ 23436 if (flags & BCM_MIRROR_PORT_EGRESS) { 23437 rv = bcm_esw_mirror_port_dest_add(unit, port, BCM_MIRROR_PORT_EGRESS, 23438 mirror_dest.mirror_dest_id); 23439 if (BCM_E_EXISTS == rv) { 23440 /* Since this function is set, not add, it is sufficient if 23441 * the destination already exists. Clear the error. */ 23442 rv = BCM_E_NONE; 23443 } 23444 } else { 23445 rv = bcm_esw_mirror_port_dest_delete(unit, port, BCM_MIRROR_PORT_EGRESS, 23446 mirror_dest.mirror_dest_id); 23447 if (BCM_E_NOT_FOUND == rv) { 23448 /* There is no clean way to identify delete. -> 23449 if destination is not found assume success. */ 23450 rv = BCM_E_NONE; 23451 } 23452 } 23453 23454 if (BCM_FAILURE(rv)) { 23455 /* Delete unused mirror destination. */ 23456 if (destroy_flag) { 23457 (void)bcm_esw_mirror_destination_destroy(unit, mirror_dest.mirror_dest_id); 23458 } 23459 MIRROR_UNLOCK(unit); 23460 return (rv); 23461 } 23462 23463 #ifdef BCM_TRIUMPH2_SUPPORT 23464 if (soc_feature(unit, soc_feature_egr_mirror_true)) { 23465 /* Enable/Disable egress true mirroring. */ 23466 if (flags & BCM_MIRROR_PORT_EGRESS_TRUE) { 23467 rv = bcm_esw_mirror_port_dest_add(unit, port, 23468 BCM_MIRROR_PORT_EGRESS_TRUE, 23469 mirror_dest.mirror_dest_id); 23470 if (BCM_E_EXISTS == rv) { 23471 /* Since this function is set, not add, it is sufficient if 23472 * the destination already exists. Clear the error. */ 23473 rv = BCM_E_NONE; 23474 } 23475 } else { 23476 rv = bcm_esw_mirror_port_dest_delete(unit, port, 23477 BCM_MIRROR_PORT_EGRESS_TRUE, 23478 mirror_dest.mirror_dest_id); 23479 if (BCM_E_NOT_FOUND == rv) { 23480 /* There is no clean way to identify delete. -> 23481 if destination is not found assume success. */ 23482 rv = BCM_E_NONE; 23483 } 23484 } 23485 23486 if (BCM_FAILURE(rv)) { 23487 /* Delete unused mirror destination. */ 23488 if (destroy_flag) { 23489 (void)bcm_esw_mirror_destination_destroy(unit, 23490 mirror_dest.mirror_dest_id); 23491 } 23492 MIRROR_UNLOCK(unit); 23493 return (rv); 23494 } 23495 } 23496 #endif /* BCM_TRIUMPH2_SUPPORT */ 23497 23498 /* Delete unused mirror destination. */ 23499 if (1 >= MIRROR_DEST_REF_COUNT(unit, mirror_dest.mirror_dest_id)) { 23500 rv = bcm_esw_mirror_destination_destroy(unit, mirror_dest.mirror_dest_id); 23501 } 23502 23503 MIRROR_UNLOCK(unit); 23504 return (rv); 23505 } 23506 /* 23507 * Function: 23508 * bcm_esw_mirror_port_get 23509 * Description: 23510 * Get mirroring configuration for a port 23511 * Parameters: 23512 * unit - BCM device number 23513 * port - port to get configuration for 23514 * dest_mod - (OUT) module id of mirror-to port 23515 * dest_port - (OUT) mirror-to port 23516 * flags - (OUT) BCM_MIRROR_PORT_* flags 23517 * Returns: 23518 * BCM_E_XXX 23519 */ 23520 int 23521 bcm_esw_mirror_port_get(int unit, bcm_port_t port, 23522 bcm_module_t *dest_mod, bcm_port_t *dest_port, 23523 uint32 *flags) 23524 { 23525 bcm_gport_t mirror_dest_id; /* Mirror destination id. */ 23526 int enable = 0; /* Egress mirror is enabled. */ 23527 int rv; /* Operation return status. */ 23528 int mirror_dest_count = 0; /* Mirror destination found. */ 23529 int isGport; /* gport indicator */ 23530 bcm_mirror_destination_t mirror_dest; /* mirror destination struct */ 23531 /* Initialization check. */ 23532 if (0 == MIRROR_INIT(unit)) { 23533 return BCM_E_INIT; 23534 } 23535 23536 /* Input parameters check. */ 23537 if ((NULL == flags) || (NULL == dest_mod) || (NULL == dest_port)) { 23538 return (BCM_E_PARAM); 23539 } 23540 23541 bcm_mirror_destination_t_init(&mirror_dest); 23542 23543 if (BCM_GPORT_IS_SET(port)) { 23544 #ifdef BCM_TRIDENT2PLUS_SUPPORT 23545 if (soc_feature(unit, soc_feature_hgproxy_subtag_coe) && 23546 _BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, port)) { 23547 } else 23548 #endif 23549 { 23550 BCM_IF_ERROR_RETURN(bcm_esw_port_local_get(unit, port, &port)); 23551 } 23552 } 23553 23554 *flags = 0; 23555 23556 /* Check if directed mirroring is enabled and gport required. */ 23557 BCM_IF_ERROR_RETURN(bcm_esw_switch_control_get(unit, bcmSwitchUseGport, 23558 &isGport)); 23559 23560 MIRROR_LOCK(unit); 23561 23562 /* Read port ingress mirroring destination ports. */ 23563 rv = bcm_esw_mirror_port_dest_get(unit, port, BCM_MIRROR_PORT_INGRESS, 23564 1, &mirror_dest_id, 23565 &mirror_dest_count); 23566 if (BCM_FAILURE(rv)) { 23567 MIRROR_UNLOCK(unit); 23568 return (rv); 23569 } 23570 23571 if (mirror_dest_count) { 23572 rv = bcm_esw_mirror_destination_get(unit, mirror_dest_id, 23573 &mirror_dest); 23574 23575 if (BCM_FAILURE(rv)) { 23576 MIRROR_UNLOCK(unit); 23577 return (rv); 23578 } 23579 *flags |= BCM_MIRROR_PORT_INGRESS; 23580 23581 /* Read mtp egress enable bitmap for source port. */ 23582 rv = _bcm_esw_mirror_egress_get(unit, port, &enable); 23583 if (BCM_FAILURE(rv)) { 23584 MIRROR_UNLOCK(unit); 23585 return (rv); 23586 } 23587 if (enable) { 23588 *flags |= BCM_MIRROR_PORT_EGRESS; 23589 } else { 23590 #ifdef BCM_TRIUMPH2_SUPPORT 23591 if (soc_feature(unit, soc_feature_egr_mirror_true)) { 23592 rv = _bcm_esw_mirror_port_dest_search(unit, port, 23593 BCM_MIRROR_PORT_EGRESS_TRUE, 23594 mirror_dest_id); 23595 if (BCM_E_EXISTS == rv) { 23596 *flags |= BCM_MIRROR_PORT_EGRESS_TRUE; 23597 } 23598 rv = BCM_E_NONE; 23599 } 23600 #endif 23601 } 23602 23603 MIRROR_UNLOCK(unit); 23604 23605 if (isGport) { 23606 *dest_port = mirror_dest.gport; 23607 } else if (BCM_GPORT_IS_TRUNK(mirror_dest.gport)) { 23608 *flags |= BCM_MIRROR_PORT_DEST_TRUNK; 23609 *dest_port = BCM_GPORT_TRUNK_GET(mirror_dest.gport); 23610 } else { 23611 BCM_IF_ERROR_RETURN( 23612 _bcm_mirror_gport_resolve(unit, mirror_dest.gport, 23613 dest_port, dest_mod)); 23614 BCM_IF_ERROR_RETURN( 23615 _bcm_gport_modport_hw2api_map(unit, *dest_mod, *dest_port, 23616 dest_mod, dest_port)); 23617 } 23618 23619 return (BCM_E_NONE); 23620 } 23621 23622 /* Read port egress mirroring destination ports. */ 23623 rv = bcm_esw_mirror_port_dest_get(unit, port, BCM_MIRROR_PORT_EGRESS, 23624 1, &mirror_dest_id, 23625 &mirror_dest_count); 23626 23627 if (BCM_FAILURE(rv)) { 23628 MIRROR_UNLOCK(unit); 23629 return (rv); 23630 } 23631 23632 if (mirror_dest_count) { 23633 rv = bcm_esw_mirror_destination_get(unit, mirror_dest_id, 23634 &mirror_dest); 23635 23636 if (BCM_FAILURE(rv)) { 23637 MIRROR_UNLOCK(unit); 23638 return (rv); 23639 } 23640 *flags |= BCM_MIRROR_PORT_EGRESS; 23641 23642 MIRROR_UNLOCK(unit); 23643 23644 if (isGport) { 23645 *dest_port = mirror_dest.gport; 23646 } else if (BCM_GPORT_IS_TRUNK(mirror_dest.gport)) { 23647 *flags |= BCM_MIRROR_PORT_DEST_TRUNK; 23648 *dest_port = BCM_GPORT_TRUNK_GET(mirror_dest.gport); 23649 } else { 23650 BCM_IF_ERROR_RETURN( 23651 _bcm_mirror_gport_resolve(unit, mirror_dest.gport, 23652 dest_port, dest_mod)); 23653 BCM_IF_ERROR_RETURN( 23654 _bcm_gport_modport_hw2api_map(unit, *dest_mod, *dest_port, 23655 dest_mod, dest_port)); 23656 } 23657 23658 return (BCM_E_NONE); 23659 } 23660 23661 #ifdef BCM_TRIUMPH2_SUPPORT 23662 if (soc_feature(unit, soc_feature_egr_mirror_true)) { 23663 /* Read port ingress mirroring destination ports. */ 23664 rv = bcm_esw_mirror_port_dest_get(unit, port, 23665 BCM_MIRROR_PORT_EGRESS_TRUE, 23666 1, &mirror_dest_id, 23667 &mirror_dest_count); 23668 23669 if (BCM_FAILURE(rv)) { 23670 MIRROR_UNLOCK(unit); 23671 return (rv); 23672 } 23673 23674 if (mirror_dest_count) { 23675 rv = bcm_esw_mirror_destination_get(unit, mirror_dest_id, 23676 &mirror_dest); 23677 23678 if (BCM_FAILURE(rv)) { 23679 MIRROR_UNLOCK(unit); 23680 return (rv); 23681 } 23682 *flags |= BCM_MIRROR_PORT_EGRESS_TRUE; 23683 23684 MIRROR_UNLOCK(unit); 23685 23686 if (isGport) { 23687 *dest_port = mirror_dest.gport; 23688 } else if (BCM_GPORT_IS_TRUNK(mirror_dest.gport)) { 23689 *flags |= BCM_MIRROR_PORT_DEST_TRUNK; 23690 *dest_port = BCM_GPORT_TRUNK_GET(mirror_dest.gport); 23691 } else { 23692 BCM_IF_ERROR_RETURN 23693 (_bcm_mirror_gport_resolve(unit, mirror_dest.gport, 23694 dest_port, dest_mod)); 23695 BCM_IF_ERROR_RETURN 23696 (_bcm_gport_modport_hw2api_map(unit, *dest_mod, *dest_port, 23697 dest_mod, dest_port)); 23698 } 23699 23700 return (BCM_E_NONE); 23701 } 23702 } 23703 #endif /* BCM_TRIUMPH2_SUPPORT */ 23704 23705 MIRROR_UNLOCK(unit); 23706 23707 return (BCM_E_NONE); 23708 } 23709 23710 STATIC int 23711 _bcm_mirror_sflow_dest_delete(int unit, uint32 flags, bcm_gport_t mirror_dest) 23712 { 23713 #if defined(BCM_TOMAHAWK_SUPPORT) 23714 int mc_enable; /* Mirror enable check. */ 23715 int mtp_index = -1; /* Mirror to port index. */ 23716 uint32 reg_val; 23717 int mtp_slot; 23718 uint32 check_flags = BCM_MIRROR_PORT_INGRESS | BCM_MIRROR_PORT_SFLOW; 23719 23720 soc_field_t mtp_idxf[BCM_MIRROR_MTP_COUNT] = { 23721 MTP_INDEX0f,MTP_INDEX1f,MTP_INDEX2f,MTP_INDEX3f}; 23722 23723 if (!soc_feature(unit, soc_feature_sflow_ing_mirror)) { 23724 return BCM_E_UNAVAIL; 23725 } 23726 23727 if (!soc_feature(unit, soc_feature_mirror_flexible)) { 23728 return BCM_E_UNAVAIL; 23729 } 23730 23731 #ifdef BCM_TRIDENT3_SUPPORT 23732 if (SOC_IS_TRIDENT3X(unit)) { 23733 check_flags |= BCM_MIRROR_PORT_PSAMP; 23734 } 23735 #endif 23736 #ifdef BCM_TOMAHAWK3_SUPPORT 23737 if (SOC_IS_TOMAHAWK3(unit)) { 23738 check_flags |= BCM_MIRROR_PORT_PSAMP; 23739 } 23740 #endif /* BCM_TOMAHAWK3_SUPPORT */ 23741 23742 /* only support BCM_MIRROR_PORT_INGRESS */ 23743 if (flags & ~check_flags) { 23744 return BCM_E_UNAVAIL; 23745 } 23746 23747 /* Look for used MTP index */ 23748 if (!MIRROR_MTP_METHOD_IS_DIRECTED_FLEXIBLE(unit)) { 23749 BCM_IF_ERROR_RETURN(_bcm_tr2_mirror_shared_mtp_match(unit, 23750 mirror_dest, FALSE, &mtp_index)); 23751 } else { 23752 BCM_IF_ERROR_RETURN(_bcm_esw_mirror_ingress_mtp_match(unit, 23753 mirror_dest, &mtp_index)); 23754 } 23755 23756 BCM_IF_ERROR_RETURN(READ_SFLOW_ING_MIRROR_CONFIGr(unit, ®_val)); 23757 mc_enable = soc_reg_field_get(unit, SFLOW_ING_MIRROR_CONFIGr, 23758 reg_val, MIRROR_ENABLEf); 23759 23760 if (MIRROR_MTP_METHOD_IS_DIRECTED_FLEXIBLE(unit)) { 23761 BCM_IF_ERROR_RETURN(_bcm_xgs3_mtp_index_port_slot_get(unit, 0, 23762 mc_enable, FALSE, mtp_index, BCM_MTP_SLOT_TYPE_SFLOW, &mtp_slot)); 23763 } else { 23764 /* Otherwise the slot and index is 1-1 */ 23765 mtp_slot = mtp_index; 23766 } 23767 23768 if (mc_enable & (1 << mtp_slot)) { 23769 mc_enable &= ~(1 << mtp_slot); 23770 soc_reg_field_set(unit, SFLOW_ING_MIRROR_CONFIGr, 23771 ®_val, MIRROR_ENABLEf,mc_enable); 23772 soc_reg_field_set(unit, SFLOW_ING_MIRROR_CONFIGr, ®_val, 23773 mtp_idxf[mtp_slot], 0); 23774 BCM_IF_ERROR_RETURN(WRITE_SFLOW_ING_MIRROR_CONFIGr(unit, reg_val)); 23775 } 23776 23777 if (MIRROR_MTP_METHOD_IS_DIRECTED_FLEXIBLE(unit)) { 23778 BCM_IF_ERROR_RETURN(_bcm_xgs3_mtp_type_slot_unreserve(unit, 23779 BCM_MIRROR_PORT_INGRESS, 23780 0, 23781 BCM_MTP_SLOT_TYPE_SFLOW, 23782 mtp_index)); 23783 } 23784 23785 /* Free MTP index for mirror destination. */ 23786 BCM_IF_ERROR_RETURN(_bcm_esw_mirror_mtp_unreserve(unit, mtp_index, TRUE, 23787 BCM_MIRROR_PORT_INGRESS)); 23788 #ifdef BCM_TRIDENT3_SUPPORT 23789 if (SOC_IS_TRIDENT3X(unit)) { 23790 if (1 >= MIRROR_DEST_REF_COUNT(unit, mirror_dest)) { 23791 BCM_IF_ERROR_RETURN(_bcm_td3_mirror_encap_profile_index_clear(unit, 23792 BCM_GPORT_MIRROR_GET(mirror_dest))); 23793 } 23794 } 23795 #endif /* BCM_TRIDENT3_SUPPORT */ 23796 23797 return BCM_E_NONE; 23798 #else 23799 return BCM_E_UNAVAIL; 23800 #endif 23801 } 23802 23803 23804 STATIC int 23805 _bcm_mirror_int_dest_delete(int unit, uint32 flags, bcm_gport_t mirror_dest) 23806 { 23807 #if defined(BCM_TOMAHAWK3_SUPPORT) 23808 int mc_enable; /* Mirror enable check. */ 23809 int mtp_index = -1; /* Mirror to port index. */ 23810 uint32 reg_val; 23811 int mtp_slot; 23812 uint32 check_flags = BCM_MIRROR_PORT_INGRESS | BCM_MIRROR_PORT_INT; 23813 23814 soc_field_t mtp_idxf[BCM_MIRROR_MTP_COUNT] = { 23815 MTP_INDEX0f,MTP_INDEX1f,MTP_INDEX2f,MTP_INDEX3f}; 23816 23817 if (!soc_feature(unit, soc_feature_inband_network_telemetry)) { 23818 return BCM_E_UNAVAIL; 23819 } 23820 23821 if (!soc_feature(unit, soc_feature_mirror_flexible)) { 23822 return BCM_E_UNAVAIL; 23823 } 23824 23825 /* only support BCM_MIRROR_PORT_INGRESS */ 23826 if (flags & ~check_flags) { 23827 return BCM_E_UNAVAIL; 23828 } 23829 23830 /* Look for used MTP index */ 23831 if (!MIRROR_MTP_METHOD_IS_DIRECTED_FLEXIBLE(unit)) { 23832 BCM_IF_ERROR_RETURN(_bcm_tr2_mirror_shared_mtp_match(unit, 23833 mirror_dest, FALSE, &mtp_index)); 23834 } else { 23835 BCM_IF_ERROR_RETURN(_bcm_esw_mirror_ingress_mtp_match(unit, 23836 mirror_dest, &mtp_index)); 23837 } 23838 23839 BCM_IF_ERROR_RETURN(READ_INT_PROCESS_CONFIGr(unit, ®_val)); 23840 mc_enable = soc_reg_field_get(unit, INT_PROCESS_CONFIGr, 23841 reg_val, MIRROR_ENABLEf); 23842 23843 if (MIRROR_MTP_METHOD_IS_DIRECTED_FLEXIBLE(unit)) { 23844 BCM_IF_ERROR_RETURN(_bcm_xgs3_mtp_index_port_slot_get(unit, 0, 23845 mc_enable, FALSE, mtp_index, BCM_MTP_SLOT_TYPE_INT, &mtp_slot)); 23846 } else { 23847 /* Otherwise the slot and index is 1-1 */ 23848 mtp_slot = mtp_index; 23849 } 23850 23851 if (mc_enable & (1 << mtp_slot)) { 23852 mc_enable &= ~(1 << mtp_slot); 23853 soc_reg_field_set(unit, INT_PROCESS_CONFIGr, ®_val, 23854 (soc_field_t)mtp_idxf[mtp_slot], 0); 23855 soc_reg_field_set(unit, INT_PROCESS_CONFIGr, ®_val, 23856 MIRROR_ENABLEf, mc_enable); 23857 BCM_IF_ERROR_RETURN(WRITE_INT_PROCESS_CONFIGr(unit, reg_val)); 23858 } 23859 23860 if (MIRROR_MTP_METHOD_IS_DIRECTED_FLEXIBLE(unit)) { 23861 BCM_IF_ERROR_RETURN(_bcm_xgs3_mtp_type_slot_unreserve(unit, 23862 BCM_MIRROR_PORT_INGRESS, 23863 0, 23864 BCM_MTP_SLOT_TYPE_INT, 23865 mtp_index)); 23866 } 23867 23868 /* Free MTP index for mirror destination. */ 23869 BCM_IF_ERROR_RETURN(_bcm_esw_mirror_mtp_unreserve(unit, mtp_index, TRUE, 23870 BCM_MIRROR_PORT_INGRESS)); 23871 return BCM_E_NONE; 23872 #else 23873 return BCM_E_UNAVAIL; 23874 #endif 23875 } 23876 23877 STATIC int 23878 _bcm_mirror_elephant_dest_delete(int unit, uint32 flags, bcm_gport_t mirror_dest) 23879 { 23880 #if defined(BCM_TOMAHAWK3_SUPPORT) 23881 int mc_enable; /* Mirror enable check. */ 23882 int mtp_index = -1; /* Mirror to port index. */ 23883 uint32 reg_val; 23884 int mtp_slot; 23885 uint32 check_flags = BCM_MIRROR_PORT_INGRESS | BCM_MIRROR_PORT_ELEPHANT; 23886 23887 soc_field_t mtp_idxf[BCM_MIRROR_MTP_COUNT] = { 23888 MTP_INDEX0f,MTP_INDEX1f,MTP_INDEX2f,MTP_INDEX3f}; 23889 23890 if (!soc_feature(unit, soc_feature_hw_etrap)) { 23891 return BCM_E_UNAVAIL; 23892 } 23893 23894 if (!soc_feature(unit, soc_feature_mirror_flexible)) { 23895 return BCM_E_UNAVAIL; 23896 } 23897 23898 /* only support BCM_MIRROR_PORT_INGRESS */ 23899 if (flags & ~check_flags) { 23900 return BCM_E_UNAVAIL; 23901 } 23902 23903 /* Look for used MTP index */ 23904 if (!MIRROR_MTP_METHOD_IS_DIRECTED_FLEXIBLE(unit)) { 23905 BCM_IF_ERROR_RETURN( 23906 _bcm_tr2_mirror_shared_mtp_match(unit, mirror_dest, 23907 FALSE, &mtp_index)); 23908 } else { 23909 BCM_IF_ERROR_RETURN( 23910 _bcm_esw_mirror_ingress_mtp_match(unit, mirror_dest, 23911 &mtp_index)); 23912 } 23913 23914 BCM_IF_ERROR_RETURN(READ_ETRAP_MONITOR_MIRROR_CONFIGr(unit, ®_val)); 23915 mc_enable = soc_reg_field_get(unit, ETRAP_MONITOR_MIRROR_CONFIGr, 23916 reg_val, MIRROR_ENABLEf); 23917 23918 if (MIRROR_MTP_METHOD_IS_DIRECTED_FLEXIBLE(unit)) { 23919 BCM_IF_ERROR_RETURN( 23920 _bcm_xgs3_mtp_index_port_slot_get(unit, 0, mc_enable, FALSE, 23921 mtp_index, 23922 BCM_MTP_SLOT_TYPE_ELEPHANT, 23923 &mtp_slot)); 23924 } else { 23925 /* Otherwise the slot and index is 1-1 */ 23926 mtp_slot = mtp_index; 23927 } 23928 23929 if (mc_enable & (1 << mtp_slot)) { 23930 mc_enable &= ~(1 << mtp_slot); 23931 soc_reg_field_set(unit, ETRAP_MONITOR_MIRROR_CONFIGr, 23932 ®_val, MIRROR_ENABLEf, mc_enable); 23933 23934 soc_reg_field_set(unit, ETRAP_MONITOR_MIRROR_CONFIGr, ®_val, 23935 (soc_field_t)mtp_idxf[mtp_slot], 0); 23936 BCM_IF_ERROR_RETURN(WRITE_ETRAP_MONITOR_MIRROR_CONFIGr(unit, reg_val)); 23937 } 23938 23939 if (MIRROR_MTP_METHOD_IS_DIRECTED_FLEXIBLE(unit)) { 23940 BCM_IF_ERROR_RETURN( 23941 _bcm_xgs3_mtp_type_slot_unreserve(unit, 23942 BCM_MIRROR_PORT_INGRESS, 23943 0, 23944 BCM_MTP_SLOT_TYPE_ELEPHANT, 23945 mtp_index)); 23946 } 23947 23948 /* Free MTP index for mirror destination. */ 23949 BCM_IF_ERROR_RETURN(_bcm_esw_mirror_mtp_unreserve(unit, mtp_index, TRUE, 23950 BCM_MIRROR_PORT_INGRESS)); 23951 return BCM_E_NONE; 23952 #else 23953 return BCM_E_UNAVAIL; 23954 #endif 23955 } 23956 23957 STATIC int 23958 _bcm_mirror_sflow_dest_get(int unit, uint32 flags, int mirror_dest_size, 23959 bcm_gport_t *mirror_dest, int *mirror_dest_count) 23960 { 23961 #if defined(BCM_TOMAHAWK_SUPPORT) 23962 uint32 reg_val; 23963 int mc_enable; 23964 int mtp_index; 23965 int index; 23966 int mtp_slot, mtp_bit; 23967 int i; 23968 uint32 index_val[BCM_MIRROR_MTP_COUNT]; 23969 uint32 check_flags = BCM_MIRROR_PORT_INGRESS | BCM_MIRROR_PORT_SFLOW; 23970 23971 soc_field_t mtp_idxf[BCM_MIRROR_MTP_COUNT] = { 23972 MTP_INDEX0f,MTP_INDEX1f,MTP_INDEX2f,MTP_INDEX3f}; 23973 23974 if (!soc_feature(unit, soc_feature_sflow_ing_mirror)) { 23975 return BCM_E_UNAVAIL; 23976 } 23977 #ifdef BCM_TRIDENT3_SUPPORT 23978 if (SOC_IS_TRIDENT3X(unit)) { 23979 check_flags |= BCM_MIRROR_PORT_PSAMP; 23980 } 23981 #endif 23982 23983 #ifdef BCM_TOMAHAWK3_SUPPORT 23984 if (SOC_IS_TOMAHAWK3(unit)) { 23985 check_flags |= BCM_MIRROR_PORT_PSAMP; 23986 } 23987 #endif /* BCM_TOMAHAWK3_SUPPORT */ 23988 23989 /* only support BCM_MIRROR_PORT_INGRESS */ 23990 if (flags & ~check_flags) { 23991 return BCM_E_UNAVAIL; 23992 } 23993 23994 BCM_IF_ERROR_RETURN(READ_SFLOW_ING_MIRROR_CONFIGr(unit, ®_val)); 23995 mc_enable = soc_reg_field_get(unit, SFLOW_ING_MIRROR_CONFIGr, 23996 reg_val, MIRROR_ENABLEf); 23997 *mirror_dest_count = 0; 23998 23999 /* Read mirror control structure to get programmed mtp indexes. */ 24000 for (i = 0; i < BCM_MIRROR_MTP_COUNT; i++) { 24001 index_val[i] = soc_reg_field_get(unit, SFLOW_ING_MIRROR_CONFIGr, 24002 reg_val, mtp_idxf[i]); 24003 } 24004 index = 0; 24005 /* Read mirror control register to compare programmed mtp indexes. */ 24006 BCM_MIRROR_MTP_ITER(MIRROR_CONFIG_MTP_DEV_MASK(unit), mtp_slot) { 24007 mtp_bit = 1 << mtp_slot; 24008 /* Check if MTP slot is enabled on port */ 24009 if (!(mc_enable & mtp_bit)) { 24010 continue; 24011 } 24012 /* MTP index is enabled and direction matches */ 24013 mtp_index = index_val[mtp_slot]; 24014 24015 if ( MIRROR_MTP_METHOD_IS_DIRECTED_FLEXIBLE(unit)) { 24016 mirror_dest[index] = 24017 MIRROR_CONFIG_ING_MTP_DEST(unit, mtp_index); 24018 } else { 24019 mirror_dest[index] = 24020 MIRROR_CONFIG_SHARED_MTP_DEST(unit, mtp_index); 24021 } 24022 index++; 24023 } 24024 *mirror_dest_count = index; 24025 24026 return BCM_E_NONE; 24027 #else 24028 return BCM_E_UNAVAIL; 24029 #endif 24030 } 24031 24032 STATIC int 24033 _bcm_mirror_int_dest_get(int unit, uint32 flags, int mirror_dest_size, 24034 bcm_gport_t *mirror_dest, int *mirror_dest_count) 24035 { 24036 #if defined(BCM_TOMAHAWK3_SUPPORT) 24037 uint32 reg_val; 24038 int mc_enable; 24039 int mtp_index; 24040 int index; 24041 int mtp_slot, mtp_bit; 24042 int i; 24043 uint32 index_val[BCM_MIRROR_MTP_COUNT]; 24044 uint32 check_flags = BCM_MIRROR_PORT_INGRESS | BCM_MIRROR_PORT_INT; 24045 24046 soc_field_t mtp_idxf[BCM_MIRROR_MTP_COUNT] = { 24047 MTP_INDEX0f,MTP_INDEX1f,MTP_INDEX2f,MTP_INDEX3f}; 24048 24049 if (!soc_feature(unit, soc_feature_inband_network_telemetry)) { 24050 return BCM_E_UNAVAIL; 24051 } 24052 24053 /* only support BCM_MIRROR_PORT_INGRESS */ 24054 if (flags & ~check_flags) { 24055 return BCM_E_UNAVAIL; 24056 } 24057 24058 BCM_IF_ERROR_RETURN(READ_INT_PROCESS_CONFIGr(unit, ®_val)); 24059 mc_enable = soc_reg_field_get(unit, INT_PROCESS_CONFIGr, 24060 reg_val, MIRROR_ENABLEf); 24061 *mirror_dest_count = 0; 24062 24063 /* Read mirror control structure to get programmed mtp indexes. */ 24064 for (i = 0; i < BCM_MIRROR_MTP_COUNT; i++) { 24065 index_val[i] = soc_reg_field_get(unit, INT_PROCESS_CONFIGr, 24066 reg_val, mtp_idxf[i]); 24067 } 24068 index = 0; 24069 /* Read mirror control register to compare programmed mtp indexes. */ 24070 BCM_MIRROR_MTP_ITER(MIRROR_CONFIG_MTP_DEV_MASK(unit), mtp_slot) { 24071 mtp_bit = 1 << mtp_slot; 24072 /* Check if MTP slot is enabled on port */ 24073 if (!(mc_enable & mtp_bit)) { 24074 continue; 24075 } 24076 /* MTP index is enabled and direction matches */ 24077 mtp_index = index_val[mtp_slot]; 24078 24079 if ( MIRROR_MTP_METHOD_IS_DIRECTED_FLEXIBLE(unit)) { 24080 mirror_dest[index] = 24081 MIRROR_CONFIG_ING_MTP_DEST(unit, mtp_index); 24082 } else { 24083 mirror_dest[index] = 24084 MIRROR_CONFIG_SHARED_MTP_DEST(unit, mtp_index); 24085 } 24086 index++; 24087 } 24088 *mirror_dest_count = index; 24089 24090 return BCM_E_NONE; 24091 #else 24092 return BCM_E_UNAVAIL; 24093 #endif 24094 } 24095 24096 STATIC int 24097 _bcm_mirror_elephant_dest_get(int unit, uint32 flags, int mirror_dest_size, 24098 bcm_gport_t *mirror_dest, int *mirror_dest_count) 24099 { 24100 #if defined(BCM_TOMAHAWK3_SUPPORT) 24101 uint32 reg_val; 24102 int mc_enable; 24103 int mtp_index; 24104 int index; 24105 int mtp_slot, mtp_bit; 24106 int i; 24107 uint32 index_val[BCM_MIRROR_MTP_COUNT]; 24108 uint32 check_flags = BCM_MIRROR_PORT_INGRESS | BCM_MIRROR_PORT_ELEPHANT; 24109 24110 soc_field_t mtp_idxf[BCM_MIRROR_MTP_COUNT] = { 24111 MTP_INDEX0f,MTP_INDEX1f,MTP_INDEX2f,MTP_INDEX3f}; 24112 24113 if (!soc_feature(unit, soc_feature_hw_etrap)) { 24114 return BCM_E_UNAVAIL; 24115 } 24116 24117 /* only support BCM_MIRROR_PORT_INGRESS */ 24118 if (flags & ~check_flags) { 24119 return BCM_E_UNAVAIL; 24120 } 24121 24122 SOC_IF_ERROR_RETURN(READ_ETRAP_MONITOR_MIRROR_CONFIGr(unit, ®_val)); 24123 mc_enable = soc_reg_field_get(unit, ETRAP_MONITOR_MIRROR_CONFIGr, 24124 reg_val, MIRROR_ENABLEf); 24125 *mirror_dest_count = 0; 24126 24127 /* Read mirror control structure to get programmed mtp indexes. */ 24128 for (i = 0; i < BCM_MIRROR_MTP_COUNT; i++) { 24129 index_val[i] = soc_reg_field_get(unit, ETRAP_MONITOR_MIRROR_CONFIGr, 24130 reg_val, mtp_idxf[i]); 24131 } 24132 index = 0; 24133 /* Read mirror control register to compare programmed mtp indexes. */ 24134 BCM_MIRROR_MTP_ITER(MIRROR_CONFIG_MTP_DEV_MASK(unit), mtp_slot) { 24135 mtp_bit = 1 << mtp_slot; 24136 /* Check if MTP slot is enabled on port */ 24137 if (!(mc_enable & mtp_bit)) { 24138 continue; 24139 } 24140 /* MTP index is enabled and direction matches */ 24141 mtp_index = index_val[mtp_slot]; 24142 24143 if ( MIRROR_MTP_METHOD_IS_DIRECTED_FLEXIBLE(unit)) { 24144 mirror_dest[index] = 24145 MIRROR_CONFIG_ING_MTP_DEST(unit, mtp_index); 24146 } else { 24147 mirror_dest[index] = 24148 MIRROR_CONFIG_SHARED_MTP_DEST(unit, mtp_index); 24149 } 24150 index++; 24151 } 24152 *mirror_dest_count = index; 24153 24154 return BCM_E_NONE; 24155 #else 24156 return BCM_E_UNAVAIL; 24157 #endif 24158 } 24159 24160 24161 STATIC int 24162 _bcm_mirror_sflow_dest_add(int unit, uint32 flags, bcm_gport_t mirror_dest) 24163 { 24164 #if defined(BCM_TOMAHAWK_SUPPORT) 24165 int rv; 24166 uint32 reg_val; 24167 int i; 24168 int mc_enable; 24169 int mtp_index; 24170 soc_field_t mtp_idxf[BCM_MIRROR_MTP_COUNT] = { 24171 MTP_INDEX0f,MTP_INDEX1f,MTP_INDEX2f,MTP_INDEX3f}; 24172 bcm_gport_t mirror_dest_list[BCM_MIRROR_MTP_COUNT]; 24173 int mirror_dest_count; 24174 int mtp_slot; /* MTP type value */ 24175 uint32 replace_flag = 0; 24176 uint32 check_flags = BCM_MIRROR_PORT_INGRESS | BCM_MIRROR_PORT_SFLOW; 24177 bcm_mirror_destination_t mirr_dest; 24178 24179 if (!soc_feature(unit, soc_feature_sflow_ing_mirror)) { 24180 return BCM_E_UNAVAIL; 24181 } 24182 if (!soc_feature(unit, soc_feature_mirror_flexible)) { 24183 return BCM_E_UNAVAIL; 24184 } 24185 24186 /* only support BCM_MIRROR_PORT_INGRESS */ 24187 #ifdef BCM_TRIDENT3_SUPPORT 24188 if (SOC_IS_TRIDENT3X(unit)) { 24189 check_flags |= BCM_MIRROR_PORT_PSAMP; 24190 } 24191 #endif 24192 24193 #ifdef BCM_TOMAHAWK3_SUPPORT 24194 if (SOC_IS_TOMAHAWK3(unit)) { 24195 check_flags |= BCM_MIRROR_PORT_PSAMP; 24196 } 24197 #endif /* BCM_TOMAHAWK3_SUPPORT */ 24198 24199 if (flags & ~check_flags) { 24200 return BCM_E_UNAVAIL; 24201 } 24202 24203 rv = bcm_esw_mirror_destination_get(unit, mirror_dest, &mirr_dest); 24204 if (BCM_FAILURE(rv)) { 24205 return (rv); 24206 } 24207 24208 replace_flag = (mirr_dest.flags & BCM_MIRROR_DEST_REPLACE) ? 1:0; 24209 24210 rv = bcm_esw_mirror_port_dest_get(unit, -1, 24211 flags, 24212 BCM_MIRROR_MTP_COUNT, 24213 mirror_dest_list, &mirror_dest_count); 24214 if (BCM_SUCCESS(rv)) { 24215 rv = BCM_E_NOT_FOUND; 24216 for (i = 0; i < mirror_dest_count; i++) { 24217 if (mirror_dest_list[i] == mirror_dest) { 24218 rv = BCM_E_EXISTS; 24219 break; 24220 } 24221 } 24222 } 24223 24224 if ((BCM_E_NOT_FOUND != rv) && 24225 !((BCM_E_EXISTS == rv) && (replace_flag == 1))) { 24226 return rv; 24227 } 24228 24229 /* Allocate MTP index for mirror destination. */ 24230 BCM_IF_ERROR_RETURN(_bcm_esw_mirror_mtp_reserve(unit, mirror_dest, 24231 BCM_MIRROR_PORT_INGRESS, &mtp_index)); 24232 24233 /* The ref_count of mtp_index for same src_port doesn't need to get increased twice */ 24234 if ((BCM_E_EXISTS == rv) && (replace_flag == 1)) { 24235 if (MIRROR_MTP_METHOD_IS_DIRECTED_FLEXIBLE(unit)) { 24236 if ((rv == BCM_E_EXISTS) && 24237 (MIRROR_CONFIG_ING_MTP_DEST(unit, mtp_index) == mirror_dest)) { 24238 MIRROR_CONFIG_ING_MTP_REF_COUNT(unit, mtp_index)--; 24239 } 24240 } else { 24241 if ((rv == BCM_E_EXISTS) && 24242 (MIRROR_CONFIG_SHARED_MTP_DEST(unit, mtp_index) == mirror_dest)) { 24243 MIRROR_CONFIG_SHARED_MTP_REF_COUNT(unit, mtp_index)--; 24244 } 24245 } 24246 } 24247 24248 rv = READ_SFLOW_ING_MIRROR_CONFIGr(unit, ®_val); 24249 if (BCM_SUCCESS(rv)) { 24250 mc_enable = soc_reg_field_get(unit, SFLOW_ING_MIRROR_CONFIGr, 24251 reg_val, MIRROR_ENABLEf); 24252 24253 if (MIRROR_MTP_METHOD_IS_DIRECTED_FLEXIBLE(unit)) { 24254 rv = _bcm_xgs3_mtp_type_slot_reserve(unit, 24255 BCM_MIRROR_PORT_INGRESS, 24256 mc_enable, 0, 24257 BCM_MTP_SLOT_TYPE_SFLOW, 24258 mtp_index, &mtp_slot); 24259 } else { 24260 /* Otherwise the slot and index is 1-1 */ 24261 mtp_slot = mtp_index; 24262 } 24263 24264 24265 if (BCM_SUCCESS(rv)) { 24266 if (mc_enable & (1 << mtp_slot)) { 24267 if (replace_flag == 1) { 24268 rv = BCM_E_NONE; 24269 } else { 24270 rv = BCM_E_EXISTS; 24271 } 24272 } else { 24273 24274 mc_enable |= 1 << mtp_slot; 24275 soc_reg_field_set(unit, SFLOW_ING_MIRROR_CONFIGr, ®_val, 24276 MIRROR_ENABLEf, mc_enable); 24277 soc_reg_field_set(unit, SFLOW_ING_MIRROR_CONFIGr, ®_val, 24278 mtp_idxf[mtp_slot], mtp_index); 24279 rv = WRITE_SFLOW_ING_MIRROR_CONFIGr(unit, reg_val); 24280 } 24281 } 24282 } 24283 if (BCM_FAILURE(rv)) { 24284 _bcm_esw_mirror_mtp_unreserve(unit, mtp_index, FALSE, 24285 BCM_MIRROR_PORT_INGRESS); 24286 } 24287 /* Enable mirroring on a port. */ 24288 if (BCM_SUCCESS(rv)) { 24289 if(!SOC_IS_XGS3_SWITCH(unit) || 24290 (BCM_MIRROR_DISABLE == MIRROR_CONFIG_MODE(unit))) { 24291 rv = _bcm_esw_mirror_enable(unit); 24292 MIRROR_CONFIG_MODE(unit) = BCM_MIRROR_L2; 24293 } 24294 } 24295 24296 if (BCM_SUCCESS(rv)) { 24297 #ifdef BCM_WARM_BOOT_SUPPORT 24298 SOC_CONTROL_LOCK(unit); 24299 SOC_CONTROL(unit)->scache_dirty = 1; 24300 SOC_CONTROL_UNLOCK(unit); 24301 #endif 24302 } 24303 24304 return rv; 24305 #else 24306 return BCM_E_UNAVAIL; 24307 #endif 24308 } 24309 24310 STATIC int 24311 _bcm_mirror_int_dest_add(int unit, uint32 flags, bcm_gport_t mirror_dest) 24312 { 24313 #if defined(BCM_TOMAHAWK3_SUPPORT) 24314 int rv; 24315 uint32 reg_val; 24316 int i; 24317 int mc_enable; 24318 int mtp_index; 24319 soc_field_t mtp_idxf[BCM_MIRROR_MTP_COUNT] = { 24320 MTP_INDEX0f,MTP_INDEX1f,MTP_INDEX2f,MTP_INDEX3f}; 24321 bcm_gport_t mirror_dest_list[BCM_MIRROR_MTP_COUNT]; 24322 int mirror_dest_count; 24323 int mtp_slot; /* MTP type value */ 24324 uint32 replace_flag = 0; 24325 uint32 check_flags = BCM_MIRROR_PORT_INGRESS | BCM_MIRROR_PORT_INT; 24326 bcm_mirror_destination_t mirr_dest; 24327 24328 if (!soc_feature(unit, soc_feature_inband_network_telemetry)) { 24329 return BCM_E_UNAVAIL; 24330 } 24331 if (!soc_feature(unit, soc_feature_mirror_flexible)) { 24332 return BCM_E_UNAVAIL; 24333 } 24334 24335 /* only support BCM_MIRROR_PORT_INGRESS */ 24336 if (flags & ~check_flags) { 24337 return BCM_E_UNAVAIL; 24338 } 24339 24340 rv = bcm_esw_mirror_destination_get(unit, mirror_dest, &mirr_dest); 24341 if (BCM_FAILURE(rv)) { 24342 return (rv); 24343 } 24344 24345 replace_flag = (mirr_dest.flags & BCM_MIRROR_DEST_REPLACE) ? 1:0; 24346 24347 rv = bcm_esw_mirror_port_dest_get(unit, -1, 24348 flags, 24349 BCM_MIRROR_MTP_COUNT, 24350 mirror_dest_list, &mirror_dest_count); 24351 if (BCM_SUCCESS(rv)) { 24352 rv = BCM_E_NOT_FOUND; 24353 for (i = 0; i < mirror_dest_count; i++) { 24354 if (mirror_dest_list[i] == mirror_dest) { 24355 rv = BCM_E_EXISTS; 24356 break; 24357 } 24358 } 24359 } 24360 24361 if ((BCM_E_NOT_FOUND != rv) && 24362 !((BCM_E_EXISTS == rv) && (replace_flag == 1))) { 24363 return rv; 24364 } 24365 24366 /* Allocate MTP index for mirror destination. */ 24367 BCM_IF_ERROR_RETURN(_bcm_esw_mirror_mtp_reserve(unit, mirror_dest, 24368 BCM_MIRROR_PORT_INGRESS, &mtp_index)); 24369 24370 /* The ref_count of mtp_index for same src_port doesn't need to get increased twice */ 24371 if ((BCM_E_EXISTS == rv) && (replace_flag == 1)) { 24372 if (MIRROR_MTP_METHOD_IS_DIRECTED_FLEXIBLE(unit)) { 24373 if ((rv == BCM_E_EXISTS) && 24374 (MIRROR_CONFIG_ING_MTP_DEST(unit, mtp_index) == mirror_dest)) { 24375 MIRROR_CONFIG_ING_MTP_REF_COUNT(unit, mtp_index)--; 24376 } 24377 } else { 24378 if ((rv == BCM_E_EXISTS) && 24379 (MIRROR_CONFIG_SHARED_MTP_DEST(unit, mtp_index) == mirror_dest)) { 24380 MIRROR_CONFIG_SHARED_MTP_REF_COUNT(unit, mtp_index)--; 24381 } 24382 } 24383 } 24384 24385 rv = READ_INT_PROCESS_CONFIGr(unit, ®_val); 24386 if (BCM_SUCCESS(rv)) { 24387 mc_enable = soc_reg_field_get(unit, INT_PROCESS_CONFIGr, 24388 reg_val, MIRROR_ENABLEf); 24389 24390 if (MIRROR_MTP_METHOD_IS_DIRECTED_FLEXIBLE(unit)) { 24391 rv = _bcm_xgs3_mtp_type_slot_reserve(unit, 24392 BCM_MIRROR_PORT_INGRESS, 24393 mc_enable, 0, 24394 BCM_MTP_SLOT_TYPE_INT, 24395 mtp_index, &mtp_slot); 24396 } else { 24397 /* Otherwise the slot and index is 1-1 */ 24398 mtp_slot = mtp_index; 24399 } 24400 24401 24402 if (BCM_SUCCESS(rv)) { 24403 if (mc_enable & (1 << mtp_slot)) { 24404 if (replace_flag == 1) { 24405 rv = BCM_E_NONE; 24406 } else { 24407 rv = BCM_E_EXISTS; 24408 } 24409 } else { 24410 24411 mc_enable |= 1 << mtp_slot; 24412 soc_reg_field_set(unit, INT_PROCESS_CONFIGr, ®_val, 24413 MIRROR_ENABLEf, mc_enable); 24414 soc_reg_field_set(unit, INT_PROCESS_CONFIGr, ®_val, 24415 mtp_idxf[mtp_slot], mtp_index); 24416 rv = WRITE_INT_PROCESS_CONFIGr(unit, reg_val); 24417 } 24418 } 24419 } 24420 if (BCM_FAILURE(rv)) { 24421 _bcm_esw_mirror_mtp_unreserve(unit, mtp_index, FALSE, 24422 BCM_MIRROR_PORT_INGRESS); 24423 } 24424 /* Enable mirroring on a port. */ 24425 if (BCM_SUCCESS(rv)) { 24426 if(!SOC_IS_XGS3_SWITCH(unit) || 24427 (BCM_MIRROR_DISABLE == MIRROR_CONFIG_MODE(unit))) { 24428 rv = _bcm_esw_mirror_enable(unit); 24429 MIRROR_CONFIG_MODE(unit) = BCM_MIRROR_L2; 24430 } 24431 } 24432 24433 if (BCM_SUCCESS(rv)) { 24434 #ifdef BCM_WARM_BOOT_SUPPORT 24435 SOC_CONTROL_LOCK(unit); 24436 SOC_CONTROL(unit)->scache_dirty = 1; 24437 SOC_CONTROL_UNLOCK(unit); 24438 #endif 24439 } 24440 24441 return rv; 24442 #else 24443 return BCM_E_UNAVAIL; 24444 #endif 24445 } 24446 24447 STATIC int 24448 _bcm_mirror_elephant_dest_add(int unit, uint32 flags, bcm_gport_t mirror_dest) 24449 { 24450 #if defined(BCM_TOMAHAWK3_SUPPORT) 24451 int rv; 24452 uint32 reg_val; 24453 int i; 24454 int mc_enable; 24455 int mtp_index; 24456 soc_field_t mtp_idxf[BCM_MIRROR_MTP_COUNT] = { 24457 MTP_INDEX0f,MTP_INDEX1f,MTP_INDEX2f,MTP_INDEX3f}; 24458 bcm_gport_t mirror_dest_list[BCM_MIRROR_MTP_COUNT]; 24459 int mirror_dest_count; 24460 int mtp_slot; /* MTP type value */ 24461 uint32 replace_flag = 0; 24462 uint32 check_flags = BCM_MIRROR_PORT_INGRESS | BCM_MIRROR_PORT_ELEPHANT; 24463 bcm_mirror_destination_t mirr_dest; 24464 24465 if (!soc_feature(unit, soc_feature_hw_etrap)) { 24466 return BCM_E_UNAVAIL; 24467 } 24468 if (!soc_feature(unit, soc_feature_mirror_flexible)) { 24469 return BCM_E_UNAVAIL; 24470 } 24471 24472 /* only support BCM_MIRROR_PORT_INGRESS */ 24473 if (flags & ~check_flags) { 24474 return BCM_E_UNAVAIL; 24475 } 24476 24477 rv = bcm_esw_mirror_destination_get(unit, mirror_dest, &mirr_dest); 24478 if (BCM_FAILURE(rv)) { 24479 return (rv); 24480 } 24481 24482 replace_flag = (mirr_dest.flags & BCM_MIRROR_DEST_REPLACE) ? 1:0; 24483 24484 rv = bcm_esw_mirror_port_dest_get(unit, -1, flags, 24485 BCM_MIRROR_MTP_COUNT, mirror_dest_list, 24486 &mirror_dest_count); 24487 if (BCM_SUCCESS(rv)) { 24488 rv = BCM_E_NOT_FOUND; 24489 for (i = 0; i < mirror_dest_count; i++) { 24490 if (mirror_dest_list[i] == mirror_dest) { 24491 rv = BCM_E_EXISTS; 24492 break; 24493 } 24494 } 24495 } 24496 24497 if ((BCM_E_NOT_FOUND != rv) && 24498 !((BCM_E_EXISTS == rv) && (replace_flag == 1))) { 24499 return rv; 24500 } 24501 24502 /* Allocate MTP index for mirror destination. */ 24503 BCM_IF_ERROR_RETURN(_bcm_esw_mirror_mtp_reserve(unit, mirror_dest, 24504 BCM_MIRROR_PORT_INGRESS, 24505 &mtp_index)); 24506 24507 /* The ref_count of mtp_index for same src_port doesn't need to get increased twice */ 24508 if ((BCM_E_EXISTS == rv) && (replace_flag == 1)) { 24509 if (MIRROR_MTP_METHOD_IS_DIRECTED_FLEXIBLE(unit)) { 24510 if ((rv == BCM_E_EXISTS) && 24511 (MIRROR_CONFIG_ING_MTP_DEST(unit, mtp_index) == mirror_dest)) { 24512 MIRROR_CONFIG_ING_MTP_REF_COUNT(unit, mtp_index)--; 24513 } 24514 } else { 24515 if ((rv == BCM_E_EXISTS) && 24516 (MIRROR_CONFIG_SHARED_MTP_DEST(unit, mtp_index) == mirror_dest)) { 24517 MIRROR_CONFIG_SHARED_MTP_REF_COUNT(unit, mtp_index)--; 24518 } 24519 } 24520 } 24521 24522 rv = READ_ETRAP_MONITOR_MIRROR_CONFIGr(unit, ®_val); 24523 if (BCM_SUCCESS(rv)) { 24524 mc_enable = soc_reg_field_get(unit, ETRAP_MONITOR_MIRROR_CONFIGr, 24525 reg_val, MIRROR_ENABLEf); 24526 24527 if (MIRROR_MTP_METHOD_IS_DIRECTED_FLEXIBLE(unit)) { 24528 rv = _bcm_xgs3_mtp_type_slot_reserve(unit, 24529 BCM_MIRROR_PORT_INGRESS, 24530 mc_enable, 0, 24531 BCM_MTP_SLOT_TYPE_ELEPHANT, 24532 mtp_index, &mtp_slot); 24533 } else { 24534 /* Otherwise the slot and index is 1-1 */ 24535 mtp_slot = mtp_index; 24536 } 24537 24538 24539 if (BCM_SUCCESS(rv)) { 24540 if (mc_enable & (1 << mtp_slot)) { 24541 if (replace_flag == 1) { 24542 rv = BCM_E_NONE; 24543 } else { 24544 rv = BCM_E_EXISTS; 24545 } 24546 } else { 24547 mc_enable |= 1 << mtp_slot; 24548 soc_reg_field_set(unit, ETRAP_MONITOR_MIRROR_CONFIGr, ®_val, 24549 MIRROR_ENABLEf, mc_enable); 24550 soc_reg_field_set(unit, ETRAP_MONITOR_MIRROR_CONFIGr, ®_val, 24551 mtp_idxf[mtp_slot], mtp_index); 24552 rv = WRITE_ETRAP_MONITOR_MIRROR_CONFIGr(unit, reg_val); 24553 } 24554 } 24555 } 24556 if (BCM_FAILURE(rv)) { 24557 _bcm_esw_mirror_mtp_unreserve(unit, mtp_index, FALSE, 24558 BCM_MIRROR_PORT_INGRESS); 24559 } 24560 /* Enable mirroring on a port. */ 24561 if (BCM_SUCCESS(rv)) { 24562 if(!SOC_IS_XGS3_SWITCH(unit) || 24563 (BCM_MIRROR_DISABLE == MIRROR_CONFIG_MODE(unit))) { 24564 rv = _bcm_esw_mirror_enable(unit); 24565 MIRROR_CONFIG_MODE(unit) = BCM_MIRROR_L2; 24566 } 24567 } 24568 24569 if (BCM_SUCCESS(rv)) { 24570 #ifdef BCM_WARM_BOOT_SUPPORT 24571 SOC_CONTROL_LOCK(unit); 24572 SOC_CONTROL(unit)->scache_dirty = 1; 24573 SOC_CONTROL_UNLOCK(unit); 24574 #endif 24575 } 24576 24577 return rv; 24578 #else 24579 return BCM_E_UNAVAIL; 24580 #endif 24581 } 24582 24583 /* 24584 * Function: 24585 * _bcm_mirror_dlb_monitor_dest_add 24586 * Purpose: 24587 * This function programs hardware for processing non tunneled mirrored 24588 * packets to which payload zeroing or truncating can be applied 24589 * Parameters: 24590 * unit - (IN) BCM device number 24591 * flags - (IN) Mirror direction flags 24592 * mirror_dest - (IN) MTP port 24593 * Returns: 24594 * BCM_E_XXX 24595 */ 24596 STATIC int 24597 _bcm_mirror_dlb_monitor_dest_add(int unit, uint32 flags, 24598 bcm_gport_t mirror_dest) 24599 { 24600 #if defined(BCM_TOMAHAWK3_SUPPORT) 24601 int rv; 24602 uint32 reg_val; 24603 int i; 24604 int mc_enable; 24605 int mtp_index; 24606 soc_field_t mtp_idxf[BCM_MIRROR_MTP_COUNT] = { 24607 MTP_INDEX0f,MTP_INDEX1f,MTP_INDEX2f,MTP_INDEX3f}; 24608 bcm_gport_t mirror_dest_list[BCM_MIRROR_MTP_COUNT]; 24609 int mirror_dest_count; 24610 int mtp_slot; /* MTP type value */ 24611 uint32 replace_flag = 0; 24612 uint32 check_flags = BCM_MIRROR_PORT_INGRESS | 24613 BCM_MIRROR_PORT_DLB_MONITOR; 24614 bcm_mirror_destination_t mirr_dest; 24615 24616 if (!soc_feature(unit, soc_feature_dlb_flow_monitoring)) { 24617 return BCM_E_UNAVAIL; 24618 } 24619 if (!soc_feature(unit, soc_feature_mirror_flexible)) { 24620 return BCM_E_UNAVAIL; 24621 } 24622 24623 if (flags & ~check_flags) { 24624 return BCM_E_UNAVAIL; 24625 } 24626 24627 rv = bcm_esw_mirror_destination_get(unit, mirror_dest, &mirr_dest); 24628 if (BCM_FAILURE(rv)) { 24629 return (rv); 24630 } 24631 24632 replace_flag = (mirr_dest.flags & BCM_MIRROR_DEST_REPLACE) ? 1 : 0; 24633 24634 rv = bcm_esw_mirror_port_dest_get(unit, -1, 24635 flags, 24636 BCM_MIRROR_MTP_COUNT, 24637 mirror_dest_list, &mirror_dest_count); 24638 if (BCM_SUCCESS(rv)) { 24639 rv = BCM_E_NOT_FOUND; 24640 for (i = 0; i < mirror_dest_count; i++) { 24641 if (mirror_dest_list[i] == mirror_dest) { 24642 rv = BCM_E_EXISTS; 24643 break; 24644 } 24645 } 24646 } 24647 24648 if ((BCM_E_NOT_FOUND != rv) && 24649 !((BCM_E_EXISTS == rv) && (replace_flag == 1))) { 24650 return rv; 24651 } 24652 24653 /* Allocate MTP index for mirror destination. */ 24654 BCM_IF_ERROR_RETURN(_bcm_esw_mirror_mtp_reserve(unit, mirror_dest, 24655 BCM_MIRROR_PORT_INGRESS, &mtp_index)); 24656 24657 /* The ref_count of mtp_index for same src_port doesn't need to get increased twice */ 24658 if ((BCM_E_EXISTS == rv) && (replace_flag == 1)) { 24659 /* Based on ing/egr support, macros MIRROR_CONFIG_ING_MTP_DEST and others will change to have egress too (if supported) */ 24660 if (MIRROR_MTP_METHOD_IS_DIRECTED_FLEXIBLE(unit)) { 24661 if ((rv == BCM_E_EXISTS) && 24662 (MIRROR_CONFIG_ING_MTP_DEST(unit, mtp_index) == mirror_dest)) { 24663 MIRROR_CONFIG_ING_MTP_REF_COUNT(unit, mtp_index)--; 24664 } 24665 } else { 24666 if ((rv == BCM_E_EXISTS) && 24667 (MIRROR_CONFIG_SHARED_MTP_DEST(unit, mtp_index) == mirror_dest)) { 24668 MIRROR_CONFIG_SHARED_MTP_REF_COUNT(unit, mtp_index)--; 24669 } 24670 } 24671 } 24672 24673 rv = READ_DLB_ECMP_MONITOR_MIRROR_CONFIGr(unit, ®_val); 24674 if (BCM_SUCCESS(rv)) { 24675 mc_enable = soc_reg_field_get(unit, DLB_ECMP_MONITOR_MIRROR_CONFIGr, 24676 reg_val, MIRROR_ENABLEf); 24677 24678 if (MIRROR_MTP_METHOD_IS_DIRECTED_FLEXIBLE(unit)) { 24679 rv = _bcm_xgs3_mtp_type_slot_reserve(unit, 24680 BCM_MIRROR_PORT_INGRESS, 24681 mc_enable, 0, 24682 BCM_MTP_SLOT_TYPE_DLB_MONITOR, 24683 mtp_index, &mtp_slot); 24684 } else { 24685 /* Otherwise the slot and index is 1-1 */ 24686 mtp_slot = mtp_index; 24687 } 24688 24689 if (BCM_SUCCESS(rv)) { 24690 if (mc_enable & (1 << mtp_slot)) { 24691 if (replace_flag == 1) { 24692 rv = BCM_E_NONE; 24693 } else { 24694 rv = BCM_E_EXISTS; 24695 } 24696 } else { 24697 24698 mc_enable |= 1 << mtp_slot; 24699 soc_reg_field_set(unit, DLB_ECMP_MONITOR_MIRROR_CONFIGr, ®_val, 24700 MIRROR_ENABLEf, mc_enable); 24701 soc_reg_field_set(unit, DLB_ECMP_MONITOR_MIRROR_CONFIGr, ®_val, 24702 mtp_idxf[mtp_slot], mtp_index); 24703 rv = WRITE_DLB_ECMP_MONITOR_MIRROR_CONFIGr(unit, reg_val); 24704 } 24705 } 24706 } 24707 if (BCM_FAILURE(rv)) { 24708 _bcm_esw_mirror_mtp_unreserve(unit, mtp_index, FALSE, 24709 BCM_MIRROR_PORT_INGRESS); 24710 } 24711 /* Enable mirroring on a port. */ 24712 if (BCM_SUCCESS(rv)) { 24713 if(!SOC_IS_XGS3_SWITCH(unit) || 24714 (BCM_MIRROR_DISABLE == MIRROR_CONFIG_MODE(unit))) { 24715 rv = _bcm_esw_mirror_enable(unit); 24716 MIRROR_CONFIG_MODE(unit) = BCM_MIRROR_L2; 24717 } 24718 } 24719 24720 if (BCM_SUCCESS(rv)) { 24721 #ifdef BCM_WARM_BOOT_SUPPORT 24722 SOC_CONTROL_LOCK(unit); 24723 SOC_CONTROL(unit)->scache_dirty = 1; 24724 SOC_CONTROL_UNLOCK(unit); 24725 #endif 24726 } 24727 24728 return rv; 24729 #else 24730 return BCM_E_UNAVAIL; 24731 #endif 24732 } 24733 24734 STATIC int 24735 _bcm_mirror_dlb_monitor_dest_delete(int unit, uint32 flags, bcm_gport_t mirror_dest) 24736 { 24737 #if defined(BCM_TOMAHAWK3_SUPPORT) 24738 int mc_enable; /* Mirror enable check */ 24739 int mtp_index = -1; /* Mirror to port index */ 24740 uint32 reg_val; 24741 int mtp_slot; 24742 uint32 check_flags = BCM_MIRROR_PORT_INGRESS | BCM_MIRROR_PORT_DLB_MONITOR; 24743 24744 soc_field_t mtp_idxf[BCM_MIRROR_MTP_COUNT] = { 24745 MTP_INDEX0f, MTP_INDEX1f, MTP_INDEX2f, MTP_INDEX3f}; 24746 24747 if (!soc_feature(unit, soc_feature_dlb_flow_monitoring)) { 24748 return BCM_E_UNAVAIL; 24749 } 24750 24751 if (!soc_feature(unit, soc_feature_mirror_flexible)) { 24752 return BCM_E_UNAVAIL; 24753 } 24754 24755 /* only support BCM_MIRROR_PORT_INGRESS */ 24756 if (flags & ~check_flags) { 24757 return BCM_E_UNAVAIL; 24758 } 24759 24760 /* Look for used MTP index */ 24761 if (!MIRROR_MTP_METHOD_IS_DIRECTED_FLEXIBLE(unit)) { 24762 BCM_IF_ERROR_RETURN(_bcm_tr2_mirror_shared_mtp_match(unit, 24763 mirror_dest, FALSE, &mtp_index)); 24764 } else { 24765 BCM_IF_ERROR_RETURN(_bcm_esw_mirror_ingress_mtp_match(unit, 24766 mirror_dest, &mtp_index)); 24767 } 24768 24769 BCM_IF_ERROR_RETURN(READ_DLB_ECMP_MONITOR_MIRROR_CONFIGr(unit, ®_val)); 24770 mc_enable = soc_reg_field_get(unit, DLB_ECMP_MONITOR_MIRROR_CONFIGr, 24771 reg_val, MIRROR_ENABLEf); 24772 24773 if (MIRROR_MTP_METHOD_IS_DIRECTED_FLEXIBLE(unit)) { 24774 BCM_IF_ERROR_RETURN(_bcm_xgs3_mtp_index_port_slot_get(unit, 0, 24775 mc_enable, FALSE, mtp_index, BCM_MTP_SLOT_TYPE_DLB_MONITOR, 24776 &mtp_slot)); 24777 } else { 24778 /* Otherwise the slot and index is 1-1 */ 24779 mtp_slot = mtp_index; 24780 } 24781 24782 if (mc_enable & (1 << mtp_slot)) { 24783 mc_enable &= ~(1 << mtp_slot); 24784 soc_reg_field_set(unit, DLB_ECMP_MONITOR_MIRROR_CONFIGr, 24785 ®_val, MIRROR_ENABLEf, mc_enable); 24786 soc_reg_field_set(unit, DLB_ECMP_MONITOR_MIRROR_CONFIGr, ®_val, 24787 mtp_idxf[mtp_slot], 0); 24788 BCM_IF_ERROR_RETURN(WRITE_DLB_ECMP_MONITOR_MIRROR_CONFIGr(unit, reg_val)); 24789 } 24790 24791 if (MIRROR_MTP_METHOD_IS_DIRECTED_FLEXIBLE(unit)) { 24792 BCM_IF_ERROR_RETURN(_bcm_xgs3_mtp_type_slot_unreserve(unit, 24793 BCM_MIRROR_PORT_INGRESS, 0, 24794 BCM_MTP_SLOT_TYPE_DLB_MONITOR, 24795 mtp_index)); 24796 } 24797 24798 /* Free MTP index for mirror destination */ 24799 BCM_IF_ERROR_RETURN(_bcm_esw_mirror_mtp_unreserve(unit, mtp_index, TRUE, 24800 BCM_MIRROR_PORT_INGRESS)); 24801 return BCM_E_NONE; 24802 #else 24803 return BCM_E_UNAVAIL; 24804 #endif 24805 } 24806 24807 STATIC int 24808 _bcm_mirror_dlb_monitor_dest_get(int unit, uint32 flags, int mirror_dest_size, 24809 bcm_gport_t *mirror_dest, 24810 int *mirror_dest_count) 24811 { 24812 #if defined(BCM_TOMAHAWK3_SUPPORT) 24813 uint32 reg_val; 24814 int mc_enable; 24815 int mtp_index; 24816 int index; 24817 int mtp_slot, mtp_bit; 24818 int i; 24819 uint32 index_val[BCM_MIRROR_MTP_COUNT]; 24820 uint32 check_flags = BCM_MIRROR_PORT_INGRESS | BCM_MIRROR_PORT_DLB_MONITOR; 24821 24822 soc_field_t mtp_idxf[BCM_MIRROR_MTP_COUNT] = { 24823 MTP_INDEX0f, MTP_INDEX1f, MTP_INDEX2f, MTP_INDEX3f}; 24824 24825 if (!soc_feature(unit, soc_feature_dlb_flow_monitoring)) { 24826 return BCM_E_UNAVAIL; 24827 } 24828 24829 /* only support BCM_MIRROR_PORT_INGRESS */ 24830 if (flags & ~check_flags) { 24831 return BCM_E_UNAVAIL; 24832 } 24833 24834 BCM_IF_ERROR_RETURN(READ_DLB_ECMP_MONITOR_MIRROR_CONFIGr(unit, ®_val)); 24835 mc_enable = soc_reg_field_get(unit, DLB_ECMP_MONITOR_MIRROR_CONFIGr, 24836 reg_val, MIRROR_ENABLEf); 24837 *mirror_dest_count = 0; 24838 24839 /* Read mirror control structure to get programmed mtp indexes */ 24840 for (i = 0; i < BCM_MIRROR_MTP_COUNT; i++) { 24841 index_val[i] = soc_reg_field_get(unit, DLB_ECMP_MONITOR_MIRROR_CONFIGr, 24842 reg_val, mtp_idxf[i]); 24843 } 24844 index = 0; 24845 /* Read mirror control register to compare programmed mtp indexes */ 24846 BCM_MIRROR_MTP_ITER(MIRROR_CONFIG_MTP_DEV_MASK(unit), mtp_slot) { 24847 mtp_bit = 1 << mtp_slot; 24848 /* Check if MTP slot is enabled on port */ 24849 if (!(mc_enable & mtp_bit)) { 24850 continue; 24851 } 24852 /* MTP index is enabled and direction matches */ 24853 mtp_index = index_val[mtp_slot]; 24854 24855 if ( MIRROR_MTP_METHOD_IS_DIRECTED_FLEXIBLE(unit)) { 24856 mirror_dest[index] = 24857 MIRROR_CONFIG_ING_MTP_DEST(unit, mtp_index); 24858 } else { 24859 mirror_dest[index] = 24860 MIRROR_CONFIG_SHARED_MTP_DEST(unit, mtp_index); 24861 } 24862 index++; 24863 } 24864 *mirror_dest_count = index; 24865 24866 return BCM_E_NONE; 24867 #else 24868 return BCM_E_UNAVAIL; 24869 #endif 24870 } 24871 24872 /* 24873 * Function: 24874 * bcm_esw_mirror_port_dest_add 24875 * Purpose: 24876 * Add mirroring destination to a port. 24877 * Parameters: 24878 * unit - (IN) BCM device number. 24879 * port - (IN) Port mirrored port. 24880 * flags - (IN) BCM_MIRROR_PORT_XXX flags. 24881 * mirror_dest - (IN) Mirroring destination gport. 24882 * Returns: 24883 * BCM_X_XXX 24884 */ 24885 int 24886 bcm_esw_mirror_port_dest_add(int unit, bcm_port_t port, 24887 uint32 flags, bcm_gport_t mirror_dest) 24888 { 24889 int rv = BCM_E_NONE; /* Operation return status. */ 24890 int orig_gport; 24891 int vp = VP_PORT_INVALID; 24892 int vp_mirror = FALSE; 24893 bcm_gport_t mirror_dest_list[BCM_MIRROR_MTP_COUNT]; 24894 int mirror_dest_count, mtp; 24895 uint32 replace_flag = 0; 24896 bcm_mirror_destination_t mirr_dest; 24897 24898 /* Initialization check. */ 24899 if (0 == MIRROR_INIT(unit)) { 24900 return BCM_E_INIT; 24901 } 24902 orig_gport = port; 24903 24904 if (-1 != port) { 24905 if (BCM_GPORT_IS_SET(port)) { 24906 24907 rv = _bcm_tr2_mirror_vp_port_get(unit, port, 24908 &vp, &port); 24909 if ((rv != BCM_E_NONE) && (rv != BCM_E_NOT_FOUND)) { 24910 return rv; 24911 } 24912 rv = BCM_E_NONE; 24913 24914 if (vp == VP_PORT_INVALID) { 24915 #ifdef BCM_TRIDENT2PLUS_SUPPORT 24916 if (soc_feature(unit, soc_feature_hgproxy_subtag_coe) && 24917 _BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, port)) { 24918 } else 24919 #endif 24920 { 24921 BCM_IF_ERROR_RETURN(bcm_esw_port_local_get(unit, port, &port)); 24922 } 24923 } 24924 } 24925 24926 if (vp == VP_PORT_INVALID && !BCM_GPORT_IS_SET(port)) { 24927 if (!SOC_PORT_VALID(unit, port)) { 24928 return (BCM_E_PORT); 24929 } 24930 24931 if (IS_CPU_PORT(unit, port) && 24932 !soc_feature(unit, soc_feature_cpuport_mirror)) { 24933 return (BCM_E_PORT); 24934 } 24935 } 24936 } 24937 24938 if (!soc_feature(unit, soc_feature_egr_mirror_true) && 24939 (flags & BCM_MIRROR_PORT_EGRESS_TRUE)) { 24940 return (BCM_E_PARAM); 24941 } 24942 24943 if (!(flags & (BCM_MIRROR_PORT_INGRESS | BCM_MIRROR_PORT_EGRESS | 24944 BCM_MIRROR_PORT_EGRESS_TRUE))) { 24945 return (BCM_E_PARAM); 24946 } 24947 24948 if (0 == BCM_GPORT_IS_MIRROR(mirror_dest)) { 24949 return (BCM_E_PARAM); 24950 } 24951 24952 MIRROR_LOCK(unit); 24953 24954 /* If destination is not valid */ 24955 if (0 == MIRROR_DEST_REF_COUNT(unit, mirror_dest)) { 24956 MIRROR_UNLOCK(unit); 24957 return (BCM_E_NOT_FOUND); 24958 } 24959 24960 MIRROR_UNLOCK(unit); 24961 24962 if (flags & BCM_MIRROR_PORT_SFLOW) { 24963 MIRROR_LOCK(unit); 24964 rv = _bcm_mirror_sflow_dest_add(unit, flags, mirror_dest); 24965 MIRROR_UNLOCK(unit); 24966 return rv; 24967 } 24968 24969 if (flags & BCM_MIRROR_PORT_INT) { 24970 MIRROR_LOCK(unit); 24971 rv = _bcm_mirror_int_dest_add(unit, flags, mirror_dest); 24972 MIRROR_UNLOCK(unit); 24973 return rv; 24974 } 24975 24976 if (flags & BCM_MIRROR_PORT_ELEPHANT) { 24977 MIRROR_LOCK(unit); 24978 rv = _bcm_mirror_elephant_dest_add(unit, flags, mirror_dest); 24979 MIRROR_UNLOCK(unit); 24980 return rv; 24981 } 24982 24983 if (flags & BCM_MIRROR_PORT_DLB_MONITOR) { 24984 MIRROR_LOCK(unit); 24985 rv = _bcm_mirror_dlb_monitor_dest_add(unit, flags, mirror_dest); 24986 MIRROR_UNLOCK(unit); 24987 return rv; 24988 } 24989 24990 /* check supported conditions for vp mirroring */ 24991 if (vp != VP_PORT_INVALID) { 24992 #ifdef BCM_TRIUMPH2_SUPPORT 24993 if (soc_feature(unit, soc_feature_mirror_flexible) && 24994 !MIRROR_MTP_METHOD_IS_NON_DIRECTED(unit) && 24995 (!(flags & BCM_MIRROR_PORT_EGRESS_TRUE))) { 24996 vp_mirror = TRUE; 24997 } 24998 #endif 24999 if (vp_mirror == FALSE) { 25000 return BCM_E_UNAVAIL; 25001 } 25002 } 25003 25004 /* Directed mirroring support check. */ 25005 if (MIRROR_MTP_METHOD_IS_NON_DIRECTED(unit)) { 25006 /* No mirroring to a trunk. */ 25007 if (BCM_GPORT_IS_TRUNK(MIRROR_DEST_GPORT(unit, mirror_dest))) { 25008 return (BCM_E_UNAVAIL); 25009 } 25010 25011 if (soc_feature(unit, soc_feature_mirror_flexible)) { 25012 if (0 != (flags & BCM_MIRROR_PORT_INGRESS)) { 25013 if (MIRROR_CONFIG_SHARED_MTP_REF_COUNT(unit, 0)) { 25014 if (MIRROR_CONFIG_SHARED_MTP_DEST(unit, 0) != 25015 mirror_dest) { 25016 return (BCM_E_RESOURCE); 25017 } 25018 } 25019 } 25020 if (0 != (flags & BCM_MIRROR_PORT_EGRESS)) { 25021 if (MIRROR_CONFIG_SHARED_MTP_REF_COUNT(unit, 25022 BCM_MIRROR_MTP_FLEX_EGRESS_D15_INDEX)) { 25023 if (MIRROR_CONFIG_SHARED_MTP_DEST(unit, 25024 BCM_MIRROR_MTP_FLEX_EGRESS_D15_INDEX) != 25025 mirror_dest) { 25026 return (BCM_E_RESOURCE); 25027 } 25028 } 25029 } 25030 } else { 25031 /* Single mirroring destination for ingress & egress. */ 25032 if (MIRROR_CONFIG_ING_MTP_REF_COUNT(unit, 0)) { 25033 if (MIRROR_CONFIG_ING_MTP_DEST(unit, 0) != mirror_dest) { 25034 return (BCM_E_RESOURCE); 25035 } 25036 } 25037 if (MIRROR_CONFIG_EGR_MTP_REF_COUNT(unit, 0)) { 25038 if (MIRROR_CONFIG_EGR_MTP_DEST(unit, 0) != mirror_dest) { 25039 return (BCM_E_RESOURCE); 25040 } 25041 } 25042 } 25043 25044 /* Some devices do not support non-directed mode */ 25045 if (soc_feature(unit, soc_feature_directed_mirror_only)) { 25046 return (BCM_E_CONFIG); 25047 } 25048 25049 /* True egress mode does not support non directed mirroring */ 25050 if (flags & BCM_MIRROR_PORT_EGRESS_TRUE) { 25051 return (BCM_E_CONFIG); 25052 } 25053 } 25054 25055 MIRROR_LOCK(unit); 25056 25057 sal_memset(&mirr_dest, 0x0, sizeof(mirr_dest)); 25058 rv = bcm_esw_mirror_destination_get(unit, mirror_dest, &mirr_dest); 25059 if (BCM_FAILURE(rv)) { 25060 MIRROR_UNLOCK(unit); 25061 return (rv); 25062 } 25063 25064 replace_flag = (mirr_dest.flags & BCM_MIRROR_DEST_REPLACE) ? 1:0; 25065 25066 if (flags & BCM_MIRROR_PORT_INGRESS) { 25067 if (!MIRROR_MTP_METHOD_IS_NON_DIRECTED(unit)) { 25068 /* Is this port to MTP already configured? */ 25069 if (vp == VP_PORT_INVALID) { 25070 rv = _bcm_esw_mirror_port_dest_search(unit, port, 25071 BCM_MIRROR_PORT_INGRESS, 25072 mirror_dest); 25073 } else { 25074 rv = bcm_esw_mirror_port_dest_get(unit, orig_gport, 25075 BCM_MIRROR_PORT_INGRESS, 25076 BCM_MIRROR_MTP_COUNT, 25077 mirror_dest_list, &mirror_dest_count); 25078 if (BCM_SUCCESS(rv)) { 25079 rv = BCM_E_NOT_FOUND; 25080 for (mtp = 0; mtp < mirror_dest_count; mtp++) { 25081 if (mirror_dest_list[mtp] == mirror_dest) { 25082 rv = BCM_E_EXISTS; 25083 break; 25084 } 25085 } 25086 } 25087 } 25088 25089 if ((BCM_E_NOT_FOUND != rv) && 25090 !((BCM_E_EXISTS == rv) && (replace_flag == 1 || mirr_dest.flags 25091 & BCM_MIRROR_DEST_ID_SHARE))) { 25092 MIRROR_UNLOCK(unit); 25093 return rv; 25094 } 25095 } 25096 25097 rv = _bcm_esw_mirror_port_ingress_dest_add( 25098 unit, 25099 (vp == VP_PORT_INVALID) ? port : orig_gport, 25100 mirror_dest); 25101 } 25102 25103 if (BCM_SUCCESS(rv) && (flags & BCM_MIRROR_PORT_EGRESS)) { 25104 if (!MIRROR_MTP_METHOD_IS_NON_DIRECTED(unit)) { 25105 /* Is this port to MTP already configured? */ 25106 if (vp == VP_PORT_INVALID) { 25107 rv = _bcm_esw_mirror_port_dest_search(unit, port, 25108 BCM_MIRROR_PORT_EGRESS, 25109 mirror_dest); 25110 } else { 25111 rv = bcm_esw_mirror_port_dest_get(unit, orig_gport, 25112 BCM_MIRROR_PORT_EGRESS, 25113 BCM_MIRROR_MTP_COUNT, 25114 mirror_dest_list, &mirror_dest_count); 25115 if (BCM_SUCCESS(rv)) { 25116 rv = BCM_E_NOT_FOUND; 25117 for (mtp = 0; mtp < mirror_dest_count; mtp++) { 25118 if (mirror_dest_list[mtp] == mirror_dest) { 25119 rv = BCM_E_EXISTS; 25120 break; 25121 } 25122 } 25123 } 25124 } 25125 if ((BCM_E_NOT_FOUND == rv) || 25126 ((BCM_E_EXISTS == rv) && (replace_flag == 1 || mirr_dest.flags 25127 & BCM_MIRROR_DEST_ID_SHARE))) { 25128 rv = BCM_E_NONE; 25129 } 25130 } 25131 25132 if (BCM_SUCCESS(rv)) { 25133 rv = _bcm_esw_mirror_port_egress_dest_add( 25134 unit, 25135 (vp == VP_PORT_INVALID) ? port : orig_gport, 25136 mirror_dest); 25137 } 25138 25139 /* Check for operation failure. */ 25140 if (BCM_FAILURE(rv)) { 25141 if (flags & BCM_MIRROR_PORT_INGRESS) { 25142 _bcm_esw_mirror_port_ingress_dest_delete( 25143 unit, 25144 (vp == VP_PORT_INVALID) ? port : orig_gport, 25145 mirror_dest); 25146 } 25147 } 25148 } 25149 25150 #ifdef BCM_TRIUMPH2_SUPPORT 25151 if (BCM_SUCCESS(rv) && (flags & BCM_MIRROR_PORT_EGRESS_TRUE)) { 25152 if (!MIRROR_MTP_METHOD_IS_NON_DIRECTED(unit)) { 25153 /* Is this port to MTP already configured? */ 25154 rv = _bcm_esw_mirror_port_dest_search(unit, port, 25155 BCM_MIRROR_PORT_EGRESS_TRUE, 25156 mirror_dest); 25157 if (BCM_E_NOT_FOUND == rv) { 25158 rv = BCM_E_NONE; 25159 } 25160 } 25161 25162 if (BCM_SUCCESS(rv)) { 25163 rv = _bcm_esw_mirror_port_egress_true_dest_add(unit, port, 25164 mirror_dest); 25165 } 25166 25167 /* Check for operation failure. */ 25168 if (BCM_FAILURE(rv)) { 25169 if (flags & BCM_MIRROR_PORT_INGRESS) { 25170 _bcm_esw_mirror_port_ingress_dest_delete( 25171 unit, 25172 (vp == VP_PORT_INVALID) ? port : orig_gport, 25173 mirror_dest); 25174 } 25175 if (flags & BCM_MIRROR_PORT_EGRESS) { 25176 _bcm_esw_mirror_port_egress_dest_delete( 25177 unit, 25178 (vp == VP_PORT_INVALID) ? port : orig_gport, 25179 mirror_dest); 25180 } 25181 } 25182 } 25183 #endif /* BCM_TRIUMPH2_SUPPORT */ 25184 25185 25186 /* Update stacking mirror destination bitmap. */ 25187 if (vp == VP_PORT_INVALID) { 25188 if (BCM_SUCCESS(rv) && (-1 != port) && 25189 !BCM_GPORT_IS_SET(port) && IS_ST_PORT(unit, port)) { 25190 rv = _bcm_esw_mirror_stacking_dest_update 25191 (unit, port, MIRROR_DEST_GPORT(unit, mirror_dest)); 25192 /* Check for operation failure. */ 25193 if (BCM_FAILURE(rv)) { 25194 if (flags & BCM_MIRROR_PORT_INGRESS) { 25195 _bcm_esw_mirror_port_ingress_dest_delete(unit, port, 25196 mirror_dest); 25197 } 25198 if (flags & BCM_MIRROR_PORT_EGRESS) { 25199 _bcm_esw_mirror_port_egress_dest_delete(unit, port, 25200 mirror_dest); 25201 } 25202 #ifdef BCM_TRIUMPH2_SUPPORT 25203 if (flags & BCM_MIRROR_PORT_EGRESS_TRUE) { 25204 _bcm_esw_mirror_port_egress_true_dest_delete(unit, port, 25205 mirror_dest); 25206 } 25207 #endif /* BCM_TRIUMPH2_SUPPORT */ 25208 } 25209 } 25210 } 25211 25212 /* Enable mirroring on a port. */ 25213 if (BCM_SUCCESS(rv)) { 25214 if(!SOC_IS_XGS3_SWITCH(unit) || 25215 (BCM_MIRROR_DISABLE == MIRROR_CONFIG_MODE(unit))) { 25216 rv = _bcm_esw_mirror_enable(unit); 25217 MIRROR_CONFIG_MODE(unit) = BCM_MIRROR_L2; 25218 } 25219 } 25220 25221 #ifdef BCM_WARM_BOOT_SUPPORT 25222 SOC_CONTROL_LOCK(unit); 25223 SOC_CONTROL(unit)->scache_dirty = 1; 25224 SOC_CONTROL_UNLOCK(unit); 25225 #endif 25226 25227 MIRROR_UNLOCK(unit); 25228 return (rv); 25229 } 25230 25231 /* 25232 * Function: 25233 * bcm_esw_mirror_port_dest_delete 25234 * Purpose: 25235 * Remove mirroring destination from a port. 25236 * Parameters: 25237 * unit - (IN) BCM device number. 25238 * port - (IN) Port mirrored port. 25239 * flags - (IN) BCM_MIRROR_PORT_XXX flags. 25240 * mirror_dest - (IN) Mirroring destination gport. 25241 * Returns: 25242 * BCM_X_XXX 25243 */ 25244 int 25245 bcm_esw_mirror_port_dest_delete(int unit, bcm_port_t port, 25246 uint32 flags, bcm_gport_t mirror_dest) 25247 { 25248 int final_rv = BCM_E_NONE; /* Operation return status. */ 25249 int rv = BCM_E_NONE; /* Operation return status. */ 25250 int vp = VP_PORT_INVALID; 25251 int vp_mirror = FALSE; 25252 int orig_gport = port; 25253 /* Initialization check. */ 25254 if (0 == MIRROR_INIT(unit)) { 25255 return BCM_E_INIT; 25256 } 25257 25258 if (-1 != port) { 25259 if (BCM_GPORT_IS_SET(port)) { 25260 rv = _bcm_tr2_mirror_vp_port_get(unit, port, 25261 &vp, &port); 25262 if ((rv != BCM_E_NONE) && (rv != BCM_E_NOT_FOUND)) { 25263 return rv; 25264 } 25265 rv = BCM_E_NONE; 25266 25267 if (vp == VP_PORT_INVALID) { 25268 #ifdef BCM_TRIDENT2PLUS_SUPPORT 25269 if (soc_feature(unit, soc_feature_hgproxy_subtag_coe) && 25270 _BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, port)) { 25271 } else 25272 #endif 25273 { 25274 BCM_IF_ERROR_RETURN(bcm_esw_port_local_get(unit, port, &port)); 25275 } 25276 } 25277 } 25278 25279 if (vp == VP_PORT_INVALID && !BCM_GPORT_IS_SET(port)) { 25280 if (!SOC_PORT_VALID(unit, port)) { 25281 return (BCM_E_PORT); 25282 } 25283 25284 if (IS_CPU_PORT(unit, port) && 25285 !soc_feature(unit, soc_feature_cpuport_mirror)) { 25286 return (BCM_E_PORT); 25287 } 25288 } 25289 } 25290 25291 if (!soc_feature(unit, soc_feature_egr_mirror_true) && 25292 (flags & BCM_MIRROR_PORT_EGRESS_TRUE)) { 25293 return (BCM_E_PARAM); 25294 } 25295 25296 if (!(flags & (BCM_MIRROR_PORT_INGRESS | BCM_MIRROR_PORT_EGRESS | 25297 BCM_MIRROR_PORT_EGRESS_TRUE))) { 25298 return (BCM_E_PARAM); 25299 } 25300 25301 if (0 == BCM_GPORT_IS_MIRROR(mirror_dest)) { 25302 return (BCM_E_PARAM); 25303 } 25304 25305 /* check supported conditions for vp mirroring */ 25306 if (vp != VP_PORT_INVALID) { 25307 #ifdef BCM_TRIUMPH2_SUPPORT 25308 if (soc_feature(unit, soc_feature_mirror_flexible) && 25309 (!(flags & BCM_MIRROR_PORT_EGRESS_TRUE))) { 25310 vp_mirror = TRUE; 25311 } 25312 #endif 25313 if (vp_mirror == FALSE) { 25314 return BCM_E_UNAVAIL; 25315 } 25316 } 25317 25318 if (flags & BCM_MIRROR_PORT_SFLOW) { 25319 MIRROR_LOCK(unit); 25320 rv = _bcm_mirror_sflow_dest_delete(unit, flags, mirror_dest); 25321 MIRROR_UNLOCK(unit); 25322 return rv; 25323 } 25324 25325 if (flags & BCM_MIRROR_PORT_INT) { 25326 MIRROR_LOCK(unit); 25327 rv = _bcm_mirror_int_dest_delete(unit, flags, mirror_dest); 25328 MIRROR_UNLOCK(unit); 25329 return rv; 25330 } 25331 25332 if (flags & BCM_MIRROR_PORT_ELEPHANT) { 25333 MIRROR_LOCK(unit); 25334 rv = _bcm_mirror_elephant_dest_delete(unit, flags, mirror_dest); 25335 MIRROR_UNLOCK(unit); 25336 return rv; 25337 } 25338 25339 if (flags & BCM_MIRROR_PORT_DLB_MONITOR) { 25340 MIRROR_LOCK(unit); 25341 rv = _bcm_mirror_dlb_monitor_dest_delete(unit, flags, mirror_dest); 25342 MIRROR_UNLOCK(unit); 25343 return rv; 25344 } 25345 25346 MIRROR_LOCK(unit); 25347 25348 if ((flags & BCM_MIRROR_PORT_INGRESS) && 25349 (BCM_GPORT_INVALID != mirror_dest)) { 25350 final_rv = _bcm_esw_mirror_port_ingress_dest_delete( 25351 unit, 25352 (vp == VP_PORT_INVALID) ? port : orig_gport, 25353 mirror_dest); 25354 } 25355 25356 if ((flags & BCM_MIRROR_PORT_EGRESS) && 25357 (BCM_GPORT_INVALID != mirror_dest)) { 25358 rv = _bcm_esw_mirror_port_egress_dest_delete( 25359 unit, 25360 (vp == VP_PORT_INVALID) ? port : orig_gport, 25361 mirror_dest); 25362 if (!BCM_FAILURE(final_rv)) { 25363 final_rv = rv; 25364 } 25365 } 25366 25367 #ifdef BCM_TRIUMPH2_SUPPORT 25368 if ((flags & BCM_MIRROR_PORT_EGRESS_TRUE) && 25369 (BCM_GPORT_INVALID != mirror_dest)) { 25370 rv = _bcm_esw_mirror_port_egress_true_dest_delete(unit, port, 25371 mirror_dest); 25372 if (!BCM_FAILURE(final_rv)) { 25373 final_rv = rv; 25374 } 25375 } 25376 #endif /* BCM_TRIUMPH2_SUPPORT */ 25377 25378 /* Update stacking mirror destination bitmap. */ 25379 if (vp == VP_PORT_INVALID) { 25380 if ((-1 != port) && !BCM_GPORT_IS_SET(port) && (IS_ST_PORT(unit, port))) { 25381 rv = _bcm_esw_mirror_stacking_dest_update(unit, port, BCM_GPORT_INVALID); 25382 if (!BCM_FAILURE(final_rv)) { 25383 final_rv = rv; 25384 } 25385 } 25386 } 25387 25388 #ifdef BCM_WARM_BOOT_SUPPORT 25389 SOC_CONTROL_LOCK(unit); 25390 SOC_CONTROL(unit)->scache_dirty = 1; 25391 SOC_CONTROL_UNLOCK(unit); 25392 #endif 25393 25394 MIRROR_UNLOCK(unit); 25395 return (final_rv); 25396 } 25397 25398 /* 25399 * Function: 25400 * bcm_esw_mirror_port_dest_get 25401 * Purpose: 25402 * Get port mirroring destinations. 25403 * Parameters: 25404 * unit - (IN) BCM device number. 25405 * port - (IN) Port mirrored port. 25406 * flags - (IN) BCM_MIRROR_PORT_XXX flags. 25407 * mirror_dest_size - (IN) Preallocated mirror_dest array size. 25408 * mirror_dest - (OUT)Filled array of port mirroring destinations 25409 * mirror_dest_count - (OUT)Actual number of mirroring destinations filled. 25410 * Returns: 25411 * BCM_X_XXX 25412 */ 25413 int 25414 bcm_esw_mirror_port_dest_get(int unit, bcm_port_t port, uint32 flags, 25415 int mirror_dest_size, bcm_gport_t *mirror_dest, 25416 int *mirror_dest_count) 25417 { 25418 #if defined(BCM_XGS3_SWITCH_SUPPORT) 25419 int idx; /* Mirror to port iteration index. */ 25420 int index = 0; /* Filled destinations index. */ 25421 bcm_gport_t mtp_dest[BCM_MIRROR_MTP_COUNT]; /* Mirror destinations array. */ 25422 #endif /* BCM_XGS3_SWITCH_SUPPORT */ 25423 int rv = BCM_E_NONE; /* Operation return status. */ 25424 int vp = VP_PORT_INVALID; 25425 int vp_mirror = FALSE; 25426 25427 /* Initialization check. */ 25428 if (0 == MIRROR_INIT(unit)) { 25429 return BCM_E_INIT; 25430 } 25431 25432 if (flags & BCM_MIRROR_PORT_SFLOW) { 25433 rv = _bcm_mirror_sflow_dest_get(unit,flags,mirror_dest_size, 25434 mirror_dest, mirror_dest_count); 25435 return rv; 25436 } 25437 25438 if (flags & BCM_MIRROR_PORT_INT) { 25439 rv = _bcm_mirror_int_dest_get(unit,flags,mirror_dest_size, 25440 mirror_dest, mirror_dest_count); 25441 return rv; 25442 } 25443 25444 if (flags & BCM_MIRROR_PORT_ELEPHANT) { 25445 rv = _bcm_mirror_elephant_dest_get(unit, flags, mirror_dest_size, 25446 mirror_dest, mirror_dest_count); 25447 return rv; 25448 } 25449 25450 if (flags & BCM_MIRROR_PORT_DLB_MONITOR) { 25451 rv = _bcm_mirror_dlb_monitor_dest_get(unit,flags,mirror_dest_size, 25452 mirror_dest, mirror_dest_count); 25453 return rv; 25454 } 25455 25456 if (BCM_GPORT_INVALID == port) { 25457 if (!MIRROR_MTP_METHOD_IS_NON_DIRECTED(unit)) { 25458 return (BCM_E_PORT); 25459 } 25460 MIRROR_LOCK(unit); 25461 if (soc_feature(unit, soc_feature_mirror_flexible) && 25462 !MIRROR_MTP_METHOD_IS_DIRECTED_FLEXIBLE(unit)) { 25463 if (MIRROR_CONFIG_SHARED_MTP_REF_COUNT(unit, 0)) { 25464 if(NULL != mirror_dest) { 25465 mirror_dest[0] = MIRROR_CONFIG_SHARED_MTP_DEST(unit, 0); 25466 } 25467 *mirror_dest_count = 1; 25468 } else { 25469 if(NULL != mirror_dest) { 25470 mirror_dest[0] = BCM_GPORT_INVALID; 25471 } 25472 *mirror_dest_count = 0; 25473 } 25474 } else { 25475 if (MIRROR_CONFIG_ING_MTP_REF_COUNT(unit, 0)) { 25476 if(NULL != mirror_dest) { 25477 mirror_dest[0] = MIRROR_CONFIG_ING_MTP_DEST(unit, 0); 25478 } 25479 *mirror_dest_count = 1; 25480 } else { 25481 if(NULL != mirror_dest) { 25482 mirror_dest[0] = BCM_GPORT_INVALID; 25483 } 25484 *mirror_dest_count = 0; 25485 } 25486 } 25487 MIRROR_UNLOCK(unit); 25488 return BCM_E_NONE; 25489 } 25490 25491 /* Input parameters check. */ 25492 if (BCM_GPORT_IS_SET(port)) { 25493 rv = _bcm_tr2_mirror_vp_port_get(unit, port, 25494 &vp, &port); 25495 if ((rv != BCM_E_NONE) && (rv != BCM_E_NOT_FOUND)) { 25496 return rv; 25497 } 25498 rv = BCM_E_NONE; 25499 25500 if (vp == VP_PORT_INVALID) { 25501 #ifdef BCM_TRIDENT2PLUS_SUPPORT 25502 if (soc_feature(unit, soc_feature_hgproxy_subtag_coe) && 25503 _BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, port)) { 25504 } else 25505 #endif 25506 { 25507 BCM_IF_ERROR_RETURN(bcm_esw_port_local_get(unit, port, &port)); 25508 } 25509 } 25510 } 25511 25512 if (vp == VP_PORT_INVALID && !BCM_GPORT_IS_SET(port)) { 25513 if (!SOC_PORT_VALID(unit, port)) { 25514 return (BCM_E_PORT); 25515 } 25516 25517 if (IS_CPU_PORT(unit, port) && 25518 !soc_feature(unit, soc_feature_cpuport_mirror)) { 25519 return (BCM_E_PORT); 25520 } 25521 } 25522 25523 if ((0 != mirror_dest_size) && (NULL == mirror_dest)) { 25524 return (BCM_E_PARAM); 25525 } 25526 25527 if (NULL == mirror_dest_count) { 25528 return (BCM_E_PARAM); 25529 } 25530 25531 if (!soc_feature(unit, soc_feature_egr_mirror_true) && 25532 (flags & BCM_MIRROR_PORT_EGRESS_TRUE)) { 25533 return (BCM_E_PARAM); 25534 } 25535 25536 if (!(flags & (BCM_MIRROR_PORT_INGRESS | BCM_MIRROR_PORT_EGRESS | 25537 BCM_MIRROR_PORT_EGRESS_TRUE))) { 25538 return (BCM_E_PARAM); 25539 } 25540 25541 /* check supported conditions for vp mirroring */ 25542 if (vp != VP_PORT_INVALID) { 25543 #ifdef BCM_TRIUMPH2_SUPPORT 25544 if (soc_feature(unit, soc_feature_mirror_flexible) && 25545 (!(flags & BCM_MIRROR_PORT_EGRESS_TRUE))) { 25546 vp_mirror = TRUE; 25547 } 25548 #endif 25549 if (vp_mirror == FALSE) { 25550 return BCM_E_UNAVAIL; 25551 } 25552 } 25553 25554 MIRROR_LOCK(unit); 25555 25556 #if defined(BCM_XGS3_SWITCH_SUPPORT) 25557 if (SOC_IS_XGS3_SWITCH(unit)) { 25558 if (flags & BCM_MIRROR_PORT_INGRESS) { 25559 rv = _bcm_xgs3_mirror_port_ingress_dest_get(unit, port, 25560 BCM_MIRROR_MTP_COUNT, 25561 mtp_dest, vp); 25562 if (BCM_SUCCESS(rv)) { 25563 for (idx = 0; idx < BCM_MIRROR_MTP_COUNT; idx++) { 25564 if ((index < mirror_dest_size) && 25565 (BCM_GPORT_INVALID != mtp_dest[idx])) { 25566 if(NULL != (mirror_dest + index)) { 25567 mirror_dest[index] = mtp_dest[idx]; 25568 } 25569 index++; 25570 } 25571 } 25572 } 25573 } 25574 if ((flags & BCM_MIRROR_PORT_EGRESS) && 25575 (index < mirror_dest_size)) { 25576 rv = _bcm_xgs3_mirror_port_egress_dest_get(unit, port, 25577 BCM_MIRROR_MTP_COUNT, 25578 mtp_dest, vp); 25579 if (BCM_SUCCESS(rv)) { 25580 for (idx = 0; idx < BCM_MIRROR_MTP_COUNT; idx++) { 25581 if ((index < mirror_dest_size) && 25582 (BCM_GPORT_INVALID != mtp_dest[idx])) { 25583 if(NULL != (mirror_dest + index)) { 25584 mirror_dest[index] = mtp_dest[idx]; 25585 } 25586 index++; 25587 } 25588 } 25589 } 25590 } 25591 #ifdef BCM_TRIUMPH2_SUPPORT 25592 if (soc_feature(unit, soc_feature_egr_mirror_true) && 25593 (flags & BCM_MIRROR_PORT_EGRESS_TRUE) && 25594 (index < mirror_dest_size)) { 25595 rv = _bcm_tr2_mirror_port_egress_true_dest_get(unit, port, 25596 BCM_MIRROR_MTP_COUNT, 25597 mtp_dest); 25598 if (BCM_SUCCESS(rv)) { 25599 for (idx = 0; idx < BCM_MIRROR_MTP_COUNT; idx++) { 25600 if ((index < mirror_dest_size) && 25601 (BCM_GPORT_INVALID != mtp_dest[idx])) { 25602 if(NULL != (mirror_dest + index)) { 25603 mirror_dest[index] = mtp_dest[idx]; 25604 } 25605 index++; 25606 } 25607 } 25608 } 25609 } 25610 #endif /* BCM_TRIUMPH2_SUPPORT */ 25611 *mirror_dest_count = index; 25612 } else 25613 #endif /* BCM_XGS3_SWITCH_SUPPORT */ 25614 { 25615 if (MIRROR_CONFIG_ING_MTP_REF_COUNT(unit, 0)) { 25616 if(NULL != mirror_dest) { 25617 mirror_dest[0] = MIRROR_CONFIG_ING_MTP_DEST(unit, 0); 25618 } 25619 *mirror_dest_count = 1; 25620 } else { 25621 if(NULL != mirror_dest) { 25622 mirror_dest[0] = BCM_GPORT_INVALID; 25623 } 25624 *mirror_dest_count = 0; 25625 } 25626 } 25627 25628 MIRROR_UNLOCK(unit); 25629 25630 return (rv); 25631 } 25632 25633 /* 25634 * Function: 25635 * bcm_esw_mirror_port_dest_delete_all 25636 * Purpose: 25637 * Remove all mirroring destinations from a port. 25638 * Parameters: 25639 * unit - (IN) BCM device number. 25640 * port - (IN) Port mirrored port. 25641 * flags - (IN) BCM_MIRROR_PORT_XXX flags. 25642 * Returns: 25643 * BCM_X_XXX 25644 */ 25645 int 25646 bcm_esw_mirror_port_dest_delete_all(int unit, bcm_port_t port, uint32 flags) 25647 { 25648 bcm_gport_t mirror_dest[BCM_MIRROR_MTP_COUNT]; 25649 int mirror_dest_count; 25650 int index; 25651 int rv; 25652 int vp = VP_PORT_INVALID; 25653 int orig_gport = port; 25654 25655 /* Initialization check. */ 25656 if (0 == MIRROR_INIT(unit)) { 25657 return BCM_E_INIT; 25658 } 25659 25660 if (!(flags & (BCM_MIRROR_PORT_INGRESS | BCM_MIRROR_PORT_EGRESS | 25661 BCM_MIRROR_PORT_EGRESS_TRUE))) { 25662 return (BCM_E_PARAM); 25663 } 25664 25665 #ifdef BCM_TOMAHAWK3_SUPPORT 25666 if (SOC_IS_TOMAHAWK3(unit)) { 25667 /* This function is not available for mtps reserved for 25668 * dlb flow monitoring feature 25669 */ 25670 if (flags & BCM_MIRROR_PORT_DLB_MONITOR) { 25671 return (BCM_E_UNAVAIL); 25672 } 25673 } 25674 #endif /* BCM_TOMAHAWK3_SUPPORT */ 25675 25676 MIRROR_LOCK(unit); 25677 25678 if (-1 != port) { 25679 if (BCM_GPORT_IS_SET(port)) { 25680 rv = _bcm_tr2_mirror_vp_port_get(unit, port, &vp, &port); 25681 if ((rv != BCM_E_NONE) && (rv != BCM_E_NOT_FOUND)) { 25682 MIRROR_UNLOCK(unit); 25683 return rv; 25684 } 25685 rv = BCM_E_NONE; 25686 } 25687 } 25688 25689 if (flags & BCM_MIRROR_PORT_INGRESS) { 25690 if (-1 != port) { 25691 if (BCM_GPORT_IS_SET(port)) { 25692 if (vp == VP_PORT_INVALID) { 25693 #ifdef BCM_TRIDENT2PLUS_SUPPORT 25694 if (soc_feature(unit, soc_feature_hgproxy_subtag_coe) && 25695 _BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, port)) { 25696 } else 25697 #endif 25698 { 25699 rv = bcm_esw_port_local_get(unit, port, &port); 25700 if (BCM_FAILURE(rv)) 25701 { 25702 MIRROR_UNLOCK(unit); 25703 return rv; 25704 } 25705 } 25706 } 25707 } 25708 25709 if(vp == VP_PORT_INVALID && !BCM_GPORT_IS_SET(port) && 25710 !SOC_PORT_VALID(unit, port)) { 25711 MIRROR_UNLOCK(unit); 25712 return (BCM_E_PORT); 25713 } 25714 25715 /* Read port ingress mirroring destination ports. */ 25716 rv = bcm_esw_mirror_port_dest_get( 25717 unit, (vp == VP_PORT_INVALID) ? port : orig_gport, 25718 BCM_MIRROR_PORT_INGRESS, BCM_MIRROR_MTP_COUNT, mirror_dest, 25719 &mirror_dest_count); 25720 } else { 25721 /* Get all ingress mirror destinations. */ 25722 rv = _bcm_mirror_dest_get_all(unit, BCM_MIRROR_PORT_INGRESS, 25723 BCM_MIRROR_MTP_COUNT, mirror_dest, 25724 &mirror_dest_count); 25725 } 25726 if (BCM_FAILURE(rv)) { 25727 MIRROR_UNLOCK(unit); 25728 return (rv); 25729 } 25730 25731 /* Remove all ingress mirroring destination ports. */ 25732 for (index = 0; index < mirror_dest_count; index++) { 25733 rv = bcm_esw_mirror_port_dest_delete( 25734 unit, (vp == VP_PORT_INVALID) ? port : orig_gport, 25735 BCM_MIRROR_PORT_INGRESS, mirror_dest[index]); 25736 if (BCM_FAILURE(rv)) { 25737 MIRROR_UNLOCK(unit); 25738 return (rv); 25739 } 25740 } 25741 } 25742 25743 if (flags & BCM_MIRROR_PORT_EGRESS) { 25744 /* Read port egress mirroring destination ports. */ 25745 if (-1 != port) { 25746 if (BCM_GPORT_IS_SET(port)) { 25747 if (vp == VP_PORT_INVALID) { 25748 rv = bcm_esw_port_local_get(unit, port, &port); 25749 if (BCM_FAILURE(rv)) 25750 { 25751 MIRROR_UNLOCK(unit); 25752 return rv; 25753 } 25754 } 25755 } 25756 if(vp == VP_PORT_INVALID && !SOC_PORT_VALID(unit, port)) { 25757 MIRROR_UNLOCK(unit); 25758 return (BCM_E_PORT); 25759 } 25760 25761 rv = bcm_esw_mirror_port_dest_get( 25762 unit, (vp == VP_PORT_INVALID) ? port : orig_gport, 25763 BCM_MIRROR_PORT_EGRESS, BCM_MIRROR_MTP_COUNT, mirror_dest, 25764 &mirror_dest_count); 25765 } else { 25766 /* Get all egress mirror destinations. */ 25767 rv = _bcm_mirror_dest_get_all(unit, BCM_MIRROR_PORT_EGRESS, 25768 BCM_MIRROR_MTP_COUNT, mirror_dest, 25769 &mirror_dest_count); 25770 } 25771 if (BCM_FAILURE(rv)) { 25772 MIRROR_UNLOCK(unit); 25773 return (rv); 25774 } 25775 25776 /* Remove all egress mirroring destination ports. */ 25777 for (index = 0; index < mirror_dest_count; index++) { 25778 rv = bcm_esw_mirror_port_dest_delete( 25779 unit, (vp == VP_PORT_INVALID) ? port : orig_gport, 25780 BCM_MIRROR_PORT_EGRESS, mirror_dest[index]); 25781 if (BCM_FAILURE(rv)) { 25782 MIRROR_UNLOCK(unit); 25783 return (rv); 25784 } 25785 } 25786 } 25787 25788 if (soc_feature(unit, soc_feature_egr_mirror_true) && 25789 (flags & BCM_MIRROR_PORT_EGRESS_TRUE)) { 25790 /* Read port egress true mirroring destination ports. */ 25791 if (-1 != port) { 25792 if (BCM_GPORT_IS_SET(port)) { 25793 rv = bcm_esw_port_local_get(unit, port, &port); 25794 if (BCM_FAILURE(rv)) 25795 { 25796 MIRROR_UNLOCK(unit); 25797 return rv; 25798 } 25799 } 25800 if(!SOC_PORT_VALID(unit, port)) { 25801 MIRROR_UNLOCK(unit); 25802 return (BCM_E_PORT); 25803 } 25804 25805 rv = bcm_esw_mirror_port_dest_get(unit, port, 25806 BCM_MIRROR_PORT_EGRESS_TRUE, 25807 BCM_MIRROR_MTP_COUNT, 25808 mirror_dest, 25809 &mirror_dest_count); 25810 } else { 25811 /* Get all egress mirror destinations. */ 25812 rv = _bcm_mirror_dest_get_all(unit, BCM_MIRROR_PORT_EGRESS_TRUE, 25813 BCM_MIRROR_MTP_COUNT, mirror_dest, 25814 &mirror_dest_count); 25815 } 25816 if (BCM_FAILURE(rv)) { 25817 MIRROR_UNLOCK(unit); 25818 return (rv); 25819 } 25820 25821 /* Remove all egress mirroring destination ports. */ 25822 for (index = 0; index < mirror_dest_count; index++) { 25823 rv = bcm_esw_mirror_port_dest_delete(unit, port, 25824 BCM_MIRROR_PORT_EGRESS_TRUE, 25825 mirror_dest[index]); 25826 if (BCM_FAILURE(rv)) { 25827 MIRROR_UNLOCK(unit); 25828 return (rv); 25829 } 25830 } 25831 } 25832 25833 MIRROR_UNLOCK(unit); 25834 return (BCM_E_NONE); 25835 } 25836 25837 /* 25838 * Function: 25839 * bcm_esw_mirror_destination_create 25840 * Purpose: 25841 * Create mirror destination description. 25842 * Parameters: 25843 * unit - (IN) BCM device number. 25844 * mirror_dest - (IN) Mirror destination description. 25845 * Returns: 25846 * BCM_X_XXX 25847 */ 25848 int 25849 bcm_esw_mirror_destination_create(int unit, bcm_mirror_destination_t *mirror_dest) 25850 { 25851 bcm_module_t mymodid; /* Local module id. */ 25852 bcm_module_t dest_mod; /* Destination module id. */ 25853 bcm_port_t dest_port; /* Destination port number. */ 25854 bcm_mirror_destination_t mirror_dest_check; 25855 int rv; /* Operation return status. */ 25856 #ifdef BCM_TOMAHAWK_SUPPORT 25857 int match_idx; 25858 #endif /* BCM_TOMAHAWK_SUPPORT */ 25859 uint8 do_gport_check = TRUE; 25860 25861 /* Initialization check. */ 25862 if (0 == MIRROR_INIT(unit)) { 25863 return BCM_E_INIT; 25864 } 25865 25866 /* Input parameters check. */ 25867 if (NULL == mirror_dest) { 25868 return (BCM_E_PARAM); 25869 } 25870 25871 #ifdef BCM_TOMAHAWK3_SUPPORT 25872 if (SOC_IS_TOMAHAWK3(unit)) { 25873 if ((mirror_dest->flags & BCM_MIRROR_DEST_ID_SHARE) || 25874 (mirror_dest->flags & BCM_MIRROR_DEST_MTP_ADD) || 25875 (mirror_dest->flags & BCM_MIRROR_DEST_MTP_REPLACE) || 25876 (mirror_dest->flags & BCM_MIRROR_DEST_MTP_DELETE) || 25877 (mirror_dest->flags & BCM_MIRROR_DEST_INT_PRI_SET)) { 25878 return (BCM_E_UNAVAIL); 25879 } 25880 25881 /* Mirroring over trunk not supported */ 25882 if (BCM_GPORT_IS_TRUNK(mirror_dest->gport)) { 25883 return (BCM_E_UNAVAIL); 25884 } 25885 25886 if ((mirror_dest->truncate != BCM_MIRROR_PAYLOAD_TRUNCATE) && 25887 (mirror_dest->truncate != 25888 BCM_MIRROR_PAYLOAD_TRUNCATE_AND_ZERO) && 25889 (mirror_dest->truncate != BCM_MIRROR_PAYLOAD_DO_NOT_TRUNCATE)) { 25890 return BCM_E_PARAM; 25891 } 25892 25893 } 25894 #endif /* BCM_TOMAHAWK3_SUPPORT */ 25895 if (!SOC_IS_TOMAHAWK3(unit)) { 25896 if (mirror_dest->truncate == BCM_MIRROR_PAYLOAD_TRUNCATE_AND_ZERO) { 25897 return BCM_E_PARAM; 25898 } 25899 } 25900 if ((mirror_dest->flags & BCM_MIRROR_DEST_TUNNEL_WITH_SPAN_ID) || 25901 (mirror_dest->flags & BCM_MIRROR_DEST_TUNNEL_RSPAN)) { 25902 return (BCM_E_PARAM); 25903 } 25904 25905 /* Check if device supports advanced mirroring mode. */ 25906 if (mirror_dest->flags & (BCM_MIRROR_DEST_TUNNEL_IP_GRE | 25907 BCM_MIRROR_DEST_PAYLOAD_UNTAGGED)) { 25908 25909 #if defined(BCM_TRIDENT3_SUPPORT) 25910 if (SOC_IS_TRIDENT3X(unit)) { 25911 if ((0 == SOC_MEM_IS_VALID(unit, EGR_MIRROR_TABLEm)) || 25912 (0 == soc_mem_index_count(unit, EGR_MIRROR_TABLEm))) { 25913 return (BCM_E_UNAVAIL); 25914 } 25915 } else 25916 #endif 25917 { 25918 if (0 == SOC_MEM_IS_VALID(unit, EGR_ERSPANm) && 25919 0 == SOC_MEM_IS_VALID(unit, EGR_MIRROR_ENCAP_CONTROLm)) { 25920 return (BCM_E_UNAVAIL); 25921 } 25922 25923 /* Bypass mode is enabled check. */ 25924 if (SOC_MEM_IS_VALID(unit, EGR_ERSPANm) && 25925 0 == soc_mem_index_count(unit, EGR_ERSPANm)) { 25926 return (BCM_E_UNAVAIL); 25927 } 25928 if (SOC_MEM_IS_VALID(unit, EGR_MIRROR_ENCAP_CONTROLm) && 25929 0 == soc_mem_index_count(unit, EGR_MIRROR_ENCAP_CONTROLm)) { 25930 return (BCM_E_UNAVAIL); 25931 } 25932 } 25933 } 25934 /* Check if device supports mirroring trill and NIV tunneling. */ 25935 if (mirror_dest->flags & BCM_MIRROR_DEST_TUNNEL_TRILL) { 25936 if (!soc_feature(unit, soc_feature_trill)) { 25937 return (BCM_E_UNAVAIL); 25938 } else if (mirror_dest->flags & BCM_MIRROR_DEST_TUNNEL_NIV) { 25939 /* Only one extra encap allowed. */ 25940 return BCM_E_PARAM; 25941 } else if (mirror_dest->flags & BCM_MIRROR_DEST_TUNNEL_ETAG) { 25942 /* Only one extra encap allowed. */ 25943 return BCM_E_PARAM; 25944 } /* else OK */ 25945 } 25946 if ((mirror_dest->flags & BCM_MIRROR_DEST_TUNNEL_NIV)) { 25947 if(!soc_feature(unit, soc_feature_niv)) { 25948 return (BCM_E_UNAVAIL); 25949 } else if (mirror_dest->flags & BCM_MIRROR_DEST_TUNNEL_ETAG) { 25950 /* Only one extra encap allowed. */ 25951 return BCM_E_PARAM; 25952 } /* else OK */ 25953 } 25954 if ((mirror_dest->flags & BCM_MIRROR_DEST_TUNNEL_ETAG) && 25955 !soc_feature(unit, soc_feature_port_extension)) { 25956 return (BCM_E_UNAVAIL); 25957 } 25958 25959 /* Untagging payload supported only on IP tunnels. */ 25960 if ((0 == (mirror_dest->flags & (BCM_MIRROR_DEST_TUNNEL_IP_GRE | 25961 BCM_MIRROR_DEST_TUNNEL_PSAMP | 25962 BCM_MIRROR_DEST_TUNNEL_SFLOW))) && 25963 (mirror_dest->flags & BCM_MIRROR_DEST_PAYLOAD_UNTAGGED)) { 25964 return (BCM_E_UNAVAIL); 25965 } 25966 25967 /* Can't do IP-GRE & L3 tunnel simultaneously. */ 25968 if ((mirror_dest->flags & BCM_MIRROR_DEST_TUNNEL_IP_GRE) && 25969 (mirror_dest->flags & BCM_MIRROR_DEST_TUNNEL_L2)) { 25970 return (BCM_E_CONFIG); 25971 } 25972 25973 /* Check if device supports assigning Traffic Class to this MTP */ 25974 if ((mirror_dest->flags & BCM_MIRROR_DEST_INT_PRI_SET) && 25975 (!(SOC_IS_TD_TT(unit) || SOC_IS_TRIUMPH3(unit) || 25976 SOC_IS_KATANAX(unit)))) { 25977 return BCM_E_PARAM; 25978 } 25979 25980 /* Check if support share destination id */ 25981 if ((mirror_dest->flags & BCM_MIRROR_DEST_ID_SHARE) && 25982 !(SOC_IS_TD2_TT2(unit))) { 25983 return BCM_E_PARAM; 25984 } 25985 25986 /* share destination id support has not been implemented for TD3 */ 25987 if ((mirror_dest->flags & BCM_MIRROR_DEST_ID_SHARE) && 25988 SOC_IS_TRIDENT3X(unit)) { 25989 return BCM_E_UNAVAIL; 25990 } 25991 25992 /* TD3 solution for IFA(Inband Flow Analyzer) application */ 25993 if (mirror_dest->flags2 & (BCM_MIRROR_DEST_FLAGS2_IFA | 25994 BCM_MIRROR_DEST_FLAGS2_INT_PROBE)) { 25995 if (!SOC_IS_TRIDENT3X(unit)) { 25996 return BCM_E_UNAVAIL; 25997 } 25998 } 25999 26000 if (mirror_dest->flags & BCM_MIRROR_DEST_ID_SHARE) { 26001 if (!(mirror_dest->flags & BCM_MIRROR_DEST_MTP_ADD) && 26002 !(mirror_dest->flags & BCM_MIRROR_DEST_MTP_DELETE)) { 26003 /* 26004 * First call will alloc mirror dest_id for shared-id mirror destination, 26005 * so do not need to check gport parameter. 26006 */ 26007 do_gport_check = FALSE; 26008 /* Rtag check */ 26009 if (mirror_dest->rtag <= bcmMirrorPscNone || 26010 mirror_dest->rtag >= bcmMirrorPscCount) { 26011 return (BCM_E_PARAM); 26012 } 26013 } 26014 } 26015 26016 if (do_gport_check) { 26017 /* Resolve miror destination gport */ 26018 BCM_IF_ERROR_RETURN( 26019 _bcm_mirror_gport_adapt(unit, &(mirror_dest->gport))); 26020 26021 /* Verify mirror destination port/trunk. */ 26022 if ((0 == BCM_GPORT_IS_MODPORT(mirror_dest->gport)) && 26023 (0 == BCM_GPORT_IS_TRUNK(mirror_dest->gport)) && 26024 (0 == BCM_GPORT_IS_DEVPORT(mirror_dest->gport))) { 26025 return (BCM_E_PORT); 26026 } 26027 } 26028 26029 /* Get local modid. */ 26030 BCM_IF_ERROR_RETURN(_bcm_esw_local_modid_get(unit, &mymodid)); 26031 26032 /* Directed mirroring support check. */ 26033 if (MIRROR_MTP_METHOD_IS_NON_DIRECTED(unit)) { 26034 int isLocal; 26035 26036 /* No mirroring to a trunk. */ 26037 if (BCM_GPORT_IS_TRUNK(mirror_dest->gport)) { 26038 return (BCM_E_UNAVAIL); 26039 } 26040 26041 /* Some devices do not support non-directed mode */ 26042 if (soc_feature(unit, soc_feature_directed_mirror_only)) { 26043 return (BCM_E_CONFIG); 26044 } 26045 26046 /* Set mirror destination to outgoing port on local module. */ 26047 dest_mod = BCM_GPORT_IS_DEVPORT(mirror_dest->gport) ? 26048 mymodid : BCM_GPORT_MODPORT_MODID_GET(mirror_dest->gport); 26049 26050 BCM_IF_ERROR_RETURN 26051 (_bcm_esw_modid_is_local(unit, dest_mod, &isLocal)); 26052 26053 if (FALSE == isLocal) { 26054 _bcm_gport_dest_t gport_st; 26055 26056 BCM_IF_ERROR_RETURN 26057 (bcm_esw_topo_port_get(unit, dest_mod, &dest_port)); 26058 gport_st.gport_type = BCM_GPORT_TYPE_MODPORT; 26059 gport_st.modid = mymodid; 26060 gport_st.port = dest_port; 26061 BCM_IF_ERROR_RETURN( 26062 _bcm_esw_gport_construct(unit, &gport_st, 26063 &(mirror_dest->gport))); 26064 } 26065 } 26066 26067 #ifdef BCM_TOMAHAWK_SUPPORT 26068 if (SOC_INFO(unit).th_tflow_enabled == 1) { 26069 if ((mirror_dest->flags & BCM_MIRROR_DEST_UPDATE_TUNNEL_SFLOW)) { 26070 rv = _bcm_esw_mirror_destination_find(unit, mirror_dest->gport, 26071 0, mirror_dest->flags, 26072 &mirror_dest_check); 26073 26074 if (BCM_SUCCESS(rv)) { 26075 /* Update the existing mirror destination entry */ 26076 (MIRROR_DEST(unit, mirror_dest_check.mirror_dest_id)) 26077 ->version = mirror_dest->version; 26078 (MIRROR_DEST(unit, mirror_dest_check.mirror_dest_id)) 26079 ->tos = mirror_dest->tos; 26080 (MIRROR_DEST(unit, mirror_dest_check.mirror_dest_id)) 26081 ->ttl = mirror_dest->ttl; 26082 (MIRROR_DEST(unit, mirror_dest_check.mirror_dest_id)) 26083 ->src_addr = mirror_dest->src_addr; 26084 (MIRROR_DEST(unit, mirror_dest_check.mirror_dest_id)) 26085 ->dst_addr = mirror_dest->dst_addr; 26086 (MIRROR_DEST(unit, mirror_dest_check.mirror_dest_id)) 26087 ->tpid = mirror_dest->tpid; 26088 (MIRROR_DEST(unit, mirror_dest_check.mirror_dest_id)) 26089 ->vlan_id = mirror_dest->vlan_id; 26090 (MIRROR_DEST(unit, mirror_dest_check.mirror_dest_id)) 26091 ->udp_src_port = mirror_dest->udp_src_port; 26092 (MIRROR_DEST(unit, mirror_dest_check.mirror_dest_id)) 26093 ->udp_dst_port = mirror_dest->udp_dst_port; 26094 sal_memcpy((MIRROR_DEST(unit, 26095 mirror_dest_check.mirror_dest_id)) 26096 ->src_mac, mirror_dest->src_mac, 6); 26097 sal_memcpy((MIRROR_DEST(unit, 26098 mirror_dest_check.mirror_dest_id)) 26099 ->dst_mac, mirror_dest->dst_mac, 6); 26100 26101 if (mirror_dest->flags & BCM_MIRROR_PORT_EGRESS) { 26102 /* Get the mtp index of the mirror destination */ 26103 BCM_IF_ERROR_RETURN 26104 (_bcm_tr2_mirror_shared_mtp_match(unit, 26105 mirror_dest_check.mirror_dest_id, 26106 TRUE, &match_idx)); 26107 /* Set sFlow headers */ 26108 BCM_IF_ERROR_RETURN 26109 (_bcm_mirror_sflow_tunnel_set(unit, match_idx, 26110 0, BCM_MIRROR_PORT_EGRESS)); 26111 } 26112 return BCM_E_NONE; 26113 } else { 26114 return rv; 26115 } 26116 } 26117 } 26118 #endif /* BCM_TOMAHAWK_SUPPORT */ 26119 26120 /* If we are NOT replacing an existing entry, check if it exists. */ 26121 if (0 == (mirror_dest->flags & BCM_MIRROR_DEST_REPLACE)) { 26122 #ifdef BCM_TRIDENT2_SUPPORT 26123 if (mirror_dest->flags & BCM_MIRROR_DEST_ID_SHARE) { 26124 /* Do nothing here */ 26125 } else 26126 #endif /* BCM_TRIDENT2_SUPPORT */ 26127 { 26128 rv = _bcm_esw_mirror_destination_find(unit, mirror_dest->gport, 0, 26129 mirror_dest->flags, 26130 &mirror_dest_check); 26131 if (BCM_SUCCESS(rv)) { 26132 /* Entry exists and we are not replacing, error */ 26133 return BCM_E_EXISTS; 26134 } else if (BCM_E_NOT_FOUND != rv) { 26135 /* If something else went wrong, error */ 26136 return rv; 26137 } 26138 } 26139 } 26140 /* Else, create destination (which handles replace properly) */ 26141 MIRROR_LOCK(unit); 26142 rv = _bcm_esw_mirror_destination_create(unit, mirror_dest); 26143 MIRROR_UNLOCK(unit); 26144 return (rv); 26145 } 26146 26147 26148 /* 26149 * Function: 26150 * bcm_esw_mirror_destination_destroy 26151 * Purpose: 26152 * Destroy mirror destination description. 26153 * Parameters: 26154 * unit - (IN) BCM device number. 26155 * mirror_dest_id - (IN) Mirror destination id. 26156 * Returns: 26157 * BCM_X_XXX 26158 */ 26159 int 26160 bcm_esw_mirror_destination_destroy(int unit, bcm_gport_t mirror_dest_id) 26161 { 26162 int rv; /* Operation return status. */ 26163 #ifdef BCM_TRIDENT2_SUPPORT 26164 _bcm_mirror_dest_config_p mdest_cfg; /* Mirror destination config */ 26165 #endif /* BCM_TRIDENT2_SUPPORT */ 26166 26167 /* Initialization check. */ 26168 if (0 == MIRROR_INIT(unit)) { 26169 return BCM_E_INIT; 26170 } 26171 26172 if (0 == BCM_GPORT_IS_MIRROR(mirror_dest_id)) { 26173 return (BCM_E_PARAM); 26174 } 26175 26176 MIRROR_LOCK(unit); 26177 26178 /* If destination stil in use - > E_BUSY */ 26179 if (1 < MIRROR_DEST_REF_COUNT(unit, mirror_dest_id)) { 26180 MIRROR_UNLOCK(unit); 26181 return (BCM_E_BUSY); 26182 } 26183 26184 #ifdef BCM_TRIDENT2_SUPPORT 26185 mdest_cfg = &MIRROR_DEST_CONFIG(unit, mirror_dest_id); 26186 26187 if (mdest_cfg->mirror_dest.flags & BCM_MIRROR_DEST_ID_SHARE) { 26188 BCM_IF_ERROR_RETURN( 26189 _bcm_mirror_dest_mtp_delete_all(unit, mirror_dest_id)); 26190 } 26191 #endif /* BCM_TRIDENT2_SUPPORT */ 26192 26193 rv = _bcm_mirror_destination_free(unit, mirror_dest_id); 26194 26195 MIRROR_UNLOCK(unit); 26196 return (rv); 26197 } 26198 26199 /* 26200 * Function: 26201 * bcm_esw_mirror_destination_get 26202 * Purpose: 26203 * Get mirror destination description. 26204 * Parameters: 26205 * unit - (IN) BCM device number. 26206 * mirror_dest_id - (IN) Mirror destination id. 26207 * mirror_dest - (IN/OUT)Mirror destination description. 26208 * Returns: 26209 * BCM_X_XXX 26210 */ 26211 int 26212 bcm_esw_mirror_destination_get(int unit, bcm_gport_t mirror_dest_id, 26213 bcm_mirror_destination_t *mirror_dest) 26214 { 26215 bcm_mirror_destination_t mirror_destination; 26216 bcm_port_t port, port_out; 26217 bcm_module_t modid, modid_out; 26218 int rv = BCM_E_NONE; 26219 #if defined(BCM_KATANA2_SUPPORT) 26220 int is_local_subport = FALSE; 26221 int pp_port = 0; 26222 #endif 26223 26224 bcm_mirror_destination_t_init(&mirror_destination); 26225 26226 /* Initialization check. */ 26227 if (0 == MIRROR_INIT(unit)) { 26228 return BCM_E_INIT; 26229 } 26230 26231 if (BCM_GPORT_INVALID == mirror_dest_id) { 26232 /* Find the mirror destination id from the dest description */ 26233 return _bcm_esw_mirror_destination_find(unit, mirror_dest->gport, 0, 26234 mirror_dest->flags, 26235 mirror_dest); 26236 } 26237 26238 if (0 == BCM_GPORT_IS_MIRROR(mirror_dest_id)) { 26239 return (BCM_E_PARAM); 26240 } 26241 26242 if (NULL == mirror_dest) { 26243 return (BCM_E_PARAM); 26244 } 26245 26246 MIRROR_LOCK(unit); 26247 26248 /* If destination is not valid */ 26249 if (0 == MIRROR_DEST_REF_COUNT(unit, mirror_dest_id)) { 26250 MIRROR_UNLOCK(unit); 26251 return (BCM_E_NOT_FOUND); 26252 } 26253 26254 #ifdef BCM_TRIDENT2_SUPPORT 26255 if (((MIRROR_DEST(unit, mirror_dest_id))->flags & BCM_MIRROR_DEST_ID_SHARE) 26256 && (BCM_GPORT_IS_MODPORT(mirror_dest->gport))) { 26257 BCM_IF_ERROR_RETURN( 26258 _bcm_mirror_dest_mtp_get(unit, mirror_dest_id, mirror_dest->gport, 26259 &mirror_destination)); 26260 } else 26261 #endif /* BCM_TRIDENT2_SUPPORT */ 26262 { 26263 mirror_destination = *(MIRROR_DEST(unit, mirror_dest_id)); 26264 } 26265 if (BCM_GPORT_IS_MODPORT(mirror_destination.gport)) { 26266 port = BCM_GPORT_MODPORT_PORT_GET(mirror_destination.gport); 26267 modid = BCM_GPORT_MODPORT_MODID_GET(mirror_destination.gport); 26268 26269 #if defined(BCM_KATANA2_SUPPORT) 26270 rv = _bcm_kt2_modport_is_local_coe_subport(unit, modid, 26271 port, &is_local_subport); 26272 if (BCM_FAILURE(rv)) { 26273 MIRROR_UNLOCK(unit); 26274 return rv; 26275 } 26276 if (is_local_subport) { 26277 rv = _bcm_kt2_modport_to_pp_port_get(unit, modid, port, &pp_port); 26278 if (BCM_FAILURE(rv)) { 26279 MIRROR_UNLOCK(unit); 26280 return rv; 26281 } 26282 mirror_destination.gport = 0; 26283 _BCM_KT2_SUBPORT_PORT_ID_SET(mirror_destination.gport, pp_port); 26284 if (BCM_PBMP_MEMBER(SOC_INFO(unit).linkphy_pp_port_pbm, pp_port)) { 26285 _BCM_KT2_SUBPORT_PORT_TYPE_SET(mirror_destination.gport, 26286 _BCM_KT2_SUBPORT_TYPE_LINKPHY); 26287 } else if (BCM_PBMP_MEMBER( 26288 SOC_INFO(unit).subtag_pp_port_pbm, pp_port)) { 26289 _BCM_KT2_SUBPORT_PORT_TYPE_SET(mirror_destination.gport, 26290 _BCM_KT2_SUBPORT_TYPE_SUBTAG); 26291 } else { 26292 MIRROR_UNLOCK(unit); 26293 return BCM_E_PORT; 26294 } 26295 } else 26296 #endif 26297 { 26298 if (NUM_MODID(unit) > 1 && port> 31) { 26299 rv = _bcm_esw_stk_modmap_map(unit, 26300 BCM_STK_MODMAP_GET, modid, port, &modid_out, &port_out); 26301 if (BCM_FAILURE(rv)) { 26302 MIRROR_UNLOCK(unit); 26303 return rv; 26304 } 26305 if (!SOC_PORT_ADDRESSABLE(unit, port_out)) { 26306 MIRROR_UNLOCK(unit); 26307 return BCM_E_PORT; 26308 } 26309 if (!SOC_MODID_ADDRESSABLE(unit, modid_out)) { 26310 MIRROR_UNLOCK(unit); 26311 return BCM_E_PARAM; 26312 } 26313 port = port_out; 26314 modid = modid_out; 26315 } 26316 rv = _bcm_mirror_gport_construct(unit, port,modid, 0, 26317 &(mirror_destination.gport)); 26318 if (BCM_FAILURE(rv)) { 26319 MIRROR_UNLOCK(unit); 26320 return rv; 26321 } 26322 } 26323 } 26324 *mirror_dest = mirror_destination; 26325 MIRROR_UNLOCK(unit); 26326 return (rv); 26327 } 26328 26329 26330 /* 26331 * Function: 26332 * bcm_esw_mirror_destination_traverse 26333 * Purpose: 26334 * Traverse installed mirror destinations 26335 * Parameters: 26336 * unit - (IN) BCM device number. 26337 * cb - (IN) Mirror destination traverse callback. 26338 * user_data - (IN) User cookie 26339 * Returns: 26340 * BCM_X_XXX 26341 */ 26342 int 26343 bcm_esw_mirror_destination_traverse(int unit, bcm_mirror_destination_traverse_cb cb, 26344 void *user_data) 26345 { 26346 int idx; /* Mirror destinations index. */ 26347 _bcm_mirror_dest_config_p mdest; /* Mirror destination description.*/ 26348 bcm_mirror_destination_t mirror_dest; /* User cb mirror destination. */ 26349 int rv = BCM_E_NONE; 26350 26351 /* Initialization check. */ 26352 if (0 == MIRROR_INIT(unit)) { 26353 return BCM_E_INIT; 26354 } 26355 26356 /* Input parameters check. */ 26357 if (NULL == cb) { 26358 return (BCM_E_PARAM); 26359 } 26360 26361 MIRROR_LOCK(unit); 26362 /* Iterate mirror destinations & call user callback for valid ones. */ 26363 for (idx = 0; idx < MIRROR_CONFIG(unit)->dest_count; idx++) { 26364 mdest = &MIRROR_CONFIG(unit)->dest_arr[idx]; 26365 if (0 == mdest->ref_count) { 26366 continue; 26367 } 26368 26369 mirror_dest = mdest->mirror_dest; 26370 #ifdef BCM_TRIDENT2_SUPPORT 26371 if (mirror_dest.flags & BCM_MIRROR_DEST_ID_SHARE) { 26372 rv = _bcm_mirror_dest_mtp_traverse( 26373 unit, mirror_dest.mirror_dest_id, 26374 cb, user_data); 26375 } else 26376 #endif /* BCM_TRIDENT2_SUPPORT */ 26377 { 26378 rv = (*cb)(unit, &mirror_dest, user_data); 26379 } 26380 if (BCM_FAILURE(rv)) { 26381 #ifdef BCM_CB_ABORT_ON_ERR 26382 if (SOC_CB_ABORT_ON_ERR(unit)) { 26383 MIRROR_UNLOCK(unit); 26384 return rv; 26385 } 26386 #endif 26387 } 26388 } 26389 MIRROR_UNLOCK(unit); 26390 return (BCM_E_NONE); 26391 } 26392 26393 /* 26394 * Function: 26395 * bcm_esw_mirror_lock 26396 * Purpose: 26397 * Allow other modules to take the mirroring mutex 26398 * Parameters: 26399 * unit - unit # 26400 * Returns: 26401 * None 26402 */ 26403 void bcm_esw_mirror_lock(int unit) { 26404 if (MIRROR_INIT(unit)) { 26405 MIRROR_LOCK(unit); 26406 } 26407 } 26408 26409 /* 26410 * Function: 26411 * bcm_esw_mirror_unlock 26412 * Purpose: 26413 * Allow other modules to give up the mirroring mutex 26414 * Parameters: 26415 * unit - unit # 26416 * Returns: 26417 * None 26418 */ 26419 void bcm_esw_mirror_unlock(int unit) { 26420 if (MIRROR_INIT(unit)) { 26421 MIRROR_UNLOCK(unit); 26422 } 26423 } 26424 26425 #ifdef BCM_TOMAHAWK3_SUPPORT 26426 /* 26427 * Function: 26428 * _bcm_esw_payload_zero_reg_field_get 26429 * Purpose: 26430 * Given a payload zero parameter name, this function returns the 26431 * corresponding (a) protocol/port value register and field pair, if 26432 * applicable, and (b) offset register and field pair. If protocol/port value 26433 * register is not defined, INVALIDr is returned 26434 * Parameters: 26435 * unit - (IN) BCM device number 26436 * field_id - (IN) Field name for which register/field pair is to be 26437 * returned 26438 * offset_reg - (OUT) Offset register corresponding to the field 26439 * proto_port_num_reg - (OUT)Protcol or port id register corresponding to the field 26440 * offset_fld - (OUT) Corresponding field in offset register 26441 * proto_port_num_fld - (OUT) Corresponding field in protocol/port id register 26442 * Returns: 26443 * BCM_E_XXX 26444 */ 26445 STATIC void 26446 _bcm_esw_payload_zero_reg_field_get(int unit, 26447 bcm_mirror_payload_zero_field_t field_id, 26448 soc_reg_t *offset_reg, 26449 soc_reg_t *proto_port_num_reg, 26450 soc_field_t *offset_fld, 26451 soc_field_t *proto_port_num_fld) 26452 { 26453 switch (field_id) { 26454 /* IPv4 */ 26455 case bcmMirrorPayloadZeroIp4Protocol0: 26456 *offset_reg = EGR_MIRROR_ZERO_PAYLOAD_OFFSET_CFG_0r; 26457 *offset_fld = IP_PROTOCOL_0_OFFSETf; 26458 *proto_port_num_reg = EGR_MIRROR_ZERO_PAYLOAD_PARSE_CFG_0r; 26459 *proto_port_num_fld = IP_PROTOCOL_0f; 26460 break; 26461 26462 case bcmMirrorPayloadZeroIp4Protocol1: 26463 *offset_reg = EGR_MIRROR_ZERO_PAYLOAD_OFFSET_CFG_0r; 26464 *offset_fld = IP_PROTOCOL_1_OFFSETf; 26465 *proto_port_num_reg = EGR_MIRROR_ZERO_PAYLOAD_PARSE_CFG_0r; 26466 *proto_port_num_fld = IP_PROTOCOL_1f; 26467 break; 26468 26469 case bcmMirrorPayloadZeroIp4Protocol2: 26470 *offset_reg = EGR_MIRROR_ZERO_PAYLOAD_OFFSET_CFG_0r; 26471 *offset_fld = IP_PROTOCOL_2_OFFSETf; 26472 *proto_port_num_reg = EGR_MIRROR_ZERO_PAYLOAD_PARSE_CFG_0r; 26473 *proto_port_num_fld = IP_PROTOCOL_2f; 26474 break; 26475 26476 /* IPv6 */ 26477 case bcmMirrorPayloadZeroIp6NxtHdr0: 26478 *offset_reg = EGR_MIRROR_ZERO_PAYLOAD_OFFSET_CFG_1r; 26479 *offset_fld = IPV6_NEXT_HEADER_0_OFFSETf; 26480 *proto_port_num_reg = EGR_MIRROR_ZERO_PAYLOAD_PARSE_CFG_1r; 26481 *proto_port_num_fld = IPV6_NEXT_HEADER_0f; 26482 break; 26483 26484 case bcmMirrorPayloadZeroIp6NxtHdr1: 26485 *offset_reg = EGR_MIRROR_ZERO_PAYLOAD_OFFSET_CFG_1r; 26486 *offset_fld = IPV6_NEXT_HEADER_1_OFFSETf; 26487 *proto_port_num_reg = EGR_MIRROR_ZERO_PAYLOAD_PARSE_CFG_1r; 26488 *proto_port_num_fld = IPV6_NEXT_HEADER_1f; 26489 break; 26490 26491 case bcmMirrorPayloadZeroIp6NxtHdr2: 26492 *offset_reg = EGR_MIRROR_ZERO_PAYLOAD_OFFSET_CFG_1r; 26493 *offset_fld = IPV6_NEXT_HEADER_2_OFFSETf; 26494 *proto_port_num_reg = EGR_MIRROR_ZERO_PAYLOAD_PARSE_CFG_1r; 26495 *proto_port_num_fld = IPV6_NEXT_HEADER_2f; 26496 break; 26497 26498 /* UDP ports */ 26499 case bcmMirrorPayloadZeroUdpPort0: 26500 *offset_reg = EGR_MIRROR_ZERO_PAYLOAD_OFFSET_CFG_2r; 26501 *offset_fld = UDP_PORT_0_OFFSETf; 26502 *proto_port_num_reg = EGR_MIRROR_ZERO_PAYLOAD_PARSE_CFG_2r; 26503 *proto_port_num_fld = UDP_PORT_0f; 26504 break; 26505 26506 case bcmMirrorPayloadZeroUdpPort1: 26507 *offset_reg = EGR_MIRROR_ZERO_PAYLOAD_OFFSET_CFG_2r; 26508 *offset_fld = UDP_PORT_1_OFFSETf; 26509 *proto_port_num_reg = EGR_MIRROR_ZERO_PAYLOAD_PARSE_CFG_2r; 26510 *proto_port_num_fld = UDP_PORT_1f; 26511 break; 26512 26513 /* Other protocols, or default field values */ 26514 case bcmMirrorPayloadZeroIpInIpOffset: 26515 *offset_reg = EGR_MIRROR_ZERO_PAYLOAD_OFFSET_CFG_3r; 26516 *offset_fld = IPINIP_OFFSETf; 26517 /* No corresponding protocol value register present */ 26518 *proto_port_num_reg = INVALIDr; 26519 *proto_port_num_fld = INVALIDf; 26520 break; 26521 26522 case bcmMirrorPayloadZeroL2Offset: 26523 *offset_reg = EGR_MIRROR_ZERO_PAYLOAD_OFFSET_CFG_3r; 26524 *offset_fld = L2_OFFSETf; 26525 /* No corresponding protocol value register present */ 26526 *proto_port_num_reg = INVALIDr; 26527 *proto_port_num_fld = INVALIDf; 26528 break; 26529 26530 case bcmMirrorPayloadZeroL3Offset: 26531 *offset_reg = EGR_MIRROR_ZERO_PAYLOAD_OFFSET_CFG_3r; 26532 *offset_fld = L3_OFFSETf; 26533 /* No corresponding protocol value register present */ 26534 *proto_port_num_reg = INVALIDr; 26535 *proto_port_num_fld = INVALIDf; 26536 break; 26537 26538 case bcmMirrorPayloadZeroMplsOffset: 26539 *offset_reg = EGR_MIRROR_ZERO_PAYLOAD_OFFSET_CFG_3r; 26540 *offset_fld = MPLS_OFFSETf; 26541 /* No corresponding protocol value register present */ 26542 *proto_port_num_reg = INVALIDr; 26543 *proto_port_num_fld = INVALIDf; 26544 break; 26545 26546 default: 26547 /* Must not hit this case */ 26548 *offset_reg = INVALIDr; 26549 *proto_port_num_reg = INVALIDr; 26550 *offset_fld = INVALIDf; 26551 *proto_port_num_fld = INVALIDf; 26552 } 26553 26554 return; 26555 } 26556 #endif /* BCM_TOMAHAWK3_SUPPORT */ 26557 26558 /* 26559 * Function: 26560 * bcm_esw_mirror_payload_zero_control_multi_set 26561 * Purpose: 26562 * This function programs payload offset and protocol values required 26563 * for payload wiping feature. They are used when this feature is enabled 26564 * on a MTP. Also read Notes section below. 26565 * Parameters: 26566 * unit - (IN) BCM device number 26567 * pyld_zero_cfg - (IN) Array containing protocol number or port number 26568 * and/or offset value for the fields represented by 26569 * bcm_mirror_payload_zero_field_t 26570 * num_elems - (IN) Number of elements in pyld_zero_cfg array. 26571 * Must be between 1 to bcmMirrorPayloadZeroCount 26572 * Returns: 26573 * BCM_E_XXX 26574 * Notes: 26575 * 1. This function must be called after mirror initialization, and before 26576 * programming the first MTP with payload wiping feature enabled. The values 26577 * programmed in h/w can be set only once 26578 * 2. If pyld_zero_cfg has duplicate values of 'field_id', the last entry's 26579 * (with duplicate 'field_id') protocol/port/offset values will overwrite 26580 * the previously programmed hardware register fields 26581 */ 26582 int bcm_esw_mirror_payload_zero_control_multi_set(int unit, 26583 bcm_mirror_payload_zero_info_t *pyld_zero_cfg, 26584 int num_elems) 26585 { 26586 #ifdef BCM_TOMAHAWK3_SUPPORT 26587 int i; 26588 soc_reg_t offset_reg = INVALIDr; 26589 soc_reg_t proto_port_num_reg = INVALIDr; 26590 soc_field_t offset_fld = INVALIDf; 26591 soc_field_t proto_port_num_fld = INVALIDf; 26592 int fld_len = 0; 26593 26594 /* Currently this API is supported on Tomahawk3 only */ 26595 if (!SOC_IS_TOMAHAWK3(unit)) { 26596 return BCM_E_UNAVAIL; 26597 } 26598 26599 if (pyld_zero_cfg == NULL) { 26600 return BCM_E_PARAM; 26601 } 26602 26603 if ((num_elems > bcmMirrorPayloadZeroCount) || 26604 (num_elems < bcmMirrorPayloadZeroIp4Protocol0)) { 26605 return BCM_E_PARAM; 26606 } 26607 26608 /* Loop for validation */ 26609 for (i = 0; i < num_elems; i++) { 26610 26611 if ((pyld_zero_cfg[i].field_id < bcmMirrorPayloadZeroIp4Protocol0) || 26612 (pyld_zero_cfg[i].field_id >= bcmMirrorPayloadZeroCount)) { 26613 return BCM_E_PARAM; 26614 } 26615 26616 /* Get register and field ids for the parameter */ 26617 _bcm_esw_payload_zero_reg_field_get(unit, 26618 pyld_zero_cfg[i].field_id, 26619 &offset_reg, 26620 &proto_port_num_reg, 26621 &offset_fld, 26622 &proto_port_num_fld); 26623 26624 if ((proto_port_num_reg == INVALIDr) && (offset_reg == INVALIDr)) { 26625 /* Should not happen, defensive check */ 26626 return BCM_E_INTERNAL; 26627 } 26628 26629 /* Validate protocol/port value passed */ 26630 if (proto_port_num_reg != INVALIDr) { 26631 fld_len = soc_reg_field_length(unit, proto_port_num_reg, 26632 proto_port_num_fld); 26633 if (_BCM_TH3_PAYLOAD_PARAM_RANGE_CHECK( 26634 pyld_zero_cfg[i].protocol_port_value, fld_len)) { 26635 return BCM_E_CONFIG; 26636 } 26637 } 26638 26639 /* Validate offset values passed */ 26640 if (offset_reg != INVALIDr) { 26641 fld_len = soc_reg_field_length(unit, offset_reg, offset_fld); 26642 if (_BCM_TH3_PAYLOAD_PARAM_RANGE_CHECK( 26643 pyld_zero_cfg[i].protocol_port_offset, fld_len)) { 26644 return BCM_E_CONFIG; 26645 } 26646 } 26647 } 26648 26649 /* Loop for programming registers */ 26650 for (i = 0; i < num_elems; i++) { 26651 uint32 reg_val; 26652 26653 /* Get register and field ids for the parameter */ 26654 _bcm_esw_payload_zero_reg_field_get(unit, 26655 pyld_zero_cfg[i].field_id, 26656 &offset_reg, 26657 &proto_port_num_reg, 26658 &offset_fld, 26659 &proto_port_num_fld); 26660 26661 /* Program protocol/port values after successful validtion */ 26662 if (proto_port_num_reg != INVALIDr) { 26663 BCM_IF_ERROR_RETURN(soc_reg32_get(unit, proto_port_num_reg, 26664 REG_PORT_ANY, 0, ®_val)); 26665 26666 soc_reg_field_set(unit, proto_port_num_reg, ®_val, 26667 proto_port_num_fld, 26668 pyld_zero_cfg[i].protocol_port_value); 26669 26670 BCM_IF_ERROR_RETURN(soc_reg32_set(unit, proto_port_num_reg, 26671 REG_PORT_ANY, 0, reg_val)); 26672 } 26673 26674 /* Program offset values after successful validation */ 26675 if (offset_reg != INVALIDr) { 26676 BCM_IF_ERROR_RETURN(soc_reg32_get(unit, offset_reg, 26677 REG_PORT_ANY, 0, ®_val)); 26678 26679 soc_reg_field_set(unit, offset_reg, ®_val, 26680 offset_fld, 26681 pyld_zero_cfg[i].protocol_port_offset); 26682 BCM_IF_ERROR_RETURN(soc_reg32_set(unit, offset_reg, 26683 REG_PORT_ANY, 0, reg_val)); 26684 } 26685 } 26686 26687 return BCM_E_NONE; 26688 26689 #else /* BCM_TOMAHAWK3_SUPPORT */ 26690 return BCM_E_UNAVAIL; 26691 #endif /* BCM_TOMAHAWK3_SUPPORT */ 26692 } 26693 26694 /* 26695 * Function: 26696 * bcm_esw_mirror_payload_zero_control_multi_get 26697 * Purpose: 26698 * This function returns a list of payload offset and protocol values 26699 * currently programmed in hardware 26700 * Parameters: 26701 * unit - (IN) BCM device number 26702 * pyld_zero_cfg - (IN/OUT) Array with the desired 'field_id' initialized 26703 * with a valid bcm_mirror_payload_zero_field_t 26704 * enum value, in each array member. 26705 * On return, each array member contains 26706 * protocol/port number(s), if the corresponding 26707 * field is present, and the corresponding 26708 * offset values. For cases in which protocol/port 26709 * numbers are not present, -1 is filled 26710 * (Use BCM_MIRROR_PAYLOAD_ZERO_INVALID_PROTO_PORT) 26711 * num_elems - (IN) Number of elements in pyld_zero_cfg array. 26712 * Must be between 1 to bcmMirrorPayloadZeroCount 26713 * Returns: 26714 * BCM_E_XXX 26715 * Notes: 26716 * The array size must be atleast 1 26717 */ 26718 int bcm_esw_mirror_payload_zero_control_multi_get(int unit, 26719 bcm_mirror_payload_zero_info_t *pyld_zero_cfg, 26720 int num_elems) 26721 { 26722 #ifdef BCM_TOMAHAWK3_SUPPORT 26723 int i; 26724 soc_reg_t offset_reg = INVALIDr; 26725 soc_reg_t proto_port_num_reg = INVALIDr; 26726 soc_field_t offset_fld = INVALIDf; 26727 soc_field_t proto_port_num_fld = INVALIDf; 26728 26729 /* Currently this API is supported on Tomahawk3 only */ 26730 if (!SOC_IS_TOMAHAWK3(unit)) { 26731 return BCM_E_UNAVAIL; 26732 } 26733 26734 if (pyld_zero_cfg == NULL) { 26735 return BCM_E_PARAM; 26736 } 26737 26738 if ((num_elems > bcmMirrorPayloadZeroCount) || 26739 (num_elems < bcmMirrorPayloadZeroIp4Protocol0)) { 26740 return BCM_E_PARAM; 26741 } 26742 26743 for (i = 0; i < num_elems; i++) { 26744 uint32 reg_val; 26745 uint32 fld_val; 26746 26747 if ((pyld_zero_cfg[i].field_id < bcmMirrorPayloadZeroIp4Protocol0) || 26748 (pyld_zero_cfg[i].field_id >= bcmMirrorPayloadZeroCount)) { 26749 return BCM_E_PARAM; 26750 } 26751 26752 /* Get register and field ids for the parameter */ 26753 _bcm_esw_payload_zero_reg_field_get(unit, 26754 pyld_zero_cfg[i].field_id, 26755 &offset_reg, 26756 &proto_port_num_reg, 26757 &offset_fld, 26758 &proto_port_num_fld); 26759 26760 if ((proto_port_num_reg == INVALIDr) && (offset_reg == INVALIDr)) { 26761 /* Should not happen, defensive check */ 26762 return BCM_E_INTERNAL; 26763 } 26764 26765 if (proto_port_num_reg != INVALIDr) { 26766 26767 BCM_IF_ERROR_RETURN(soc_reg32_get(unit, proto_port_num_reg, 26768 REG_PORT_ANY, 0, ®_val)); 26769 26770 fld_val = soc_reg_field_get(unit, proto_port_num_reg, reg_val, 26771 proto_port_num_fld); 26772 26773 pyld_zero_cfg[i].protocol_port_value = fld_val; 26774 } else { 26775 pyld_zero_cfg[i].protocol_port_value = 26776 BCM_MIRROR_PAYLOAD_ZERO_INVALID_PROTO_PORT; 26777 } 26778 26779 if (offset_reg != INVALIDr) { 26780 26781 BCM_IF_ERROR_RETURN(soc_reg32_get(unit, offset_reg, 26782 REG_PORT_ANY, 0, ®_val)); 26783 26784 fld_val = soc_reg_field_get(unit, offset_reg, reg_val, offset_fld); 26785 26786 pyld_zero_cfg[i].protocol_port_offset = fld_val; 26787 26788 } else { 26789 /* This should not happen */ 26790 pyld_zero_cfg[i].protocol_port_offset = 26791 BCM_MIRROR_PAYLOAD_ZERO_INVALID_OFFSET; 26792 } 26793 } 26794 26795 return BCM_E_NONE; 26796 26797 #else /* BCM_TOMAHAWK3_SUPPORT */ 26798 return BCM_E_UNAVAIL; 26799 #endif /* BCM_TOMAHAWK3_SUPPORT */ 26800 } 26801 26802 #ifdef BCM_WARM_BOOT_SUPPORT_SW_DUMP 26803 STATIC int 26804 my_i2xdigit(int digit) 26805 { 26806 digit &= 0xf; 26807 26808 return (digit > 9) ? digit - 10 + 'a' : digit + '0'; 26809 } 26810 26811 STATIC void 26812 fmt_macaddr(char buf[SAL_MACADDR_STR_LEN], sal_mac_addr_t macaddr) 26813 { 26814 int i; 26815 26816 for (i = 0; i <= 5; i++) { 26817 *buf++ = my_i2xdigit(macaddr[i] >> 4); 26818 *buf++ = my_i2xdigit(macaddr[i]); 26819 *buf++ = ':'; 26820 } 26821 26822 *--buf = 0; 26823 } 26824 26825 STATIC void 26826 fmt_ip6addr(char buf[IP6ADDR_STR_LEN], ip6_addr_t ipaddr) 26827 { 26828 sal_sprintf(buf, "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x", 26829 (((uint16)ipaddr[0] << 8) | ipaddr[1]), 26830 (((uint16)ipaddr[2] << 8) | ipaddr[3]), 26831 (((uint16)ipaddr[4] << 8) | ipaddr[5]), 26832 (((uint16)ipaddr[6] << 8) | ipaddr[7]), 26833 (((uint16)ipaddr[8] << 8) | ipaddr[9]), 26834 (((uint16)ipaddr[10] << 8) | ipaddr[11]), 26835 (((uint16)ipaddr[12] << 8) | ipaddr[13]), 26836 (((uint16)ipaddr[14] << 8) | ipaddr[15])); 26837 } 26838 26839 /* 26840 * Function: 26841 * _bcm_mirror_sw_dump 26842 * Purpose: 26843 * Displays mirror software structure information. 26844 * Parameters: 26845 * unit - Device unit number 26846 * Returns: 26847 * None 26848 */ 26849 void 26850 _bcm_mirror_sw_dump(int unit) 26851 { 26852 int idx, mode; 26853 _bcm_mirror_config_t *mcp = MIRROR_CONFIG(unit); 26854 bcm_mirror_destination_t *mdest; 26855 _bcm_mtp_config_p mtp_cfg; 26856 char ip6_str[IP6ADDR_STR_LEN]; 26857 char mac_str[SAL_MACADDR_STR_LEN]; 26858 bcm_gport_t gport; 26859 char pfmt[SOC_PBMP_FMT_LEN]; 26860 26861 LOG_CLI((BSL_META_U(unit, 26862 "\nSW Information Mirror - Unit %d\n"), unit)); 26863 mode = MIRROR_CONFIG_MODE(unit); 26864 LOG_CLI((BSL_META_U(unit, 26865 " Mode : %s\n"), 26866 (mode == BCM_MIRROR_DISABLE) ? "Disabled" : 26867 ((mode == BCM_MIRROR_L2) ? "L2" : 26868 ((mode == BCM_MIRROR_L2_L3) ? "L2_L3" : "Unknown")))); 26869 LOG_CLI((BSL_META_U(unit, 26870 " Dest Count : %4d\n"), mcp->dest_count)); 26871 if (soc_feature(unit, soc_feature_mirror_flexible)) { 26872 LOG_CLI((BSL_META_U(unit, 26873 " Max Ing MTP for Port: %4d\n"), mcp->port_im_mtp_count)); 26874 LOG_CLI((BSL_META_U(unit, 26875 " Max Eng MTP for Port: %4d\n"), mcp->port_em_mtp_count)); 26876 } else { 26877 LOG_CLI((BSL_META_U(unit, 26878 " Ing MTP Count: %4d\n"), mcp->ing_mtp_count)); 26879 LOG_CLI((BSL_META_U(unit, 26880 " Egr MTP Count: %4d\n"), mcp->egr_mtp_count)); 26881 } 26882 #ifdef BCM_TRIUMPH2_SUPPORT 26883 if (soc_feature(unit, soc_feature_egr_mirror_true)) { 26884 LOG_CLI((BSL_META_U(unit, 26885 " Egr True MTP Count: %4d\n"), 26886 mcp->egr_true_mtp_count)); 26887 } 26888 #endif /* BCM_TRIUMPH2_SUPPORT */ 26889 26890 LOG_CLI((BSL_META_U(unit, 26891 " Directed : %s\n"), 26892 MIRROR_MTP_METHOD_IS_DIRECTED_FLEXIBLE(unit) ? "Flexible" : 26893 (MIRROR_MTP_METHOD_IS_DIRECTED_LOCKED(unit) ? 26894 "Locked" : "No"))); 26895 26896 if (SOC_IS_TRX(unit) && !SOC_IS_HURRICANEX(unit) && 26897 !SOC_IS_GREYHOUND2(unit) && 26898 !soc_feature(unit, soc_feature_mirror_flexible)) { 26899 LOG_CLI((BSL_META_U(unit, 26900 " Mirror Exclusive : %s\n"), 26901 MIRROR_SWITCH_IS_EXCLUSIVE(unit) ? "Yes" : "No")); 26902 } 26903 26904 /* Mirror destinations */ 26905 for (idx = 0; idx < MIRROR_CONFIG(unit)->dest_count; idx++) { 26906 BCM_GPORT_MIRROR_SET(gport, idx); 26907 if (0 == MIRROR_DEST_REF_COUNT(unit, gport)) { 26908 continue; 26909 } 26910 26911 mdest = MIRROR_DEST(unit, gport); 26912 26913 LOG_CLI((BSL_META_U(unit, 26914 " Mirror dest(%d): 0x%08x Ref count: %4d\n"), 26915 idx, mdest->mirror_dest_id, 26916 MIRROR_DEST_REF_COUNT(unit, gport))); 26917 LOG_CLI((BSL_META_U(unit, 26918 " Gport : 0x%08x\n"), 26919 mdest->gport)); 26920 LOG_CLI((BSL_META_U(unit, 26921 " TOS : 0x%02x\n"), 26922 mdest->tos)); 26923 LOG_CLI((BSL_META_U(unit, 26924 " TTL : 0x%02x\n"), 26925 mdest->ttl)); 26926 LOG_CLI((BSL_META_U(unit, 26927 " IP Version: 0x%02x\n"), 26928 mdest->version)); 26929 if (mdest->version == 4) { 26930 LOG_CLI((BSL_META_U(unit, 26931 " Src IP : 0x%08x\n"), 26932 mdest->src_addr)); 26933 LOG_CLI((BSL_META_U(unit, 26934 " Dest IP : 0x%08x\n"), 26935 mdest->dst_addr)); 26936 } else { 26937 fmt_ip6addr(ip6_str, mdest->src6_addr); 26938 LOG_CLI((BSL_META_U(unit, 26939 " Src IP : %-42s\n"), 26940 ip6_str)); 26941 fmt_ip6addr(ip6_str, mdest->dst6_addr); 26942 LOG_CLI((BSL_META_U(unit, 26943 " Dest IP : %-42s\n"), 26944 ip6_str)); 26945 } 26946 fmt_macaddr(mac_str, mdest->src_mac); 26947 LOG_CLI((BSL_META_U(unit, 26948 " Src MAC : %-18s\n"), 26949 mac_str)); 26950 fmt_macaddr(mac_str, mdest->dst_mac); 26951 LOG_CLI((BSL_META_U(unit, 26952 " Dest MAC : %-18s\n"), 26953 mac_str)); 26954 LOG_CLI((BSL_META_U(unit, 26955 " Flow label: 0x%08x\n"), 26956 mdest->flow_label)); 26957 LOG_CLI((BSL_META_U(unit, 26958 " TPID : 0x%04x\n"), 26959 mdest->tpid)); 26960 LOG_CLI((BSL_META_U(unit, 26961 " VLAN : 0x%04x\n"), 26962 mdest->vlan_id)); 26963 26964 LOG_CLI((BSL_META_U(unit, 26965 " Flags :"))); 26966 if (mdest->flags & BCM_MIRROR_DEST_REPLACE) { 26967 LOG_CLI((BSL_META_U(unit, 26968 " Replace"))); 26969 } 26970 if (mdest->flags & BCM_MIRROR_DEST_WITH_ID) { 26971 LOG_CLI((BSL_META_U(unit, 26972 " ID provided"))); 26973 } 26974 if (mdest->flags & BCM_MIRROR_DEST_TUNNEL_L2) { 26975 LOG_CLI((BSL_META_U(unit, 26976 " L2 tunnel"))); 26977 } 26978 if (mdest->flags & BCM_MIRROR_DEST_TUNNEL_IP_GRE) { 26979 if (mdest->flags & BCM_MIRROR_DEST_TUNNEL_WITH_SEQ) { 26980 LOG_CLI((BSL_META_U(unit, 26981 " IP GRE tunnel with sequence number"))); 26982 } else { 26983 LOG_CLI((BSL_META_U(unit, 26984 " IP GRE tunnel"))); 26985 } 26986 } 26987 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_GREYHOUND_SUPPORT) 26988 if (mdest->flags & BCM_MIRROR_DEST_TUNNEL_TRILL) { 26989 LOG_CLI((BSL_META_U(unit, 26990 " TRILL tunnel"))); 26991 } 26992 if (mdest->flags & BCM_MIRROR_DEST_TUNNEL_NIV) { 26993 LOG_CLI((BSL_META_U(unit, 26994 " NIV tunnel"))); 26995 } 26996 #endif /* TRIDENT */ 26997 if (soc_feature(unit, soc_feature_port_extension)) { 26998 if (mdest->flags & BCM_MIRROR_DEST_TUNNEL_ETAG) { 26999 LOG_CLI((BSL_META_U(unit, 27000 " ETAG tunnel"))); 27001 } 27002 } 27003 27004 if (mdest->flags & BCM_MIRROR_DEST_PAYLOAD_UNTAGGED) { 27005 LOG_CLI((BSL_META_U(unit, 27006 " Untagged payload"))); 27007 } 27008 if (mdest->flags & BCM_MIRROR_DEST_PORT) { 27009 LOG_CLI((BSL_META_U(unit, 27010 " Port destination"))); 27011 } 27012 if (mdest->flags & BCM_MIRROR_DEST_FIELD) { 27013 LOG_CLI((BSL_META_U(unit, 27014 " Field destination"))); 27015 } 27016 LOG_CLI((BSL_META_U(unit, 27017 "\n"))); 27018 } 27019 27020 for (idx = 0; idx < BCM_MIRROR_MTP_COUNT; idx++) { 27021 LOG_CLI((BSL_META_U(unit, 27022 " MTP(%d).pbmp_used=%s\n"), 27023 idx, SOC_PBMP_FMT(MIRROR_CONFIG_PBMP_MTP_SLOT_USED(unit, idx), 27024 pfmt))); 27025 } 27026 27027 if (soc_feature(unit, soc_feature_mirror_flexible) && 27028 !MIRROR_MTP_METHOD_IS_DIRECTED_FLEXIBLE(unit)) { 27029 27030 for (idx = 0; idx < BCM_MIRROR_MTP_COUNT; idx++) { 27031 mtp_cfg = &MIRROR_CONFIG_SHARED_MTP(unit, idx); 27032 if (0 == mtp_cfg->ref_count) { 27033 continue; 27034 } 27035 27036 LOG_CLI((BSL_META_U(unit, 27037 " %s MTP(%d): 0x%08x Ref count: %4d\n"), 27038 (TRUE == mtp_cfg->egress) ? "Egr" : "Ing", 27039 idx, mtp_cfg->dest_id, mtp_cfg->ref_count)); 27040 } 27041 } else { 27042 /* Ingress MTPs */ 27043 for (idx = 0; idx < MIRROR_CONFIG(unit)->ing_mtp_count; idx++) { 27044 mtp_cfg = &MIRROR_CONFIG_ING_MTP(unit, idx); 27045 if (0 == mtp_cfg->ref_count) { 27046 continue; 27047 } 27048 27049 LOG_CLI((BSL_META_U(unit, 27050 " Ing MTP(%d): 0x%08x Ref count: %4d\n"), 27051 idx, mtp_cfg->dest_id, mtp_cfg->ref_count)); 27052 } 27053 27054 /* Egress MTPs */ 27055 for (idx = 0; idx < MIRROR_CONFIG(unit)->egr_mtp_count; idx++) { 27056 mtp_cfg = &MIRROR_CONFIG_EGR_MTP(unit, idx); 27057 if (0 == mtp_cfg->ref_count) { 27058 continue; 27059 } 27060 27061 LOG_CLI((BSL_META_U(unit, 27062 " Egr MTP(%d): 0x%08x Ref count: %4d\n"), 27063 idx, mtp_cfg->dest_id, mtp_cfg->ref_count)); 27064 } 27065 } 27066 27067 #ifdef BCM_TRIUMPH2_SUPPORT 27068 if (soc_feature(unit, soc_feature_egr_mirror_true)) { 27069 for (idx = 0; idx < MIRROR_CONFIG(unit)->egr_true_mtp_count; idx++) { 27070 mtp_cfg = &MIRROR_CONFIG_EGR_TRUE_MTP(unit, idx); 27071 if (0 == mtp_cfg->ref_count) { 27072 continue; 27073 } 27074 27075 LOG_CLI((BSL_META_U(unit, 27076 " Egress True MTP(%d): 0x%08x Ref count: %4d\n"), 27077 idx, mtp_cfg->dest_id, mtp_cfg->ref_count)); 27078 } 27079 } 27080 27081 if (soc_feature(unit, soc_feature_mirror_flexible) && 27082 MIRROR_MTP_METHOD_IS_DIRECTED_FLEXIBLE(unit)) { 27083 int mtp_slot, mtp_bit, mtp_type; 27084 27085 BCM_MIRROR_MTP_ITER(MIRROR_CONFIG_MTP_DEV_MASK(unit), mtp_slot) { 27086 mtp_bit = 1 << mtp_slot; 27087 if (0 != MIRROR_CONFIG_MTP_MODE_REF_COUNT(unit, mtp_slot)) { 27088 LOG_CLI((BSL_META_U(unit, 27089 " MTP slot(%d): %s Ref count: %4d\n"), 27090 mtp_slot, 27091 MIRROR_CONFIG_MTP_MODE_BMP(unit) & mtp_bit ? 27092 "Egress" : "Ingress", 27093 MIRROR_CONFIG_MTP_MODE_REF_COUNT(unit, 27094 mtp_slot))); 27095 for (mtp_type = BCM_MTP_SLOT_TYPE_PORT; 27096 mtp_type < BCM_MTP_SLOT_TYPES; 27097 mtp_type++) { 27098 if (0 != MIRROR_CONFIG_TYPE_MTP_REF_COUNT(unit, 27099 mtp_slot, mtp_type)) { 27100 LOG_CLI((BSL_META_U(unit, 27101 " MTP type(%d): %5s Ref count: %4d\n"), 27102 mtp_type, 27103 (BCM_MTP_SLOT_TYPE_PORT == mtp_type) ? "Port": ( 27104 (BCM_MTP_SLOT_TYPE_FP == mtp_type) ? "Field": 27105 "IPFIX"), 27106 MIRROR_CONFIG_TYPE_MTP_REF_COUNT(unit, 27107 mtp_slot, mtp_type))); 27108 } 27109 } 27110 } 27111 } 27112 } 27113 #endif /* BCM_TRIUMPH2_SUPPORT */ 27114 27115 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_GREYHOUND_SUPPORT) 27116 if (soc_feature(unit, soc_feature_mirror_encap_profile)) { 27117 #ifdef BCM_TRIDENT3_SUPPORT 27118 if (SOC_IS_TRIDENT3X(unit)) { 27119 return (_bcm_td3_mirror_encap_sw_dump(unit)); 27120 } else 27121 #endif /* BCM_TRIDENT3_SUPPORT */ 27122 { 27123 egr_mirror_encap_control_entry_t control_entry; 27124 egr_mirror_encap_data_1_entry_t data_1_entry; 27125 egr_mirror_encap_data_2_entry_t data_2_entry; 27126 void *entries[EGR_MIRROR_ENCAP_ENTRIES_NUM]; 27127 int i, rv, ref_count, num_entries; 27128 27129 entries[EGR_MIRROR_ENCAP_ENTRIES_CONTROL] = &control_entry; 27130 entries[EGR_MIRROR_ENCAP_ENTRIES_DATA_1] = &data_1_entry; 27131 entries[EGR_MIRROR_ENCAP_ENTRIES_DATA_2] = &data_2_entry; 27132 27133 num_entries = soc_mem_index_count(unit, EGR_MIRROR_ENCAP_CONTROLm); 27134 27135 LOG_CLI((BSL_META_U(unit, 27136 "\n Egress encap profiles\n"))); 27137 LOG_CLI((BSL_META_U(unit, 27138 " Number of entries: %d\n"), num_entries)); 27139 27140 for (i = 0; i < num_entries; i ++) { 27141 rv = soc_profile_mem_ref_count_get(unit, 27142 EGR_MIRROR_ENCAP(unit), 27143 i, &ref_count); 27144 if (SOC_FAILURE(rv)) { 27145 LOG_CLI((BSL_META_U(unit, 27146 " *** Error retrieving profile reference: %d ***\n"), 27147 rv)); 27148 break; 27149 } 27150 27151 if (ref_count <= 0) { 27152 continue; 27153 } 27154 27155 rv = soc_profile_mem_get(unit, EGR_MIRROR_ENCAP(unit), 27156 i, 1, entries); 27157 if (SOC_FAILURE(rv)) { 27158 LOG_CLI((BSL_META_U(unit, 27159 " *** Error retrieving profile data: %d ***\n"), rv)); 27160 break; 27161 } 27162 27163 LOG_CLI((BSL_META_U(unit, 27164 " %5d %8d\n"), i, ref_count)); 27165 soc_mem_entry_dump(unit, EGR_MIRROR_ENCAP_CONTROLm, 27166 entries[EGR_MIRROR_ENCAP_ENTRIES_CONTROL], BSL_LSS_CLI); 27167 LOG_CLI((BSL_META_U(unit, 27168 "\n"))); 27169 soc_mem_entry_dump(unit, EGR_MIRROR_ENCAP_DATA_1m, 27170 entries[EGR_MIRROR_ENCAP_ENTRIES_DATA_1], BSL_LSS_CLI); 27171 LOG_CLI((BSL_META_U(unit, 27172 "\n"))); 27173 soc_mem_entry_dump(unit, EGR_MIRROR_ENCAP_DATA_2m, 27174 entries[EGR_MIRROR_ENCAP_ENTRIES_DATA_2], BSL_LSS_CLI); 27175 LOG_CLI((BSL_META_U(unit, 27176 "\n"))); 27177 } 27178 } 27179 } 27180 #endif /* BCM_TRIDENT_SUPPORT || BCM_GREYHOUND_SUPPORT */ 27181 27182 return; 27183 } 27184 #endif /* BCM_WARM_BOOT_SUPPORT_SW_DUMP */