ipmc.c (207303B)
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: ipmc.c 8 * Purpose: Tracks and manages IPMC tables. 9 */ 10 11 #ifdef INCLUDE_L3 12 #include <shared/bsl.h> 13 #include <soc/l3x.h> 14 #if defined(BCM_BRADLEY_SUPPORT) 15 #include <soc/bradley.h> 16 #endif /* BCM_BRADLEY_SUPPORT */ 17 18 #include <bcm/error.h> 19 #include <bcm/stack.h> 20 21 #include <bcm_int/esw/ipmc.h> 22 #include <bcm_int/esw/mbcm.h> 23 #include <bcm_int/esw/firebolt.h> 24 #include <bcm_int/esw/stack.h> 25 #include <bcm_int/common/multicast.h> 26 #include <bcm_int/esw/multicast.h> 27 #include <bcm_int/esw_dispatch.h> 28 #if defined(BCM_BRADLEY_SUPPORT) 29 #include <bcm_int/esw/bradley.h> 30 #endif /* BCM_BRADLEY_SUPPORT */ 31 32 #include <bcm_int/esw_dispatch.h> 33 34 #define REPL_PORT_CHECK(unit, port) \ 35 if (!IS_PORT(unit, port)) { return BCM_E_PARAM; } 36 37 #if defined(BCM_FIREBOLT_SUPPORT) 38 typedef struct _fb_repl_port_info_s { 39 uint32 *vlan_count; /* # VLANs the port repl to */ 40 uint32 emc_val; /* EGRMETERINGCONFIG value */ 41 } _fb_repl_port_info_t; 42 43 typedef struct _fb_repl_info_s { 44 int ipmc_size; 45 uint32 intf_num; /* Number of interfaces on this device */ 46 uint16 ipmc_vlan_total; /* Keep track of total and */ 47 uint32 *bitmap_entries_used; /* free entries of IPMC_VLAN table */ 48 _bcm_repl_list_info_t *repl_list_info; 49 _fb_repl_port_info_t *port_info[SOC_MAX_NUM_PORTS]; 50 51 /* Per port replication info */ 52 int *l3_intf_to_l3_nh_ipmc; /* L3_NH array : for L3_INTF based IPMC repl */ 53 int *l3_nh_to_l3_intf_ipmc; 54 } _fb_repl_info_t; 55 56 static _fb_repl_info_t *_fb_repl_info[BCM_MAX_NUM_UNITS]; 57 58 #define IPMC_REPL_LOCK(_u_) \ 59 { \ 60 soc_mem_lock(_u_, MMU_IPMC_VLAN_TBLm); \ 61 } 62 #define IPMC_REPL_UNLOCK(_u_) \ 63 { \ 64 soc_mem_unlock(_u_, MMU_IPMC_VLAN_TBLm); \ 65 } 66 #define IPMC_REPL_ID(_u_, _id_) \ 67 if ((_id_ < 0) || (_id_ >= _fb_repl_info[_u_]->ipmc_size)) \ 68 { return BCM_E_PARAM; } 69 #define IPMC_REPL_INIT(unit) \ 70 if (_fb_repl_info[unit] == NULL) { return BCM_E_INIT; } 71 #define IPMC_REPL_TOTAL(_u_) \ 72 _fb_repl_info[_u_]->ipmc_vlan_total 73 #define IPMC_REPL_GROUP_NUM(_u_) \ 74 _fb_repl_info[_u_]->ipmc_size 75 #define IPMC_REPL_INTF_TOTAL(_u_) \ 76 _fb_repl_info[_u_]->intf_num 77 #define IPMC_REPL_VE_USED_GET(_u_, _i_) \ 78 SHR_BITGET(_fb_repl_info[_u_]->bitmap_entries_used, _i_) 79 #define IPMC_REPL_VE_USED_SET(_u_, _i_) \ 80 SHR_BITSET(_fb_repl_info[_u_]->bitmap_entries_used, _i_) 81 #define IPMC_REPL_VE_USED_CLR(_u_, _i_) \ 82 SHR_BITCLR(_fb_repl_info[_u_]->bitmap_entries_used, _i_) 83 84 #define IPMC_REPL_LIST_INFO(_u_) \ 85 _fb_repl_info[_u_]->repl_list_info 86 #define IPMC_REPL_PORT_INFO(_u_, _p_) \ 87 _fb_repl_info[_u_]->port_info[_p_] 88 #define IPMC_REPL_PORT_VLAN_COUNT(_u_, _p_, _ipmc_id_) \ 89 _fb_repl_info[_u_]->port_info[_p_]->vlan_count[_ipmc_id_] 90 91 #define IPMC_REPL_L3_INTF_TO_L3_NH_IPMC(_u_, _intf_) \ 92 _fb_repl_info[(_u_)]->l3_intf_to_l3_nh_ipmc[(_intf_)] 93 94 #define IPMC_REPL_L3_NH_TO_L3_INTF_IPMC(_u_, nh_id) \ 95 _fb_repl_info[(_u_)]->l3_nh_to_l3_intf_ipmc[(nh_id)] 96 97 #define REPL_NH_INDEX_UNALLOCATED (-1) 98 #define REPL_L3_INTF_UNALLOCATED (-1) 99 100 101 typedef struct _rep_regs_s { 102 soc_field_t port_ptr; 103 soc_field_t last_ptr; 104 soc_mem_t mem; 105 }_rep_regs_t; 106 107 108 _rep_regs_t fb_rep_regs[28] = { {PORT0_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL0m}, 109 {PORT1_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL0m}, 110 {PORT2_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL0m}, 111 {PORT3_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL0m}, 112 {PORT4_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL0m}, 113 {PORT5_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL0m}, 114 {PORT6_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL1m}, 115 {PORT7_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL1m}, 116 {PORT8_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL1m}, 117 {PORT9_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL1m}, 118 {PORT10_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL1m}, 119 {PORT11_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL1m}, 120 {PORT12_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL2m}, 121 {PORT13_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL2m}, 122 {PORT14_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL2m}, 123 {PORT15_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL2m}, 124 {PORT16_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL2m}, 125 {PORT17_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL2m}, 126 {PORT18_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL3m}, 127 {PORT19_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL3m}, 128 {PORT20_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL3m}, 129 {PORT21_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL3m}, 130 {PORT22_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL3m}, 131 {PORT23_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL3m}, 132 {PORT24_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL4m}, 133 {PORT25_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL5m}, 134 {PORT26_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL6m}, 135 {PORT27_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL7m} 136 }; 137 #if defined(BCM_HB_GW_SUPPORT) 138 _rep_regs_t hbgw_rep_regs[20] = { {PORT0_1STPTRf, PORT0_LASTf, MMU_IPMC_GROUP_TBL0m}, 139 {PORT1_1STPTRf, PORT1_LASTf, MMU_IPMC_GROUP_TBL0m}, 140 {PORT2_1STPTRf, PORT2_LASTf, MMU_IPMC_GROUP_TBL0m}, 141 {PORT3_1STPTRf, PORT3_LASTf, MMU_IPMC_GROUP_TBL0m}, 142 {PORT4_1STPTRf, PORT4_LASTf, MMU_IPMC_GROUP_TBL0m}, 143 {PORT5_1STPTRf, PORT5_LASTf, MMU_IPMC_GROUP_TBL1m}, 144 {PORT6_1STPTRf, PORT6_LASTf, MMU_IPMC_GROUP_TBL1m}, 145 {PORT7_1STPTRf, PORT7_LASTf, MMU_IPMC_GROUP_TBL1m}, 146 {PORT8_1STPTRf, PORT8_LASTf, MMU_IPMC_GROUP_TBL1m}, 147 {PORT9_1STPTRf, PORT9_LASTf, MMU_IPMC_GROUP_TBL1m}, 148 {PORT10_1STPTRf, PORT10_LASTf, MMU_IPMC_GROUP_TBL2m}, 149 {PORT11_1STPTRf, PORT11_LASTf, MMU_IPMC_GROUP_TBL2m}, 150 {PORT12_1STPTRf, PORT12_LASTf, MMU_IPMC_GROUP_TBL2m}, 151 {PORT13_1STPTRf, PORT13_LASTf, MMU_IPMC_GROUP_TBL2m}, 152 {PORT14_1STPTRf, PORT14_LASTf, MMU_IPMC_GROUP_TBL2m}, 153 {PORT15_1STPTRf, PORT15_LASTf, MMU_IPMC_GROUP_TBL3m}, 154 {PORT16_1STPTRf, PORT16_LASTf, MMU_IPMC_GROUP_TBL3m}, 155 {PORT17_1STPTRf, PORT17_LASTf, MMU_IPMC_GROUP_TBL3m}, 156 {PORT18_1STPTRf, PORT18_LASTf, MMU_IPMC_GROUP_TBL3m}, 157 {PORT19_1STPTRf, PORT19_LASTf, MMU_IPMC_GROUP_TBL3m} 158 }; 159 #endif 160 #if defined (BCM_SCORPION_SUPPORT) 161 _rep_regs_t sco_rep_regs[29] = { {INVALIDf, INVALIDf, INVALIDm}, 162 {PORT1_1STPTRf, PORT1_LASTf, MMU_IPMC_GROUP_TBL0m}, 163 {PORT2_1STPTRf, PORT2_LASTf, MMU_IPMC_GROUP_TBL0m}, 164 {PORT3_1STPTRf, PORT3_LASTf, MMU_IPMC_GROUP_TBL0m}, 165 {PORT4_1STPTRf, PORT4_LASTf, MMU_IPMC_GROUP_TBL0m}, 166 {PORT5_1STPTRf, PORT5_LASTf, MMU_IPMC_GROUP_TBL1m}, 167 {PORT6_1STPTRf, PORT6_LASTf, MMU_IPMC_GROUP_TBL1m}, 168 {PORT7_1STPTRf, PORT7_LASTf, MMU_IPMC_GROUP_TBL1m}, 169 {PORT8_1STPTRf, PORT8_LASTf, MMU_IPMC_GROUP_TBL1m}, 170 {PORT9_1STPTRf, PORT9_LASTf, MMU_IPMC_GROUP_TBL2m}, 171 {PORT10_1STPTRf, PORT10_LASTf, MMU_IPMC_GROUP_TBL2m}, 172 {PORT11_1STPTRf, PORT11_LASTf, MMU_IPMC_GROUP_TBL2m}, 173 {PORT12_1STPTRf, PORT12_LASTf, MMU_IPMC_GROUP_TBL2m}, 174 {PORT13_1STPTRf, PORT13_LASTf, MMU_IPMC_GROUP_TBL3m}, 175 {PORT14_1STPTRf, PORT14_LASTf, MMU_IPMC_GROUP_TBL3m}, 176 {PORT15_1STPTRf, PORT15_LASTf, MMU_IPMC_GROUP_TBL3m}, 177 {PORT16_1STPTRf, PORT16_LASTf, MMU_IPMC_GROUP_TBL3m}, 178 {PORT17_1STPTRf, PORT17_LASTf, MMU_IPMC_GROUP_TBL4m}, 179 {PORT18_1STPTRf, PORT18_LASTf, MMU_IPMC_GROUP_TBL4m}, 180 {PORT19_1STPTRf, PORT19_LASTf, MMU_IPMC_GROUP_TBL4m}, 181 {PORT20_1STPTRf, PORT20_LASTf, MMU_IPMC_GROUP_TBL4m}, 182 {PORT21_1STPTRf, PORT21_LASTf, MMU_IPMC_GROUP_TBL5m}, 183 {PORT22_1STPTRf, PORT22_LASTf, MMU_IPMC_GROUP_TBL5m}, 184 {PORT23_1STPTRf, PORT23_LASTf, MMU_IPMC_GROUP_TBL5m}, 185 {PORT24_1STPTRf, PORT24_LASTf, MMU_IPMC_GROUP_TBL5m}, 186 {PORT25_1STPTRf, PORT25_LASTf, MMU_IPMC_GROUP_TBL6m}, 187 {PORT26_1STPTRf, PORT26_LASTf, MMU_IPMC_GROUP_TBL6m}, 188 {PORT27_1STPTRf, PORT27_LASTf, MMU_IPMC_GROUP_TBL6m}, 189 {PORT28_1STPTRf, PORT28_LASTf, MMU_IPMC_GROUP_TBL6m} 190 }; 191 #endif 192 #if defined(BCM_RAVEN_SUPPORT) 193 _rep_regs_t rvn_rep_regs[30] = { {INVALIDf, INVALIDf, INVALIDm}, 194 {PORT1_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL0m}, 195 {PORT2_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL0m}, 196 {PORT3_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL0m}, 197 {PORT4_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL0m}, 198 {PORT5_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL0m}, 199 {PORT6_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL0m}, 200 {PORT7_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL0m}, 201 {PORT8_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL0m}, 202 {PORT9_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL0m}, 203 {PORT10_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL0m}, 204 {PORT11_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL1m}, 205 {PORT12_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL1m}, 206 {PORT13_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL1m}, 207 {PORT14_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL1m}, 208 {PORT15_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL1m}, 209 {PORT16_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL1m}, 210 {PORT17_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL1m}, 211 {PORT18_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL1m}, 212 {PORT19_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL1m}, 213 {PORT20_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL1m}, 214 {PORT21_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL2m}, 215 {PORT22_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL2m}, 216 {PORT23_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL2m}, 217 {PORT24_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL2m}, 218 {PORT25_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL2m}, 219 {PORT26_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL2m}, 220 {PORT27_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL2m}, 221 {PORT28_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL2m}, 222 {PORT29_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL2m} 223 }; 224 #endif /* BCM_RAVEN_SUPPORT */ 225 #if defined(BCM_TRIUMPH_SUPPORT) 226 _rep_regs_t tr_rep_regs[55] = { {INVALIDf, INVALIDf, INVALIDm}, 227 {PORT1_1STPTRf, PORT1_LASTf, MMU_IPMC_GROUP_TBL0m}, 228 {PORT2_1STPTRf, PORT2_LASTf, MMU_IPMC_GROUP_TBL0m}, 229 {PORT3_1STPTRf, PORT3_LASTf, MMU_IPMC_GROUP_TBL0m}, 230 {PORT4_1STPTRf, PORT4_LASTf, MMU_IPMC_GROUP_TBL0m}, 231 {PORT5_1STPTRf, PORT5_LASTf, MMU_IPMC_GROUP_TBL0m}, 232 {PORT6_1STPTRf, PORT6_LASTf, MMU_IPMC_GROUP_TBL0m}, 233 {PORT7_1STPTRf, PORT7_LASTf, MMU_IPMC_GROUP_TBL1m}, 234 {PORT8_1STPTRf, PORT8_LASTf, MMU_IPMC_GROUP_TBL1m}, 235 {PORT9_1STPTRf, PORT9_LASTf, MMU_IPMC_GROUP_TBL1m}, 236 {PORT10_1STPTRf, PORT10_LASTf, MMU_IPMC_GROUP_TBL1m}, 237 {PORT11_1STPTRf, PORT11_LASTf, MMU_IPMC_GROUP_TBL1m}, 238 {PORT12_1STPTRf, PORT12_LASTf, MMU_IPMC_GROUP_TBL1m}, 239 {PORT13_1STPTRf, PORT13_LASTf, MMU_IPMC_GROUP_TBL2m}, 240 {PORT14_1STPTRf, PORT14_LASTf, MMU_IPMC_GROUP_TBL2m}, 241 {PORT15_1STPTRf, PORT15_LASTf, MMU_IPMC_GROUP_TBL2m}, 242 {PORT16_1STPTRf, PORT16_LASTf, MMU_IPMC_GROUP_TBL2m}, 243 {PORT17_1STPTRf, PORT17_LASTf, MMU_IPMC_GROUP_TBL2m}, 244 {PORT18_1STPTRf, PORT18_LASTf, MMU_IPMC_GROUP_TBL2m}, 245 {PORT19_1STPTRf, PORT19_LASTf, MMU_IPMC_GROUP_TBL3m}, 246 {PORT20_1STPTRf, PORT20_LASTf, MMU_IPMC_GROUP_TBL3m}, 247 {PORT21_1STPTRf, PORT21_LASTf, MMU_IPMC_GROUP_TBL3m}, 248 {PORT22_1STPTRf, PORT22_LASTf, MMU_IPMC_GROUP_TBL3m}, 249 {PORT23_1STPTRf, PORT23_LASTf, MMU_IPMC_GROUP_TBL3m}, 250 {PORT24_1STPTRf, PORT24_LASTf, MMU_IPMC_GROUP_TBL3m}, 251 {PORT25_1STPTRf, PORT25_LASTf, MMU_IPMC_GROUP_TBL4m}, 252 {PORT26_1STPTRf, PORT26_LASTf, MMU_IPMC_GROUP_TBL4m}, 253 {PORT27_1STPTRf, PORT27_LASTf, MMU_IPMC_GROUP_TBL4m}, 254 {PORT28_1STPTRf, PORT28_LASTf, MMU_IPMC_GROUP_TBL4m}, 255 {PORT29_1STPTRf, PORT29_LASTf, MMU_IPMC_GROUP_TBL4m}, 256 {PORT30_1STPTRf, PORT30_LASTf, MMU_IPMC_GROUP_TBL4m}, 257 {PORT31_1STPTRf, PORT31_LASTf, MMU_IPMC_GROUP_TBL5m}, 258 {PORT32_1STPTRf, PORT32_LASTf, MMU_IPMC_GROUP_TBL5m}, 259 {PORT33_1STPTRf, PORT33_LASTf, MMU_IPMC_GROUP_TBL5m}, 260 {PORT34_1STPTRf, PORT34_LASTf, MMU_IPMC_GROUP_TBL5m}, 261 {PORT35_1STPTRf, PORT35_LASTf, MMU_IPMC_GROUP_TBL5m}, 262 {PORT36_1STPTRf, PORT36_LASTf, MMU_IPMC_GROUP_TBL5m}, 263 {PORT37_1STPTRf, PORT37_LASTf, MMU_IPMC_GROUP_TBL6m}, 264 {PORT38_1STPTRf, PORT38_LASTf, MMU_IPMC_GROUP_TBL6m}, 265 {PORT39_1STPTRf, PORT39_LASTf, MMU_IPMC_GROUP_TBL6m}, 266 {PORT40_1STPTRf, PORT40_LASTf, MMU_IPMC_GROUP_TBL6m}, 267 {PORT41_1STPTRf, PORT41_LASTf, MMU_IPMC_GROUP_TBL6m}, 268 {PORT42_1STPTRf, PORT42_LASTf, MMU_IPMC_GROUP_TBL6m}, 269 {PORT43_1STPTRf, PORT43_LASTf, MMU_IPMC_GROUP_TBL7m}, 270 {PORT44_1STPTRf, PORT44_LASTf, MMU_IPMC_GROUP_TBL7m}, 271 {PORT45_1STPTRf, PORT45_LASTf, MMU_IPMC_GROUP_TBL7m}, 272 {PORT46_1STPTRf, PORT46_LASTf, MMU_IPMC_GROUP_TBL7m}, 273 {PORT47_1STPTRf, PORT47_LASTf, MMU_IPMC_GROUP_TBL7m}, 274 {PORT48_1STPTRf, PORT48_LASTf, MMU_IPMC_GROUP_TBL7m}, 275 {PORT49_1STPTRf, PORT49_LASTf, MMU_IPMC_GROUP_TBL8m}, 276 {PORT50_1STPTRf, PORT50_LASTf, MMU_IPMC_GROUP_TBL8m}, 277 {PORT51_1STPTRf, PORT51_LASTf, MMU_IPMC_GROUP_TBL8m}, 278 {PORT52_1STPTRf, PORT52_LASTf, MMU_IPMC_GROUP_TBL8m}, 279 {PORT53_1STPTRf, PORT53_LASTf, MMU_IPMC_GROUP_TBL8m}, 280 }; 281 #endif 282 283 #if defined(BCM_ENDURO_SUPPORT) 284 _rep_regs_t en_rep_regs[] = { {INVALIDf, INVALIDf, INVALIDm}, 285 {INVALIDf, INVALIDf, INVALIDm}, 286 {PORT2_1STPTRf, PORT2_LASTf, MMU_IPMC_GROUP_TBL0m}, 287 {PORT3_1STPTRf, PORT3_LASTf, MMU_IPMC_GROUP_TBL0m}, 288 {PORT4_1STPTRf, PORT4_LASTf, MMU_IPMC_GROUP_TBL0m}, 289 {PORT5_1STPTRf, PORT5_LASTf, MMU_IPMC_GROUP_TBL0m}, 290 {PORT6_1STPTRf, PORT6_LASTf, MMU_IPMC_GROUP_TBL0m}, 291 {PORT7_1STPTRf, PORT7_LASTf, MMU_IPMC_GROUP_TBL0m}, 292 {PORT8_1STPTRf, PORT8_LASTf, MMU_IPMC_GROUP_TBL0m}, 293 {PORT9_1STPTRf, PORT9_LASTf, MMU_IPMC_GROUP_TBL1m}, 294 {PORT10_1STPTRf, PORT10_LASTf, MMU_IPMC_GROUP_TBL1m}, 295 {PORT11_1STPTRf, PORT11_LASTf, MMU_IPMC_GROUP_TBL1m}, 296 {PORT12_1STPTRf, PORT12_LASTf, MMU_IPMC_GROUP_TBL1m}, 297 {PORT13_1STPTRf, PORT13_LASTf, MMU_IPMC_GROUP_TBL1m}, 298 {PORT14_1STPTRf, PORT14_LASTf, MMU_IPMC_GROUP_TBL1m}, 299 {PORT15_1STPTRf, PORT15_LASTf, MMU_IPMC_GROUP_TBL1m}, 300 {PORT16_1STPTRf, PORT16_LASTf, MMU_IPMC_GROUP_TBL2m}, 301 {PORT17_1STPTRf, PORT17_LASTf, MMU_IPMC_GROUP_TBL2m}, 302 {PORT18_1STPTRf, PORT18_LASTf, MMU_IPMC_GROUP_TBL2m}, 303 {PORT19_1STPTRf, PORT19_LASTf, MMU_IPMC_GROUP_TBL2m}, 304 {PORT20_1STPTRf, PORT20_LASTf, MMU_IPMC_GROUP_TBL2m}, 305 {PORT21_1STPTRf, PORT21_LASTf, MMU_IPMC_GROUP_TBL2m}, 306 {PORT22_1STPTRf, PORT22_LASTf, MMU_IPMC_GROUP_TBL2m}, 307 {PORT23_1STPTRf, PORT23_LASTf, MMU_IPMC_GROUP_TBL3m}, 308 {PORT24_1STPTRf, PORT24_LASTf, MMU_IPMC_GROUP_TBL3m}, 309 {PORT25_1STPTRf, PORT25_LASTf, MMU_IPMC_GROUP_TBL3m}, 310 {PORT26_1STPTRf, PORT26_LASTf, MMU_IPMC_GROUP_TBL3m}, 311 {PORT27_1STPTRf, PORT27_LASTf, MMU_IPMC_GROUP_TBL3m}, 312 {PORT28_1STPTRf, PORT28_LASTf, MMU_IPMC_GROUP_TBL3m}, 313 {PORT29_1STPTRf, PORT29_LASTf, MMU_IPMC_GROUP_TBL3m}, 314 }; 315 #endif 316 #if defined(BCM_HURRICANE_SUPPORT) || defined(BCM_HURRICANE2_SUPPORT) 317 _rep_regs_t hu_rep_regs[30] = { {INVALIDf, INVALIDf, INVALIDm}, 318 {INVALIDf, INVALIDf, MMU_IPMC_GROUP_TBL0m}, 319 {PORT2_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL0m}, 320 {PORT3_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL0m}, 321 {PORT4_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL0m}, 322 {PORT5_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL0m}, 323 {PORT6_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL0m}, 324 {PORT7_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL0m}, 325 {PORT8_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL0m}, 326 {PORT9_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL0m}, 327 {PORT10_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL0m}, 328 {PORT11_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL0m}, 329 {PORT12_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL0m}, 330 {PORT13_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL0m}, 331 {PORT14_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL1m}, 332 {PORT15_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL1m}, 333 {PORT16_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL1m}, 334 {PORT17_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL1m}, 335 {PORT18_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL1m}, 336 {PORT19_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL1m}, 337 {PORT20_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL1m}, 338 {PORT21_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL1m}, 339 {PORT22_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL1m}, 340 {PORT23_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL1m}, 341 {PORT24_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL1m}, 342 {PORT25_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL1m}, 343 {PORT26_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL2m}, 344 {PORT27_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL3m}, 345 {PORT28_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL4m}, 346 {PORT29_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL5m} 347 }; 348 #endif /* BCM_HURRICANE_SUPPORT */ 349 350 #if defined(BCM_GREYHOUND_SUPPORT) 351 _rep_regs_t gh_rep_regs[30] = { {INVALIDf, INVALIDf, INVALIDm}, 352 {INVALIDf, INVALIDf, INVALIDm}, 353 {PORT2_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL2m}, 354 {PORT3_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL3m}, 355 {PORT4_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL4m}, 356 {PORT5_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL5m}, 357 {PORT6_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL6m}, 358 {PORT7_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL7m}, 359 {PORT8_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL8m}, 360 {PORT9_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL9m}, 361 {PORT10_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL10m}, 362 {PORT11_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL11m}, 363 {PORT12_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL12m}, 364 {PORT13_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL13m}, 365 {PORT14_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL14m}, 366 {PORT15_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL15m}, 367 {PORT16_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL16m}, 368 {PORT17_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL17m}, 369 {PORT18_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL18m}, 370 {PORT19_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL19m}, 371 {PORT20_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL20m}, 372 {PORT21_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL21m}, 373 {PORT22_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL22m}, 374 {PORT23_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL23m}, 375 {PORT24_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL24m}, 376 {PORT25_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL25m}, 377 {PORT26_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL26m}, 378 {PORT27_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL27m}, 379 {PORT28_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL28m}, 380 {PORT29_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL29m} 381 }; 382 #endif /* BCM_GREYHOUND_SUPPORT */ 383 384 #if defined(BCM_HURRICANE3_SUPPORT) 385 _rep_regs_t hr3_rep_regs[32] = { {INVALIDf, INVALIDf, INVALIDm}, 386 {INVALIDf, INVALIDf, INVALIDm}, 387 {PORT2_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL2m}, 388 {PORT3_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL3m}, 389 {PORT4_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL4m}, 390 {PORT5_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL5m}, 391 {PORT6_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL6m}, 392 {PORT7_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL7m}, 393 {PORT8_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL8m}, 394 {PORT9_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL9m}, 395 {PORT10_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL10m}, 396 {PORT11_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL11m}, 397 {PORT12_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL12m}, 398 {PORT13_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL13m}, 399 {PORT14_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL14m}, 400 {PORT15_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL15m}, 401 {PORT16_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL16m}, 402 {PORT17_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL17m}, 403 {PORT18_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL18m}, 404 {PORT19_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL19m}, 405 {PORT20_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL20m}, 406 {PORT21_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL21m}, 407 {PORT22_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL22m}, 408 {PORT23_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL23m}, 409 {PORT24_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL24m}, 410 {PORT25_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL25m}, 411 {PORT26_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL26m}, 412 {PORT27_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL27m}, 413 {PORT28_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL28m}, 414 {PORT29_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL29m}, 415 {PORT30_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL30m}, 416 {PORT31_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL31m} 417 }; 418 #endif /* BCM_HURRICANE3_SUPPORT */ 419 #if defined(BCM_GREYHOUND2_SUPPORT) 420 _rep_regs_t gh2_rep_regs[66] = { {INVALIDf, INVALIDf, INVALIDm}, 421 {INVALIDf, INVALIDf, INVALIDm}, 422 {PORT_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL2m}, 423 {PORT_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL3m}, 424 {PORT_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL4m}, 425 {PORT_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL5m}, 426 {PORT_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL6m}, 427 {PORT_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL7m}, 428 {PORT_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL8m}, 429 {PORT_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL9m}, 430 {PORT_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL10m}, 431 {PORT_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL11m}, 432 {PORT_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL12m}, 433 {PORT_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL13m}, 434 {PORT_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL14m}, 435 {PORT_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL15m}, 436 {PORT_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL16m}, 437 {PORT_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL17m}, 438 {PORT_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL18m}, 439 {PORT_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL19m}, 440 {PORT_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL20m}, 441 {PORT_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL21m}, 442 {PORT_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL22m}, 443 {PORT_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL23m}, 444 {PORT_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL24m}, 445 {PORT_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL25m}, 446 {PORT_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL26m}, 447 {PORT_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL27m}, 448 {PORT_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL28m}, 449 {PORT_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL29m}, 450 {PORT_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL30m}, 451 {PORT_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL31m}, 452 {PORT_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL32m}, 453 {PORT_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL33m}, 454 {PORT_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL34m}, 455 {PORT_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL35m}, 456 {PORT_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL36m}, 457 {PORT_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL37m}, 458 {PORT_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL38m}, 459 {PORT_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL39m}, 460 {PORT_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL40m}, 461 {PORT_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL41m}, 462 {PORT_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL42m}, 463 {PORT_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL43m}, 464 {PORT_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL44m}, 465 {PORT_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL45m}, 466 {PORT_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL46m}, 467 {PORT_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL47m}, 468 {PORT_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL48m}, 469 {PORT_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL49m}, 470 {PORT_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL50m}, 471 {PORT_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL51m}, 472 {PORT_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL52m}, 473 {PORT_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL53m}, 474 {PORT_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL54m}, 475 {PORT_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL55m}, 476 {PORT_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL56m}, 477 {PORT_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL57m}, 478 {PORT_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL58m}, 479 {PORT_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL59m}, 480 {PORT_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL60m}, 481 {PORT_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL61m}, 482 {PORT_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL62m}, 483 {PORT_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL63m}, 484 {PORT_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL64m}, 485 {PORT_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL65m} 486 }; 487 #endif /* BCM_GREYHOUND2_SUPPORT */ 488 STATIC int 489 _fb_ipmc_vlan_ptr(int unit,int ipmc_id, 490 bcm_port_t port, int *vptr, int last, int set) 491 { 492 soc_field_t port_ptr = INVALIDf; 493 soc_field_t last_ptr = INVALIDf; 494 soc_mem_t mem = INVALIDm; 495 mmu_ipmc_group_tbl0_entry_t gentry; 496 int rv; 497 _rep_regs_t *rep_arr_ptr; 498 #if defined(BCM_GREYHOUND2_SUPPORT) 499 int mmu_port, phy_port = 0; 500 const soc_field_t port_ptrf[8] = { 501 PORT_1STPTR_0f, PORT_1STPTR_1f, PORT_1STPTR_2f, PORT_1STPTR_3f, 502 PORT_1STPTR_4f, PORT_1STPTR_5f, PORT_1STPTR_6f, PORT_1STPTR_7f}; 503 #endif 504 505 rep_arr_ptr = NULL; 506 if (SOC_IS_FB_FX_HX(unit)) { 507 rep_arr_ptr = fb_rep_regs; 508 } 509 #if defined(BCM_HB_GW_SUPPORT) 510 if (SOC_IS_HB_GW(unit)) { 511 rep_arr_ptr = hbgw_rep_regs; 512 } 513 #endif 514 #if defined(BCM_RAVEN_SUPPORT) 515 if (SOC_IS_RAVEN(unit)) { 516 rep_arr_ptr = rvn_rep_regs; 517 } 518 #endif /* BCM_RAVEN_SUPPORT */ 519 #if defined(BCM_TRIUMPH_SUPPORT) 520 #if defined(BCM_HURRICANE_SUPPORT) 521 if (SOC_IS_HURRICANE(unit) || SOC_IS_HURRICANE2(unit)) { 522 rep_arr_ptr = hu_rep_regs; 523 } else 524 #endif /* BCM_HURRICANE_SUPPORT */ 525 if (SOC_IS_TR_VL(unit)) { 526 rep_arr_ptr = tr_rep_regs; 527 } 528 #endif 529 #if defined (BCM_SCORPION_SUPPORT) 530 if (SOC_IS_SC_CQ(unit)) { 531 rep_arr_ptr = sco_rep_regs; 532 } 533 #endif 534 #if defined(BCM_ENDURO_SUPPORT) 535 if (SOC_IS_ENDURO(unit)) { 536 rep_arr_ptr = en_rep_regs; 537 } 538 #endif 539 #if defined(BCM_GREYHOUND_SUPPORT) 540 if (SOC_IS_GREYHOUND(unit)) { 541 rep_arr_ptr = gh_rep_regs; 542 } 543 #endif 544 #if defined(BCM_HURRICANE3_SUPPORT) 545 if (SOC_IS_HURRICANE3(unit)) { 546 rep_arr_ptr = hr3_rep_regs; 547 } 548 #endif 549 #if defined(BCM_GREYHOUND2_SUPPORT) 550 if (SOC_IS_GREYHOUND2(unit)) { 551 rep_arr_ptr = gh2_rep_regs; 552 } 553 #endif 554 if (NULL == rep_arr_ptr) { 555 return BCM_E_UNIT; 556 } 557 558 #if defined(BCM_GREYHOUND2_SUPPORT) 559 if (SOC_IS_GREYHOUND2(unit)) { 560 phy_port = SOC_INFO(unit).port_l2p_mapping[port]; 561 mmu_port = SOC_INFO(unit).port_p2m_mapping[phy_port]; 562 } else { 563 mmu_port = port; 564 } 565 mem = rep_arr_ptr[mmu_port].mem; 566 port_ptr = rep_arr_ptr[mmu_port].port_ptr; 567 last_ptr = rep_arr_ptr[mmu_port].last_ptr; 568 #else 569 mem = rep_arr_ptr[port].mem; 570 port_ptr = rep_arr_ptr[port].port_ptr; 571 last_ptr = rep_arr_ptr[port].last_ptr; 572 #endif /* BCM_GREYHOUND2_SUPPORT */ 573 574 if ((INVALIDm == mem) || (INVALIDf == port_ptr)){ 575 return BCM_E_PARAM; 576 } 577 soc_mem_lock(unit, mem); 578 #if defined(BCM_GREYHOUND2_SUPPORT) 579 if (SOC_MEM_FIELD_VALID(unit, mem, port_ptrf[0])) { 580 /* length of ipmc_id exceed 10 bits using different hw structure */ 581 if ((rv = soc_mem_read(unit, mem, MEM_BLOCK_ALL, 582 (ipmc_id >> 3), &gentry)) < 0) { 583 soc_mem_unlock(unit, mem); 584 return rv; 585 } 586 } else 587 #endif /* BCM_GREYHOUND2_SUPPORT */ 588 { 589 if ((rv = soc_mem_read(unit, mem, MEM_BLOCK_ALL, 590 ipmc_id, &gentry)) < 0) { 591 soc_mem_unlock(unit, mem); 592 return rv; 593 } 594 } 595 if (set) { 596 #if defined(BCM_GREYHOUND2_SUPPORT) 597 if (SOC_MEM_FIELD_VALID(unit, mem, port_ptrf[0])) { 598 soc_mem_field32_set(unit, mem, &gentry, port_ptrf[(ipmc_id & 0x7)], 599 *vptr); 600 if (soc_feature(unit, soc_feature_ipmc_repl_penultimate)) { 601 soc_mem_field32_set(unit, mem, &gentry, last_ptr,last ? 1 : 0); 602 } 603 if ((rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, (ipmc_id >> 3), 604 &gentry)) < 0) { 605 soc_mem_unlock(unit, mem); 606 return rv; 607 } 608 } else 609 #endif /* BCM_GREYHOUND2_SUPPORT */ 610 { 611 soc_mem_field32_set(unit, mem, &gentry, port_ptr, *vptr); 612 if (soc_feature(unit, soc_feature_ipmc_repl_penultimate)) { 613 soc_mem_field32_set(unit, mem, &gentry, last_ptr,last ? 1 : 0); 614 } 615 if ((rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, ipmc_id, 616 &gentry)) < 0) { 617 soc_mem_unlock(unit, mem); 618 return rv; 619 } 620 } 621 LOG_VERBOSE(BSL_LS_SOC_COMMON, 622 (BSL_META_U(unit, 623 "set IPMC_GROUPm(port=%d,group=%d,ptr=%d)\n"), 624 port, ipmc_id, *vptr)); 625 626 627 } else { 628 #if defined(BCM_GREYHOUND2_SUPPORT) 629 if (SOC_MEM_FIELD_VALID(unit, mem, port_ptrf[0])) { 630 *vptr = soc_mem_field32_get(unit, mem, &gentry, 631 port_ptrf[(ipmc_id & 0x7)]); 632 } else 633 #endif /* BCM_GREYHOUND2_SUPPORT */ 634 { 635 *vptr = soc_mem_field32_get(unit, mem, &gentry, port_ptr); 636 } 637 } 638 soc_mem_unlock(unit, mem); 639 640 return BCM_E_NONE; 641 } 642 643 /* 644 * Function: 645 * _bcm_fb_ipmc_repl_freeze 646 * Purpose: 647 * Pause IPMC replication (actually all traffic) before reconfiging 648 * Parameters: 649 * unit - SOC unit # 650 * Returns: 651 * BCM_E_XXX 652 */ 653 STATIC int 654 _bcm_fb_ipmc_repl_freeze(int unit) 655 { 656 int rv = BCM_E_NONE; 657 uint32 rval; 658 uint32 op_verify; 659 soc_port_t port; 660 uint32 emb_set, emb_get, emc_set; 661 662 /* MISCCONFIG.METERING_CLK_EN is set by chip init */ 663 664 /* This is a lock, so it must be released! */ 665 SOC_EGRESS_METERING_LOCK(unit); 666 667 emc_set = 0; 668 soc_reg_field_set(unit, EGRMETERINGCONFIGr, &emc_set, REFRESHf, 0); 669 soc_reg_field_set(unit, EGRMETERINGCONFIGr, &emc_set, THD_SELf, 1); 670 671 emb_set = 0; 672 soc_reg_field_set(unit, EGRMETERINGBUCKETr, &emb_set, BUCKETf, 0xffffff); 673 674 PBMP_E_ITER(unit, port) { 675 if ((rv = READ_EGRMETERINGCONFIGr(unit, port, &rval)) < 0) { 676 break; 677 } 678 IPMC_REPL_PORT_INFO(unit, port)->emc_val = rval; 679 if ((rv = WRITE_EGRMETERINGCONFIGr(unit, port, emc_set)) < 0) { 680 break; 681 } 682 683 /* Write to EGRMETERINGBUCKET register might be stomped by 684 * traffic. Verify that the IN_PROFILE_FLAG is successfully set. */ 685 do { 686 if ((rv = WRITE_EGRMETERINGBUCKETr(unit, port, emb_set)) < 0) { 687 break; 688 } 689 690 if (!SAL_BOOT_SIMULATION) { 691 if ((rv = READ_EGRMETERINGBUCKETr(unit, port, &emb_get)) < 0) { 692 break; 693 } 694 695 op_verify = soc_reg_field_get(unit, EGRMETERINGBUCKETr, 696 emb_get, IN_PROFILE_FLAGf); 697 } else { 698 op_verify = 1; 699 } 700 } while (op_verify != 1); 701 702 if (rv < 0) { 703 break; 704 } 705 } 706 707 if (rv < 0) { 708 SOC_EGRESS_METERING_UNLOCK(unit); 709 } 710 711 return rv; 712 } 713 714 /* 715 * Function: 716 * _bcm_fb_ipmc_repl_thaw 717 * Purpose: 718 * Start IPMC replication (actually all traffic) after reconfiging 719 * Parameters: 720 * unit - SOC unit # 721 * Returns: 722 * BCM_E_XXX 723 */ 724 STATIC int 725 _bcm_fb_ipmc_repl_thaw(int unit) 726 { 727 int rv = BCM_E_NONE; 728 uint32 rval; 729 soc_port_t port; 730 731 PBMP_E_ITER(unit, port) { 732 rval = 0; 733 /* 734 * all fields in "rval" are already zero 735 * soc_reg_field_set(unit, EGRMETERINGBUCKETr, &rval, 736 * IN_PROFILE_FLAGf, 0); 737 * soc_reg_field_set(unit, EGRMETERINGBUCKETr, &rval, BUCKETf, 0); 738 */ 739 if ((rv = WRITE_EGRMETERINGBUCKETr(unit, port, rval)) < 0) { 740 break; 741 } 742 743 rval = IPMC_REPL_PORT_INFO(unit, port)->emc_val; 744 if ((rv = WRITE_EGRMETERINGCONFIGr(unit, port, rval)) < 0) { 745 break; 746 } 747 } 748 749 /* Must thaw here to release lock from freeze */ 750 SOC_EGRESS_METERING_UNLOCK(unit); 751 752 return rv; 753 } 754 755 #ifdef BCM_WARM_BOOT_SUPPORT 756 /* 757 * Function: 758 * _bcm_xgs3_ipmc_repl_reload 759 * Purpose: 760 * Re-Initialize IPMC replication software to state consistent with 761 * hardware 762 * Parameters: 763 * unit - SOC unit # 764 * Returns: 765 * BCM_E_XXX 766 */ 767 int 768 _bcm_xgs3_ipmc_repl_reload(int unit) 769 { 770 mmu_ipmc_vlan_tbl_entry_t vlan_entry; 771 uint32 ms_bit, ls_bits[2]; 772 bcm_port_t port; 773 int ipmc_id, alloc_size, intf_alloc_size; 774 int vlan_ptr, next_vlan_ptr, first_vlan_ptr; 775 SHR_BITDCL *intf_vec = NULL; 776 SHR_BITDCL *intf_vec_egr = NULL; 777 _bcm_repl_list_info_t *rli_start, *rli_current; 778 uint8 flags; 779 int rv; 780 int i; 781 int egr_id; 782 bcm_l3_egress_t egr_nh; 783 784 bcm_fb_ipmc_repl_detach(unit); 785 /* TD3TBD */ 786 if (SOC_IS_TRIDENT3X(unit)) { 787 return BCM_E_NONE; 788 } 789 790 /* Allocate struct for IPMC replication booking keeping */ 791 alloc_size = sizeof(_fb_repl_info_t); 792 _fb_repl_info[unit] = sal_alloc(alloc_size, "IPMC repl info"); 793 if (_fb_repl_info[unit] == NULL) { 794 return BCM_E_MEMORY; 795 } 796 sal_memset(_fb_repl_info[unit], 0, alloc_size); 797 798 IPMC_REPL_GROUP_NUM(unit) = soc_mem_index_count(unit, L3_IPMCm); 799 800 #ifdef BCM_TRIUMPH_SUPPORT 801 if (SOC_IS_TR_VL(unit) && !SOC_IS_HURRICANEX(unit) && 802 !SOC_IS_GREYHOUND(unit) && !SOC_IS_GREYHOUND2(unit)) { 803 /* For VPLS, can replicate to 16k next-hop entries */ 804 IPMC_REPL_INTF_TOTAL(unit) = soc_mem_index_count(unit, EGR_L3_NEXT_HOPm); 805 } else 806 #endif 807 { 808 IPMC_REPL_INTF_TOTAL(unit) = soc_mem_index_count(unit, EGR_L3_INTFm); 809 } 810 811 /* 812 * soc_feature_l3mc_use_egress_next_hop use EGR_L3_NEXT_HOP as 813 * replication interface instead of using EGR_L3_INTF. 814 */ 815 if (soc_feature(unit, soc_feature_l3mc_use_egress_next_hop)) { 816 IPMC_REPL_INTF_TOTAL(unit) = soc_mem_index_count(unit, EGR_L3_NEXT_HOPm); 817 } 818 819 IPMC_REPL_TOTAL(unit) = soc_mem_index_count(unit, MMU_IPMC_VLAN_TBLm); 820 alloc_size = SHR_BITALLOCSIZE(IPMC_REPL_TOTAL(unit)); 821 _fb_repl_info[unit]->bitmap_entries_used = 822 sal_alloc(alloc_size, "IPMC repl entries used"); 823 if (_fb_repl_info[unit]->bitmap_entries_used == NULL) { 824 bcm_fb_ipmc_repl_detach(unit); 825 return BCM_E_MEMORY; 826 } 827 sal_memset(_fb_repl_info[unit]->bitmap_entries_used, 0, alloc_size); 828 829 if (NULL == _fb_repl_info[unit]->l3_intf_to_l3_nh_ipmc) { 830 _fb_repl_info[unit]->l3_intf_to_l3_nh_ipmc = 831 sal_alloc(sizeof(int) * soc_mem_index_count(unit, EGR_L3_INTFm), 832 "l3_intf_to_next_hop_ipmc"); 833 if (NULL == _fb_repl_info[unit]->l3_intf_to_l3_nh_ipmc) { 834 bcm_fb_ipmc_repl_detach(unit); 835 return BCM_E_MEMORY; 836 } 837 } 838 for (i = 0; i < soc_mem_index_count(unit, EGR_L3_INTFm); i++) { 839 _fb_repl_info[unit]->l3_intf_to_l3_nh_ipmc[i] = 840 REPL_NH_INDEX_UNALLOCATED; 841 } 842 843 /* Always reserve slot 0 (because 0 means NULL pointer) */ 844 IPMC_REPL_VE_USED_SET(unit, 0); 845 846 PBMP_ITER(PBMP_PORT_ALL(unit), port) { 847 alloc_size = sizeof(_fb_repl_port_info_t); 848 IPMC_REPL_PORT_INFO(unit, port) = 849 sal_alloc(alloc_size, "IPMC repl port info"); 850 if (IPMC_REPL_PORT_INFO(unit, port) == NULL) { 851 bcm_fb_ipmc_repl_detach(unit); 852 return BCM_E_MEMORY; 853 } 854 sal_memset(IPMC_REPL_PORT_INFO(unit, port), 0, alloc_size); 855 856 alloc_size = sizeof(int32) * IPMC_REPL_GROUP_NUM(unit); 857 IPMC_REPL_PORT_INFO(unit, port)->vlan_count = 858 sal_alloc(alloc_size, "IPMC repl port vlan count"); 859 if (IPMC_REPL_PORT_INFO(unit, port)->vlan_count == NULL) { 860 bcm_fb_ipmc_repl_detach(unit); 861 return BCM_E_MEMORY; 862 } 863 sal_memset(IPMC_REPL_PORT_INFO(unit, port)->vlan_count, 864 0, alloc_size); 865 } 866 /* 867 * HR3 and GH family use L3_EGR_NH table instead of L3_INTF when indexed by IPMC_VLAN. 868 * And it uses soc_feature_l3mc_use_egress_next_hop to distinquish this 869 */ 870 if (soc_feature(unit, soc_feature_l3mc_use_egress_next_hop)) { 871 alloc_size = SHR_BITALLOCSIZE(soc_mem_index_count(unit, 872 EGR_L3_NEXT_HOPm)); 873 } else { 874 alloc_size = SHR_BITALLOCSIZE(IPMC_REPL_INTF_TOTAL(unit)); 875 } 876 intf_vec = sal_alloc(alloc_size, "IPMC repl interface vector"); 877 if (intf_vec == NULL) { 878 bcm_fb_ipmc_repl_detach(unit); 879 return BCM_E_MEMORY; 880 } 881 intf_alloc_size = alloc_size; 882 rli_start = IPMC_REPL_LIST_INFO(unit); 883 884 /* 885 * Read IPMC group and IPMC VLAN tables to build up software state 886 */ 887 for (ipmc_id = soc_mem_index_min(unit, L3_IPMCm); 888 ipmc_id <= soc_mem_index_max(unit, L3_IPMCm); ipmc_id++) { 889 890 PBMP_ITER (PBMP_PORT_ALL(unit), port) { 891 rv = _fb_ipmc_vlan_ptr(unit, ipmc_id, port, &first_vlan_ptr, 0, 0); 892 if (BCM_FAILURE(rv)) { 893 sal_free(intf_vec); 894 bcm_fb_ipmc_repl_detach(unit); 895 return rv; 896 } 897 if (first_vlan_ptr == 0) { 898 continue; 899 } 900 if (IPMC_REPL_VE_USED_GET(unit, first_vlan_ptr)) { 901 /* We've already traversed this list, just note it */ 902 for (rli_current = rli_start; rli_current != NULL; 903 rli_current = rli_current->next) { 904 if (rli_current->index == first_vlan_ptr) { 905 (rli_current->refcount)++; 906 IPMC_REPL_PORT_VLAN_COUNT(unit, port, ipmc_id) = 907 rli_current->list_size; 908 break; 909 } 910 } 911 if (rli_current == NULL) { 912 /* Table out of sync. Not good. */ 913 sal_free(intf_vec); 914 bcm_fb_ipmc_repl_detach(unit); 915 return BCM_E_INTERNAL; 916 } else { 917 continue; 918 } 919 } 920 sal_memset(intf_vec, 0, intf_alloc_size); 921 next_vlan_ptr = first_vlan_ptr; 922 vlan_ptr = 0; 923 while (vlan_ptr != next_vlan_ptr) { 924 vlan_ptr = next_vlan_ptr; 925 rv = READ_MMU_IPMC_VLAN_TBLm(unit, MEM_BLOCK_ALL, 926 vlan_ptr, &vlan_entry); 927 if (BCM_FAILURE(rv)) { 928 sal_free(intf_vec); 929 bcm_fb_ipmc_repl_detach(unit); 930 return rv; 931 } 932 soc_MMU_IPMC_VLAN_TBLm_field_get(unit, &vlan_entry, 933 LSB_VLAN_BMf, ls_bits); 934 ms_bit = soc_MMU_IPMC_VLAN_TBLm_field32_get( 935 unit, &vlan_entry, MSB_VLANf); 936 intf_vec[2 * ms_bit + 0] = ls_bits[0]; 937 intf_vec[2 * ms_bit + 1] = ls_bits[1]; 938 IPMC_REPL_PORT_VLAN_COUNT(unit, port, ipmc_id) += 939 _shr_popcount(ls_bits[0]) + _shr_popcount(ls_bits[1]); 940 IPMC_REPL_VE_USED_SET(unit, vlan_ptr); 941 next_vlan_ptr = soc_MMU_IPMC_VLAN_TBLm_field32_get(unit, 942 &vlan_entry, NEXTPTRf); 943 } 944 945 /* Create new list element */ 946 alloc_size = sizeof(_bcm_repl_list_info_t); 947 rli_current = sal_alloc(alloc_size, "IPMC repl list info"); 948 if (rli_current == NULL) { 949 sal_free(intf_vec); 950 bcm_fb_ipmc_repl_detach(unit); 951 return BCM_E_MEMORY; 952 } 953 sal_memset(rli_current, 0, alloc_size); 954 rli_current->index = first_vlan_ptr; 955 if (soc_feature(unit, soc_feature_l3mc_use_egress_next_hop)) { 956 /* 957 * Previous intf_vef is derived from egr_l3_next_hop, 958 * now need to transfer l3_intf to l3_intf_egr. 959 */ 960 intf_vec_egr = 961 sal_alloc(SHR_BITALLOCSIZE(IPMC_REPL_INTF_TOTAL(unit)), 962 "IPMC repl interface vector, l3mc use egr nh"); 963 if (intf_vec_egr == NULL) { 964 sal_free(intf_vec); 965 sal_free(rli_current); 966 bcm_fb_ipmc_repl_detach(unit); 967 return BCM_E_MEMORY; 968 } 969 sal_memset(intf_vec_egr, 0, 970 SHR_BITALLOCSIZE(IPMC_REPL_INTF_TOTAL(unit))); 971 SHR_BIT_ITER(intf_vec, soc_mem_index_count( 972 unit, EGR_L3_NEXT_HOPm), egr_id) { 973 rv = bcm_xgs3_nh_get(unit, egr_id, &egr_nh); 974 /* SW data not recover, will always return BCM_E_NOT_FOUND */ 975 if (BCM_FAILURE(rv) && rv != BCM_E_NOT_FOUND) { 976 sal_free(intf_vec_egr); 977 sal_free(intf_vec); 978 sal_free(rli_current); 979 bcm_fb_ipmc_repl_detach(unit); 980 return rv; 981 } 982 SHR_BITSET(intf_vec_egr, egr_nh.intf); 983 } 984 rli_current->hash = 985 _shr_crc32b(0, (uint8 *)intf_vec_egr, 986 IPMC_REPL_INTF_TOTAL(unit)); 987 sal_free(intf_vec_egr); 988 intf_vec_egr = NULL; 989 } else { 990 rli_current->hash = 991 _shr_crc32b(0, (uint8 *)intf_vec, 992 IPMC_REPL_INTF_TOTAL(unit)); 993 } 994 rli_current->next = rli_start; 995 rli_current->list_size = 996 IPMC_REPL_PORT_VLAN_COUNT(unit, port, ipmc_id); 997 IPMC_REPL_LIST_INFO(unit) = rli_current; 998 rli_start = rli_current; 999 (rli_current->refcount)++; 1000 } 1001 } 1002 1003 /* Recover REPL list mode from HW cache */ 1004 rv = _bcm_esw_ipmc_repl_wb_flags_get(unit, 1005 _BCM_IPMC_WB_REPL_LIST, &flags); 1006 if (flags) { 1007 SOC_IPMCREPLSHR_SET(unit, 1); 1008 } 1009 1010 sal_free(intf_vec); 1011 1012 /* Init the nexthop to l3 intf sw structure */ 1013 if (NULL == _fb_repl_info[unit]->l3_nh_to_l3_intf_ipmc) { 1014 _fb_repl_info[unit]->l3_nh_to_l3_intf_ipmc = 1015 sal_alloc(sizeof(int) * soc_mem_index_count(unit, EGR_L3_NEXT_HOPm), 1016 "next_hop_to_l3_intf_ipmc"); 1017 1018 if (NULL == _fb_repl_info[unit]->l3_nh_to_l3_intf_ipmc) { 1019 bcm_fb_ipmc_repl_detach(unit); 1020 return BCM_E_MEMORY; 1021 } 1022 } 1023 for (i = 0; i < soc_mem_index_count(unit, EGR_L3_NEXT_HOPm); i++) { 1024 _fb_repl_info[unit]->l3_nh_to_l3_intf_ipmc[i] = 1025 REPL_L3_INTF_UNALLOCATED; 1026 } 1027 1028 if (NULL == _fb_repl_info[unit]->l3_intf_to_l3_nh_ipmc) { 1029 _fb_repl_info[unit]->l3_intf_to_l3_nh_ipmc = 1030 sal_alloc(sizeof(int) * soc_mem_index_count(unit, EGR_L3_INTFm), 1031 "l3_intf_to_next_hop_ipmc"); 1032 1033 if (NULL == _fb_repl_info[unit]->l3_intf_to_l3_nh_ipmc) { 1034 bcm_fb_ipmc_repl_detach(unit); 1035 return BCM_E_MEMORY; 1036 } 1037 } 1038 for (i = 0; i < soc_mem_index_count(unit, EGR_L3_INTFm); i++) { 1039 _fb_repl_info[unit]->l3_intf_to_l3_nh_ipmc[i] = 1040 REPL_NH_INDEX_UNALLOCATED; 1041 } 1042 1043 return BCM_E_NONE; 1044 } 1045 #endif /* BCM_WARM_BOOT_SUPPORT */ 1046 #endif /* BCM_FIREBOLT_SUPPORT */ 1047 1048 #if defined(BCM_FIREBOLT_SUPPORT) 1049 /* 1050 * Function: 1051 * _bcm_xgs3_ipmc_l3entry_list_add 1052 * Purpose: 1053 * Add a L3 entry to IPMC group's linked list of L3 entries 1054 * Parameters: 1055 * unit - (IN) BCM device number. 1056 * ipmc_index - (IN) IPMC group ID. 1057 * _bcm_l3_cfg_t - (IN) l3 config structure 1058 * Returns: 1059 * BCM_E_XXX 1060 */ 1061 static int 1062 _bcm_xgs3_ipmc_l3entry_list_add(int unit, int ipmc_index, 1063 _bcm_l3_cfg_t *l3cfg) 1064 { 1065 _bcm_esw_ipmc_l3entry_t *ipmc_l3entry; 1066 1067 ipmc_l3entry = sal_alloc(sizeof(_bcm_esw_ipmc_l3entry_t), "IPMC L3 entry"); 1068 if (ipmc_l3entry == NULL) { 1069 return BCM_E_MEMORY; 1070 } 1071 ipmc_l3entry->ip6 = (l3cfg->l3c_flags & BCM_L3_IP6) ? 1 : 0; 1072 ipmc_l3entry->l3info.flags = l3cfg->l3c_flags; 1073 ipmc_l3entry->l3info.vrf = l3cfg->l3c_vrf; 1074 ipmc_l3entry->l3info.ip_addr = l3cfg->l3c_ipmc_group; 1075 ipmc_l3entry->l3info.src_ip_addr = l3cfg->l3c_src_ip_addr; 1076 sal_memcpy(ipmc_l3entry->l3info.ip6, l3cfg->l3c_ip6, BCM_IP6_ADDRLEN); 1077 sal_memcpy(ipmc_l3entry->l3info.sip6, l3cfg->l3c_sip6, BCM_IP6_ADDRLEN); 1078 ipmc_l3entry->l3info.vid = l3cfg->l3c_vid; 1079 ipmc_l3entry->l3info.prio = l3cfg->l3c_prio; 1080 ipmc_l3entry->l3info.ipmc_ptr = l3cfg->l3c_ipmc_ptr; 1081 ipmc_l3entry->l3info.lookup_class = l3cfg->l3c_lookup_class; 1082 ipmc_l3entry->next = IPMC_GROUP_INFO(unit, ipmc_index)->l3entry_list; 1083 IPMC_GROUP_INFO(unit, ipmc_index)->l3entry_list = ipmc_l3entry; 1084 1085 return BCM_E_NONE; 1086 } 1087 1088 /* 1089 * Function: 1090 * _bcm_xgs3_ipmc_l3entry_list_del 1091 * Purpose: 1092 * Delete a L3 entry from IPMC group's linked list of L3 entries 1093 * Parameters: 1094 * unit - (IN) BCM device number. 1095 * ipmc_index - (IN) IPMC group ID. 1096 * _bcm_l3_cfg_t - (IN) l3 config structure 1097 * Returns: 1098 * BCM_E_XXX 1099 */ 1100 STATIC int 1101 _bcm_xgs3_ipmc_l3entry_list_del(int unit, int ipmc_index, 1102 _bcm_l3_cfg_t *l3cfg) 1103 { 1104 _bcm_esw_ipmc_l3entry_t *ipmc_l3entry; 1105 _bcm_esw_ipmc_l3entry_t *prev_ipmc_l3entry = NULL; 1106 1107 ipmc_l3entry = IPMC_GROUP_INFO(unit, ipmc_index)->l3entry_list; 1108 while (ipmc_l3entry != NULL) { 1109 if ((ipmc_l3entry->l3info.ip_addr == l3cfg->l3c_ip_addr) && 1110 (ipmc_l3entry->l3info.src_ip_addr == l3cfg->l3c_src_ip_addr) && 1111 (!sal_memcmp(ipmc_l3entry->l3info.ip6, l3cfg->l3c_ip6, BCM_IP6_ADDRLEN)) && 1112 (!sal_memcmp(ipmc_l3entry->l3info.sip6, l3cfg->l3c_sip6, BCM_IP6_ADDRLEN)) && 1113 (ipmc_l3entry->l3info.vid == l3cfg->l3c_vid) && 1114 (ipmc_l3entry->l3info.vrf == l3cfg->l3c_vrf)) { 1115 if (ipmc_l3entry == IPMC_GROUP_INFO(unit, ipmc_index)->l3entry_list) { 1116 IPMC_GROUP_INFO(unit, ipmc_index)->l3entry_list = ipmc_l3entry->next; 1117 } else { 1118 /* 1119 * In the following line of code, Coverity thinks the 1120 * prev_ipmc_l3entry pointer may still be NULL when 1121 * dereferenced. This situation will never occur because 1122 * if ipmc_l3entry is not pointing to the head of the 1123 * linked list, prev_ipmc_l3entry would not be NULL. 1124 */ 1125 /* coverity[var_deref_op : FALSE] */ 1126 prev_ipmc_l3entry->next = ipmc_l3entry->next; 1127 } 1128 sal_free(ipmc_l3entry); 1129 break; 1130 } 1131 prev_ipmc_l3entry = ipmc_l3entry; 1132 ipmc_l3entry = ipmc_l3entry->next; 1133 } 1134 1135 if (ipmc_l3entry == NULL) { 1136 return BCM_E_NOT_FOUND; 1137 } 1138 1139 return BCM_E_NONE; 1140 } 1141 1142 STATIC int 1143 _bcm_xgs3_ipmc_l3entry_list_update(int unit, int ipmc_index, 1144 _bcm_l3_cfg_t *l3cfg) 1145 { 1146 _bcm_esw_ipmc_l3entry_t *ipmc_l3entry; 1147 1148 ipmc_l3entry = IPMC_GROUP_INFO(unit, ipmc_index)->l3entry_list; 1149 while (ipmc_l3entry != NULL) { 1150 if ((ipmc_l3entry->l3info.ip_addr == l3cfg->l3c_ip_addr) && 1151 (ipmc_l3entry->l3info.src_ip_addr == l3cfg->l3c_src_ip_addr) && 1152 (!sal_memcmp(ipmc_l3entry->l3info.ip6, l3cfg->l3c_ip6, BCM_IP6_ADDRLEN)) && 1153 (!sal_memcmp(ipmc_l3entry->l3info.sip6, l3cfg->l3c_sip6, BCM_IP6_ADDRLEN)) && 1154 (ipmc_l3entry->l3info.vid == l3cfg->l3c_vid)) { 1155 ipmc_l3entry->l3info.flags = l3cfg->l3c_flags; 1156 ipmc_l3entry->l3info.vrf = l3cfg->l3c_vrf; 1157 ipmc_l3entry->l3info.prio = l3cfg->l3c_prio; 1158 ipmc_l3entry->l3info.ipmc_ptr = l3cfg->l3c_ipmc_ptr; 1159 ipmc_l3entry->l3info.lookup_class = l3cfg->l3c_lookup_class; 1160 break; 1161 } 1162 ipmc_l3entry = ipmc_l3entry->next; 1163 } 1164 1165 if (ipmc_l3entry == NULL) { 1166 return BCM_E_NOT_FOUND; 1167 } 1168 1169 return BCM_E_NONE; 1170 } 1171 1172 /* 1173 * Function: 1174 * _bcm_xgs3_ipmc_l3entry_list_size_get 1175 * Purpose: 1176 * Get the number of L3 entries in IPMC group's linked list. 1177 * Parameters: 1178 * unit - (IN) BCM device number. 1179 * ipmc_index - (IN) IPMC group ID. 1180 * size - (OUT) Number of L3 entries. 1181 * Returns: 1182 * BCM_E_XXX 1183 */ 1184 STATIC int 1185 _bcm_xgs3_ipmc_l3entry_list_size_get(int unit, int ipmc_index, 1186 int *size) 1187 { 1188 if (IPMC_USED_ISSET(unit, ipmc_index)) { 1189 *size = IPMC_GROUP_INFO(unit, ipmc_index)->ref_count - 1; 1190 } else { 1191 *size = 0; 1192 } 1193 1194 return BCM_E_NONE; 1195 } 1196 1197 #endif /* BCM_FIREBOLT_SUPPORT */ 1198 1199 /* 1200 * Function: 1201 * bcm_xgs3_ipmc_create 1202 * Purpose: 1203 * Create an ipmc entry. 1204 */ 1205 1206 int 1207 bcm_xgs3_ipmc_create(int unit, int *ipmc_id) 1208 { 1209 int i; 1210 1211 IPMC_LOCK(unit); 1212 for (i = 0; i < IPMC_GROUP_NUM(unit); i++) { 1213 if (!IPMC_USED_ISSET(unit, i)) { 1214 IPMC_USED_SET(unit, i); 1215 *ipmc_id = i; 1216 IPMC_UNLOCK(unit); 1217 return BCM_E_NONE; 1218 } 1219 } 1220 IPMC_UNLOCK(unit); 1221 1222 return (BCM_E_FULL); 1223 } 1224 1225 /* 1226 * Function: 1227 * bcm_xgs3_ipmc_id_alloc 1228 * Purpose: 1229 * allocate the given ipmc entry. 1230 */ 1231 1232 int 1233 bcm_xgs3_ipmc_id_alloc(int unit, int ipmc_id) 1234 { 1235 IPMC_LOCK(unit); 1236 IPMC_USED_SET(unit, ipmc_id); 1237 IPMC_UNLOCK(unit); 1238 return BCM_E_NONE; 1239 } 1240 1241 /* 1242 * Function: 1243 * bcm_xgs3_ipmc_id_free 1244 * Purpose: 1245 * Delete an ipmc entry. 1246 */ 1247 1248 int 1249 bcm_xgs3_ipmc_id_free(int unit, int ipmc_id) 1250 { 1251 IPMC_INIT(unit); 1252 IPMC_ID(unit, ipmc_id); 1253 1254 IPMC_LOCK(unit); 1255 if (IPMC_USED_ISSET(unit, ipmc_id)) { 1256 IPMC_USED_CLR(unit, ipmc_id); 1257 } 1258 IPMC_UNLOCK(unit); 1259 1260 return BCM_E_NONE; 1261 } 1262 1263 /* 1264 * Function: 1265 * bcm_xgs3_ipmc_id_is_set 1266 * Purpose: 1267 * Verify an ipmc entry. 1268 */ 1269 1270 int 1271 bcm_xgs3_ipmc_id_is_set(int unit, int ipmc_id, int *is_set) 1272 { 1273 IPMC_INIT(unit); 1274 IPMC_ID(unit, ipmc_id); 1275 1276 IPMC_LOCK(unit); 1277 *is_set = (0 != IPMC_USED_ISSET(unit, ipmc_id)); 1278 IPMC_UNLOCK(unit); 1279 1280 return BCM_E_NONE; 1281 } 1282 1283 /* 1284 * Function: 1285 * _xgs3_ipmc_info_get 1286 * Purpose: 1287 * Fill information to bcm_ipmc_addr_t struct. 1288 */ 1289 1290 STATIC int 1291 _xgs3_ipmc_info_get(int unit, int hw_index, int index, int er_index_get, 1292 bcm_ipmc_addr_t *ipmc, ipmc_entry_t *entry, 1293 uint8 do_l3_lkup, 1294 _bcm_esw_ipmc_l3entry_t *use_ipmc_l3entry) 1295 { 1296 uint32 mod, port_tgid, is_trunk; 1297 uint32 chk_val; 1298 int no_src_check = FALSE; 1299 #if defined(BCM_FIREBOLT_SUPPORT) 1300 _bcm_esw_ipmc_l3entry_t *ipmc_l3entry = NULL; 1301 #endif 1302 1303 ipmc->v = soc_L3_IPMCm_field32_get(unit, entry, VALIDf); 1304 1305 chk_val = SOC_IS_RAVEN(unit) ? 0x7f : 0x3f; 1306 if (soc_feature(unit, soc_feature_trunk_group_overlay)) { 1307 is_trunk = soc_L3_IPMCm_field32_get(unit, entry, Tf); 1308 mod = soc_L3_IPMCm_field32_get(unit, entry, MODULE_IDf); 1309 port_tgid = soc_L3_IPMCm_field32_get(unit, entry, PORT_NUMf); 1310 if (is_trunk) { 1311 if ((port_tgid == chk_val) && ((int)mod == SOC_MODID_MAX(unit))) { 1312 no_src_check = TRUE; 1313 } else { 1314 mod = 0; 1315 port_tgid = soc_L3_IPMCm_field32_get(unit, entry, TGIDf); 1316 } 1317 } 1318 } else { 1319 mod = soc_L3_IPMCm_field32_get(unit, entry, MODULE_IDf); 1320 port_tgid = soc_L3_IPMCm_field32_get(unit, entry, PORT_TGIDf); 1321 is_trunk = port_tgid & BCM_TGID_TRUNK_INDICATOR(unit); 1322 if ((port_tgid == chk_val) && ((int)mod == SOC_MODID_MAX(unit))) { 1323 no_src_check = TRUE; 1324 } else if (is_trunk) { 1325 port_tgid = BCM_MODIDf_TGIDf_TO_TRUNK(unit, mod, port_tgid); 1326 } 1327 } 1328 if (no_src_check) { 1329 ipmc->ts = 0; 1330 ipmc->mod_id = -1; 1331 ipmc->port_tgid = -1; 1332 ipmc->flags |= BCM_IPMC_SOURCE_PORT_NOCHECK; 1333 } else if (is_trunk) { 1334 ipmc->ts = 1; 1335 ipmc->mod_id = 0; 1336 ipmc->port_tgid = port_tgid; 1337 } else { 1338 bcm_module_t mod_in, mod_out; 1339 bcm_port_t port_in, port_out; 1340 1341 mod_in = mod; 1342 port_in = port_tgid; 1343 BCM_IF_ERROR_RETURN 1344 (_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET, 1345 mod_in, port_in, 1346 &mod_out, &port_out)); 1347 ipmc->ts = 0; 1348 ipmc->mod_id = mod_out; 1349 ipmc->port_tgid = port_out; 1350 } 1351 1352 if (ipmc->v) { 1353 if (SOC_IS_FBX(unit) && do_l3_lkup) { 1354 #if defined(BCM_FIREBOLT_SUPPORT) 1355 if (use_ipmc_l3entry) { 1356 /* use the passed in l3 info */ 1357 ipmc_l3entry = use_ipmc_l3entry; 1358 } else { 1359 /* Note: this simply picks up the first l3 info */ 1360 ipmc_l3entry = IPMC_GROUP_INFO(unit, index)->l3entry_list; 1361 if (NULL == ipmc_l3entry) { 1362 /* No entries in Multicast host table */ 1363 return BCM_E_EMPTY; 1364 } 1365 } 1366 if (ipmc_l3entry->ip6) { 1367 ipmc->flags |= BCM_IPMC_IP6; 1368 } else { 1369 ipmc->flags &= ~BCM_IPMC_IP6; 1370 } 1371 #endif /* BCM_FIREBOLT_SUPPORT */ 1372 } 1373 1374 if (SOC_IS_FBX(unit) && do_l3_lkup) { 1375 #if defined(BCM_FIREBOLT_SUPPORT) 1376 _bcm_l3_cfg_t l3cfg; 1377 sal_memset(&l3cfg, 0, sizeof(_bcm_l3_cfg_t)); 1378 1379 l3cfg.l3c_flags = BCM_L3_IPMC; 1380 l3cfg.l3c_vrf = ipmc_l3entry->l3info.vrf; 1381 if (soc_feature(unit, soc_feature_l3_sgv)) { 1382 ipmc->vid = ipmc_l3entry->l3info.vid; 1383 l3cfg.l3c_vid = ipmc_l3entry->l3info.vid; 1384 } 1385 1386 if (ipmc->flags & BCM_IPMC_HIT_CLEAR) { 1387 l3cfg.l3c_flags |= BCM_L3_HIT_CLEAR; 1388 } 1389 1390 if (ipmc->flags & BCM_IPMC_IP6) { 1391 sal_memcpy(ipmc->s_ip6_addr, &ipmc_l3entry->l3info.sip6, BCM_IP6_ADDRLEN); 1392 sal_memcpy(ipmc->mc_ip6_addr, &ipmc_l3entry->l3info.ip6, BCM_IP6_ADDRLEN); 1393 sal_memcpy(l3cfg.l3c_sip6, &ipmc_l3entry->l3info.sip6, BCM_IP6_ADDRLEN); 1394 sal_memcpy(l3cfg.l3c_ip6, &ipmc_l3entry->l3info.ip6, BCM_IP6_ADDRLEN); 1395 l3cfg.l3c_flags |= BCM_L3_IP6; 1396 BCM_IF_ERROR_RETURN(mbcm_driver[unit]->mbcm_l3_ip6_get(unit, &l3cfg)); 1397 } else { 1398 ipmc->s_ip_addr = ipmc_l3entry->l3info.src_ip_addr; 1399 ipmc->mc_ip_addr = ipmc_l3entry->l3info.ipmc_group; 1400 l3cfg.l3c_src_ip_addr = ipmc_l3entry->l3info.src_ip_addr; 1401 l3cfg.l3c_ipmc_group = ipmc_l3entry->l3info.ipmc_group; 1402 BCM_IF_ERROR_RETURN(mbcm_driver[unit]->mbcm_l3_ip4_get(unit, &l3cfg)); 1403 } 1404 if (l3cfg.l3c_flags & BCM_L3_HIT) { 1405 ipmc->flags |= BCM_IPMC_HIT; 1406 } 1407 1408 if (ipmc_l3entry->l3info.flags & BCM_L3_RPE) { 1409 ipmc->cos = ipmc_l3entry->l3info.prio; 1410 ipmc->flags |= BCM_IPMC_SETPRI; 1411 } else { 1412 ipmc->cos = -1; 1413 ipmc->flags &= ~BCM_IPMC_SETPRI; 1414 } 1415 ipmc->group = index; 1416 ipmc->lookup_class = ipmc_l3entry->l3info.lookup_class; 1417 ipmc->vrf = ipmc_l3entry->l3info.vrf; 1418 #endif /* BCM_FIREBOLT_SUPPORT */ 1419 } 1420 } 1421 1422 return BCM_E_NONE; 1423 } 1424 1425 /* 1426 * Function: 1427 * _xgs3_ipmc_read 1428 * Purpose: 1429 * Read an ipmc entry. 1430 */ 1431 1432 STATIC INLINE int 1433 _xgs3_ipmc_read(int unit, int ipmc_id, ipmc_entry_t *ipmc_entry) 1434 { 1435 int rv; 1436 1437 rv = soc_mem_read(unit, L3_IPMCm, MEM_BLOCK_ANY, ipmc_id, ipmc_entry); 1438 1439 return (rv); 1440 } 1441 1442 /* 1443 * Function: 1444 * _xgs3_ipmc_write 1445 * Purpose: 1446 * Write an ipmc entry from bcm_ipmc_addr_t struct. 1447 */ 1448 1449 STATIC int 1450 _xgs3_ipmc_write(int unit, int ipmc_id, bcm_ipmc_addr_t *ipmc) 1451 { 1452 int rv; 1453 ipmc_entry_t entry; 1454 int mod, port_tgid, is_trunk, no_src_check = FALSE; 1455 1456 BCM_IF_ERROR_RETURN 1457 (soc_mem_read(unit, L3_IPMCm, MEM_BLOCK_ANY, ipmc_id, &entry)); 1458 1459 soc_L3_IPMCm_field32_set(unit, &entry, VALIDf, ipmc->v); 1460 1461 if ((ipmc->flags & BCM_IPMC_SOURCE_PORT_NOCHECK) || 1462 (ipmc->port_tgid < 0)) { /* no source port */ 1463 no_src_check = TRUE; 1464 is_trunk = 0; 1465 mod = SOC_MODID_MAX(unit); 1466 #ifdef BCM_RAVEN_SUPPORT 1467 if (SOC_IS_RAVEN(unit)) { 1468 port_tgid = 0x7f; 1469 } else 1470 #endif 1471 { 1472 port_tgid = 0x3f; 1473 } 1474 } else if (ipmc->ts) { /* trunk source port */ 1475 is_trunk = 1; 1476 mod = 0; 1477 port_tgid = ipmc->port_tgid; 1478 } else { /* source port */ 1479 bcm_module_t mod_in, mod_out; 1480 bcm_port_t port_in, port_out; 1481 1482 mod_in = ipmc->mod_id; 1483 port_in = ipmc->port_tgid; 1484 BCM_IF_ERROR_RETURN 1485 (_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_SET, 1486 mod_in, port_in, 1487 &mod_out, &port_out)); 1488 /* Check parameters, since above is an application callback */ 1489 if (!SOC_MODID_ADDRESSABLE(unit, mod_out)) { 1490 return BCM_E_BADID; 1491 } 1492 if (!SOC_PORT_ADDRESSABLE(unit, port_out)) { 1493 return BCM_E_PORT; 1494 } 1495 is_trunk = 0; 1496 mod = mod_out; 1497 port_tgid = port_out; 1498 } 1499 1500 if (soc_feature(unit, soc_feature_trunk_group_overlay)) { 1501 if (is_trunk) { 1502 soc_L3_IPMCm_field32_set(unit, &entry, Tf, 1); 1503 soc_L3_IPMCm_field32_set(unit, &entry, TGIDf, port_tgid); 1504 } else { 1505 soc_L3_IPMCm_field32_set(unit, &entry, MODULE_IDf, mod); 1506 soc_L3_IPMCm_field32_set(unit, &entry, PORT_NUMf, port_tgid); 1507 if (no_src_check) { 1508 soc_L3_IPMCm_field32_set(unit, &entry, Tf, 1); 1509 } else { 1510 soc_L3_IPMCm_field32_set(unit, &entry, Tf, 0); 1511 } 1512 } 1513 } else { 1514 if (is_trunk) { 1515 mod = BCM_TRUNK_TO_MODIDf(unit, port_tgid); 1516 port_tgid = BCM_TRUNK_TO_TGIDf(unit, port_tgid); 1517 } 1518 soc_L3_IPMCm_field32_set(unit, &entry, MODULE_IDf, mod); 1519 soc_L3_IPMCm_field32_set(unit, &entry, PORT_TGIDf, port_tgid); 1520 } 1521 1522 rv = soc_mem_write(unit, L3_IPMCm, MEM_BLOCK_ALL, ipmc_id, &entry); 1523 1524 return (rv); 1525 } 1526 1527 /* 1528 * Function: 1529 * _xgs3_ipmc_enable 1530 * Purpose: 1531 * Enable/disable IPMC support. 1532 * Parameters: 1533 * unit - StrataSwitch PCI device unit number (driver internal). 1534 * enable - TRUE: enable IPMC support. 1535 * FALSE: disable IPMC support. 1536 * Returns: 1537 * BCM_E_XXX 1538 */ 1539 1540 STATIC int 1541 _xgs3_ipmc_enable(int unit, int enable) 1542 { 1543 int port, do_vlan; 1544 bcm_pbmp_t port_pbmp; 1545 1546 enable = enable ? 1 : 0; 1547 do_vlan = soc_property_get(unit, spn_IPMC_DO_VLAN, 1); 1548 1549 BCM_PBMP_CLEAR(port_pbmp); 1550 BCM_PBMP_ASSIGN(port_pbmp, PBMP_PORT_ALL(unit)); 1551 BCM_PBMP_OR(port_pbmp, PBMP_CMIC(unit)); 1552 1553 PBMP_ITER(port_pbmp, port) { 1554 BCM_IF_ERROR_RETURN 1555 (_bcm_esw_port_config_set(unit, port, 1556 _bcmPortIpmcV4Enable, enable)); 1557 BCM_IF_ERROR_RETURN 1558 (_bcm_esw_port_config_set(unit, port, 1559 _bcmPortIpmcV6Enable, enable)); 1560 BCM_IF_ERROR_RETURN 1561 (_bcm_esw_port_config_set(unit, port, 1562 _bcmPortIpmcVlanKey, 1563 (enable && do_vlan) ? 1 : 0)); 1564 } 1565 1566 return BCM_E_NONE; 1567 } 1568 1569 /* 1570 * Function: 1571 * bcm_fb_er_ipmc_init 1572 * Purpose: 1573 * Initialize the IPMC module and enable IPMC support. 1574 * Parameters: 1575 * unit - StrataSwitch PCI device unit number (driver internal). 1576 * Returns: 1577 * BCM_E_XXX 1578 * Notes: 1579 * This function has to be called before any other IPMC functions. 1580 */ 1581 1582 int 1583 bcm_fb_er_ipmc_init(int unit) 1584 { 1585 _bcm_esw_ipmc_t *info = IPMC_INFO(unit); 1586 1587 BCM_IF_ERROR_RETURN(bcm_fb_er_ipmc_detach(unit)); 1588 BCM_IF_ERROR_RETURN(_xgs3_ipmc_enable(unit, TRUE)); 1589 1590 IPMC_GROUP_NUM(unit) = soc_mem_index_count(unit, L3_IPMCm); 1591 1592 #ifdef BCM_BRADLEY_SUPPORT 1593 if (SOC_IS_HBX(unit)) { 1594 int ipmc_base, ipmc_size; 1595 1596 SOC_IF_ERROR_RETURN 1597 (soc_hbx_ipmc_size_get(unit, &ipmc_base, &ipmc_size)); 1598 1599 if (IPMC_GROUP_NUM(unit) > ipmc_size) { 1600 /* Reduce to fix allocated table space */ 1601 IPMC_GROUP_NUM(unit) = ipmc_size; 1602 } 1603 } 1604 #endif 1605 1606 info->ipmc_count = 0; 1607 1608 info->ipmc_group_info = 1609 sal_alloc(IPMC_GROUP_NUM(unit) * sizeof(_bcm_esw_ipmc_group_info_t), 1610 "IPMC group info"); 1611 if (info->ipmc_group_info == NULL) { 1612 return (BCM_E_MEMORY); 1613 } 1614 sal_memset(info->ipmc_group_info, 0, 1615 IPMC_GROUP_NUM(unit) * sizeof(_bcm_esw_ipmc_group_info_t)); 1616 1617 info->ipmc_initialized = TRUE; 1618 1619 return BCM_E_NONE; 1620 } 1621 1622 /* 1623 * Function: 1624 * bcm_fb_er_ipmc_detach 1625 * Purpose: 1626 * Detach the IPMC module. 1627 * Parameters: 1628 * unit - StrataSwitch PCI device unit number (driver internal). 1629 * Returns: 1630 * BCM_E_XXX 1631 */ 1632 1633 int 1634 bcm_fb_er_ipmc_detach(int unit) 1635 { 1636 _bcm_esw_ipmc_t *info = IPMC_INFO(unit); 1637 _bcm_esw_ipmc_l3entry_t *ipmc_l3entry; 1638 int i, rv; 1639 1640 if (info->ipmc_initialized) { 1641 /* Delete all IPMC entries. BCM_E_NOT_FOUND or BCM_E_FAIL may be 1642 * returned by bcm_fb_er_ipmc_delete_all since L3 module 1643 * clears L3 tables during initialization. 1644 */ 1645 rv = bcm_fb_er_ipmc_delete_all(unit); 1646 if (BCM_FAILURE(rv) && (rv != BCM_E_NOT_FOUND) && (rv != BCM_E_FAIL)) { 1647 return rv; 1648 } 1649 1650 BCM_IF_ERROR_RETURN(_xgs3_ipmc_enable(unit, FALSE)); 1651 1652 if (info->ipmc_group_info != NULL) { 1653 for (i = 0; i < IPMC_GROUP_NUM(unit); i++) { 1654 ipmc_l3entry = IPMC_GROUP_INFO(unit, i)->l3entry_list; 1655 while (ipmc_l3entry != NULL) { 1656 IPMC_GROUP_INFO(unit, i)->l3entry_list = ipmc_l3entry->next; 1657 sal_free(ipmc_l3entry); 1658 ipmc_l3entry = IPMC_GROUP_INFO(unit, i)->l3entry_list; 1659 } 1660 } 1661 sal_free(info->ipmc_group_info); 1662 info->ipmc_group_info = NULL; 1663 } 1664 1665 info->ipmc_initialized = FALSE; 1666 } 1667 1668 return BCM_E_NONE; 1669 } 1670 1671 /* 1672 * Function: 1673 * bcm_fb_er_ipmc_get 1674 * Purpose: 1675 * Get an IPMC entry by index. 1676 * Parameters: 1677 * unit - StrataSwitch PCI device unit number (driver internal). 1678 * index - The index number. 1679 * ipmc - (OUT) IPMC entry information. 1680 * Returns: 1681 * BCM_E_XXX 1682 */ 1683 1684 int 1685 bcm_fb_er_ipmc_get(int unit, int index, bcm_ipmc_addr_t *ipmc) 1686 { 1687 ipmc_entry_t ipmc_entry; 1688 int rv; 1689 int l3index = 0; 1690 1691 IPMC_INIT(unit); 1692 IPMC_ID(unit, index); 1693 1694 if (IPMC_USED_ISSET(unit, index)) { 1695 SOC_IF_ERROR_RETURN 1696 (soc_mem_read(unit, L3_IPMCm, MEM_BLOCK_ANY, index, &ipmc_entry)); 1697 1698 rv = _xgs3_ipmc_info_get(unit, l3index, index, TRUE, ipmc, &ipmc_entry, 1699 1, NULL); 1700 ipmc->group = index; 1701 1702 return rv; 1703 } 1704 1705 return BCM_E_NOT_FOUND; 1706 } 1707 1708 /* 1709 * Function: 1710 * _bcm_fb_er_ipmc_find 1711 * Purpose: 1712 * Look up an IPMC entry by sip, mcip and vid 1713 * Parameters: 1714 * unit - StrataSwitch PCI device unit number (driver internal). 1715 * ipmc - (IN) IPMC entry information. 1716 * l3cfg - (OUT) The index number. 1717 * Returns: 1718 * BCM_E_XXX 1719 */ 1720 1721 STATIC int 1722 _bcm_fb_er_ipmc_find(int unit, bcm_ipmc_addr_t *ipmc, _bcm_l3_cfg_t *l3cfg) 1723 { 1724 if (SOC_IS_FBX(unit)) { 1725 sal_memset(l3cfg, 0, sizeof(_bcm_l3_cfg_t)); 1726 l3cfg->l3c_vid = ipmc->vid; 1727 l3cfg->l3c_flags = BCM_L3_IPMC; 1728 l3cfg->l3c_vrf = ipmc->vrf; 1729 1730 if (ipmc->flags & BCM_IPMC_HIT_CLEAR) { 1731 l3cfg->l3c_flags |= BCM_L3_HIT_CLEAR; 1732 } 1733 1734 if (ipmc->flags & BCM_IPMC_IP6) { 1735 sal_memcpy(l3cfg->l3c_sip6, ipmc->s_ip6_addr, BCM_IP6_ADDRLEN); 1736 sal_memcpy(l3cfg->l3c_ip6, ipmc->mc_ip6_addr, BCM_IP6_ADDRLEN); 1737 l3cfg->l3c_flags |= BCM_L3_IP6; 1738 BCM_IF_ERROR_RETURN(mbcm_driver[unit]->mbcm_l3_ip6_get(unit, l3cfg)); 1739 } else { 1740 l3cfg->l3c_src_ip_addr = ipmc->s_ip_addr; 1741 l3cfg->l3c_ipmc_group = ipmc->mc_ip_addr; 1742 BCM_IF_ERROR_RETURN(mbcm_driver[unit]->mbcm_l3_ip4_get(unit, l3cfg)); 1743 } 1744 } 1745 1746 return BCM_E_NONE; 1747 } 1748 1749 /* 1750 * Function: 1751 * bcm_fb_er_ipmc_lookup 1752 * Purpose: 1753 * Look up an IPMC entry by sip, mcip and vid 1754 * Parameters: 1755 * unit - StrataSwitch PCI device unit number (driver internal). 1756 * index - (OUT) The index number. 1757 * ipmc - (IN, OUT) IPMC entry information. 1758 * Returns: 1759 * BCM_E_XXX 1760 */ 1761 1762 int 1763 bcm_fb_er_ipmc_lookup(int unit, int *index, bcm_ipmc_addr_t *ipmc) 1764 { 1765 ipmc_entry_t ipmc_entry; 1766 _bcm_l3_cfg_t l3cfg; 1767 int l3_id, ipmc_id; 1768 1769 IPMC_INIT(unit); 1770 1771 BCM_IF_ERROR_RETURN( 1772 _bcm_fb_er_ipmc_find(unit, ipmc, &l3cfg)); 1773 1774 ipmc_id = SOC_IS_FBX(unit) ? l3cfg.l3c_ipmc_ptr : ipmc->group; 1775 BCM_IF_ERROR_RETURN 1776 (_xgs3_ipmc_read(unit, ipmc_id, &ipmc_entry)); 1777 1778 l3_id = SOC_IS_FBX(unit) ? l3cfg.l3c_hw_index : ipmc->group; 1779 BCM_IF_ERROR_RETURN 1780 (_xgs3_ipmc_info_get(unit, l3_id, ipmc_id, FALSE, ipmc, &ipmc_entry, 1781 0, NULL)); 1782 if (SOC_IS_FBX(unit) && ipmc->v) { 1783 ipmc->group = l3cfg.l3c_ipmc_ptr; 1784 ipmc->lookup_class = l3cfg.l3c_lookup_class; 1785 if (l3cfg.l3c_flags & BCM_L3_HIT) { 1786 ipmc->flags |= BCM_IPMC_HIT; 1787 } 1788 if (l3cfg.l3c_flags & BCM_L3_RPE) { 1789 ipmc->cos = l3cfg.l3c_prio; 1790 ipmc->flags |= BCM_IPMC_SETPRI; 1791 } else { 1792 ipmc->cos = -1; 1793 ipmc->flags &= ~BCM_IPMC_SETPRI; 1794 } 1795 } 1796 if (index != NULL) { 1797 *index = SOC_IS_FBX(unit) ? l3cfg.l3c_ipmc_ptr : ipmc->group; 1798 } 1799 1800 return BCM_E_NONE; 1801 } 1802 1803 #if defined(BCM_FIREBOLT_SUPPORT) 1804 1805 /* 1806 * Function: 1807 * _bcm_fb_ipmc_add 1808 * Purpose: 1809 * Add a new entry to the L3 table. 1810 * Parameters: 1811 * unit - (IN) BCM device number. 1812 * ipmc - (IN)IPMC entry information. 1813 * Returns: 1814 * BCM_E_XXX 1815 */ 1816 1817 int 1818 _bcm_fb_ipmc_add(int unit, bcm_ipmc_addr_t *ipmc) 1819 { 1820 _bcm_l3_cfg_t l3cfg; /* L3 ipmc entry. */ 1821 int rv; /* Operation return status. */ 1822 1823 sal_memset(&l3cfg, 0, sizeof(_bcm_l3_cfg_t)); 1824 1825 l3cfg.l3c_vid = ipmc->vid; 1826 l3cfg.l3c_flags = BCM_L3_IPMC; 1827 l3cfg.l3c_vrf = ipmc->vrf; 1828 l3cfg.l3c_lookup_class = ipmc->lookup_class; 1829 if (ipmc->flags & BCM_IPMC_SETPRI) { 1830 l3cfg.l3c_flags |= BCM_L3_RPE; 1831 l3cfg.l3c_prio = ipmc->cos; 1832 } 1833 if (ipmc->flags & BCM_IPMC_IP6) { 1834 if (!BCM_IP6_MULTICAST(ipmc->mc_ip6_addr)) { 1835 return BCM_E_PARAM; 1836 } 1837 sal_memcpy(l3cfg.l3c_sip6, ipmc->s_ip6_addr, BCM_IP6_ADDRLEN); 1838 sal_memcpy(l3cfg.l3c_ip6, ipmc->mc_ip6_addr, BCM_IP6_ADDRLEN); 1839 l3cfg.l3c_flags |= BCM_L3_IP6; 1840 } else { 1841 if (!BCM_IP4_MULTICAST(ipmc->mc_ip_addr)) { 1842 return BCM_E_PARAM; 1843 } 1844 l3cfg.l3c_src_ip_addr = ipmc->s_ip_addr; 1845 l3cfg.l3c_ipmc_group = ipmc->mc_ip_addr; 1846 } 1847 1848 l3cfg.l3c_ipmc_ptr = ipmc->group; 1849 l3cfg.l3c_flags |= BCM_L3_HIT; 1850 1851 if (soc_feature(unit, soc_feature_l3_sgv)) { 1852 l3cfg.l3c_vid = ipmc->vid; 1853 } 1854 1855 if (ipmc->flags & BCM_IPMC_REPLACE) { 1856 l3cfg.l3c_flags |= BCM_L3_REPLACE; 1857 } 1858 1859 /* Write mcast entry to hw. */ 1860 l3cfg.l3c_hw_index = BCM_XGS3_L3_INVALID_INDEX;/* Add /No overrite. */ 1861 1862 if (ipmc->flags & BCM_IPMC_IP6) { 1863 rv = mbcm_driver[unit]->mbcm_l3_ip6_add(unit, &l3cfg); 1864 } else { 1865 rv = mbcm_driver[unit]->mbcm_l3_ip4_add(unit, &l3cfg); 1866 } 1867 1868 if (BCM_SUCCESS(rv)) { 1869 rv = _bcm_xgs3_ipmc_l3entry_list_add(unit, ipmc->group, 1870 &l3cfg); 1871 } 1872 1873 return (rv); 1874 } 1875 1876 /* 1877 * Function: 1878 * _bcm_fb_ipmc_del 1879 * Purpose: 1880 * Remove an entry from the L3 table. 1881 * Parameters: 1882 * unit - (IN) BCM device number. 1883 * ipmc - (IN)IPMC entry information. 1884 * modify_l3entry_list - (IN) Controls whether to modify IPMC group's 1885 * L3 entry list. 1886 * Returns: 1887 * BCM_E_XXX 1888 */ 1889 1890 int 1891 _bcm_fb_ipmc_del(int unit, bcm_ipmc_addr_t *ipmc, int modify_l3entry_list) 1892 { 1893 _bcm_l3_cfg_t l3cfg; /* L3 ipmc entry. */ 1894 int rv; /* Operation return status. */ 1895 int ipmc_index = 0; 1896 1897 sal_memset(&l3cfg, 0, sizeof(_bcm_l3_cfg_t)); 1898 1899 l3cfg.l3c_vid = ipmc->vid; 1900 l3cfg.l3c_flags = BCM_L3_IPMC; 1901 l3cfg.l3c_vrf = ipmc->vrf; 1902 1903 if (ipmc->flags & BCM_IPMC_IP6) { 1904 if (!BCM_IP6_MULTICAST(ipmc->mc_ip6_addr)) { 1905 return BCM_E_PARAM; 1906 } 1907 sal_memcpy(l3cfg.l3c_sip6, ipmc->s_ip6_addr, BCM_IP6_ADDRLEN); 1908 sal_memcpy(l3cfg.l3c_ip6, ipmc->mc_ip6_addr, BCM_IP6_ADDRLEN); 1909 l3cfg.l3c_flags |= BCM_L3_IP6; 1910 } else { 1911 if (!BCM_IP4_MULTICAST(ipmc->mc_ip_addr)) { 1912 return BCM_E_PARAM; 1913 } 1914 l3cfg.l3c_src_ip_addr = ipmc->s_ip_addr; 1915 l3cfg.l3c_ipmc_group = ipmc->mc_ip_addr; 1916 } 1917 1918 if (soc_feature(unit, soc_feature_l3_sgv)) { 1919 l3cfg.l3c_vid = ipmc->vid; 1920 } 1921 1922 if (ipmc->flags & BCM_IPMC_IP6) { 1923 rv = mbcm_driver[unit]->mbcm_l3_ip6_get(unit, &l3cfg); 1924 if (BCM_SUCCESS(rv)) { 1925 ipmc_index = l3cfg.l3c_ipmc_ptr; 1926 rv = mbcm_driver[unit]->mbcm_l3_ip6_delete(unit, &l3cfg); 1927 } 1928 } else { 1929 rv = mbcm_driver[unit]->mbcm_l3_ip4_get(unit, &l3cfg); 1930 if (BCM_SUCCESS(rv)) { 1931 ipmc_index = l3cfg.l3c_ipmc_ptr; 1932 rv = mbcm_driver[unit]->mbcm_l3_ip4_delete(unit, &l3cfg); 1933 } 1934 } 1935 1936 if (BCM_SUCCESS(rv) && modify_l3entry_list) { 1937 rv = _bcm_xgs3_ipmc_l3entry_list_del(unit, ipmc_index, 1938 &l3cfg); 1939 } 1940 1941 return (rv); 1942 } 1943 /* 1944 * Function: 1945 * _bcm_fb_ipmc_replace 1946 * Purpose: 1947 * Overwrite an entry in the IPMC table. 1948 * Parameters: 1949 * unit - StrataSwitch PCI device unit number (driver internal). 1950 * ipmc - New IPMC entry information. 1951 * old_l3cfg - Old IPMC configuration information. 1952 * Returns: 1953 * BCM_E_XXX 1954 */ 1955 STATIC int 1956 _bcm_fb_ipmc_replace(int unit, bcm_ipmc_addr_t *ipmc, _bcm_l3_cfg_t *old_l3cfg) 1957 { 1958 _bcm_l3_cfg_t l3cfg; 1959 int old_ipmc_index; 1960 1961 l3cfg = *old_l3cfg; 1962 old_ipmc_index = l3cfg.l3c_ipmc_ptr; 1963 1964 if (!(ipmc->flags & BCM_IPMC_SETPRI)) { 1965 l3cfg.l3c_flags &= ~BCM_L3_RPE; 1966 l3cfg.l3c_prio = 0; 1967 } else { 1968 l3cfg.l3c_flags |= BCM_L3_RPE; 1969 l3cfg.l3c_prio = ipmc->cos; 1970 } 1971 l3cfg.l3c_ipmc_ptr = ipmc->group; 1972 1973 BCM_IF_ERROR_RETURN 1974 (bcm_xgs3_l3_replace(unit, &l3cfg)); 1975 1976 if (old_ipmc_index != ipmc->group) { 1977 BCM_IF_ERROR_RETURN 1978 (_bcm_xgs3_ipmc_l3entry_list_del(unit, old_ipmc_index, 1979 &l3cfg)); 1980 BCM_IF_ERROR_RETURN 1981 (_bcm_xgs3_ipmc_l3entry_list_add(unit, ipmc->group, 1982 &l3cfg)); 1983 } else { 1984 BCM_IF_ERROR_RETURN 1985 (_bcm_xgs3_ipmc_l3entry_list_update(unit, old_ipmc_index, 1986 &l3cfg)); 1987 } 1988 1989 return BCM_E_NONE; 1990 } 1991 #endif /* BCM_FIREBOLT_SUPPORT */ 1992 1993 /* 1994 * Function: 1995 * _bcm_xgs3_ipmc_src_port_compare 1996 * Purpose: 1997 * Compare the IPMC source port parameters. 1998 * Parameters: 1999 * unit - StrataSwitch PCI device unit number (driver internal). 2000 * ipmc_index - IPMC index to be shared. 2001 * ipmc - IPMC address entry info. 2002 * match - (OUT) Match indication. 2003 * Returns: 2004 * BCM_E_XXX 2005 */ 2006 STATIC int 2007 _bcm_xgs3_ipmc_src_port_compare(int unit, int ipmc_index, 2008 bcm_ipmc_addr_t *ipmc, int *match) 2009 { 2010 ipmc_entry_t entry; 2011 int t_f, tgid_f, mod_f, port_f, port_tgid_f; 2012 int no_src_check, is_trunk, tgid, mod, port; 2013 2014 BCM_IF_ERROR_RETURN 2015 (soc_mem_read(unit, L3_IPMCm, MEM_BLOCK_ANY, ipmc_index, &entry)); 2016 2017 no_src_check = FALSE; 2018 is_trunk = 0; 2019 tgid = -1; 2020 mod = -1; 2021 port = -1; 2022 if (soc_feature(unit, soc_feature_trunk_group_overlay)) { 2023 t_f = soc_L3_IPMCm_field32_get(unit, &entry, Tf); 2024 tgid_f = soc_L3_IPMCm_field32_get(unit, &entry, TGIDf); 2025 mod_f = soc_L3_IPMCm_field32_get(unit, &entry, MODULE_IDf); 2026 port_f = soc_L3_IPMCm_field32_get(unit, &entry, PORT_NUMf); 2027 2028 if ((t_f == 1) && (mod_f == SOC_MODID_MAX(unit)) && 2029 (port_f == (SOC_IS_RAVEN(unit) ? 0x7f : 0x3f))) { 2030 no_src_check = TRUE; 2031 } else if (t_f == 1) { 2032 is_trunk = 1; 2033 tgid = tgid_f; 2034 } else { 2035 mod = mod_f; 2036 port = port_f; 2037 } 2038 } else { 2039 mod_f = soc_L3_IPMCm_field32_get(unit, &entry, MODULE_IDf); 2040 port_tgid_f = soc_L3_IPMCm_field32_get(unit, &entry, PORT_TGIDf); 2041 2042 if ((mod_f == SOC_MODID_MAX(unit)) && 2043 (port_tgid_f == (SOC_IS_RAVEN(unit) ? 0x7f : 0x3f))) { 2044 no_src_check = TRUE; 2045 } else if (BCM_TGID_TRUNK_INDICATOR(unit) & port_tgid_f) { 2046 is_trunk = 1; 2047 tgid = BCM_MODIDf_TGIDf_TO_TRUNK(unit, mod_f, port_tgid_f); 2048 } else { 2049 mod = mod_f; 2050 port = port_tgid_f; 2051 } 2052 } 2053 2054 *match = FALSE; 2055 if ((ipmc->flags & BCM_IPMC_SOURCE_PORT_NOCHECK) || 2056 (ipmc->port_tgid < 0)) { /* no source port */ 2057 if (no_src_check) { 2058 *match = TRUE; 2059 } 2060 } else if (ipmc->ts) { /* trunk source port */ 2061 if (is_trunk && (tgid == ipmc->port_tgid)) { 2062 *match = TRUE; 2063 } 2064 } else { /* source port */ 2065 bcm_module_t mod_in, mod_out; 2066 bcm_port_t port_in, port_out; 2067 2068 mod_in = ipmc->mod_id; 2069 port_in = ipmc->port_tgid; 2070 BCM_IF_ERROR_RETURN 2071 (_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_SET, 2072 mod_in, port_in, 2073 &mod_out, &port_out)); 2074 /* Check parameters, since above is an application callback */ 2075 if (!SOC_MODID_ADDRESSABLE(unit, mod_out)) { 2076 return BCM_E_BADID; 2077 } 2078 if (!SOC_PORT_ADDRESSABLE(unit, port_out)) { 2079 return BCM_E_PORT; 2080 } 2081 2082 if ((mod == mod_out) && (port == port_out)) { 2083 *match = TRUE; 2084 } 2085 } 2086 2087 return BCM_E_NONE; 2088 } 2089 2090 /* 2091 * Function: 2092 * _bcm_xgs3_ipmc_src_port_consistency_check 2093 * Purpose: 2094 * When multiple IPMC address entries share the same IPMC 2095 * index, they must also have the same port parameter 2096 * for the purpose of IPMC source port checking. This 2097 * procedure makes sure this is the case. 2098 * Parameters: 2099 * unit - StrataSwitch PCI device unit number (driver internal). 2100 * ipmc_index - IPMC index to be shared. 2101 * ipmc - IPMC address entry info. 2102 * already_used - Indicates if the given IPMC address entry is 2103 * already using the ipmc index to be shared. 2104 * Returns: 2105 * BCM_E_XXX 2106 */ 2107 STATIC int 2108 _bcm_xgs3_ipmc_src_port_consistency_check(int unit, int ipmc_index, 2109 bcm_ipmc_addr_t *ipmc, int already_used, int *need_write) 2110 { 2111 int l3entry_list_size = 0; 2112 int match; 2113 2114 *need_write = TRUE; 2115 2116 if (SOC_IS_FBX(unit)) { 2117 #if defined(BCM_FIREBOLT_SUPPORT) 2118 BCM_IF_ERROR_RETURN(_bcm_xgs3_ipmc_l3entry_list_size_get(unit, 2119 ipmc_index, &l3entry_list_size)); 2120 #endif /* BCM_FIREBOLT_SUPPORT */ 2121 } 2122 2123 if ((already_used && (l3entry_list_size > 1)) || 2124 (!already_used && (l3entry_list_size > 0))) { 2125 /* If there are IPMC address entries other than the given IPMC address 2126 * entry that are pointing the given ipmc index, verify that the IPMC 2127 * source port check parameters are the same. If not, the ipmc index 2128 * cannot be shared. 2129 */ 2130 BCM_IF_ERROR_RETURN(_bcm_xgs3_ipmc_src_port_compare(unit, 2131 ipmc_index, ipmc, &match)); 2132 if (!match) { 2133 return BCM_E_PARAM; 2134 } 2135 2136 *need_write = FALSE; 2137 } 2138 2139 return BCM_E_NONE; 2140 } 2141 2142 /* 2143 * Function: 2144 * bcm_fb_er_ipmc_add 2145 * Purpose: 2146 * Add a new entry to the IPMC table. 2147 * Parameters: 2148 * unit - StrataSwitch PCI device unit number (driver internal). 2149 * ipmc - IPMC entry information. 2150 * Returns: 2151 * BCM_E_XXX 2152 */ 2153 2154 int 2155 bcm_fb_er_ipmc_add(int unit, bcm_ipmc_addr_t *ipmc) 2156 { 2157 _bcm_l3_cfg_t l3cfg; 2158 int old_ipmc_index; 2159 int new_entry, rv, need_write; 2160 2161 IPMC_INIT(unit); 2162 IPMC_ID(unit, ipmc->group); 2163 2164 if (!IPMC_USED_ISSET(unit, ipmc->group)) { 2165 return BCM_E_PARAM; 2166 } 2167 2168 /* Check if IPMC entry already exists. 2169 * In case of BCM_IPMC_REPLACE flag being set, 2170 * if entry is already present, the entry will be replaced, 2171 * else new entry will be created. This is the expected behaviour 2172 */ 2173 rv = _bcm_fb_er_ipmc_find(unit, ipmc, &l3cfg); 2174 old_ipmc_index = SOC_IS_FBX(unit) ? l3cfg.l3c_ipmc_ptr : ipmc->group; 2175 if (BCM_SUCCESS(rv)) { 2176 if (!(ipmc->flags & BCM_IPMC_REPLACE)) { 2177 return (BCM_E_EXISTS); 2178 } else { 2179 new_entry = FALSE; 2180 } 2181 } else { 2182 /* Return if error occured. */ 2183 if (rv != BCM_E_NOT_FOUND) { 2184 return (rv); 2185 } 2186 new_entry = TRUE; 2187 } 2188 2189 if (new_entry) { 2190 BCM_IF_ERROR_RETURN(_bcm_xgs3_ipmc_src_port_consistency_check(unit, 2191 ipmc->group, ipmc, 0, &need_write)); 2192 2193 /* Increment the reference count of the given ipmc_index. */ 2194 BCM_IF_ERROR_RETURN(bcm_xgs3_ipmc_id_alloc(unit, ipmc->group)); 2195 } else { 2196 if (ipmc->group != old_ipmc_index) { 2197 BCM_IF_ERROR_RETURN 2198 (_bcm_xgs3_ipmc_src_port_consistency_check(unit, 2199 ipmc->group, 2200 ipmc, 0, &need_write)); 2201 /* Increment the reference count of the given ipmc_index. */ 2202 BCM_IF_ERROR_RETURN(bcm_xgs3_ipmc_id_alloc(unit, ipmc->group)); 2203 2204 /* Decrement the reference count of the old ipmc_index. */ 2205 BCM_IF_ERROR_RETURN(bcm_xgs3_ipmc_id_free(unit, old_ipmc_index)); 2206 if (!IPMC_USED_ISSET(unit, old_ipmc_index)) { 2207 /* Reference count should not be zero yet. */ 2208 return BCM_E_INTERNAL; 2209 } 2210 } else { 2211 BCM_IF_ERROR_RETURN 2212 (_bcm_xgs3_ipmc_src_port_consistency_check(unit, 2213 ipmc->group, 2214 ipmc, 1, &need_write)); 2215 } 2216 } 2217 2218 ipmc->v = (ipmc->flags & BCM_IPMC_ADD_DISABLED) ? 0 : 1; 2219 2220 if (new_entry) { 2221 if (need_write) { 2222 /* Write L3_IPMC table entry. */ 2223 rv = _xgs3_ipmc_write(unit, ipmc->group, ipmc); 2224 if (BCM_FAILURE(rv)) { 2225 bcm_xgs3_ipmc_id_free(unit, ipmc->group); 2226 return (rv); 2227 } 2228 } 2229 2230 /* Add new L3 table entry */ 2231 if (SOC_IS_FBX(unit)) { 2232 #if defined(BCM_FIREBOLT_SUPPORT) 2233 rv = _bcm_fb_ipmc_add(unit, ipmc); 2234 #endif /* BCM_FIREBOLT_SUPPORT */ 2235 } 2236 if (BCM_FAILURE(rv)) { 2237 bcm_xgs3_ipmc_id_free(unit, ipmc->group); 2238 if (!IPMC_USED_ISSET(unit, ipmc->group)) { 2239 /* Reference count should not be zero yet. */ 2240 return BCM_E_INTERNAL; 2241 } 2242 return (rv); 2243 } 2244 } else { 2245 if (need_write) { 2246 /* Write L3_IPMC table entry. */ 2247 rv = _xgs3_ipmc_write(unit, ipmc->group, ipmc); 2248 if (BCM_FAILURE(rv)) { 2249 if (SOC_IS_FBX(unit)) { 2250 #if defined(BCM_FIREBOLT_SUPPORT) 2251 _bcm_fb_ipmc_del(unit, ipmc, TRUE); 2252 #endif /* BCM_FIREBOLT_SUPPORT */ 2253 } 2254 bcm_xgs3_ipmc_id_free(unit, ipmc->group); 2255 return (rv); 2256 } 2257 } 2258 2259 /* Update existing IPMC entry */ 2260 rv = _bcm_fb_ipmc_replace(unit, ipmc, &l3cfg); 2261 if (BCM_FAILURE(rv)) { 2262 if (SOC_IS_FBX(unit)) { 2263 #if defined(BCM_FIREBOLT_SUPPORT) 2264 _bcm_fb_ipmc_del(unit, ipmc, TRUE); 2265 #endif /* BCM_FIREBOLT_SUPPORT */ 2266 } 2267 bcm_xgs3_ipmc_id_free(unit, ipmc->group); 2268 return rv; 2269 } 2270 } 2271 2272 return BCM_E_NONE; 2273 } 2274 2275 /* 2276 * Function: 2277 * bcm_fb_er_ipmc_put 2278 * Purpose: 2279 * Overwrite an entry in the IPMC table. 2280 * Parameters: 2281 * unit - StrataSwitch PCI device unit number (driver internal). 2282 * index - Table index to overwrite. 2283 * data - IPMC entry information. 2284 * Returns: 2285 * BCM_E_XXX 2286 */ 2287 2288 int 2289 bcm_fb_er_ipmc_put(int unit, int index, bcm_ipmc_addr_t *ipmc) 2290 { 2291 IPMC_INIT(unit); 2292 IPMC_ID(unit, index); 2293 2294 BCM_IF_ERROR_RETURN(_xgs3_ipmc_write(unit, index, ipmc)); 2295 2296 if (SOC_IS_FBX(unit)) { 2297 #if defined(BCM_FIREBOLT_SUPPORT) 2298 _bcm_l3_cfg_t l3cfg; 2299 2300 sal_memset(&l3cfg, 0, sizeof(_bcm_l3_cfg_t)); 2301 l3cfg.l3c_vid = ipmc->vid; 2302 l3cfg.l3c_flags = BCM_L3_IPMC; 2303 l3cfg.l3c_vrf = ipmc->vrf; 2304 l3cfg.l3c_lookup_class = ipmc->lookup_class; 2305 if (ipmc->flags & BCM_IPMC_IP6) { 2306 sal_memcpy(l3cfg.l3c_sip6, ipmc->s_ip6_addr, BCM_IP6_ADDRLEN); 2307 sal_memcpy(l3cfg.l3c_ip6, ipmc->mc_ip6_addr, BCM_IP6_ADDRLEN); 2308 l3cfg.l3c_flags |= BCM_L3_IP6; 2309 BCM_IF_ERROR_RETURN 2310 (mbcm_driver[unit]->mbcm_l3_ip6_get(unit, &l3cfg)); 2311 } else { 2312 l3cfg.l3c_src_ip_addr = ipmc->s_ip_addr; 2313 l3cfg.l3c_ipmc_group = ipmc->mc_ip_addr; 2314 BCM_IF_ERROR_RETURN 2315 (mbcm_driver[unit]->mbcm_l3_ip4_get(unit, &l3cfg)); 2316 } 2317 2318 return _bcm_fb_ipmc_replace(unit, ipmc, &l3cfg); 2319 #endif /* BCM_FIREBOLT_SUPPORT */ 2320 } 2321 2322 return BCM_E_NONE; 2323 } 2324 2325 /* 2326 * Function: 2327 * _bcm_fb_er_ipmc_delete 2328 * Purpose: 2329 * Delete an entry from the IPMC table. 2330 * Parameters: 2331 * unit - StrataSwitch PCI device unit number (driver internal). 2332 * data - IPMC entry information. 2333 * modify_l3entry_list - Control whether to modify IPMC group's linked 2334 * list of L3 entries. 2335 * Returns: 2336 * BCM_E_XXX 2337 * Notes: 2338 * If BCM_IPMC_KEEP_ENTRY is true, the entry valid bit is cleared 2339 * but the entry is not deleted from the table. 2340 */ 2341 2342 STATIC int 2343 _bcm_fb_er_ipmc_delete(int unit, bcm_ipmc_addr_t *ipmc, int modify_l3entry_list) 2344 { 2345 int ipmc_id; 2346 _bcm_l3_cfg_t l3cfg; 2347 2348 IPMC_INIT(unit); 2349 2350 if (SOC_IS_FBX(unit)) { 2351 #if defined(BCM_FIREBOLT_SUPPORT) 2352 sal_memset(&l3cfg, 0, sizeof(_bcm_l3_cfg_t)); 2353 l3cfg.l3c_vid = ipmc->vid; 2354 l3cfg.l3c_flags = BCM_L3_IPMC; 2355 l3cfg.l3c_vrf = ipmc->vrf; 2356 if (ipmc->flags & BCM_IPMC_IP6) { 2357 sal_memcpy(l3cfg.l3c_sip6, ipmc->s_ip6_addr, BCM_IP6_ADDRLEN); 2358 sal_memcpy(l3cfg.l3c_ip6, ipmc->mc_ip6_addr, BCM_IP6_ADDRLEN); 2359 l3cfg.l3c_flags |= BCM_L3_IP6; 2360 BCM_IF_ERROR_RETURN( 2361 mbcm_driver[unit]->mbcm_l3_ip6_get(unit, &l3cfg)); 2362 } else { 2363 l3cfg.l3c_src_ip_addr = ipmc->s_ip_addr; 2364 l3cfg.l3c_ipmc_group = ipmc->mc_ip_addr; 2365 BCM_IF_ERROR_RETURN( 2366 mbcm_driver[unit]->mbcm_l3_ip4_get(unit, &l3cfg)); 2367 } 2368 #endif /* BCM_FIREBOLT_SUPPORT */ 2369 } 2370 ipmc_id = SOC_IS_FBX(unit) ? l3cfg.l3c_ipmc_ptr : ipmc->group; 2371 2372 if (!(ipmc->flags & BCM_IPMC_KEEP_ENTRY)) { 2373 2374 if (SOC_IS_FBX(unit)) { 2375 #if defined(BCM_FIREBOLT_SUPPORT) 2376 BCM_IF_ERROR_RETURN(_bcm_fb_ipmc_del(unit, ipmc, modify_l3entry_list)); 2377 #endif /* BCM_FIREBOLT_SUPPORT */ 2378 } 2379 2380 bcm_xgs3_ipmc_id_free(unit, ipmc_id); 2381 if (!IPMC_USED_ISSET(unit, ipmc_id)) { 2382 /* Reference count should not be zero yet. */ 2383 return BCM_E_INTERNAL; 2384 } 2385 } 2386 2387 return BCM_E_NONE; 2388 } 2389 2390 /* 2391 * Function: 2392 * bcm_fb_er_ipmc_delete 2393 * Purpose: 2394 * Delete an entry from the IPMC table. 2395 * Parameters: 2396 * unit - StrataSwitch PCI device unit number (driver internal). 2397 * data - IPMC entry information. 2398 * Returns: 2399 * BCM_E_XXX 2400 * Notes: 2401 * If BCM_IPMC_KEEP_ENTRY is true, the entry valid bit is cleared 2402 * but the entry is not deleted from the table. 2403 */ 2404 2405 int 2406 bcm_fb_er_ipmc_delete(int unit, bcm_ipmc_addr_t *ipmc) 2407 { 2408 return _bcm_fb_er_ipmc_delete(unit, ipmc, TRUE); 2409 } 2410 2411 /* 2412 * Function: 2413 * bcm_fb_er_ipmc_delete_all 2414 * Purpose: 2415 * Delete all entries from the IPMC table. 2416 * Parameters: 2417 * unit - StrataSwitch PCI device unit number (driver internal). 2418 * Returns: 2419 * BCM_E_XXX 2420 */ 2421 2422 int 2423 bcm_fb_er_ipmc_delete_all(int unit) 2424 { 2425 _bcm_esw_ipmc_l3entry_t *ipmc_l3entry; 2426 int rv = BCM_E_NONE, i; 2427 #if defined(BCM_FIREBOLT_SUPPORT) 2428 _bcm_l3_cfg_t l3cfg; 2429 #endif /* BCM_FIREBOLT_SUPPORT */ 2430 2431 IPMC_INIT(unit); 2432 2433 IPMC_LOCK(unit); 2434 for (i = 0; i < IPMC_GROUP_NUM(unit); i++) { 2435 if (IPMC_USED_ISSET(unit, i)) { 2436 ipmc_l3entry = IPMC_GROUP_INFO(unit, i)->l3entry_list; 2437 while (ipmc_l3entry != NULL) { 2438 if (SOC_IS_FBX(unit)) { 2439 #if defined(BCM_FIREBOLT_SUPPORT) 2440 sal_memset(&l3cfg, 0, sizeof(_bcm_l3_cfg_t)); 2441 l3cfg.l3c_vid = ipmc_l3entry->l3info.vid; 2442 l3cfg.l3c_flags = BCM_L3_IPMC; 2443 l3cfg.l3c_vrf = ipmc_l3entry->l3info.vrf; 2444 if (ipmc_l3entry->l3info.flags & BCM_L3_IP6) { 2445 sal_memcpy(l3cfg.l3c_sip6, ipmc_l3entry->l3info.sip6, BCM_IP6_ADDRLEN); 2446 sal_memcpy(l3cfg.l3c_ip6, ipmc_l3entry->l3info.ip6, BCM_IP6_ADDRLEN); 2447 l3cfg.l3c_flags |= BCM_L3_IP6; 2448 } else { 2449 l3cfg.l3c_src_ip_addr = ipmc_l3entry->l3info.src_ip_addr; 2450 l3cfg.l3c_ipmc_group = ipmc_l3entry->l3info.ip_addr; 2451 } 2452 rv = bcm_xgs3_l3_del(unit, &l3cfg); 2453 if (BCM_FAILURE(rv)) { 2454 IPMC_UNLOCK(unit); 2455 return rv; 2456 } 2457 #endif /* BCM_FIREBOLT_SUPPORT */ 2458 } 2459 IPMC_GROUP_INFO(unit, i)->l3entry_list = ipmc_l3entry->next; 2460 sal_free(ipmc_l3entry); 2461 ipmc_l3entry = IPMC_GROUP_INFO(unit, i)->l3entry_list; 2462 } 2463 2464 /* For IPMC groups that have non-zero reference counts, 2465 * decrease reference count to 1, meaning the IPMC group 2466 * is only referenced by bcm_multicast_egress APIs. 2467 */ 2468 IPMC_USED_ONE(unit, i); 2469 } 2470 } 2471 2472 IPMC_UNLOCK(unit); 2473 2474 return rv; 2475 } 2476 2477 2478 /* 2479 * Function: 2480 * bcm_xgs3_ipmc_age 2481 * Purpose: 2482 * Age out the ipmc entry by clearing the HIT bit when appropriate, 2483 * the ipmc entry itself is removed if HIT bit is not set. 2484 * Parameters: 2485 * unit - (IN) BCM device number. 2486 * flags - (IN) The criteria used to age out ipmc table. 2487 * IPv6/IPv4 2488 * age_cb - (IN) Call back routine. 2489 * user_data - (IN) User provided cookie for callback. 2490 * Returns: 2491 * BCM_E_XXX 2492 */ 2493 int 2494 bcm_xgs3_ipmc_age(int unit, uint32 flags, bcm_ipmc_traverse_cb age_cb, 2495 void *user_data) 2496 { 2497 int idx; /* Ipmc table iteration index. */ 2498 bcm_ipmc_addr_t entry; /* Ipmc entry iterator. */ 2499 int rv = BCM_E_NONE; /* Operation return status. */ 2500 ipmc_entry_t ipmc_entry; 2501 _bcm_esw_ipmc_l3entry_t *ipmc_l3entry; 2502 _bcm_esw_ipmc_l3entry_t *prev_ipmc_l3entry = NULL; 2503 int l3index = 0; 2504 2505 IPMC_INIT(unit); 2506 IPMC_LOCK(unit); 2507 2508 for (idx = 0; idx < IPMC_GROUP_NUM(unit); idx++) { 2509 if (IPMC_USED_ISSET(unit, idx)) { 2510 2511 rv = soc_mem_read(unit, L3_IPMCm, MEM_BLOCK_ANY, idx, &ipmc_entry); 2512 if (BCM_FAILURE(rv)) { 2513 goto age_done; 2514 } 2515 2516 ipmc_l3entry = IPMC_GROUP_INFO(unit, idx)->l3entry_list; 2517 while (ipmc_l3entry != NULL) { 2518 sal_memset(&entry, 0, sizeof(bcm_ipmc_addr_t)); 2519 rv = _xgs3_ipmc_info_get(unit, l3index, idx, TRUE, &entry, 2520 &ipmc_entry, 1, ipmc_l3entry); 2521 if (BCM_FAILURE(rv)) { 2522 goto age_done; 2523 } 2524 2525 /* Make sure update only ipv4 or ipv6 entries. */ 2526 if ((flags & BCM_IPMC_IP6) != (entry.flags & BCM_IPMC_IP6)) { 2527 prev_ipmc_l3entry = ipmc_l3entry; 2528 ipmc_l3entry = ipmc_l3entry->next; 2529 continue; 2530 } 2531 2532 if (entry.flags & BCM_IPMC_HIT) { 2533 if (SOC_IS_FBX(unit)) { 2534 _bcm_l3_cfg_t l3cfg; 2535 /* Clear hit bit on used entry (by doing a lookup !!) */ 2536 sal_memset(&l3cfg, 0, sizeof(_bcm_l3_cfg_t)); 2537 l3cfg.l3c_flags |= BCM_L3_HIT_CLEAR; 2538 l3cfg.l3c_vid = ipmc_l3entry->l3info.vid; 2539 l3cfg.l3c_flags |= BCM_L3_IPMC; 2540 l3cfg.l3c_vrf = ipmc_l3entry->l3info.vrf; 2541 l3cfg.l3c_vid = ipmc_l3entry->l3info.vid; 2542 2543 if (ipmc_l3entry->ip6) { 2544 sal_memcpy(l3cfg.l3c_sip6, &ipmc_l3entry->l3info.sip6, 2545 BCM_IP6_ADDRLEN); 2546 sal_memcpy(l3cfg.l3c_ip6, &ipmc_l3entry->l3info.ip6, 2547 BCM_IP6_ADDRLEN); 2548 l3cfg.l3c_flags |= BCM_L3_IP6; 2549 rv = (mbcm_driver[unit]->mbcm_l3_ip6_get(unit, &l3cfg)); 2550 } else { 2551 l3cfg.l3c_src_ip_addr = ipmc_l3entry->l3info.src_ip_addr; 2552 l3cfg.l3c_ipmc_group = ipmc_l3entry->l3info.ipmc_group; 2553 rv = (mbcm_driver[unit]->mbcm_l3_ip4_get(unit, &l3cfg)); 2554 } 2555 } else { 2556 /* Clear hit bit on used entry. */ 2557 entry.flags |= BCM_IPMC_HIT_CLEAR; 2558 rv = _xgs3_ipmc_info_get(unit, l3index, idx, TRUE, &entry, 2559 &ipmc_entry, 0, NULL); 2560 } 2561 if (BCM_FAILURE(rv)) { 2562 goto age_done; 2563 } 2564 prev_ipmc_l3entry = ipmc_l3entry; 2565 ipmc_l3entry = ipmc_l3entry->next; 2566 } else { 2567 /* Delete IPMC L3 entry. Inhibit modification of IPMC group's 2568 * l3entry_list by _bcm_fb_er_ipmc_delete. 2569 */ 2570 rv = _bcm_fb_er_ipmc_delete(unit, &entry, FALSE); 2571 if (BCM_FAILURE(rv)) { 2572 goto age_done; 2573 } 2574 2575 /* Delete from IPMC group's l3entry_list */ 2576 if (ipmc_l3entry == IPMC_GROUP_INFO(unit, idx)->l3entry_list) { 2577 IPMC_GROUP_INFO(unit, idx)->l3entry_list = ipmc_l3entry->next; 2578 sal_free(ipmc_l3entry); 2579 ipmc_l3entry = IPMC_GROUP_INFO(unit, idx)->l3entry_list; 2580 } else { 2581 /* 2582 * In the following line of code, Coverity thinks the 2583 * prev_ipmc_l3entry pointer may still be NULL when 2584 * dereferenced. This situation will never occur because 2585 * if ipmc_l3entry is not pointing to the head of the 2586 * linked list, prev_ipmc_l3entry would not be NULL. 2587 */ 2588 /* coverity[var_deref_op : FALSE] */ 2589 prev_ipmc_l3entry->next = ipmc_l3entry->next; 2590 sal_free(ipmc_l3entry); 2591 ipmc_l3entry = prev_ipmc_l3entry->next; 2592 } 2593 2594 /* Invoke user callback. */ 2595 if (NULL != age_cb) { 2596 _BCM_MULTICAST_GROUP_SET(entry.group, 2597 _BCM_MULTICAST_TYPE_L3, entry.group); 2598 rv = (*age_cb)(unit, &entry, user_data); 2599 #ifdef BCM_CB_ABORT_ON_ERR 2600 if (BCM_FAILURE(rv) && SOC_CB_ABORT_ON_ERR(unit)) { 2601 goto age_done; 2602 } 2603 #endif 2604 } 2605 } 2606 } 2607 } 2608 } 2609 2610 age_done: 2611 IPMC_UNLOCK(unit); 2612 return (rv); 2613 } 2614 2615 /* 2616 * Function: 2617 * bcm_xgs3_ipmc_traverse 2618 * Purpose: 2619 * Go through all valid ipmc entries, and call the callback function 2620 * at each entry 2621 * Parameters: 2622 * unit - (IN) BCM device number. 2623 * flags - (IN) The criteria used to age out ipmc table. 2624 * cb - (IN) User supplied callback function. 2625 * user_data - (IN) User supplied cookie used in parameter 2626 * in callback function. 2627 * Returns: 2628 * BCM_E_XXX 2629 */ 2630 int 2631 bcm_xgs3_ipmc_traverse(int unit, uint32 flags, bcm_ipmc_traverse_cb cb, 2632 void *user_data) 2633 { 2634 int idx; /* Ipmc table iteration index. */ 2635 bcm_ipmc_addr_t entry; /* Ipmc entry iterator. */ 2636 int rv = BCM_E_NONE; /* Operation return status. */ 2637 ipmc_entry_t ipmc_entry; 2638 _bcm_esw_ipmc_l3entry_t *ipmc_l3entry; 2639 int l3index = 0; 2640 2641 IPMC_INIT(unit); 2642 IPMC_LOCK(unit); 2643 2644 for (idx = 0; idx < IPMC_GROUP_NUM(unit); idx++) { 2645 if (IPMC_USED_ISSET(unit, idx)) { 2646 2647 rv = soc_mem_read(unit, L3_IPMCm, MEM_BLOCK_ANY, idx, &ipmc_entry); 2648 if (BCM_FAILURE(rv)) { 2649 goto traverse_done; 2650 } 2651 2652 ipmc_l3entry = IPMC_GROUP_INFO(unit, idx)->l3entry_list; 2653 while (ipmc_l3entry != NULL) { 2654 sal_memset(&entry, 0, sizeof(bcm_ipmc_addr_t)); 2655 rv = _xgs3_ipmc_info_get(unit, l3index, idx, TRUE, &entry, 2656 &ipmc_entry, 1, ipmc_l3entry); 2657 if (BCM_FAILURE(rv)) { 2658 goto traverse_done; 2659 } 2660 2661 if ((flags & BCM_IPMC_IP6) != (entry.flags & BCM_IPMC_IP6)) { 2662 ipmc_l3entry = ipmc_l3entry->next; 2663 continue; 2664 } 2665 2666 /* Get the pointer to next ipmc_l3entry before callback, 2667 * since callback may delete the current ipmc_l3entry. 2668 */ 2669 ipmc_l3entry = ipmc_l3entry->next; 2670 2671 /* Invoke user callback. */ 2672 _BCM_MULTICAST_GROUP_SET(entry.group, 2673 _BCM_MULTICAST_TYPE_L3, entry.group); 2674 rv = (*cb)(unit, &entry, user_data); 2675 #ifdef BCM_CB_ABORT_ON_ERR 2676 if (BCM_FAILURE(rv) && SOC_CB_ABORT_ON_ERR(unit)) { 2677 goto traverse_done; 2678 } 2679 #endif 2680 } 2681 } 2682 } 2683 2684 traverse_done: 2685 IPMC_UNLOCK(unit); 2686 return (rv); 2687 } 2688 2689 2690 /* 2691 * Function: 2692 * bcm_fb_er_ipmc_enable 2693 * Purpose: 2694 * Enable or disable IPMC chip functions. 2695 * Parameters: 2696 * unit - Unit number 2697 * enable - TRUE to enable; FALSE to disable 2698 * Returns: 2699 * BCM_E_XXX 2700 */ 2701 2702 int 2703 bcm_fb_er_ipmc_enable(int unit, int enable) 2704 { 2705 IPMC_INIT(unit); 2706 2707 return _xgs3_ipmc_enable(unit, enable); 2708 } 2709 2710 /* 2711 * Function: 2712 * _bcm_xgs3_ipmc_valid_as_hit_get 2713 * Purpose: 2714 * Check if IPMC valid bit as hit bit mode is enabled. 2715 * Parameters: 2716 * unit - Unit number 2717 * valid_as_hit - (OUT) TRUE for hit bit; FALSE for valid bit 2718 * Returns: 2719 * BCM_E_XXX 2720 */ 2721 2722 int 2723 _bcm_xgs3_ipmc_valid_as_hit_get(int unit, int *valid_as_hit) 2724 { 2725 IPMC_INIT(unit); 2726 *valid_as_hit = IPMC_VALID_AS_HIT(unit); 2727 return BCM_E_NONE; 2728 } 2729 2730 /* 2731 * Function: 2732 * bcm_fb_er_ipmc_src_port_check 2733 * Purpose: 2734 * Enable or disable Source Port checking in IPMC lookups. 2735 * Parameters: 2736 * unit - Unit number 2737 * enable - TRUE to enable; FALSE to disable 2738 * Returns: 2739 * BCM_E_XXX 2740 */ 2741 2742 int 2743 bcm_fb_er_ipmc_src_port_check(int unit, int enable) 2744 { 2745 IPMC_INIT(unit); 2746 2747 return BCM_E_UNAVAIL; 2748 } 2749 2750 /* 2751 * Function: 2752 * bcm_fb_er_ipmc_src_ip_search 2753 * Purpose: 2754 * Enable or disable Source IP significance in IPMC lookups. 2755 * Parameters: 2756 * unit - Unit number 2757 * enable - TRUE to enable; FALSE to disable 2758 * Returns: 2759 * BCM_E_XXX 2760 */ 2761 2762 int 2763 bcm_fb_er_ipmc_src_ip_search(int unit, int enable) 2764 { 2765 IPMC_INIT(unit); 2766 2767 if (enable) { 2768 return BCM_E_NONE; /* always on */ 2769 } else { 2770 return BCM_E_FAIL; /* cannot be disabled */ 2771 } 2772 } 2773 2774 2775 /* 2776 * Function: 2777 * bcm_fb_er_ipmc_egress_port_set 2778 * Purpose: 2779 * Configure the IP Multicast egress properties 2780 * Parameters: 2781 * unit - StrataSwitch PCI device unit number (driver internal). 2782 * port - port to config. 2783 * mac - MAC address. 2784 * untag - 1: The IP multicast packet is transmitted as untagged packet. 2785 * 0: The IP multicast packet is transmitted as tagged packet 2786 * with VLAN tag vid. 2787 * vid - VLAN ID. 2788 * ttl - 1 to disable the TTL decrement, 0 otherwise. 2789 * Returns: 2790 * BCM_E_XXX 2791 */ 2792 2793 int 2794 bcm_fb_er_ipmc_egress_port_set(int unit, bcm_port_t port, 2795 const bcm_mac_t mac, int untag, 2796 bcm_vlan_t vid, int ttl) 2797 { 2798 uint32 cfg2; 2799 2800 #if defined(BCM_RAPTOR_SUPPORT) 2801 if (SOC_IS_RAPTOR(unit) || SOC_IS_HAWKEYE(unit)) { 2802 return BCM_E_UNAVAIL; 2803 } 2804 #endif 2805 2806 if (!SOC_PBMP_PORT_VALID(port) || !IS_PORT(unit, port)) { 2807 return BCM_E_BADID; 2808 } 2809 2810 cfg2 = 0; 2811 2812 soc_reg_field_set(unit, EGR_IPMC_CFG2r, &cfg2, 2813 UNTAGf, untag ? 1 : 0); 2814 soc_reg_field_set(unit, EGR_IPMC_CFG2r, &cfg2, 2815 VIDf, vid); 2816 soc_reg_field_set(unit, EGR_IPMC_CFG2r, &cfg2, 2817 DISABLE_SA_REPLACEf, 0); 2818 2819 SOC_IF_ERROR_RETURN(WRITE_EGR_IPMC_CFG2r(unit, port, cfg2)); 2820 2821 return BCM_E_NONE; 2822 } 2823 2824 /* 2825 * Function: 2826 * bcm_fb_er_ipmc_egress_port_get 2827 * Purpose: 2828 * Return the IP Multicast egress properties 2829 * Parameters: 2830 * unit - StrataSwitch PCI device unit number (driver internal). 2831 * port - port to config. 2832 * mac - (OUT) MAC address. 2833 * untag - (OUT) 1: The IP multicast packet is transmitted as 2834 * untagged packet. 2835 * 0: The IP multicast packet is transmitted as tagged 2836 * packet with VLAN tag vid. 2837 * vid - (OUT) VLAN ID. 2838 * ttl_thresh - (OUT) Drop IPMC packets if TTL <= ttl_thresh. 2839 * Returns: 2840 * BCM_E_XXX 2841 */ 2842 2843 int 2844 bcm_fb_er_ipmc_egress_port_get(int unit, bcm_port_t port, sal_mac_addr_t mac, 2845 int *untag, bcm_vlan_t *vid, int *ttl_thresh) 2846 { 2847 uint32 cfg2; 2848 2849 #if defined(BCM_RAPTOR_SUPPORT) 2850 if (SOC_IS_RAPTOR(unit) || SOC_IS_HAWKEYE(unit)) { 2851 return BCM_E_UNAVAIL; 2852 } 2853 #endif 2854 2855 if (!SOC_PBMP_PORT_VALID(port) || !IS_PORT(unit, port)) { 2856 return BCM_E_BADID; 2857 } 2858 2859 2860 SOC_IF_ERROR_RETURN(READ_EGR_IPMC_CFG2r(unit, port, &cfg2)); 2861 2862 *untag = soc_reg_field_get(unit, EGR_IPMC_CFG2r, cfg2, UNTAGf); 2863 *vid = soc_reg_field_get(unit, EGR_IPMC_CFG2r, cfg2, VIDf); 2864 *ttl_thresh = -1; 2865 2866 return BCM_E_NONE; 2867 } 2868 2869 #if defined(BCM_FIREBOLT_SUPPORT) 2870 /* 2871 * Function: 2872 * bcm_fb_ipmc_repl_init 2873 * Purpose: 2874 * Initialize IPMC replication. 2875 * Parameters: 2876 * unit - SOC unit # 2877 * Returns: 2878 * BCM_E_XXX 2879 */ 2880 2881 int 2882 bcm_fb_ipmc_repl_init(int unit) 2883 { 2884 bcm_port_t port; 2885 int alloc_size; 2886 int act_port; 2887 #if defined(BCM_GREYHOUND2_SUPPORT) 2888 int mmu_port, phy_port = 0; 2889 #endif 2890 int i; 2891 2892 bcm_fb_ipmc_repl_detach(unit); 2893 2894 /* Allocate struct for IPMC replication bookkeeping */ 2895 alloc_size = sizeof(_fb_repl_info_t); 2896 _fb_repl_info[unit] = sal_alloc(alloc_size, "IPMC repl info"); 2897 if (_fb_repl_info[unit] == NULL) { 2898 return BCM_E_MEMORY; 2899 } 2900 sal_memset(_fb_repl_info[unit], 0, alloc_size); 2901 _fb_repl_info[unit]->ipmc_size = soc_mem_index_count(unit, L3_IPMCm); 2902 2903 #ifdef BCM_BRADLEY_SUPPORT 2904 if (SOC_IS_HBX(unit)) { 2905 int ipmc_base, ipmc_size; 2906 2907 SOC_IF_ERROR_RETURN 2908 (soc_hbx_ipmc_size_get(unit, &ipmc_base, &ipmc_size)); 2909 2910 if (_fb_repl_info[unit]->ipmc_size > ipmc_size) { 2911 /* Reduce to fix allocated table space */ 2912 _fb_repl_info[unit]->ipmc_size = ipmc_size; 2913 } 2914 } 2915 #endif 2916 2917 #ifdef BCM_TRIUMPH_SUPPORT 2918 if (SOC_IS_TR_VL(unit) && !SOC_IS_HURRICANEX(unit) && 2919 !SOC_IS_GREYHOUND(unit) && !SOC_IS_GREYHOUND2(unit)) { 2920 /* For VPLS, can replicate to 16k next-hop entries */ 2921 IPMC_REPL_INTF_TOTAL(unit) = soc_mem_index_count(unit, EGR_L3_NEXT_HOPm); 2922 } else 2923 #endif 2924 { 2925 /* for GH case, eventhough the L3MC egress logic changed to goto 2926 * EGR_L3_NEXT_HOPm before EGR_L3_INTFm, the maximum replication still 2927 * be limited of EGR_L3_INTFm size. 2928 */ 2929 IPMC_REPL_INTF_TOTAL(unit) = soc_mem_index_count(unit, EGR_L3_INTFm); 2930 } 2931 2932 /* 2933 * soc_feature_l3mc_use_egress_next_hop use EGR_L3_NEXT_HOP as 2934 * replication interface instead of using EGR_L3_INTF. 2935 */ 2936 if (soc_feature(unit, soc_feature_l3mc_use_egress_next_hop)) { 2937 IPMC_REPL_INTF_TOTAL(unit) = soc_mem_index_count(unit, EGR_L3_NEXT_HOPm); 2938 } 2939 2940 IPMC_REPL_TOTAL(unit) = soc_mem_index_count(unit, MMU_IPMC_VLAN_TBLm); 2941 alloc_size = SHR_BITALLOCSIZE(IPMC_REPL_TOTAL(unit)); 2942 _fb_repl_info[unit]->bitmap_entries_used = 2943 sal_alloc(alloc_size, "IPMC repl entries used"); 2944 if (_fb_repl_info[unit]->bitmap_entries_used == NULL) { 2945 bcm_fb_ipmc_repl_detach(unit); 2946 return BCM_E_MEMORY; 2947 } 2948 sal_memset(_fb_repl_info[unit]->bitmap_entries_used, 0, alloc_size); 2949 2950 if (NULL == _fb_repl_info[unit]->l3_intf_to_l3_nh_ipmc) { 2951 _fb_repl_info[unit]->l3_intf_to_l3_nh_ipmc = 2952 sal_alloc(sizeof(int) * soc_mem_index_count(unit, EGR_L3_INTFm), 2953 "l3_intf_to_next_hop_ipmc"); 2954 if (NULL == _fb_repl_info[unit]->l3_intf_to_l3_nh_ipmc) { 2955 bcm_fb_ipmc_repl_detach(unit); 2956 return BCM_E_MEMORY; 2957 } 2958 } 2959 for (i = 0; i < soc_mem_index_count(unit, EGR_L3_INTFm); i++) { 2960 _fb_repl_info[unit]->l3_intf_to_l3_nh_ipmc[i] = 2961 REPL_NH_INDEX_UNALLOCATED; 2962 } 2963 2964 if (NULL == _fb_repl_info[unit]->l3_nh_to_l3_intf_ipmc) { 2965 _fb_repl_info[unit]->l3_nh_to_l3_intf_ipmc = 2966 sal_alloc(sizeof(int) * soc_mem_index_count(unit, EGR_L3_NEXT_HOPm), 2967 "next_hop_to_l3_intf_ipmc"); 2968 2969 if (NULL == _fb_repl_info[unit]->l3_nh_to_l3_intf_ipmc) { 2970 bcm_fb_ipmc_repl_detach(unit); 2971 return BCM_E_MEMORY; 2972 } 2973 } 2974 for (i = 0; i < soc_mem_index_count(unit, EGR_L3_NEXT_HOPm); i++) { 2975 _fb_repl_info[unit]->l3_nh_to_l3_intf_ipmc[i] = 2976 REPL_L3_INTF_UNALLOCATED; 2977 } 2978 2979 /* Always reserve slot 0 */ 2980 IPMC_REPL_VE_USED_SET(unit, 0); 2981 2982 PBMP_ITER(PBMP_PORT_ALL(unit), port) { 2983 act_port = port; 2984 alloc_size = sizeof(_fb_repl_port_info_t); 2985 IPMC_REPL_PORT_INFO(unit, act_port) = 2986 sal_alloc(alloc_size, "IPMC repl port info"); 2987 if (IPMC_REPL_PORT_INFO(unit, act_port) == NULL) { 2988 bcm_fb_ipmc_repl_detach(unit); 2989 return BCM_E_MEMORY; 2990 } 2991 sal_memset(IPMC_REPL_PORT_INFO(unit, act_port), 0, alloc_size); 2992 2993 alloc_size = sizeof(int32) * soc_mem_index_count(unit, L3_IPMCm); 2994 IPMC_REPL_PORT_INFO(unit, act_port)->vlan_count = 2995 sal_alloc(alloc_size, "IPMC repl port vlan count"); 2996 if (IPMC_REPL_PORT_INFO(unit, act_port)->vlan_count == NULL) { 2997 bcm_fb_ipmc_repl_detach(unit); 2998 return BCM_E_MEMORY; 2999 } 3000 sal_memset(IPMC_REPL_PORT_INFO(unit, act_port)->vlan_count, 3001 0, alloc_size); 3002 } 3003 3004 if (!SAL_BOOT_QUICKTURN) { 3005 #ifdef BCM_GREYHOUND_SUPPORT 3006 /* to clear all MMU_IPMC_GROUP_TBLm 3007 * 3008 * Note : Greyhound device changed these tables from system to 3009 * port based tables. 3010 */ 3011 if (SOC_IS_GREYHOUND(unit) || SOC_IS_HURRICANE3(unit) || SOC_IS_GREYHOUND2(unit)){ 3012 _rep_regs_t *ipmc_group_tbl = gh_rep_regs; 3013 3014 #if defined(BCM_HURRICANE3_SUPPORT) 3015 if (SOC_IS_HURRICANE3(unit)) { 3016 ipmc_group_tbl = hr3_rep_regs; 3017 } 3018 #endif /* HURRICANE3 */ 3019 #if defined(BCM_GREYHOUND2_SUPPORT) 3020 if (SOC_IS_GREYHOUND2(unit)) { 3021 ipmc_group_tbl = gh2_rep_regs; 3022 } 3023 #endif /* HURRICANE3 */ 3024 3025 PBMP_ITER(PBMP_PORT_ALL(unit), port) { 3026 #if defined(BCM_GREYHOUND2_SUPPORT) 3027 if (SOC_IS_GREYHOUND2(unit)) { 3028 phy_port = SOC_INFO(unit).port_l2p_mapping[port]; 3029 mmu_port = SOC_INFO(unit).port_p2m_mapping[phy_port]; 3030 act_port = mmu_port; 3031 } else 3032 #endif 3033 { 3034 act_port = port; 3035 } 3036 if (ipmc_group_tbl[act_port].mem == INVALIDm) { 3037 continue; 3038 } 3039 3040 SOC_IF_ERROR_RETURN(soc_mem_clear(unit, 3041 ipmc_group_tbl[act_port].mem, COPYNO_ALL, FALSE)); 3042 } 3043 } else 3044 #endif /* BCM_GREYHOUND_SUPPORT */ 3045 { 3046 3047 SOC_IF_ERROR_RETURN 3048 (soc_mem_clear(unit, MMU_IPMC_GROUP_TBL0m, COPYNO_ALL, FALSE)); 3049 SOC_IF_ERROR_RETURN 3050 (soc_mem_clear(unit, MMU_IPMC_GROUP_TBL1m, COPYNO_ALL, FALSE)); 3051 SOC_IF_ERROR_RETURN 3052 (soc_mem_clear(unit, MMU_IPMC_GROUP_TBL2m, COPYNO_ALL, FALSE)); 3053 if (!SOC_IS_RAVEN(unit)) { 3054 SOC_IF_ERROR_RETURN 3055 (soc_mem_clear(unit, MMU_IPMC_GROUP_TBL3m, COPYNO_ALL, FALSE)); 3056 } 3057 if (!SOC_IS_HB_GW(unit) && !SOC_IS_RAVEN(unit) && !SOC_IS_ENDURO(unit)) { 3058 SOC_IF_ERROR_RETURN 3059 (soc_mem_clear(unit, MMU_IPMC_GROUP_TBL4m, COPYNO_ALL, FALSE)); 3060 SOC_IF_ERROR_RETURN 3061 (soc_mem_clear(unit, MMU_IPMC_GROUP_TBL5m, COPYNO_ALL, FALSE)); 3062 if(!SOC_IS_HURRICANEX(unit)) { 3063 SOC_IF_ERROR_RETURN 3064 (soc_mem_clear(unit, MMU_IPMC_GROUP_TBL6m, COPYNO_ALL, FALSE)); 3065 } 3066 if (!SOC_IS_SC_CQ(unit) && !SOC_IS_HURRICANEX(unit)) { 3067 SOC_IF_ERROR_RETURN 3068 (soc_mem_clear(unit, MMU_IPMC_GROUP_TBL7m, COPYNO_ALL, 3069 FALSE)); 3070 } 3071 } 3072 #ifdef BCM_TRIUMPH_SUPPORT 3073 if (SOC_MEM_IS_VALID(unit, MMU_IPMC_GROUP_TBL8m)) { 3074 SOC_IF_ERROR_RETURN 3075 (soc_mem_clear(unit, MMU_IPMC_GROUP_TBL8m, COPYNO_ALL, FALSE)); 3076 } 3077 #endif 3078 3079 SOC_IF_ERROR_RETURN 3080 (soc_mem_clear(unit, MMU_IPMC_VLAN_TBLm, COPYNO_ALL, FALSE)); 3081 3082 } /* if (SOC_IS_GREYHOUND) */ 3083 } 3084 3085 return BCM_E_NONE; 3086 3087 } 3088 3089 /* 3090 * Function: 3091 * bcm_fb_ipmc_repl_detach 3092 * Purpose: 3093 * Initialize IPMC replication. 3094 * Parameters: 3095 * unit - SOC unit # 3096 * Returns: 3097 * BCM_E_XXX 3098 */ 3099 3100 int 3101 bcm_fb_ipmc_repl_detach(int unit) 3102 { 3103 bcm_port_t port; 3104 _bcm_repl_list_info_t *rli_current, *rli_free; 3105 3106 if (_fb_repl_info[unit] != NULL) { 3107 PBMP_ITER(PBMP_PORT_ALL(unit), port) { 3108 if (_fb_repl_info[unit]->port_info[port] != NULL) { 3109 if (_fb_repl_info[unit]-> 3110 port_info[port]->vlan_count != NULL) { 3111 sal_free(_fb_repl_info[unit]-> 3112 port_info[port]->vlan_count); 3113 } 3114 sal_free(_fb_repl_info[unit]->port_info[port]); 3115 } 3116 } 3117 3118 if (_fb_repl_info[unit]->bitmap_entries_used != NULL) { 3119 sal_free(_fb_repl_info[unit]->bitmap_entries_used); 3120 } 3121 3122 if (_fb_repl_info[unit]->l3_intf_to_l3_nh_ipmc != NULL) { 3123 sal_free(_fb_repl_info[unit]->l3_intf_to_l3_nh_ipmc); 3124 } 3125 3126 if (_fb_repl_info[unit]->l3_nh_to_l3_intf_ipmc != NULL) { 3127 sal_free(_fb_repl_info[unit]->l3_nh_to_l3_intf_ipmc); 3128 } 3129 3130 if (_fb_repl_info[unit]->repl_list_info != NULL) { 3131 rli_current = IPMC_REPL_LIST_INFO(unit); 3132 while (rli_current != NULL) { 3133 rli_free = rli_current; 3134 rli_current = rli_current->next; 3135 sal_free(rli_free); 3136 } 3137 } 3138 3139 sal_free(_fb_repl_info[unit]); 3140 _fb_repl_info[unit] = NULL; 3141 } 3142 3143 return BCM_E_NONE; 3144 } 3145 3146 /* 3147 * Function: 3148 * bcm_fb_ipmc_repl_get 3149 * Purpose: 3150 * Return set of VLANs selected for port's replication list for chosen 3151 * IPMC group. 3152 * Parameters: 3153 * unit - StrataSwitch PCI device unit number. 3154 * ipmc_id - The index number. 3155 * port - port to list. 3156 * vlan_vec - (OUT) vector of replicated VLANs common to selected ports. 3157 * Returns: 3158 * BCM_E_XXX 3159 */ 3160 3161 int 3162 bcm_fb_ipmc_repl_get(int unit, int ipmc_id, bcm_port_t port, 3163 bcm_vlan_vector_t vlan_vec) 3164 { 3165 int rv = BCM_E_NONE; 3166 uint32 ms_bit; 3167 uint32 ls_bits[2]; 3168 mmu_ipmc_vlan_tbl_entry_t vlan_entry; 3169 bcm_l3_intf_t l3_intf; 3170 int vlan_ptr, last_vlan_ptr; 3171 uint32 vlan_count; 3172 int ls_pos; 3173 int rvth = BCM_E_NONE; 3174 3175 IPMC_REPL_INIT(unit); 3176 3177 IPMC_REPL_ID(unit, ipmc_id); 3178 3179 REPL_PORT_CHECK(unit, port); 3180 3181 BCM_VLAN_VEC_ZERO(vlan_vec); 3182 3183 IPMC_REPL_LOCK(unit); 3184 if (IPMC_REPL_PORT_VLAN_COUNT(unit, port, ipmc_id) == 0) { 3185 IPMC_REPL_UNLOCK(unit); 3186 return rvth; 3187 } 3188 3189 if (soc_feature(unit, soc_feature_ipmc_repl_freeze) && 3190 ((rv = _bcm_fb_ipmc_repl_freeze(unit)) < 0)) { 3191 IPMC_REPL_UNLOCK(unit); 3192 return rv; 3193 } 3194 3195 if ((rv = _fb_ipmc_vlan_ptr(unit, ipmc_id, port, &vlan_ptr, 0, 0)) < 0) { 3196 goto get_done; 3197 } 3198 last_vlan_ptr = -1; 3199 vlan_count = 0; 3200 while (vlan_ptr != last_vlan_ptr) { 3201 if ((rv = READ_MMU_IPMC_VLAN_TBLm(unit, MEM_BLOCK_ALL, 3202 vlan_ptr, &vlan_entry)) < 0) { 3203 goto get_done; 3204 } 3205 ms_bit = soc_MMU_IPMC_VLAN_TBLm_field32_get(unit, 3206 &vlan_entry, MSB_VLANf); 3207 soc_MMU_IPMC_VLAN_TBLm_field_get(unit, &vlan_entry, 3208 LSB_VLAN_BMf, ls_bits); 3209 last_vlan_ptr = vlan_ptr; 3210 vlan_ptr = soc_MMU_IPMC_VLAN_TBLm_field32_get(unit, 3211 &vlan_entry, NEXTPTRf); 3212 3213 /* Translate the HW L3 interfaces into the corresponding VLANs. 3214 * Note, this may result in some loss of information. 3215 */ 3216 for (ls_pos = 0; ls_pos < 64; ls_pos++) { 3217 if (ls_bits[ls_pos / 32] & (1 << (ls_pos % 32))) { 3218 bcm_l3_intf_t_init(&l3_intf); 3219 l3_intf.l3a_intf_id = 3220 (ms_bit << 6) + ls_pos; 3221 if ((rv = bcm_esw_l3_intf_get(unit, &l3_intf)) < 0) { 3222 goto get_done; 3223 } 3224 BCM_VLAN_VEC_SET(vlan_vec, l3_intf.l3a_vid); 3225 vlan_count++; 3226 } 3227 } 3228 if (vlan_count >= IPMC_REPL_PORT_VLAN_COUNT(unit, port, ipmc_id)) { 3229 break; 3230 } 3231 } 3232 3233 get_done: 3234 if (soc_feature(unit, soc_feature_ipmc_repl_freeze)) { 3235 rvth = _bcm_fb_ipmc_repl_thaw(unit); 3236 rv = (rv < 0) ? rv : rvth; 3237 } 3238 IPMC_REPL_UNLOCK(unit); 3239 return rv; 3240 } 3241 3242 STATIC int 3243 _fb_ipmc_repl_next_free_ptr(int unit) 3244 { 3245 int ix, bit; 3246 SHR_BITDCL not_ptrs; 3247 3248 for (ix = 0; ix < _SHR_BITDCLSIZE(IPMC_REPL_TOTAL(unit)); ix++) { 3249 not_ptrs = ~_fb_repl_info[unit]->bitmap_entries_used[ix]; 3250 if (not_ptrs) { 3251 for (bit = 0; bit < SHR_BITWID; bit++) { 3252 if (not_ptrs & (1 << bit)) { 3253 return (ix * SHR_BITWID) + bit; 3254 } 3255 } 3256 } 3257 } 3258 3259 return -1; 3260 } 3261 3262 /* 3263 * Function: 3264 * bcm_fb_ipmc_repl_add 3265 * Purpose: 3266 * Add VLAN to selected ports' replication list for chosen 3267 * IPMC group. 3268 *Parameters: 3269 * unit - StrataSwitch PCI device unit number. 3270 * ipmc_id - The index number. 3271 * port - port to add. 3272 * vlan - VLAN to replicate. 3273 * Returns: 3274 * BCM_E_XXX 3275 */ 3276 3277 int 3278 bcm_fb_ipmc_repl_add(int unit, int ipmc_id, bcm_port_t port, 3279 bcm_vlan_t vlan) 3280 { 3281 int rv = BCM_E_NONE; 3282 uint32 ls_bits[2]; 3283 mmu_ipmc_vlan_tbl_entry_t vlan_entry; 3284 int ms_bit, target_ms_bit, ls_bit; 3285 int vlan_ptr, last_vlan_ptr; 3286 pbmp_t pbmp, ubmp; 3287 bcm_l3_intf_t l3_intf; 3288 uint32 vlan_count; 3289 int rvth = BCM_E_NONE; 3290 3291 IPMC_REPL_INIT(unit); 3292 IPMC_REPL_ID(unit, ipmc_id); 3293 REPL_PORT_CHECK(unit, port); 3294 3295 /* Check if port belongs to this VLAN */ 3296 BCM_IF_ERROR_RETURN 3297 (bcm_esw_vlan_port_get(unit, vlan, &pbmp, &ubmp)); 3298 if (!SOC_PBMP_MEMBER(pbmp, port)) { 3299 return BCM_E_PARAM; 3300 } 3301 3302 bcm_l3_intf_t_init(&l3_intf); 3303 l3_intf.l3a_vid = vlan; 3304 if (bcm_esw_l3_intf_find_vlan(unit, &l3_intf) < 0) { 3305 return BCM_E_PARAM; 3306 } 3307 3308 if (SOC_IPMCREPLSHR_GET(unit) || 3309 soc_feature(unit, soc_feature_ipmc_repl_penultimate)) { 3310 int alloc_size, intf_max, if_count, rv = BCM_E_NONE; 3311 bcm_if_t *if_array = NULL; 3312 3313 intf_max = IPMC_REPL_INTF_TOTAL(unit); 3314 alloc_size = intf_max * sizeof(bcm_if_t); 3315 if_array = sal_alloc(alloc_size, "IPMC repl interface array"); 3316 if (if_array == NULL) { 3317 return BCM_E_MEMORY; 3318 } 3319 3320 IPMC_REPL_LOCK(unit); 3321 rv = bcm_fb_ipmc_egress_intf_get(unit, ipmc_id, port, intf_max, 3322 if_array, &if_count); 3323 if (BCM_SUCCESS(rv)) { 3324 if (if_count < intf_max) { 3325 if_array[if_count++] = l3_intf.l3a_intf_id; 3326 rv = bcm_fb_ipmc_egress_intf_set(unit, ipmc_id, port, 3327 if_count, if_array, 1, FALSE); 3328 } else { 3329 rv = BCM_E_EXISTS; 3330 } 3331 } 3332 3333 IPMC_REPL_UNLOCK(unit); 3334 sal_free(if_array); 3335 return rv; 3336 } 3337 3338 IPMC_REPL_LOCK(unit); 3339 if (soc_feature(unit, soc_feature_ipmc_repl_freeze) && 3340 ((rv = _bcm_fb_ipmc_repl_freeze(unit)) < 0)) { 3341 IPMC_REPL_UNLOCK(unit); 3342 return rv; 3343 } 3344 3345 if ((rv = _fb_ipmc_vlan_ptr(unit, ipmc_id, port, &vlan_ptr, 0, 0)) < 0) { 3346 goto add_done; 3347 } 3348 3349 target_ms_bit = (l3_intf.l3a_intf_id >> 6) & 0x3f; 3350 ls_bit = l3_intf.l3a_intf_id & 0x3f; 3351 3352 last_vlan_ptr = -1; 3353 vlan_count = 0; 3354 ms_bit = -1; 3355 3356 if (IPMC_REPL_PORT_VLAN_COUNT(unit, port, ipmc_id)) { 3357 /* 3358 * Add to existing chain 3359 */ 3360 while (vlan_ptr != last_vlan_ptr) { 3361 if ((rv = READ_MMU_IPMC_VLAN_TBLm(unit, MEM_BLOCK_ALL, 3362 vlan_ptr, &vlan_entry)) < 0) { 3363 goto add_done; 3364 } 3365 3366 ms_bit = soc_MMU_IPMC_VLAN_TBLm_field32_get(unit, 3367 &vlan_entry, MSB_VLANf); 3368 3369 if (ms_bit == target_ms_bit) { 3370 /* Add to existing entry */ 3371 break; 3372 } 3373 3374 last_vlan_ptr = vlan_ptr; 3375 vlan_ptr = soc_MMU_IPMC_VLAN_TBLm_field32_get(unit, 3376 &vlan_entry, NEXTPTRf); 3377 3378 soc_MMU_IPMC_VLAN_TBLm_field_get(unit, &vlan_entry, 3379 LSB_VLAN_BMf, ls_bits); 3380 vlan_count += 3381 _shr_popcount(ls_bits[0]) + _shr_popcount(ls_bits[1]); 3382 if (vlan_count >= IPMC_REPL_PORT_VLAN_COUNT(unit, port, ipmc_id)) { 3383 break; 3384 } 3385 } 3386 } 3387 3388 if (ms_bit != target_ms_bit) { 3389 /* New entry, find slot */ 3390 vlan_ptr = _fb_ipmc_repl_next_free_ptr(unit); 3391 if (vlan_ptr < 0) { 3392 /* Out of LS entries */ 3393 rv = BCM_E_RESOURCE; 3394 goto add_done; 3395 } 3396 3397 if (last_vlan_ptr < 0) { 3398 /* Update group table */ 3399 if ((rv = _fb_ipmc_vlan_ptr(unit, ipmc_id, 3400 port, &vlan_ptr, 0, 1)) < 0) { 3401 goto add_done; 3402 } 3403 } else { 3404 /* Update last entry */ 3405 soc_MMU_IPMC_VLAN_TBLm_field32_set(unit, &vlan_entry, 3406 NEXTPTRf, vlan_ptr); 3407 if ((rv = WRITE_MMU_IPMC_VLAN_TBLm(unit, MEM_BLOCK_ALL, 3408 last_vlan_ptr, &vlan_entry)) < 0) { 3409 goto add_done; 3410 } 3411 } 3412 3413 sal_memset(&vlan_entry, 0, sizeof(vlan_entry)); 3414 soc_MMU_IPMC_VLAN_TBLm_field32_set(unit, &vlan_entry, 3415 MSB_VLANf, target_ms_bit); 3416 /* Point to self */ 3417 soc_MMU_IPMC_VLAN_TBLm_field32_set(unit, &vlan_entry, 3418 NEXTPTRf, vlan_ptr); 3419 3420 IPMC_REPL_VE_USED_SET(unit, vlan_ptr); 3421 } 3422 3423 /* Insert replacement */ 3424 soc_MMU_IPMC_VLAN_TBLm_field_get(unit, &vlan_entry, 3425 LSB_VLAN_BMf, ls_bits); 3426 if (ls_bits[ls_bit / 32] & (1 << (ls_bit % 32))) { 3427 /* Already exists! */ 3428 rv = BCM_E_EXISTS; 3429 goto add_done; 3430 } 3431 ls_bits[ls_bit / 32] |= 1 << (ls_bit % 32); 3432 soc_MMU_IPMC_VLAN_TBLm_field_set(unit, &vlan_entry, 3433 LSB_VLAN_BMf, ls_bits); 3434 3435 3436 if ((rv = WRITE_MMU_IPMC_VLAN_TBLm(unit, MEM_BLOCK_ALL, 3437 vlan_ptr, &vlan_entry)) < 0) { 3438 goto add_done; 3439 } 3440 3441 IPMC_REPL_PORT_VLAN_COUNT(unit, port, ipmc_id)++; 3442 3443 add_done: 3444 if (soc_feature(unit, soc_feature_ipmc_repl_freeze)) { 3445 rvth = _bcm_fb_ipmc_repl_thaw(unit); 3446 rv = (rv < 0) ? rv : rvth; 3447 } 3448 IPMC_REPL_UNLOCK(unit); 3449 return rv; 3450 } 3451 3452 /* 3453 * Function: 3454 * bcm_fb_ipmc_repl_delete 3455 * Purpose: 3456 * Remove VLAN from selected ports' replication list for chosen 3457 * IPMC group. 3458 * Parameters: 3459 * unit - StrataSwitch PCI device unit number. 3460 * ipmc_id - The index number. 3461 * port - port to remove. 3462 * vlan - VLAN to delete from replication. 3463 * Returns: 3464 * BCM_E_XXX 3465 */ 3466 3467 int 3468 bcm_fb_ipmc_repl_delete(int unit, int ipmc_id, bcm_port_t port, 3469 bcm_vlan_t vlan) 3470 { 3471 int rv = BCM_E_NONE; 3472 uint32 ls_bits[2]; 3473 mmu_ipmc_vlan_tbl_entry_t vlan_entry, prev_vlan_entry; 3474 int ms_bit, target_ms_bit, ls_bit; 3475 int vlan_ptr, last_vlan_ptr, next_vlan_ptr; 3476 bcm_l3_intf_t l3_intf; 3477 uint32 vlan_count; 3478 int rvth = BCM_E_NONE; 3479 3480 IPMC_REPL_INIT(unit); 3481 IPMC_REPL_ID(unit, ipmc_id); 3482 REPL_PORT_CHECK(unit, port); 3483 3484 if (!IPMC_REPL_PORT_VLAN_COUNT(unit, port, ipmc_id)) { 3485 return BCM_E_NOT_FOUND; 3486 } 3487 3488 bcm_l3_intf_t_init(&l3_intf); 3489 l3_intf.l3a_vid = vlan; 3490 if (bcm_esw_l3_intf_find_vlan(unit, &l3_intf) < 0) { 3491 return BCM_E_PARAM; 3492 } 3493 3494 if (SOC_IPMCREPLSHR_GET(unit) || 3495 soc_feature(unit, soc_feature_ipmc_repl_penultimate)) { 3496 int alloc_size, intf_max, if_count, if_cur, match, rv = BCM_E_NONE; 3497 bcm_if_t *if_array = NULL; 3498 3499 intf_max = IPMC_REPL_INTF_TOTAL(unit); 3500 alloc_size = intf_max * sizeof(bcm_if_t); 3501 if_array = sal_alloc(alloc_size, "IPMC repl interface array"); 3502 if (if_array == NULL) { 3503 return BCM_E_MEMORY; 3504 } 3505 3506 IPMC_REPL_LOCK(unit); 3507 rv = bcm_fb_ipmc_egress_intf_get(unit, ipmc_id, port, intf_max, 3508 if_array, &if_count); 3509 if (BCM_SUCCESS(rv)) { 3510 match = FALSE; 3511 for (if_cur = 0; if_cur < if_count; if_cur++) { 3512 if (match) { 3513 if_array[if_cur - 1] = if_array[if_cur]; 3514 } else { 3515 if (if_array[if_cur] == l3_intf.l3a_intf_id) { 3516 match = TRUE; 3517 } 3518 } 3519 } 3520 if (match) { 3521 if_count--; 3522 rv = bcm_fb_ipmc_egress_intf_set(unit, ipmc_id, port, 3523 if_count, if_array, 1, FALSE); 3524 } else { 3525 rv = BCM_E_NOT_FOUND; 3526 } 3527 } 3528 IPMC_REPL_UNLOCK(unit); 3529 sal_free(if_array); 3530 return rv; 3531 } 3532 3533 IPMC_REPL_LOCK(unit); 3534 if (soc_feature(unit, soc_feature_ipmc_repl_freeze) && 3535 ((rv = _bcm_fb_ipmc_repl_freeze(unit)) < 0)) { 3536 IPMC_REPL_UNLOCK(unit); 3537 return rv; 3538 } 3539 3540 if ((rv = _fb_ipmc_vlan_ptr(unit, ipmc_id, port, &vlan_ptr, 0, 0)) < 0) { 3541 goto del_done; 3542 } 3543 3544 target_ms_bit = (l3_intf.l3a_intf_id >> 6) & 0x3f; 3545 ls_bit = l3_intf.l3a_intf_id & 0x3f; 3546 3547 last_vlan_ptr = 0; /* Since ptr 0 should never be used! */ 3548 vlan_count = 0; 3549 ms_bit = -1; 3550 3551 while (vlan_ptr != last_vlan_ptr) { 3552 if ((rv = READ_MMU_IPMC_VLAN_TBLm(unit, MEM_BLOCK_ALL, 3553 vlan_ptr, &vlan_entry)) < 0) { 3554 goto del_done; 3555 } 3556 3557 ms_bit = soc_MMU_IPMC_VLAN_TBLm_field32_get(unit, 3558 &vlan_entry, MSB_VLANf); 3559 if (ms_bit == target_ms_bit) { 3560 /* Delete existing entry */ 3561 soc_MMU_IPMC_VLAN_TBLm_field_get(unit, &vlan_entry, 3562 LSB_VLAN_BMf, ls_bits); 3563 if (!(ls_bits[ls_bit / 32] & (1 << (ls_bit % 32)))) { 3564 /* Doesn't exist! */ 3565 rv = BCM_E_NOT_FOUND; 3566 goto del_done; 3567 } 3568 ls_bits[ls_bit / 32] &= ~(1 << (ls_bit % 32)); 3569 soc_MMU_IPMC_VLAN_TBLm_field_set(unit, &vlan_entry, 3570 LSB_VLAN_BMf, ls_bits); 3571 3572 if ((ls_bits[0] == 0) && (ls_bits[1] == 0)) { 3573 /* Wiped out the entry */ 3574 /* Record before overwrite */ 3575 next_vlan_ptr = 3576 soc_MMU_IPMC_VLAN_TBLm_field32_get(unit, 3577 &vlan_entry, NEXTPTRf); 3578 soc_MMU_IPMC_VLAN_TBLm_field32_set(unit, 3579 &vlan_entry, MSB_VLANf, 0); 3580 soc_MMU_IPMC_VLAN_TBLm_field32_set(unit, 3581 &vlan_entry, NEXTPTRf, 0); 3582 if (last_vlan_ptr == 0) { 3583 /* First entry for this (group, port) */ 3584 if (vlan_ptr == next_vlan_ptr) { 3585 /* Only link in chain */ 3586 next_vlan_ptr = 0; 3587 } 3588 if ((rv = _fb_ipmc_vlan_ptr(unit, ipmc_id, 3589 port, &next_vlan_ptr, 0, 1)) < 0) { 3590 goto del_done; 3591 } 3592 } else { 3593 /* Link over with last entry */ 3594 if (vlan_ptr == next_vlan_ptr) { 3595 /* If this is end of chain, end on previous link */ 3596 next_vlan_ptr = last_vlan_ptr; 3597 } 3598 soc_MMU_IPMC_VLAN_TBLm_field32_set(unit, 3599 &prev_vlan_entry, NEXTPTRf, next_vlan_ptr); 3600 if ((rv = WRITE_MMU_IPMC_VLAN_TBLm(unit, 3601 MEM_BLOCK_ALL, last_vlan_ptr, 3602 &prev_vlan_entry)) < 0) { 3603 goto del_done; 3604 } 3605 } 3606 3607 IPMC_REPL_VE_USED_CLR(unit, vlan_ptr); 3608 } 3609 3610 if ((rv = WRITE_MMU_IPMC_VLAN_TBLm(unit, 3611 MEM_BLOCK_ALL, vlan_ptr, &vlan_entry)) < 0) { 3612 goto del_done; 3613 } 3614 3615 IPMC_REPL_PORT_VLAN_COUNT(unit, port, ipmc_id)--; 3616 3617 goto del_done; 3618 } 3619 3620 last_vlan_ptr = vlan_ptr; 3621 vlan_ptr = soc_MMU_IPMC_VLAN_TBLm_field32_get(unit, 3622 &vlan_entry, NEXTPTRf); 3623 sal_memcpy(&prev_vlan_entry, &vlan_entry, 3624 sizeof(mmu_ipmc_vlan_tbl_entry_t)); 3625 3626 soc_MMU_IPMC_VLAN_TBLm_field_get(unit, &vlan_entry, 3627 LSB_VLAN_BMf, ls_bits); 3628 vlan_count += 3629 _shr_popcount(ls_bits[0]) + _shr_popcount(ls_bits[1]); 3630 if (vlan_count >= IPMC_REPL_PORT_VLAN_COUNT(unit, port, ipmc_id)) { 3631 rv = BCM_E_NOT_FOUND; 3632 goto del_done; 3633 } 3634 } 3635 3636 rv = BCM_E_NOT_FOUND; 3637 3638 del_done: 3639 if (soc_feature(unit, soc_feature_ipmc_repl_freeze)) { 3640 rvth = _bcm_fb_ipmc_repl_thaw(unit); 3641 rv = (rv < 0) ? rv : rvth; 3642 } 3643 IPMC_REPL_UNLOCK(unit); 3644 return rv; 3645 } 3646 3647 /* 3648 * Function: 3649 * bcm_fb_ipmc_repl_delete_all 3650 * Purpose: 3651 * Remove all VLANs from selected ports' replication list for chosen 3652 * IPMC group. 3653 * Parameters: 3654 * unit - StrataSwitch PCI device unit number. 3655 * ipmc_id - The MC index number. 3656 * port - port from which to remove VLANs. 3657 * Returns: 3658 * BCM_E_XXX 3659 */ 3660 3661 int 3662 bcm_fb_ipmc_repl_delete_all(int unit, int ipmc_id, bcm_port_t port) 3663 { 3664 int rv = BCM_E_NONE; 3665 uint32 ls_bits[2]; 3666 mmu_ipmc_vlan_tbl_entry_t vlan_entry; 3667 int vlan_ptr, last_vlan_ptr; 3668 int rvth = BCM_E_NONE; 3669 int num_vlans; 3670 3671 IPMC_REPL_INIT(unit); 3672 IPMC_REPL_ID(unit, ipmc_id); 3673 REPL_PORT_CHECK(unit, port); 3674 3675 if (!IPMC_REPL_PORT_VLAN_COUNT(unit, port, ipmc_id)) { 3676 /* Nothing to do */ 3677 return BCM_E_NONE; 3678 } 3679 3680 if (SOC_IPMCREPLSHR_GET(unit) || 3681 soc_feature(unit, soc_feature_ipmc_repl_penultimate)) { 3682 return bcm_fb_ipmc_egress_intf_set(unit, ipmc_id, port, 0, NULL, 1, FALSE); 3683 } 3684 3685 IPMC_REPL_LOCK(unit); 3686 if (soc_feature(unit, soc_feature_ipmc_repl_freeze) && 3687 ((rv = _bcm_fb_ipmc_repl_freeze(unit)) < 0)) { 3688 IPMC_REPL_UNLOCK(unit); 3689 return rv; 3690 } 3691 3692 if ((rv = _fb_ipmc_vlan_ptr(unit, ipmc_id, 3693 port, &vlan_ptr, 0, 0)) < 0) { 3694 goto del_all_done; 3695 } 3696 last_vlan_ptr = 0; 3697 if ((rv = _fb_ipmc_vlan_ptr(unit, ipmc_id, 3698 port, &last_vlan_ptr, 0, 1)) < 0) { 3699 goto del_all_done; 3700 } 3701 3702 while (vlan_ptr != last_vlan_ptr) { 3703 if ((rv = READ_MMU_IPMC_VLAN_TBLm(unit, MEM_BLOCK_ALL, 3704 vlan_ptr, &vlan_entry)) < 0) { 3705 goto del_all_done; 3706 } 3707 3708 if ((rv = WRITE_MMU_IPMC_VLAN_TBLm(unit, 3709 MEM_BLOCK_ALL, vlan_ptr, soc_mem_entry_null(unit, 3710 MMU_IPMC_VLAN_TBLm))) < 0) { 3711 goto del_all_done; 3712 } 3713 3714 IPMC_REPL_VE_USED_CLR(unit, vlan_ptr); 3715 3716 last_vlan_ptr = vlan_ptr; 3717 vlan_ptr = soc_MMU_IPMC_VLAN_TBLm_field32_get(unit, 3718 &vlan_entry, NEXTPTRf); 3719 3720 soc_MMU_IPMC_VLAN_TBLm_field_get(unit, &vlan_entry, 3721 LSB_VLAN_BMf, ls_bits); 3722 num_vlans = _shr_popcount(ls_bits[0]) + _shr_popcount(ls_bits[1]); 3723 if (IPMC_REPL_PORT_VLAN_COUNT(unit, port, ipmc_id) < num_vlans) { 3724 IPMC_REPL_PORT_VLAN_COUNT(unit, port, ipmc_id) = 0; 3725 goto del_all_done; 3726 } 3727 IPMC_REPL_PORT_VLAN_COUNT(unit, port, ipmc_id) -= num_vlans; 3728 } 3729 3730 del_all_done: 3731 if (soc_feature(unit, soc_feature_ipmc_repl_freeze)) { 3732 rvth = _bcm_fb_ipmc_repl_thaw(unit); 3733 rv = (rv < 0) ? rv : rvth; 3734 } 3735 IPMC_REPL_UNLOCK(unit); 3736 return rv; 3737 } 3738 3739 /* 3740 * Function: 3741 * bcm_fb_ipmc_egress_intf_add 3742 * Purpose: 3743 * Add L3 interface to selected ports' replication list for chosen 3744 * IPMC group. 3745 * Parameters: 3746 * unit - StrataSwitch PCI device unit number. 3747 * ipmc_id - The index number. 3748 * port - port to add. 3749 * l3_intf - L3 interface to replicate. 3750 * Returns: 3751 * BCM_E_XXX 3752 */ 3753 int 3754 bcm_fb_ipmc_egress_intf_add(int unit, int ipmc_id, bcm_port_t port, 3755 bcm_l3_intf_t *l3_intf) 3756 { 3757 int rv = BCM_E_NONE; 3758 uint32 ls_bits[2]; 3759 mmu_ipmc_vlan_tbl_entry_t vlan_entry; 3760 int ms_bit, target_ms_bit, ls_bit; 3761 int vlan_ptr, last_vlan_ptr; 3762 pbmp_t pbmp, ubmp; 3763 uint32 vlan_count; 3764 int rvth = BCM_E_NONE; 3765 3766 IPMC_REPL_INIT(unit); 3767 IPMC_REPL_ID(unit, ipmc_id); 3768 REPL_PORT_CHECK(unit, port); 3769 3770 /* Check if port belongs to this VLAN */ 3771 BCM_IF_ERROR_RETURN 3772 (bcm_esw_vlan_port_get(unit, l3_intf->l3a_vid, &pbmp, &ubmp)); 3773 if (!SOC_PBMP_MEMBER(pbmp, port)) { 3774 return BCM_E_PARAM; 3775 } 3776 3777 if (SOC_IPMCREPLSHR_GET(unit) || 3778 soc_feature(unit, soc_feature_ipmc_repl_penultimate)) { 3779 bcm_if_t *if_array = NULL; 3780 int intf_num, intf_max, alloc_size, rv = BCM_E_NONE; 3781 3782 intf_max = IPMC_REPL_INTF_TOTAL(unit); 3783 alloc_size = intf_max * sizeof(bcm_if_t); 3784 if_array = sal_alloc(alloc_size, "IPMC repl interface array"); 3785 if (if_array == NULL) { 3786 return BCM_E_MEMORY; 3787 } 3788 3789 IPMC_REPL_LOCK(unit); 3790 rv = bcm_fb_ipmc_egress_intf_get(unit, ipmc_id, port, intf_max, 3791 if_array, &intf_num); 3792 if (BCM_SUCCESS(rv)) { 3793 if (intf_num < intf_max) { 3794 if_array[intf_num++] = l3_intf->l3a_intf_id; 3795 rv = bcm_fb_ipmc_egress_intf_set(unit, ipmc_id, port, 3796 intf_num, if_array, 1, FALSE); 3797 } else { 3798 rv = BCM_E_EXISTS; 3799 } 3800 } 3801 3802 IPMC_REPL_UNLOCK(unit); 3803 sal_free(if_array); 3804 return rv; 3805 } 3806 3807 IPMC_REPL_LOCK(unit); 3808 if (soc_feature(unit, soc_feature_ipmc_repl_freeze) && 3809 ((rv = _bcm_fb_ipmc_repl_freeze(unit)) < 0)) { 3810 IPMC_REPL_UNLOCK(unit); 3811 return rv; 3812 } 3813 3814 if ((rv = _fb_ipmc_vlan_ptr(unit, ipmc_id, port, &vlan_ptr, 0, 0)) < 0) { 3815 goto add_done; 3816 } 3817 3818 target_ms_bit = (l3_intf->l3a_intf_id >> 6) & 0x3f; 3819 ls_bit = l3_intf->l3a_intf_id & 0x3f; 3820 3821 last_vlan_ptr = -1; 3822 vlan_count = 0; 3823 ms_bit = -1; 3824 3825 if (IPMC_REPL_PORT_VLAN_COUNT(unit, port, ipmc_id)) { 3826 /* 3827 * Add to existing chain 3828 */ 3829 while (vlan_ptr != last_vlan_ptr) { 3830 if ((rv = READ_MMU_IPMC_VLAN_TBLm(unit, MEM_BLOCK_ALL, 3831 vlan_ptr, &vlan_entry)) < 0) { 3832 goto add_done; 3833 } 3834 3835 ms_bit = soc_MMU_IPMC_VLAN_TBLm_field32_get(unit, 3836 &vlan_entry, MSB_VLANf); 3837 3838 if (ms_bit == target_ms_bit) { 3839 /* Add to existing entry */ 3840 break; 3841 } 3842 3843 last_vlan_ptr = vlan_ptr; 3844 vlan_ptr = soc_MMU_IPMC_VLAN_TBLm_field32_get(unit, 3845 &vlan_entry, NEXTPTRf); 3846 3847 soc_MMU_IPMC_VLAN_TBLm_field_get(unit, &vlan_entry, 3848 LSB_VLAN_BMf, ls_bits); 3849 vlan_count += 3850 _shr_popcount(ls_bits[0]) + _shr_popcount(ls_bits[1]); 3851 if (vlan_count >= IPMC_REPL_PORT_VLAN_COUNT(unit, port, ipmc_id)) { 3852 break; 3853 } 3854 } 3855 } 3856 3857 if (ms_bit != target_ms_bit) { 3858 /* New entry, find slot */ 3859 vlan_ptr = _fb_ipmc_repl_next_free_ptr(unit); 3860 if (vlan_ptr < 0) { 3861 /* Out of LS entries */ 3862 rv = BCM_E_RESOURCE; 3863 goto add_done; 3864 } 3865 3866 if (last_vlan_ptr < 0) { 3867 /* Update group table */ 3868 if ((rv = _fb_ipmc_vlan_ptr(unit, ipmc_id, 3869 port, &vlan_ptr, 0, 1)) < 0) { 3870 goto add_done; 3871 } 3872 } else { 3873 /* Update last entry */ 3874 soc_MMU_IPMC_VLAN_TBLm_field32_set(unit, &vlan_entry, 3875 NEXTPTRf, vlan_ptr); 3876 if ((rv = WRITE_MMU_IPMC_VLAN_TBLm(unit, MEM_BLOCK_ALL, 3877 last_vlan_ptr, &vlan_entry)) < 0) { 3878 goto add_done; 3879 } 3880 } 3881 3882 sal_memset(&vlan_entry, 0, sizeof(vlan_entry)); 3883 soc_MMU_IPMC_VLAN_TBLm_field32_set(unit, &vlan_entry, 3884 MSB_VLANf, target_ms_bit); 3885 /* Point to self */ 3886 soc_MMU_IPMC_VLAN_TBLm_field32_set(unit, &vlan_entry, 3887 NEXTPTRf, vlan_ptr); 3888 3889 IPMC_REPL_VE_USED_SET(unit, vlan_ptr); 3890 } 3891 3892 /* Insert replacement */ 3893 soc_MMU_IPMC_VLAN_TBLm_field_get(unit, &vlan_entry, 3894 LSB_VLAN_BMf, ls_bits); 3895 if (ls_bits[ls_bit / 32] & (1 << (ls_bit % 32))) { 3896 /* Already exists! */ 3897 rv = BCM_E_EXISTS; 3898 goto add_done; 3899 } 3900 ls_bits[ls_bit / 32] |= 1 << (ls_bit % 32); 3901 soc_MMU_IPMC_VLAN_TBLm_field_set(unit, &vlan_entry, 3902 LSB_VLAN_BMf, ls_bits); 3903 3904 3905 if ((rv = WRITE_MMU_IPMC_VLAN_TBLm(unit, MEM_BLOCK_ALL, 3906 vlan_ptr, &vlan_entry)) < 0) { 3907 goto add_done; 3908 } 3909 3910 IPMC_REPL_PORT_VLAN_COUNT(unit, port, ipmc_id)++; 3911 3912 add_done: 3913 if (soc_feature(unit, soc_feature_ipmc_repl_freeze)) { 3914 rvth = _bcm_fb_ipmc_repl_thaw(unit); 3915 rv = (rv < 0) ? rv : rvth; 3916 } 3917 IPMC_REPL_UNLOCK(unit); 3918 return rv; 3919 } 3920 3921 /* 3922 * Function: 3923 * bcm_fb_ipmc_egress_intf_delete 3924 * Purpose: 3925 * Remove L3 interface from selected ports' replication list for chosen 3926 * IPMC group. 3927 * Parameters: 3928 * unit - StrataSwitch PCI device unit number. 3929 * ipmc_id - The index number. 3930 * port - port to remove. 3931 * l3_intf - L3 interface to delete from replication. 3932 * Returns: 3933 * BCM_E_XXX 3934 */ 3935 int 3936 bcm_fb_ipmc_egress_intf_delete(int unit, int ipmc_id, bcm_port_t port, 3937 bcm_l3_intf_t *l3_intf) 3938 { 3939 int rv = BCM_E_NONE; 3940 uint32 ls_bits[2]; 3941 mmu_ipmc_vlan_tbl_entry_t vlan_entry, prev_vlan_entry; 3942 int ms_bit, target_ms_bit, ls_bit; 3943 int vlan_ptr, last_vlan_ptr, next_vlan_ptr; 3944 uint32 vlan_count; 3945 int rvth = BCM_E_NONE; 3946 3947 IPMC_REPL_INIT(unit); 3948 IPMC_REPL_ID(unit, ipmc_id); 3949 REPL_PORT_CHECK(unit, port); 3950 3951 if (!IPMC_REPL_PORT_VLAN_COUNT(unit, port, ipmc_id)) { 3952 return BCM_E_NOT_FOUND; 3953 } 3954 3955 if (SOC_IPMCREPLSHR_GET(unit) || 3956 soc_feature(unit, soc_feature_ipmc_repl_penultimate)) { 3957 bcm_if_t *if_array = NULL; 3958 int alloc_size, intf_max, if_count, if_cur, match, rv = BCM_E_NONE; 3959 3960 intf_max = IPMC_REPL_INTF_TOTAL(unit); 3961 alloc_size = intf_max * sizeof(bcm_if_t); 3962 if_array = sal_alloc(alloc_size, "IPMC repl interface array"); 3963 if (if_array == NULL) { 3964 return BCM_E_MEMORY; 3965 } 3966 3967 IPMC_REPL_LOCK(unit); 3968 rv = bcm_fb_ipmc_egress_intf_get(unit, ipmc_id, port, intf_max, 3969 if_array, &if_count); 3970 if (BCM_SUCCESS(rv)) { 3971 match = FALSE; 3972 for (if_cur = 0; if_cur < if_count; if_cur++) { 3973 if (match) { 3974 if_array[if_cur - 1] = if_array[if_cur]; 3975 } else { 3976 if (if_array[if_cur] == l3_intf->l3a_intf_id) { 3977 match = TRUE; 3978 } 3979 } 3980 } 3981 if (match) { 3982 if_count--; 3983 rv = bcm_fb_ipmc_egress_intf_set(unit, ipmc_id, port, 3984 if_count, if_array, 1, FALSE); 3985 } else { 3986 rv = BCM_E_NOT_FOUND; 3987 } 3988 } 3989 3990 IPMC_REPL_UNLOCK(unit); 3991 sal_free(if_array); 3992 return rv; 3993 } 3994 3995 IPMC_REPL_LOCK(unit); 3996 if (soc_feature(unit, soc_feature_ipmc_repl_freeze) && 3997 ((rv = _bcm_fb_ipmc_repl_freeze(unit)) < 0)) { 3998 IPMC_REPL_UNLOCK(unit); 3999 return rv; 4000 } 4001 4002 if ((rv = _fb_ipmc_vlan_ptr(unit, ipmc_id, port, &vlan_ptr, 0, 0)) < 0) { 4003 goto del_done; 4004 } 4005 4006 target_ms_bit = (l3_intf->l3a_intf_id >> 6) & 0x3f; 4007 ls_bit = l3_intf->l3a_intf_id & 0x3f; 4008 4009 last_vlan_ptr = 0; /* Since ptr 0 should never be used! */ 4010 vlan_count = 0; 4011 ms_bit = -1; 4012 4013 while (vlan_ptr != last_vlan_ptr) { 4014 if ((rv = READ_MMU_IPMC_VLAN_TBLm(unit, MEM_BLOCK_ALL, 4015 vlan_ptr, &vlan_entry)) < 0) { 4016 goto del_done; 4017 } 4018 4019 ms_bit = soc_MMU_IPMC_VLAN_TBLm_field32_get(unit, 4020 &vlan_entry, MSB_VLANf); 4021 if (ms_bit == target_ms_bit) { 4022 /* Delete existing entry */ 4023 soc_MMU_IPMC_VLAN_TBLm_field_get(unit, &vlan_entry, 4024 LSB_VLAN_BMf, ls_bits); 4025 if (!(ls_bits[ls_bit / 32] & (1 << (ls_bit % 32)))) { 4026 /* Doesn't exist! */ 4027 rv = BCM_E_NOT_FOUND; 4028 goto del_done; 4029 } 4030 ls_bits[ls_bit / 32] &= ~(1 << (ls_bit % 32)); 4031 soc_MMU_IPMC_VLAN_TBLm_field_set(unit, &vlan_entry, 4032 LSB_VLAN_BMf, ls_bits); 4033 4034 if ((ls_bits[0] == 0) && (ls_bits[1] == 0)) { 4035 /* Wiped out the entry */ 4036 /* Record before overwrite */ 4037 next_vlan_ptr = 4038 soc_MMU_IPMC_VLAN_TBLm_field32_get(unit, 4039 &vlan_entry, NEXTPTRf); 4040 soc_MMU_IPMC_VLAN_TBLm_field32_set(unit, 4041 &vlan_entry, MSB_VLANf, 0); 4042 soc_MMU_IPMC_VLAN_TBLm_field32_set(unit, 4043 &vlan_entry, NEXTPTRf, 0); 4044 if (last_vlan_ptr == 0) { 4045 /* First entry for this (group, port) */ 4046 if (vlan_ptr == next_vlan_ptr) { 4047 /* Only link in chain */ 4048 next_vlan_ptr = 0; 4049 } 4050 if ((rv = _fb_ipmc_vlan_ptr(unit, ipmc_id, port, 4051 &next_vlan_ptr, 0, 1)) < 0) { 4052 goto del_done; 4053 } 4054 } else { 4055 /* Link over with last entry */ 4056 if (vlan_ptr == next_vlan_ptr) { 4057 /* If this is end of chain, end on previous link */ 4058 next_vlan_ptr = last_vlan_ptr; 4059 } 4060 soc_MMU_IPMC_VLAN_TBLm_field32_set(unit, 4061 &prev_vlan_entry, NEXTPTRf, next_vlan_ptr); 4062 if ((rv = WRITE_MMU_IPMC_VLAN_TBLm(unit, 4063 MEM_BLOCK_ALL, last_vlan_ptr, 4064 &prev_vlan_entry)) < 0) { 4065 goto del_done; 4066 } 4067 } 4068 4069 IPMC_REPL_VE_USED_CLR(unit, vlan_ptr); 4070 } 4071 4072 if ((rv = WRITE_MMU_IPMC_VLAN_TBLm(unit, 4073 MEM_BLOCK_ALL, vlan_ptr, &vlan_entry)) < 0) { 4074 goto del_done; 4075 } 4076 4077 IPMC_REPL_PORT_VLAN_COUNT(unit, port, ipmc_id)--; 4078 4079 goto del_done; 4080 } 4081 4082 last_vlan_ptr = vlan_ptr; 4083 vlan_ptr = soc_MMU_IPMC_VLAN_TBLm_field32_get(unit, 4084 &vlan_entry, NEXTPTRf); 4085 sal_memcpy(&prev_vlan_entry, &vlan_entry, 4086 sizeof(mmu_ipmc_vlan_tbl_entry_t)); 4087 4088 soc_MMU_IPMC_VLAN_TBLm_field_get(unit, &vlan_entry, 4089 LSB_VLAN_BMf, ls_bits); 4090 vlan_count += 4091 _shr_popcount(ls_bits[0]) + _shr_popcount(ls_bits[1]); 4092 if (vlan_count >= IPMC_REPL_PORT_VLAN_COUNT(unit, port, ipmc_id)) { 4093 rv = BCM_E_NOT_FOUND; 4094 goto del_done; 4095 } 4096 } 4097 4098 rv = BCM_E_NOT_FOUND; 4099 4100 del_done: 4101 if (soc_feature(unit, soc_feature_ipmc_repl_freeze)) { 4102 rvth = _bcm_fb_ipmc_repl_thaw(unit); 4103 rv = (rv < 0) ? rv : rvth; 4104 } 4105 IPMC_REPL_UNLOCK(unit); 4106 return rv; 4107 } 4108 4109 4110 int 4111 _bcm_fb_ipmc_egress_intf_add(int unit, int ipmc_id, bcm_port_t port, 4112 int id, int is_l3) 4113 { 4114 int *if_array = NULL; 4115 int intf_num, intf_max, alloc_size, rv = BCM_E_NONE; 4116 bcm_l3_intf_t l3_intf; 4117 int is_l3_intf = 0, int_l3_nh_created = -1; 4118 int intf_index = 0, nh_index = 0; 4119 uint32 nh_flags; 4120 bcm_l3_egress_t nh_info; 4121 egr_l3_next_hop_entry_t egr_nh; 4122 4123 if (!SOC_IPMCREPLSHR_GET(unit) && !SOC_IS_TRX(unit) && 4124 !soc_feature(unit, soc_feature_ipmc_repl_penultimate)) { 4125 return BCM_E_UNAVAIL; 4126 } 4127 4128 IPMC_REPL_INIT(unit); 4129 IPMC_REPL_ID(unit, ipmc_id); 4130 REPL_PORT_CHECK(unit, port); 4131 4132 intf_max = IPMC_REPL_INTF_TOTAL(unit); 4133 alloc_size = intf_max * sizeof(int); 4134 if_array = sal_alloc(alloc_size, "IPMC repl interface array"); 4135 if (if_array == NULL) { 4136 return BCM_E_MEMORY; 4137 } 4138 4139 IPMC_REPL_LOCK(unit); 4140 rv = bcm_fb_ipmc_egress_intf_get(unit, ipmc_id, port, intf_max, 4141 if_array, &intf_num); 4142 if (BCM_SUCCESS(rv)) { 4143 if (intf_num < intf_max) { 4144 if (soc_feature(unit, soc_feature_l3mc_use_egress_next_hop)) { 4145 if (BCM_XGS3_L3_EGRESS_IDX_VALID(unit, id)) { 4146 id = id - BCM_XGS3_EGRESS_IDX_MIN(unit); 4147 } else { 4148 /* 4149 * SDK-111244: to request L3 INTF index format for 4150 * adding L3MC replication as well. 4151 * 4152 * Due to the L3_INTF can be shared by L3_NH, once user 4153 * request IPMC replication through L3_INTF index, an 4154 * internal L3_NH entry will always created internally 4155 * for such request. 4156 */ 4157 is_l3_intf = TRUE; 4158 intf_index = id; 4159 4160 /* index validation */ 4161 if (intf_index >= BCM_XGS3_L3_IF_TBL_SIZE(unit)) { 4162 rv = BCM_E_PARAM; 4163 goto intf_add_done; 4164 } else if (!BCM_L3_INTF_USED_GET(unit, intf_index)) { 4165 rv = BCM_E_NOT_FOUND; 4166 goto intf_add_done; 4167 } 4168 4169 if (IPMC_REPL_L3_INTF_TO_L3_NH_IPMC(unit, intf_index) != 4170 REPL_NH_INDEX_UNALLOCATED) { 4171 id = IPMC_REPL_L3_INTF_TO_L3_NH_IPMC(unit, intf_index); 4172 _bcm_xgs3_nh_ref_cnt_incr(unit, id); 4173 } else { 4174 bcm_l3_egress_t_init(&nh_info); 4175 nh_flags = _BCM_L3_SHR_MATCH_DISABLE | 4176 _BCM_L3_SHR_WRITE_DISABLE; 4177 rv = bcm_xgs3_nh_add(unit, nh_flags, &nh_info, 4178 &nh_index); 4179 if (BCM_FAILURE(rv)) { 4180 goto intf_add_done; 4181 } 4182 4183 int_l3_nh_created = nh_index; 4184 4185 sal_memset(&egr_nh, 0, 4186 sizeof(egr_l3_next_hop_entry_t)); 4187 /* ENTRY_TYPEf=7 is for L3MC view */ 4188 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 4189 ENTRY_TYPEf, 7); 4190 4191 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 4192 L3MC__INTF_NUMf, id); 4193 4194 rv = soc_mem_write(unit, EGR_L3_NEXT_HOPm, 4195 MEM_BLOCK_ALL, nh_index, &egr_nh); 4196 if (BCM_FAILURE(rv)) { 4197 goto intf_add_done; 4198 } 4199 4200 LOG_VERBOSE(BSL_LS_BCM_IPMC, (BSL_META_U(unit, 4201 "unit %d, IPMC replication for L3_INTF(id=%d):" 4202 "L3_NH(id=%d) is created!\n"), 4203 unit, id, nh_index)); 4204 4205 /* change id from L3_INTF to L3_NH index */ 4206 id = nh_index; 4207 IPMC_REPL_L3_INTF_TO_L3_NH_IPMC(unit, intf_index) = id; 4208 IPMC_REPL_L3_NH_TO_L3_INTF_IPMC(unit, id) = intf_index; 4209 } 4210 } 4211 } else { 4212 if (BCM_XGS3_DVP_EGRESS_IDX_VALID(unit, id)) { 4213 id = id - BCM_XGS3_DVP_EGRESS_IDX_MIN(unit); 4214 } 4215 } 4216 if_array[intf_num++] = id; 4217 4218 /* For IPMC, check port is a member of the L3 interface's VLAN. 4219 * Performing this check here is more efficient than performing 4220 * it in bcm_fb_ipmc_egress_intf_set. 4221 */ 4222 if ((uint32)id > IPMC_REPL_INTF_TOTAL(unit)) { 4223 rv = BCM_E_PARAM; 4224 goto intf_add_done; 4225 } 4226 4227 if (is_l3) { 4228 bcm_l3_intf_t_init(&l3_intf); 4229 4230 if (soc_feature(unit, soc_feature_l3mc_use_egress_next_hop)) { 4231 if (is_l3_intf){ 4232 l3_intf.l3a_intf_id = intf_index; 4233 } else { 4234 bcm_l3_egress_t egr_nh; 4235 4236 rv = bcm_xgs3_nh_get(unit, id, &egr_nh); 4237 if (BCM_FAILURE(rv)) { 4238 goto intf_add_done; 4239 } 4240 l3_intf.l3a_intf_id = egr_nh.intf; 4241 } 4242 } else { 4243 l3_intf.l3a_intf_id = id; 4244 } 4245 4246 if ((rv = bcm_esw_l3_intf_get(unit, &l3_intf)) < 0) { 4247 goto intf_add_done; 4248 } 4249 } 4250 4251 rv = bcm_fb_ipmc_egress_intf_set(unit, ipmc_id, port, 4252 intf_num, if_array, is_l3, FALSE); 4253 } else { 4254 rv = BCM_E_EXISTS; 4255 } 4256 } 4257 4258 intf_add_done: 4259 4260 IPMC_REPL_UNLOCK(unit); 4261 sal_free(if_array); 4262 4263 if (BCM_FAILURE(rv) && (int_l3_nh_created != -1)) { 4264 nh_index = int_l3_nh_created; 4265 if (bcm_xgs3_nh_del(unit, 0, nh_index) != BCM_E_NONE) { 4266 LOG_VERBOSE(BSL_LS_BCM_IPMC, (BSL_META_U(unit, 4267 "unit %d, can't delete internal L3_NH(id=%d)!\n"), 4268 unit, nh_index)); 4269 } 4270 } 4271 4272 return rv; 4273 } 4274 4275 int 4276 _bcm_fb_ipmc_egress_intf_delete(int unit, int ipmc_id, bcm_port_t port, 4277 int if_max, int id, int is_l3) 4278 { 4279 int intf_index = 0; 4280 int *if_array = NULL; 4281 int alloc_size, if_count, if_cur, match, rv = BCM_E_NONE; 4282 4283 if (!SOC_IPMCREPLSHR_GET(unit) && !SOC_IS_TRX(unit) && 4284 !soc_feature(unit, soc_feature_ipmc_repl_penultimate)) { 4285 return BCM_E_CONFIG; 4286 } 4287 4288 IPMC_REPL_INIT(unit); 4289 IPMC_REPL_ID(unit, ipmc_id); 4290 REPL_PORT_CHECK(unit, port); 4291 4292 if (!IPMC_REPL_PORT_VLAN_COUNT(unit, port, ipmc_id)) { 4293 return BCM_E_NOT_FOUND; 4294 } else if ((if_max <= 0) || ((uint32)if_max > IPMC_REPL_INTF_TOTAL(unit))) { 4295 return BCM_E_PARAM; 4296 } 4297 alloc_size = if_max * sizeof(int); 4298 if_array = sal_alloc(alloc_size, "IPMC repl interface array"); 4299 if (if_array == NULL) { 4300 return BCM_E_MEMORY; 4301 } 4302 4303 IPMC_REPL_LOCK(unit); 4304 rv = bcm_fb_ipmc_egress_intf_get(unit, ipmc_id, port, if_max, 4305 if_array, &if_count); 4306 if (BCM_SUCCESS(rv)) { 4307 /* id now is still at encap_id format. Need to modify for GH case. */ 4308 if (soc_feature(unit, soc_feature_l3mc_use_egress_next_hop)) { 4309 if (BCM_XGS3_L3_EGRESS_IDX_VALID(unit, id)) { 4310 id = id - BCM_XGS3_EGRESS_IDX_MIN(unit); 4311 } else { 4312 /* 4313 * SDK-111244 : to request L3 INTF index format for 4314 * deleting L3MC replication as well. 4315 */ 4316 intf_index = id; 4317 4318 /* index validation */ 4319 if (intf_index >= BCM_XGS3_L3_IF_TBL_SIZE(unit)) { 4320 rv = BCM_E_PARAM; 4321 goto intf_del_done; 4322 } else if (!BCM_L3_INTF_USED_GET(unit, intf_index)) { 4323 rv = BCM_E_NOT_FOUND; 4324 goto intf_del_done; 4325 } 4326 4327 if (IPMC_REPL_L3_INTF_TO_L3_NH_IPMC(unit, intf_index) == 4328 REPL_NH_INDEX_UNALLOCATED) { 4329 rv = BCM_E_NOT_FOUND; 4330 goto intf_del_done; 4331 } 4332 4333 /* reassign "id" for further delete process */ 4334 id = IPMC_REPL_L3_INTF_TO_L3_NH_IPMC(unit, intf_index); 4335 } 4336 } 4337 4338 match = FALSE; 4339 for (if_cur = 0; if_cur < if_count; if_cur++) { 4340 if (match) { 4341 if_array[if_cur - 1] = if_array[if_cur]; 4342 } else { 4343 if (if_array[if_cur] == id) { 4344 match = TRUE; 4345 } 4346 } 4347 } 4348 if (match) { 4349 if_count--; 4350 rv = bcm_fb_ipmc_egress_intf_set(unit, ipmc_id, port, 4351 if_count, if_array, is_l3, FALSE); 4352 } else { 4353 rv = BCM_E_NOT_FOUND; 4354 } 4355 } 4356 4357 intf_del_done: 4358 4359 IPMC_REPL_UNLOCK(unit); 4360 sal_free(if_array); 4361 return rv; 4362 } 4363 4364 /* 4365 * Function: 4366 * _bcm_fb_repl_list_compare 4367 * Description: 4368 * Compare HW list starting at vlan_index to the VLAN list contained 4369 * in vlan_vec. 4370 */ 4371 4372 STATIC int 4373 _bcm_fb_repl_list_compare(int unit, int vlan_index, 4374 SHR_BITDCL *intf_vec) 4375 { 4376 uint32 ms_bit, hw_ms_bit, ms_max; 4377 uint32 ls_bits[2], hw_ls_bits[2]; 4378 mmu_ipmc_vlan_tbl_entry_t vlan_entry; 4379 int vlan_ptr, last_vlan_ptr; 4380 int intf_less32 = 0; /* L3_INTF support <=32 */ 4381 4382 last_vlan_ptr = -1; 4383 vlan_ptr = vlan_index; 4384 ms_max = _SHR_BITDCLSIZE(IPMC_REPL_INTF_TOTAL(unit))/2; /* 32 -> 64 */ 4385 4386 if (ms_max == 0) { 4387 intf_less32 = 1; 4388 ms_max = 1; 4389 } 4390 4391 for (ms_bit = 0; ms_bit < ms_max; ms_bit++) { 4392 ls_bits[0] = intf_vec[2 * ms_bit + 0]; 4393 if (intf_less32) { 4394 ls_bits[1] = 0; 4395 } else { 4396 ls_bits[1] = intf_vec[2 * ms_bit + 1]; 4397 } 4398 4399 if ((ls_bits[0] != 0) || (ls_bits[1] != 0)) { 4400 if (vlan_ptr == last_vlan_ptr) { /* HW list end, not app list */ 4401 return BCM_E_NOT_FOUND; 4402 } 4403 SOC_IF_ERROR_RETURN 4404 (READ_MMU_IPMC_VLAN_TBLm(unit, MEM_BLOCK_ANY, 4405 vlan_ptr, &vlan_entry)); 4406 hw_ms_bit = soc_MMU_IPMC_VLAN_TBLm_field32_get(unit, 4407 &vlan_entry, MSB_VLANf); 4408 soc_MMU_IPMC_VLAN_TBLm_field_get(unit, &vlan_entry, 4409 LSB_VLAN_BMf, hw_ls_bits); 4410 if ((hw_ms_bit != ms_bit) || (ls_bits[0] != hw_ls_bits[0]) || 4411 (ls_bits[1] != hw_ls_bits[1])) { 4412 return BCM_E_NOT_FOUND; 4413 } 4414 last_vlan_ptr = vlan_ptr; 4415 vlan_ptr = soc_MMU_IPMC_VLAN_TBLm_field32_get(unit, 4416 &vlan_entry, NEXTPTRf); 4417 } 4418 } 4419 return BCM_E_NONE; 4420 } 4421 4422 /* 4423 * Function: 4424 * _bcm_fb_repl_list_free 4425 * Description: 4426 * Release the IPMC_VLAN entries in the HW list starting at start_ptr. 4427 */ 4428 4429 STATIC int 4430 _bcm_fb_repl_list_free(int unit, int start_ptr) 4431 { 4432 mmu_ipmc_vlan_tbl_entry_t vlan_entry; 4433 int vlan_ptr, last_vlan_ptr; 4434 4435 last_vlan_ptr = -1; 4436 vlan_ptr = start_ptr; 4437 4438 while (vlan_ptr != last_vlan_ptr) { 4439 SOC_IF_ERROR_RETURN 4440 (READ_MMU_IPMC_VLAN_TBLm(unit, MEM_BLOCK_ANY, 4441 vlan_ptr, &vlan_entry)); 4442 last_vlan_ptr = vlan_ptr; 4443 vlan_ptr = soc_MMU_IPMC_VLAN_TBLm_field32_get(unit, 4444 &vlan_entry, NEXTPTRf); 4445 IPMC_REPL_VE_USED_CLR(unit, last_vlan_ptr); 4446 } 4447 4448 return BCM_E_NONE; 4449 } 4450 4451 /* 4452 * Function: 4453 * _bcm_fb_repl_list_write 4454 * Description: 4455 * Write the VLAN list contained in vlan_vec into the HW table. 4456 * Return the start_index and total VLAN count. 4457 */ 4458 4459 STATIC int 4460 _bcm_fb_repl_list_write(int unit, int *start_index, int *count, 4461 SHR_BITDCL *intf_vec) 4462 { 4463 uint32 ms_bit, ms_max; 4464 uint32 ls_bits[2]; 4465 mmu_ipmc_vlan_tbl_entry_t vlan_entry; 4466 int vlan_ptr, last_vlan_ptr; 4467 #if defined(BCM_BRADLEY_SUPPORT) || defined(BCM_TRIUMPH_SUPPORT) 4468 int last_write_ptr = -1; 4469 #endif 4470 int vlan_count = 0; 4471 4472 int intf_less32 = 0; /* L3_INTF support <=32 */ 4473 last_vlan_ptr = -1; 4474 4475 ms_max = _SHR_BITDCLSIZE(IPMC_REPL_INTF_TOTAL(unit)) / 2; /* 32 -> 64 */ 4476 4477 if (ms_max == 0) { 4478 intf_less32 = 1; 4479 ms_max = 1; 4480 } 4481 4482 for (ms_bit = 0; ms_bit < ms_max; ms_bit++) { 4483 ls_bits[0] = intf_vec[2 * ms_bit + 0]; 4484 if (intf_less32) { 4485 ls_bits[1] = 0; 4486 } else { 4487 ls_bits[1] = intf_vec[2 * ms_bit + 1]; 4488 } 4489 4490 if ((ls_bits[0] != 0) || (ls_bits[1] != 0)) { 4491 vlan_ptr = _fb_ipmc_repl_next_free_ptr(unit); 4492 if (last_vlan_ptr > 0) { 4493 /* Write previous non-zero entry */ 4494 soc_MMU_IPMC_VLAN_TBLm_field32_set(unit, 4495 &vlan_entry, NEXTPTRf, 4496 (vlan_ptr > 0) ? vlan_ptr : last_vlan_ptr); 4497 /* If vlan_ptr <= 0, terminate so 4498 * later cleanup can remove the chain. */ 4499 SOC_IF_ERROR_RETURN 4500 (WRITE_MMU_IPMC_VLAN_TBLm(unit, 4501 MEM_BLOCK_ALL, last_vlan_ptr, &vlan_entry)); 4502 #if defined(BCM_BRADLEY_SUPPORT) || defined(BCM_TRIUMPH_SUPPORT) 4503 last_write_ptr = last_vlan_ptr; 4504 #endif 4505 if (vlan_ptr < 0) { 4506 _bcm_fb_repl_list_free(unit, *start_index); 4507 return BCM_E_RESOURCE; 4508 } 4509 } else { 4510 if (vlan_ptr < 0) { 4511 return BCM_E_RESOURCE; 4512 } 4513 *start_index = vlan_ptr; 4514 } 4515 sal_memset(&vlan_entry, 0, sizeof(vlan_entry)); 4516 soc_MMU_IPMC_VLAN_TBLm_field32_set(unit, &vlan_entry, 4517 MSB_VLANf, ms_bit); 4518 soc_MMU_IPMC_VLAN_TBLm_field_set(unit, &vlan_entry, 4519 LSB_VLAN_BMf, ls_bits); 4520 IPMC_REPL_VE_USED_SET(unit, vlan_ptr); 4521 vlan_count += 4522 _shr_popcount(ls_bits[0]) + _shr_popcount(ls_bits[1]); 4523 last_vlan_ptr = vlan_ptr; 4524 } 4525 } 4526 if (last_vlan_ptr > 0) { 4527 /* Write final entry */ 4528 soc_MMU_IPMC_VLAN_TBLm_field32_set(unit, 4529 &vlan_entry, NEXTPTRf, last_vlan_ptr); 4530 SOC_IF_ERROR_RETURN 4531 (WRITE_MMU_IPMC_VLAN_TBLm(unit, 4532 MEM_BLOCK_ALL, last_vlan_ptr, &vlan_entry)); 4533 4534 #if defined(BCM_BRADLEY_SUPPORT) || defined(BCM_TRIUMPH_SUPPORT) 4535 if (soc_feature(unit, soc_feature_ipmc_repl_penultimate) && 4536 (last_write_ptr > 0)) { 4537 soc_MMU_IPMC_VLAN_TBLm_field_get(unit, &vlan_entry, 4538 LSB_VLAN_BMf, ls_bits); 4539 if ((_shr_popcount(ls_bits[0]) + 4540 _shr_popcount(ls_bits[1])) == 1) { 4541 /* Mark previous link with "last" flag */ 4542 SOC_IF_ERROR_RETURN 4543 (READ_MMU_IPMC_VLAN_TBLm(unit, 4544 MEM_BLOCK_ANY, last_write_ptr, &vlan_entry)); 4545 soc_MMU_IPMC_VLAN_TBLm_field32_set(unit, &vlan_entry, 4546 LASTf, 1); 4547 SOC_IF_ERROR_RETURN 4548 (WRITE_MMU_IPMC_VLAN_TBLm(unit, 4549 MEM_BLOCK_ALL, last_write_ptr, &vlan_entry)); 4550 } 4551 } 4552 #endif /* BCM_BRADLEY_SUPPORT || BCM_TRIUMPH_SUPPORT */ 4553 } 4554 4555 *count = vlan_count; 4556 return BCM_E_NONE; 4557 } 4558 4559 4560 /* 4561 * Function: 4562 * _bcm_fb_ipmc_egress_intf_nh_clear 4563 * Description: 4564 * clear the internal created EGR_L3_NEXT_HOP entry 4565 * especially for the IPMC needs. 4566 */ 4567 4568 STATIC int 4569 _bcm_fb_ipmc_egress_intf_nh_clear( 4570 int unit, 4571 int ipmc_id, 4572 bcm_port_t port, 4573 int if_count, 4574 bcm_if_t *if_array) 4575 { 4576 int *nh_array = NULL; 4577 int rv = BCM_E_NONE, rv1 = BCM_E_NONE, match; 4578 int if_num, nh_num, nh_count, if_max, nh_id, nh2intf; 4579 int alloc_size; 4580 bcm_l3_egress_t nh_info; 4581 4582 4583 IPMC_REPL_INIT(unit); 4584 IPMC_REPL_ID(unit, ipmc_id); 4585 REPL_PORT_CHECK(unit, port); 4586 4587 if ((uint32)if_count > IPMC_REPL_INTF_TOTAL(unit)) { 4588 return BCM_E_PARAM; 4589 } 4590 if_max = IPMC_REPL_INTF_TOTAL(unit); 4591 4592 alloc_size = IPMC_REPL_INTF_TOTAL(unit) * sizeof(int); 4593 nh_array = sal_alloc(alloc_size, "IPMC repl interface array"); 4594 if (nh_array == NULL) { 4595 return BCM_E_MEMORY; 4596 } 4597 4598 4599 IPMC_REPL_LOCK(unit); 4600 /* the intf get from bellow api is NH index */ 4601 if ((rv = bcm_fb_ipmc_egress_intf_get(unit, ipmc_id, port, if_max, 4602 nh_array, &nh_count)) < 0) { 4603 goto internal_nh_del_done; 4604 } 4605 4606 /* Check whether the old if_array is included in the new if_array */ 4607 for (nh_num = 0; nh_num < nh_count; nh_num++) { 4608 match = 0; 4609 /* the NH index is not internally created */ 4610 if (IPMC_REPL_L3_NH_TO_L3_INTF_IPMC(unit, nh_array[nh_num]) == 4611 REPL_L3_INTF_UNALLOCATED) { 4612 continue; 4613 } 4614 for (if_num = 0; if_num < if_count; if_num++) { 4615 if ((uint32)if_array[if_num] > IPMC_REPL_INTF_TOTAL(unit)) { 4616 rv = BCM_E_PARAM; 4617 goto internal_nh_del_done; 4618 } 4619 if (soc_feature(unit, soc_feature_l3mc_use_egress_next_hop)) { 4620 nh_id = if_array[if_num]; 4621 } 4622 else { 4623 nh_id = IPMC_REPL_L3_INTF_TO_L3_NH_IPMC(unit, if_array[if_num]); 4624 } 4625 /* if match */ 4626 if ((nh_id != REPL_NH_INDEX_UNALLOCATED) && 4627 (nh_id == nh_array[nh_num])) { 4628 match = 1; 4629 break; 4630 } 4631 } 4632 /* Delete the internal created NH index*/ 4633 if (match == 0) { 4634 4635 /* remove this internal created L3_NH, when ref_count=1 */ 4636 if ((rv = bcm_xgs3_nh_del(unit, 0, nh_array[nh_num])) < 0 ) { 4637 goto internal_nh_del_done; 4638 } 4639 /* make sure the NH is being deleted from HW */ 4640 bcm_l3_egress_t_init(&nh_info); 4641 rv1 = bcm_xgs3_nh_get(unit, nh_array[nh_num], &nh_info); 4642 if (rv1 == BCM_E_NOT_FOUND) { 4643 nh2intf = IPMC_REPL_L3_NH_TO_L3_INTF_IPMC(unit, 4644 nh_array[nh_num]); 4645 IPMC_REPL_L3_INTF_TO_L3_NH_IPMC( 4646 unit, nh2intf) = REPL_NH_INDEX_UNALLOCATED; 4647 IPMC_REPL_L3_NH_TO_L3_INTF_IPMC( 4648 unit, nh_array[nh_num]) = REPL_L3_INTF_UNALLOCATED; 4649 LOG_VERBOSE(BSL_LS_BCM_IPMC, (BSL_META_U(unit, 4650 "unit %d, internal L3_NH(id=%d) " 4651 "is deleted\n"), 4652 unit, nh_array[nh_num])); 4653 } 4654 } 4655 } 4656 4657 internal_nh_del_done: 4658 IPMC_REPL_UNLOCK(unit); 4659 sal_free(nh_array); 4660 return rv; 4661 } 4662 4663 /* 4664 * Function: 4665 * bcm_fb_ipmc_egress_intf_set 4666 * Purpose: 4667 * Assign set of egress interfaces to port's replication list for chosen 4668 * IPMC group. 4669 * Parameters: 4670 * unit - StrataSwitch PCI device unit number. 4671 * ipmc_id - The index number. 4672 * port - port to list. 4673 * if_count - number of interfaces in replication list. 4674 * if_array - (IN) List of interface numbers. 4675 * is_l3 - (IN) FALSE if list contains non-L3 interface (ex. MPLS/SUBPORT) 4676 * check_port - (IN) If is_l3 = TRUE, this parameter controls whether to 4677 * check the given port is a member in each L3 interface's 4678 * VLAN. This check should be disabled when not needed, 4679 * in order to improve performance. 4680 * Returns: 4681 * BCM_E_XXX 4682 */ 4683 4684 int 4685 bcm_fb_ipmc_egress_intf_set(int unit, int ipmc_id, bcm_port_t port, 4686 int if_count, bcm_if_t *if_array, int is_l3, 4687 int check_port) 4688 { 4689 int rvth = BCM_E_NONE, rv = BCM_E_NONE; 4690 SHR_BITDCL *intf_vec = NULL; 4691 int list_start_ptr, prev_start_ptr; 4692 int alloc_size, repl_hash, vlan_count, last_flag; 4693 int if_num; 4694 bcm_l3_intf_t l3_intf; 4695 _bcm_repl_list_info_t *rli_start, *rli_current, *rli_prev; 4696 4697 if (!SOC_IS_FBX(unit)) { 4698 return BCM_E_UNAVAIL; 4699 } 4700 4701 if (!SOC_IPMCREPLSHR_GET(unit) && !SOC_IS_HURRICANEX(unit) && 4702 !SOC_IS_GREYHOUND(unit) && !SOC_IS_GREYHOUND2(unit) && 4703 !soc_feature(unit, soc_feature_ipmc_repl_penultimate)) { 4704 return BCM_E_CONFIG; 4705 } 4706 4707 IPMC_REPL_INIT(unit); 4708 IPMC_REPL_ID(unit, ipmc_id); 4709 REPL_PORT_CHECK(unit, port); 4710 4711 if ((uint32)if_count > IPMC_REPL_INTF_TOTAL(unit)) { 4712 return BCM_E_PARAM; 4713 } 4714 4715 alloc_size = SHR_BITALLOCSIZE(IPMC_REPL_INTF_TOTAL(unit)); 4716 intf_vec = sal_alloc(alloc_size, "IPMC repl interface vector"); 4717 if (intf_vec == NULL) { 4718 return BCM_E_MEMORY; 4719 } 4720 sal_memset(intf_vec, 0, alloc_size); 4721 4722 IPMC_REPL_LOCK(unit); 4723 if (soc_feature(unit, soc_feature_ipmc_repl_freeze) && 4724 ((rv = _bcm_fb_ipmc_repl_freeze(unit)) < 0)) { 4725 IPMC_REPL_UNLOCK(unit); 4726 sal_free(intf_vec); 4727 return rv; 4728 } 4729 4730 /* Interface validation and vector construction */ 4731 for (if_num = 0; if_num < if_count; if_num++) { 4732 if ((uint32)if_array[if_num] > IPMC_REPL_INTF_TOTAL(unit)) { 4733 rv = BCM_E_PARAM; 4734 goto intf_set_done; 4735 } 4736 if (is_l3 && check_port) { 4737 bcm_l3_intf_t_init(&l3_intf); 4738 4739 if (soc_feature(unit, soc_feature_l3mc_use_egress_next_hop)) { 4740 bcm_l3_egress_t egr_nh; 4741 4742 rv = bcm_xgs3_nh_get(unit, if_array[if_num], &egr_nh); 4743 if (BCM_FAILURE(rv)) { 4744 goto intf_set_done; 4745 } 4746 l3_intf.l3a_intf_id = egr_nh.intf; 4747 } else { 4748 l3_intf.l3a_intf_id = if_array[if_num]; 4749 } 4750 4751 if ((rv = bcm_esw_l3_intf_get(unit, &l3_intf)) < 0) { 4752 goto intf_set_done; 4753 } 4754 } 4755 SHR_BITSET(intf_vec, if_array[if_num]); 4756 } 4757 4758 /* Check previous group pointer */ 4759 if ((rv = _fb_ipmc_vlan_ptr(unit, ipmc_id, port, 4760 &prev_start_ptr, 0, 0)) < 0) { 4761 goto intf_set_done; 4762 } 4763 4764 /* Search for list already in table */ 4765 rli_start = IPMC_REPL_LIST_INFO(unit); 4766 4767 repl_hash = 4768 _shr_crc32b(0, (uint8 *)intf_vec, IPMC_REPL_INTF_TOTAL(unit)); 4769 4770 for (rli_current = rli_start; rli_current != NULL; 4771 rli_current = rli_current->next) { 4772 if (repl_hash == rli_current->hash) { 4773 rv = _bcm_fb_repl_list_compare(unit, rli_current->index, 4774 intf_vec); 4775 if (rv == BCM_E_NOT_FOUND) { 4776 continue; /* Not a match */ 4777 } else if (rv < 0) { 4778 goto intf_set_done; /* Access error */ 4779 } else { 4780 break; /* Match */ 4781 } 4782 } 4783 } 4784 4785 if (rli_current != NULL) { 4786 /* delete the internal created NH idx when it is removed out of IPMC*/ 4787 if (soc_feature(unit, soc_feature_l3mc_use_egress_next_hop)) { 4788 if ((rv = _bcm_fb_ipmc_egress_intf_nh_clear( 4789 unit, ipmc_id, port, if_count, if_array)) < 0){ 4790 goto intf_set_done; 4791 } 4792 } 4793 /* Found a match, point to here and increase reference count */ 4794 if (prev_start_ptr == rli_current->index) { 4795 /* We're already pointing to this list, so done */ 4796 rv = BCM_E_NONE; 4797 goto intf_set_done; 4798 } else { 4799 list_start_ptr = rli_current->index; 4800 vlan_count = rli_current->list_size; 4801 } 4802 } else { 4803 /* Not a match, make a new chain */ 4804 if ((rv = _bcm_fb_repl_list_write(unit, &list_start_ptr, 4805 &vlan_count, intf_vec)) < 0) { 4806 goto intf_set_done; 4807 } 4808 4809 if (vlan_count > 0) { 4810 /* Update data structures */ 4811 alloc_size = sizeof(_bcm_repl_list_info_t); 4812 rli_current = sal_alloc(alloc_size, "IPMC repl list info"); 4813 if (rli_current == NULL) { 4814 /* Release list */ 4815 _bcm_fb_repl_list_free(unit, list_start_ptr); 4816 rv = BCM_E_MEMORY; 4817 goto intf_set_done; 4818 } 4819 sal_memset(rli_current, 0, alloc_size); 4820 rli_current->index = list_start_ptr; 4821 rli_current->hash = repl_hash; 4822 rli_current->next = rli_start; 4823 rli_current->list_size = vlan_count; 4824 IPMC_REPL_LIST_INFO(unit) = rli_current; 4825 rli_start = rli_current; 4826 } 4827 /* delete the internal created NH idx when it is removed out of IPMC*/ 4828 if (soc_feature(unit, soc_feature_l3mc_use_egress_next_hop)) { 4829 if ((rv = _bcm_fb_ipmc_egress_intf_nh_clear( 4830 unit, ipmc_id, port, if_count, if_array)) < 0){ 4831 goto intf_set_done; 4832 } 4833 } 4834 } 4835 4836 last_flag = (vlan_count == 1); 4837 if (vlan_count > 0) { 4838 if ((rv = _fb_ipmc_vlan_ptr(unit, ipmc_id, port, 4839 &list_start_ptr, last_flag, 1)) < 0) { 4840 if (rli_current->refcount == 0) { 4841 /* This was new */ 4842 _bcm_fb_repl_list_free(unit, list_start_ptr); 4843 IPMC_REPL_LIST_INFO(unit) = rli_current->next; 4844 sal_free(rli_current); 4845 } 4846 goto intf_set_done; 4847 } 4848 4849 (rli_current->refcount)++; 4850 /* we don't need this rli_current anymore */ 4851 } else if (prev_start_ptr != 0) { 4852 list_start_ptr = 0; 4853 if ((rv = _fb_ipmc_vlan_ptr(unit, ipmc_id, port, 4854 &list_start_ptr, last_flag, 1)) < 0) { 4855 goto intf_set_done; 4856 } 4857 } 4858 4859 IPMC_REPL_PORT_VLAN_COUNT(unit, port, ipmc_id) = vlan_count; 4860 4861 if (prev_start_ptr != 0) { 4862 rli_prev = NULL; 4863 for (rli_current = rli_start; rli_current != NULL; 4864 rli_current = rli_current->next) { 4865 if (prev_start_ptr == rli_current->index) { 4866 (rli_current->refcount)--; 4867 if (rli_current->refcount == 0) { 4868 /* Free these linked list entries */ 4869 rv = _bcm_fb_repl_list_free(unit, prev_start_ptr); 4870 /* If we have an error, we'll fall out anyway */ 4871 if (rli_prev == NULL) { 4872 IPMC_REPL_LIST_INFO(unit) = rli_current->next; 4873 } else { 4874 rli_prev->next = rli_current->next; 4875 } 4876 sal_free(rli_current); 4877 } 4878 break; 4879 } 4880 rli_prev = rli_current; 4881 } 4882 } 4883 4884 intf_set_done: 4885 if (soc_feature(unit, soc_feature_ipmc_repl_freeze)) { 4886 rvth = _bcm_fb_ipmc_repl_thaw(unit); 4887 rv = (rv < 0) ? rv : rvth; 4888 } 4889 IPMC_REPL_UNLOCK(unit); 4890 if (intf_vec != NULL) { 4891 sal_free(intf_vec); 4892 } 4893 return rv; 4894 } 4895 4896 /* 4897 * Function: 4898 * bcm_fb_ipmc_egress_intf_get 4899 * Purpose: 4900 * Retreieve set of egress interfaces in port's replication list 4901 * for chosen IPMC group. 4902 * Parameters: 4903 * unit - StrataSwitch PCI device unit number. 4904 * ipmc_id - The index number. 4905 * port - port to list. 4906 * if_max - maximum number of interfaces in replication list. 4907 * if_array - (OUT) List of interface numbers. 4908 * if_count - (OUT) number of interfaces returned in replication list. 4909 * Returns: 4910 * BCM_E_XXX 4911 * Notes: 4912 * If the input parameter if_max = 0, return in the output parameter 4913 * if_count the total number of interfaces in the specified multicast 4914 * group's replication list. 4915 */ 4916 4917 int 4918 bcm_fb_ipmc_egress_intf_get(int unit, int ipmc_id, bcm_port_t port, 4919 int if_max, bcm_if_t *if_array, int *if_count) 4920 { 4921 int rv = BCM_E_NONE; 4922 uint32 ms_bit; 4923 uint32 ls_bits[2]; 4924 mmu_ipmc_vlan_tbl_entry_t vlan_entry; 4925 int vlan_ptr, last_vlan_ptr; 4926 uint32 vlan_count; 4927 int ls_pos; 4928 int rvth = BCM_E_NONE; 4929 4930 if (!SOC_IS_FBX(unit)) { 4931 return BCM_E_UNAVAIL; 4932 } 4933 4934 if (!SOC_IPMCREPLSHR_GET(unit) && !SOC_IS_HURRICANEX(unit) && 4935 !SOC_IS_GREYHOUND(unit) && !SOC_IS_GREYHOUND2(unit) && 4936 !soc_feature(unit, soc_feature_ipmc_repl_penultimate)) { 4937 return BCM_E_CONFIG; 4938 } 4939 4940 IPMC_REPL_INIT(unit); 4941 IPMC_REPL_ID(unit, ipmc_id); 4942 REPL_PORT_CHECK(unit, port); 4943 4944 if (if_max < 0) { 4945 return BCM_E_PARAM; 4946 } 4947 4948 IPMC_REPL_LOCK(unit); 4949 if (IPMC_REPL_PORT_VLAN_COUNT(unit, port, ipmc_id) == 0) { 4950 *if_count = 0; 4951 IPMC_REPL_UNLOCK(unit); 4952 return rvth; 4953 } 4954 4955 if (soc_feature(unit, soc_feature_ipmc_repl_freeze) && 4956 ((rv = _bcm_fb_ipmc_repl_freeze(unit)) < 0)) { 4957 IPMC_REPL_UNLOCK(unit); 4958 return rv; 4959 } 4960 4961 if ((rv = _fb_ipmc_vlan_ptr(unit, ipmc_id, port, &vlan_ptr, 0, 0)) < 0) { 4962 goto intf_get_done; 4963 } 4964 last_vlan_ptr = -1; 4965 vlan_count = 0; 4966 while (vlan_ptr != last_vlan_ptr) { 4967 if ((rv = READ_MMU_IPMC_VLAN_TBLm(unit, MEM_BLOCK_ANY, 4968 vlan_ptr, &vlan_entry)) < 0) { 4969 goto intf_get_done; 4970 } 4971 ms_bit = soc_MMU_IPMC_VLAN_TBLm_field32_get(unit, 4972 &vlan_entry, MSB_VLANf); 4973 soc_MMU_IPMC_VLAN_TBLm_field_get(unit, &vlan_entry, 4974 LSB_VLAN_BMf, ls_bits); 4975 for (ls_pos = 0; ls_pos < 64; ls_pos++) { 4976 if (ls_bits[ls_pos / 32] & (1 << (ls_pos % 32))) { 4977 if (if_max == 0) { 4978 vlan_count++; 4979 } else { 4980 if_array[vlan_count++] = (ms_bit * 64) + ls_pos; 4981 if (vlan_count == (uint32)if_max) { 4982 *if_count = vlan_count; 4983 goto intf_get_done; 4984 } 4985 } 4986 } 4987 } 4988 last_vlan_ptr = vlan_ptr; 4989 vlan_ptr = soc_MMU_IPMC_VLAN_TBLm_field32_get(unit, 4990 &vlan_entry, NEXTPTRf); 4991 4992 if (vlan_count >= IPMC_REPL_PORT_VLAN_COUNT(unit, port, ipmc_id)) { 4993 break; 4994 } 4995 } 4996 4997 *if_count = vlan_count; 4998 4999 intf_get_done: 5000 if (soc_feature(unit, soc_feature_ipmc_repl_freeze)) { 5001 rvth = _bcm_fb_ipmc_repl_thaw(unit); 5002 rv = (rv < 0) ? rv : rvth; 5003 } 5004 IPMC_REPL_UNLOCK(unit); 5005 return rv; 5006 } 5007 5008 /* 5009 * Function: 5010 * bcm_fb_ipmc_repl_set 5011 * Purpose: 5012 * Assign set of VLANs provided to port's replication list for chosen 5013 * IPMC group. 5014 * Parameters: 5015 * unit - StrataSwitch PCI device unit number. 5016 * ipmc_id - The index number. 5017 * port - port to list. 5018 * vlan_vec - (IN) vector of replicated VLANs common to selected ports. 5019 * Returns: 5020 * BCM_E_XXX 5021 */ 5022 5023 int 5024 bcm_fb_ipmc_repl_set(int unit, int ipmc_id, bcm_port_t port, 5025 bcm_vlan_vector_t vlan_vec) 5026 { 5027 int rv = BCM_E_NONE; 5028 bcm_if_t *if_array = NULL; 5029 bcm_l3_intf_t l3_intf; 5030 pbmp_t pbmp, ubmp; 5031 int intf_num, intf_max, alloc_size, vid; 5032 5033 if (!SOC_IS_FBX(unit)) { 5034 return BCM_E_UNAVAIL; 5035 } 5036 5037 if (!SOC_IPMCREPLSHR_GET(unit) && !SOC_IS_HURRICANEX(unit) && 5038 !SOC_IS_GREYHOUND(unit) && !!SOC_IS_GREYHOUND2(unit) && 5039 !soc_feature(unit, soc_feature_ipmc_repl_penultimate)) { 5040 return BCM_E_CONFIG; 5041 } 5042 5043 IPMC_REPL_INIT(unit); 5044 IPMC_REPL_ID(unit, ipmc_id); 5045 REPL_PORT_CHECK(unit, port); 5046 5047 intf_max = IPMC_REPL_INTF_TOTAL(unit); 5048 alloc_size = intf_max * sizeof(bcm_if_t); 5049 if_array = sal_alloc(alloc_size, "IPMC repl interface array"); 5050 if (if_array == NULL) { 5051 return BCM_E_MEMORY; 5052 } 5053 5054 sal_memset(if_array, 0, alloc_size); 5055 intf_num = 0; 5056 for (vid = BCM_VLAN_MIN; vid < BCM_VLAN_MAX; vid++) { 5057 if (BCM_VLAN_VEC_GET(vlan_vec, vid)) { 5058 if ((rv = bcm_esw_vlan_port_get(unit, vid, &pbmp, &ubmp)) < 0) { 5059 sal_free(if_array); 5060 return rv; 5061 } 5062 if (!BCM_PBMP_MEMBER(pbmp, port)) { 5063 sal_free(if_array); 5064 return BCM_E_PARAM; 5065 } 5066 bcm_l3_intf_t_init(&l3_intf); 5067 l3_intf.l3a_vid = vid; 5068 if ((rv = bcm_esw_l3_intf_find_vlan(unit, &l3_intf)) < 0) { 5069 sal_free(if_array); 5070 return rv; 5071 } 5072 if_array[intf_num++] = l3_intf.l3a_intf_id; 5073 } 5074 } 5075 5076 rv = bcm_fb_ipmc_egress_intf_set(unit, ipmc_id, port, 5077 intf_num, if_array, 1, FALSE); 5078 5079 sal_free(if_array); 5080 return rv; 5081 } 5082 5083 #ifdef BCM_WARM_BOOT_SUPPORT 5084 /* 5085 * Reload IPMC state on XGS3 class of devices 5086 */ 5087 int 5088 _bcm_xgs3_ipmc_reinit(int unit) 5089 { 5090 int i, rv = BCM_E_NONE; 5091 int ipmc_ptr; 5092 int l3_min, l3_max; 5093 _bcm_esw_ipmc_t *info = IPMC_INFO(unit); 5094 _bcm_esw_ipmc_l3entry_t *ipmc_l3entry; 5095 5096 info->ipmc_group_info = NULL; 5097 5098 IPMC_GROUP_NUM(unit) = soc_mem_index_count(unit, L3_IPMCm); 5099 5100 info->ipmc_count = 0; 5101 5102 info->ipmc_group_info = 5103 sal_alloc(IPMC_GROUP_NUM(unit) * sizeof(_bcm_esw_ipmc_group_info_t), 5104 "IPMC group info"); 5105 if (info->ipmc_group_info == NULL) { 5106 rv = BCM_E_MEMORY; 5107 goto ret_err; 5108 } 5109 sal_memset(info->ipmc_group_info, 0, 5110 IPMC_GROUP_NUM(unit) * sizeof(_bcm_esw_ipmc_group_info_t)); 5111 5112 if (SOC_IS_FBX(unit)) { 5113 l3_entry_ipv4_multicast_entry_t *l3x_entry, *ipmc_table; 5114 l3_entry_ipv6_multicast_entry_t *l3x_v6entry, *ipmc6_table; 5115 ipmc_entry_t *l3_ipmc_entry, *l3_ipmc_table; 5116 int ipmc_tbl_sz, ipmc6_tbl_sz, l3_ipmc_tbl_sz; 5117 uint8 flags; 5118 5119 l3_min = soc_mem_index_min(unit, L3_ENTRY_IPV4_MULTICASTm); 5120 l3_max = soc_mem_index_max(unit, L3_ENTRY_IPV4_MULTICASTm); 5121 ipmc_tbl_sz = sizeof(l3_entry_ipv4_multicast_entry_t) * \ 5122 (l3_max - l3_min + 1); 5123 ipmc_table = soc_cm_salloc(unit, ipmc_tbl_sz, "ipmc tbl dma"); 5124 if (ipmc_table == NULL) { 5125 rv = BCM_E_MEMORY; 5126 goto ret_err; 5127 } 5128 5129 memset((void *)ipmc_table, 0, ipmc_tbl_sz); 5130 if ((rv = soc_mem_read_range(unit, L3_ENTRY_IPV4_MULTICASTm, 5131 MEM_BLOCK_ANY, 5132 l3_min, l3_max, ipmc_table)) < 0) { 5133 soc_cm_sfree(unit, ipmc_table); 5134 goto ret_err; 5135 } 5136 5137 for (i = l3_min; i <= l3_max; i++) { 5138 l3x_entry = soc_mem_table_idx_to_pointer(unit, 5139 L3_ENTRY_IPV4_MULTICASTm, 5140 l3_entry_ipv4_multicast_entry_t *, 5141 ipmc_table, i); 5142 5143 if (soc_L3_ENTRY_IPV4_MULTICASTm_field32_get(unit, l3x_entry, 5144 VALIDf) == 0) { 5145 continue; 5146 } 5147 5148 if (soc_L3_ENTRY_IPV4_MULTICASTm_field32_get(unit, l3x_entry, 5149 IPMCf) == 0) { 5150 continue; 5151 } 5152 5153 if (soc_L3_ENTRY_IPV4_MULTICASTm_field32_get(unit, l3x_entry, 5154 V6f)) { 5155 continue; 5156 } 5157 5158 ipmc_ptr = soc_L3_ENTRY_IPV4_MULTICASTm_field32_get(unit, 5159 l3x_entry, L3MC_INDEXf); 5160 IPMC_USED_SET(unit, ipmc_ptr); 5161 { 5162 #if defined(BCM_FIREBOLT_SUPPORT) 5163 _bcm_l3_cfg_t l3cfg; 5164 sal_memset(&l3cfg, 0, sizeof(_bcm_l3_cfg_t)); 5165 l3cfg.l3c_flags |= BCM_L3_IPMC; 5166 l3cfg.l3c_flags |= BCM_L3_HIT; 5167 if (soc_L3_ENTRY_IPV4_MULTICASTm_field32_get(unit, 5168 l3x_entry, RPEf)) { 5169 l3cfg.l3c_flags |= BCM_L3_RPE; 5170 } 5171 l3cfg.l3c_ipmc_group = soc_L3_ENTRY_IPV4_MULTICASTm_field32_get(unit, 5172 l3x_entry, GROUP_IP_ADDRf); 5173 l3cfg.l3c_src_ip_addr = soc_L3_ENTRY_IPV4_MULTICASTm_field32_get(unit, 5174 l3x_entry, SOURCE_IP_ADDRf); 5175 l3cfg.l3c_vid = soc_L3_ENTRY_IPV4_MULTICASTm_field32_get(unit, 5176 l3x_entry, VLAN_IDf); 5177 l3cfg.l3c_prio = soc_L3_ENTRY_IPV4_MULTICASTm_field32_get(unit, 5178 l3x_entry, PRIf); 5179 if (SOC_MEM_FIELD_VALID(unit, L3_ENTRY_IPV4_MULTICASTm, CLASS_IDf)) { 5180 l3cfg.l3c_lookup_class = 5181 soc_L3_ENTRY_IPV4_MULTICASTm_field32_get(unit, 5182 l3x_entry, CLASS_IDf); 5183 } 5184 rv = _bcm_xgs3_ipmc_l3entry_list_add(unit, ipmc_ptr, &l3cfg); 5185 #endif /* BCM_FIREBOLT_SUPPORT */ 5186 } 5187 5188 if (rv < 0) { 5189 soc_cm_sfree(unit, ipmc_table); 5190 goto ret_err; 5191 } 5192 } 5193 soc_cm_sfree(unit, ipmc_table); 5194 5195 /* 5196 * Deal with IPv6 multicast table now 5197 */ 5198 l3_min = soc_mem_index_min(unit, L3_ENTRY_IPV6_MULTICASTm); 5199 l3_max = soc_mem_index_max(unit, L3_ENTRY_IPV6_MULTICASTm); 5200 ipmc6_tbl_sz = sizeof(l3_entry_ipv6_multicast_entry_t) * \ 5201 (l3_max - l3_min + 1); 5202 5203 ipmc6_table = soc_cm_salloc(unit, ipmc6_tbl_sz, "ipmc v6 tbl dma"); 5204 if (ipmc6_table == NULL) { 5205 rv = BCM_E_MEMORY; 5206 goto ret_err; 5207 } 5208 5209 memset((void *)ipmc6_table, 0, ipmc6_tbl_sz); 5210 5211 if ((rv = soc_mem_read_range(unit, L3_ENTRY_IPV6_MULTICASTm, 5212 MEM_BLOCK_ANY, 5213 l3_min, l3_max, ipmc6_table)) < 0) { 5214 soc_cm_sfree(unit, ipmc6_table); 5215 goto ret_err; 5216 } 5217 5218 for (i = l3_min; i <= l3_max; i++) { 5219 5220 l3x_v6entry = soc_mem_table_idx_to_pointer(unit, 5221 L3_ENTRY_IPV6_MULTICASTm, 5222 l3_entry_ipv6_multicast_entry_t *, 5223 ipmc6_table, i); 5224 if (soc_L3_ENTRY_IPV6_MULTICASTm_field32_get(unit, l3x_v6entry, 5225 VALID_0f) == 0) { 5226 continue; 5227 } 5228 5229 if (soc_L3_ENTRY_IPV6_MULTICASTm_field32_get(unit, l3x_v6entry, 5230 VALID_1f) == 0) { 5231 continue; 5232 } 5233 5234 if (soc_L3_ENTRY_IPV6_MULTICASTm_field32_get(unit, l3x_v6entry, 5235 VALID_2f) == 0) { 5236 continue; 5237 } 5238 5239 if (soc_L3_ENTRY_IPV6_MULTICASTm_field32_get(unit, l3x_v6entry, 5240 VALID_3f) == 0) { 5241 continue; 5242 } 5243 5244 if (soc_L3_ENTRY_IPV6_MULTICASTm_field32_get(unit, l3x_v6entry, 5245 V6_0f) == 0) { 5246 continue; 5247 } 5248 5249 if (soc_L3_ENTRY_IPV6_MULTICASTm_field32_get(unit, l3x_v6entry, 5250 V6_1f) == 0) { 5251 continue; 5252 } 5253 5254 if (soc_L3_ENTRY_IPV6_MULTICASTm_field32_get(unit, l3x_v6entry, 5255 V6_2f) == 0) { 5256 continue; 5257 } 5258 5259 if (soc_L3_ENTRY_IPV6_MULTICASTm_field32_get(unit, l3x_v6entry, 5260 V6_3f) == 0) { 5261 continue; 5262 } 5263 5264 if (soc_L3_ENTRY_IPV6_MULTICASTm_field32_get(unit, l3x_v6entry, 5265 IPMC_0f) == 0) { 5266 continue; 5267 } 5268 5269 if (soc_L3_ENTRY_IPV6_MULTICASTm_field32_get(unit, l3x_v6entry, 5270 IPMC_1f) == 0) { 5271 continue; 5272 } 5273 5274 if (soc_L3_ENTRY_IPV6_MULTICASTm_field32_get(unit, l3x_v6entry, 5275 IPMC_2f) == 0) { 5276 continue; 5277 } 5278 5279 if (soc_L3_ENTRY_IPV6_MULTICASTm_field32_get(unit, l3x_v6entry, 5280 IPMC_3f) == 0) { 5281 continue; 5282 } 5283 5284 ipmc_ptr = soc_L3_ENTRY_IPV6_MULTICASTm_field32_get(unit, 5285 l3x_v6entry, L3MC_INDEX_0f); 5286 IPMC_USED_SET(unit, ipmc_ptr); 5287 { 5288 #if defined(BCM_FIREBOLT_SUPPORT) 5289 _bcm_l3_cfg_t l3cfg; 5290 sal_memset(&l3cfg, 0, sizeof(_bcm_l3_cfg_t)); 5291 l3cfg.l3c_flags |= BCM_IPMC_IP6; 5292 l3cfg.l3c_flags |= BCM_L3_IPMC; 5293 l3cfg.l3c_flags |= BCM_L3_HIT; 5294 if (soc_L3_ENTRY_IPV6_MULTICASTm_field32_get(unit, 5295 l3x_v6entry, RPEf)) { 5296 l3cfg.l3c_flags |= BCM_L3_RPE; 5297 } 5298 /* Get group address. */ 5299 soc_mem_ip6_addr_get(unit, L3_ENTRY_IPV6_MULTICASTm, l3x_v6entry, 5300 GROUP_IP_ADDR_LWR_64f, l3cfg.l3c_ip6, 5301 SOC_MEM_IP6_LOWER_ONLY); 5302 5303 soc_mem_ip6_addr_get(unit, L3_ENTRY_IPV6_MULTICASTm, l3x_v6entry, 5304 GROUP_IP_ADDR_UPR_56f, l3cfg.l3c_ip6, 5305 SOC_MEM_IP6_UPPER_ONLY); 5306 5307 /* Get source address. */ 5308 soc_mem_ip6_addr_get(unit, L3_ENTRY_IPV6_MULTICASTm, l3x_v6entry, 5309 SOURCE_IP_ADDR_LWR_64f, l3cfg.l3c_sip6, 5310 SOC_MEM_IP6_LOWER_ONLY); 5311 soc_mem_ip6_addr_get(unit, L3_ENTRY_IPV6_MULTICASTm, l3x_v6entry, 5312 SOURCE_IP_ADDR_UPR_64f, l3cfg.l3c_sip6, 5313 SOC_MEM_IP6_UPPER_ONLY); 5314 5315 l3cfg.l3c_ip6[0] = 0xff; /* Set entry to multicast*/ 5316 l3cfg.l3c_vid = soc_L3_ENTRY_IPV6_MULTICASTm_field32_get(unit, 5317 l3x_v6entry, VLAN_IDf); 5318 l3cfg.l3c_prio = soc_L3_ENTRY_IPV6_MULTICASTm_field32_get(unit, 5319 l3x_v6entry, PRIf); 5320 l3cfg.l3c_lookup_class = soc_L3_ENTRY_IPV6_MULTICASTm_field32_get(unit, 5321 l3x_v6entry, CLASS_IDf); 5322 rv = _bcm_xgs3_ipmc_l3entry_list_add(unit, ipmc_ptr, &l3cfg); 5323 #endif /* BCM_FIREBOLT_SUPPORT */ 5324 } 5325 if (rv < 0) { 5326 soc_cm_sfree(unit, ipmc6_table); 5327 goto ret_err; 5328 } 5329 } 5330 soc_cm_sfree(unit, ipmc6_table); 5331 5332 /* Recover multicast mode from HW cache */ 5333 rv = _bcm_esw_ipmc_repl_wb_flags_get(unit, 5334 _BCM_IPMC_WB_MULTICAST_MODE, 5335 &flags); 5336 5337 if (flags) { 5338 /* 5339 * Increase reference count for all mulitcast groups now 5340 */ 5341 l3_min = soc_mem_index_min(unit, L3_IPMCm); 5342 l3_max = soc_mem_index_max(unit, L3_IPMCm); 5343 l3_ipmc_tbl_sz = sizeof(ipmc_entry_t) * \ 5344 (l3_max - l3_min + 1); 5345 5346 l3_ipmc_table = soc_cm_salloc(unit, l3_ipmc_tbl_sz, 5347 "L3 ipmc tbl dma"); 5348 if (l3_ipmc_table == NULL) { 5349 rv = BCM_E_MEMORY; 5350 goto ret_err; 5351 } 5352 5353 memset((void *)l3_ipmc_table, 0, l3_ipmc_tbl_sz); 5354 5355 if ((rv = soc_mem_read_range(unit, L3_IPMCm, 5356 MEM_BLOCK_ANY, 5357 l3_min, l3_max, 5358 l3_ipmc_table)) < 0) { 5359 soc_cm_sfree(unit, l3_ipmc_table); 5360 goto ret_err; 5361 } 5362 5363 for (i = l3_min; i <= l3_max; i++) { 5364 l3_ipmc_entry = soc_mem_table_idx_to_pointer(unit, 5365 L3_IPMCm, 5366 ipmc_entry_t *, 5367 l3_ipmc_table, i); 5368 if (0 == soc_L3_IPMCm_field32_get(unit, l3_ipmc_entry, 5369 VALIDf)) { 5370 continue; 5371 } 5372 5373 /* It's a multicast group we need to note. */ 5374 IPMC_USED_SET(unit, i); 5375 } 5376 soc_cm_sfree(unit, l3_ipmc_table); 5377 } 5378 5379 /* 5380 * Recover replication state 5381 */ 5382 rv = _bcm_xgs3_ipmc_repl_reload(unit); 5383 } 5384 5385 ret_err: 5386 if (BCM_FAILURE(rv)) { 5387 5388 if (info->ipmc_group_info != NULL) { 5389 for (i = 0; i < IPMC_GROUP_NUM(unit); i++) { 5390 ipmc_l3entry = IPMC_GROUP_INFO(unit, i)->l3entry_list; 5391 while (ipmc_l3entry != NULL) { 5392 IPMC_GROUP_INFO(unit, i)->l3entry_list = ipmc_l3entry->next; 5393 sal_free(ipmc_l3entry); 5394 ipmc_l3entry = IPMC_GROUP_INFO(unit, i)->l3entry_list; 5395 } 5396 } 5397 sal_free(info->ipmc_group_info); 5398 info->ipmc_group_info = NULL; 5399 } 5400 } else { 5401 info->ipmc_initialized = TRUE; 5402 } 5403 5404 return rv; 5405 } 5406 5407 /* 5408 * Sync IPMC state on XGS3 class of devices 5409 */ 5410 int 5411 _bcm_fb_ipmc_sync( 5412 int unit, 5413 uint8 **scache_ptr) 5414 { 5415 int i; 5416 5417 /* Input parameters sanity check. */ 5418 if (NULL == scache_ptr) { 5419 return (BCM_E_PARAM); 5420 } 5421 5422 /* Synce IPMC replication info*/ 5423 for (i = 0; i < soc_mem_index_count(unit, EGR_L3_NEXT_HOPm); i++) { 5424 sal_memcpy((*scache_ptr), 5425 &(_fb_repl_info[unit]->l3_nh_to_l3_intf_ipmc[i]), 5426 sizeof(int)); 5427 (*scache_ptr) += sizeof(int); 5428 } 5429 5430 for (i = 0; i < soc_mem_index_count(unit, EGR_L3_INTFm); i++) { 5431 sal_memcpy((*scache_ptr), 5432 &(_fb_repl_info[unit]->l3_intf_to_l3_nh_ipmc[i]), 5433 sizeof(int)); 5434 (*scache_ptr) += sizeof(int); 5435 } 5436 5437 return BCM_E_NONE; 5438 } 5439 5440 int 5441 _bcm_fb_ipmc_scahce_size_get( 5442 int unit, 5443 uint32 *size) 5444 { 5445 int num_l3_nh, num_l3_intf; 5446 5447 /* Input parameters sanity check. */ 5448 if (NULL == size) { 5449 return (BCM_E_PARAM); 5450 } 5451 5452 *size = 0; 5453 /* Get IPMC replication info scache size*/ 5454 num_l3_nh = soc_mem_index_count(unit, EGR_L3_NEXT_HOPm); 5455 num_l3_intf = soc_mem_index_count(unit, EGR_L3_INTFm); 5456 *size = (num_l3_nh * sizeof(int)) + (num_l3_intf * sizeof(int)); 5457 5458 return BCM_E_NONE; 5459 } 5460 5461 int 5462 _bcm_fb_ipmc_repl_scache_recover( 5463 int unit, 5464 uint8 **scache_ptr) 5465 { 5466 int i; 5467 5468 /* Input parameters sanity check. */ 5469 if (NULL == scache_ptr) { 5470 return (BCM_E_PARAM); 5471 } 5472 5473 /* Recover IPMC replication info state */ 5474 for (i = 0; i < soc_mem_index_count(unit, EGR_L3_NEXT_HOPm); i++) { 5475 sal_memcpy(&(_fb_repl_info[unit]->l3_nh_to_l3_intf_ipmc[i]), 5476 (*scache_ptr), 5477 sizeof(int)); 5478 (*scache_ptr) += sizeof(int); 5479 } 5480 5481 for (i = 0; i < soc_mem_index_count(unit, EGR_L3_INTFm); i++) { 5482 sal_memcpy(&(_fb_repl_info[unit]->l3_intf_to_l3_nh_ipmc[i]), 5483 (*scache_ptr), 5484 sizeof(int)); 5485 (*scache_ptr) += sizeof(int); 5486 } 5487 5488 return BCM_E_NONE; 5489 } 5490 5491 5492 5493 5494 5495 #endif /* BCM_WARM_BOOT_SUPPORT */ 5496 5497 #ifndef BCM_SW_STATE_DUMP_DISABLE 5498 /* 5499 * Function: 5500 * _bcm_xgs3_ipmc_repl_sw_dump 5501 * Purpose: 5502 * Displays IPMC replication information maintained by software. 5503 * Parameters: 5504 * unit - Device unit number 5505 * Returns: 5506 * None 5507 */ 5508 void 5509 _bcm_xgs3_ipmc_repl_sw_dump(int unit) 5510 { 5511 int i, j, port; 5512 _fb_repl_info_t *repl_info; 5513 uint32 *bitmap; 5514 _fb_repl_port_info_t *port_info; 5515 _bcm_repl_list_info_t *rli_start, *rli_current; 5516 5517 /* 5518 * _fb_repl_info 5519 */ 5520 5521 LOG_CLI((BSL_META_U(unit, 5522 " IPMC REPL Info -\n"))); 5523 repl_info = _fb_repl_info[unit]; 5524 if (repl_info != NULL) { 5525 LOG_CLI((BSL_META_U(unit, 5526 " IPMC Size : %d\n"), repl_info->ipmc_size)); 5527 LOG_CLI((BSL_META_U(unit, 5528 " Intf Size : %d\n"), repl_info->intf_num)); 5529 LOG_CLI((BSL_META_U(unit, 5530 " Vlan total : %d\n"), repl_info->ipmc_vlan_total)); 5531 5532 LOG_CLI((BSL_META_U(unit, 5533 " Bitmap (index:value-hex) :"))); 5534 if (repl_info->bitmap_entries_used != NULL) { 5535 bitmap = repl_info->bitmap_entries_used; 5536 for (i = 0, j = 0; 5537 i < _SHR_BITDCLSIZE(repl_info->ipmc_vlan_total); i++) { 5538 /* If zero, skip print */ 5539 if (bitmap[i] == 0) { 5540 continue; 5541 } 5542 if (!(j % 4)) { 5543 LOG_CLI((BSL_META_U(unit, 5544 "\n "))); 5545 } 5546 LOG_CLI((BSL_META_U(unit, 5547 " %5d:%8.8x"), i, bitmap[i])); 5548 j++; 5549 } 5550 } 5551 LOG_CLI((BSL_META_U(unit, 5552 "\n"))); 5553 5554 LOG_CLI((BSL_META_U(unit, 5555 " Port Info -\n"))); 5556 LOG_CLI((BSL_META_U(unit, 5557 " port (index:vlan-count) :\n"))); 5558 for (port = 0; port < SOC_MAX_NUM_PORTS; port++) { 5559 port_info = repl_info->port_info[port]; 5560 LOG_CLI((BSL_META_U(unit, 5561 " %3d -"), port)); 5562 if (port_info == NULL) { 5563 LOG_CLI((BSL_META_U(unit, 5564 " null\n"))); 5565 continue; 5566 } 5567 for (i = 0, j = 0; i < IPMC_GROUP_NUM(unit); i++) { 5568 /* If zero, skip print */ 5569 if (port_info->vlan_count[i] == 0) { 5570 continue; 5571 } 5572 if ((j > 0) && !(j % 4)) { 5573 LOG_CLI((BSL_META_U(unit, 5574 "\n "))); 5575 } 5576 LOG_CLI((BSL_META_U(unit, 5577 " %5d:%-4d"), i, port_info->vlan_count[i])); 5578 j++; 5579 } 5580 LOG_CLI((BSL_META_U(unit, 5581 "\n"))); 5582 } 5583 5584 5585 rli_start = IPMC_REPL_LIST_INFO(unit); 5586 LOG_CLI((BSL_META_U(unit, 5587 " List Info -\n"))); 5588 for (rli_current = rli_start; rli_current != NULL; 5589 rli_current = rli_current->next) { 5590 LOG_CLI((BSL_META_U(unit, 5591 " Hash: 0x%08x\n"), rli_current->hash)); 5592 LOG_CLI((BSL_META_U(unit, 5593 " Index: %4d\n"), rli_current->index)); 5594 LOG_CLI((BSL_META_U(unit, 5595 " Size: %4d\n"), rli_current->list_size)); 5596 LOG_CLI((BSL_META_U(unit, 5597 " Refs: %4d\n"), rli_current->refcount)); 5598 } 5599 } 5600 5601 return; 5602 } 5603 5604 /* 5605 * Function: 5606 * _bcm_xgs3_ipmc_sw_dump 5607 * Purpose: 5608 * Displays IPMC information maintained by software. 5609 * Parameters: 5610 * unit - Device unit number 5611 * Returns: 5612 * None 5613 */ 5614 void 5615 _bcm_xgs3_ipmc_sw_dump(int unit) 5616 { 5617 int i, j; 5618 _bcm_esw_ipmc_t *ipmc_info; 5619 _bcm_esw_ipmc_l3entry_t *ipmc_l3entry; 5620 5621 5622 /* 5623 * xgs3_ipmc_info 5624 */ 5625 5626 ipmc_info = IPMC_INFO(unit); 5627 5628 LOG_CLI((BSL_META_U(unit, 5629 " XGS3 IPMC Info -\n"))); 5630 LOG_CLI((BSL_META_U(unit, 5631 " Init : %d\n"), ipmc_info->ipmc_initialized)); 5632 LOG_CLI((BSL_META_U(unit, 5633 " Size : %d\n"), IPMC_GROUP_NUM(unit))); 5634 LOG_CLI((BSL_META_U(unit, 5635 " Count : %d\n"), ipmc_info->ipmc_count)); 5636 5637 LOG_CLI((BSL_META_U(unit, 5638 " Alloc index :"))); 5639 if (ipmc_info->ipmc_group_info != NULL) { 5640 for (i = 0, j = 0; i < IPMC_GROUP_NUM(unit); i++) { 5641 /* If not set, skip print */ 5642 if (!IPMC_USED_ISSET(unit, i)) { 5643 continue; 5644 } 5645 if (!(j % 10)) { 5646 LOG_CLI((BSL_META_U(unit, 5647 "\n "))); 5648 } 5649 LOG_CLI((BSL_META_U(unit, 5650 " %5d"), i)); 5651 j++; 5652 } 5653 } 5654 LOG_CLI((BSL_META_U(unit, 5655 "\n"))); 5656 5657 LOG_CLI((BSL_META_U(unit, 5658 " Reference count (index:value) :"))); 5659 if (ipmc_info->ipmc_group_info != NULL) { 5660 for (i = 0, j = 0; i < IPMC_GROUP_NUM(unit); i++) { 5661 if (!IPMC_USED_ISSET(unit, i)) { 5662 continue; 5663 } 5664 if (!(j % 4)) { 5665 LOG_CLI((BSL_META_U(unit, 5666 "\n "))); 5667 } 5668 LOG_CLI((BSL_META_U(unit, 5669 " %5d:%-5d"), i, IPMC_GROUP_INFO(unit, i)->ref_count)); 5670 j++; 5671 } 5672 } 5673 LOG_CLI((BSL_META_U(unit, 5674 "\n"))); 5675 LOG_CLI((BSL_META_U(unit, 5676 " IP6 (index:value) :"))); 5677 if (ipmc_info->ipmc_group_info != NULL) { 5678 for (i = 0, j = 0; i < IPMC_GROUP_NUM(unit); i++) { 5679 ipmc_l3entry = IPMC_GROUP_INFO(unit, i)->l3entry_list; 5680 while (ipmc_l3entry != NULL) { 5681 if (ipmc_l3entry->ip6 == 1) { 5682 if (!(j % 4)) { 5683 LOG_CLI((BSL_META_U(unit, 5684 "\n "))); 5685 } 5686 LOG_CLI((BSL_META_U(unit, 5687 " %5d:%-5d"), i, ipmc_l3entry->ip6)); 5688 j++; 5689 } 5690 ipmc_l3entry = ipmc_l3entry->next; 5691 } 5692 } 5693 } 5694 LOG_CLI((BSL_META_U(unit, 5695 "\n"))); 5696 5697 _bcm_xgs3_ipmc_repl_sw_dump(unit); 5698 5699 return; 5700 } 5701 #endif /* BCM_SW_STATE_DUMP_DISABLE */ 5702 5703 #endif /* BCM_FIREBOLT_SUPPORT */ 5704 5705 #endif /* INCLUDE_L3 */ 5706 5707 int _bcm_esw_firebolt_ipmc_not_empty; 5708