openbcm

Git mirror of https://github.com/Broadcom-Network-Switching-Software/OpenBCM
git clone git://git.finwo.net/mirror/broadcom/openbcm
Log | Files | Refs | README

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, &ether_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                       &reg_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                       &reg_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, &reg_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                                       &param0, &param1);
   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                                       &param0, &param1);
   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, &reg_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, &reg_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, &reg_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, &reg_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, &reg_val));
  17371 
  17372     if (!(enable & BCM_MIRROR_MTP_ONE)) {
  17373         /* Mtp one is available */
  17374         soc_reg_field_set(unit, MIRROR_CONTROLr, &reg_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, &reg_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, &reg_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, &reg_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, &reg_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, &reg_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, &reg_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, &reg_val);
  21175             
  21176                         if (BCM_SUCCESS(rv)) {
  21177                             soc_reg64_field32_set(unit, EGR_PORT_64r, &reg_val, 
  21178                                                   MIRROR_ENCAP_ENABLEf, 0);
  21179                             soc_reg64_field32_set(unit, EGR_PORT_64r, &reg_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, &regval,
  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, &reg_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, &reg_val, 
  22853                                       MIRROR_ENCAP_ENABLEf, 1);
  22854                 soc_reg64_field32_set(unit, EGR_PORT_64r, &reg_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, &reg_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, &reg_val, 
  22901                                           MIRROR_ENCAP_ENABLEf, 0);
  22902                 soc_reg64_field32_set(unit, EGR_PORT_64r, &reg_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, &reg_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, &reg_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                                           &reg_val, MIRROR_ENABLEf,mc_enable);
  23772         soc_reg_field_set(unit, SFLOW_ING_MIRROR_CONFIGr, &reg_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, &reg_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, &reg_val,
  23854                     (soc_field_t)mtp_idxf[mtp_slot], 0);
  23855         soc_reg_field_set(unit, INT_PROCESS_CONFIGr, &reg_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, &reg_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                           &reg_val, MIRROR_ENABLEf, mc_enable);
  23933 
  23934         soc_reg_field_set(unit, ETRAP_MONITOR_MIRROR_CONFIGr, &reg_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, &reg_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, &reg_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, &reg_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, &reg_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, &reg_val,
  24276                             MIRROR_ENABLEf, mc_enable);
  24277                 soc_reg_field_set(unit, SFLOW_ING_MIRROR_CONFIGr, &reg_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, &reg_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, &reg_val,
  24413                             MIRROR_ENABLEf, mc_enable);
  24414                 soc_reg_field_set(unit, INT_PROCESS_CONFIGr, &reg_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, &reg_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, &reg_val,
  24549                             MIRROR_ENABLEf, mc_enable);
  24550                 soc_reg_field_set(unit, ETRAP_MONITOR_MIRROR_CONFIGr, &reg_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, &reg_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, &reg_val,
  24700                             MIRROR_ENABLEf, mc_enable);
  24701                 soc_reg_field_set(unit, DLB_ECMP_MONITOR_MIRROR_CONFIGr, &reg_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, &reg_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                                           &reg_val, MIRROR_ENABLEf, mc_enable);
  24786         soc_reg_field_set(unit, DLB_ECMP_MONITOR_MIRROR_CONFIGr, &reg_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, &reg_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, &reg_val));
  26665 
  26666             soc_reg_field_set(unit, proto_port_num_reg, &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, &reg_val));
  26678 
  26679             soc_reg_field_set(unit, offset_reg, &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, &reg_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, &reg_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 */