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 */