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