l2.c (36355B)
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: l2.c 8 * Purpose: Trident L2 function implementations 9 */ 10 #include <soc/defs.h> 11 12 #if defined(BCM_TRIDENT_SUPPORT) 13 14 #include <assert.h> 15 16 #include <sal/core/libc.h> 17 18 #include <soc/mem.h> 19 #include <soc/debug.h> 20 #include <soc/cm.h> 21 #include <soc/drv.h> 22 #include <soc/register.h> 23 #include <soc/memory.h> 24 #include <soc/hash.h> 25 #include <soc/l2x.h> 26 #if defined(BCM_TRIUMPH3_SUPPORT) 27 #include <soc/ism_hash.h> 28 #endif /* BCM_TRIUMPH3_SUPPORT */ 29 #if defined(BCM_TRIDENT2_SUPPORT) 30 #include <soc/trident2.h> 31 #endif /* BCM_TRIDENT2_SUPPORT */ 32 #include <soc/triumph.h> 33 34 #include <bcm/l2.h> 35 #include <bcm/error.h> 36 37 #include <bcm_int/esw/l2.h> 38 #include <bcm_int/common/multicast.h> 39 #include <bcm_int/esw/trill.h> 40 #include <bcm_int/esw/trident.h> 41 #include <bcm_int/esw/firebolt.h> 42 #include <bcm_int/esw/triumph.h> 43 44 typedef uint32 L2_ENTRY_T[SOC_MAX_MEM_FIELD_WORDS]; 45 46 #if defined(INCLUDE_L3) 47 /* 48 * Purpose: 49 * Add TRILL Multicast entry 50 * Parameters: 51 * unit - Device unit number 52 * key - defines entry type 53 * vid - Customer Vlan ID 54 * mac - Customer MAC 55 * trill_tree_id - specify Multicast Tree ID 56 * group - Multicast group 57 * Returns: 58 * BCM_E_NONE - Success. 59 * BCM_E_XXX 60 */ 61 int 62 bcm_td_l2_trill_multicast_entry_add(int unit, uint32 flags, int key, 63 bcm_vlan_t vid, bcm_mac_t mac, 64 uint8 trill_tree_id, bcm_multicast_t group) 65 { 66 L2_ENTRY_T l2_entry, l2_lookup; 67 soc_mem_t mem; 68 soc_field_t field_key; 69 int rv=BCM_E_NONE; 70 int mc_index=0,l2_index=0; 71 vlan_tab_entry_t vt; 72 73 sal_memset(&l2_entry, 0, sizeof (l2_entry)); 74 75 mem = L2Xm; 76 77 if (_BCM_MULTICAST_IS_SET(group)) { 78 79 mc_index = _BCM_MULTICAST_ID_GET(group); 80 81 switch (key) { 82 case TR_L2_HASH_KEY_TYPE_BRIDGE: 83 field_key = TR_L2_HASH_KEY_TYPE_BRIDGE; 84 soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry, 85 KEY_TYPEf, field_key); 86 soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry, 87 VALIDf, 1); 88 soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry, 89 L2__DEST_TYPEf, 0); 90 soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry, 91 L2__L2MC_PTRf, mc_index); 92 soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry, 93 L2__TRILL_NETWORK_RECEIVERS_PRESENTf, 1); 94 soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry, 95 L2__VLAN_IDf, vid); 96 soc_mem_mac_addr_set(unit, mem, (uint32 *)&l2_entry, 97 L2__MAC_ADDRf, mac); 98 break; 99 100 case TR_L2_HASH_KEY_TYPE_TRILL_NONUC_ACCESS: 101 field_key = TR_L2_HASH_KEY_TYPE_TRILL_NONUC_ACCESS; 102 soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry, 103 TRILL_NONUC_ACCESS__DEST_TYPEf, 0x3); 104 soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry, 105 KEY_TYPEf, field_key); 106 if (flags & BCM_TRILL_MULTICAST_STATIC) { 107 soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry, 108 TRILL_NONUC_ACCESS__STATIC_BITf, 0x1); 109 } 110 soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry, 111 TRILL_NONUC_ACCESS__L3MC_PTRf, mc_index); 112 soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry, 113 TRILL_NONUC_ACCESS__VLAN_IDf, vid); 114 soc_mem_mac_addr_set(unit, mem, (uint32 *)&l2_entry, 115 TRILL_NONUC_ACCESS__MAC_ADDRf, mac); 116 soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry, 117 VALIDf, 1); 118 break; 119 120 case TR_L2_HASH_KEY_TYPE_TRILL_NONUC_NETWORK_SHORT: 121 field_key = TR_L2_HASH_KEY_TYPE_TRILL_NONUC_NETWORK_SHORT; 122 if (flags & BCM_TRILL_MULTICAST_STATIC) { 123 soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry, 124 TRILL_NONUC_NETWORK_SHORT__STATIC_BITf, 0x1); 125 } 126 127 soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry, 128 TRILL_NONUC_NETWORK_SHORT__DEST_TYPEf, 0x3); 129 soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry, 130 KEY_TYPEf, field_key); 131 soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry, VALIDf, 1); 132 soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry, 133 TRILL_NONUC_NETWORK_SHORT__TREE_IDf, trill_tree_id); 134 soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry, 135 TRILL_NONUC_NETWORK_SHORT__L3MC_INDEXf, mc_index); 136 soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry, 137 TRILL_NONUC_NETWORK_SHORT__VLAN_IDf, vid); 138 139 BCM_IF_ERROR_RETURN(soc_mem_read(unit, VLAN_TABm, 140 MEM_BLOCK_ANY, vid, &vt)); 141 142 if (soc_mem_field32_get(unit, VLAN_TABm, &vt, 143 TRILL_ACCESS_RECEIVERS_PRESENTf)) { 144 soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry, 145 TRILL_NONUC_NETWORK_SHORT__TRILL_ACCESS_RECEIVERS_PRESENTf, 1); 146 } 147 148 break; 149 150 case TR_L2_HASH_KEY_TYPE_TRILL_NONUC_NETWORK_LONG: 151 field_key = TR_L2_HASH_KEY_TYPE_TRILL_NONUC_NETWORK_LONG; 152 if (flags & BCM_TRILL_MULTICAST_STATIC) { 153 soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry, 154 TRILL_NONUC_NETWORK_LONG__STATIC_BITf, 0x1); 155 } 156 soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry, 157 TRILL_NONUC_NETWORK_LONG__DEST_TYPEf, 0x3); 158 soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry, 159 KEY_TYPEf, field_key); 160 soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry, VALIDf, 1); 161 soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry, 162 TRILL_NONUC_NETWORK_LONG__TREE_IDf, trill_tree_id); 163 soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry, 164 TRILL_NONUC_NETWORK_LONG__TRILL_ACCESS_RECEIVERS_PRESENTf, 1); 165 soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry, 166 TRILL_NONUC_NETWORK_LONG__L3MC_INDEXf, mc_index); 167 soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry, 168 TRILL_NONUC_NETWORK_LONG__VLAN_IDf, vid); 169 soc_mem_mac_addr_set(unit, mem, (uint32 *)&l2_entry, 170 TRILL_NONUC_NETWORK_LONG__MAC_ADDRESSf, mac); 171 break; 172 173 default: 174 break; 175 } 176 } 177 178 179 /* See if the entry already exists */ 180 rv = soc_mem_search(unit, mem, MEM_BLOCK_ANY, &l2_index, 181 (void *)&l2_entry, (void *)&l2_lookup, 0); 182 183 if (rv == SOC_E_NONE) { 184 if (key == TR_L2_HASH_KEY_TYPE_BRIDGE) { 185 soc_mem_field32_set(unit, mem, (uint32*)&l2_lookup, 186 L2__TRILL_NETWORK_RECEIVERS_PRESENTf, 1); 187 rv = soc_mem_write(unit, mem, 188 MEM_BLOCK_ALL, l2_index, 189 &l2_lookup); 190 } 191 } else if ((rv < 0) && (rv != SOC_E_NOT_FOUND)) { 192 return rv; 193 } else { 194 /* Add Entry */ 195 rv = soc_mem_insert(unit, mem, MEM_BLOCK_ANY, (void *)&l2_entry); 196 if ((rv == SOC_E_FULL) && 197 ((key == TR_L2_HASH_KEY_TYPE_TRILL_NONUC_NETWORK_SHORT) || 198 (key == TR_L2_HASH_KEY_TYPE_TRILL_NONUC_NETWORK_LONG)) && 199 (flags & BCM_TRILL_MULTICAST_REPLACE_DYNAMIC)) { 200 /* 201 * If the table is FULL, 202 * replace the existing entry for TRILL_NW_SHORT and TRILL_NW_LONG. 203 */ 204 l2x_entry_t l2x_entry; 205 sal_memcpy((void *)&l2x_entry, 206 (void *)&l2_entry, sizeof(l2x_entry_t)); 207 rv = _bcm_l2_hash_dynamic_replace(unit, &l2x_entry); 208 } 209 } 210 return rv; 211 } 212 213 214 /* 215 * Purpose: 216 * Update TRILL Multicast entry 217 * Parameters: 218 * unit - Device unit number 219 * key - defines entry type 220 * vid - Customer Vlan ID 221 * mac - Customer MAC 222 * trill_tree_id - specify Multicast Tree ID 223 * group - Trill Multicast group 224 * Returns: 225 * BCM_E_NONE - Success. 226 * BCM_E_XXX 227 */ 228 int 229 bcm_td_l2_trill_multicast_entry_update(int unit, int key, 230 bcm_vlan_t vid, bcm_mac_t mac, 231 uint8 trill_tree_id, bcm_multicast_t group) 232 { 233 L2_ENTRY_T l2_entry, l2_lookup; 234 soc_mem_t mem; 235 soc_field_t field_key; 236 int rv=BCM_E_NONE; 237 int l2_index=0; 238 239 sal_memset(&l2_entry, 0, sizeof (l2_entry)); 240 241 mem = L2Xm; 242 243 if (_BCM_MULTICAST_IS_TRILL(group)) { 244 245 switch (key) { 246 case TR_L2_HASH_KEY_TYPE_BRIDGE: 247 field_key = TR_L2_HASH_KEY_TYPE_BRIDGE; 248 soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry, 249 KEY_TYPEf, field_key); 250 soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry, 251 VALIDf, 1); 252 soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry, 253 L2__VLAN_IDf, vid); 254 soc_mem_mac_addr_set(unit, mem, (uint32 *)&l2_entry, 255 L2__MAC_ADDRf, mac); 256 break; 257 258 } 259 } 260 261 /* See if the entry already exists */ 262 rv = soc_mem_search(unit, mem, MEM_BLOCK_ANY, &l2_index, 263 (void *)&l2_entry, (void *)&l2_lookup, 0); 264 if (rv == SOC_E_NONE) { 265 if (key == TR_L2_HASH_KEY_TYPE_BRIDGE) { 266 soc_mem_field32_set(unit, mem, (uint32*)&l2_lookup, 267 L2__TRILL_NETWORK_RECEIVERS_PRESENTf, 1); 268 rv = soc_mem_write(unit, mem, 269 MEM_BLOCK_ALL, l2_index, 270 &l2_lookup); 271 } 272 } else { 273 /* Entry must exist */ 274 return rv; 275 } 276 return rv; 277 } 278 279 /* 280 * Purpose: 281 * Delete TRILL Multicast entry 282 * Parameters: 283 * unit - Device unit number 284 * key - defines entry type 285 * vid - Customer Vlan ID 286 * mac - Customer MAC 287 * trill_tree_id - specify Multicast Tree ID 288 * Returns: 289 * BCM_E_NONE - Success. 290 * BCM_E_XXX 291 */ 292 int 293 bcm_td_l2_trill_multicast_entry_delete(int unit, int key, bcm_vlan_t vid, 294 bcm_mac_t mac, uint8 trill_tree_id) 295 { 296 L2_ENTRY_T l2_entry, l2_lookup; 297 soc_mem_t mem; 298 soc_field_t field_key; 299 int rv=BCM_E_NONE; 300 int l2_index=0; 301 302 sal_memset(&l2_entry, 0, sizeof (l2_entry)); 303 304 mem = L2Xm; 305 306 switch (key) { 307 case TR_L2_HASH_KEY_TYPE_BRIDGE: 308 field_key = TR_L2_HASH_KEY_TYPE_BRIDGE; 309 soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry, 310 KEY_TYPEf, field_key); 311 soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry, 312 L2__VLAN_IDf, vid); 313 soc_mem_mac_addr_set(unit, mem, (uint32 *)&l2_entry, 314 L2__MAC_ADDRf, mac); 315 break; 316 317 case TR_L2_HASH_KEY_TYPE_TRILL_NONUC_ACCESS: 318 field_key = TR_L2_HASH_KEY_TYPE_TRILL_NONUC_ACCESS; 319 soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry, 320 KEY_TYPEf, field_key); 321 soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry, 322 L2__VLAN_IDf, vid); 323 soc_mem_mac_addr_set(unit, mem, (uint32 *)&l2_entry, 324 L2__MAC_ADDRf, mac); 325 break; 326 327 case TR_L2_HASH_KEY_TYPE_TRILL_NONUC_NETWORK_SHORT: 328 field_key = TR_L2_HASH_KEY_TYPE_TRILL_NONUC_NETWORK_SHORT; 329 soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry, 330 KEY_TYPEf, field_key); 331 soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry, 332 TRILL_NONUC_NETWORK_SHORT__TREE_IDf, 333 trill_tree_id); 334 soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry, 335 TRILL_NONUC_NETWORK_SHORT__VLAN_IDf, vid); 336 break; 337 338 case TR_L2_HASH_KEY_TYPE_TRILL_NONUC_NETWORK_LONG: 339 field_key = TR_L2_HASH_KEY_TYPE_TRILL_NONUC_NETWORK_LONG; 340 soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry, 341 KEY_TYPEf, field_key); 342 soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry, 343 TRILL_NONUC_NETWORK_LONG__TREE_IDf, 344 trill_tree_id); 345 soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry, 346 TRILL_NONUC_NETWORK_LONG__VLAN_IDf, vid); 347 soc_mem_mac_addr_set(unit, mem, (uint32 *)&l2_entry, 348 TRILL_NONUC_NETWORK_LONG__MAC_ADDRESSf, mac); 349 break; 350 351 default: 352 break; 353 } 354 355 rv = soc_mem_search(unit, mem, MEM_BLOCK_ANY, &l2_index, 356 (void *)&l2_entry, (void *)&l2_lookup, 0); 357 358 if ((rv < 0) && (rv != BCM_E_NOT_FOUND)) { 359 return rv; 360 } 361 362 rv = soc_mem_delete(unit, mem, MEM_BLOCK_ANY, (void *)&l2_entry); 363 return rv; 364 } 365 366 367 /* 368 * Description: 369 * Delete all TRILL tree-sepecific Multicast entries 370 * Parameters: 371 * unit - device number 372 * tree_id - Trill Tree ID 373 * Return: 374 * BCM_E_XXX 375 */ 376 int 377 bcm_td_l2_trill_multicast_entry_delete_all (int unit, uint8 tree_id) 378 { 379 int ix, key_type, chnk_end; 380 int chunksize, chunk, chunk_max, mem_idx_max; 381 L2_ENTRY_T *l2e, *l2ep; 382 soc_control_t *soc = SOC_CONTROL(unit); 383 soc_mem_t mem; 384 int rv = BCM_E_NONE; 385 chunksize = soc_property_get(unit, spn_L2DELETE_CHUNKS, 386 L2_MEM_CHUNKS_DEFAULT); 387 388 mem = L2Xm; 389 390 l2e = soc_cm_salloc(unit, chunksize * sizeof(*l2e), "l2entrydel_chunk"); 391 if (l2e == NULL) { 392 return BCM_E_MEMORY; 393 } 394 mem_idx_max = soc_mem_index_max(unit, mem); 395 soc_mem_lock(unit, mem); 396 for (chunk = soc_mem_index_min(unit, mem); chunk <= mem_idx_max; 397 chunk += chunksize) { 398 399 chunk_max = chunk + chunksize - 1; 400 if (chunk_max > mem_idx_max) { 401 chunk_max = mem_idx_max; 402 } 403 404 rv = soc_mem_read_range(unit, mem, MEM_BLOCK_ANY, 405 chunk, chunk_max, l2e); 406 if (rv < 0) { 407 break; 408 } 409 chnk_end = (chunk_max - chunk); 410 for (ix = 0; ix <= chnk_end; ix++) { 411 l2ep = soc_mem_table_idx_to_pointer(unit, mem, 412 L2_ENTRY_T *, l2e, ix); 413 if (!soc_mem_field32_get(unit, mem, l2ep, VALIDf)) { 414 continue; 415 } 416 if (soc_mem_field32_get(unit, mem, l2ep, PENDINGf)) { 417 continue; 418 } 419 420 /* Match the Key Type to TRILL */ 421 key_type = soc_mem_field32_get(unit, mem, l2ep, KEY_TYPEf); 422 if (key_type != TR_L2_HASH_KEY_TYPE_TRILL_NONUC_ACCESS) { 423 if (key_type != TR_L2_HASH_KEY_TYPE_TRILL_NONUC_NETWORK_SHORT) { 424 if (key_type != TR_L2_HASH_KEY_TYPE_TRILL_NONUC_NETWORK_LONG) { 425 continue; 426 } 427 } 428 } 429 430 if ((tree_id != soc_mem_field32_get (unit, mem, l2ep, 431 TRILL_NONUC_NETWORK_LONG__TREE_IDf)) && 432 (tree_id != soc_mem_field32_get(unit, mem, l2ep, 433 TRILL_NONUC_NETWORK_SHORT__TREE_IDf))){ 434 continue; 435 } 436 437 if (SOC_L2_DEL_SYNC_LOCK(soc) < 0) { 438 rv = BCM_E_RESOURCE; 439 break; 440 } 441 if (((rv = soc_mem_delete(unit, mem, MEM_BLOCK_ALL, l2ep)) < 0) || 442 ((rv = soc_l2x_sync_delete(unit, (uint32 *) l2ep, 443 (chunk + ix), 0)) < 0)) { 444 SOC_L2_DEL_SYNC_UNLOCK(soc); 445 break; 446 } 447 SOC_L2_DEL_SYNC_UNLOCK(soc); 448 } 449 if (rv < 0) { 450 break; 451 } 452 } 453 soc_mem_unlock(unit, mem); 454 soc_cm_sfree(unit, l2e); 455 456 return rv; 457 } 458 459 /* 460 * Purpose: 461 * Get TRILL Multicast entry 462 * Parameters: 463 * unit - Device unit number 464 * key - defines entry type 465 * vid - Customer Vlan ID 466 * mac - Customer MAC 467 * trill_tree_id - specify Multicast Tree ID 468 * group - (OUT) Multicast group 469 * Returns: 470 * BCM_E_NONE - Success. 471 * BCM_E_XXX 472 */ 473 int 474 bcm_td_l2_trill_multicast_entry_get(int unit, int key, bcm_vlan_t vid, 475 bcm_mac_t mac, uint8 trill_tree_id, bcm_multicast_t *group) 476 { 477 L2_ENTRY_T l2_entry; 478 soc_mem_t mem; 479 soc_field_t field_key; 480 int rv=BCM_E_NONE; 481 int l2_index=0; 482 483 sal_memset(&l2_entry, 0, sizeof (l2_entry)); 484 485 if (SOC_IS_TRIUMPH3(unit)) { 486 mem = L2_ENTRY_1m; 487 } else { 488 mem = L2Xm; 489 } 490 491 switch (key) { 492 case TR_L2_HASH_KEY_TYPE_BRIDGE: 493 field_key = TR_L2_HASH_KEY_TYPE_BRIDGE; 494 soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry, 495 KEY_TYPEf, field_key); 496 soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry, 497 L2__VLAN_IDf, vid); 498 soc_mem_mac_addr_set(unit, mem, (uint32 *)&l2_entry, 499 L2__MAC_ADDRf, mac); 500 break; 501 502 case TR_L2_HASH_KEY_TYPE_TRILL_NONUC_ACCESS: 503 field_key = TR_L2_HASH_KEY_TYPE_TRILL_NONUC_ACCESS; 504 soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry, 505 KEY_TYPEf, field_key); 506 soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry, 507 L2__VLAN_IDf, vid); 508 soc_mem_mac_addr_set(unit, mem, (uint32 *)&l2_entry, 509 L2__MAC_ADDRf, mac); 510 break; 511 512 case TR_L2_HASH_KEY_TYPE_TRILL_NONUC_NETWORK_SHORT: 513 field_key = TR_L2_HASH_KEY_TYPE_TRILL_NONUC_NETWORK_SHORT; 514 soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry, 515 KEY_TYPEf, field_key); 516 soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry, 517 TRILL_NONUC_NETWORK_SHORT__TREE_IDf, 518 trill_tree_id); 519 soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry, 520 TRILL_NONUC_NETWORK_SHORT__VLAN_IDf, vid); 521 break; 522 523 case TR_L2_HASH_KEY_TYPE_TRILL_NONUC_NETWORK_LONG: 524 field_key = TR_L2_HASH_KEY_TYPE_TRILL_NONUC_NETWORK_LONG; 525 soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry, 526 KEY_TYPEf, field_key); 527 soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry, 528 TRILL_NONUC_NETWORK_LONG__TREE_IDf, 529 trill_tree_id); 530 soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry, 531 TRILL_NONUC_NETWORK_LONG__VLAN_IDf, vid); 532 soc_mem_mac_addr_set(unit, mem, (uint32 *)&l2_entry, 533 TRILL_NONUC_NETWORK_LONG__MAC_ADDRESSf, mac); 534 break; 535 536 default: 537 break; 538 } 539 540 rv = soc_mem_search(unit, mem, MEM_BLOCK_ANY, &l2_index, 541 (void *)&l2_entry, (void *)&l2_entry, 0); 542 543 if (BCM_FAILURE(rv)) { 544 return rv; 545 } 546 547 switch (key) { 548 case TR_L2_HASH_KEY_TYPE_BRIDGE: 549 _BCM_MULTICAST_GROUP_SET(*group, 550 _BCM_MULTICAST_TYPE_L2, 551 soc_mem_field32_get (unit, mem, (uint32 *)&l2_entry, 552 L2__L2MC_PTRf)); 553 break; 554 555 case TR_L2_HASH_KEY_TYPE_TRILL_NONUC_ACCESS: 556 if (SOC_IS_TRIUMPH3(unit)) { 557 _BCM_MULTICAST_GROUP_SET(*group, 558 _BCM_MULTICAST_TYPE_TRILL, 559 soc_mem_field32_get (unit, mem, (uint32 *)&l2_entry, 560 L2__L2MC_PTRf)); 561 break; 562 } else if (SOC_IS_TRIDENT2X(unit)) { 563 _BCM_MULTICAST_GROUP_SET(*group, 564 _BCM_MULTICAST_TYPE_TRILL, 565 soc_mem_field32_get (unit, mem, (uint32 *)&l2_entry, 566 L2__L3MC_PTRf)); 567 break; 568 } else { 569 _BCM_MULTICAST_GROUP_SET(*group, 570 _BCM_MULTICAST_TYPE_TRILL, 571 soc_mem_field32_get (unit, mem, (uint32 *)&l2_entry, 572 TRILL_NONUC_ACCESS__L3MC_PTRf)); 573 break; 574 } 575 576 case TR_L2_HASH_KEY_TYPE_TRILL_NONUC_NETWORK_SHORT: 577 _BCM_MULTICAST_GROUP_SET(*group, 578 _BCM_MULTICAST_TYPE_TRILL, 579 soc_mem_field32_get (unit, mem, (uint32 *)&l2_entry, 580 TRILL_NONUC_NETWORK_SHORT__L3MC_INDEXf)); 581 break; 582 583 case TR_L2_HASH_KEY_TYPE_TRILL_NONUC_NETWORK_LONG: 584 _BCM_MULTICAST_GROUP_SET(*group, 585 _BCM_MULTICAST_TYPE_TRILL, 586 soc_mem_field32_get (unit, mem, (uint32 *)&l2_entry, 587 TRILL_NONUC_NETWORK_LONG__L3MC_INDEXf)); 588 break; 589 default: 590 break; 591 } 592 return rv; 593 } 594 595 596 /* 597 * Description: 598 * Traverse TRILL Long and Short Multicast entries 599 * Parameters: 600 * unit - device number 601 * trav_st - Traverse structure with all the data. 602 * Return: 603 * BCM_E_XXX 604 */ 605 int 606 bcm_td_l2_trill_network_multicast_entry_traverse (int unit, _bcm_td_trill_multicast_entry_traverse_t *trav_st) 607 { 608 /* Indexes to iterate over memories, chunks and entries */ 609 int chnk_idx, ent_idx, chnk_idx_max, mem_idx_max; 610 int buf_size, chunksize, chnk_end; 611 /* Buffer to store chunk of L2 table we currently work on */ 612 uint32 *l2_trill_tbl_chnk; 613 L2_ENTRY_T *l2_entry; 614 int rv = BCM_E_NONE; 615 soc_mem_t mem; 616 int key_type=-1; 617 uint16 tree_id = 0; 618 bcm_trill_multicast_entry_t trill_mc; 619 620 mem = L2Xm; 621 622 sal_memset (&trill_mc, 0, sizeof (bcm_trill_multicast_entry_t)); 623 624 if (!soc_mem_index_count(unit, mem)) { 625 return BCM_E_NONE; 626 } 627 628 chunksize = soc_property_get(unit, spn_L2DELETE_CHUNKS, 629 L2_MEM_CHUNKS_DEFAULT); 630 631 buf_size = 4 * SOC_MAX_MEM_FIELD_WORDS * chunksize; 632 l2_trill_tbl_chnk = soc_cm_salloc(unit, buf_size, "trill network multicast traverse"); 633 if (NULL == l2_trill_tbl_chnk) { 634 return BCM_E_MEMORY; 635 } 636 637 mem_idx_max = soc_mem_index_max(unit, mem); 638 for (chnk_idx = soc_mem_index_min(unit, mem); chnk_idx <= mem_idx_max; 639 chnk_idx += chunksize) { 640 sal_memset((void *)l2_trill_tbl_chnk, 0, buf_size); 641 642 chnk_idx_max = 643 ((chnk_idx + chunksize) < mem_idx_max) ? 644 (chnk_idx + chunksize - 1) : mem_idx_max; 645 646 rv = soc_mem_read_range(unit, mem, MEM_BLOCK_ANY, 647 chnk_idx, chnk_idx_max, l2_trill_tbl_chnk); 648 if (SOC_FAILURE(rv)) { 649 break; 650 } 651 chnk_end = (chnk_idx_max - chnk_idx); 652 for (ent_idx = 0 ; ent_idx <= chnk_end; ent_idx ++) { 653 l2_entry = soc_mem_table_idx_to_pointer(unit, mem, L2_ENTRY_T *, 654 l2_trill_tbl_chnk, ent_idx); 655 656 if (!soc_mem_field32_get(unit, mem, l2_entry, VALIDf)) { 657 continue; 658 } 659 660 key_type = soc_mem_field32_get(unit, mem, l2_entry, KEY_TYPEf); 661 662 /* Match the Key Type to TRILL */ 663 if (key_type != TR_L2_HASH_KEY_TYPE_TRILL_NONUC_NETWORK_LONG) { 664 if (key_type != TR_L2_HASH_KEY_TYPE_TRILL_NONUC_NETWORK_SHORT) { 665 continue; 666 } 667 } 668 669 switch (key_type) { 670 671 case TR_L2_HASH_KEY_TYPE_TRILL_NONUC_NETWORK_SHORT: 672 tree_id = soc_mem_field32_get(unit, mem, l2_entry, 673 TRILL_NONUC_NETWORK_SHORT__TREE_IDf); 674 /* Check for Valid Tree_Id */ 675 if (tree_id >= BCM_MAX_NUM_TRILL_TREES ) { 676 continue; 677 } 678 (void) bcm_td_trill_root_name_get (unit, tree_id, &trill_mc.root_name); 679 _BCM_MULTICAST_GROUP_SET(trill_mc.group, 680 _BCM_MULTICAST_TYPE_TRILL, 681 soc_mem_field32_get (unit, mem, l2_entry, 682 TRILL_NONUC_NETWORK_SHORT__L3MC_INDEXf)); 683 trill_mc.c_vlan = soc_mem_field32_get (unit, mem, l2_entry, 684 TRILL_NONUC_NETWORK_SHORT__VLAN_IDf); 685 break; 686 687 case TR_L2_HASH_KEY_TYPE_TRILL_NONUC_NETWORK_LONG: 688 tree_id = soc_mem_field32_get (unit, mem, l2_entry, 689 TRILL_NONUC_NETWORK_LONG__TREE_IDf); 690 /* Check for Valid Tree_Id */ 691 if (tree_id >= BCM_MAX_NUM_TRILL_TREES ) { 692 continue; 693 } 694 (void) bcm_td_trill_root_name_get (unit, tree_id, &trill_mc.root_name); 695 _BCM_MULTICAST_GROUP_SET(trill_mc.group, 696 _BCM_MULTICAST_TYPE_TRILL, 697 soc_mem_field32_get (unit, mem, l2_entry, 698 TRILL_NONUC_NETWORK_LONG__L3MC_INDEXf)); 699 trill_mc.c_vlan = soc_mem_field32_get (unit, mem, l2_entry, 700 TRILL_NONUC_NETWORK_LONG__VLAN_IDf); 701 soc_mem_mac_addr_get(unit, mem, l2_entry, 702 TRILL_NONUC_NETWORK_LONG__MAC_ADDRESSf, trill_mc.c_dmac); 703 break; 704 705 } 706 trill_mc.flags = BCM_TRILL_MULTICAST_STATIC; 707 rv = trav_st->user_cb(unit, &trill_mc, trav_st->user_data); 708 if (BCM_FAILURE(rv)) { 709 break; 710 } 711 } 712 if (BCM_FAILURE(rv)) { 713 break; 714 } 715 } 716 soc_cm_sfree(unit, l2_trill_tbl_chnk); 717 return rv; 718 } 719 720 /* 721 * Description: 722 * Traverse TRILL Access to Network Multicast entries 723 * Parameters: 724 * unit - device number 725 * trav_st - Traverse structure with all the data. 726 * Return: 727 * BCM_E_XXX 728 */ 729 int 730 bcm_td_l2_trill_access_multicast_entry_traverse (int unit, _bcm_td_trill_multicast_entry_traverse_t *trav_st) 731 { 732 /* Indexes to iterate over memories, chunks and entries */ 733 int chnk_idx, ent_idx, chnk_idx_max, mem_idx_max; 734 int buf_size, chunksize, chnk_end; 735 /* Buffer to store chunk of L2 table we currently work on */ 736 uint32 *l2_trill_tbl_chnk; 737 L2_ENTRY_T *l2_entry; 738 int rv = BCM_E_NONE; 739 soc_mem_t mem; 740 int key_type=-1; 741 bcm_trill_multicast_entry_t trill_mc; 742 743 mem = L2Xm; 744 745 sal_memset (&trill_mc, 0, sizeof (bcm_trill_multicast_entry_t)); 746 747 if (!soc_mem_index_count(unit, mem)) { 748 return BCM_E_NONE; 749 } 750 751 chunksize = soc_property_get(unit, spn_L2DELETE_CHUNKS, 752 L2_MEM_CHUNKS_DEFAULT); 753 754 buf_size = 4 * SOC_MAX_MEM_FIELD_WORDS * chunksize; 755 l2_trill_tbl_chnk = soc_cm_salloc(unit, buf_size, "trill access multicast traverse"); 756 if (NULL == l2_trill_tbl_chnk) { 757 return BCM_E_MEMORY; 758 } 759 760 mem_idx_max = soc_mem_index_max(unit, mem); 761 for (chnk_idx = soc_mem_index_min(unit, mem); chnk_idx <= mem_idx_max; 762 chnk_idx += chunksize) { 763 sal_memset((void *)l2_trill_tbl_chnk, 0, buf_size); 764 765 chnk_idx_max = 766 ((chnk_idx + chunksize) < mem_idx_max) ? 767 (chnk_idx + chunksize - 1) : mem_idx_max; 768 769 rv = soc_mem_read_range(unit, mem, MEM_BLOCK_ANY, 770 chnk_idx, chnk_idx_max, l2_trill_tbl_chnk); 771 if (SOC_FAILURE(rv)) { 772 break; 773 } 774 chnk_end = (chnk_idx_max - chnk_idx); 775 for (ent_idx = 0 ; ent_idx <= chnk_end; ent_idx ++) { 776 l2_entry = soc_mem_table_idx_to_pointer(unit, mem, L2_ENTRY_T *, 777 l2_trill_tbl_chnk, ent_idx); 778 779 if (!soc_mem_field32_get(unit, mem, l2_entry, VALIDf)) { 780 continue; 781 } 782 key_type = soc_mem_field32_get(unit, mem, l2_entry, KEY_TYPEf); 783 if (key_type != TR_L2_HASH_KEY_TYPE_TRILL_NONUC_ACCESS) { 784 continue; 785 } else { 786 _BCM_MULTICAST_GROUP_SET(trill_mc.group, 787 _BCM_MULTICAST_TYPE_TRILL, 788 soc_mem_field32_get(unit, mem, l2_entry, 789 TRILL_NONUC_ACCESS__L3MC_PTRf)); 790 trill_mc.c_vlan = soc_mem_field32_get(unit, mem, l2_entry, 791 TRILL_NONUC_ACCESS__VLAN_IDf); 792 soc_mem_mac_addr_get(unit, mem, l2_entry, 793 TRILL_NONUC_ACCESS__MAC_ADDRf, trill_mc.c_dmac); 794 } 795 trill_mc.flags = BCM_TRILL_MULTICAST_ACCESS_TO_NETWORK | BCM_TRILL_MULTICAST_STATIC; 796 rv = bcm_td_multicast_trill_rootname_get(unit, trill_mc.group, &trill_mc.root_name); 797 if (BCM_FAILURE(rv)) { 798 continue; 799 } 800 801 rv = trav_st->user_cb(unit, &trill_mc, trav_st->user_data); 802 if (BCM_FAILURE(rv)) { 803 break; 804 } 805 } 806 if (BCM_FAILURE(rv)) { 807 break; 808 } 809 } 810 soc_cm_sfree(unit, l2_trill_tbl_chnk); 811 return rv; 812 } 813 814 /* 815 * Description: 816 * Modify TRILL short Multicast entries 817 * Parameters: 818 * unit - device number 819 * trav_st - Traverse structure with all the data. 820 * Return: 821 * BCM_E_XXX 822 */ 823 int 824 bcm_td_l2_trill_vlan_multicast_entry_modify (int unit, bcm_vlan_t vlan, int set_bit) 825 { 826 /* Indexes to iterate over memories, chunks and entries */ 827 int chnk_idx, ent_idx, chnk_idx_max, mem_idx_max; 828 int buf_size, chunksize, chnk_end; 829 /* Buffer to store chunk of L2 table we currently work on */ 830 uint32 *l2_trill_tbl_chnk; 831 L2_ENTRY_T *l2_entry; 832 int rv = BCM_E_NONE; 833 soc_mem_t mem; 834 int key_type=-1; 835 int key_comp=-1; 836 uint16 tree_id = 0; 837 bcm_trill_multicast_entry_t trill_mc; 838 int count=0; 839 840 #if defined (BCM_TRIDENT2_SUPPORT) 841 if (SOC_IS_TRIDENT2X(unit)) { 842 mem = L2Xm; 843 /* coverity[mixed_enums] */ 844 key_comp = TD2_L2_HASH_KEY_TYPE_TRILL_NONUC_NETWORK_SHORT; 845 } else 846 #endif /* BCM_TRIDENT2_SUPPORT */ 847 #if defined (BCM_TRIUMPH3_SUPPORT) 848 if (SOC_IS_TRIUMPH3(unit)) { 849 mem = L2_ENTRY_1m; 850 /* Suppress coverity warning, because enum values used here 851 * for key_comp are defined differently based on device type 852 */ 853 /* coverity[mixed_enums] */ 854 key_comp = SOC_MEM_KEY_L2_ENTRY_1_TRILL_NONUC_NETWORK_SHORT_TRILL_NONUC_NETWORK_SHORT; 855 } else 856 #endif /* BCM_TRIUMPH3_SUPPORT */ 857 { 858 mem = L2Xm; 859 /* Suppress coverity warning, because enum values used here 860 * for key_comp are defined differently based on device type 861 */ 862 /* coverity[mixed_enums] */ 863 key_comp = TR_L2_HASH_KEY_TYPE_TRILL_NONUC_NETWORK_SHORT; 864 } 865 866 sal_memset (&trill_mc, 0, sizeof (bcm_trill_multicast_entry_t)); 867 868 if (!soc_mem_index_count(unit, mem)) { 869 return BCM_E_NONE; 870 } 871 872 chunksize = soc_property_get(unit, spn_L2DELETE_CHUNKS, 873 L2_MEM_CHUNKS_DEFAULT); 874 875 buf_size = 4 * SOC_MAX_MEM_FIELD_WORDS * chunksize; 876 l2_trill_tbl_chnk = soc_cm_salloc(unit, buf_size, "trill network multicast traverse"); 877 if (NULL == l2_trill_tbl_chnk) { 878 return BCM_E_MEMORY; 879 } 880 881 mem_idx_max = soc_mem_index_max(unit, mem); 882 for (chnk_idx = soc_mem_index_min(unit, mem); chnk_idx <= mem_idx_max; 883 chnk_idx += chunksize) { 884 sal_memset((void *)l2_trill_tbl_chnk, 0, buf_size); 885 886 chnk_idx_max = 887 ((chnk_idx + chunksize) < mem_idx_max) ? 888 (chnk_idx + chunksize - 1) : mem_idx_max; 889 890 rv = soc_mem_read_range(unit, mem, MEM_BLOCK_ANY, 891 chnk_idx, chnk_idx_max, l2_trill_tbl_chnk); 892 if (SOC_FAILURE(rv)) { 893 break; 894 } 895 chnk_end = (chnk_idx_max - chnk_idx); 896 for (ent_idx = 0 ; ent_idx <= chnk_end; ent_idx ++) { 897 l2_entry = soc_mem_table_idx_to_pointer(unit, mem, L2_ENTRY_T *, 898 l2_trill_tbl_chnk, ent_idx); 899 900 if (!soc_mem_field32_get(unit, mem, l2_entry, VALIDf)) { 901 continue; 902 } 903 904 key_type = soc_mem_field32_get(unit, mem, l2_entry, KEY_TYPEf); 905 906 /* Match the Key Type to TRILL */ 907 if (key_type != key_comp) { 908 continue; 909 } else { 910 tree_id = soc_mem_field32_get(unit, mem, l2_entry, 911 TRILL_NONUC_NETWORK_SHORT__TREE_IDf); 912 /* Check for Valid Tree_Id */ 913 if (tree_id >= BCM_MAX_NUM_TRILL_TREES ) { 914 continue; 915 } 916 trill_mc.c_vlan = soc_mem_field32_get (unit, mem, l2_entry, 917 TRILL_NONUC_NETWORK_SHORT__VLAN_IDf); 918 if (vlan == trill_mc.c_vlan) { 919 if (set_bit) { 920 soc_mem_field32_set(unit, mem, (uint32 *)l2_entry, 921 TRILL_NONUC_NETWORK_SHORT__TRILL_ACCESS_RECEIVERS_PRESENTf, 0x1); 922 } else { 923 soc_mem_field32_set(unit, mem, (uint32 *)l2_entry, 924 TRILL_NONUC_NETWORK_SHORT__TRILL_ACCESS_RECEIVERS_PRESENTf, 0x0); 925 } 926 count ++; 927 } 928 } 929 } 930 if (count > 0) { 931 rv = soc_mem_write_range(unit, mem, 932 MEM_BLOCK_ANY, chnk_idx, 933 chnk_idx_max, l2_trill_tbl_chnk); 934 } 935 } 936 soc_cm_sfree(unit, l2_trill_tbl_chnk); 937 return rv; 938 } 939 940 #endif /* INCLUDE_L3 */ 941 942 #endif /* BCM_TRIDENT_SUPORT */