l2cache.c (10053B)
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 * L2 Cache - Layer 2 BPDU and overflow address cache 8 */ 9 10 #include <shared/bsl.h> 11 12 #include <sal/core/libc.h> 13 #include <shared/alloc.h> 14 15 #include <bcm/types.h> 16 17 #include <bcmx/l2.h> 18 #include <bcmx/lport.h> 19 #include <bcmx/bcmx.h> 20 #include <bcmx/lplist.h> 21 22 #include "bcmx_int.h" 23 24 #define BCMX_L2_CACHE_INIT_CHECK BCMX_READY_CHECK 25 26 #define BCMX_L2_CACHE_ERROR_CHECK(_unit, _check, _rv) \ 27 BCMX_ERROR_CHECK(_unit, _check, _rv) 28 29 #define BCMX_L2_CACHE_SET_ERROR_CHECK(_unit, _check, _rv) \ 30 BCMX_SET_ERROR_CHECK(_unit, _check, _rv) 31 32 #define BCMX_L2_CACHE_DELETE_ERROR_CHECK(_unit, _check, _rv) \ 33 BCMX_DELETE_ERROR_CHECK(_unit, _check, _rv) 34 35 #define BCMX_L2_CACHE_GET_IS_VALID(_unit, _rv) \ 36 BCMX_ERROR_IS_VALID(_unit, _rv) 37 38 39 STATIC INLINE void 40 _bcmx_l2_cache_addr_t_init(bcmx_l2_cache_addr_t *addr) 41 { 42 sal_memset(addr, 0, sizeof (*addr)); 43 } 44 45 STATIC INLINE int 46 _bcmx_l2_cache_addr_to_bcm(int bcm_unit, 47 bcm_l2_cache_addr_t *dest, 48 bcmx_l2_cache_addr_t *source) 49 { 50 uint32 flags = BCMX_DEST_CONVERT_NON_GPORT; 51 _bcmx_dest_bcm_t to_bcm; 52 _bcmx_dest_bcmx_t from_bcmx; 53 54 bcm_l2_cache_addr_t_init(dest); 55 dest->flags = source->flags; 56 sal_memcpy(dest->mac, source->mac, sizeof(bcm_mac_t)); 57 sal_memcpy(dest->mac_mask, source->mac_mask, sizeof(bcm_mac_t)); 58 dest->vlan = source->vlan; 59 dest->vlan_mask = source->vlan_mask; 60 61 dest->src_port = source->src_port; 62 dest->src_port_mask = source->src_port_mask; 63 dest->lookup_class = source->lookup_class; 64 65 /* 66 * Convert to destination port list to bitmap if destination 67 * is not a trunk and DESTPORTS flag is set 68 */ 69 if (!(source->flags & BCM_L2_CACHE_TRUNK) && 70 (source->flags & BCM_L2_CACHE_DESTPORTS)) { 71 BCM_PBMP_CLEAR(dest->dest_ports); 72 BCMX_LPLIST_TO_PBMP(source->dest_ports, bcm_unit, dest->dest_ports); 73 74 } else { 75 /* 76 * Convert destination data 77 */ 78 _bcmx_dest_bcmx_t_init(&from_bcmx); 79 80 /* Set flags and data to convert */ 81 if (source->flags & BCM_L2_CACHE_TRUNK) { 82 flags |= BCMX_DEST_TRUNK; 83 } 84 from_bcmx.port = source->dest_lport; 85 from_bcmx.trunk = source->dest_trunk; 86 87 /* Convert */ 88 BCM_IF_ERROR_RETURN(_bcmx_dest_to_bcm(&from_bcmx, &to_bcm, &flags)); 89 90 /* Set converted flags and data */ 91 if (flags & BCMX_DEST_TRUNK) { 92 dest->flags |= BCM_L2_CACHE_TRUNK; 93 } else if (flags & BCMX_DEST_DISCARD) { 94 dest->flags |= BCM_L2_CACHE_DISCARD; 95 } 96 97 dest->dest_modid = to_bcm.module_id; 98 dest->dest_port = to_bcm.module_port; 99 dest->dest_trunk = to_bcm.trunk; 100 } 101 102 dest->prio = source->prio; 103 104 return BCM_E_NONE; 105 } 106 107 STATIC INLINE int 108 _bcmx_l2_cache_addr_from_bcm(bcmx_l2_cache_addr_t *dest, 109 bcm_l2_cache_addr_t *source) 110 { 111 uint32 flags = BCMX_DEST_CONVERT_DEFAULT; 112 _bcmx_dest_bcm_t from_bcm; 113 _bcmx_dest_bcmx_t to_bcmx; 114 115 _bcmx_l2_cache_addr_t_init(dest); 116 dest->flags = source->flags; 117 sal_memcpy(dest->mac, source->mac, sizeof(bcm_mac_t)); 118 sal_memcpy(dest->mac_mask, source->mac_mask, sizeof(bcm_mac_t)); 119 dest->vlan = source->vlan; 120 dest->vlan_mask = source->vlan_mask; 121 122 dest->src_port = source->src_port; 123 dest->src_port_mask = source->src_port_mask; 124 dest->lookup_class = source->lookup_class; 125 126 /* 127 * Convert bitmap to destination port list if destination 128 * is not a trunk and DESTPORTS flag is set 129 */ 130 if (!(source->flags & BCM_L2_CACHE_TRUNK) && 131 (source->flags & BCM_L2_CACHE_DESTPORTS)) { 132 bcm_port_t port; 133 bcmx_lport_t lport; 134 135 bcmx_lplist_clear(&dest->dest_ports); 136 BCM_PBMP_ITER(source->dest_ports, port) { 137 BCM_IF_ERROR_RETURN 138 (_bcmx_dest_from_modid_port(&lport, source->dest_modid, port, 139 BCMX_DEST_CONVERT_DEFAULT)); 140 BCMX_LPLIST_ADD(&dest->dest_ports, lport); 141 } 142 143 } else { 144 /* 145 * Convert destination data 146 */ 147 _bcmx_dest_bcm_t_init(&from_bcm); 148 149 /* Set flags and data to convert */ 150 if (source->flags & BCM_L2_CACHE_TRUNK) { 151 flags |= BCMX_DEST_TRUNK; 152 } 153 from_bcm.module_id = source->dest_modid; 154 from_bcm.module_port = source->dest_port; 155 from_bcm.trunk = source->dest_trunk; 156 157 /* Convert */ 158 BCM_IF_ERROR_RETURN(_bcmx_dest_from_bcm(&to_bcmx, &from_bcm, &flags)); 159 160 /* Set converted flags and data */ 161 if (flags & BCMX_DEST_TRUNK) { 162 dest->flags |= BCM_L2_CACHE_TRUNK; 163 } else if (flags & BCMX_DEST_DISCARD) { 164 dest->flags |= BCM_L2_CACHE_DISCARD; 165 } 166 167 dest->dest_lport = to_bcmx.port; 168 dest->dest_trunk = to_bcmx.trunk; 169 } 170 171 dest->prio = source->prio; 172 173 return BCM_E_NONE; 174 } 175 176 177 /* 178 * Function: 179 * bcmx_l2_cache_init 180 */ 181 182 int 183 bcmx_l2_cache_init(void) 184 { 185 int rv = BCM_E_UNAVAIL, tmp_rv; 186 int i, bcm_unit; 187 188 BCMX_L2_CACHE_INIT_CHECK; 189 190 BCMX_UNIT_ITER(bcm_unit, i) { 191 tmp_rv = bcm_l2_cache_init(bcm_unit); 192 BCM_IF_ERROR_RETURN(BCMX_L2_CACHE_ERROR_CHECK(bcm_unit, tmp_rv, &rv)); 193 } 194 195 return rv; 196 } 197 198 199 /* 200 * Function: 201 * bcmx_l2_cache_addr_t_init 202 */ 203 204 void 205 bcmx_l2_cache_addr_t_init(bcmx_l2_cache_addr_t *addr) 206 { 207 if (addr != NULL) { 208 _bcmx_l2_cache_addr_t_init(addr); 209 bcmx_lplist_t_init(&addr->dest_ports); 210 } 211 } 212 213 /* 214 * Function: 215 * bcmx_l2_cache_addr_t_free 216 * Purpose: 217 * Free memory allocated to bcmx_l2_cache_addr_t struct 218 */ 219 void 220 bcmx_l2_cache_addr_t_free(bcmx_l2_cache_addr_t *addr) 221 { 222 if (addr != NULL) { 223 bcmx_lplist_free(&addr->dest_ports); 224 } 225 } 226 227 228 /* 229 * Function: 230 * bcmx_l2_cache_size_get 231 */ 232 233 int 234 bcmx_l2_cache_size_get(int *size) 235 { 236 int rv = BCM_E_UNAVAIL, tmp_rv; 237 int i, bcm_unit; 238 int tmp_size = 0, current_size = 0; 239 240 BCMX_L2_CACHE_INIT_CHECK; 241 242 BCMX_PARAM_NULL_CHECK(size); 243 244 BCMX_UNIT_ITER(bcm_unit, i) { 245 tmp_rv = bcm_l2_cache_size_get(bcm_unit, &tmp_size); 246 if (BCMX_L2_CACHE_GET_IS_VALID(bcm_unit, tmp_rv)) { 247 rv = tmp_rv; 248 if (BCM_FAILURE(tmp_rv)) { 249 break; 250 } 251 252 /* Set current_size to the first non-zero cache size 253 or the minimum of all valid cache sizes found. */ 254 if ((tmp_size > 0) && 255 ((current_size == 0) || (tmp_size < current_size))) { 256 current_size = tmp_size; 257 } 258 } 259 } 260 *size = current_size; 261 262 return rv; 263 } 264 265 266 /* 267 * Function: 268 * bcmx_l2_cache_set 269 */ 270 271 int 272 bcmx_l2_cache_set(int index, bcmx_l2_cache_addr_t *addr, int *index_used) 273 { 274 int rv = BCM_E_UNAVAIL, tmp_rv; 275 int i, bcm_unit; 276 bcm_l2_cache_addr_t bcm_l2; 277 int map_local_cpu; /* Is local CPU port mapping required? */ 278 bcmx_lport_t cpu_lport; 279 280 BCMX_L2_CACHE_INIT_CHECK; 281 282 BCMX_PARAM_NULL_CHECK(addr); 283 BCMX_PARAM_NULL_CHECK(index_used); 284 285 /* Auto inser is not support across chips of different types */ 286 if (index < 0) { 287 return BCM_E_PARAM; 288 } 289 290 map_local_cpu = ((!(addr->flags & BCM_L2_CACHE_TRUNK)) && 291 (addr->dest_lport == BCMX_LPORT_LOCAL_CPU)); 292 293 BCMX_UNIT_ITER(bcm_unit, i) { 294 if (_bcmx_l2_cache_addr_to_bcm(bcm_unit, &bcm_l2, addr) < 0) { 295 LOG_WARN(BSL_LS_BCMX_COMMON, 296 (BSL_META("BCMX L2 CACHE WARN: " 297 "Failed to convert " 298 "L2 Cache address to BCM\n"))); 299 } else { 300 if (map_local_cpu) { 301 cpu_lport = BCMX_LPORT_LOCAL_CPU_GET(bcm_unit); 302 if (BCM_FAILURE 303 (_bcmx_dest_to_modid_port(cpu_lport, 304 &bcm_l2.dest_modid, 305 &bcm_l2.dest_port, 306 BCMX_DEST_CONVERT_DEFAULT))) { 307 /* Skip if can't find local CPU port */ 308 continue; 309 } 310 } 311 tmp_rv = bcm_l2_cache_set(bcm_unit, index, &bcm_l2, index_used); 312 313 BCM_IF_ERROR_RETURN 314 (BCMX_L2_CACHE_SET_ERROR_CHECK(bcm_unit, tmp_rv, &rv)); 315 } 316 } 317 318 *index_used = index; 319 320 return rv; 321 } 322 323 324 /* 325 * Function: 326 * bcmx_l2_cache_get 327 */ 328 329 int 330 bcmx_l2_cache_get(int index, bcmx_l2_cache_addr_t *addr) 331 { 332 int rv; 333 int i, bcm_unit; 334 bcm_l2_cache_addr_t bcm_l2; 335 336 BCMX_L2_CACHE_INIT_CHECK; 337 338 BCMX_PARAM_NULL_CHECK(addr); 339 340 BCMX_UNIT_ITER(bcm_unit, i) { 341 rv = bcm_l2_cache_get(bcm_unit, index, &bcm_l2); 342 343 if (BCMX_L2_CACHE_GET_IS_VALID(bcm_unit, rv)) { 344 if (BCM_SUCCESS(rv)) { 345 rv = _bcmx_l2_cache_addr_from_bcm(addr, &bcm_l2); 346 } 347 return rv; 348 } 349 } 350 351 return BCM_E_UNAVAIL; 352 } 353 354 355 /* 356 * Function: 357 * bcmx_l2_cache_delete 358 */ 359 360 int 361 bcmx_l2_cache_delete(int index) 362 { 363 int rv = BCM_E_UNAVAIL, tmp_rv; 364 int i, bcm_unit; 365 366 BCMX_L2_CACHE_INIT_CHECK; 367 368 BCMX_UNIT_ITER(bcm_unit, i) { 369 tmp_rv = bcm_l2_cache_delete(bcm_unit, index); 370 BCM_IF_ERROR_RETURN 371 (BCMX_L2_CACHE_DELETE_ERROR_CHECK(bcm_unit, tmp_rv, &rv)); 372 } 373 374 return rv; 375 } 376 377 378 /* 379 * Function: 380 * bcmx_l2_cache_delete_all 381 */ 382 383 int 384 bcmx_l2_cache_delete_all(void) 385 { 386 int rv = BCM_E_UNAVAIL, tmp_rv; 387 int i, bcm_unit; 388 389 BCMX_L2_CACHE_INIT_CHECK; 390 391 BCMX_UNIT_ITER(bcm_unit, i) { 392 tmp_rv = bcm_l2_cache_delete_all(bcm_unit); 393 BCM_IF_ERROR_RETURN 394 (BCMX_L2_CACHE_DELETE_ERROR_CHECK(bcm_unit, tmp_rv, &rv)); 395 } 396 397 return rv; 398 }