extender.c (24738B)
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: extender.c 8 * Purpose: Implements bcm_extender_forward_* APIs for Trident2. 9 */ 10 11 #include <soc/defs.h> 12 #include <sal/core/libc.h> 13 #include <soc/katana2.h> 14 15 #if defined(BCM_TRIDENT2_SUPPORT) || defined(BCM_PE_SUPPORT) 16 #if defined(INCLUDE_L3) 17 18 #include <soc/mem.h> 19 #include <soc/ism_hash.h> 20 21 #include <bcm/error.h> 22 23 #include <bcm_int/common/multicast.h> 24 #include <bcm_int/esw/trident2.h> 25 26 /* 27 * Purpose: 28 * Add a downstream forwarding entry 29 * Parameters: 30 * unit - (IN) Device Number 31 * forward_entry - (IN) Forwarding entry 32 */ 33 int 34 bcm_td2_extender_forward_add(int unit, bcm_extender_forward_t *forward_entry) 35 { 36 int rv = BCM_E_NONE; 37 bcm_module_t mod_out; 38 bcm_port_t port_out; 39 bcm_trunk_t tgid_out; 40 int id_out; 41 l2x_entry_t l2x_entry; 42 int lower_th, higher_th; 43 44 if (forward_entry->name_space > 0xfff) { 45 return BCM_E_PARAM; 46 } 47 48 BCM_IF_ERROR_RETURN( 49 bcm_esw_switch_control_get(unit, 50 bcmSwitchExtenderMulticastLowerThreshold, 51 &lower_th)); 52 BCM_IF_ERROR_RETURN( 53 bcm_esw_switch_control_get(unit, 54 bcmSwitchExtenderMulticastHigherThreshold, 55 &higher_th)); 56 57 if ((forward_entry->extended_port_vid >= 58 (1 << soc_mem_field_length(unit, L2Xm, PE_VID__ETAG_VIDf))) || 59 (forward_entry->class_id >= 60 (1 << soc_mem_field_length(unit, L2Xm, PE_VID__CLASS_IDf)))) { 61 return BCM_E_PARAM; 62 } 63 64 if (!(forward_entry->flags & BCM_EXTENDER_FORWARD_MULTICAST)) { 65 if ((forward_entry->extended_port_vid >= lower_th) && 66 (forward_entry->extended_port_vid <= higher_th)) { 67 return BCM_E_PARAM; 68 } 69 70 BCM_IF_ERROR_RETURN(_bcm_esw_gport_resolve(unit, 71 forward_entry->dest_port, 72 &mod_out, &port_out, &tgid_out, &id_out)); 73 if (-1 != id_out) { 74 return BCM_E_PARAM; 75 } 76 77 sal_memset(&l2x_entry, 0, sizeof(l2x_entry)); 78 soc_L2Xm_field32_set(unit, &l2x_entry, 79 soc_feature(unit, soc_feature_base_valid) ? BASE_VALIDf : VALIDf, 1); 80 #ifdef BCM_PE_SUPPORT 81 if (soc_feature(unit, soc_feature_port_extension_kt2_key_type)) { 82 soc_L2Xm_field32_set(unit, &l2x_entry, KEY_TYPEf, 83 KT2_L2_HASH_KEY_TYPE_PE_VID); 84 } else 85 #endif /* BCM_PE_SUPPORT */ 86 { 87 soc_L2Xm_field32_set(unit, &l2x_entry, KEY_TYPEf, 88 TR_L2_HASH_KEY_TYPE_PE_VID); 89 } 90 soc_L2Xm_field32_set(unit, &l2x_entry, PE_VID__NAMESPACEf, 91 forward_entry->name_space); 92 soc_L2Xm_field32_set(unit, &l2x_entry, PE_VID__ETAG_VIDf, 93 forward_entry->extended_port_vid); 94 soc_L2Xm_field32_set(unit, &l2x_entry, PE_VID__CLASS_IDf, 95 forward_entry->class_id); 96 if (-1 != tgid_out) { 97 BCM_IF_ERROR_RETURN(_bcm_trunk_id_validate(unit, tgid_out)); 98 if (soc_feature(unit, soc_feature_generic_dest)) { 99 soc_mem_field32_dest_set(unit, L2Xm, &l2x_entry, 100 PE_VID__DESTINATIONf, SOC_MEM_FIF_DEST_LAG, tgid_out); 101 } else { 102 soc_L2Xm_field32_set(unit, &l2x_entry, PE_VID__DEST_TYPEf, 1); 103 soc_L2Xm_field32_set(unit, &l2x_entry, PE_VID__TGIDf, tgid_out); 104 } 105 } else { 106 if (soc_feature(unit, soc_feature_generic_dest)) { 107 soc_mem_field32_dest_set(unit, L2Xm, &l2x_entry, 108 PE_VID__DESTINATIONf, SOC_MEM_FIF_DEST_DGPP, 109 mod_out << SOC_MEM_FIF_DGPP_MOD_ID_SHIFT_BITS | port_out); 110 } else { 111 soc_L2Xm_field32_set(unit, &l2x_entry, 112 PE_VID__MODULE_IDf, mod_out); 113 soc_L2Xm_field32_set(unit, &l2x_entry, 114 PE_VID__PORT_NUMf, port_out); 115 } 116 } 117 soc_L2Xm_field32_set(unit, &l2x_entry, PE_VID__STATIC_BITf, 1); 118 119 } else { /* Multicast forward entry */ 120 if ((forward_entry->extended_port_vid < lower_th) || 121 (forward_entry->extended_port_vid > higher_th)) { 122 return BCM_E_PARAM; 123 } 124 if (!_BCM_MULTICAST_IS_L2(forward_entry->dest_multicast)) { 125 return BCM_E_PARAM; 126 } 127 128 sal_memset(&l2x_entry, 0, sizeof(l2x_entry)); 129 soc_L2Xm_field32_set(unit, &l2x_entry, 130 soc_feature(unit, soc_feature_base_valid) ? BASE_VALIDf : VALIDf, 1); 131 #ifdef BCM_PE_SUPPORT 132 if (soc_feature(unit, soc_feature_port_extension_kt2_key_type)) { 133 soc_L2Xm_field32_set(unit, &l2x_entry, KEY_TYPEf, 134 KT2_L2_HASH_KEY_TYPE_PE_VID); 135 } else 136 #endif /* BCM_PE_SUPPORT */ 137 { 138 soc_L2Xm_field32_set(unit, &l2x_entry, KEY_TYPEf, 139 TR_L2_HASH_KEY_TYPE_PE_VID); 140 } 141 soc_L2Xm_field32_set(unit, &l2x_entry, PE_VID__NAMESPACEf, 142 forward_entry->name_space); 143 soc_L2Xm_field32_set(unit, &l2x_entry, PE_VID__ETAG_VIDf, 144 forward_entry->extended_port_vid); 145 soc_L2Xm_field32_set(unit, &l2x_entry, PE_VID__CLASS_IDf, 146 forward_entry->class_id); 147 if (soc_feature(unit, soc_feature_generic_dest)) { 148 soc_mem_field32_dest_set(unit, L2Xm, &l2x_entry, 149 PE_VID__DESTINATIONf, SOC_MEM_FIF_DEST_L2MC, 150 _BCM_MULTICAST_ID_GET(forward_entry->dest_multicast)); 151 } else { 152 soc_L2Xm_field32_set(unit, &l2x_entry, PE_VID__L2MC_PTRf, 153 _BCM_MULTICAST_ID_GET(forward_entry->dest_multicast)); 154 } 155 soc_L2Xm_field32_set(unit, &l2x_entry, PE_VID__STATIC_BITf, 1); 156 } 157 158 if (forward_entry->flags & BCM_EXTENDER_FORWARD_COPY_TO_CPU) { 159 if (SOC_MEM_FIELD_VALID(unit, L2Xm, PE_VID__DST_CPUf)) { 160 soc_L2Xm_field32_set(unit, &l2x_entry, PE_VID__DST_CPUf, 1); 161 } else if (SOC_MEM_FIELD_VALID(unit, L2Xm, PE_VID__CPUf)) { 162 soc_L2Xm_field32_set(unit, &l2x_entry, PE_VID__CPUf, 1); 163 } 164 } 165 166 soc_mem_lock(unit, L2Xm); 167 168 if (!(forward_entry->flags & BCM_EXTENDER_FORWARD_REPLACE)) { 169 l2x_entry_t l2x_lookup; 170 int l2_index; 171 172 /* See if the entry already exists */ 173 rv = soc_mem_generic_lookup(unit, L2Xm, MEM_BLOCK_ANY, 0, &l2x_entry, 174 &l2x_lookup, &l2_index); 175 if (BCM_FAILURE(rv) && (rv != BCM_E_NOT_FOUND)) { 176 soc_mem_unlock(unit, L2Xm); 177 return rv; 178 } 179 if (BCM_SUCCESS(rv)) { 180 soc_mem_unlock(unit, L2Xm); 181 return BCM_E_EXISTS; 182 } 183 184 rv = soc_mem_insert(unit, L2Xm, MEM_BLOCK_ALL, &l2x_entry); 185 if (SOC_FAILURE(rv)) { 186 soc_mem_unlock(unit, L2Xm); 187 return rv; 188 } 189 } else { /* Replace existing entry */ 190 rv = soc_mem_delete(unit, L2Xm, MEM_BLOCK_ALL, &l2x_entry); 191 if (SOC_FAILURE(rv)) { 192 soc_mem_unlock(unit, L2Xm); 193 return rv; 194 } 195 rv = soc_mem_insert(unit, L2Xm, MEM_BLOCK_ALL, &l2x_entry); 196 if (SOC_FAILURE(rv)) { 197 soc_mem_unlock(unit, L2Xm); 198 return rv; 199 } 200 } 201 202 soc_mem_unlock(unit, L2Xm); 203 204 return rv; 205 } 206 207 /* 208 * Purpose: 209 * Delete a downstream forwarding entry 210 * Parameters: 211 * unit - (IN) Device Number 212 * forward_entry - (IN) Forwarding entry 213 */ 214 int 215 bcm_td2_extender_forward_delete(int unit, bcm_extender_forward_t *forward_entry) 216 { 217 int rv = BCM_E_NONE; 218 l2x_entry_t l2x_entry; 219 int lower_th, higher_th; 220 221 if (forward_entry->name_space > 0xfff) { 222 return BCM_E_PARAM; 223 } 224 225 BCM_IF_ERROR_RETURN( 226 bcm_esw_switch_control_get(unit, 227 bcmSwitchExtenderMulticastLowerThreshold, 228 &lower_th)); 229 BCM_IF_ERROR_RETURN( 230 bcm_esw_switch_control_get(unit, 231 bcmSwitchExtenderMulticastHigherThreshold, 232 &higher_th)); 233 234 if (forward_entry->extended_port_vid >= 235 (1 << soc_mem_field_length(unit, L2Xm, PE_VID__ETAG_VIDf))) { 236 return BCM_E_PARAM; 237 } 238 239 if (!(forward_entry->flags & BCM_EXTENDER_FORWARD_MULTICAST)) { 240 if ((forward_entry->extended_port_vid >= lower_th) && 241 (forward_entry->extended_port_vid <= higher_th)) { 242 return BCM_E_PARAM; 243 } 244 } else { /* Multicast forward entry */ 245 if ((forward_entry->extended_port_vid < lower_th) || 246 (forward_entry->extended_port_vid > higher_th)) { 247 return BCM_E_PARAM; 248 } 249 } 250 251 sal_memset(&l2x_entry, 0, sizeof(l2x_entry)); 252 #ifdef BCM_PE_SUPPORT 253 if (soc_feature(unit, soc_feature_port_extension_kt2_key_type)) { 254 soc_L2Xm_field32_set(unit, &l2x_entry, KEY_TYPEf, 255 KT2_L2_HASH_KEY_TYPE_PE_VID); 256 } else 257 #endif /* BCM_PE_SUPPORT */ 258 { 259 soc_L2Xm_field32_set(unit, &l2x_entry, KEY_TYPEf, 260 TR_L2_HASH_KEY_TYPE_PE_VID); 261 } 262 soc_L2Xm_field32_set(unit, &l2x_entry, PE_VID__NAMESPACEf, 263 forward_entry->name_space); 264 soc_L2Xm_field32_set(unit, &l2x_entry, PE_VID__ETAG_VIDf, 265 forward_entry->extended_port_vid); 266 soc_mem_lock(unit, L2Xm); 267 rv = soc_mem_delete(unit, L2Xm, MEM_BLOCK_ALL, &l2x_entry); 268 soc_mem_unlock(unit, L2Xm); 269 270 return rv; 271 } 272 273 /* 274 * Purpose: 275 * Delete all downstream forwarding entries 276 * Parameters: 277 * unit - Device Number 278 */ 279 int 280 bcm_td2_extender_forward_delete_all(int unit) 281 { 282 int rv = BCM_E_NONE; 283 int field_len; 284 285 #ifdef BCM_TOMAHAWK_SUPPORT 286 if (soc_feature(unit, soc_feature_l2_bulk_unified_table)) { 287 l2_bulk_entry_t match_mask, match_data; 288 289 sal_memset(&match_mask, 0, sizeof(match_mask)); 290 sal_memset(&match_data, 0, sizeof(match_data)); 291 292 if (soc_feature(unit, soc_feature_base_valid)) { 293 soc_mem_field32_set(unit, L2_BULKm, &match_mask, BASE_VALIDf, 1); 294 soc_mem_field32_set(unit, L2_BULKm, &match_data, BASE_VALIDf, 1); 295 } else { 296 soc_mem_field32_set(unit, L2_BULKm, &match_mask, VALIDf, 1); 297 soc_mem_field32_set(unit, L2_BULKm, &match_data, VALIDf, 1); 298 } 299 300 field_len = soc_mem_field_length(unit, L2_BULKm, KEY_TYPEf); 301 soc_mem_field32_set(unit, L2_BULKm, &match_mask, KEY_TYPEf, 302 (1 << field_len) - 1); 303 soc_mem_field32_set(unit, L2_BULKm, &match_data, KEY_TYPEf, 304 TR_L2_HASH_KEY_TYPE_PE_VID); 305 soc_mem_lock(unit, L2Xm); 306 rv = WRITE_L2_BULKm(unit, MEM_BLOCK_ALL, _BCM_L2_BULK_MATCH_MASK_INX, 307 &match_mask); 308 if (BCM_SUCCESS(rv)) { 309 rv = WRITE_L2_BULKm(unit, MEM_BLOCK_ALL, 310 _BCM_L2_BULK_MATCH_DATA_INX, 311 &match_data); 312 } 313 if (BCM_SUCCESS(rv)) { 314 rv = soc_reg_field32_modify(unit, L2_BULK_CONTROLr, REG_PORT_ANY, 315 NUM_ENTRIESf, 316 soc_mem_index_count(unit, L2Xm)); 317 } 318 } else 319 #endif /* BCM_TOMAHAWK_SUPPORT */ 320 { 321 l2_bulk_match_mask_entry_t match_mask; 322 l2_bulk_match_data_entry_t match_data; 323 324 sal_memset(&match_mask, 0, sizeof(match_mask)); 325 sal_memset(&match_data, 0, sizeof(match_data)); 326 327 soc_mem_field32_set(unit, L2_BULK_MATCH_MASKm, &match_mask, VALIDf, 1); 328 soc_mem_field32_set(unit, L2_BULK_MATCH_DATAm, &match_data, VALIDf, 1); 329 330 field_len = soc_mem_field_length(unit, L2_BULK_MATCH_MASKm, KEY_TYPEf); 331 soc_mem_field32_set(unit, L2_BULK_MATCH_MASKm, &match_mask, KEY_TYPEf, 332 (1 << field_len) - 1); 333 #ifdef BCM_PE_SUPPORT 334 if (soc_feature(unit, soc_feature_port_extension_kt2_key_type)) { 335 soc_mem_field32_set(unit, L2_BULK_MATCH_DATAm, &match_data, KEY_TYPEf, 336 KT2_L2_HASH_KEY_TYPE_PE_VID); 337 } else 338 #endif /* BCM_PE_SUPPORT */ 339 { 340 soc_mem_field32_set(unit, L2_BULK_MATCH_DATAm, &match_data, KEY_TYPEf, 341 TR_L2_HASH_KEY_TYPE_PE_VID); 342 } 343 soc_mem_lock(unit, L2Xm); 344 rv = WRITE_L2_BULK_MATCH_MASKm(unit, MEM_BLOCK_ALL, 0, 345 &match_mask); 346 if (BCM_SUCCESS(rv)) { 347 rv = WRITE_L2_BULK_MATCH_DATAm(unit, MEM_BLOCK_ALL, 0, 348 &match_data); 349 } 350 } 351 if (BCM_SUCCESS(rv)) { 352 rv = soc_reg_field32_modify(unit, L2_BULK_CONTROLr, REG_PORT_ANY, 353 ACTIONf, 1); 354 } 355 if (BCM_SUCCESS(rv)) { 356 rv = soc_l2x_port_age(unit, L2_BULK_CONTROLr, INVALIDr); 357 } 358 soc_mem_unlock(unit, L2Xm); 359 return rv; 360 } 361 362 /* 363 * Purpose: 364 * Get a downstream forwarding entry 365 * Parameters: 366 * unit - (IN) Device Number 367 * forward_entry - (IN/OUT) Forwarding entry 368 */ 369 int 370 bcm_td2_extender_forward_get(int unit, bcm_extender_forward_t *forward_entry) 371 { 372 int rv = BCM_E_NONE; 373 l2x_entry_t l2x_entry, l2x_entry_out; 374 int idx; 375 _bcm_gport_dest_t dest; 376 int l2mc_index; 377 int lower_th, higher_th; 378 379 if (forward_entry->name_space > 0xfff) { 380 return BCM_E_PARAM; 381 } 382 383 BCM_IF_ERROR_RETURN( 384 bcm_esw_switch_control_get(unit, 385 bcmSwitchExtenderMulticastLowerThreshold, 386 &lower_th)); 387 BCM_IF_ERROR_RETURN( 388 bcm_esw_switch_control_get(unit, 389 bcmSwitchExtenderMulticastHigherThreshold, 390 &higher_th)); 391 392 if (forward_entry->extended_port_vid >= 393 (1 << soc_mem_field_length(unit, L2Xm, PE_VID__ETAG_VIDf))) { 394 return BCM_E_PARAM; 395 } 396 397 if (!(forward_entry->flags & BCM_EXTENDER_FORWARD_MULTICAST)) { 398 if ((forward_entry->extended_port_vid >= lower_th) && 399 (forward_entry->extended_port_vid <= higher_th)) { 400 return BCM_E_PARAM; 401 } 402 } else { /* Multicast forward entry */ 403 if ((forward_entry->extended_port_vid < lower_th) || 404 (forward_entry->extended_port_vid > higher_th)) { 405 return BCM_E_PARAM; 406 } 407 } 408 409 sal_memset(&l2x_entry, 0, sizeof(l2x_entry)); 410 #ifdef BCM_PE_SUPPORT 411 if (soc_feature(unit, soc_feature_port_extension_kt2_key_type)) { 412 soc_L2Xm_field32_set(unit, &l2x_entry, KEY_TYPEf, 413 KT2_L2_HASH_KEY_TYPE_PE_VID); 414 } else 415 #endif /* BCM_PE_SUPPORT */ 416 { 417 soc_L2Xm_field32_set(unit, &l2x_entry, KEY_TYPEf, 418 TR_L2_HASH_KEY_TYPE_PE_VID); 419 } 420 soc_L2Xm_field32_set(unit, &l2x_entry, PE_VID__NAMESPACEf, 421 forward_entry->name_space); 422 soc_L2Xm_field32_set(unit, &l2x_entry, PE_VID__ETAG_VIDf, 423 forward_entry->extended_port_vid); 424 soc_mem_lock(unit, L2Xm); 425 rv = soc_mem_search(unit, L2Xm, MEM_BLOCK_ALL, &idx, &l2x_entry, 426 &l2x_entry_out, 0); 427 soc_mem_unlock(unit, L2Xm); 428 429 if (SOC_SUCCESS(rv)) { 430 uint32 dv, dt = SOC_MEM_FIF_DEST_INVALID; 431 if (!(forward_entry->flags & BCM_EXTENDER_FORWARD_MULTICAST)) { 432 if (soc_feature(unit, soc_feature_generic_dest)) { 433 dv = soc_mem_field32_dest_get(unit, L2Xm, &l2x_entry_out, 434 PE_VID__DESTINATIONf, &dt); 435 if (dt == SOC_MEM_FIF_DEST_LAG) { 436 dest.tgid = dv; 437 dest.gport_type = _SHR_GPORT_TYPE_TRUNK; 438 } else { 439 dest.port = dv & SOC_MEM_FIF_DGPP_PORT_MASK; 440 dest.modid = (dv & SOC_MEM_FIF_DGPP_MOD_ID_MASK) >> 441 SOC_MEM_FIF_DGPP_MOD_ID_SHIFT_BITS; 442 dest.gport_type = _SHR_GPORT_TYPE_MODPORT; 443 } 444 } else { 445 if (soc_L2Xm_field32_get(unit, &l2x_entry_out, 446 PE_VID__DEST_TYPEf)) { 447 dest.tgid = soc_L2Xm_field32_get(unit, &l2x_entry_out, 448 PE_VID__TGIDf); 449 dest.gport_type = _SHR_GPORT_TYPE_TRUNK; 450 } else { 451 dest.modid = soc_L2Xm_field32_get(unit, &l2x_entry_out, 452 PE_VID__MODULE_IDf); 453 dest.port = soc_L2Xm_field32_get(unit, &l2x_entry_out, 454 PE_VID__PORT_NUMf); 455 dest.gport_type = _SHR_GPORT_TYPE_MODPORT; 456 } 457 } 458 BCM_IF_ERROR_RETURN(_bcm_esw_gport_construct(unit, &dest, 459 &(forward_entry->dest_port))); 460 } else { 461 if (soc_feature(unit, soc_feature_generic_dest)) { 462 dv = soc_mem_field32_dest_get(unit, L2Xm, &l2x_entry_out, 463 PE_VID__DESTINATIONf, &dt); 464 l2mc_index = (dt == SOC_MEM_FIF_DEST_L2MC) ? dv : 0; 465 } else { 466 l2mc_index = soc_L2Xm_field32_get(unit, &l2x_entry_out, 467 PE_VID__L2MC_PTRf); 468 } 469 _BCM_MULTICAST_GROUP_SET(forward_entry->dest_multicast, 470 _BCM_MULTICAST_TYPE_L2, l2mc_index); 471 } 472 forward_entry->class_id = soc_L2Xm_field32_get(unit, &l2x_entry_out, 473 PE_VID__CLASS_IDf); 474 } 475 476 return rv; 477 } 478 479 /* 480 * Purpose: 481 * Traverse all valid downstream forwarding entries and call the 482 * supplied callback routine. 483 * Parameters: 484 * unit - Device Number 485 * cb - User callback function, called once per forwarding entry. 486 * user_data - cookie 487 * Returns: 488 * BCM_E_XXX 489 */ 490 int 491 bcm_td2_extender_forward_traverse(int unit, 492 bcm_extender_forward_traverse_cb cb, 493 void *user_data) 494 { 495 int rv = BCM_E_NONE; 496 int chunk_entries, chunk_bytes; 497 uint8 *l2_tbl_chunk = NULL; 498 int chunk_idx_min, chunk_idx_max; 499 int ent_idx; 500 l2x_entry_t *l2x_entry; 501 bcm_extender_forward_t forward_entry; 502 int l2mc_index; 503 _bcm_gport_dest_t dest; 504 int lower_th, higher_th; 505 int key_val = 0; 506 507 /* Get ETAG VID multicast range */ 508 BCM_IF_ERROR_RETURN(bcm_esw_switch_control_get(unit, 509 bcmSwitchExtenderMulticastLowerThreshold, &lower_th)); 510 BCM_IF_ERROR_RETURN(bcm_esw_switch_control_get(unit, 511 bcmSwitchExtenderMulticastHigherThreshold, &higher_th)); 512 513 chunk_entries = soc_property_get(unit, spn_L2DELETE_CHUNKS, 514 L2_MEM_CHUNKS_DEFAULT); 515 chunk_bytes = 4 * SOC_MEM_WORDS(unit, L2Xm) * chunk_entries; 516 l2_tbl_chunk = soc_cm_salloc(unit, chunk_bytes, "extender forward traverse"); 517 if (NULL == l2_tbl_chunk) { 518 return BCM_E_MEMORY; 519 } 520 for (chunk_idx_min = soc_mem_index_min(unit, L2Xm); 521 chunk_idx_min <= soc_mem_index_max(unit, L2Xm); 522 chunk_idx_min += chunk_entries) { 523 524 /* Read a chunk of L2 table */ 525 sal_memset(l2_tbl_chunk, 0, chunk_bytes); 526 chunk_idx_max = chunk_idx_min + chunk_entries - 1; 527 if (chunk_idx_max > soc_mem_index_max(unit, L2Xm)) { 528 chunk_idx_max = soc_mem_index_max(unit, L2Xm); 529 } 530 rv = soc_mem_read_range(unit, L2Xm, MEM_BLOCK_ANY, 531 chunk_idx_min, chunk_idx_max, l2_tbl_chunk); 532 if (SOC_FAILURE(rv)) { 533 break; 534 } 535 for (ent_idx = 0; 536 ent_idx <= (chunk_idx_max - chunk_idx_min); 537 ent_idx++) { 538 uint32 dv, dt = SOC_MEM_FIF_DEST_INVALID; 539 l2x_entry = soc_mem_table_idx_to_pointer(unit, L2Xm, l2x_entry_t *, 540 l2_tbl_chunk, ent_idx); 541 if (soc_L2Xm_field32_get(unit, l2x_entry, 542 soc_feature(unit, soc_feature_base_valid) ? 543 BASE_VALIDf : 544 VALIDf) == 0) { 545 continue; 546 } 547 #ifdef BCM_PE_SUPPORT 548 if (soc_feature(unit, soc_feature_port_extension_kt2_key_type)) { 549 key_val = (int)KT2_L2_HASH_KEY_TYPE_PE_VID; 550 } else 551 #endif /* BCM_PE_SUPPORT */ 552 { 553 key_val = (int)TR_L2_HASH_KEY_TYPE_PE_VID; 554 } 555 if (soc_L2Xm_field32_get(unit, l2x_entry, KEY_TYPEf) != key_val) { 556 continue; 557 } 558 559 /* Get fields of forwarding entry */ 560 bcm_extender_forward_t_init(&forward_entry); 561 forward_entry.name_space = soc_L2Xm_field32_get(unit, l2x_entry, 562 PE_VID__NAMESPACEf); 563 forward_entry.extended_port_vid = soc_L2Xm_field32_get(unit, 564 l2x_entry, PE_VID__ETAG_VIDf); 565 forward_entry.class_id = soc_L2Xm_field32_get(unit, 566 l2x_entry, PE_VID__CLASS_IDf); 567 if ((forward_entry.extended_port_vid >= lower_th) && 568 (forward_entry.extended_port_vid <= higher_th)) { 569 /* Multicast forward entry */ 570 forward_entry.flags |= BCM_EXTENDER_FORWARD_MULTICAST; 571 if (soc_feature(unit, soc_feature_generic_dest)) { 572 dv = soc_mem_field32_dest_get(unit, L2Xm, l2x_entry, 573 PE_VID__DESTINATIONf, &dt); 574 l2mc_index = (dt == SOC_MEM_FIF_DEST_L2MC) ? dv : 0; 575 } else { 576 l2mc_index = soc_L2Xm_field32_get(unit, l2x_entry, 577 PE_VID__L2MC_PTRf); 578 } 579 _BCM_MULTICAST_GROUP_SET(forward_entry.dest_multicast, 580 _BCM_MULTICAST_TYPE_L2, l2mc_index); 581 } else { 582 if (soc_feature(unit, soc_feature_generic_dest)) { 583 dv = soc_mem_field32_dest_get(unit, L2Xm, l2x_entry, 584 PE_VID__DESTINATIONf, &dt); 585 if (dt == SOC_MEM_FIF_DEST_LAG) { 586 dest.tgid = dv; 587 dest.gport_type = _SHR_GPORT_TYPE_TRUNK; 588 } else { 589 dest.port = dv & SOC_MEM_FIF_DGPP_PORT_MASK; 590 dest.modid = (dv & SOC_MEM_FIF_DGPP_MOD_ID_MASK) >> 591 SOC_MEM_FIF_DGPP_MOD_ID_SHIFT_BITS; 592 dest.gport_type = _SHR_GPORT_TYPE_MODPORT; 593 } 594 } else { 595 if (soc_L2Xm_field32_get(unit, l2x_entry, 596 PE_VID__DEST_TYPEf)) { 597 dest.tgid = soc_L2Xm_field32_get(unit, l2x_entry, 598 PE_VID__TGIDf); 599 dest.gport_type = _SHR_GPORT_TYPE_TRUNK; 600 } else { 601 dest.modid = soc_L2Xm_field32_get(unit, l2x_entry, 602 PE_VID__MODULE_IDf); 603 dest.port = soc_L2Xm_field32_get(unit, l2x_entry, 604 PE_VID__PORT_NUMf); 605 dest.gport_type = _SHR_GPORT_TYPE_MODPORT; 606 } 607 } 608 rv = _bcm_esw_gport_construct(unit, &dest, 609 &(forward_entry.dest_port)); 610 if (BCM_FAILURE(rv)) { 611 break; 612 } 613 } 614 615 if (SOC_MEM_FIELD_VALID(unit, L2Xm, PE_VID__DST_CPUf)) { 616 if (soc_L2Xm_field32_get(unit, l2x_entry, 617 PE_VID__DST_CPUf)) { 618 forward_entry.flags |= BCM_EXTENDER_FORWARD_COPY_TO_CPU; 619 } 620 } else if (SOC_MEM_FIELD_VALID(unit, L2Xm, PE_VID__CPUf)) { 621 if (soc_L2Xm_field32_get(unit, l2x_entry, 622 PE_VID__CPUf)) { 623 forward_entry.flags |= BCM_EXTENDER_FORWARD_COPY_TO_CPU; 624 } 625 } 626 627 rv = cb(unit, &forward_entry, user_data); 628 if (BCM_FAILURE(rv)) { 629 break; 630 } 631 } 632 if (BCM_FAILURE(rv)) { 633 break; 634 } 635 } 636 soc_cm_sfree(unit, l2_tbl_chunk); 637 638 return rv; 639 } 640 #endif 641 #endif /* BCM_TRIDENT2_SUPPORT || BCM_PE_SUPPORT && INCLUDE_L3 */