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

multicast.c (11748B)


      1 /*
      2  * 
      3  * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file.
      4  * 
      5  * Copyright 2007-2019 Broadcom Inc. All rights reserved.
      6  *
      7  * File:    multicast.c
      8  * Purpose: Manages multicast functions
      9  */
     10 
     11 #include <soc/defs.h>
     12 #include <sal/core/libc.h>
     13 
     14 #if defined(BCM_TRIUMPH2_SUPPORT) && defined(INCLUDE_L3)
     15 
     16 #include <soc/drv.h>
     17 #include <soc/mem.h>
     18 #include <soc/util.h>
     19 #include <soc/debug.h>
     20 #include <soc/triumph.h>
     21 
     22 #include <bcm/error.h>
     23 
     24 #include <bcm_int/esw/mbcm.h>
     25 #include <bcm_int/esw/l3.h>
     26 #include <bcm_int/esw/firebolt.h>
     27 #include <bcm_int/esw/virtual.h>
     28 #include <bcm_int/esw/xgs3.h>
     29 #include <bcm_int/common/multicast.h>
     30 #include <bcm_int/esw/multicast.h>
     31 #include <bcm_int/esw/triumph.h>
     32 #include <bcm_int/esw/trx.h>
     33 #include <bcm_int/esw/triumph2.h>
     34 #include <bcm_int/esw/stack.h>
     35 #ifdef BCM_TRIDENT_SUPPORT
     36 #include <bcm_int/esw/trill.h>
     37 #include <bcm_int/esw/trident.h>
     38 #endif /* BCM_TRIDENT_SUPPORT */
     39 #include <bcm_int/esw_dispatch.h>
     40 #include <bcm_int/api_xlate_port.h>
     41 
     42 #if defined(BCM_TRIDENT_SUPPORT)
     43 /*
     44  * Function:
     45  *      bcm_td_multicast_trill_group_update
     46  * Purpose:
     47  *      Update TRILL Tree ID of L3-IPMC group
     48  * Parameters:
     49  *      unit         - (IN) Unit number.
     50  *      ipmc_index (IN)
     51  *      trill_tree_id  (IN)
     52  * Returns:
     53  *      BCM_E_XXX
     54  * Notes:
     55  */
     56 int
     57 bcm_td_multicast_trill_group_update(int unit, int ipmc_index, uint8 trill_tree_id)
     58 {
     59     int rv = BCM_E_NONE;
     60     egr_ipmc_entry_t egr_ipmc;
     61 
     62     soc_mem_lock(unit, EGR_IPMCm);
     63 
     64     rv = READ_EGR_IPMCm(unit, MEM_BLOCK_ALL, ipmc_index, &egr_ipmc);
     65     if (rv < 0 ) {
     66          soc_mem_unlock(unit, EGR_IPMCm);       
     67          return rv;
     68     }
     69 
     70     if(soc_mem_field_valid(unit, EGR_IPMCm, TRILL_TREE_PROFILE_PTRf)) {
     71          soc_EGR_IPMCm_field32_set(unit, &egr_ipmc, 
     72               TRILL_TREE_PROFILE_PTRf, trill_tree_id);
     73     }
     74     if(soc_mem_field_valid(unit, EGR_IPMCm, IPMC_GROUP_TYPEf)) {
     75          soc_EGR_IPMCm_field32_set(unit, &egr_ipmc, IPMC_GROUP_TYPEf, 0x1);
     76     }
     77 
     78     rv =  WRITE_EGR_IPMCm(unit, MEM_BLOCK_ALL, 
     79               ipmc_index, &egr_ipmc);
     80     soc_mem_unlock(unit, EGR_IPMCm);
     81 
     82     return rv;
     83 }
     84 
     85 /*
     86  * Function:
     87  *      bcm_td_multicast_trill_group_get
     88  * Purpose:
     89  *      Get L3-IPMC group for matching Trill Tree_id
     90  * Parameters:
     91  *      unit         - (IN) Unit number.
     92  *      ipmc_index  - (IN)
     93  *      trill_tree_id  - (OUT)
     94  * Returns:
     95  *      BCM_E_XXX
     96  * Notes:
     97  */
     98 int
     99 bcm_td_multicast_trill_group_get(int unit, int ipmc_index, uint8 *trill_tree_id)
    100 {
    101     int rv = BCM_E_NONE;
    102     egr_ipmc_entry_t egr_ipmc;
    103 
    104     rv = READ_EGR_IPMCm(unit, MEM_BLOCK_ALL, ipmc_index, &egr_ipmc);
    105     if (rv < 0 ) {
    106          return rv;
    107     }
    108 
    109     if(soc_mem_field_valid(unit, EGR_IPMCm, IPMC_GROUP_TYPEf)) {
    110         if (soc_EGR_IPMCm_field32_get(unit, &egr_ipmc, IPMC_GROUP_TYPEf)) {
    111             if(soc_mem_field_valid(unit, EGR_IPMCm, TRILL_TREE_PROFILE_PTRf)) {
    112                 *trill_tree_id = soc_EGR_IPMCm_field32_get(unit, &egr_ipmc, 
    113                                                    TRILL_TREE_PROFILE_PTRf);
    114                 return BCM_E_NONE;
    115             }
    116         }
    117     }
    118     return BCM_E_NOT_FOUND;
    119 }
    120 #endif /* BCM_TRIDENT_SUPPORT */
    121 
    122 /*
    123  * Function:
    124  *      bcm_multicast_vpls_encap_get
    125  * Purpose:
    126  *      Get the Encap ID for a MPLS port.
    127  * Parameters:
    128  *      unit         - (IN) Unit number.
    129  *      group        - (IN) Multicast group ID.
    130  *      port         - (IN) Physical port.
    131  *      mpls_port_id - (IN) MPLS port ID.
    132  *      encap_id     - (OUT) Encap ID.
    133  * Returns:
    134  *      BCM_E_XXX
    135  * Notes:
    136  */
    137 int
    138 bcm_tr2_multicast_vpls_encap_get(int unit, bcm_multicast_t group, bcm_gport_t port,
    139                                 bcm_gport_t mpls_port_id, bcm_if_t *encap_id)
    140 {
    141     BCM_IF_ERROR_RETURN(
    142         bcm_tr_multicast_vpls_encap_get(unit, group, port, 
    143                                         mpls_port_id, encap_id));
    144     /* Triumph2 is able to do multicast replications over next hops and interfaces */
    145     *encap_id += BCM_XGS3_DVP_EGRESS_IDX_MIN(unit);
    146     return BCM_E_NONE;
    147 }
    148 
    149 /*
    150  * Function:
    151  *      bcm_multicast_mim_encap_get
    152  * Purpose:
    153  *      Get the Encap ID for a MiM port.
    154  * Parameters:
    155  *      unit         - (IN) Unit number.
    156  *      group        - (IN) Multicast group ID.
    157  *      port         - (IN) Physical port.
    158  *      mim_port_id -  (IN) MIM port ID.
    159  *      encap_id     - (OUT) Encap ID.
    160  * Returns:
    161  *      BCM_E_XXX
    162  * Notes:
    163  */
    164 int
    165 bcm_tr2_multicast_mim_encap_get(int unit, bcm_multicast_t group, bcm_gport_t port,
    166                                 bcm_gport_t mim_port_id, bcm_if_t *encap_id)
    167 {
    168     int vp;
    169     ing_dvp_table_entry_t dvp;
    170 
    171     if (!BCM_GPORT_IS_MIM_PORT(mim_port_id)) {
    172         return BCM_E_PARAM;
    173     }
    174     vp = BCM_GPORT_MIM_PORT_ID_GET(mim_port_id); 
    175     if (vp >= soc_mem_index_count(unit, SOURCE_VPm)) {
    176         return BCM_E_PARAM;
    177     }
    178     if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeMim)) {
    179             return BCM_E_PARAM;
    180     }
    181     BCM_IF_ERROR_RETURN (READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp, &dvp));
    182 
    183     /* Next-hop index is used for multicast replication */
    184     *encap_id = (bcm_if_t) soc_ING_DVP_TABLEm_field32_get(unit, &dvp, NEXT_HOP_INDEXf);
    185     if (!SOC_IS_ENDURO(unit)) {
    186         *encap_id += BCM_XGS3_DVP_EGRESS_IDX_MIN(unit);
    187     }
    188     return BCM_E_NONE;
    189 }
    190 
    191 /*
    192  * Function:
    193  *      bcm_multicast_wlan_encap_get
    194  * Purpose:
    195  *      Get the Encap ID for a WLAN port.
    196  * Parameters:
    197  *      unit         - (IN) Unit number.
    198  *      group        - (IN) Multicast group ID.
    199  *      port         - (IN) Physical port.
    200  *      wlan_port_id - (IN) WLAN port ID.
    201  *      encap_id     - (OUT) Encap ID.
    202  * Returns:
    203  *      BCM_E_XXX
    204  * Notes:
    205  */
    206 int
    207 bcm_tr2_multicast_wlan_encap_get(int unit, bcm_multicast_t group, bcm_gport_t port,
    208                                 bcm_gport_t wlan_port_id, bcm_if_t *encap_id)
    209 {
    210     int vp;
    211     ing_dvp_table_entry_t dvp;
    212     soc_mem_t wlan_svp_mem;
    213 
    214 #if defined(BCM_TRIUMPH3_SUPPORT)
    215     if (SOC_IS_TRIUMPH3(unit)) {
    216         wlan_svp_mem = AXP_WRX_SVP_ASSIGNMENTm;
    217     } else
    218 #endif /* BCM_TRIUMPH3_SUPPORT */
    219     {
    220         wlan_svp_mem = WLAN_SVP_TABLEm;
    221     }
    222 
    223     if (!BCM_GPORT_IS_WLAN_PORT(wlan_port_id)) {
    224         return BCM_E_PARAM;
    225     }
    226     vp = BCM_GPORT_WLAN_PORT_ID_GET(wlan_port_id); 
    227     if (vp >= soc_mem_index_count(unit, wlan_svp_mem)) {
    228         return BCM_E_PARAM;
    229     }
    230     if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeWlan)) {
    231             return BCM_E_PARAM;
    232     }
    233     BCM_IF_ERROR_RETURN (READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp, &dvp));
    234 
    235     /* Next-hop index is used for multicast replication */
    236     *encap_id = (bcm_if_t) soc_ING_DVP_TABLEm_field32_get(unit, &dvp, NEXT_HOP_INDEXf);
    237     *encap_id += BCM_XGS3_DVP_EGRESS_IDX_MIN(unit);
    238     return BCM_E_NONE;
    239 }
    240 
    241 /*
    242  * Function:
    243  *      bcm_multicast_subport_encap_get
    244  * Purpose:
    245  *      Get the Encap ID for a subport.
    246  * Parameters:
    247  *      unit      - (IN) Unit number.
    248  *      group     - (IN) Multicast group ID.
    249  *      port      - (IN) Physical port.
    250  *      subport   - (IN) Subport ID.
    251  *      encap_id  - (OUT) Encap ID.
    252  * Returns:
    253  *      BCM_E_XXX
    254  * Notes:
    255  */
    256 int
    257 bcm_tr2_multicast_subport_encap_get(int unit, bcm_multicast_t group, 
    258                                     bcm_gport_t port,
    259                                     bcm_gport_t subport, bcm_if_t *encap_id)
    260 {
    261     int vp, l3_idx,rv;
    262     ing_dvp_table_entry_t dvp;
    263     egr_l3_intf_entry_t l3_intf;
    264 
    265     if (!BCM_GPORT_IS_SUBPORT_PORT(subport)) {
    266         return BCM_E_PARAM;
    267     }
    268 
    269     l3_idx = BCM_GPORT_SUBPORT_PORT_GET(subport) & 0xfff;
    270     if (l3_idx >= BCM_XGS3_L3_IF_TBL_SIZE(unit)) { 
    271         return (BCM_E_PARAM);
    272     }
    273 
    274     rv = soc_mem_read(unit, EGR_L3_INTFm, MEM_BLOCK_ALL, l3_idx, &l3_intf);
    275     BCM_IF_ERROR_RETURN(rv);
    276 
    277     vp = soc_mem_field32_get(unit, EGR_L3_INTFm, &l3_intf, IVIDf);
    278     if (vp >= soc_mem_index_count(unit, SOURCE_VPm)) {
    279         return BCM_E_PARAM;
    280     }
    281     if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeSubport)) {
    282             return BCM_E_PARAM;
    283     }
    284     BCM_IF_ERROR_RETURN (READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp, &dvp));
    285 
    286     /* Next-hop index is used for multicast replication */
    287     *encap_id = (bcm_if_t) soc_ING_DVP_TABLEm_field32_get(unit, &dvp, NEXT_HOP_INDEXf);
    288     if (!SOC_IS_ENDURO(unit)) {
    289         *encap_id += BCM_XGS3_DVP_EGRESS_IDX_MIN(unit);
    290     }
    291     return BCM_E_NONE;
    292 }
    293 
    294 /*
    295  * Function:
    296  *      bcm_tr2_ipmc_remap_set
    297  * Purpose:
    298  *      Set a multicast binding.
    299  * Parameters:
    300  *      unit      - (IN) Unit number.
    301  *      mc_from   - (IN) Multicast index from
    302  *      mc_to     - (IN) Multicast index to
    303  * Returns:
    304  *      BCM_E_XXX
    305  * Notes:
    306  *      Mulitcast types are already validated as appropriate
    307  *      for IPMC
    308  */
    309 int
    310 bcm_tr2_ipmc_remap_set(int unit, bcm_multicast_t mc_from, int mc_to)
    311 {
    312     int rv = BCM_E_UNAVAIL;
    313     int ipmc_from;
    314     int ipmc_to;
    315     int ipmc_idx_min;
    316     int ipmc_idx_max;
    317     bcm_multicast_t mcgroup;
    318     ipmc_remap_entry_t l3_ipmc_remap;
    319 
    320     ipmc_from = _BCM_MULTICAST_ID_GET(mc_from);
    321     ipmc_to = _BCM_MULTICAST_ID_GET(mc_to);
    322     ipmc_idx_min = soc_mem_index_min(unit, L3_IPMC_REMAPm);
    323     ipmc_idx_max = soc_mem_index_max(unit, L3_IPMC_REMAPm);
    324 
    325     /* Table index sanity check. */
    326     if ((ipmc_from < ipmc_idx_min) || (ipmc_from > ipmc_idx_max)) {
    327         return BCM_E_PARAM;
    328     }
    329 
    330     if ((ipmc_to < ipmc_idx_min) || (ipmc_to > ipmc_idx_max)) {
    331         return BCM_E_PARAM;
    332     }
    333 
    334     /* Sanity check the converted IPMC index to see if it really
    335        corresponds to a valid multicast group. Don't check if the
    336        multicast groups in and out are identical because it's possible
    337        that there's some interesting "cross group" programming going
    338        on. */
    339     rv = _bcm_tr_multicast_ipmc_group_type_get(unit, ipmc_from, &mcgroup);
    340     BCM_IF_ERROR_RETURN(rv);
    341 
    342     rv = _bcm_tr_multicast_ipmc_group_type_get(unit, ipmc_to, &mcgroup);
    343     BCM_IF_ERROR_RETURN(rv);
    344 
    345     sal_memset(&l3_ipmc_remap, 0, sizeof(l3_ipmc_remap));
    346 
    347     soc_L3_IPMC_REMAPm_field32_set(unit, &l3_ipmc_remap, L3MC_INDEXf, ipmc_to);
    348 
    349     rv =  WRITE_L3_IPMC_REMAPm(unit, MEM_BLOCK_ALL, ipmc_from, &l3_ipmc_remap);
    350 
    351     return rv;
    352 }
    353 
    354 /*
    355  * Function:
    356  *      bcm_tr2_ipmc_remap_get
    357  * Purpose:
    358  *      Get a multicast binding.
    359  * Parameters:
    360  *      unit      - (IN) Unit number.
    361  *      mc_from   - (IN) Multicast group from.
    362  *      mc_to     - (OUT) Pointer to multicast group to.
    363  * Returns:
    364  *      BCM_E_XXX
    365  * Notes:
    366  *      Mulitcast types are already validated as appropriate
    367  *      for IPMC
    368  */
    369 int
    370 bcm_tr2_ipmc_remap_get(int unit, bcm_multicast_t mc_from, int *mc_to)
    371 {
    372     int rv = BCM_E_UNAVAIL;
    373     int ipmc_from;
    374     int ipmc_to;
    375     bcm_multicast_t mcgroup;
    376     ipmc_remap_entry_t l3_ipmc_remap;
    377 
    378     ipmc_from = _BCM_MULTICAST_ID_GET(mc_from);
    379 
    380     /* Table index sanity check. */
    381     if ((ipmc_from < soc_mem_index_min(unit, L3_IPMC_REMAPm)) ||
    382         (ipmc_from > soc_mem_index_max(unit, L3_IPMC_REMAPm))) {
    383         return BCM_E_PARAM;
    384     }
    385 
    386     /* validate that the multicast group is valid */
    387     rv = _bcm_tr_multicast_ipmc_group_type_get(unit, ipmc_from, &mcgroup);
    388     BCM_IF_ERROR_RETURN(rv);
    389 
    390     sal_memset(&l3_ipmc_remap, 0, sizeof(l3_ipmc_remap));
    391 
    392     rv =  READ_L3_IPMC_REMAPm(unit, MEM_BLOCK_ALL, ipmc_from, &l3_ipmc_remap);
    393 
    394     if (SOC_SUCCESS(rv)) {
    395         ipmc_to =
    396             soc_L3_IPMC_REMAPm_field32_get(unit, &l3_ipmc_remap, L3MC_INDEXf);
    397         rv = _bcm_tr_multicast_ipmc_group_type_get(unit, ipmc_to, &mcgroup);
    398         if (BCM_SUCCESS(rv)) {
    399             *mc_to = (int)mcgroup;
    400         }
    401     }
    402 
    403     return rv;
    404 }
    405 
    406 #else  /* INCLUDE_L3 && BCM_TRIUMPH2_SUPPORT */
    407 int bcm_esw_triumph2_multicast_not_empty;
    408 #endif /* INCLUDE_L3 && BCM_TRIUMPH2_SUPPORT */