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

ipmc.c (129457B)


      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  * IP Multicast API
      8  */
      9 
     10 #ifdef INCLUDE_L3
     11 
     12 #include <shared/bsl.h>
     13 
     14 #include <soc/drv.h>
     15 #include <soc/scache.h>
     16 #include <soc/l3x.h>
     17 #if defined(BCM_BRADLEY_SUPPORT)
     18 #include <soc/bradley.h>
     19 #endif /* BCM_BRADLEY_SUPPORT */
     20 
     21 #if defined BCM_METROLITE_SUPPORT
     22 #include <soc/katana2.h>
     23 #endif
     24 
     25 #include <bcm/error.h>
     26 #include <bcm/ipmc.h>
     27 
     28 #include <bcm_int/esw/l3.h>
     29 #include <bcm_int/esw/mbcm.h>
     30 #include <bcm_int/esw/proxy.h>
     31 #include <bcm_int/esw_dispatch.h>
     32 #include <bcm_int/esw/firebolt.h>
     33 #if defined(BCM_BRADLEY_SUPPORT)
     34 #include <bcm_int/esw/bradley.h>
     35 #endif /* BCM_BRADLEY_SUPPORT */
     36 #if defined(BCM_TRIUMPH2_SUPPORT)
     37 #include <bcm_int/esw/triumph2.h>
     38 #endif /* BCM_TRIUMPH2_SUPPORT */
     39 #if defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_KATANA2_SUPPORT)
     40 #include <bcm_int/esw/triumph3.h>
     41 #endif /* BCM_TRIUMPH3_SUPPORT */
     42 #if defined(BCM_TRIDENT2_SUPPORT)
     43 #include <bcm_int/esw/trident2.h>
     44 #endif /* BCM_TRIDENT2_SUPPORT */
     45 #if defined(BCM_KATANA_SUPPORT)
     46 #include <bcm_int/esw/katana.h>
     47 #endif /* BCM_KATANA_SUPPORT */
     48 #if defined(BCM_KATANA2_SUPPORT)
     49 #include <bcm_int/esw/katana2.h>
     50 #endif /* BCM_KATANA2_SUPPORT */
     51 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
     52 #include <bcm_int/esw/trident2plus.h>
     53 #endif /* BCM_TRIDENT2PLUS_SUPPORT */
     54 #if defined(BCM_TOMAHAWK_SUPPORT)
     55 #include <bcm_int/esw/tomahawk.h>
     56 #endif /* BCM_TOMAHAWK_SUPPORT */
     57 #if defined(BCM_HGPROXY_COE_SUPPORT)
     58 #include <bcm_int/esw/xgs5.h>
     59 #endif /* BCM_HGPROXY_COE_SUPPORT */
     60 
     61 #include <bcm_int/esw/ipmc.h>
     62 #include <bcm_int/esw/switch.h>
     63 
     64 #include <bcm_int/esw/multicast.h>
     65 #ifndef BCM_SW_STATE_DUMP_DISABLE
     66 #if defined(BCM_TRIUMPH_SUPPORT)
     67 #include <bcm_int/esw/triumph.h>
     68 #endif /* BCM_TRIUMPH_SUPPORT */
     69 #endif /* BCM_SW_STATE_DUMP_DISABLE */
     70 
     71 #include <bcm_int/common/multicast.h>
     72 #include <bcm_int/esw_dispatch.h>
     73 
     74 #ifdef BCM_TRIDENT3_SUPPORT
     75 #include <soc/esw/cancun.h>
     76 #include <soc/esw/cancun_enums.h>
     77 #endif /* BCM_TRIDENT3_SUPPORT */
     78 
     79 _bcm_esw_ipmc_t esw_ipmc_info[BCM_MAX_NUM_UNITS] = {{ 0 }};
     80 
     81 #define	IPMC_REPL_UNIT(unit) \
     82 	if (!soc_feature(unit, soc_feature_ip_mcast_repl)) \
     83         { return BCM_E_UNAVAIL; }
     84 
     85 static int _bcm_ipmc_init[BCM_MAX_NUM_UNITS];
     86 static int _bcm_ipmc_idx_ret_type[BCM_MAX_NUM_UNITS];
     87 static int _bcm_ipmc_repl_threshold[BCM_MAX_NUM_UNITS];
     88 
     89 #ifdef BCM_WARM_BOOT_SUPPORT
     90 
     91 #define BCM_WB_VERSION_1_0     SOC_SCACHE_VERSION(1,0)
     92 #define BCM_WB_VERSION_1_1     SOC_SCACHE_VERSION(1,1)
     93 #define BCM_WB_VERSION_1_2     SOC_SCACHE_VERSION(1,2)
     94 #define BCM_WB_VERSION_1_3     SOC_SCACHE_VERSION(1,3)
     95 #define BCM_WB_VERSION_1_4     SOC_SCACHE_VERSION(1,4)
     96 #define BCM_WB_VERSION_1_5     SOC_SCACHE_VERSION(1,5)
     97 #define BCM_WB_DEFAULT_VERSION BCM_WB_VERSION_1_5
     98 
     99 /* Entry 0 of the MMU_IPMC_VLAN_TBL is reserved from replication use.
    100  * We can use the MSB_VLAN bits as long as the rest is not marked
    101  * for use. This allows us to store a few IPMC-related flags for
    102  * recovery during Warm Boot.
    103  * Note that we do not check for IPMC init, because this is also used
    104  * to store the L2MC multicast group type encoding marker.  Although
    105  * this means we can only recover the L2MC group type choice with L3
    106  * support, the entire multicast module requires that, so there is no
    107  * point in using the L2MC group type multicast encoding without
    108  * L3 support.
    109  */
    110 
    111 int
    112 _bcm_esw_ipmc_repl_wb_flags_set(int unit, uint8 flags, uint8 flags_mask)
    113 {
    114 #ifdef BCM_XGS3_SWITCH_SUPPORT
    115     if (SOC_IS_XGS3_SWITCH(unit)) { 
    116         mmu_ipmc_vlan_tbl_entry_t vlan_entry;
    117 
    118 #ifdef BCM_KATANA2_SUPPORT
    119         if (SOC_IS_KATANA2(unit)) {
    120             if (SOC_MEM_IS_VALID(unit, MMU_REPL_LIST_TBLm)) {
    121                 mmu_repl_list_tbl_entry_t repl_list_entry;       
    122                 uint8 oms_bits, ms_bits;
    123 
    124                 /* Entry 0 is reserved from replication use.  We can use the
    125                  * MSB_VLANf bits as long as the rest is not marked for use. */
    126 
    127                 SOC_IF_ERROR_RETURN
    128                    (READ_MMU_REPL_LIST_TBLm(unit, MEM_BLOCK_ANY, 0,
    129                                          &repl_list_entry));
    130 
    131                 oms_bits = ms_bits =
    132                       soc_MMU_REPL_LIST_TBLm_field32_get(unit,
    133                         &repl_list_entry, MSB_VLANf);
    134                 ms_bits &= ~flags_mask;
    135                 ms_bits |= (flags & flags_mask);
    136                 ms_bits &= 0xff;
    137                 if (ms_bits != oms_bits) {
    138                     soc_MMU_REPL_LIST_TBLm_field32_set(unit, &repl_list_entry,
    139                         MSB_VLANf, ms_bits);
    140                     SOC_IF_ERROR_RETURN
    141                     (WRITE_MMU_REPL_LIST_TBLm(unit, MEM_BLOCK_ALL,
    142                                               0, &repl_list_entry));
    143                 }
    144                 return BCM_E_NONE;
    145             }
    146         } else 
    147 #endif /* BCM_KATANA2_SUPPORT */
    148 #ifdef BCM_TOMAHAWK_SUPPORT
    149         if (SOC_IS_TOMAHAWKX(unit) || SOC_IS_TRIDENT3X(unit)) {
    150             mmu_repl_list_tbl_entry_t repl_list_entry;
    151             uint16 next_hop_index_0_field;
    152 
    153             /* Entry 0 is reserved from replication use.  We can use the
    154              * NEXT_HOP_INDEX_0, 1, 2, and 3 fields as long as MODE = 1 and
    155              * MODE_1_BITMAP = 0.
    156              */
    157 #ifdef BCM_TOMAHAWK3_SUPPORT
    158            if(SOC_IS_TOMAHAWK3(unit)) {
    159                 SOC_IF_ERROR_RETURN
    160                     (READ_MMU_REPL_LIST_TBLm(unit, MEM_BLOCK_ALL,
    161                                                     0, &repl_list_entry));
    162 
    163            } else
    164 #endif
    165            {
    166                 SOC_IF_ERROR_RETURN
    167                     (READ_MMU_REPL_LIST_TBL_PIPE0m(unit, MEM_BLOCK_ANY, 0,
    168                                                        &repl_list_entry));
    169            }
    170             if (soc_mem_field_valid(unit, MMU_REPL_LIST_TBLm,
    171                                     NEXT_HOP_INDEX_0f)) {
    172                 next_hop_index_0_field = soc_MMU_REPL_LIST_TBLm_field32_get(
    173                                              unit, 
    174                                              &repl_list_entry, NEXT_HOP_INDEX_0f);
    175                 next_hop_index_0_field &= ~flags_mask;
    176                 next_hop_index_0_field |= (flags & flags_mask);
    177                 next_hop_index_0_field &= 0xffff;
    178                 soc_MMU_REPL_LIST_TBLm_field32_set(unit, &repl_list_entry,
    179                             NEXT_HOP_INDEX_0f, next_hop_index_0_field);
    180            }
    181            soc_MMU_REPL_LIST_TBLm_field32_set(unit, &repl_list_entry,
    182                                               MODEf, 1);
    183            soc_MMU_REPL_LIST_TBLm_field32_set(unit, &repl_list_entry,
    184                                               MODE_1_BITMAPf, 0);
    185 #ifdef BCM_TOMAHAWK3_SUPPORT
    186            if(SOC_IS_TOMAHAWK3(unit)) {
    187                 SOC_IF_ERROR_RETURN
    188                     (WRITE_MMU_REPL_LIST_TBLm(unit, MEM_BLOCK_ALL,
    189                                                  0, &repl_list_entry));
    190 
    191            } else
    192 #endif
    193            {
    194                 SOC_IF_ERROR_RETURN
    195                     (WRITE_MMU_REPL_LIST_TBL_PIPE0m(unit, MEM_BLOCK_ALL,
    196                                                  0, &repl_list_entry));
    197            }
    198            return BCM_E_NONE;
    199         } else
    200 #endif /* BCM_TOMAHAWK_SUPPORT */
    201 #if defined(BCM_TRIUMPH3_SUPPORT) 
    202         if (SOC_MEM_IS_VALID(unit, MMU_REPL_LIST_TBLm)) {
    203             mmu_repl_list_tbl_entry_t repl_list_entry;
    204             uint16 next_hop_index_0_field;
    205 
    206             /* Entry 0 is reserved from replication use.  We can use the
    207              * NEXT_HOP_INDEX_0, 1, 2, and 3 fields as long as MODE = 1 and
    208              * MODE_1_BITMAP = 0.
    209              */
    210             SOC_IF_ERROR_RETURN
    211                 (READ_MMU_REPL_LIST_TBLm(unit, MEM_BLOCK_ANY, 0,
    212                                              &repl_list_entry));
    213             if (soc_mem_field_valid(unit,
    214                                        MMU_REPL_LIST_TBLm, NEXT_HOP_INDEX_0f)) {
    215                 next_hop_index_0_field = soc_MMU_REPL_LIST_TBLm_field32_get(
    216                                              unit, 
    217                                              &repl_list_entry, NEXT_HOP_INDEX_0f);
    218                 next_hop_index_0_field &= ~flags_mask;
    219                 next_hop_index_0_field |= (flags & flags_mask);
    220                 next_hop_index_0_field &= 0xffff;
    221                 soc_MMU_REPL_LIST_TBLm_field32_set(unit, &repl_list_entry,
    222                             NEXT_HOP_INDEX_0f, next_hop_index_0_field);
    223            }
    224            soc_MMU_REPL_LIST_TBLm_field32_set(unit, &repl_list_entry,
    225                                               MODEf, 1);
    226            soc_MMU_REPL_LIST_TBLm_field32_set(unit, &repl_list_entry,
    227                                               MODE_1_BITMAPf, 0);
    228            SOC_IF_ERROR_RETURN
    229                  (WRITE_MMU_REPL_LIST_TBLm(unit, MEM_BLOCK_ALL,
    230                                        0, &repl_list_entry));
    231            return BCM_E_NONE;
    232         } else 
    233 #endif /* BCM_TRIUMPH3_SUPPORT */
    234 #ifdef BCM_TRIDENT_SUPPORT
    235         if (SOC_IS_TD_TT(unit)) {
    236             uint16 intf_num_0_bits;
    237 
    238             /* Entry 0 is reserved from replication use.  We can use the
    239              * INTF_NUM_0, 1, 2, and 3 fields as long as MODE = 1 and
    240              * MODE_1_BITMAP = 0.
    241              */
    242             SOC_IF_ERROR_RETURN
    243                 (READ_MMU_IPMC_VLAN_TBLm(unit, MEM_BLOCK_ALL, 0, &vlan_entry));
    244             intf_num_0_bits = soc_MMU_IPMC_VLAN_TBLm_field32_get(unit,
    245                     &vlan_entry, INTF_NUM_0f);
    246             intf_num_0_bits &= ~flags_mask;
    247             intf_num_0_bits |= (flags & flags_mask);
    248             intf_num_0_bits &= 0x3fff;
    249             soc_MMU_IPMC_VLAN_TBLm_field32_set(unit, &vlan_entry,
    250                     MODEf, 1);
    251             soc_MMU_IPMC_VLAN_TBLm_field32_set(unit, &vlan_entry,
    252                     MODE_1_BITMAPf, 0);
    253             soc_MMU_IPMC_VLAN_TBLm_field32_set(unit, &vlan_entry,
    254                     INTF_NUM_0f, intf_num_0_bits);
    255             SOC_IF_ERROR_RETURN
    256                 (WRITE_MMU_IPMC_VLAN_TBLm(unit, MEM_BLOCK_ALL,
    257                                           0, &vlan_entry));
    258             return BCM_E_NONE;
    259 
    260         } else
    261 #endif /* BCM_TRIDENT_SUPPORT */
    262         if (soc_mem_field_valid(unit, MMU_IPMC_VLAN_TBLm, MSB_VLANf)) {
    263             uint8 oms_bits, ms_bits, flen;
    264             uint32 f_bmp;
    265 
    266             /* Entry 0 is reserved from replication use.  We can use the
    267              * MSB_VLANf bits as long as the rest is not marked for use. */
    268             SOC_IF_ERROR_RETURN
    269                 (READ_MMU_IPMC_VLAN_TBLm(unit, MEM_BLOCK_ALL, 0, &vlan_entry));
    270             oms_bits = ms_bits =
    271                 soc_MMU_IPMC_VLAN_TBLm_field32_get(unit,
    272                         &vlan_entry, MSB_VLANf);
    273             ms_bits &= ~flags_mask;
    274             ms_bits |= (flags & flags_mask);
    275             flen = soc_mem_field_length(unit, MMU_IPMC_VLAN_TBLm, MSB_VLANf);
    276             /* Set the mask for MSB_VLANf */
    277             f_bmp = ((1 << flen) - 1);
    278             ms_bits &= f_bmp;
    279             if (ms_bits != oms_bits) {
    280                 soc_MMU_IPMC_VLAN_TBLm_field32_set(unit, &vlan_entry,
    281                         MSB_VLANf, ms_bits);
    282                 SOC_IF_ERROR_RETURN
    283                     (WRITE_MMU_IPMC_VLAN_TBLm(unit, MEM_BLOCK_ALL,
    284                                               0, &vlan_entry));
    285             }
    286             return BCM_E_NONE;
    287         }
    288     }
    289 #endif /* BCM_XGS3_SWITCH_SUPPORT */
    290 
    291     return BCM_E_UNAVAIL;
    292 }
    293 
    294 int
    295 _bcm_esw_ipmc_repl_wb_flags_get(int unit, uint8 flags_mask, uint8 *flags)
    296 {
    297 #ifdef BCM_XGS3_SWITCH_SUPPORT
    298     if (SOC_IS_XGS3_SWITCH(unit)) {
    299         mmu_ipmc_vlan_tbl_entry_t vlan_entry;
    300 #ifdef BCM_KATANA2_SUPPORT 
    301         if( SOC_IS_KATANA2(unit)) {
    302             if (SOC_MEM_IS_VALID(unit, MMU_REPL_LIST_TBLm)) {
    303                 mmu_repl_list_tbl_entry_t repl_list_entry;
    304                 uint8 ms_bits;
    305 
    306                 SOC_IF_ERROR_RETURN
    307                   (READ_MMU_REPL_LIST_TBLm(unit, MEM_BLOCK_ALL, 0, &repl_list_entry));
    308                 ms_bits = soc_MMU_REPL_LIST_TBLm_field32_get(unit, &repl_list_entry,
    309                           MSB_VLANf);
    310                 ms_bits &= flags_mask;
    311                 *flags = ms_bits;
    312                 return BCM_E_NONE;
    313             }
    314         } else 
    315 #endif /* BCM_KATANA2_SUPPORT */
    316 #ifdef BCM_TOMAHAWK_SUPPORT
    317         if (SOC_IS_TOMAHAWKX(unit) || SOC_IS_TRIDENT3X(unit)) {
    318             mmu_repl_list_tbl_entry_t repl_list_entry;
    319             int mode;
    320             uint16 next_hop_index_0_field;
    321 #ifdef BCM_TOMAHAWK3_SUPPORT
    322            if(SOC_IS_TOMAHAWK3(unit)) {
    323                 SOC_IF_ERROR_RETURN
    324                     (READ_MMU_REPL_LIST_TBLm(unit, MEM_BLOCK_ALL,
    325                                                     0, &repl_list_entry));
    326 
    327            } else
    328 #endif
    329            {
    330                 SOC_IF_ERROR_RETURN
    331                     (READ_MMU_REPL_LIST_TBL_PIPE0m(unit, MEM_BLOCK_ANY, 0,
    332                                                &repl_list_entry));
    333            }
    334             mode = soc_MMU_REPL_LIST_TBLm_field32_get(unit, &repl_list_entry,
    335                         MODEf);
    336             if (0 == mode) {
    337                 /* No flags have been set */
    338                 *flags = 0;
    339                 return BCM_E_NONE;
    340             }
    341             next_hop_index_0_field = soc_MMU_REPL_LIST_TBLm_field32_get(unit,
    342                                      &repl_list_entry, NEXT_HOP_INDEX_0f);
    343             next_hop_index_0_field &= flags_mask;
    344             *flags = next_hop_index_0_field;
    345             return BCM_E_NONE;
    346         } else
    347 #endif /* BCM_TOMAHAWK_SUPPORT */
    348 #if defined(BCM_TRIUMPH3_SUPPORT)
    349         if (SOC_MEM_IS_VALID(unit, MMU_REPL_LIST_TBLm)) {
    350             mmu_repl_list_tbl_entry_t repl_list_entry;
    351             int mode;
    352             uint16 next_hop_index_0_field;
    353 
    354             SOC_IF_ERROR_RETURN
    355             (READ_MMU_REPL_LIST_TBLm(unit, MEM_BLOCK_ANY, 0,
    356                                       &repl_list_entry));
    357             mode = soc_MMU_REPL_LIST_TBLm_field32_get(unit, &repl_list_entry,
    358                         MODEf);
    359             if (0 == mode) {
    360                 /* No flags have been set */
    361                 *flags = 0;
    362                 return BCM_E_NONE;
    363             }
    364             next_hop_index_0_field = soc_MMU_REPL_LIST_TBLm_field32_get(unit,
    365                                      &repl_list_entry, NEXT_HOP_INDEX_0f);
    366             next_hop_index_0_field &= flags_mask;
    367             *flags = next_hop_index_0_field;
    368             return BCM_E_NONE;
    369         } else
    370 #endif /* BCM_TRIUMPH3_SUPPORT */
    371 #ifdef BCM_TRIDENT_SUPPORT
    372         if (SOC_IS_TD_TT(unit)) {
    373             int mode;
    374             uint16 intf_num_0_bits;
    375 
    376             SOC_IF_ERROR_RETURN
    377                 (READ_MMU_IPMC_VLAN_TBLm(unit, MEM_BLOCK_ALL, 0, &vlan_entry));
    378             mode = soc_MMU_IPMC_VLAN_TBLm_field32_get(unit, &vlan_entry,
    379                     MODEf);
    380             if (0 == mode) {
    381                 /* No flags have been set */
    382                 *flags = 0;
    383                 return BCM_E_NONE;
    384             }
    385             intf_num_0_bits = soc_MMU_IPMC_VLAN_TBLm_field32_get(unit,
    386                     &vlan_entry, INTF_NUM_0f);
    387             intf_num_0_bits &= flags_mask;
    388             *flags = intf_num_0_bits;
    389             return BCM_E_NONE;
    390 
    391         } else
    392 #endif /* BCM_TRIDENT_SUPPORT */
    393         if (soc_mem_field_valid(unit, MMU_IPMC_VLAN_TBLm, MSB_VLANf)) {
    394             uint8 ms_bits;
    395 
    396             SOC_IF_ERROR_RETURN
    397                 (READ_MMU_IPMC_VLAN_TBLm(unit, MEM_BLOCK_ALL, 0, &vlan_entry));
    398             ms_bits = soc_MMU_IPMC_VLAN_TBLm_field32_get(unit, &vlan_entry,
    399                     MSB_VLANf);
    400             ms_bits &= flags_mask;
    401             *flags = ms_bits;
    402             return BCM_E_NONE;
    403         }
    404     }
    405 #endif /* BCM_XGS3_SWITCH_SUPPORT */
    406 
    407     return BCM_E_UNAVAIL;
    408 }
    409 
    410 STATIC int
    411 _bcm_esw_ipmc_repl_wb_threshold_set(int unit, int threshold)
    412 {
    413 #if defined(BCM_KATANA2_SUPPORT)
    414     if (SOC_IS_KATANA2(unit))
    415     {
    416        /* To be fixed for Katana2/Katana */
    417        return BCM_E_UNAVAIL;
    418     } else
    419 #endif /* BCM_KATANA2_SUPPORT */
    420 #ifdef BCM_TOMAHAWK_SUPPORT
    421     if (SOC_IS_TOMAHAWKX(unit) || SOC_IS_TRIDENT3X(unit)) {
    422         mmu_repl_list_tbl_entry_t repl_list_entry;
    423 
    424         /* Entry 0 is reserved from replication use.  We can use the
    425          * NEXT_HOP_INDEX_0, 1, 2, and 3 fields as long as MODE = 1 and
    426          * MODE_1_BITMAP = 0.
    427          */
    428 #ifdef BCM_TOMAHAWK3_SUPPORT
    429         if(SOC_IS_TOMAHAWK3(unit)) {
    430             SOC_IF_ERROR_RETURN
    431                 (READ_MMU_REPL_LIST_TBLm(unit, MEM_BLOCK_ALL,
    432                                             0, &repl_list_entry));
    433         } else
    434 #endif
    435         {
    436             SOC_IF_ERROR_RETURN
    437                 (READ_MMU_REPL_LIST_TBL_PIPE0m(unit, MEM_BLOCK_ANY, 0,
    438                                            &repl_list_entry));
    439         }
    440         soc_MMU_REPL_LIST_TBLm_field32_set(unit, &repl_list_entry,
    441                                            MODEf, 1);
    442         soc_MMU_REPL_LIST_TBLm_field32_set(unit, &repl_list_entry,
    443                                            MODE_1_BITMAPf, 0);
    444         if (soc_mem_field_valid(unit,MMU_REPL_LIST_TBLm, NEXT_HOP_INDEX_1f)) {
    445             threshold &= 0xffff;
    446             soc_MMU_REPL_LIST_TBLm_field32_set(unit, &repl_list_entry,
    447                                                NEXT_HOP_INDEX_1f, threshold);
    448 #ifdef BCM_TOMAHAWK3_SUPPORT
    449            if(SOC_IS_TOMAHAWK3(unit)) {
    450                 SOC_IF_ERROR_RETURN
    451                     (WRITE_MMU_REPL_LIST_TBLm(unit, MEM_BLOCK_ALL,
    452                                                 0, &repl_list_entry));
    453 
    454            } else
    455 #endif
    456             {
    457                 SOC_IF_ERROR_RETURN
    458                     (WRITE_MMU_REPL_LIST_TBL_PIPE0m(unit, MEM_BLOCK_ALL,
    459                                                 0, &repl_list_entry));
    460             }
    461         }
    462         return BCM_E_NONE;
    463     }
    464 #endif /* BCM_TOMAHAWK_SUPPORT */
    465 #if defined(BCM_TRIUMPH3_SUPPORT)     
    466     if (SOC_MEM_IS_VALID(unit, MMU_REPL_LIST_TBLm)) {
    467         mmu_repl_list_tbl_entry_t repl_list_entry;
    468 
    469         /* Entry 0 is reserved from replication use.  We can use the
    470          * NEXT_HOP_INDEX_0, 1, 2, and 3 fields as long as MODE = 1 and
    471          * MODE_1_BITMAP = 0.
    472          */
    473         SOC_IF_ERROR_RETURN
    474             (READ_MMU_REPL_LIST_TBLm(unit, MEM_BLOCK_ANY, 0,
    475                                          &repl_list_entry));
    476         soc_MMU_REPL_LIST_TBLm_field32_set(unit, &repl_list_entry,
    477                     MODEf, 1);
    478         soc_MMU_REPL_LIST_TBLm_field32_set(unit, &repl_list_entry,
    479                     MODE_1_BITMAPf, 0);
    480         if (soc_mem_field_valid(unit,MMU_REPL_LIST_TBLm, NEXT_HOP_INDEX_1f)) {
    481             threshold &= 0xffff;
    482             soc_MMU_REPL_LIST_TBLm_field32_set(unit, &repl_list_entry,
    483                     NEXT_HOP_INDEX_1f, threshold);
    484             SOC_IF_ERROR_RETURN
    485                 (WRITE_MMU_REPL_LIST_TBLm(unit, MEM_BLOCK_ALL,
    486                                           0, &repl_list_entry));
    487         }
    488         return BCM_E_NONE;
    489      } else 
    490 #endif /* BCM_TRIUMPH3_SUPPORT */
    491 #ifdef BCM_TRIDENT_SUPPORT
    492     if (SOC_IS_TD_TT(unit)) {
    493         mmu_ipmc_vlan_tbl_entry_t vlan_entry;
    494 
    495         /* Entry 0 is reserved from replication use.  We can use the
    496          * INTF_NUM_0, 1, 2, and 3 fields as long as MODE = 1 and
    497          * MODE_1_BITMAP = 0.
    498          */
    499         SOC_IF_ERROR_RETURN
    500             (READ_MMU_IPMC_VLAN_TBLm(unit, MEM_BLOCK_ALL, 0, &vlan_entry));
    501         soc_MMU_IPMC_VLAN_TBLm_field32_set(unit, &vlan_entry,
    502                 MODEf, 1);
    503         soc_MMU_IPMC_VLAN_TBLm_field32_set(unit, &vlan_entry,
    504                 MODE_1_BITMAPf, 0);
    505         threshold &= 0x3fff;
    506         soc_MMU_IPMC_VLAN_TBLm_field32_set(unit, &vlan_entry,
    507                 INTF_NUM_1f, threshold);
    508         SOC_IF_ERROR_RETURN
    509             (WRITE_MMU_IPMC_VLAN_TBLm(unit, MEM_BLOCK_ALL,
    510                                       0, &vlan_entry));
    511         return BCM_E_NONE;
    512 
    513     }
    514 #endif /* BCM_TRIDENT_SUPPORT */
    515 
    516     return BCM_E_UNAVAIL;
    517 }
    518 
    519 STATIC int
    520 _bcm_esw_ipmc_repl_wb_threshold_get(int unit, int *threshold)
    521 {
    522 #if defined (BCM_KATANA2_SUPPORT)
    523     if (SOC_IS_KATANA2(unit))
    524     {
    525        /* To be fixed for Katana2/Katana */
    526        return BCM_E_UNAVAIL;
    527     } else
    528 #endif /* BCM_KATANA2_SUPPORT */
    529 #ifdef BCM_TOMAHAWK_SUPPORT
    530     if (SOC_IS_TOMAHAWKX(unit) || SOC_IS_TRIDENT3X(unit)) {
    531         mmu_repl_list_tbl_entry_t repl_list_entry;
    532         int mode;
    533 #ifdef BCM_TOMAHAWK3_SUPPORT
    534        if(SOC_IS_TOMAHAWK3(unit)) {
    535             SOC_IF_ERROR_RETURN
    536                 (READ_MMU_REPL_LIST_TBLm(unit, MEM_BLOCK_ALL,
    537                                                 0, &repl_list_entry));
    538 
    539        } else
    540 #endif
    541        {
    542             SOC_IF_ERROR_RETURN
    543                 (READ_MMU_REPL_LIST_TBL_PIPE0m(unit, MEM_BLOCK_ANY, 0,
    544                                                &repl_list_entry));
    545        }
    546         mode = soc_MMU_REPL_LIST_TBLm_field32_get(unit, &repl_list_entry,
    547                                                   MODEf);
    548         if (0 == mode) {
    549             /* Threshold has not been set */
    550             *threshold = 0;
    551             return BCM_E_NONE;
    552         }
    553         *threshold = soc_MMU_REPL_LIST_TBLm_field32_get(unit,
    554                                                         &repl_list_entry,
    555                                                         NEXT_HOP_INDEX_1f);
    556         return BCM_E_NONE;
    557     }
    558 #endif /* BCM_TOMAHAWK_SUPPORT */
    559 #if defined(BCM_TRIUMPH3_SUPPORT) 
    560     if (SOC_MEM_IS_VALID(unit, MMU_REPL_LIST_TBLm)) {
    561         mmu_repl_list_tbl_entry_t repl_list_entry;
    562         int mode;
    563 
    564         SOC_IF_ERROR_RETURN
    565                 (READ_MMU_REPL_LIST_TBLm(unit, MEM_BLOCK_ANY, 0,
    566                                          &repl_list_entry));
    567         mode = soc_MMU_REPL_LIST_TBLm_field32_get(unit, &repl_list_entry,
    568                     MODEf);
    569         if (0 == mode) {
    570             /* Threshold has not been set */
    571             *threshold = 0;
    572             return BCM_E_NONE;
    573         }
    574         *threshold = soc_MMU_REPL_LIST_TBLm_field32_get(unit,
    575                     &repl_list_entry, NEXT_HOP_INDEX_1f);
    576         return BCM_E_NONE;
    577     } else
    578 #endif /* BCM_TRIUMPH3_SUPPORT */
    579 #ifdef BCM_TRIDENT_SUPPORT
    580     if (SOC_IS_TD_TT(unit)) {
    581         mmu_ipmc_vlan_tbl_entry_t vlan_entry;
    582         int mode;
    583 
    584         SOC_IF_ERROR_RETURN
    585             (READ_MMU_IPMC_VLAN_TBLm(unit, MEM_BLOCK_ALL, 0, &vlan_entry));
    586         mode = soc_MMU_IPMC_VLAN_TBLm_field32_get(unit, &vlan_entry,
    587                 MODEf);
    588         if (0 == mode) {
    589             /* Threshold has not been set */
    590             *threshold = 0;
    591             return BCM_E_NONE;
    592         }
    593         *threshold = soc_MMU_IPMC_VLAN_TBLm_field32_get(unit,
    594                 &vlan_entry, INTF_NUM_1f);
    595         return BCM_E_NONE;
    596 
    597     }
    598 #endif /* BCM_TRIDENT_SUPPORT */
    599 
    600     return BCM_E_UNAVAIL;
    601 }
    602 
    603 /*
    604  * Function:
    605  *      _bcm_esw_ipmc_required_scache_size_get
    606  * Purpose:
    607  *      Get required IPMC module scache size for Level 2 Warm Boot
    608  * Parameters:
    609  *      unit - StrataSwitch unit number.
    610  *      size - (OUT) Required scache size.
    611  * Returns:
    612  *      BCM_E_XXX
    613  */
    614 STATIC int
    615 _bcm_esw_ipmc_required_scache_size_get(int unit, uint32 *size)
    616 {
    617     *size = 0;
    618 
    619 #ifdef BCM_TRIDENT2_SUPPORT
    620     if (soc_feature(unit, soc_feature_pim_bidir)) {
    621         uint32 temp_size;
    622 
    623         BCM_IF_ERROR_RETURN
    624             (bcm_td2_ipmc_pim_bidir_scache_size_get(unit, &temp_size));
    625         *size += temp_size;
    626     }
    627 #endif /* BCM_TRIDENT2_SUPPORT */
    628 
    629 #ifdef BCM_TRIUMPH3_SUPPORT
    630     if (soc_feature(unit, soc_feature_repl_l3_intf_use_next_hop)) {
    631         uint32 temp_size;
    632 
    633         BCM_IF_ERROR_RETURN
    634             (bcm_tr3_ipmc_repl_l3_intf_scache_size_get(unit, &temp_size));
    635         *size += temp_size;
    636     }
    637 #endif /* BCM_TRIUMPH3_SUPPORT */
    638 
    639 #if defined(BCM_TRIDENT2PLUS_SUPPORT) || defined(BCM_TOMAHAWK_SUPPORT)
    640     if (BCM_MC_PER_TRUNK_REPL_MODE(unit)) {
    641         uint32 aggid_info_size;
    642 #if defined(BCM_TOMAHAWK_SUPPORT)
    643         if (SOC_IS_TOMAHAWKX(unit) || SOC_IS_TRIDENT3X(unit)) {
    644             BCM_IF_ERROR_RETURN
    645                 (bcm_th_ipmc_aggid_info_scache_size_get(unit, &aggid_info_size));
    646             *size += aggid_info_size;
    647         }
    648 #endif
    649 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
    650         if (SOC_IS_TRIDENT2PLUS(unit) || SOC_IS_APACHE(unit)) {
    651             BCM_IF_ERROR_RETURN
    652                 (bcm_td2p_ipmc_aggid_info_scache_size_get(unit, &aggid_info_size));
    653             *size += aggid_info_size;
    654         }
    655 #endif
    656     }
    657 #endif /* BCM_TRIDENT2PLUS_SUPPORT || BCM_TOMAHAWK_SUPPORT */
    658 
    659 #ifdef BCM_TRIUMPH3_SUPPORT
    660         if (soc_feature(unit, soc_feature_repl_l3_intf_use_next_hop)) {
    661             uint32 temp_size;
    662 #ifdef BCM_TOMAHAWK_SUPPORT
    663             if (SOC_IS_TOMAHAWKX(unit) || SOC_IS_TRIDENT3X(unit)) {
    664                 BCM_IF_ERROR_RETURN
    665                     (_bcm_th_ipmc_repl_l3_intf_nh_map_scache_size_get(unit,
    666                                                                &temp_size));
    667                 *size += temp_size;
    668             } else
    669 #endif /* BCM_TOMAHAWK_SUPPORT */
    670             {
    671                 BCM_IF_ERROR_RETURN
    672                     (bcm_tr3_ipmc_repl_l3_intf_nh_map_scache_size_get(unit,
    673                                                                &temp_size));
    674                 *size += temp_size;
    675             }
    676         }
    677 #endif /* BCM_TRIUMPH3_SUPPORT */
    678 
    679 #ifdef BCM_TRIUMPH3_SUPPORT
    680             if (soc_feature(unit, soc_feature_repl_l3_intf_use_next_hop)) {
    681                 uint32 temp_size;
    682 #ifdef BCM_TOMAHAWK_SUPPORT
    683                 if (SOC_IS_TOMAHAWKX(unit) || SOC_IS_TRIDENT3X(unit)) {
    684                     BCM_IF_ERROR_RETURN
    685                         (_bcm_th_ipmc_repl_l3_intf_trill_nh_map_scache_size_get(
    686                             unit, &temp_size));
    687                     *size += temp_size;
    688                 } else
    689 #endif /* BCM_TOMAHAWK_SUPPORT */
    690                 {
    691                     BCM_IF_ERROR_RETURN
    692                         (bcm_tr3_ipmc_repl_l3_intf_trill_nh_map_scache_size_get(
    693                             unit, &temp_size));
    694                     *size += temp_size;
    695                 }
    696             }
    697 #endif /* BCM_TRIUMPH3_SUPPORT */
    698 #ifdef BCM_KATANA_SUPPORT
    699     if ((SOC_IS_KATANA(unit)) ||
    700         (SOC_IS_KATANA2(unit) && !SOC_IS_SABER2(unit))) {
    701         uint32 temp_size;
    702         BCM_IF_ERROR_RETURN
    703             (_bcm_kt_ipmc_hw_queue_info_scache_size_get(unit, &temp_size));
    704         *size += temp_size;
    705     }
    706 #endif /* BCM_KATANA_SUPPORT */
    707 #if defined(BCM_GREYHOUND_SUPPORT)
    708             if (soc_feature(unit, soc_feature_l3mc_use_egress_next_hop)) {
    709                 uint32 temp_size;
    710                 BCM_IF_ERROR_RETURN
    711                    (_bcm_fb_ipmc_scahce_size_get(unit, &temp_size));
    712                 *size += temp_size;
    713             }
    714 #endif /* BCM_GREYHOUND_SUPPORT */
    715 
    716     return BCM_E_NONE;
    717 }
    718 
    719 /*
    720  * Function:
    721  *      _bcm_esw_ipmc_sync
    722  * Purpose:
    723  *      Record IPMC module persistent info for Level 2 Warm Boot
    724  * Parameters:
    725  *      unit - StrataSwitch unit number.
    726  * Returns:
    727  *      BCM_E_XXX
    728  */
    729 int
    730 _bcm_esw_ipmc_sync(int unit)
    731 {
    732     int rv = BCM_E_NONE;
    733     soc_scache_handle_t scache_handle;
    734     uint8 *ipmc_scache_ptr;
    735     uint32 required_scache_size;
    736 
    737     BCM_IF_ERROR_RETURN
    738         (_bcm_esw_ipmc_required_scache_size_get(unit, &required_scache_size));
    739     if (required_scache_size == 0) {
    740         /* Nothing to sync */
    741         return BCM_E_NONE;
    742     }
    743 
    744     SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_IPMC, 0);
    745     rv = _bcm_esw_scache_ptr_get(unit, scache_handle, FALSE,
    746                                  0, &ipmc_scache_ptr,
    747                                  BCM_WB_DEFAULT_VERSION, NULL);
    748     if (rv == BCM_E_NOT_FOUND) {
    749         /* For Triumph3, BCM_WB_VERSION_1_0 contains no data,
    750          * while BCM_WB_VERSION_1_1 contains the L3 interface bitmap.
    751          * When upgrading SDK from VERSION_1_0 to VERSION_1_1 on Triumph3,
    752          * _bcm_esw_ipmc_reinit will not read any data from IPMC scache since
    753          * it does not exist. Subsequently, during _bcm_esw_ipmc_sync,
    754          * _bcm_esw_scache_ptr_get will return BCM_E_NOT_FOUND. In this case,
    755          * IPMC scache needs to be created.
    756          */
    757         rv = _bcm_esw_scache_ptr_get(unit, scache_handle, TRUE,
    758                 required_scache_size, &ipmc_scache_ptr,
    759                 BCM_WB_DEFAULT_VERSION, NULL);
    760         BCM_IF_ERROR_RETURN(rv);
    761     }
    762 
    763 #ifdef BCM_TRIDENT2_SUPPORT
    764     if (soc_feature(unit, soc_feature_pim_bidir)) {
    765         BCM_IF_ERROR_RETURN
    766             (bcm_td2_ipmc_pim_bidir_sync(unit, &ipmc_scache_ptr));
    767     }
    768 #endif /* BCM_TRIDENT2_SUPPORT */
    769 
    770 #ifdef BCM_TRIUMPH3_SUPPORT
    771     if (soc_feature(unit, soc_feature_repl_l3_intf_use_next_hop)) {
    772 #ifdef BCM_TOMAHAWK_SUPPORT
    773         if (SOC_IS_TOMAHAWKX(unit) || SOC_IS_TRIDENT3X(unit)) {
    774             BCM_IF_ERROR_RETURN
    775                 (_bcm_th_ipmc_repl_l3_intf_sync(unit, &ipmc_scache_ptr));
    776         } else
    777 #endif /* BCM_TOMAHAWK_SUPPORT */
    778         {
    779             BCM_IF_ERROR_RETURN
    780                 (bcm_tr3_ipmc_repl_l3_intf_sync(unit, &ipmc_scache_ptr));
    781         }
    782     }
    783 #endif /* BCM_TRIUMPH3_SUPPORT */
    784 
    785 #if defined(BCM_TRIDENT2PLUS_SUPPORT) || defined(BCM_TOMAHAWK_SUPPORT)
    786     if (BCM_MC_PER_TRUNK_REPL_MODE(unit)) {
    787 #if defined(BCM_TOMAHAWK_SUPPORT)
    788         if (SOC_IS_TOMAHAWKX(unit) || SOC_IS_TRIDENT3X(unit)) {
    789             BCM_IF_ERROR_RETURN
    790                 (bcm_th_ipmc_aggid_info_sync(unit, &ipmc_scache_ptr));
    791         }
    792 #endif
    793 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
    794         if (SOC_IS_TRIDENT2PLUS(unit) || SOC_IS_APACHE(unit)) {
    795             BCM_IF_ERROR_RETURN
    796                 (bcm_td2p_ipmc_aggid_info_sync(unit, &ipmc_scache_ptr));
    797         }
    798 #endif
    799     }
    800 #endif /* BCM_TRIDENT2PLUS_SUPPORT || BCM_TOMAHAWK_SUPPORT */
    801 
    802 #ifdef BCM_TRIUMPH3_SUPPORT
    803         if (soc_feature(unit, soc_feature_repl_l3_intf_use_next_hop)) {
    804 #ifdef BCM_TOMAHAWK_SUPPORT
    805             if (SOC_IS_TOMAHAWKX(unit) || SOC_IS_TRIDENT3X(unit)) {
    806                 BCM_IF_ERROR_RETURN
    807                     (_bcm_th_ipmc_repl_l3_intf_nh_map_sync(unit, &ipmc_scache_ptr));
    808             } else
    809 #endif /* BCM_TOMAHAWK_SUPPORT */
    810             {
    811                 BCM_IF_ERROR_RETURN
    812                     (bcm_tr3_ipmc_repl_l3_intf_nh_map_sync(unit, &ipmc_scache_ptr));
    813             }
    814         }
    815 #endif /* BCM_TRIUMPH3_SUPPORT */
    816 
    817 #ifdef BCM_TRIUMPH3_SUPPORT
    818         if (soc_feature(unit, soc_feature_repl_l3_intf_use_next_hop)) {
    819 #ifdef BCM_TOMAHAWK_SUPPORT
    820             if (SOC_IS_TOMAHAWKX(unit) || SOC_IS_TRIDENT3X(unit)) {
    821                 BCM_IF_ERROR_RETURN
    822                     (_bcm_th_ipmc_repl_l3_intf_trill_nh_map_sync(
    823                         unit, &ipmc_scache_ptr));
    824             } else
    825 #endif /* BCM_TOMAHAWK_SUPPORT */
    826             {
    827                 BCM_IF_ERROR_RETURN
    828                     (bcm_tr3_ipmc_repl_l3_intf_trill_nh_map_sync(
    829                          unit, &ipmc_scache_ptr));
    830             }
    831         }
    832 #endif /* BCM_TRIUMPH3_SUPPORT */
    833 #if defined(BCM_KATANA_SUPPORT)
    834     if ((SOC_IS_KATANA(unit)) ||
    835         (SOC_IS_KATANA2(unit) && !SOC_IS_SABER2(unit))) {
    836         BCM_IF_ERROR_RETURN
    837            (_bcm_kt_ipmc_hw_queue_info_sync(unit, &ipmc_scache_ptr));
    838     }
    839 #endif /* BCM_KATANA_SUPPORT */
    840 
    841 #if defined(BCM_GREYHOUND_SUPPORT)
    842         if (soc_feature(unit, soc_feature_l3mc_use_egress_next_hop)) {
    843             BCM_IF_ERROR_RETURN
    844                (_bcm_fb_ipmc_sync(unit, &ipmc_scache_ptr));
    845         }
    846 #endif /* BCM_GREYHOUND_SUPPORT */
    847 
    848 
    849     return BCM_E_NONE;
    850 }
    851 
    852 STATIC int _bcm_esw_ipmc_reinit(int unit)
    853 {
    854     int rv = BCM_E_UNAVAIL;
    855     uint32 required_scache_size;
    856     soc_scache_handle_t scache_handle;
    857     uint8               *ipmc_scache_ptr;
    858     uint16              recovered_ver;
    859     uint32 additional_scache_size;
    860 #if defined(BCM_TRIDENT2PLUS_SUPPORT) || defined(BCM_TOMAHAWK_SUPPORT)
    861     uint32 aggid_info_size = 0;
    862 #endif /* BCM_TRIDENT2PLUS_SUPPORT || BCM_TOMAHAWK_SUPPORT */
    863 #if defined BCM_KATANA_SUPPORT
    864     uint32 sw_hw_queue_info_size = 0;
    865 #endif
    866 #ifdef BCM_XGS3_SWITCH_SUPPORT
    867     if (SOC_IS_XGS3_SWITCH(unit)) {
    868 #ifdef BCM_TRIUMPH_SUPPORT
    869         if (SOC_IS_TR_VL(unit)) {
    870             rv = _bcm_tr_ipmc_reinit(unit);
    871         } else
    872 #endif /* BCM_TRIUMPH_SUPPORT */
    873         if (!SOC_IS_RAPTOR(unit)) {
    874             rv = _bcm_xgs3_ipmc_reinit(unit);
    875         }
    876         if (BCM_SUCCESS(rv)) {
    877             uint8 flags;
    878             int threshold;
    879 
    880             _bcm_ipmc_init[unit] = TRUE;
    881             rv = _bcm_esw_ipmc_repl_wb_flags_get(unit,
    882                            _BCM_IPMC_WB_IPMC_GROUP_TYPE_MULTICAST, &flags);
    883             if (BCM_SUCCESS(rv)) {
    884                 _bcm_ipmc_idx_ret_type[unit] = (0 != flags);
    885             } else {
    886                 _bcm_ipmc_idx_ret_type[unit] = 0;
    887             }
    888 
    889             rv = _bcm_esw_ipmc_repl_wb_threshold_get(unit, &threshold);
    890             if (BCM_SUCCESS(rv)) {
    891                 _bcm_ipmc_repl_threshold[unit] = threshold;
    892             } else {
    893                 _bcm_ipmc_repl_threshold[unit] = 0;
    894                 rv = BCM_E_NONE;
    895             }
    896         }
    897     }
    898 #endif /* BCM_XGS3_SWITCH_SUPPORT */
    899 
    900     if (SOC_IS_XGS12_FABRIC(unit)) {
    901         rv = BCM_E_NONE;
    902     }
    903 
    904     /* Recover from IPMC scache */
    905     if (BCM_FAILURE(rv)) {
    906         return rv;
    907     }
    908 
    909     BCM_IF_ERROR_RETURN
    910         (_bcm_esw_ipmc_required_scache_size_get(unit,
    911                                                 &required_scache_size));
    912     if (required_scache_size <= 0) {
    913         return rv;
    914     }
    915 
    916     SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_IPMC, 0);
    917     rv = _bcm_esw_scache_ptr_get(unit, scache_handle, FALSE,
    918             0, &ipmc_scache_ptr,
    919             BCM_WB_DEFAULT_VERSION, &recovered_ver);
    920     if (BCM_E_NOT_FOUND == rv) {
    921         /* level 1 warmboot */
    922         rv = BCM_E_NONE;
    923         ipmc_scache_ptr = NULL;
    924     } else if (BCM_FAILURE(rv)) {
    925         return rv;
    926     } else {
    927 #ifdef BCM_TRIDENT2_SUPPORT
    928         if (soc_feature(unit, soc_feature_pim_bidir)) {
    929             /* Recovery of PIM-BIDIR info from scache needs to be done
    930              * after initialization of PIM-BIDIR data structures, which
    931              * is performed in _bcm_tr_ipmc_reinit.
    932              */
    933             BCM_IF_ERROR_RETURN
    934                 (bcm_td2_ipmc_pim_bidir_scache_recover(unit,
    935                                                        &ipmc_scache_ptr));
    936         }
    937 #endif /* BCM_TRIDENT2_SUPPORT */
    938 
    939         additional_scache_size = 0;
    940         if (recovered_ver >= BCM_WB_VERSION_1_1) {
    941 #ifdef BCM_TRIUMPH3_SUPPORT
    942             if (soc_feature(unit, soc_feature_repl_l3_intf_use_next_hop)) {
    943 #ifdef BCM_TOMAHAWK_SUPPORT
    944                 if (SOC_IS_TOMAHAWKX(unit) || SOC_IS_TRIDENT3X(unit)) {
    945                     (_bcm_th_ipmc_repl_l3_intf_scache_recover(unit,
    946                                                               &ipmc_scache_ptr));
    947                 } else
    948 #endif /* BCM_TOMAHAWK_SUPPORT */
    949                 {
    950                     BCM_IF_ERROR_RETURN
    951                         (bcm_tr3_ipmc_repl_l3_intf_scache_recover(unit,
    952                                                                   &ipmc_scache_ptr));
    953                 }
    954             }
    955 #endif /* BCM_TRIUMPH3_SUPPORT */
    956         } else {
    957 #ifdef BCM_TRIUMPH3_SUPPORT
    958             if (soc_feature(unit, soc_feature_repl_l3_intf_use_next_hop)) {
    959                 uint32 temp_size;
    960 #ifdef BCM_TOMAHAWK_SUPPORT
    961                 if (SOC_IS_TOMAHAWKX(unit) || SOC_IS_TRIDENT3X(unit)) {
    962                     BCM_IF_ERROR_RETURN
    963                         (_bcm_th_ipmc_repl_l3_intf_scache_size_get(unit,
    964                                                                    &temp_size));
    965                 } else
    966 #endif /* BCM_TOMAHAWK_SUPPORT */
    967                 {
    968                     BCM_IF_ERROR_RETURN
    969                         (bcm_tr3_ipmc_repl_l3_intf_scache_size_get(unit,
    970                                                                    &temp_size));
    971                 }
    972                 additional_scache_size += temp_size;
    973             }
    974 #endif /* BCM_TRIUMPH3_SUPPORT */
    975         }
    976 
    977 #if defined(BCM_TRIDENT2PLUS_SUPPORT) || defined(BCM_TOMAHAWK_SUPPORT)
    978         if (recovered_ver >= BCM_WB_VERSION_1_2) {
    979             if (BCM_MC_PER_TRUNK_REPL_MODE(unit)) {
    980 #if defined(BCM_TOMAHAWK_SUPPORT)
    981                 if (SOC_IS_TOMAHAWKX(unit) || SOC_IS_TRIDENT3X(unit)) {
    982                     BCM_IF_ERROR_RETURN(
    983                         bcm_th_ipmc_aggid_info_recover(
    984                             unit, &ipmc_scache_ptr));
    985                 }
    986 #endif
    987 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
    988                 if (SOC_IS_TRIDENT2PLUS(unit) || SOC_IS_APACHE(unit)) {
    989                     BCM_IF_ERROR_RETURN(
    990                         bcm_td2p_ipmc_aggid_info_recover(
    991                             unit, &ipmc_scache_ptr));
    992                 }
    993 #endif
    994             }
    995         } else {
    996             if (BCM_MC_PER_TRUNK_REPL_MODE(unit)) {
    997 #if defined(BCM_TOMAHAWK_SUPPORT)
    998                 if (SOC_IS_TOMAHAWKX(unit) || SOC_IS_TRIDENT3X(unit)) {
    999                     BCM_IF_ERROR_RETURN(
   1000                         bcm_th_ipmc_aggid_info_scache_size_get(
   1001                             unit, &aggid_info_size));
   1002                 }
   1003 #endif
   1004 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   1005                 if (SOC_IS_TRIDENT2PLUS(unit) || SOC_IS_APACHE(unit)) {
   1006                     BCM_IF_ERROR_RETURN(
   1007                         bcm_td2p_ipmc_aggid_info_scache_size_get(
   1008                             unit, &aggid_info_size));
   1009                 }
   1010 #endif
   1011                 additional_scache_size += aggid_info_size;
   1012             }
   1013         }
   1014 #endif /* BCM_TRIDENT2PLUS_SUPPORT || BCM_TOMAHAWK_SUPPORT */
   1015 
   1016         if (recovered_ver >= BCM_WB_VERSION_1_3) {
   1017 #ifdef BCM_TRIUMPH3_SUPPORT
   1018             if (soc_feature(unit, soc_feature_repl_l3_intf_use_next_hop)) {
   1019 #ifdef BCM_TOMAHAWK_SUPPORT
   1020                 if (SOC_IS_TOMAHAWKX(unit) || SOC_IS_TRIDENT3X(unit)) {
   1021                     BCM_IF_ERROR_RETURN(
   1022                         _bcm_th_ipmc_repl_l3_intf_nh_map_scache_recover(
   1023                             unit, &ipmc_scache_ptr));
   1024                 } else
   1025 #endif /* BCM_TOMAHAWK_SUPPORT */
   1026                 {
   1027                     BCM_IF_ERROR_RETURN(
   1028                         bcm_tr3_ipmc_repl_l3_intf_nh_map_scache_recover(
   1029                             unit, &ipmc_scache_ptr));
   1030                 }
   1031             }
   1032 #endif /* BCM_TRIUMPH3_SUPPORT */
   1033         } else {
   1034 #ifdef BCM_TRIUMPH3_SUPPORT
   1035             if (soc_feature(unit, soc_feature_repl_l3_intf_use_next_hop)) {
   1036                 uint32 temp_size;
   1037 #ifdef BCM_TOMAHAWK_SUPPORT
   1038                 if (SOC_IS_TOMAHAWKX(unit) || SOC_IS_TRIDENT3X(unit)) {
   1039                     BCM_IF_ERROR_RETURN(
   1040                         _bcm_th_ipmc_repl_l3_intf_nh_map_scache_size_get(
   1041                             unit, &temp_size));
   1042                 } else
   1043 #endif /* BCM_TOMAHAWK_SUPPORT */
   1044                 {
   1045                     BCM_IF_ERROR_RETURN(
   1046                         bcm_tr3_ipmc_repl_l3_intf_nh_map_scache_size_get(
   1047                             unit, &temp_size));
   1048                 }
   1049                 additional_scache_size += temp_size;
   1050             }
   1051 #endif /* BCM_TRIUMPH3_SUPPORT */
   1052         }
   1053 
   1054         if (recovered_ver >= BCM_WB_VERSION_1_4) {
   1055 #ifdef BCM_TRIUMPH3_SUPPORT
   1056             if (soc_feature(unit, soc_feature_repl_l3_intf_use_next_hop)) {
   1057 #ifdef BCM_TOMAHAWK_SUPPORT
   1058                 if (SOC_IS_TOMAHAWKX(unit) || SOC_IS_TRIDENT3X(unit)) {
   1059                     BCM_IF_ERROR_RETURN(
   1060                         _bcm_th_ipmc_repl_l3_intf_trill_nh_map_scache_recover(
   1061                             unit, &ipmc_scache_ptr));
   1062                 } else
   1063 #endif /* BCM_TOMAHAWK_SUPPORT */
   1064                 {
   1065                     BCM_IF_ERROR_RETURN(
   1066                         bcm_tr3_ipmc_repl_l3_intf_trill_nh_map_scache_recover(
   1067                             unit, &ipmc_scache_ptr));
   1068                 }
   1069             }
   1070 #endif /* BCM_TRIUMPH3_SUPPORT */
   1071         } else {
   1072 #ifdef BCM_TRIUMPH3_SUPPORT
   1073             if (soc_feature(unit, soc_feature_repl_l3_intf_use_next_hop)) {
   1074                 uint32 temp_size;
   1075 #ifdef BCM_TOMAHAWK_SUPPORT
   1076                 if (SOC_IS_TOMAHAWKX(unit) || SOC_IS_TRIDENT3X(unit)) {
   1077                     BCM_IF_ERROR_RETURN(
   1078                         _bcm_th_ipmc_repl_l3_intf_trill_nh_map_scache_size_get(
   1079                             unit, &temp_size));
   1080                 } else
   1081 #endif /* BCM_TOMAHAWK_SUPPORT */
   1082                 {
   1083                     BCM_IF_ERROR_RETURN(
   1084                         bcm_tr3_ipmc_repl_l3_intf_trill_nh_map_scache_size_get(
   1085                             unit, &temp_size));
   1086                 }
   1087                 additional_scache_size += temp_size;
   1088             }
   1089 #endif /* BCM_TRIUMPH3_SUPPORT */
   1090         }
   1091 
   1092         if (recovered_ver >= BCM_WB_VERSION_1_5) {
   1093 #if defined(BCM_KATANA_SUPPORT)
   1094             if ((SOC_IS_KATANA(unit)) ||
   1095                 (SOC_IS_KATANA2(unit) && !SOC_IS_SABER2(unit))) {
   1096                 BCM_IF_ERROR_RETURN(
   1097                     _bcm_kt_ipmc_hw_queue_info_recover(
   1098                         unit, &ipmc_scache_ptr));
   1099             }
   1100 #endif /* BCM_KATANA_SUPPORT */
   1101         } else {
   1102 #if defined(BCM_KATANA_SUPPORT)
   1103             if ((SOC_IS_KATANA(unit)) ||
   1104                 (SOC_IS_KATANA2(unit) && !SOC_IS_SABER2(unit))) {
   1105                 BCM_IF_ERROR_RETURN(
   1106                     _bcm_kt_ipmc_hw_queue_info_scache_size_get(
   1107                         unit, &sw_hw_queue_info_size));
   1108             }
   1109             additional_scache_size += sw_hw_queue_info_size;
   1110 #endif /* BCM_KATANA_SUPPORT */
   1111         }
   1112 #if defined(BCM_GREYHOUND_SUPPORT)
   1113             if (soc_feature(unit, soc_feature_l3mc_use_egress_next_hop)) {
   1114                 uint32 temp_size;
   1115                 BCM_IF_ERROR_RETURN
   1116                    (_bcm_fb_ipmc_repl_scache_recover(unit, &ipmc_scache_ptr));
   1117                 BCM_IF_ERROR_RETURN
   1118                    (_bcm_fb_ipmc_scahce_size_get(unit, &temp_size));
   1119                 additional_scache_size += temp_size;
   1120             }
   1121 #endif /* BCM_GREYHOUND_SUPPORT */
   1122 
   1123 
   1124         if (additional_scache_size > 0) {
   1125             SOC_IF_ERROR_RETURN(soc_scache_realloc(unit, scache_handle,
   1126                         additional_scache_size));
   1127         }
   1128     }
   1129 
   1130     return rv;
   1131 }
   1132 #endif /* BCM_WARM_BOOT_SUPPORT */
   1133 
   1134 
   1135 
   1136 /*
   1137  * Function:
   1138  *	    _bcm_esw_ipmc_gport_construct
   1139  * Description:
   1140  *	    Constructs gport from port, modid or trunk given in the data structure
   1141  *	    if bcmSwitchUseGport is set. 
   1142  * Parameters:
   1143  *	    unit - StrataSwitch PCI device unit number (driver internal).
   1144  *      data - (IN/OUT) data structure to use in order to construct a gport
   1145  * Returns:
   1146  *	    BCM_E_XXX
   1147  */
   1148 
   1149 STATIC int 
   1150 _bcm_esw_ipmc_gport_construct(int unit, bcm_ipmc_addr_t *data)
   1151 {
   1152     int                 isGport, rv;
   1153     bcm_gport_t         gport;
   1154     _bcm_gport_dest_t   dest;
   1155     bcm_module_t        mymodid;
   1156 #if defined(BCM_KATANA2_SUPPORT)
   1157     bcm_port_t          pp_port;
   1158     int                 min_subport = SOC_INFO(unit).pp_port_index_min;
   1159     int                 max_subport = SOC_INFO(unit).pp_port_index_max;
   1160 #endif
   1161 #if defined(BCM_KATANA2_SUPPORT) || defined(BCM_HGPROXY_COE_SUPPORT)
   1162     int                 is_local_subport = 0;
   1163 #endif
   1164 
   1165     if (NULL == data) {
   1166         return BCM_E_PARAM;
   1167     }
   1168 
   1169     BCM_IF_ERROR_RETURN(
   1170         bcm_esw_switch_control_get(unit, bcmSwitchUseGport, &isGport));
   1171 
   1172     /* if output should not be gport then do nothing*/
   1173     if (!isGport) {
   1174         return BCM_E_NONE;
   1175     }
   1176 
   1177 #if defined(BCM_HGPROXY_COE_SUPPORT)
   1178     if (soc_feature(unit, soc_feature_hgproxy_subtag_coe)) {
   1179 
   1180         if(_bcm_xgs5_subport_coe_mod_port_local(unit, data->mod_id,
   1181                                                 data->port_tgid)) {
   1182             is_local_subport = 1;
   1183 
   1184             /* Encode parameter as GPORT_SUBPORT type and fill in the
   1185                associated (mod,port) */
   1186             _BCM_SUBPORT_COE_PORT_ID_SET(gport, data->mod_id, data->port_tgid);
   1187 
   1188             /* Set the bit on the outgoing param indicating this is subtag type */
   1189             _BCM_SUBPORT_COE_PORT_TYPE_SET(gport, _BCM_SUBPORT_COE_TYPE_SUBTAG);
   1190         }
   1191     } 
   1192 #endif
   1193 #if defined(BCM_KATANA2_SUPPORT)
   1194     if (soc_feature(unit, soc_feature_linkphy_coe) ||
   1195         soc_feature(unit, soc_feature_subtag_coe)) {
   1196         /* For LinkPHY/SubportPktTag pp_ports, check if the mod is valid */
   1197         if ((_bcm_kt2_mod_is_coe_mod_check(unit, data->mod_id) == BCM_E_NONE)
   1198             && !(data->ts)) {
   1199             BCM_IF_ERROR_RETURN(_bcm_kt2_modport_to_pp_port_get(unit,
   1200                 data->mod_id, data->port_tgid, &pp_port));
   1201             /*For KT2, pp_port >=42 are used for LinkPHY/SubportPktTag subport.
   1202             * Get the subport info associated with the pp_port and form the
   1203             * subport_gport */
   1204 #if defined BCM_METROLITE_SUPPORT
   1205             if (soc_feature(unit, soc_feature_discontinuous_pp_port)) {
   1206                 if (_SOC_IS_PP_PORT_LINKPHY_SUBTAG(unit, pp_port)) {
   1207                     is_local_subport = 1;
   1208                     /* construct LinkPHY/SubportPkttag subport gport */
   1209                     _BCM_KT2_SUBPORT_PORT_ID_SET(gport, pp_port);
   1210                     if (BCM_PBMP_MEMBER(
   1211                                 SOC_INFO(unit).linkphy_pp_port_pbm, pp_port)) {
   1212                         _BCM_KT2_SUBPORT_PORT_TYPE_SET(gport,
   1213                                 _BCM_KT2_SUBPORT_TYPE_LINKPHY);
   1214                     } else if (BCM_PBMP_MEMBER(
   1215                                 SOC_INFO(unit).subtag_pp_port_pbm, pp_port)) {
   1216                         _BCM_KT2_SUBPORT_PORT_TYPE_SET(gport,
   1217                                 _BCM_KT2_SUBPORT_TYPE_SUBTAG);
   1218                     } else {
   1219                         return BCM_E_PORT;
   1220                     }
   1221                 }
   1222             } else
   1223 #endif
   1224             {            
   1225                 if ((pp_port >= min_subport) &&
   1226                     (pp_port <= max_subport)) {
   1227                     is_local_subport = 1;
   1228                     /* construct LinkPHY/SubportPkttag subport gport */
   1229                     _BCM_KT2_SUBPORT_PORT_ID_SET(gport, pp_port);
   1230                     if (BCM_PBMP_MEMBER(
   1231                                 SOC_INFO(unit).linkphy_pp_port_pbm, pp_port)) {
   1232                         _BCM_KT2_SUBPORT_PORT_TYPE_SET(gport,
   1233                                 _BCM_KT2_SUBPORT_TYPE_LINKPHY);
   1234                     } else if (BCM_PBMP_MEMBER(
   1235                                 SOC_INFO(unit).subtag_pp_port_pbm, pp_port)) {
   1236                         _BCM_KT2_SUBPORT_PORT_TYPE_SET(gport,
   1237                                 _BCM_KT2_SUBPORT_TYPE_SUBTAG);
   1238                     } else {
   1239                         return BCM_E_PORT;
   1240                     }
   1241                 }
   1242             }
   1243         }
   1244     }
   1245 #endif
   1246 
   1247 #if defined(BCM_KATANA2_SUPPORT) || defined(BCM_HGPROXY_COE_SUPPORT)
   1248     if (is_local_subport) {
   1249         /* gport assigned above */
   1250     } else
   1251 #endif
   1252     {
   1253         _bcm_gport_dest_t_init(&dest);
   1254     
   1255         if (data->ts) {
   1256             dest.tgid = data->port_tgid;
   1257             dest.gport_type = _SHR_GPORT_TYPE_TRUNK;
   1258         } else {
   1259             /* Stacking ports should be encoded as devport */
   1260             if (IS_ST_PORT(unit, data->port_tgid)) {
   1261                 rv = bcm_esw_stk_my_modid_get(unit, &mymodid);
   1262                 if (BCM_E_UNAVAIL == rv) {
   1263                     dest.gport_type = _SHR_GPORT_TYPE_DEVPORT;
   1264                 } else {
   1265                     dest.gport_type = _SHR_GPORT_TYPE_MODPORT;
   1266                     dest.modid = data->mod_id;
   1267                 }
   1268             } else {
   1269                 dest.modid = data->mod_id;
   1270                 dest.gport_type = _SHR_GPORT_TYPE_MODPORT;
   1271             }
   1272             dest.port = data->port_tgid;
   1273         }
   1274         BCM_IF_ERROR_RETURN(
   1275             _bcm_esw_gport_construct(unit, &dest, &gport));
   1276     }
   1277     data->port_tgid = gport;
   1278     return BCM_E_NONE;
   1279 }
   1280 
   1281 
   1282 /*
   1283  * Function:
   1284  *	    _bcm_esw_ipmc_gport_resolve
   1285  * Description:
   1286  *	    Resolve port, modid or trunk from given gport. 
   1287  * Parameters:
   1288  *	    unit - StrataSwitch PCI device unit number (driver internal).
   1289  *      gport - given gport
   1290  *      port  - (Out) physical port encoded in gport
   1291  *      modid - (Out) module id encoded in gport 
   1292  *      tgid  - (Out) Trunk group ID encoded in gport
   1293  *      tbit  - (Out) Trunk indicator 1 if trunk encoded in gport 0 otherwise
   1294  *      isPortLocal - Indicator if port encoded in gport must be only local physical port
   1295  * Returns:
   1296  *	    BCM_E_XXX
   1297  */
   1298 
   1299 STATIC int 
   1300 _bcm_esw_ipmc_gport_resolve(int unit, bcm_gport_t gport, bcm_port_t *port, 
   1301                             bcm_module_t *modid, bcm_trunk_t *tgid, int *tbit,
   1302                             int isPortLocal)
   1303 {
   1304     int id;
   1305     bcm_trunk_t     local_tgid;
   1306     bcm_module_t    local_modid;
   1307     bcm_port_t      local_port;
   1308 #if defined(BCM_KATANA2_SUPPORT)
   1309     int             pp_port = -1;
   1310     int             my_modid;
   1311     int             min_subport = SOC_INFO(unit).pp_port_index_min;
   1312     int             max_subport = SOC_INFO(unit).pp_port_index_max;
   1313 #endif
   1314 #if defined(BCM_KATANA2_SUPPORT) || defined(BCM_HGPROXY_COE_SUPPORT)
   1315     int             is_local_subport = 0;
   1316 #endif
   1317 
   1318     if ((NULL == port) || (NULL == modid) || (NULL == tgid) ||
   1319         (NULL == tbit) ) {
   1320         return BCM_E_PARAM;
   1321     }
   1322 
   1323     BCM_IF_ERROR_RETURN(
   1324         _bcm_esw_gport_resolve(unit, gport,
   1325             &local_modid, &local_port, &local_tgid, &id));
   1326 
   1327 
   1328 #if defined(BCM_HGPROXY_COE_SUPPORT)
   1329     if (soc_feature(unit, soc_feature_hgproxy_subtag_coe) &&
   1330         _BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, gport)) {
   1331         if(_bcm_xgs5_subport_coe_mod_port_local(unit, local_modid, local_port)) {
   1332             is_local_subport = 1;
   1333         }
   1334 
   1335         *port = local_port;
   1336         *modid = local_modid;
   1337         *tbit = 0;
   1338         if (isPortLocal) {
   1339             if (is_local_subport == 0) {
   1340                 return BCM_E_PARAM;
   1341             }
   1342         }
   1343         return BCM_E_NONE;
   1344     } else
   1345 #endif
   1346 #if defined(BCM_KATANA2_SUPPORT)
   1347     if (BCM_GPORT_IS_SET(gport) &&
   1348         _BCM_KT2_GPORT_IS_LINKPHY_OR_SUBTAG_SUBPORT_GPORT(unit, gport)) {
   1349         BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &my_modid));
   1350         if (_bcm_kt2_mod_is_coe_mod_check(unit, local_modid) == BCM_E_NONE) {
   1351             pp_port = BCM_GPORT_SUBPORT_PORT_GET(gport);
   1352 #if defined BCM_METROLITE_SUPPORT
   1353             if (soc_feature(unit, soc_feature_discontinuous_pp_port)) {
   1354                 if (_SOC_IS_PP_PORT_LINKPHY_SUBTAG(unit, pp_port)) {
   1355                     is_local_subport = 1;
   1356                 }
   1357             } else
   1358 #endif
   1359             {
   1360                 if ((pp_port >= min_subport) &&
   1361                     (pp_port <= max_subport)) {
   1362                     is_local_subport = 1;
   1363                 }
   1364             }
   1365         }
   1366         *port = local_port;
   1367         *modid = local_modid;
   1368         *tbit = 0;
   1369         if (isPortLocal) {
   1370             if (is_local_subport == 0) {
   1371                 return BCM_E_PARAM;
   1372             }
   1373         }
   1374         return BCM_E_NONE;
   1375     } else
   1376 #endif
   1377     {
   1378         if (-1 != id) {
   1379             return BCM_E_PORT;
   1380         }
   1381     }
   1382 
   1383     if (BCM_TRUNK_INVALID != local_tgid) {
   1384         *tgid = local_tgid;
   1385         *tbit = 1;
   1386     } else {
   1387         *port = local_port;
   1388         *modid = local_modid;
   1389         *tbit = 0;
   1390         if (isPortLocal) {
   1391             int    ismymodid;
   1392 
   1393             BCM_IF_ERROR_RETURN(
   1394                 _bcm_esw_modid_is_local(unit, local_modid, &ismymodid));
   1395             if (ismymodid != TRUE) {
   1396                 return BCM_E_PARAM;
   1397             }
   1398         }
   1399     }
   1400 
   1401     return BCM_E_NONE;
   1402 }
   1403 
   1404 /*
   1405  * Function:
   1406  *      bcm_esw_multicast_ipmc_group_type_get
   1407  * Description:
   1408  *      Get multicast group type associated with given IPMC group
   1409  *
   1410  * Parameters:
   1411  *      unit                - (IN) unit number
   1412  *      ipmc_id             - (IN) IPMC entry id
   1413  *      group               - (IN) group type
   1414  * Return Value:
   1415  *      BCM_E_XXX
   1416  * Notes:
   1417  */
   1418 bcm_error_t bcm_esw_multicast_ipmc_group_type_get(
   1419             int unit,
   1420             uint32 ipmc_id,
   1421             bcm_multicast_t *group)
   1422 {
   1423     int rv = BCM_E_NOT_FOUND;
   1424 
   1425 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   1426     if(soc_feature(unit, soc_feature_ipmc_l2_use_vlan_vpn) &&
   1427             soc_property_get(unit, spn_IPMC_L2_USE_VLAN_VPN, 0)){
   1428         rv = _bcm_tr_multicast_ipmc_group_type_get(unit, ipmc_id, group);
   1429     }
   1430 #endif
   1431     if (rv == BCM_E_NOT_FOUND)
   1432     {
   1433         /* default to _BCM_MULTICAST_TYPE_L3 */
   1434         _BCM_MULTICAST_GROUP_SET(*group, _BCM_MULTICAST_TYPE_L3, ipmc_id);
   1435         return BCM_E_NONE;
   1436     } else {
   1437         return rv;
   1438     }
   1439 }
   1440 
   1441 /*
   1442  * Function:
   1443  *      _bcm_esw_ipmc_convert_mcindex_m2h
   1444  * Purpose:
   1445  *      Convert a bcm_multicast_t ipmc index to a hardware ipmc index.
   1446  * Parameters:
   1447  *	mcindex - (IN/OUT) Pointer to a multicast index 
   1448  * Returns:
   1449  *      BCM_E_NONE
   1450  *      BCM_E_PARAM   If bcm_multicast_t is not L3 type 
   1451  */
   1452 
   1453 STATIC int
   1454 _bcm_esw_ipmc_convert_mcindex_m2h(int *mcindex)
   1455 {
   1456     /* If the input parameter mcindex is a L3 type bcm_multicast_t, 
   1457      * convert it to a hardware ipmc index.
   1458      */
   1459     if (_BCM_MULTICAST_IS_SET(*mcindex)) {
   1460         if (_BCM_MULTICAST_IS_L3(*mcindex)) {
   1461             *mcindex = _BCM_MULTICAST_ID_GET(*mcindex);
   1462         } else {
   1463             return BCM_E_PARAM;
   1464         }
   1465     }
   1466 
   1467     return BCM_E_NONE;
   1468 }
   1469 
   1470 /*
   1471  * Function:
   1472  *      _bcm_esw_ipmc_convert_mcindex_h2m
   1473  * Purpose:
   1474  *      Convert a hardware ipmc index to a bcm_multicast_t ipmc index,
   1475  *      if the global property _bcm_ipmc_idx_ret_type[unit] is set.
   1476  * Parameters:
   1477  *      unit - unit number.
   1478  *	mcindex - (IN/OUT) Pointer to a multicast index 
   1479  * Returns:
   1480  *      None.
   1481  */
   1482 
   1483 STATIC void
   1484 _bcm_esw_ipmc_convert_mcindex_h2m(int unit, int *mcindex)
   1485 {
   1486     if (_bcm_ipmc_idx_ret_type[unit]) {
   1487         /* Convert hardware ipmc index to a L3 type bcm_multicast_t */
   1488         _BCM_MULTICAST_GROUP_SET(*mcindex, _BCM_MULTICAST_TYPE_L3, *mcindex);
   1489     }
   1490 }
   1491 
   1492 /*
   1493  * Function:
   1494  *	bcm_esw_ipmc_init
   1495  * Description:
   1496  *	Initialize the IPMC module and enable IPMC support. This
   1497  *	function will enable the source port checking and the
   1498  *	search rule to include source IP checking.
   1499  * Parameters:
   1500  *	unit - StrataSwitch PCI device unit number (driver internal).
   1501  * Returns:
   1502  *	BCM_E_XXX
   1503  * Notes:
   1504  *	This function has to be called before any other IPMC functions.
   1505  */
   1506 
   1507 int
   1508 bcm_esw_ipmc_init(int unit)
   1509 {
   1510     int         rv;
   1511 
   1512 #ifdef BCM_WARM_BOOT_SUPPORT
   1513     soc_scache_handle_t scache_handle;
   1514     uint32              required_scache_size;
   1515     uint8               *ipmc_scache_ptr;
   1516 #endif /* BCM_WARM_BOOT_SUPPORT */
   1517 
   1518     if (!soc_feature(unit, soc_feature_ip_mcast)) {
   1519         return BCM_E_UNAVAIL;
   1520     }
   1521 
   1522     LOG_INFO(BSL_LS_BCM_IPMC,
   1523              (BSL_META_U(unit,
   1524                          "IPMC %d: Init\n"),
   1525               unit));
   1526 
   1527 #ifdef BCM_WARM_BOOT_SUPPORT
   1528     if (SOC_WARM_BOOT(unit)) {
   1529         return (_bcm_esw_ipmc_reinit(unit));
   1530     }
   1531 #endif /* BCM_WARM_BOOT_SUPPORT */
   1532     rv = mbcm_driver[unit]->mbcm_ipmc_init(unit);
   1533 
   1534     if (rv >= 0 && soc_feature(unit, soc_feature_ip_mcast_repl)) {
   1535         rv = mbcm_driver[unit]->mbcm_ipmc_repl_init(unit);
   1536     }
   1537 
   1538 #ifdef BCM_WARM_BOOT_SUPPORT
   1539     if (!SOC_WARM_BOOT(unit)) {
   1540         BCM_IF_ERROR_RETURN
   1541             (_bcm_esw_ipmc_required_scache_size_get(unit, &required_scache_size));
   1542         if (required_scache_size > 0) {
   1543             SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_IPMC, 0);
   1544             rv = _bcm_esw_scache_ptr_get(unit, scache_handle,
   1545                     TRUE,
   1546                     required_scache_size, &ipmc_scache_ptr,
   1547                     BCM_WB_DEFAULT_VERSION, NULL);
   1548             if (BCM_FAILURE(rv) && (rv != BCM_E_NOT_FOUND)) {
   1549                 return rv;
   1550             }
   1551             rv = BCM_E_NONE;
   1552         }
   1553     }
   1554 #endif /* BCM_WARM_BOOT_SUPPORT */
   1555 
   1556     /*
   1557      * Note: for Lynx, egress_port_init requires ipmc_repl_init to have
   1558      * been done already.
   1559      */
   1560 
   1561     if (rv >= 0) {
   1562         rv = bcm_esw_ipmc_egress_port_init(unit);
   1563     }
   1564 
   1565     if (rv >= 0) {
   1566         _bcm_ipmc_init[unit] = TRUE;
   1567         _bcm_ipmc_idx_ret_type[unit] = 0;
   1568         _bcm_ipmc_repl_threshold[unit] = 0;
   1569 #ifdef BCM_WARM_BOOT_SUPPORT
   1570         rv = _bcm_esw_ipmc_repl_wb_threshold_set(unit, 0);
   1571         if (BCM_E_UNAVAIL == rv) {
   1572             rv = BCM_E_NONE;
   1573         } else if (BCM_FAILURE(rv)) {
   1574             return rv;
   1575         }
   1576 #endif /* BCM_WARM_BOOT_SUPPORT */
   1577     }
   1578 
   1579 #if defined(BCM_XGS3_SWITCH_SUPPORT) && defined(INCLUDE_L3)
   1580     if (SOC_IS_XGS3_SWITCH(unit) && !(SOC_IS_KATANAX(unit))) {
   1581         int ipmc_id = 0;
   1582         /* reserve L3_IPMC entry 0 for default behavior */
   1583         /* for Katana and Katana2 0 and 1 get reserved from inside 
   1584          * bcm_tr2_ipmc_repl_init() and
   1585          * bcm_kt2_ipmc_repl_init
   1586          */ 
   1587         BCM_IF_ERROR_RETURN(bcm_xgs3_ipmc_create(unit, &ipmc_id));
   1588     }
   1589 #endif
   1590 
   1591     return rv;
   1592 }
   1593 
   1594 /*
   1595  * Function:
   1596  *	bcm_esw_ipmc_detach
   1597  * Description:
   1598  *	Delete all entries of the IPMC table.
   1599  * Parameters:
   1600  *	unit - StrataSwitch PCI device unit number (driver internal).
   1601  * Returns:
   1602  *	BCM_E_XXX
   1603  */
   1604 
   1605 int
   1606 bcm_esw_ipmc_detach(int unit)
   1607 {
   1608     int         rv = BCM_E_NONE;
   1609 
   1610     if (!_bcm_ipmc_init[unit]) {
   1611         return (rv);
   1612     }
   1613 
   1614     LOG_INFO(BSL_LS_BCM_IPMC,
   1615              (BSL_META_U(unit,
   1616                          "IPMC %d: Detach\n"),
   1617               unit));
   1618     if (soc_feature(unit, soc_feature_ip_mcast_repl)) {
   1619         rv = mbcm_driver[unit]->mbcm_ipmc_repl_detach(unit);
   1620     }
   1621 
   1622     if (rv >= 0) {
   1623         rv = mbcm_driver[unit]->mbcm_ipmc_detach(unit);
   1624     }
   1625 
   1626     if (rv >= 0) {
   1627 	_bcm_ipmc_init[unit] = FALSE;
   1628     }
   1629 
   1630     return rv;
   1631 }
   1632 
   1633 /*
   1634  * Function:
   1635  *	bcm_esw_ipmc_enable
   1636  * Description:
   1637  *	Enable/disable IPMC support.
   1638  * Parameters:
   1639  *	unit - StrataSwitch PCI device unit number (driver internal).
   1640  *	enable - 1: enable IPMC support.
   1641  *		0: disable IPMC support.
   1642  * Returns:
   1643  *	BCM_E_XXX
   1644  */
   1645 
   1646 int
   1647 bcm_esw_ipmc_enable(int unit, int enable)
   1648 {
   1649     IPMC_INIT(unit);
   1650 
   1651     LOG_INFO(BSL_LS_BCM_IPMC,
   1652              (BSL_META_U(unit,
   1653                          "IPMC %d: %sable\n"),
   1654               unit, enable ? "En" : "Dis"));
   1655     return mbcm_driver[unit]->mbcm_ipmc_enable(unit, enable);
   1656 }
   1657 
   1658 /*
   1659  * Function:
   1660  *      _bcm_esw_ipmc_key_validate
   1661  * Description:
   1662  *      Validate ipmc lookup key 
   1663  * Parameters:
   1664  *      unit - StrataSwitch PCI device unit number (driver internal).
   1665  *	    data - IPMC entry information.
   1666  * Returns:
   1667  *      BCM_E_XXX
   1668  */
   1669 
   1670 STATIC int
   1671 _bcm_ipmc_key_validate(int unit, bcm_ipmc_addr_t *data)
   1672 {
   1673     bcm_if_t l3iif = 0;
   1674     uint8 l3iif_validate = 0;
   1675     /* Make sure ipmc was initialized on the device. */
   1676     IPMC_INIT(unit);
   1677 
   1678     /* Input parameters check. */
   1679     if (NULL == data) {
   1680         return (BCM_E_PARAM);
   1681     }
   1682 
   1683     /* Validate vrf range. */
   1684     if ((data->vrf > SOC_VRF_MAX(unit)) ||
   1685         (data->vrf < BCM_L3_VRF_DEFAULT)) {
   1686         return (BCM_E_PARAM);
   1687     }
   1688 
   1689     /* IPv6 support check. */ 
   1690     if ((data->flags & BCM_IPMC_IP6) && !SOC_IS_XGS3_SWITCH(unit)) {
   1691         if (!_bcm_proxy_client_enabled(unit)) {
   1692             return (BCM_E_UNAVAIL);
   1693         } else {
   1694             data->flags |= BCM_IPMC_PROXY_IP6;
   1695         }
   1696     }
   1697 
   1698      if (!(data->flags & BCM_IPMC_L2) && (data->ing_intf != BCM_IF_INVALID)) {
   1699         /* if BCM_IPMC_L2 is not set then validate ing_intf */
   1700            l3iif_validate = 1;
   1701            l3iif = data->ing_intf;
   1702      } else if (!BCM_VLAN_VALID(data->vid) && BCM_VLAN_NONE != data->vid
   1703                                            && !(data->flags & BCM_IPMC_L2)) {
   1704         /* Vlan id range check. Allow BCM_VLAN_NONE for non-vlan matching entries
   1705          * data->vid can also carry L3 incoming interface, which may be
   1706          * greater than 4k.
   1707          */
   1708          l3iif_validate = 1;
   1709          l3iif = data->vid;
   1710      }
   1711 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   1712      else if (soc_feature(unit, soc_feature_ipmc_l2_use_vlan_vpn)
   1713                   && soc_property_get(unit, spn_IPMC_L2_USE_VLAN_VPN, 0)
   1714                   && (data->flags & BCM_IPMC_L2)) {
   1715         /* data->vid carries VFI or VID */
   1716         if (_BCM_VPN_VFI_IS_SET(data->vid)) {
   1717             int vfi;
   1718             _BCM_VPN_GET(vfi, _BCM_VPN_TYPE_VFI, data->vid);
   1719             if (vfi >= soc_mem_index_count(unit, VFIm)) {
   1720                 return BCM_E_PARAM;
   1721             }
   1722         } else if (!BCM_VLAN_VALID(data->vid)) {
   1723             return BCM_E_PARAM;
   1724         }
   1725      }
   1726 #endif /* BCM_TRIDENT2PLUS_SUPPORT */
   1727 
   1728      if(l3iif_validate) {
   1729         soc_mem_t l3_entry_mem;
   1730         soc_field_t l3_iif_field;
   1731         if (data->flags & BCM_IPMC_IP6) {
   1732             if (soc_mem_is_valid(unit, L3_ENTRY_4m)) {
   1733                 l3_entry_mem = L3_ENTRY_4m;
   1734                 l3_iif_field = IPV6MC__L3_IIFf;
   1735             } else if (soc_mem_is_valid(unit, L3_ENTRY_QUADm)) {
   1736                 l3_entry_mem = L3_ENTRY_QUADm;
   1737                 l3_iif_field = IPV6MC__L3_IIFf;
   1738             } else {
   1739                 l3_entry_mem = L3_ENTRY_IPV6_MULTICASTm;
   1740                 l3_iif_field = L3_IIFf;
   1741             }
   1742         } else {
   1743             if (soc_mem_is_valid(unit, L3_ENTRY_2m)) {
   1744                 l3_entry_mem = L3_ENTRY_2m;
   1745                 l3_iif_field = IPV4MC__L3_IIFf;
   1746             } else if (soc_mem_is_valid(unit, L3_ENTRY_DOUBLEm)) {
   1747                 l3_entry_mem = L3_ENTRY_DOUBLEm;
   1748                 l3_iif_field = IPV4MC__L3_IIFf;
   1749             } else {
   1750                 l3_entry_mem = L3_ENTRY_IPV4_MULTICASTm;
   1751                 l3_iif_field = L3_IIFf;
   1752             }
   1753         }
   1754         if (soc_mem_field_valid(unit, l3_entry_mem, l3_iif_field)) {
   1755             /* HR/HR2/GH has no L3_IIFm */
   1756             if (soc_mem_is_valid(unit, L3_IIFm)) {
   1757                 if (l3iif >= soc_mem_index_count(unit, L3_IIFm)) {
   1758                     return (BCM_E_PARAM);
   1759                 }
   1760             }
   1761         } else {
   1762             return (BCM_E_PARAM);
   1763         }
   1764     } 
   1765 
   1766     /* Destination address must be multicast */
   1767     /* Source address must be unicast        */
   1768     if (data->flags & BCM_IPMC_IP6) {
   1769         if (!BCM_IP6_MULTICAST(data->mc_ip6_addr)) {
   1770             return (BCM_E_PARAM);
   1771         } 
   1772         if (BCM_IP6_MULTICAST(data->s_ip6_addr)) {
   1773             return (BCM_E_PARAM);
   1774         } 
   1775     } else {
   1776         if (!BCM_IP4_MULTICAST(data->mc_ip_addr)) {
   1777             return (BCM_E_PARAM);
   1778         } 
   1779         if (BCM_IP4_MULTICAST(data->s_ip_addr)) {
   1780             return (BCM_E_PARAM);
   1781         } 
   1782     }
   1783 
   1784     /* Expected L3 IIF range check */
   1785     if (data->flags & BCM_IPMC_POST_LOOKUP_RPF_CHECK) {
   1786         /* IIF = 0 disables RPF checking */
   1787         if ((data->l3a_intf <= 0) ||
   1788             (data->l3a_intf >= BCM_XGS3_L3_ING_IF_TBL_SIZE(unit))) {
   1789             return (BCM_E_PARAM);
   1790         }
   1791     }
   1792 
   1793     return (BCM_E_NONE);
   1794 }
   1795 
   1796 /*
   1797  * Function:
   1798  *	bcm_esw_ipmc_add
   1799  * Description:
   1800  *	Adds a new entry to the IPMC table.
   1801  * Parameters:
   1802  *	unit - StrataSwitch PCI device unit number (driver internal).
   1803  *	data - IPMC entry information.
   1804  * Returns:
   1805  *	BCM_E_XXX
   1806  */
   1807 
   1808 int
   1809 bcm_esw_ipmc_add(int unit, bcm_ipmc_addr_t *data)
   1810 {
   1811     bcm_gport_t     gport;
   1812     bcm_port_t      local_port;
   1813     int             is_local_mod;
   1814     int             rv;
   1815     bcm_ipmc_addr_t l_data;
   1816     int             check_port_dualmodid_valid;
   1817     soc_mem_t       v4mc_mem;
   1818     soc_field_t     pri_field;
   1819 
   1820     /* Input parameters validation. */
   1821     BCM_IF_ERROR_RETURN(_bcm_ipmc_key_validate(unit, data));
   1822 
   1823     /* Copy input to local storage to enable modifying */
   1824     sal_memcpy(&l_data, data, sizeof(bcm_ipmc_addr_t));
   1825 
   1826     if (!(l_data.flags & BCM_IPMC_SOURCE_PORT_NOCHECK)) {
   1827         /* Validate source port/trunk. */ 
   1828         if (BCM_GPORT_IS_SET(l_data.port_tgid)) {
   1829             BCM_IF_ERROR_RETURN
   1830                 (_bcm_esw_ipmc_gport_resolve(unit, l_data.port_tgid,
   1831                                              &(l_data.port_tgid),
   1832                                              &(l_data.mod_id),
   1833                                              &(l_data.port_tgid),
   1834                                              &(l_data.ts), 0)); 
   1835 
   1836             /* In multiple modid mode, port number should be less than 32.
   1837              * This check has already been done when resolving gport.
   1838              */
   1839             check_port_dualmodid_valid = 0;
   1840         } else {
   1841             check_port_dualmodid_valid = 1;
   1842         } 
   1843 
   1844         if(l_data.ts) { 
   1845             if (BCM_FAILURE(_bcm_trunk_id_validate(unit, l_data.port_tgid))) {
   1846                 return (BCM_E_PARAM);
   1847             }
   1848         } else  {
   1849             /* Check port validity only on local module. */
   1850             BCM_IF_ERROR_RETURN
   1851                 (_bcm_esw_modid_is_local(unit, l_data.mod_id, &is_local_mod));
   1852             if (is_local_mod) {
   1853                 if (check_port_dualmodid_valid) {
   1854                     PORT_DUALMODID_VALID(unit, l_data.port_tgid);
   1855                 }
   1856                 BCM_GPORT_MODPORT_SET(gport, l_data.mod_id, l_data.port_tgid);
   1857                 BCM_IF_ERROR_RETURN
   1858                     (bcm_esw_port_local_get(unit, gport, &local_port));
   1859             }
   1860         }
   1861     }
   1862 
   1863     /* Validate lookup class range. */
   1864     if (soc_feature(unit, soc_feature_extended_address_class)) {
   1865         if ((l_data.lookup_class > SOC_EXT_ADDR_CLASS_MAX(unit)) ||
   1866             (l_data.lookup_class < 0)) {
   1867             return (BCM_E_PARAM);
   1868         }
   1869     } else if ((l_data.lookup_class > SOC_ADDR_CLASS_MAX(unit)) || 
   1870         (l_data.lookup_class < 0)) {
   1871         return (BCM_E_PARAM);
   1872     }
   1873 
   1874 
   1875     /* Validate cos range. */ 
   1876     if (l_data.flags & BCM_IPMC_SETPRI) {
   1877         if (SOC_MEM_IS_VALID(unit, L3_ENTRY_DOUBLEm)) {
   1878             v4mc_mem = L3_ENTRY_DOUBLEm;
   1879             pri_field = IPV4MC__PRIf;
   1880         } else
   1881         {
   1882             v4mc_mem = L3_ENTRY_IPV4_MULTICASTm;
   1883             pri_field = PRIf;
   1884         }
   1885         if(SOC_MEM_IS_VALID(unit, v4mc_mem)) {
   1886             if(soc_mem_field_length(unit, v4mc_mem, pri_field) > 3) {
   1887                 if (!BCM_RPE_PRIORITY_VALID(l_data.cos)) {
   1888                     return (BCM_E_PARAM);
   1889                 }
   1890             }
   1891         } else {
   1892             if (!BCM_PRIORITY_VALID(l_data.cos)) {
   1893                 return (BCM_E_PARAM);
   1894             }
   1895         }
   1896     }
   1897 
   1898     LOG_INFO(BSL_LS_BCM_IPMC,
   1899              (BSL_META_U(unit,
   1900                          "IPMC %d: Add mc 0x%x, sip 0x%x, vid %d. cos %d, %s %d\n"),
   1901               unit,
   1902               l_data.mc_ip_addr,
   1903               l_data.s_ip_addr,
   1904               l_data.vid,
   1905               l_data.cos,
   1906               l_data.ts ? "trunk" : "port",
   1907               l_data.port_tgid));
   1908 
   1909     if (l_data.group_l2 &&
   1910         (_BCM_MULTICAST_IS_L3(l_data.group_l2) ||
   1911          _BCM_MULTICAST_IS_VPLS(l_data.group_l2) ||
   1912          _BCM_MULTICAST_IS_FLOW(l_data.group_l2))) {
   1913         l_data.group_l2 = _BCM_MULTICAST_ID_GET(l_data.group_l2);
   1914     }
   1915 
   1916     if (_BCM_MULTICAST_IS_L3(l_data.group) ||
   1917         _BCM_MULTICAST_IS_VPLS(l_data.group) ||
   1918         _BCM_MULTICAST_IS_FLOW(l_data.group)) {
   1919         l_data.group = _BCM_MULTICAST_ID_GET(l_data.group);
   1920     } else {
   1921         return BCM_E_PARAM;
   1922     }
   1923 
   1924     L3_LOCK(unit);
   1925     rv = mbcm_driver[unit]->mbcm_ipmc_add(unit, &l_data);
   1926     L3_UNLOCK(unit);
   1927 
   1928     return rv;
   1929 }
   1930 
   1931 /*
   1932  * Function:
   1933  *      bcm_esw_ipmc_remove
   1934  * Description:
   1935  *      Delete an entry from the IPMC table.
   1936  * Parameters:
   1937  *      unit - StrataSwitch PCI device unit number (driver internal).
   1938  *	data - IPMC entry information.
   1939  * Returns:
   1940  *      BCM_E_XXX
   1941  */
   1942 
   1943 int
   1944 bcm_esw_ipmc_remove(int unit, bcm_ipmc_addr_t *data)
   1945 {
   1946     int rv;
   1947 
   1948     BCM_IF_ERROR_RETURN(_bcm_ipmc_key_validate(unit, data));
   1949 
   1950     L3_LOCK(unit);
   1951     rv = mbcm_driver[unit]->mbcm_ipmc_delete(unit, data);
   1952     L3_UNLOCK(unit);
   1953 
   1954     return rv;
   1955 }
   1956 
   1957 /*
   1958  * Function:
   1959  *      bcm_esw_ipmc_remove_all
   1960  * Description:
   1961  *      Remove all entries of the IPMC table.
   1962  * Parameters:
   1963  *      unit - StrataSwitch PCI device unit number (driver internal).
   1964  * Returns:
   1965  *      BCM_E_XXX
   1966  */
   1967 
   1968 int
   1969 bcm_esw_ipmc_remove_all(int unit)
   1970 {
   1971     int rv;
   1972 
   1973     IPMC_INIT(unit);
   1974 
   1975     LOG_INFO(BSL_LS_BCM_IPMC,
   1976              (BSL_META_U(unit,
   1977                          "IPMC %d: Del all\n"),
   1978               unit));
   1979 
   1980     L3_LOCK(unit);
   1981     rv = mbcm_driver[unit]->mbcm_ipmc_delete_all(unit);
   1982     L3_UNLOCK(unit);
   1983     return rv;
   1984 }
   1985 
   1986 /*
   1987  * Function:
   1988  *	bcm_esw_ipmc_get_by_index
   1989  * Description:
   1990  *	Get an IPMC entry.
   1991  * Parameters:
   1992  *	unit - StrataSwitch PCI device unit number (driver internal).
   1993  *	index - The index number.
   1994  *	data - (OUTPUT) IPMC entry information.
   1995  * Returns:
   1996  *	BCM_E_XXX
   1997  */
   1998 int
   1999 bcm_esw_ipmc_get_by_index(int unit, int index, bcm_ipmc_addr_t *data)
   2000 {
   2001     int rv;
   2002     int flags;
   2003 
   2004     IPMC_INIT(unit);
   2005 
   2006     if(NULL == data) {
   2007         return (BCM_E_PARAM);
   2008     } 
   2009 
   2010     flags = data->flags;
   2011     bcm_ipmc_addr_t_init(data);
   2012     data->flags = flags;
   2013 
   2014     BCM_IF_ERROR_RETURN(_bcm_esw_ipmc_convert_mcindex_m2h(&index));
   2015 
   2016     L3_LOCK(unit);
   2017     rv = mbcm_driver[unit]->mbcm_ipmc_get(unit, index, data);
   2018     L3_UNLOCK(unit);
   2019 
   2020     if (BCM_SUCCESS(rv)) {
   2021         _bcm_esw_ipmc_convert_mcindex_h2m(unit, &data->group);
   2022         if (data->group_l2 > 0) {
   2023             _bcm_esw_ipmc_convert_mcindex_h2m(unit, &data->group_l2);
   2024         }
   2025         rv = _bcm_esw_ipmc_gport_construct(unit, data);
   2026     }
   2027 
   2028     return rv;
   2029 }
   2030 
   2031 /*
   2032  * Function:
   2033  *      bcm_esw_ipmc_find
   2034  * Description:
   2035  *      Find an IPMC entry.
   2036  * Parameters:
   2037  *      unit - StrataSwitch PCI device unit number (driver internal).
   2038  *      data - IPMC entry information.
   2039  * Returns:
   2040  *      BCM_E_XXX
   2041  */
   2042 
   2043 int
   2044 bcm_esw_ipmc_find(int unit, bcm_ipmc_addr_t *data)
   2045 {
   2046     int index, rv;
   2047 
   2048     BCM_IF_ERROR_RETURN(_bcm_ipmc_key_validate(unit, data));
   2049 
   2050     L3_LOCK(unit);
   2051     rv = mbcm_driver[unit]->mbcm_ipmc_lookup(unit, &index, data);
   2052     L3_UNLOCK(unit);
   2053 
   2054     if (BCM_SUCCESS(rv)) {
   2055         BCM_IF_ERROR_RETURN(bcm_esw_multicast_ipmc_group_type_get(unit,
   2056             data->group, &(data->group)));
   2057         if (data->group_l2 > 0) {
   2058             BCM_IF_ERROR_RETURN(bcm_esw_multicast_ipmc_group_type_get(unit,
   2059                 data->group_l2, &(data->group_l2)));
   2060         }
   2061         rv = _bcm_esw_ipmc_gport_construct(unit, data);
   2062     }
   2063 
   2064     return rv;
   2065 }
   2066 
   2067 /*
   2068  * Function:
   2069  *	bcm_esw_ipmc_egress_port_init
   2070  * Description:
   2071  *	Reinitialize/clear the egress IP multicast configuration
   2072  * Parameters:
   2073  *	unit - StrataSwitch PCI device unit number (driver internal).
   2074  * Returns:
   2075  *	BCM_E_XXX
   2076  */
   2077 
   2078 int
   2079 bcm_esw_ipmc_egress_port_init(int unit)
   2080 {
   2081 
   2082     if (soc_feature(unit, soc_feature_ip_mcast)) {
   2083         int        port;
   2084         bcm_pbmp_t e_pbmp;
   2085 
   2086         BCM_PBMP_CLEAR(e_pbmp);
   2087         BCM_PBMP_ASSIGN(e_pbmp, PBMP_E_ALL(unit));
   2088 
   2089 #if defined(BCM_KATANA2_SUPPORT)
   2090         if (soc_feature(unit, soc_feature_linkphy_coe) ||
   2091             soc_feature(unit, soc_feature_subtag_coe)) {
   2092             _bcm_kt2_subport_pbmp_update(unit, &e_pbmp);
   2093         }
   2094         if (SOC_IS_KATANA2(unit)) {
   2095             BCM_IF_ERROR_RETURN(_bcm_kt2_flexio_pbmp_update (unit, &e_pbmp));
   2096         }
   2097 #endif
   2098 
   2099         if (!soc_feature(unit, soc_feature_no_egr_ipmc_cfg)) {
   2100             PBMP_ITER(e_pbmp, port) {
   2101                 BCM_IF_ERROR_RETURN(bcm_esw_ipmc_egress_port_set(unit, port,
   2102                     _soc_mac_all_zeroes, 0, 0, 0));
   2103             }
   2104         }
   2105     }
   2106 
   2107     return BCM_E_NONE;
   2108 }
   2109 
   2110 /*
   2111  * Function:
   2112  *	bcm_esw_ipmc_egress_port_set
   2113  * Description:
   2114  *	Config the egress IP multicast Configuration Register.
   2115  * Parameters:
   2116  *	unit - StrataSwitch PCI device unit number (driver internal).
   2117  *	port - port to config.
   2118  *	mac - MAC address.
   2119  *	untag - 1: The IP multicast packet is transmitted as untagged packet.
   2120  *		0: The IP multicast packet is transmitted as tagged packet
   2121  *		with VLAN tag vid.
   2122  *	vid  - VLAN ID.
   2123  *	ttl_thresh - Drop IPMC packets if TTL of IP packet <= ttl_thresh.
   2124  * Returns:
   2125  *	BCM_E_XXX
   2126  */
   2127 
   2128 int
   2129 bcm_esw_ipmc_egress_port_set(int unit, bcm_port_t port, const bcm_mac_t mac,
   2130                              int untag, bcm_vlan_t vid, int ttl_thresh)
   2131 {
   2132     /*
   2133      * Can't check IPMC_INIT here because this function is used as part
   2134      * of the bcm_esw_ipmc_init function (via bcm_ipmc_egress_port_init).
   2135      * Just check that IPMC feature is enabled.
   2136      */
   2137     if (!soc_feature(unit, soc_feature_ip_mcast)) {
   2138         return BCM_E_UNAVAIL;
   2139     }
   2140 
   2141     if (!BCM_VLAN_VALID(vid) && vid != BCM_VLAN_NONE) {
   2142         return (BCM_E_PARAM);
   2143     }
   2144 
   2145     BCM_IF_ERROR_RETURN(_bcm_esw_port_gport_validate (unit, port, &port));
   2146 
   2147     if (!BCM_TTL_VALID(ttl_thresh)) {
   2148         return (BCM_E_PARAM);
   2149     }
   2150 
   2151     return mbcm_driver[unit]->mbcm_ipmc_egress_port_set(unit, port, mac,
   2152                                                         untag, vid, ttl_thresh);
   2153 }
   2154 
   2155 /*
   2156  * Function:
   2157  *	bcm_esw_ipmc_egress_port_get
   2158  * Description:
   2159  *    Get the egress IP multicast Configuration Register.
   2160  * Parameters:
   2161  *    unit - StrataSwitch PCI device unit number (driver internal).
   2162  *    port - port to config.
   2163  *    mac - (OUT) MAC address.
   2164  *    untag - (OUT) 1: The IP multicast packet is transmitted as untagged packet.
   2165  *                  0: The IP multicast packet is transmitted as tagged
   2166  *                     packet with VLAN tag vid.
   2167  *    vid - (OUT) VLAN ID.
   2168  *    ttl_thresh - (OUT) Drop IPMC packets if TTL <= ttl_thresh.
   2169  * Returns:
   2170  *    BCM_E_XXX
   2171  */
   2172 
   2173 int
   2174 bcm_esw_ipmc_egress_port_get(int unit, bcm_port_t port, sal_mac_addr_t mac,
   2175                              int *untag, bcm_vlan_t *vid, int *ttl_thresh)
   2176 {
   2177     /* Make sure ipmc was initialized on the device. */
   2178     IPMC_INIT(unit);
   2179 
   2180     if ((NULL == untag) || (NULL == vid) || (NULL == ttl_thresh)) {
   2181         return (BCM_E_PARAM);
   2182     }
   2183 
   2184     BCM_IF_ERROR_RETURN(_bcm_esw_port_gport_validate (unit, port, &port));
   2185 
   2186     return mbcm_driver[unit]->mbcm_ipmc_egress_port_get(unit, port, mac,
   2187                                                         untag, vid, ttl_thresh);
   2188 }
   2189 
   2190 /*
   2191  * Function:
   2192  *	bcm_esw_ipmc_counters_get
   2193  * Description:
   2194  *	Get IPMC counters of hardware.
   2195  * Parameters:
   2196  *	unit - StrataSwitch PCI device unit number (driver internal).
   2197  *	port - port to get information.
   2198  *	counters - (OUT) IPMC entry information.
   2199  * Returns:
   2200  *	BCM_E_XXX
   2201  */
   2202 
   2203 int
   2204 bcm_esw_ipmc_counters_get(int unit, bcm_port_t port,
   2205                                       bcm_ipmc_counters_t *counters)
   2206 {
   2207 #if defined(BCM_KATANA2_SUPPORT)
   2208     int my_modid = -1, pp_port = -1;
   2209     int max_subport = SOC_INFO(unit).pp_port_index_max; 
   2210     int min_subport = SOC_INFO(unit).pp_port_index_min;
   2211 #endif
   2212 
   2213 #if defined(BCM_KATANA2_SUPPORT) || defined(BCM_HGPROXY_COE_SUPPORT)
   2214     int is_local_subport = 0;
   2215     bcm_module_t mod_out = -1;
   2216     bcm_port_t   port_out = -1;
   2217     bcm_trunk_t  trunk_id = -1;
   2218     int          id = -1;
   2219 #endif
   2220 
   2221     IPMC_INIT(unit);
   2222 
   2223 #if defined(BCM_HGPROXY_COE_SUPPORT)
   2224     if (soc_feature(unit, soc_feature_hgproxy_subtag_coe) &&
   2225         _BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, port)) {
   2226         BCM_IF_ERROR_RETURN(_bcm_esw_gport_resolve(unit, port, &mod_out, 
   2227                                     &port_out, &trunk_id, &id));
   2228         if(_bcm_xgs5_subport_coe_mod_port_local(unit, mod_out, port_out)) {
   2229             is_local_subport = 1;
   2230 			BCM_IF_ERROR_RETURN(_bcmi_coe_subport_physical_port_get(unit,
   2231 																	port,
   2232 																	&port));
   2233         }
   2234 
   2235         if (is_local_subport == 0) {
   2236             return BCM_E_PORT;
   2237         }
   2238     } else
   2239 #endif
   2240 
   2241 #if defined(BCM_KATANA2_SUPPORT)
   2242     if (BCM_GPORT_IS_SET(port) &&
   2243         _BCM_KT2_GPORT_IS_LINKPHY_OR_SUBTAG_SUBPORT_GPORT(unit, port)) {
   2244         BCM_IF_ERROR_RETURN(_bcm_esw_gport_resolve(unit, port, &mod_out, 
   2245                                     &port_out, &trunk_id, &id));
   2246         BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &my_modid));
   2247         if (_bcm_kt2_mod_is_coe_mod_check(unit, mod_out) == BCM_E_NONE) {
   2248             pp_port = BCM_GPORT_SUBPORT_PORT_GET(port);
   2249 #if defined BCM_METROLITE_SUPPORT
   2250             if (soc_feature(unit, soc_feature_discontinuous_pp_port)) {
   2251                 if (_SOC_IS_PP_PORT_LINKPHY_SUBTAG(unit, pp_port)) {
   2252                     is_local_subport = 1;
   2253                     port = pp_port;
   2254                 }
   2255             } else
   2256 #endif
   2257             {
   2258                 if ((pp_port >= min_subport) &&
   2259                     (pp_port <= max_subport)) {
   2260                     is_local_subport = 1;
   2261 				    port = pp_port;
   2262                 }
   2263             }
   2264         }
   2265         if (is_local_subport == 0) {
   2266             return BCM_E_PORT;
   2267         }
   2268     }
   2269 #endif
   2270 
   2271 #if defined(BCM_HGPROXY_COE_SUPPORT)
   2272     if (BCM_GPORT_IS_SET(port) &&
   2273         _BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, port) &&
   2274         soc_feature(unit, soc_feature_hgproxy_subtag_coe) &&
   2275         is_local_subport) {
   2276     } else
   2277 #endif
   2278 
   2279 #if defined(BCM_KATANA2_SUPPORT)
   2280     if (BCM_GPORT_IS_SET(port) &&
   2281         _BCM_KT2_GPORT_IS_LINKPHY_OR_SUBTAG_SUBPORT_GPORT(unit, port) &&
   2282         is_local_subport) {
   2283     } else
   2284 #endif
   2285     {
   2286         if (BCM_GPORT_IS_SET(port)) {
   2287             BCM_IF_ERROR_RETURN(bcm_esw_port_local_get(unit, port, &port)); 
   2288         } 
   2289     
   2290         if (!SOC_PBMP_PORT_VALID(port) || !IS_E_PORT(unit, port)) {
   2291             return BCM_E_PORT;
   2292         }
   2293     }
   2294 
   2295     if (NULL == counters) {
   2296         return (BCM_E_PARAM);
   2297     }
   2298 
   2299     BCM_IF_ERROR_RETURN
   2300         (bcm_esw_stat_get(unit, port, snmpIfHCInMulticastPkts,
   2301                           &counters->rmca));
   2302     BCM_IF_ERROR_RETURN
   2303         (bcm_esw_stat_get(unit, port, snmpIfHCOutMulticastPkts,
   2304                           &counters->tmca));
   2305     BCM_IF_ERROR_RETURN
   2306         (bcm_esw_stat_get(unit, port, snmpBcmIPMCBridgedPckts,
   2307                           &counters->imbp));
   2308     BCM_IF_ERROR_RETURN
   2309         (bcm_esw_stat_get(unit, port, snmpBcmIPMCRoutedPckts,
   2310                           &counters->imrp));
   2311     BCM_IF_ERROR_RETURN
   2312         (bcm_esw_stat_get(unit, port, snmpBcmIPMCInDroppedPckts,
   2313                           &counters->rimdr));
   2314     BCM_IF_ERROR_RETURN
   2315         (bcm_esw_stat_get(unit, port, snmpBcmIPMCOutDroppedPckts,
   2316                           &counters->timdr));
   2317 
   2318     return BCM_E_NONE;
   2319 }
   2320 
   2321 #if defined(BCM_XGS2_FABRIC_SUPPORT)
   2322 STATIC int
   2323 _bcm5675_ipmc_bitmap_set(int unit, int ipmc_idx,
   2324 			 bcm_port_t in_port, bcm_pbmp_t pbmp)
   2325 {
   2326     mem_ipmc_entry_t  entry;
   2327     int             blk;
   2328     int             rv;
   2329 
   2330     /* Make sure packet never goes back */
   2331     BCM_PBMP_PORT_REMOVE(pbmp, in_port);
   2332 
   2333     blk = SOC_PORT_BLOCK(unit, in_port);
   2334 
   2335     sal_memset(&entry, 0, sizeof(entry));
   2336 
   2337     soc_mem_lock(unit, MEM_IPMCm);
   2338 
   2339     if ((rv = READ_MEM_IPMCm(unit, blk, ipmc_idx, &entry)) >= 0)
   2340     {
   2341         soc_MEM_IPMCm_field32_set(unit, &entry, IPMCBITMAPf,
   2342                                   SOC_PBMP_WORD_GET(pbmp, 0));
   2343         rv = WRITE_MEM_IPMCm(unit, blk, ipmc_idx, &entry);
   2344     }
   2345 
   2346     soc_mem_unlock(unit, MEM_IPMCm);
   2347 
   2348     return rv;
   2349 }
   2350 
   2351 STATIC int
   2352 _bcm5675_ipmc_bitmap_get(int unit, int ipmc_idx,
   2353 			 bcm_port_t in_port, bcm_pbmp_t *pbmp)
   2354 {
   2355     mem_ipmc_entry_t  entry;
   2356     int             blk;
   2357 
   2358     sal_memset(&entry, 0, sizeof(entry));
   2359     blk = SOC_PORT_BLOCK(unit, in_port);
   2360 
   2361     SOC_IF_ERROR_RETURN
   2362         (READ_MEM_IPMCm(unit, blk, ipmc_idx, &entry));
   2363 
   2364     BCM_PBMP_CLEAR(*pbmp);
   2365     SOC_PBMP_WORD_SET(
   2366         *pbmp, 0, soc_MEM_IPMCm_field32_get(unit, &entry, IPMCBITMAPf));
   2367 
   2368     return BCM_E_NONE;
   2369 }
   2370 
   2371 STATIC int
   2372 _bcm5675_ipmc_bitmap_del(int unit, int ipmc_idx,
   2373 			 bcm_port_t in_port, bcm_pbmp_t pbmp)
   2374 {
   2375     mem_ipmc_entry_t  entry;
   2376     uint32          fval;
   2377     int             blk;
   2378     int             rv;
   2379 
   2380     blk = SOC_PORT_BLOCK(unit, in_port);
   2381 
   2382     sal_memset(&entry, 0, sizeof(entry));
   2383 
   2384     soc_mem_lock(unit, MEM_IPMCm);
   2385 
   2386     if ((rv = READ_MEM_IPMCm(unit, blk, ipmc_idx, &entry)) >= 0)
   2387     {
   2388         soc_MEM_IPMCm_field_get(unit, &entry, IPMCBITMAPf, &fval);
   2389         fval &= ~SOC_PBMP_WORD_GET(pbmp, 0);
   2390         soc_MEM_IPMCm_field32_set(unit, &entry, IPMCBITMAPf, fval);
   2391         rv = WRITE_MEM_IPMCm(unit, blk, ipmc_idx, &entry);
   2392 
   2393     }
   2394     soc_mem_unlock(unit, MEM_IPMCm);
   2395 
   2396     return rv;
   2397 }
   2398 #endif /* BCM_XGS2_FABRIC_SUPPORT */
   2399 
   2400 #ifdef BCM_BRADLEY_SUPPORT
   2401 int
   2402 _bcm_xgs3_ipmc_bitmap_set(int unit, int ipmc_idx, bcm_pbmp_t pbmp)
   2403 {
   2404     int		rv, mc_base, mc_size, mc_index;
   2405     l2mc_entry_t	l2mc;
   2406 
   2407     SOC_IF_ERROR_RETURN
   2408         (soc_hbx_ipmc_size_get(unit, &mc_base, &mc_size));
   2409     if (ipmc_idx < 0 || ipmc_idx > mc_size) {
   2410         return BCM_E_PARAM;
   2411     }
   2412     mc_index = ipmc_idx + mc_base;
   2413 
   2414     soc_mem_lock(unit, L2MCm);
   2415     rv = READ_L2MCm(unit, MEM_BLOCK_ANY, mc_index, &l2mc);
   2416     if (rv >= 0) {
   2417         soc_mem_pbmp_field_set(unit, L2MCm, &l2mc, PORT_BITMAPf, &pbmp);
   2418         soc_mem_field32_set(unit, L2MCm, &l2mc, VALIDf, 1);
   2419         rv = WRITE_L2MCm(unit, MEM_BLOCK_ALL, mc_index, &l2mc);
   2420     }
   2421     soc_mem_unlock(unit, L2MCm);
   2422 
   2423     /* set the l3_ipmc table entry valid but empty */
   2424     if (rv >= 0 && ipmc_idx <= soc_mem_index_max(unit, L3_IPMCm)) {
   2425         ipmc_entry_t	ipmc_e;
   2426 
   2427         sal_memset(&ipmc_e, 0, sizeof(ipmc_e));
   2428         soc_mem_field32_set(unit, L3_IPMCm, &ipmc_e, VALIDf, 1);
   2429         rv = WRITE_L3_IPMCm(unit, MEM_BLOCK_ALL, ipmc_idx, &ipmc_e);
   2430     }
   2431     return rv;
   2432 }
   2433 
   2434 int
   2435 _bcm_xgs3_ipmc_bitmap_get(int unit, int ipmc_idx, bcm_pbmp_t *pbmp)
   2436 {
   2437     int		mc_base, mc_size, mc_index;
   2438     l2mc_entry_t	l2mc;
   2439 
   2440     SOC_IF_ERROR_RETURN
   2441         (soc_hbx_ipmc_size_get(unit, &mc_base, &mc_size));
   2442     if (ipmc_idx < 0 || ipmc_idx > mc_size) {
   2443         return BCM_E_PARAM;
   2444     }
   2445     mc_index = ipmc_idx + mc_base;
   2446 
   2447     SOC_IF_ERROR_RETURN(READ_L2MCm(unit, MEM_BLOCK_ANY, mc_index, &l2mc));
   2448     soc_mem_pbmp_field_get(unit, L2MCm, &l2mc, PORT_BITMAPf, pbmp);
   2449     return BCM_E_NONE;
   2450 }
   2451 
   2452 int
   2453 _bcm_xgs3_ipmc_bitmap_del(int unit, int ipmc_idx, bcm_pbmp_t pbmp)
   2454 {
   2455     int		rv, mc_base, mc_size, mc_index;
   2456     l2mc_entry_t	l2mc;
   2457     bcm_pbmp_t          tmp_pbmp;
   2458 
   2459     SOC_IF_ERROR_RETURN
   2460         (soc_hbx_ipmc_size_get(unit, &mc_base, &mc_size));
   2461     if (ipmc_idx < 0 || ipmc_idx > mc_size) {
   2462         return BCM_E_PARAM;
   2463     }
   2464     mc_index = ipmc_idx + mc_base;
   2465 
   2466     soc_mem_lock(unit, L2MCm);
   2467     rv = READ_L2MCm(unit, MEM_BLOCK_ANY, mc_index, &l2mc);
   2468     if (rv >= 0) {
   2469         soc_mem_pbmp_field_get(unit, L2MCm, &l2mc, PORT_BITMAPf, &tmp_pbmp);
   2470         SOC_PBMP_REMOVE(tmp_pbmp, pbmp);
   2471         soc_mem_pbmp_field_set(unit, L2MCm, &l2mc, PORT_BITMAPf, &tmp_pbmp);
   2472         soc_mem_field32_set(unit, L2MCm, &l2mc, VALIDf, 1);
   2473         rv = WRITE_L2MCm(unit, MEM_BLOCK_ALL, mc_index, &l2mc);
   2474     }
   2475     soc_mem_unlock(unit, L2MCm);
   2476 
   2477     /* set the l3_ipmc table entry valid but empty */
   2478     if (rv >= 0 && ipmc_idx <= soc_mem_index_max(unit, L3_IPMCm)) {
   2479         ipmc_entry_t	ipmc_e;
   2480 
   2481         sal_memset(&ipmc_e, 0, sizeof(ipmc_e));
   2482         soc_mem_field32_set(unit, L3_IPMCm, &ipmc_e, VALIDf, 1);
   2483         rv = WRITE_L3_IPMCm(unit, MEM_BLOCK_ALL, ipmc_idx, &ipmc_e);
   2484     }
   2485     return rv;
   2486 }
   2487 
   2488 int
   2489 _bcm_xgs3_ipmc_bitmap_clear(int unit, int ipmc_idx)
   2490 {
   2491     int		mc_base, mc_size, mc_index, rv;
   2492     l2mc_entry_t	l2mc;
   2493 
   2494     SOC_IF_ERROR_RETURN
   2495         (soc_hbx_ipmc_size_get(unit, &mc_base, &mc_size));
   2496     if (ipmc_idx < 0 || ipmc_idx > mc_size) {
   2497         return BCM_E_PARAM;
   2498     }
   2499     mc_index = ipmc_idx + mc_base;
   2500     sal_memset(&l2mc, 0, sizeof(l2mc_entry_t));
   2501 
   2502     soc_mem_lock(unit, L2MCm);
   2503     rv = WRITE_L2MCm(unit, MEM_BLOCK_ALL, mc_index, &l2mc);
   2504     soc_mem_unlock(unit, L2MCm);
   2505 
   2506     return rv;
   2507 }
   2508 
   2509 #endif /* BCM_BRADLEY_SUPPORT */
   2510 
   2511 /*
   2512  * Function:
   2513  *	bcm_esw_ipmc_bitmap_max_get
   2514  * Purpose:
   2515  *	Provides maximum IPMC index that this fabric can handle
   2516  * Parameters:
   2517  *	unit - device
   2518  *	max_index - (OUT) returned number of entries
   2519  * Returns:
   2520  *	BCM_E_XXX
   2521  * Notes:
   2522  *	Fabric only
   2523  */
   2524 
   2525 int
   2526 bcm_esw_ipmc_bitmap_max_get(int unit, int *max_index)
   2527 {
   2528 #ifdef	BCM_HERCULES_SUPPORT
   2529     if (SOC_IS_HERCULES15(unit)) {
   2530 	*max_index = soc_mem_index_count(unit, MEM_IPMCm);
   2531 	return BCM_E_NONE;
   2532     }
   2533 #endif	/* BCM_HERCULES_SUPPORT */
   2534 
   2535 #ifdef	BCM_XGS3_FABRIC_SUPPORT
   2536     if (SOC_IS_XGS3_FABRIC(unit)) {
   2537 	int	mc_base, mc_size;
   2538 
   2539 	SOC_IF_ERROR_RETURN
   2540             (soc_hbx_ipmc_size_get(unit, &mc_base, &mc_size));
   2541 	*max_index = mc_size;
   2542 	return BCM_E_NONE;
   2543     }
   2544 #endif	/* BCM_XGS3_FABRIC_SUPPORT */
   2545 
   2546     *max_index = 0;
   2547     return BCM_E_UNAVAIL;
   2548 }
   2549 
   2550 /*
   2551  * Function:
   2552  *	bcm_esw_ipmc_bitmap_set
   2553  * Purpose:
   2554  *	Set the IPMC forwarding port bitmap
   2555  * Parameters:
   2556  *	unit     - SOC unit #
   2557  *	index    - the IPMC index carried in HiGig header
   2558  *	in_port  - ingress port number
   2559  *	pbmp     - IPMC forwarding port bitmap
   2560  * Returns:
   2561  *	BCM_E_XXX
   2562  * Note:
   2563  *	Fabric only
   2564  */
   2565 
   2566 int
   2567 bcm_esw_ipmc_bitmap_set(int unit, int index,
   2568 			bcm_port_t in_port, bcm_pbmp_t pbmp)
   2569 {
   2570     bcm_module_t    modid;
   2571     bcm_trunk_t     tgid;
   2572     int             t;
   2573 
   2574     if (BCM_GPORT_IS_SET(in_port)) {
   2575         BCM_IF_ERROR_RETURN(
   2576             _bcm_esw_ipmc_gport_resolve(unit, in_port, &in_port, &modid, &tgid, &t, 1)); 
   2577     } 
   2578     if (!SOC_PORT_VALID(unit, in_port)) {
   2579         return BCM_E_PORT;
   2580     }
   2581 
   2582     BCM_IF_ERROR_RETURN(_bcm_esw_ipmc_convert_mcindex_m2h(&index));
   2583 
   2584 #ifdef	BCM_HERCULES_SUPPORT
   2585     if (SOC_IS_HERCULES15(unit)) {
   2586         return _bcm5675_ipmc_bitmap_set(unit, index, in_port, pbmp);
   2587     }
   2588 #endif	/* BCM_HERCULES_SUPPORT */
   2589 
   2590 #ifdef	BCM_XGS3_FABRIC_SUPPORT
   2591     if (SOC_IS_XGS3_FABRIC(unit)) {
   2592         COMPILER_REFERENCE(in_port);
   2593         return _bcm_xgs3_ipmc_bitmap_set(unit, index, pbmp);
   2594     }
   2595 #endif	/* BCM_XGS3_FABRIC_SUPPORT */
   2596 
   2597     return BCM_E_UNAVAIL;
   2598 }
   2599 
   2600 /*
   2601  * Function:
   2602  *	bcm_esw_ipmc_bitmap_get
   2603  * Purpose:
   2604  *	Get the IPMC forwarding port bitmap
   2605  * Parameters:
   2606  *	unit     - SOC unit #
   2607  *	index    - the IPMC index carried in HiGig header
   2608  *	in_port  - ingress port number
   2609  *	pbmp     - IPMC forwarding port bitmap
   2610  * Returns:
   2611  *	BCM_E_XXX
   2612  * Note:
   2613  *	Fabric only
   2614  */
   2615 
   2616 int
   2617 bcm_esw_ipmc_bitmap_get(int unit, int index,
   2618 			bcm_port_t in_port, bcm_pbmp_t *pbmp)
   2619 {
   2620     bcm_module_t    modid;
   2621     bcm_trunk_t     tgid;
   2622     int             t;
   2623 
   2624     if (BCM_GPORT_IS_SET(in_port)) {
   2625         BCM_IF_ERROR_RETURN(
   2626             _bcm_esw_ipmc_gport_resolve(unit, in_port, &in_port, &modid, &tgid, &t, 1)); 
   2627     } 
   2628     if (!SOC_PORT_VALID(unit, in_port)) {
   2629         return BCM_E_PORT;
   2630     }
   2631 
   2632     BCM_IF_ERROR_RETURN(_bcm_esw_ipmc_convert_mcindex_m2h(&index));
   2633 
   2634 #ifdef	BCM_HERCULES_SUPPORT
   2635     if (SOC_IS_HERCULES15(unit)) {
   2636         return _bcm5675_ipmc_bitmap_get(unit, index, in_port, pbmp);
   2637     }
   2638 #endif	/* BCM_HERCULES_SUPPORT */
   2639 
   2640 #ifdef	BCM_XGS3_FABRIC_SUPPORT
   2641     if (SOC_IS_XGS3_FABRIC(unit)) {
   2642         COMPILER_REFERENCE(in_port);
   2643         return _bcm_xgs3_ipmc_bitmap_get(unit, index, pbmp);
   2644     }
   2645 #endif	/* BCM_XGS3_FABRIC_SUPPORT */
   2646 
   2647     return BCM_E_UNAVAIL;
   2648 }
   2649 
   2650 /*
   2651  * Function:
   2652  *	bcm_esw_ipmc_bitmap_del
   2653  * Purpose:
   2654  *	Remove IPMC forwarding port bitmap
   2655  * Parameters:
   2656  *	unit     - SOC unit #
   2657  *	index - the IPMC index carried in HiGig header
   2658  *	in_port  - ingress port number
   2659  *	pbmp     - IPMC forwarding port bitmap
   2660  * Returns:
   2661  *	BCM_E_XXX
   2662  * Note:
   2663  * 	Fabric only
   2664  */
   2665 
   2666 int
   2667 bcm_esw_ipmc_bitmap_del(int unit, int index,
   2668 			bcm_port_t in_port, bcm_pbmp_t pbmp)
   2669 {
   2670     bcm_module_t    modid;
   2671     bcm_trunk_t     tgid;
   2672     int             t;
   2673 
   2674     if (BCM_GPORT_IS_SET(in_port)) {
   2675         BCM_IF_ERROR_RETURN(
   2676             _bcm_esw_ipmc_gport_resolve(unit, in_port, &in_port, &modid, &tgid, &t, 1)); 
   2677     } 
   2678     if (!SOC_PORT_VALID(unit, in_port)) {
   2679         return BCM_E_PORT;
   2680     }
   2681 
   2682     BCM_IF_ERROR_RETURN(_bcm_esw_ipmc_convert_mcindex_m2h(&index));
   2683 
   2684 #ifdef	BCM_HERCULES_SUPPORT
   2685     if (SOC_IS_HERCULES15(unit)) {
   2686         return _bcm5675_ipmc_bitmap_del(unit, index, in_port, pbmp);
   2687     }
   2688 #endif	/* BCM_HERCULES_SUPPORT */
   2689 
   2690 #ifdef	BCM_XGS3_FABRIC_SUPPORT
   2691     if (SOC_IS_XGS3_FABRIC(unit)) {
   2692         COMPILER_REFERENCE(in_port);
   2693         return _bcm_xgs3_ipmc_bitmap_del(unit, index, pbmp);
   2694     }
   2695 #endif	/* BCM_XGS3_FABRIC_SUPPORT */
   2696 
   2697     return BCM_E_UNAVAIL;
   2698 }
   2699 
   2700 /*
   2701  * Function:
   2702  *      bcm_esw_ipmc_age
   2703  * Purpose:
   2704  *      Age out the ipmc entry by clearing the HIT bit when appropriate,
   2705  *      the ipmc entry itself is removed if HIT bit is not set.
   2706  * Parameters:
   2707  *      unit       -  (IN) BCM device number.
   2708  *      flags      -  (IN) The criteria used to age out ipmc table.
   2709  *      age_cb     -  (IN) Call back routine.
   2710  *      user_data  -  (IN) User provided cookie for callback.
   2711  * Returns:
   2712  *      BCM_E_XXX 
   2713  */
   2714 int
   2715 bcm_esw_ipmc_age(int unit, uint32 flags, bcm_ipmc_traverse_cb age_cb, 
   2716                  void *user_data)
   2717 {
   2718     int rv;
   2719 
   2720     IPMC_INIT(unit);
   2721     
   2722     L3_LOCK(unit);
   2723     rv = mbcm_driver[unit]->mbcm_ipmc_age(unit, flags, age_cb, user_data);
   2724     L3_UNLOCK(unit);
   2725     return rv;
   2726 }
   2727 
   2728 /*
   2729  * Function:
   2730  *      bcm_esw_ipmc_traverse
   2731  * Purpose:
   2732  *      Go through all valid ipmc entries, and call the callback function
   2733  *      at each entry
   2734  * Parameters:
   2735  *      unit      - (IN) BCM device number.
   2736  *      flags     - (IN) The criteria used to age out ipmc table.
   2737  *      cb        - (IN) User supplied callback function.
   2738  *      user_data - (IN) User supplied cookie used in parameter 
   2739  *                       in callback function.
   2740  * Returns:
   2741  *      BCM_E_XXX
   2742  */
   2743 int
   2744 bcm_esw_ipmc_traverse(int unit, uint32 flags,
   2745                       bcm_ipmc_traverse_cb cb, void *user_data)
   2746 {
   2747     int rv;
   2748 
   2749     IPMC_INIT(unit);
   2750 
   2751     /* Input parameters check. */
   2752     if (NULL == cb) {
   2753         return (BCM_E_PARAM);
   2754     }
   2755 
   2756     L3_LOCK(unit);
   2757     rv = mbcm_driver[unit]->mbcm_ipmc_traverse(unit, flags, cb, user_data);
   2758     L3_UNLOCK(unit);
   2759     return rv;
   2760 }
   2761 
   2762 /*
   2763  * Function:
   2764  *	_bcm_esw_ipmc_egress_intf_set
   2765  * Purpose:
   2766  *	    Helper function to call per device specific routines
   2767  * Parameters:
   2768  *	unit     - StrataSwitch PCI device unit number.
   2769  *	mc_index - The index number.
   2770  *	port     - port to list.
   2771  *      if_count - number of interfaces in list.
   2772  *	if_array - (IN) array of bcm_if_t interfaces, size if_count.
   2773  *      is_l3    - Indicates if multicast group type is IPMC.
   2774  *      check_port - indication if the port should be checked 
   2775  * Returns:
   2776  *	BCM_E_XXX
   2777  */
   2778 
   2779 int
   2780 _bcm_esw_ipmc_egress_intf_set(int unit, int mc_index, bcm_port_t port,
   2781                               int if_count, bcm_if_t *if_array, int is_l3, 
   2782                               int check_port)
   2783 {
   2784 #if defined(INCLUDE_L3)
   2785 
   2786 #if defined(BCM_TOMAHAWK_SUPPORT)
   2787     if (SOC_IS_TOMAHAWKX(unit) || SOC_IS_TRIDENT3X(unit)) {
   2788         return bcm_th_ipmc_egress_intf_set(unit, mc_index, port, if_count,
   2789                 if_array, is_l3, check_port);
   2790     }
   2791 #endif
   2792 #if defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_KATANA2_SUPPORT)
   2793     if (SOC_IS_TRIUMPH3(unit) || SOC_IS_TD2_TT2(unit) || SOC_IS_KATANA2(unit)) {
   2794         return bcm_tr3_ipmc_egress_intf_set(unit, mc_index, port, if_count,
   2795                 if_array, is_l3, check_port);
   2796     }
   2797 #endif
   2798 #ifdef	BCM_TRIUMPH2_SUPPORT
   2799     if (SOC_IS_TRIUMPH2(unit) || SOC_IS_APOLLO(unit) || 
   2800         SOC_IS_VALKYRIE2(unit) || SOC_IS_TRIDENT(unit) || SOC_IS_KATANA(unit)) {
   2801         return bcm_tr2_ipmc_egress_intf_set(unit, mc_index, port,
   2802                                             if_count, if_array, check_port);
   2803     }
   2804 #endif
   2805 #if defined(BCM_FIREBOLT_SUPPORT)
   2806     if (SOC_IS_FBX(unit)) {
   2807         return bcm_fb_ipmc_egress_intf_set(unit, mc_index, port, if_count, 
   2808                                            if_array, is_l3, check_port);
   2809     }
   2810 #endif
   2811 #endif  /* INCLUDE_L3 */
   2812     return BCM_E_UNAVAIL;
   2813 
   2814 }
   2815 
   2816 int
   2817 _bcm_esw_ipmc_port_trunkid_get(int unit, bcm_port_t port, int *tgid)
   2818 {
   2819 #if defined(INCLUDE_L3)
   2820 
   2821 #if defined(BCM_TOMAHAWK_SUPPORT)
   2822         if (SOC_IS_TOMAHAWKX(unit) || SOC_IS_TRIDENT3X(unit)) {
   2823             return bcm_th_port_trunkid_get(unit, port, tgid);
   2824         }
   2825 #endif
   2826 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   2827         if (SOC_IS_TRIDENT2PLUS(unit) || SOC_IS_APACHE(unit)) {
   2828             return bcm_td2p_port_trunkid_get(unit, port, tgid);
   2829         }
   2830 #endif
   2831 
   2832 #endif  /* INCLUDE_L3 */
   2833         return BCM_E_UNAVAIL;
   2834 }
   2835 
   2836 
   2837 int
   2838 _bcm_esw_ipmc_egress_intf_set_for_trunk_first_member(
   2839     int unit, int mc_index, bcm_port_t port,
   2840     int if_count, bcm_if_t *if_array, int is_l3,
   2841     int check_port, bcm_trunk_t tgid)
   2842 {
   2843 #if defined(INCLUDE_L3)
   2844 
   2845 #if defined(BCM_TOMAHAWK_SUPPORT)
   2846         if (SOC_IS_TOMAHAWKX(unit) || SOC_IS_TRIDENT3X(unit)) {
   2847             return bcm_th_ipmc_egress_intf_set_for_trunk_first_member(
   2848                        unit, mc_index, port, if_count, if_array,
   2849                        is_l3, check_port, tgid);
   2850         }
   2851 #endif
   2852 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   2853         if (SOC_IS_TRIDENT2PLUS(unit) || SOC_IS_APACHE(unit)) {
   2854             return bcm_td2p_ipmc_egress_intf_set_for_trunk_first_member(
   2855                        unit, mc_index, port, if_count, if_array,
   2856                        is_l3, check_port, tgid);
   2857         }
   2858 #endif
   2859 
   2860 #endif  /* INCLUDE_L3 */
   2861         return BCM_E_UNAVAIL;
   2862 }
   2863 
   2864 
   2865 int
   2866 _bcm_esw_ipmc_egress_intf_set_for_same_pipe_member(
   2867     int unit, int mc_index, bcm_port_t port,
   2868     bcm_port_t first_port, bcm_trunk_t tgid)
   2869 {
   2870 #if defined(INCLUDE_L3)
   2871 
   2872 #if defined(BCM_TOMAHAWK_SUPPORT)
   2873         if (SOC_IS_TOMAHAWKX(unit) || SOC_IS_TRIDENT3X(unit)) {
   2874             return bcm_th_ipmc_egress_intf_set_for_same_pipe_member(
   2875                        unit, mc_index, port, first_port, tgid);
   2876 
   2877         }
   2878 #endif
   2879 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   2880         if (SOC_IS_TRIDENT2PLUS(unit) || SOC_IS_APACHE(unit)) {
   2881             return bcm_td2p_ipmc_egress_intf_set_for_same_pipe_member(
   2882                        unit, mc_index, port, first_port, tgid);
   2883         }
   2884 #endif
   2885 
   2886 #endif  /* INCLUDE_L3 */
   2887         return BCM_E_UNAVAIL;
   2888 }
   2889 
   2890 int
   2891 _bcm_esw_ipmc_egress_intf_add_trunk_member(int unit, int mc_index,
   2892                                            bcm_port_t port)
   2893 {
   2894 #if defined(INCLUDE_L3)
   2895 
   2896 #if defined(BCM_TOMAHAWK_SUPPORT)
   2897     if (SOC_IS_TOMAHAWKX(unit) || SOC_IS_TRIDENT3X(unit)) {
   2898         return bcm_th_ipmc_egress_intf_add_trunk_member(unit, mc_index, port);
   2899     }
   2900 #endif
   2901 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   2902     if (SOC_IS_TRIDENT2PLUS(unit) || SOC_IS_APACHE(unit)) {
   2903         return bcm_td2p_ipmc_egress_intf_add_trunk_member(unit, mc_index, port);
   2904     }
   2905 #endif
   2906 
   2907 #endif  /* INCLUDE_L3 */
   2908     return BCM_E_UNAVAIL;
   2909 }
   2910 
   2911 int
   2912 _bcm_esw_ipmc_egress_intf_del_trunk_member(int unit, int mc_index,
   2913                                            bcm_port_t port)
   2914 {
   2915 #if defined(INCLUDE_L3)
   2916 
   2917 #if defined(BCM_TOMAHAWK_SUPPORT)
   2918     if (SOC_IS_TOMAHAWKX(unit) || SOC_IS_TRIDENT3X(unit)) {
   2919         return bcm_th_ipmc_egress_intf_del_trunk_member(unit, mc_index, port);
   2920     }
   2921 #endif
   2922 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   2923     if (SOC_IS_TRIDENT2PLUS(unit) || SOC_IS_APACHE(unit)) {
   2924         return bcm_td2p_ipmc_egress_intf_del_trunk_member(unit, mc_index, port);
   2925     }
   2926 #endif
   2927 
   2928 #endif  /* INCLUDE_L3 */
   2929     return BCM_E_UNAVAIL;
   2930 }
   2931 
   2932 
   2933 int
   2934 _bcm_esw_ipmc_egress_intf_add_for_trunk(int unit, int mc_index, bcm_trunk_t tgid,
   2935                                        int encap_id, int is_l3)
   2936 {
   2937 #if defined(INCLUDE_L3)
   2938 
   2939 #if defined(BCM_TOMAHAWK_SUPPORT)
   2940     if (SOC_IS_TOMAHAWKX(unit) || SOC_IS_TRIDENT3X(unit)) {
   2941         return bcm_th_ipmc_egress_intf_add_for_trunk(unit, mc_index, tgid,
   2942                                                        encap_id, is_l3);
   2943     }
   2944 #endif
   2945 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   2946     if (SOC_IS_TRIDENT2PLUS(unit) || SOC_IS_APACHE(unit)) {
   2947         return bcm_td2p_ipmc_egress_intf_add_for_trunk(unit, mc_index, tgid,
   2948                                                        encap_id, is_l3);
   2949     }
   2950 #endif
   2951 
   2952 #endif  /* INCLUDE_L3 */
   2953     return BCM_E_UNAVAIL;
   2954 }
   2955 
   2956 int
   2957 _bcm_esw_ipmc_egress_intf_del_for_trunk(int unit, int mc_index, bcm_trunk_t tgid,
   2958                                         int if_max, int encap_id, int is_l3)
   2959 {
   2960 #if defined(INCLUDE_L3)
   2961 
   2962 #if defined(BCM_TOMAHAWK_SUPPORT)
   2963     if (SOC_IS_TOMAHAWKX(unit) || SOC_IS_TRIDENT3X(unit)) {
   2964         return bcm_th_ipmc_egress_intf_del_for_trunk(unit, mc_index, tgid,
   2965                                                        if_max, encap_id, is_l3);
   2966     }
   2967 #endif
   2968 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   2969     if (SOC_IS_TRIDENT2PLUS(unit) || SOC_IS_APACHE(unit)) {
   2970         return bcm_td2p_ipmc_egress_intf_del_for_trunk(unit, mc_index, tgid,
   2971                                                        if_max, encap_id, is_l3);
   2972     }
   2973 #endif
   2974 
   2975 #endif  /* INCLUDE_L3 */
   2976     return BCM_E_UNAVAIL;
   2977 }
   2978 
   2979 int
   2980 _bcm_esw_ipmc_egress_intf_add_in_per_trunk_mode(int unit, int mc_index,
   2981                                        bcm_port_t port,
   2982                                        int encap_id, int is_l3)
   2983 {
   2984 #if defined(INCLUDE_L3)
   2985 
   2986 #if defined(BCM_TOMAHAWK_SUPPORT)
   2987     if (SOC_IS_TOMAHAWKX(unit) || SOC_IS_TRIDENT3X(unit)) {
   2988         return bcm_th_ipmc_egress_intf_add_in_per_trunk_mode(unit, mc_index,
   2989                                                              port, encap_id,
   2990                                                              is_l3);
   2991     }
   2992 #endif
   2993 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   2994     if (SOC_IS_TRIDENT2PLUS(unit) || SOC_IS_APACHE(unit)) {
   2995         return bcm_td2p_ipmc_egress_intf_add_in_per_trunk_mode(unit, mc_index,
   2996                                                                port, encap_id,
   2997                                                                is_l3);
   2998     }
   2999 #endif
   3000 
   3001 #endif  /* INCLUDE_L3 */
   3002     return BCM_E_UNAVAIL;
   3003 }
   3004 
   3005 int
   3006 _bcm_esw_ipmc_egress_intf_del_in_per_trunk_mode(int unit, int mc_index,
   3007                                        bcm_port_t port, int if_max,
   3008                                        int encap_id, int is_l3)
   3009 {
   3010 #if defined(INCLUDE_L3)
   3011 
   3012 #if defined(BCM_TOMAHAWK_SUPPORT)
   3013     if (SOC_IS_TOMAHAWKX(unit) || SOC_IS_TRIDENT3X(unit)) {
   3014         return bcm_th_ipmc_egress_intf_del_in_per_trunk_mode(unit, mc_index,
   3015                                                              port, if_max,
   3016                                                              encap_id, is_l3);
   3017     }
   3018 #endif
   3019 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   3020     if (SOC_IS_TRIDENT2PLUS(unit) || SOC_IS_APACHE(unit)) {
   3021         return bcm_td2p_ipmc_egress_intf_del_in_per_trunk_mode(unit, mc_index,
   3022                                                                port, if_max,
   3023                                                                encap_id, is_l3);
   3024     }
   3025 #endif
   3026 
   3027 #endif  /* INCLUDE_L3 */
   3028     return BCM_E_UNAVAIL;
   3029 }
   3030 
   3031 
   3032 /*
   3033  * Function:
   3034  *	bcm_esw_ipmc_egress_intf_get
   3035  * Purpose:
   3036  *	Retrieve list of interfaces in port's replication list
   3037  *      for chosen IPMC group.
   3038  * Parameters:
   3039  *	unit     - StrataSwitch PCI device unit number.
   3040  *	mc_index - The index number.
   3041  *	port     - port to list.
   3042  *      if_max   - maximum size of returned interface array.
   3043  *      if_count - (OUT) number of interfaces in list.
   3044  *	if_array - (OUT) array of bcm_if_t interfaces, size if_count.
   3045  * Returns:
   3046  *	BCM_E_XXX
   3047  */
   3048 
   3049 int
   3050 bcm_esw_ipmc_egress_intf_get(int unit, int mc_index, bcm_port_t port,
   3051                              int if_max, bcm_if_t *if_array, int *if_count)
   3052 {
   3053     bcm_module_t    modid;
   3054     bcm_trunk_t     tgid;
   3055     int             id, t, ismymodid;
   3056     int             port_out;
   3057 #if defined(BCM_HGPROXY_COE_SUPPORT)
   3058     int             is_local_subport;
   3059 #endif
   3060 
   3061     IPMC_INIT(unit);
   3062     IPMC_REPL_UNIT(unit);
   3063 
   3064     if (BCM_GPORT_IS_SET(port)) {
   3065         if (BCM_GPORT_IS_WLAN_PORT(port)) {
   3066             BCM_IF_ERROR_RETURN(
   3067                 _bcm_esw_gport_resolve(unit, port, &modid, &port, &tgid, &id));
   3068             BCM_IF_ERROR_RETURN(
   3069                 _bcm_esw_modid_is_local(unit, modid, &ismymodid));
   3070             if (ismymodid != TRUE) {
   3071                 return BCM_E_PORT;
   3072             }
   3073         } else {
   3074             BCM_IF_ERROR_RETURN(
   3075                 _bcm_esw_ipmc_gport_resolve(unit, port, &port_out, &modid,
   3076                                             &tgid, &t, 1));
   3077 #if defined(BCM_HGPROXY_COE_SUPPORT)
   3078             BCM_IF_ERROR_RETURN(
   3079                 _bcm_esw_port_is_local_subport(unit, port, modid, port_out,
   3080                                                &is_local_subport, &port_out));
   3081 #endif
   3082             port = port_out;
   3083         }
   3084     }
   3085 
   3086     if (!SOC_PORT_VALID(unit, port)) {
   3087         return BCM_E_PORT;
   3088     }
   3089 
   3090     BCM_IF_ERROR_RETURN(_bcm_esw_ipmc_convert_mcindex_m2h(&mc_index));
   3091 
   3092 
   3093 #if defined(INCLUDE_L3)
   3094 #if defined(BCM_TOMAHAWK_SUPPORT)
   3095     if (SOC_IS_TOMAHAWKX(unit) || SOC_IS_TRIDENT3X(unit)) {
   3096         return bcm_th_ipmc_egress_intf_get(unit, mc_index, port,
   3097                                             if_max, if_array, if_count);
   3098     }
   3099 #endif
   3100 #if defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_KATANA2_SUPPORT)
   3101     if (SOC_IS_TRIUMPH3(unit) || SOC_IS_TD2_TT2(unit) || SOC_IS_KATANA2(unit))     {
   3102         return bcm_tr3_ipmc_egress_intf_get(unit, mc_index, port,
   3103                                             if_max, if_array, if_count);
   3104     }
   3105 #endif
   3106 #ifdef	BCM_TRIUMPH2_SUPPORT
   3107     if (SOC_IS_TRIUMPH2(unit) || SOC_IS_APOLLO(unit) || 
   3108         SOC_IS_VALKYRIE2(unit) || SOC_IS_TRIDENT(unit) || SOC_IS_KATANA(unit)) {
   3109         return bcm_tr2_ipmc_egress_intf_get(unit, mc_index, port,
   3110                                             if_max, if_array, if_count);
   3111     }
   3112 #endif
   3113 #if defined(BCM_FIREBOLT_SUPPORT)
   3114     if (SOC_IS_FBX(unit)) {
   3115         return bcm_fb_ipmc_egress_intf_get(unit, mc_index, port,
   3116                                            if_max, if_array, if_count);
   3117     }
   3118 #endif
   3119 #endif /* INCLUDE_L3 */
   3120     return BCM_E_UNAVAIL;
   3121 }
   3122 
   3123 /****************************************************************
   3124  *
   3125  * Stack port updating of IPMC tables
   3126  */
   3127 
   3128 STATIC void
   3129 _xgs_ipmc_bitmaps_get(int unit, ipmc_entry_t *ipmc_entry,
   3130                       bcm_pbmp_t *l2_ports, bcm_pbmp_t *l3_ports)
   3131 {
   3132     BCM_PBMP_CLEAR(*l2_ports);
   3133     BCM_PBMP_CLEAR(*l3_ports);
   3134 
   3135     soc_mem_pbmp_field_get(unit, L3_IPMCm, ipmc_entry, L3_BITMAPf, l3_ports);
   3136     soc_mem_pbmp_field_get(unit, L3_IPMCm, ipmc_entry, L2_BITMAPf, l2_ports);
   3137 }
   3138 
   3139 STATIC void
   3140 _xgs_ipmc_bitmaps_set(int unit, ipmc_entry_t *ipmc_entry,
   3141                       bcm_pbmp_t l2_ports, bcm_pbmp_t l3_ports)
   3142 {
   3143 #if defined(BCM_TRIDENT3_SUPPORT)
   3144     /* Set new bitmaps and write back entry */
   3145     if (SOC_MEM_FIELD_VALID(unit, L3_IPMCm, L2_L3f) &&
   3146         BCM_PBMP_NOT_NULL(l3_ports)) {
   3147         uint32 cancun_ver;
   3148         int32 rv = SOC_E_UNAVAIL;
   3149 
   3150         rv =  soc_cancun_version_get(unit, &cancun_ver);
   3151         if ((SOC_SUCCESS(rv)) &&
   3152                 (cancun_ver < SOC_CANCUN_VERSION_DEF_5_3_2)) {
   3153             soc_mem_field32_set(unit, L3_IPMCm, ipmc_entry, L2_L3f, 1);
   3154         }
   3155     }
   3156 #endif
   3157 
   3158     soc_mem_pbmp_field_set(unit, L3_IPMCm, ipmc_entry, L3_BITMAPf, &l3_ports);
   3159     soc_mem_pbmp_field_set(unit, L3_IPMCm, ipmc_entry, L2_BITMAPf, &l2_ports);
   3160 }
   3161 
   3162 
   3163 STATIC int
   3164 _xgs_ipmc_stk_update(int unit, bcm_pbmp_t add_ports,
   3165                      bcm_pbmp_t remove_ports)
   3166 {
   3167     int rv = BCM_E_NONE;  /* Ignore if unavailable */
   3168 
   3169 #if defined(BCM_XGS_SUPPORT)
   3170     int i;
   3171     ipmc_entry_t	ipmc_entry;
   3172     bcm_pbmp_t new_l2_ports, old_l2_ports;
   3173     bcm_pbmp_t new_l3_ports, old_l3_ports;
   3174     int changed = 0;
   3175 
   3176     soc_mem_lock(unit, L3_IPMCm);
   3177     for (i = soc_mem_index_min(unit, L3_IPMCm);
   3178              i <= soc_mem_index_max(unit, L3_IPMCm);
   3179              i++) {
   3180         rv = soc_mem_read(unit, L3_IPMCm, MEM_BLOCK_ANY, i, &ipmc_entry);
   3181         if (rv < 0) {
   3182             break;
   3183         }
   3184         if (soc_L3_IPMCm_field32_get(unit, &ipmc_entry, VALIDf) == 0) {
   3185             continue;
   3186         }
   3187 
   3188         /* Get bitmaps, update, write back if changed */
   3189         _xgs_ipmc_bitmaps_get(unit, &ipmc_entry,
   3190                               &old_l2_ports, &old_l3_ports);
   3191         SOC_PBMP_ASSIGN(new_l3_ports, old_l3_ports);
   3192         SOC_PBMP_ASSIGN(new_l2_ports, old_l2_ports);
   3193 
   3194         BCM_PBMP_OR(new_l2_ports, add_ports);
   3195         BCM_PBMP_REMOVE(new_l2_ports, remove_ports);
   3196         BCM_PBMP_REMOVE(new_l3_ports, SOC_PBMP_STACK_CURRENT(unit));
   3197 
   3198         if (BCM_PBMP_NEQ(new_l2_ports, old_l2_ports) ||
   3199                 BCM_PBMP_NEQ(new_l3_ports, old_l3_ports)) {
   3200             ++changed;
   3201             _xgs_ipmc_bitmaps_set(unit, &ipmc_entry,
   3202                                   new_l2_ports, new_l3_ports);
   3203             rv = soc_mem_write(unit, L3_IPMCm, MEM_BLOCK_ALL, i, &ipmc_entry);
   3204             if (rv < 0) {
   3205                 break;
   3206             }
   3207         }
   3208     }
   3209     soc_mem_unlock(unit, L3_IPMCm);
   3210 
   3211     if (changed) {
   3212         LOG_VERBOSE(BSL_LS_BCM_IPMC,
   3213                     (BSL_META_U(unit,
   3214                                 "IPMC %d: xgs stk update changed %d entries\n"),
   3215                      unit, changed));
   3216     }
   3217 #endif
   3218 
   3219     return rv;
   3220 }
   3221 
   3222 
   3223 /*
   3224  * Function:
   3225  *      _bcm_esw_ipmc_stk_update
   3226  * Purpose:
   3227  *      Update port bitmaps after stack change
   3228  * Parameters:
   3229  *
   3230  * Returns:
   3231  *      BCM_E_XXX
   3232  * Notes:
   3233  */
   3234 
   3235 
   3236 int
   3237 _bcm_esw_ipmc_stk_update(int unit, uint32 flags)
   3238 {
   3239     bcm_pbmp_t add_ports, remove_ports;
   3240     int rv = BCM_E_NONE;
   3241 
   3242     if (soc_feature(unit, soc_feature_ip_mcast)) {
   3243         /* Calculate ports that should and should not be in bitmap */
   3244         SOC_PBMP_ASSIGN(add_ports, SOC_PBMP_STACK_CURRENT(unit));
   3245         SOC_PBMP_REMOVE(add_ports, SOC_PBMP_STACK_INACTIVE(unit));
   3246 
   3247         /* Remove ports no longer stacking, or explicitly inactive */
   3248         SOC_PBMP_ASSIGN(remove_ports, SOC_PBMP_STACK_PREVIOUS(unit));
   3249         SOC_PBMP_REMOVE(remove_ports, SOC_PBMP_STACK_CURRENT(unit));
   3250         SOC_PBMP_OR(remove_ports, SOC_PBMP_STACK_INACTIVE(unit));
   3251 
   3252         if (SOC_IS_XGS_SWITCH(unit)) {
   3253             rv = _xgs_ipmc_stk_update(unit, add_ports, remove_ports);
   3254         } else { 
   3255             rv = BCM_E_NONE;  /* Ignore if unavailable */
   3256         }
   3257     }
   3258 
   3259     return rv;
   3260 }
   3261 
   3262 #ifndef BCM_SW_STATE_DUMP_DISABLE
   3263 /*
   3264  * Function:
   3265  *     _bcm_ipmc_sw_dump
   3266  * Purpose:
   3267  *     Displays IPMC information maintained by software.
   3268  * Parameters:
   3269  *     unit - Device unit number
   3270  * Returns:
   3271  *     None
   3272  */
   3273 void
   3274 _bcm_ipmc_sw_dump(int unit)
   3275 {
   3276     LOG_CLI((BSL_META_U(unit,
   3277                         "\nSW Information IPMC - Unit %d\n"), unit));
   3278     LOG_CLI((BSL_META_U(unit,
   3279                         "  Init : %d\n"), _bcm_ipmc_init[unit]));
   3280     LOG_CLI((BSL_META_U(unit,
   3281                         "  Multicast Index Return Type : %d\n"), _bcm_ipmc_idx_ret_type[unit]));
   3282 #ifdef BCM_WARM_BOOT_SUPPORT
   3283     if (SOC_IS_XGS3_SWITCH(unit)) {
   3284         int rv;
   3285         uint8 flags;
   3286         int threshold;
   3287 
   3288         rv = _bcm_esw_ipmc_repl_wb_flags_get(unit, _BCM_IPMC_WB_FLAGS_ALL,
   3289                                              &flags);
   3290         if (BCM_SUCCESS(rv)) {
   3291             LOG_CLI((BSL_META_U(unit,
   3292                                 "  IPMC SW flags:")));
   3293             if (flags & _BCM_IPMC_WB_REPL_LIST) {
   3294                 LOG_CLI((BSL_META_U(unit,
   3295                                     "  ReplicationSharing")));
   3296             }
   3297             if (flags & _BCM_IPMC_WB_MULTICAST_MODE) {
   3298                 LOG_CLI((BSL_META_U(unit,
   3299                                     "  MulticastAPIMode")));
   3300             }
   3301             if (flags & _BCM_IPMC_WB_IPMC_GROUP_TYPE_MULTICAST) {
   3302                 LOG_CLI((BSL_META_U(unit,
   3303                                     "  L3McIdxRetType")));
   3304             }
   3305             if (flags & _BCM_IPMC_WB_L2MC_GROUP_TYPE_MULTICAST) {
   3306                 LOG_CLI((BSL_META_U(unit,
   3307                                     "  L2McIdxRetType")));
   3308             }
   3309             LOG_CLI((BSL_META_U(unit,
   3310                                 "\n")));
   3311         } else {
   3312             LOG_CLI((BSL_META_U(unit,
   3313                                 "Unable to retrieve unit %d IPMC flags - %d\n"),
   3314                      unit, rv));
   3315         }
   3316 
   3317         LOG_CLI((BSL_META_U(unit,
   3318                             "  IPMC replication availablity threshold: ")));
   3319         rv = _bcm_esw_ipmc_repl_wb_threshold_get(unit, &threshold);
   3320         if (BCM_SUCCESS(rv)) {
   3321             LOG_CLI((BSL_META_U(unit,
   3322                                 "%d percent\n"), threshold));
   3323         } else {
   3324             LOG_CLI((BSL_META_U(unit,
   3325                                 "0 percent\n")));
   3326         }
   3327     }
   3328 #endif /* BCM_WARM_BOOT_SUPPORT */
   3329 #if defined(BCM_TRIUMPH_SUPPORT) 
   3330     if (SOC_IS_TR_VL(unit)) {
   3331          _bcm_tr_ipmc_sw_dump(unit); 
   3332     } else
   3333 #endif /* BCM_TRIUMPH_SUPPORT */
   3334 #ifdef BCM_XGS3_SWITCH_SUPPORT
   3335     if (SOC_IS_FBX(unit)) {
   3336         _bcm_xgs3_ipmc_sw_dump(unit);
   3337     }
   3338 #endif /* BCM_XGS3_SWITCH_SUPPORT */
   3339 
   3340     return;
   3341 }
   3342 #endif /* BCM_SW_STATE_DUMP_DISABLE */
   3343 
   3344 /*
   3345  * Function:
   3346  *      _bcm_esw_ipmc_idx_ret_type_set
   3347  * Purpose:
   3348  *      Set multicast index return type.
   3349  * Parameters:
   3350  *      unit - StrataSwitch unit #
   3351  *      arg - 0 means hardware multicast index, 1 means bcm_multicast_t
   3352  * Returns:
   3353  *      BCM_E_NONE 
   3354  *      BCM_E_UNAVAIL
   3355  */
   3356 
   3357 int
   3358 _bcm_esw_ipmc_idx_ret_type_set(int unit, int arg)
   3359 {
   3360     if (SOC_IS_XGS3_SWITCH(unit)) {
   3361         IPMC_INIT(unit);
   3362         _bcm_ipmc_idx_ret_type[unit] = arg;
   3363 
   3364 #ifdef BCM_WARM_BOOT_SUPPORT
   3365         /* Record this value in HW for Warm Boot recovery. */
   3366         BCM_IF_ERROR_RETURN
   3367             (_bcm_esw_ipmc_repl_wb_flags_set(unit,
   3368                   (arg ? _BCM_IPMC_WB_IPMC_GROUP_TYPE_MULTICAST : 0),
   3369                          _BCM_IPMC_WB_IPMC_GROUP_TYPE_MULTICAST));
   3370 #endif /* BCM_WARM_BOOT_SUPPORT */
   3371         
   3372         return BCM_E_NONE;
   3373     } 
   3374 
   3375     return BCM_E_UNAVAIL;
   3376 }
   3377 
   3378 /*
   3379  * Function:
   3380  *      _bcm_esw_ipmc_idx_ret_type_get
   3381  * Purpose:
   3382  *      Get multicast index return type.
   3383  * Parameters:
   3384  *      unit - StrataSwitch unit #
   3385  *      arg - Pointer to where retrieved value will be written
   3386  * Returns:
   3387  *      BCM_E_NONE 
   3388  *      BCM_E_UNAVAIL
   3389  */
   3390 
   3391 int
   3392 _bcm_esw_ipmc_idx_ret_type_get(int unit, int *arg)
   3393 {
   3394     if (SOC_IS_XGS3_SWITCH(unit)) {
   3395         IPMC_INIT(unit);
   3396         *arg = _bcm_ipmc_idx_ret_type[unit];
   3397         return BCM_E_NONE;
   3398     }
   3399 
   3400     return BCM_E_UNAVAIL;
   3401 }
   3402 
   3403 /*
   3404  * Function:
   3405  *      _bcm_esw_ipmc_repl_threshold_set
   3406  * Purpose:
   3407  *      Set IPMC replication table available space threshold.
   3408  * Parameters:
   3409  *      unit - StrataSwitch unit #
   3410  *      arg - Available space threshold
   3411  * Returns:
   3412  *      BCM_E_NONE 
   3413  *      BCM_E_UNAVAIL
   3414  */
   3415 int
   3416 _bcm_esw_ipmc_repl_threshold_set(int unit, int arg)
   3417 {
   3418 #ifdef BCM_TRIDENT_SUPPORT
   3419     if (SOC_IS_TD_TT(unit)) {
   3420         IPMC_INIT(unit);
   3421         if ((arg < 0) || (arg > 100)) {
   3422             return BCM_E_PARAM;
   3423         }
   3424         _bcm_ipmc_repl_threshold[unit] = arg;
   3425 
   3426 #ifdef BCM_WARM_BOOT_SUPPORT
   3427         /* Record this value in HW for Warm Boot recovery. */
   3428         BCM_IF_ERROR_RETURN
   3429             (_bcm_esw_ipmc_repl_wb_threshold_set(unit, arg));
   3430 #endif /* BCM_WARM_BOOT_SUPPORT */
   3431         
   3432         return BCM_E_NONE;
   3433     } 
   3434 #endif /* BCM_TRIDENT_SUPPORT */
   3435 
   3436     return BCM_E_UNAVAIL;
   3437 }
   3438 
   3439 /*
   3440  * Function:
   3441  *      _bcm_esw_ipmc_repl_threshold_get
   3442  * Purpose:
   3443  *      Get IPMC replication table available space threshold.
   3444  * Parameters:
   3445  *      unit - StrataSwitch unit #
   3446  *      arg - Available space threshold
   3447  * Returns:
   3448  *      BCM_E_NONE 
   3449  *      BCM_E_UNAVAIL
   3450  */
   3451 int
   3452 _bcm_esw_ipmc_repl_threshold_get(int unit, int *arg)
   3453 {
   3454 #ifdef BCM_TRIDENT_SUPPORT
   3455     if (SOC_IS_TD_TT(unit)) {
   3456         IPMC_INIT(unit);
   3457         *arg = _bcm_ipmc_repl_threshold[unit];
   3458         return BCM_E_NONE;
   3459     }
   3460 #endif /* BCM_TRIDENT_SUPPORT */
   3461 
   3462     return BCM_E_UNAVAIL;
   3463 }
   3464 
   3465 /*
   3466  * Function:
   3467  *      bcm_esw_ipmc_rp_create
   3468  * Purpose:
   3469  *      Create a rendezvous point.
   3470  * Parameters:
   3471  *      unit - StrataSwitch unit #
   3472  *      flags - BCM_IPMC_RP_xxx flags.
   3473  *      rp_id - (IN/OUT) Rendezvous point ID.
   3474  * Returns:
   3475  *      BCM_E_xxx
   3476  */
   3477 int 
   3478 bcm_esw_ipmc_rp_create(
   3479     int unit, 
   3480     uint32 flags, 
   3481     int *rp_id)
   3482 {
   3483 #ifdef BCM_TRIDENT2_SUPPORT
   3484     if (soc_feature(unit, soc_feature_pim_bidir)) {
   3485         int rv;
   3486 
   3487         L3_LOCK(unit);
   3488         rv = bcm_td2_ipmc_rp_create(unit, flags, rp_id);
   3489         L3_UNLOCK(unit);
   3490         return rv;
   3491     }
   3492 #endif /* BCM_TRIDENT2_SUPPORT */
   3493 
   3494     return BCM_E_UNAVAIL;
   3495 }
   3496 
   3497 /*
   3498  * Function:
   3499  *      bcm_esw_ipmc_rp_destroy
   3500  * Purpose:
   3501  *      Destroy a rendezvous point.
   3502  * Parameters:
   3503  *      unit - StrataSwitch unit #
   3504  *      rp_id - Rendezvous point ID.
   3505  * Returns:
   3506  *      BCM_E_xxx
   3507  */
   3508 int 
   3509 bcm_esw_ipmc_rp_destroy(
   3510     int unit, 
   3511     int rp_id)
   3512 {
   3513 #ifdef BCM_TRIDENT2_SUPPORT
   3514     if (soc_feature(unit, soc_feature_pim_bidir)) {
   3515         int rv;
   3516 
   3517         L3_LOCK(unit);
   3518         rv = bcm_td2_ipmc_rp_destroy(unit, rp_id);
   3519         L3_UNLOCK(unit);
   3520         return rv;
   3521     }
   3522 #endif /* BCM_TRIDENT2_SUPPORT */
   3523 
   3524     return BCM_E_UNAVAIL;
   3525 }
   3526 
   3527 /*
   3528  * Function:
   3529  *      bcm_esw_ipmc_rp_set
   3530  * Purpose:
   3531  *      Set active L3 interfaces for a rendezvous point.
   3532  * Parameters:
   3533  *      unit - StrataSwitch unit #
   3534  *      rp_id - Rendezvous point ID
   3535  *      intf_count - Number of elements in intf_array
   3536  *      intf_array - Array of active L3 interfaces
   3537  * Returns:
   3538  *      BCM_E_xxx
   3539  */
   3540 int 
   3541 bcm_esw_ipmc_rp_set(
   3542     int unit, 
   3543     int rp_id, 
   3544     int intf_count, 
   3545     bcm_if_t *intf_array)
   3546 {
   3547 #ifdef BCM_TRIDENT2_SUPPORT
   3548     if (soc_feature(unit, soc_feature_pim_bidir)) {
   3549         int rv;
   3550 
   3551         L3_LOCK(unit);
   3552         rv = bcm_td2_ipmc_rp_set(unit, rp_id, intf_count, intf_array);
   3553         L3_UNLOCK(unit);
   3554         return rv;
   3555     }
   3556 #endif /* BCM_TRIDENT2_SUPPORT */
   3557 
   3558     return BCM_E_UNAVAIL;
   3559 }
   3560 
   3561 /*
   3562  * Function:
   3563  *      bcm_esw_ipmc_rp_get
   3564  * Purpose:
   3565  *      Get active L3 interfaces for a rendezvous point.
   3566  * Parameters:
   3567  *      unit - StrataSwitch unit #
   3568  *      rp_id - Rendezvous point ID
   3569  *      intf_max - Number of elements in intf_array
   3570  *      intf_array - (OUT) Array of active L3 interfaces
   3571  *      intf_count - (OUT) Number of elements returned in intf_array
   3572  * Returns:
   3573  *      BCM_E_xxx
   3574  */
   3575 int 
   3576 bcm_esw_ipmc_rp_get(
   3577     int unit, 
   3578     int rp_id, 
   3579     int intf_max, 
   3580     bcm_if_t *intf_array, 
   3581     int *intf_count)
   3582 {
   3583 #ifdef BCM_TRIDENT2_SUPPORT
   3584     if (soc_feature(unit, soc_feature_pim_bidir)) {
   3585         int rv;
   3586 
   3587         L3_LOCK(unit);
   3588         rv = bcm_td2_ipmc_rp_get(unit, rp_id, intf_max, intf_array, intf_count);
   3589         L3_UNLOCK(unit);
   3590         return rv;
   3591     }
   3592 #endif /* BCM_TRIDENT2_SUPPORT */
   3593 
   3594     return BCM_E_UNAVAIL;
   3595 }
   3596 
   3597 /*
   3598  * Function:
   3599  *      bcm_esw_ipmc_rp_add
   3600  * Purpose:
   3601  *      Add an active L3 interface to a rendezvous point.
   3602  * Parameters:
   3603  *      unit - StrataSwitch unit #
   3604  *      rp_id - Rendezvous point ID
   3605  *      intf_id - L3 interface ID
   3606  * Returns:
   3607  *      BCM_E_xxx
   3608  */
   3609 int 
   3610 bcm_esw_ipmc_rp_add(
   3611     int unit, 
   3612     int rp_id, 
   3613     bcm_if_t intf_id)
   3614 {
   3615 #ifdef BCM_TRIDENT2_SUPPORT
   3616     if (soc_feature(unit, soc_feature_pim_bidir)) {
   3617         int rv;
   3618 
   3619         L3_LOCK(unit);
   3620         rv = bcm_td2_ipmc_rp_add(unit, rp_id, intf_id);
   3621         L3_UNLOCK(unit);
   3622         return rv;
   3623     }
   3624 #endif /* BCM_TRIDENT2_SUPPORT */
   3625 
   3626     return BCM_E_UNAVAIL;
   3627 }
   3628 
   3629 /*
   3630  * Function:
   3631  *      bcm_esw_ipmc_rp_delete
   3632  * Purpose:
   3633  *      Delete an active L3 interface from a rendezvous point.
   3634  * Parameters:
   3635  *      unit - StrataSwitch unit #
   3636  *      rp_id - Rendezvous point ID
   3637  *      intf_id - L3 interface ID
   3638  * Returns:
   3639  *      BCM_E_xxx
   3640  */
   3641 int 
   3642 bcm_esw_ipmc_rp_delete(
   3643     int unit, 
   3644     int rp_id, 
   3645     bcm_if_t intf_id)
   3646 {
   3647 #ifdef BCM_TRIDENT2_SUPPORT
   3648     if (soc_feature(unit, soc_feature_pim_bidir)) {
   3649         int rv;
   3650 
   3651         L3_LOCK(unit);
   3652         rv = bcm_td2_ipmc_rp_delete(unit, rp_id, intf_id);
   3653         L3_UNLOCK(unit);
   3654         return rv;
   3655     }
   3656 #endif /* BCM_TRIDENT2_SUPPORT */
   3657 
   3658     return BCM_E_UNAVAIL;
   3659 }
   3660 
   3661 /*
   3662  * Function:
   3663  *      bcm_esw_ipmc_rp_delete_all
   3664  * Purpose:
   3665  *      Delete all active L3 interfaces from a rendezvous point.
   3666  * Parameters:
   3667  *      unit - StrataSwitch unit #
   3668  *      rp_id - Rendezvous point ID
   3669  * Returns:
   3670  *      BCM_E_xxx
   3671  */
   3672 int 
   3673 bcm_esw_ipmc_rp_delete_all(
   3674     int unit, 
   3675     int rp_id)
   3676 {
   3677 #ifdef BCM_TRIDENT2_SUPPORT
   3678     if (soc_feature(unit, soc_feature_pim_bidir)) {
   3679         int rv;
   3680 
   3681         L3_LOCK(unit);
   3682         rv = bcm_td2_ipmc_rp_delete_all(unit, rp_id);
   3683         L3_UNLOCK(unit);
   3684         return rv;
   3685     }
   3686 #endif /* BCM_TRIDENT2_SUPPORT */
   3687 
   3688     return BCM_E_UNAVAIL;
   3689 }
   3690 
   3691 /*
   3692  * Function:
   3693  *      bcm_esw_ipmc_range_add
   3694  * Purpose:
   3695  *      Add a range of PIM-BIDIR IPMC addresses.
   3696  * Parameters:
   3697  *      unit - StrataSwitch unit #
   3698  *      range_id - (IN/OUT) Range ID
   3699  *      range - IPMC address range info
   3700  * Returns:
   3701  *      BCM_E_xxx
   3702  */
   3703 int 
   3704 bcm_esw_ipmc_range_add(
   3705     int unit, 
   3706     int *range_id, 
   3707     bcm_ipmc_range_t *range)
   3708 {
   3709 #ifdef BCM_TRIDENT2_SUPPORT
   3710     if (soc_feature(unit, soc_feature_pim_bidir)) {
   3711         int rv;
   3712 
   3713         L3_LOCK(unit);
   3714         rv = bcm_td2_ipmc_range_add(unit, range_id, range);
   3715         L3_UNLOCK(unit);
   3716         return rv;
   3717     }
   3718 #endif /* BCM_TRIDENT2_SUPPORT */
   3719 
   3720     return BCM_E_UNAVAIL;
   3721 }
   3722 
   3723 /*
   3724  * Function:
   3725  *      bcm_esw_ipmc_range_delete
   3726  * Purpose:
   3727  *      Delete a range of PIM-BIDIR IPMC addresses.
   3728  * Parameters:
   3729  *      unit - StrataSwitch unit #
   3730  *      range_id - Range ID
   3731  * Returns:
   3732  *      BCM_E_xxx
   3733  */
   3734 int 
   3735 bcm_esw_ipmc_range_delete(
   3736     int unit, 
   3737     int range_id)
   3738 {
   3739 #ifdef BCM_TRIDENT2_SUPPORT
   3740     if (soc_feature(unit, soc_feature_pim_bidir)) {
   3741         int rv;
   3742 
   3743         L3_LOCK(unit);
   3744         rv = bcm_td2_ipmc_range_delete(unit, range_id);
   3745         L3_UNLOCK(unit);
   3746         return rv;
   3747     }
   3748 #endif /* BCM_TRIDENT2_SUPPORT */
   3749 
   3750     return BCM_E_UNAVAIL;
   3751 }
   3752 
   3753 /*
   3754  * Function:
   3755  *      bcm_esw_ipmc_range_delete_all
   3756  * Purpose:
   3757  *      Delete all ranges of PIM-BIDIR IPMC addresses.
   3758  * Parameters:
   3759  *      unit - StrataSwitch unit #
   3760  *      range_id - Range ID
   3761  * Returns:
   3762  *      BCM_E_xxx
   3763  */
   3764 int 
   3765 bcm_esw_ipmc_range_delete_all(
   3766     int unit)
   3767 {
   3768 #ifdef BCM_TRIDENT2_SUPPORT
   3769     if (soc_feature(unit, soc_feature_pim_bidir)) {
   3770         int rv;
   3771 
   3772         L3_LOCK(unit);
   3773         rv = bcm_td2_ipmc_range_delete_all(unit);
   3774         L3_UNLOCK(unit);
   3775         return rv;
   3776     }
   3777 #endif /* BCM_TRIDENT2_SUPPORT */
   3778 
   3779    return BCM_E_UNAVAIL;
   3780 }
   3781 
   3782 /*
   3783  * Function:
   3784  *      bcm_esw_ipmc_range_get
   3785  * Purpose:
   3786  *      Get a range of PIM-BIDIR IPMC addresses.
   3787  * Parameters:
   3788  *      unit - StrataSwitch unit #
   3789  *      range_id - Range ID
   3790  *      range - (OUT) Range info
   3791  * Returns:
   3792  *      BCM_E_xxx
   3793  */
   3794 int 
   3795 bcm_esw_ipmc_range_get(
   3796     int unit, 
   3797     int range_id, 
   3798     bcm_ipmc_range_t *range)
   3799 {
   3800 #ifdef BCM_TRIDENT2_SUPPORT
   3801     if (soc_feature(unit, soc_feature_pim_bidir)) {
   3802         int rv;
   3803 
   3804         L3_LOCK(unit);
   3805         rv = bcm_td2_ipmc_range_get(unit, range_id, range);
   3806         L3_UNLOCK(unit);
   3807         return rv;
   3808     }
   3809 #endif /* BCM_TRIDENT2_SUPPORT */
   3810 
   3811     return BCM_E_UNAVAIL;
   3812 }
   3813 
   3814 /*
   3815  * Function:
   3816  *      bcm_esw_ipmc_range_size_get
   3817  * Purpose:
   3818  *      Get the number of PIM-BIDIR IPMC address ranges supported by the device.
   3819  * Parameters:
   3820  *      unit - StrataSwitch unit #
   3821  *      size - (OUT) Number of ranges 
   3822  * Returns:
   3823  *      BCM_E_xxx
   3824  */
   3825 int 
   3826 bcm_esw_ipmc_range_size_get(
   3827     int unit, 
   3828     int *size)
   3829 {
   3830 #ifdef BCM_TRIDENT2_SUPPORT
   3831     if (soc_feature(unit, soc_feature_pim_bidir)) {
   3832         int rv;
   3833 
   3834         L3_LOCK(unit);
   3835         rv = bcm_td2_ipmc_range_size_get(unit, size);
   3836         L3_UNLOCK(unit);
   3837         return rv;
   3838     }
   3839 #endif /* BCM_TRIDENT2_SUPPORT */
   3840 
   3841     return BCM_E_UNAVAIL;
   3842 }
   3843 
   3844 /*
   3845  * Function:
   3846  *      bcm_esw_ipmc_stat_attach
   3847  * Description:
   3848  *      Attach counters entries to the given IPMC group
   3849  *
   3850  * Parameters:
   3851  *      unit             - (IN) unit number
   3852  *      info             - (IN) IPMC entry information  
   3853  *      stat_counter_id  - (IN) Stat Counter ID.
   3854  *
   3855  * Return Value:
   3856  *      BCM_E_XXX
   3857  */
   3858 bcm_error_t bcm_esw_ipmc_stat_attach(
   3859             int unit,
   3860             bcm_ipmc_addr_t *info,
   3861             uint32 stat_counter_id)
   3862 {
   3863 #if defined(BCM_TRIDENT2_SUPPORT)
   3864     if (SOC_IS_TD2_TT2(unit)) {
   3865         return _bcm_td2_ipmc_stat_attach(unit, info, stat_counter_id);
   3866     } else
   3867 #endif
   3868     {
   3869         return BCM_E_UNAVAIL;
   3870     }
   3871 }
   3872 
   3873 /*
   3874  * Function:
   3875  *      bcm_esw_ipmc_stat_detach
   3876  * Description:
   3877  *      Detach counters entries to the given IPMC group
   3878  *
   3879  * Parameters:
   3880  *      unit             - (IN) unit number
   3881  *      info             - (IN) IPMC entry information
   3882  *
   3883  * Return Value:
   3884  *      BCM_E_XXX
   3885  * Notes:
   3886  */
   3887 bcm_error_t bcm_esw_ipmc_stat_detach(
   3888             int unit,
   3889             bcm_ipmc_addr_t *info)
   3890 {
   3891 #if defined(BCM_TRIDENT2_SUPPORT)
   3892     if (SOC_IS_TD2_TT2(unit)) {    
   3893         return _bcm_td2_ipmc_stat_detach(unit, info);
   3894     } else
   3895 #endif
   3896     {
   3897         return BCM_E_UNAVAIL;
   3898     }
   3899 }
   3900 
   3901 /*
   3902  * Function:
   3903  *      _bcm_esw_ipmc_stat_counter_get
   3904  * Description:
   3905  *      Get counter statistic values for specific IPMC group
   3906  *
   3907  * Parameters:
   3908  *      unit             - (IN) unit number
   3909  *      sync_mode        - (IN) if 1 sync sw count value with hw count
   3910  *                              before retieving count else get
   3911  *                              sw accumulated count
   3912  *      info             - (IN) IPMC entry information
   3913  *      stat             - (IN) Type of the counter to retrieve
   3914  *                              I.e. ingress/egress byte/packet)
   3915  *      num_entries      - (IN) Number of counter Entries
   3916  *      counter_indexes  - (IN) Pointer to Counter indexes entries
   3917  *      counter_values   - (OUT) Pointer to counter values
   3918  *
   3919  * Return Value:
   3920  *      BCM_E_XXX
   3921  * Notes:
   3922  */
   3923 bcm_error_t
   3924 _bcm_esw_ipmc_stat_counter_get(int              unit,
   3925                                int              sync_mode,
   3926                                bcm_ipmc_addr_t  *info,
   3927                                bcm_ipmc_stat_t  stat,
   3928                                uint32           num_entries,
   3929                                uint32           *counter_indexes,
   3930                                bcm_stat_value_t *counter_values)
   3931 {
   3932 #if defined(BCM_TRIDENT2_SUPPORT)
   3933     if (SOC_IS_TD2_TT2(unit)) { 
   3934         return _bcm_td2_ipmc_stat_counter_get(unit, sync_mode, info, stat, 
   3935                     num_entries, counter_indexes, counter_values);
   3936     } else
   3937 #endif
   3938     {
   3939         return BCM_E_UNAVAIL;
   3940     }
   3941 }
   3942 
   3943 /*
   3944  * Function:
   3945  *      bcm_esw_ipmc_stat_counter_get
   3946  * Description:
   3947  *      Get sw accumulated counter statistic values for i
   3948  *      specific IPMC group
   3949  *
   3950  * Parameters:
   3951  *      unit             - (IN) unit number
   3952  *      info             - (IN) IPMC entry information
   3953  *      stat             - (IN) Type of the counter to retrieve
   3954  *                              I.e. ingress/egress byte/packet)
   3955  *      num_entries      - (IN) Number of counter Entries
   3956  *      counter_indexes  - (IN) Pointer to Counter indexes entries
   3957  *      counter_values   - (OUT) Pointer to counter values
   3958  *
   3959  * Return Value:
   3960  *      BCM_E_XXX
   3961  * Notes:
   3962  */
   3963 bcm_error_t
   3964 bcm_esw_ipmc_stat_counter_get(int              unit,
   3965                               bcm_ipmc_addr_t  *info,
   3966                               bcm_ipmc_stat_t  stat,
   3967                               uint32           num_entries,
   3968                               uint32           *counter_indexes,
   3969                               bcm_stat_value_t *counter_values)
   3970 {
   3971         return _bcm_esw_ipmc_stat_counter_get(unit, 0, info, stat, 
   3972                     num_entries, counter_indexes, counter_values);
   3973 }
   3974 
   3975 /*
   3976  * Function:
   3977  *      bcm_esw_ipmc_stat_counter_sync_get
   3978  * Description:
   3979  *      Get counter statistic values for specific IPMC group
   3980  *      but sync the software accumulated count with hw count 
   3981  *      
   3982  *
   3983  * Parameters:
   3984  *      unit             - (IN) unit number
   3985  *      info             - (IN) IPMC entry information
   3986  *      stat             - (IN) Type of the counter to retrieve
   3987  *                              I.e. ingress/egress byte/packet)
   3988  *      num_entries      - (IN) Number of counter Entries
   3989  *      counter_indexes  - (IN) Pointer to Counter indexes entries
   3990  *      counter_values   - (OUT) Pointer to counter values
   3991  *
   3992  * Return Value:
   3993  *      BCM_E_XXX
   3994  * Notes:
   3995  */
   3996 bcm_error_t
   3997 bcm_esw_ipmc_stat_counter_sync_get(int              unit,
   3998                                    bcm_ipmc_addr_t  *info,
   3999                                    bcm_ipmc_stat_t  stat,
   4000                                    uint32           num_entries,
   4001                                    uint32           *counter_indexes,
   4002                                    bcm_stat_value_t *counter_values)
   4003 {
   4004         return _bcm_esw_ipmc_stat_counter_get(unit, 1, info, stat, 
   4005                     num_entries, counter_indexes, counter_values);
   4006 }
   4007 
   4008 /*
   4009  * Function:
   4010  *      bcm_esw_ipmc_stat_counter_set
   4011  * Description:
   4012  *      Set counter statistic values for specific IPMC group
   4013  *
   4014  * Parameters:
   4015  *      unit             - (IN) unit number
   4016  *      info             - (IN) IPMC entry information
   4017  *      stat             - (IN) Type of the counter to retrieve
   4018  *                              I.e. ingress/egress byte/packet)
   4019  *      num_entries      - (IN) Number of counter Entries
   4020  *      counter_indexes  - (IN) Pointer to Counter indexes entries
   4021  *      counter_values   - (IN) Pointer to counter values
   4022  *
   4023  * Return Value:
   4024  *      BCM_E_XXX
   4025  * Notes:
   4026  */
   4027 bcm_error_t bcm_esw_ipmc_stat_counter_set(
   4028             int unit,
   4029             bcm_ipmc_addr_t *info,
   4030             bcm_ipmc_stat_t stat,
   4031             uint32 num_entries,
   4032             uint32 *counter_indexes,
   4033             bcm_stat_value_t *counter_values)
   4034 {
   4035 #if defined(BCM_TRIDENT2_SUPPORT)
   4036     if (SOC_IS_TD2_TT2(unit)) {
   4037         return _bcm_td2_ipmc_stat_counter_set(unit, info, stat,
   4038                     num_entries, counter_indexes, counter_values);
   4039     } else
   4040 #endif
   4041     {
   4042         return BCM_E_UNAVAIL;
   4043     }
   4044 }
   4045 
   4046 /*
   4047  * Function:
   4048  *      bcm_esw_ipmc_stat_multi_get
   4049  *
   4050  * Description:
   4051  *  Get Multiple IPMC entry counter value for specified IPMC entry index for multiple stat
   4052  *  types
   4053  *
   4054  * Parameters:
   4055  *      unit             - (IN) unit number
   4056  *      info			 - (IN) IPMC entry information
   4057  *      nstat            - (IN) Number of elements in stat array
   4058  *      stat_arr         - (IN) Collected statistics descriptors array
   4059  *      value_arr        - (OUT) Collected counters values
   4060  *
   4061  * Return Value:
   4062  *      BCM_E_XXX
   4063  * Notes:
   4064  */
   4065 
   4066     
   4067  bcm_error_t  bcm_esw_ipmc_stat_multi_get(
   4068                             int                 unit, 
   4069                             bcm_ipmc_addr_t	    *info,
   4070                             int                 nstat, 
   4071                             bcm_ipmc_stat_t *stat_arr,
   4072                             uint64              *value_arr)
   4073 {
   4074 #if defined(BCM_TRIDENT2_SUPPORT)
   4075     if (SOC_IS_TD2_TT2(unit)) {    
   4076         return _bcm_td2_ipmc_stat_multi_get (
   4077                     unit, info, nstat, stat_arr, value_arr);
   4078     } else
   4079 #endif
   4080     {
   4081         return BCM_E_UNAVAIL;
   4082     }
   4083 }
   4084 
   4085 /*
   4086  * Function:
   4087  *      bcm_esw_ipmc_stat_multi_get32
   4088  *
   4089  * Description:
   4090  *  Get 32bit IPMC entry counter value for specified IPMC entry index for multiple stat
   4091  *  types
   4092  *
   4093  * Parameters:
   4094  *      unit             - (IN) unit number
   4095  *      info		 	 - (IN) IPMC entry information
   4096  *      nstat            - (IN) Number of elements in stat array
   4097  *      stat_arr         - (IN) Collected statistics descriptors array
   4098  *      value_arr        - (OUT) Collected counters values
   4099  *
   4100  * Return Value:
   4101  *      BCM_E_XXX
   4102  * Notes:
   4103  */
   4104  bcm_error_t  bcm_esw_ipmc_stat_multi_get32(
   4105                             int                 unit, 
   4106                             bcm_ipmc_addr_t	    *info,
   4107                             int                 nstat, 
   4108                             bcm_ipmc_stat_t *stat_arr,
   4109                             uint32              *value_arr)
   4110 {
   4111 #if defined(BCM_TRIDENT2_SUPPORT)
   4112     if (SOC_IS_TD2_TT2(unit)) {    
   4113         return _bcm_td2_ipmc_stat_multi_get32 (
   4114                      unit, info, nstat, stat_arr, value_arr);
   4115     } else
   4116 #endif
   4117     {
   4118         return BCM_E_UNAVAIL;
   4119     }
   4120 }
   4121 
   4122 /*
   4123  * Function:
   4124  *     bcm_esw_ipmc_stat_multi_set
   4125  *
   4126  * Description:
   4127  *  Set IPMC entry counter value for specified IPMC entry index for multiple stat
   4128  *  types
   4129  *
   4130  * Parameters:
   4131  *      unit             - (IN) unit number
   4132  *      info			 - (IN) IPMC entry information
   4133  *      stat             - (IN) IPMC entry counter stat types
   4134  *      num_entries      - (IN) Number of counter Entries
   4135  *      counter_indexes  - (IN) Pointer to Counter indexes entries
   4136  *      counter_values   - (OUT) Pointer to counter values
   4137  *
   4138  * Return Value:
   4139  *      BCM_E_XXX
   4140  * Notes:
   4141  */
   4142 bcm_error_t  bcm_esw_ipmc_stat_multi_set(
   4143                             int                 unit, 
   4144                             bcm_ipmc_addr_t	    *info,
   4145                             int                 nstat, 
   4146                             bcm_ipmc_stat_t *stat_arr,
   4147                             uint64              *value_arr)
   4148 {
   4149 #if defined(BCM_TRIDENT2_SUPPORT)
   4150     if (SOC_IS_TD2_TT2(unit)) {    
   4151         return _bcm_td2_ipmc_stat_multi_set (
   4152                     unit, info, nstat, stat_arr, value_arr);
   4153     } else
   4154 #endif
   4155     {
   4156         return BCM_E_UNAVAIL;
   4157     }
   4158 }
   4159 
   4160 /*
   4161  * Function:
   4162  *      bcm_esw_ipmc_stat_multi_set32
   4163  *
   4164  * Description:
   4165  *  Set 32bit IPMC entry counter value for specified IPMC entry index for multiple stat
   4166  *  types
   4167  *
   4168  * Parameters:
   4169  *      unit             - (IN) unit number
   4170  *      info			 - (IN) IPMC entry information
   4171  *      stat             - (IN) IPMC entry counter stat types
   4172  *      num_entries      - (IN) Number of counter Entries
   4173  *      counter_indexes  - (IN) Pointer to Counter indexes entries
   4174  *      counter_values   - (OUT) Pointer to counter values
   4175  *
   4176  * Return Value:
   4177  *      BCM_E_XXX
   4178  * Notes:
   4179  */
   4180 
   4181  bcm_error_t  bcm_esw_ipmc_stat_multi_set32(
   4182                             int                 unit, 
   4183                             bcm_ipmc_addr_t	    *info,
   4184                             int                 nstat, 
   4185                             bcm_ipmc_stat_t *stat_arr,
   4186                             uint32              *value_arr)
   4187 {
   4188 #if defined(BCM_TRIDENT2_SUPPORT)
   4189     if (SOC_IS_TD2_TT2(unit)) {    
   4190         return _bcm_td2_ipmc_stat_multi_set32 (
   4191                     unit, info, nstat, stat_arr, value_arr);
   4192     } else
   4193 #endif
   4194     {
   4195         return BCM_E_UNAVAIL;
   4196     }
   4197 }
   4198 
   4199 /*
   4200  * Function:
   4201  *      bcm_esw_ipmc_stat_id_get
   4202  * Description:
   4203  *      Get stat counter id associated with given IPMC group
   4204  *
   4205  * Parameters:
   4206  *      unit             - (IN) unit number
   4207  *      info             - (IN) IPMC entry information
   4208  *      stat             - (IN) Type of the counter to retrieve
   4209  *                              I.e. ingress/egress byte/packet)
   4210  *      Stat_counter_id  - (OUT) Stat Counter ID
   4211  * Return Value:
   4212  *      BCM_E_XXX
   4213  * Notes:
   4214  */
   4215 bcm_error_t bcm_esw_ipmc_stat_id_get(
   4216             int unit,
   4217             bcm_ipmc_addr_t *info,
   4218             bcm_ipmc_stat_t stat,
   4219             uint32 *stat_counter_id)
   4220 {
   4221 #if defined(BCM_TRIDENT2_SUPPORT)
   4222     if (SOC_IS_TD2_TT2(unit)) { 
   4223         return _bcm_td2_ipmc_stat_id_get(unit, info, stat, stat_counter_id);
   4224     } else
   4225 #endif
   4226     {
   4227         return BCM_E_UNAVAIL;
   4228     }
   4229 }
   4230 
   4231 #else /* INCLUDE_L3 */
   4232 int _bcm_esw_ipmc_not_empty;
   4233 #endif	/* INCLUDE_L3 */