niv.c (18272B)
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: niv.c 8 * Purpose: Implements bcm_niv_forward_* APIs for Greyhound. 9 */ 10 11 #include <soc/defs.h> 12 #include <sal/core/libc.h> 13 14 #if defined(BCM_GREYHOUND_SUPPORT) && defined(INCLUDE_L3) 15 16 #include <soc/mem.h> 17 18 #include <bcm/error.h> 19 20 #include <bcm_int/common/multicast.h> 21 #include <bcm_int/esw/l2.h> 22 #include <bcm_int/esw/greyhound.h> 23 24 /* 25 * Purpose: 26 * Create NIV Forwarding table entry 27 * Parameters: 28 * unit - (IN) Device Number 29 * iv_fwd_entry - (IN) NIV Forwarding table entry 30 */ 31 int 32 bcm_gh_niv_forward_add(int unit, bcm_niv_forward_t *iv_fwd_entry) 33 { 34 int rv = BCM_E_NONE; 35 bcm_module_t mod_out; 36 bcm_port_t port_out; 37 bcm_trunk_t tgid_out; 38 int id_out; 39 l2x_entry_t l2x_entry; 40 41 if (iv_fwd_entry->name_space > 0xfff) { 42 return BCM_E_PARAM; 43 } 44 45 if (!(iv_fwd_entry->flags & BCM_NIV_FORWARD_MULTICAST)) { 46 if (iv_fwd_entry->virtual_interface_id > 0x3fff) { 47 return BCM_E_PARAM; 48 } 49 50 BCM_IF_ERROR_RETURN(_bcm_esw_gport_resolve(unit, 51 iv_fwd_entry->dest_port, 52 &mod_out, &port_out, &tgid_out, &id_out)); 53 if (-1 != id_out) { 54 return BCM_E_PARAM; 55 } 56 57 sal_memset(&l2x_entry, 0, sizeof(l2x_entry)); 58 soc_L2Xm_field32_set(unit, &l2x_entry, VALIDf, 1); 59 soc_L2Xm_field32_set(unit, &l2x_entry, KEY_TYPEf, 60 GH_L2_HASH_KEY_TYPE_VIF); /* VIF */ 61 soc_L2Xm_field32_set(unit, &l2x_entry, VIF__NAMESPACEf, 62 iv_fwd_entry->name_space); 63 soc_L2Xm_field32_set(unit, &l2x_entry, VIF__Pf, 0); 64 soc_L2Xm_field32_set(unit, &l2x_entry, VIF__DST_VIFf, 65 iv_fwd_entry->virtual_interface_id); 66 if (-1 != tgid_out) { 67 BCM_IF_ERROR_RETURN(_bcm_trunk_id_validate(unit, tgid_out)); 68 soc_L2Xm_field32_set(unit, &l2x_entry, VIF__DEST_TYPEf, 1); 69 soc_L2Xm_field32_set(unit, &l2x_entry, VIF__TGIDf, tgid_out); 70 } else { 71 soc_L2Xm_field32_set(unit, &l2x_entry, VIF__MODULE_IDf, mod_out); 72 soc_L2Xm_field32_set(unit, &l2x_entry, VIF__PORT_NUMf, port_out); 73 } 74 soc_L2Xm_field32_set(unit, &l2x_entry, STATIC_BITf, 1); 75 76 } else { /* Multicast forward entry */ 77 if (iv_fwd_entry->virtual_interface_id > 0x3fff) { 78 return BCM_E_PARAM; 79 } 80 if (!_BCM_MULTICAST_IS_L2(iv_fwd_entry->dest_multicast)) { 81 return BCM_E_PARAM; 82 } 83 84 sal_memset(&l2x_entry, 0, sizeof(l2x_entry)); 85 soc_L2Xm_field32_set(unit, &l2x_entry, VALIDf, 1); 86 soc_L2Xm_field32_set(unit, &l2x_entry, KEY_TYPEf, 87 GH_L2_HASH_KEY_TYPE_VIF); /* VIF */ 88 soc_L2Xm_field32_set(unit, &l2x_entry, VIF__NAMESPACEf, 89 iv_fwd_entry->name_space); 90 soc_L2Xm_field32_set(unit, &l2x_entry, VIF__Pf, 1); 91 soc_L2Xm_field32_set(unit, &l2x_entry, VIF__DST_VIFf, 92 iv_fwd_entry->virtual_interface_id); 93 soc_L2Xm_field32_set(unit, &l2x_entry, VIF__L2MC_PTRf, 94 _BCM_MULTICAST_ID_GET(iv_fwd_entry->dest_multicast)); 95 soc_L2Xm_field32_set(unit, &l2x_entry, STATIC_BITf, 1); 96 } 97 98 soc_mem_lock(unit, L2Xm); 99 100 if (!(iv_fwd_entry->flags & BCM_NIV_FORWARD_REPLACE)) { 101 l2x_entry_t l2x_lookup; 102 int l2_index; 103 104 /* See if the entry already exists */ 105 rv = soc_mem_generic_lookup(unit, L2Xm, MEM_BLOCK_ANY, 0, &l2x_entry, 106 &l2x_lookup, &l2_index); 107 if (BCM_FAILURE(rv) && (rv != BCM_E_NOT_FOUND)) { 108 soc_mem_unlock(unit, L2Xm); 109 return rv; 110 } 111 if (BCM_SUCCESS(rv)) { 112 soc_mem_unlock(unit, L2Xm); 113 return BCM_E_EXISTS; 114 } 115 116 rv = soc_mem_insert(unit, L2Xm, MEM_BLOCK_ALL, &l2x_entry); 117 if (SOC_FAILURE(rv)) { 118 soc_mem_unlock(unit, L2Xm); 119 return rv; 120 } 121 } else { /* Replace existing entry */ 122 rv = soc_mem_delete(unit, L2Xm, MEM_BLOCK_ALL, &l2x_entry); 123 if (SOC_FAILURE(rv)) { 124 soc_mem_unlock(unit, L2Xm); 125 return rv; 126 } 127 rv = soc_mem_insert(unit, L2Xm, MEM_BLOCK_ALL, &l2x_entry); 128 if (SOC_FAILURE(rv)) { 129 soc_mem_unlock(unit, L2Xm); 130 return rv; 131 } 132 } 133 134 soc_mem_unlock(unit, L2Xm); 135 136 return rv; 137 } 138 139 /* 140 * Purpose: 141 * Delete NIV Forwarding table entry 142 * Parameters: 143 * unit - (IN) Device Number 144 * iv_fwd_entry - (IN) NIV Forwarding table entry 145 */ 146 int 147 bcm_gh_niv_forward_delete(int unit, bcm_niv_forward_t *iv_fwd_entry) 148 { 149 int rv = BCM_E_NONE; 150 l2x_entry_t l2x_entry; 151 152 if (iv_fwd_entry->name_space > 0xfff) { 153 return BCM_E_PARAM; 154 } 155 156 if (!(iv_fwd_entry->flags & BCM_NIV_FORWARD_MULTICAST)) { 157 if (iv_fwd_entry->virtual_interface_id > 0x3fff) { 158 return BCM_E_PARAM; 159 } 160 161 sal_memset(&l2x_entry, 0, sizeof(l2x_entry)); 162 soc_L2Xm_field32_set(unit, &l2x_entry, KEY_TYPEf, 163 GH_L2_HASH_KEY_TYPE_VIF); /* VIF */ 164 soc_L2Xm_field32_set(unit, &l2x_entry, VIF__NAMESPACEf, 165 iv_fwd_entry->name_space); 166 soc_L2Xm_field32_set(unit, &l2x_entry, VIF__Pf, 0); 167 soc_L2Xm_field32_set(unit, &l2x_entry, VIF__DST_VIFf, 168 iv_fwd_entry->virtual_interface_id); 169 170 } else { /* Multicast forward entry */ 171 if (iv_fwd_entry->virtual_interface_id > 0x3fff) { 172 return BCM_E_PARAM; 173 } 174 175 sal_memset(&l2x_entry, 0, sizeof(l2x_entry)); 176 soc_L2Xm_field32_set(unit, &l2x_entry, KEY_TYPEf, 177 GH_L2_HASH_KEY_TYPE_VIF); /* VIF */ 178 soc_L2Xm_field32_set(unit, &l2x_entry, VIF__NAMESPACEf, 179 iv_fwd_entry->name_space); 180 soc_L2Xm_field32_set(unit, &l2x_entry, VIF__Pf, 1); 181 soc_L2Xm_field32_set(unit, &l2x_entry, VIF__DST_VIFf, 182 iv_fwd_entry->virtual_interface_id); 183 } 184 185 soc_mem_lock(unit, L2Xm); 186 rv = soc_mem_delete(unit, L2Xm, MEM_BLOCK_ALL, &l2x_entry); 187 soc_mem_unlock(unit, L2Xm); 188 189 return rv; 190 } 191 192 int 193 _bcm_gh_niv_forward_delete_all(int unit, bcm_niv_forward_t *iv_fwd_entry, void *data) 194 { 195 BCM_IF_ERROR_RETURN(bcm_gh_niv_forward_delete(unit, iv_fwd_entry)); 196 197 return BCM_E_NONE; 198 } 199 200 /* 201 * Purpose: 202 * Delete all NIV Forwarding table entries 203 * Parameters: 204 * unit - Device Number 205 */ 206 int 207 bcm_gh_niv_forward_delete_all(int unit) 208 { 209 int rv = BCM_E_NONE; 210 #if 1 /* TBD */ 211 BCM_IF_ERROR_RETURN(bcm_gh_niv_forward_traverse(unit, 212 _bcm_gh_niv_forward_delete_all, NULL)); 213 214 #else 215 int seconds, enabled; 216 l2_entry_1_entry_t match_mask; 217 l2_entry_1_entry_t match_data; 218 l2_bulk_entry_t l2_bulk; 219 int match_mask_index, match_data_index; 220 uint32 rval; 221 int field_len; 222 223 SOC_IF_ERROR_RETURN 224 (SOC_FUNCTIONS(unit)->soc_age_timer_get(unit, &seconds, &enabled)); 225 if (enabled) { 226 SOC_IF_ERROR_RETURN(soc_tr3_l2_bulk_age_stop(unit)); 227 } 228 229 soc_mem_lock(unit, L2_ENTRY_1m); 230 231 /* Set match mask and data */ 232 sal_memset(&match_mask, 0, sizeof(match_mask)); 233 sal_memset(&match_data, 0, sizeof(match_data)); 234 235 soc_mem_field32_set(unit, L2_ENTRY_1m, &match_mask, VALIDf, 1); 236 soc_mem_field32_set(unit, L2_ENTRY_1m, &match_data, VALIDf, 1); 237 238 soc_mem_field32_set(unit, L2_ENTRY_1m, &match_mask, WIDEf, 1); 239 soc_mem_field32_set(unit, L2_ENTRY_1m, &match_data, WIDEf, 0); 240 241 field_len = soc_mem_field_length(unit, L2_ENTRY_1m, KEY_TYPEf); 242 soc_mem_field32_set(unit, L2_ENTRY_1m, &match_mask, KEY_TYPEf, 243 (1 << field_len) - 1); 244 soc_mem_field32_set(unit, L2_ENTRY_1m, &match_data, KEY_TYPEf, 245 SOC_MEM_KEY_L2_ENTRY_1_VIF_VIF); 246 247 sal_memset(&l2_bulk, 0, sizeof(l2_bulk)); 248 sal_memcpy(&l2_bulk, &match_mask, sizeof(match_mask)); 249 match_mask_index = 1; 250 rv = WRITE_L2_BULKm(unit, MEM_BLOCK_ALL, match_mask_index, &l2_bulk); 251 if (BCM_SUCCESS(rv)) { 252 sal_memset(&l2_bulk, 0, sizeof(l2_bulk)); 253 sal_memcpy(&l2_bulk, &match_data, sizeof(match_data)); 254 match_data_index = 0; 255 rv = WRITE_L2_BULKm(unit, MEM_BLOCK_ALL, match_data_index, &l2_bulk); 256 } 257 258 /* Set bulk control */ 259 rval = 0; 260 soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, L2_MOD_FIFO_RECORDf, 0); 261 soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, ACTIONf, 1); 262 soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, BURST_ENTRIESf, 263 _SOC_TR3_L2_BULK_BURST_MAX); 264 soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, ENTRY_WIDTHf, 0); 265 soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, NUM_ENTRIESf, 266 soc_mem_index_count(unit, L2_ENTRY_1m)); 267 soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, EXTERNAL_L2_ENTRYf, 0); 268 if (BCM_SUCCESS(rv)) { 269 rv = WRITE_L2_BULK_CONTROLr(unit, rval); 270 } 271 if (BCM_SUCCESS(rv)) { 272 rv = soc_tr3_l2_port_age(unit, L2_BULK_CONTROLr, INVALIDr); 273 } 274 275 soc_mem_unlock(unit, L2_ENTRY_1m); 276 277 if(enabled) { 278 SOC_IF_ERROR_RETURN(soc_tr3_l2_bulk_age_start(unit, seconds)); 279 } 280 #endif 281 return rv; 282 } 283 284 /* 285 * Purpose: 286 * Get NIV Forwarding table entry 287 * Parameters: 288 * unit - (IN) Device Number 289 * iv_fwd_entry - (IN/OUT) NIV forwarding table info 290 */ 291 int 292 bcm_gh_niv_forward_get(int unit, bcm_niv_forward_t *iv_fwd_entry) 293 { 294 int rv = BCM_E_NONE; 295 l2x_entry_t l2x_entry, l2x_entry_out; 296 int idx; 297 _bcm_gport_dest_t dest; 298 int l2mc_index; 299 300 if (iv_fwd_entry->name_space > 0xfff) { 301 return BCM_E_PARAM; 302 } 303 304 if (!(iv_fwd_entry->flags & BCM_NIV_FORWARD_MULTICAST)) { 305 if (iv_fwd_entry->virtual_interface_id > 0x3fff) { 306 return BCM_E_PARAM; 307 } 308 309 sal_memset(&l2x_entry, 0, sizeof(l2x_entry)); 310 soc_L2Xm_field32_set(unit, &l2x_entry, KEY_TYPEf, 311 GH_L2_HASH_KEY_TYPE_VIF); /* VIF */ 312 soc_L2Xm_field32_set(unit, &l2x_entry, VIF__NAMESPACEf, 313 iv_fwd_entry->name_space); 314 soc_L2Xm_field32_set(unit, &l2x_entry, VIF__Pf, 0); 315 soc_L2Xm_field32_set(unit, &l2x_entry, VIF__DST_VIFf, 316 iv_fwd_entry->virtual_interface_id); 317 318 } else { /* Multicast forward entry */ 319 if (iv_fwd_entry->virtual_interface_id > 0x3fff) { 320 return BCM_E_PARAM; 321 } 322 323 sal_memset(&l2x_entry, 0, sizeof(l2x_entry)); 324 soc_L2Xm_field32_set(unit, &l2x_entry, KEY_TYPEf, 325 GH_L2_HASH_KEY_TYPE_VIF); /* VIF */ 326 soc_L2Xm_field32_set(unit, &l2x_entry, VIF__NAMESPACEf, 327 iv_fwd_entry->name_space); 328 soc_L2Xm_field32_set(unit, &l2x_entry, VIF__Pf, 1); 329 soc_L2Xm_field32_set(unit, &l2x_entry, VIF__DST_VIFf, 330 iv_fwd_entry->virtual_interface_id); 331 } 332 333 soc_mem_lock(unit, L2Xm); 334 rv = soc_mem_search(unit, L2Xm, MEM_BLOCK_ALL, &idx, &l2x_entry, 335 &l2x_entry_out, 0); 336 soc_mem_unlock(unit, L2Xm); 337 338 if (SOC_SUCCESS(rv)) { 339 if (!(iv_fwd_entry->flags & BCM_NIV_FORWARD_MULTICAST)) { 340 if (soc_L2Xm_field32_get(unit, &l2x_entry_out, 341 VIF__DEST_TYPEf)) { 342 dest.tgid = soc_L2Xm_field32_get(unit, &l2x_entry_out, 343 VIF__TGIDf); 344 dest.gport_type = _SHR_GPORT_TYPE_TRUNK; 345 } else { 346 dest.modid = soc_L2Xm_field32_get(unit, &l2x_entry_out, 347 VIF__MODULE_IDf); 348 dest.port = soc_L2Xm_field32_get(unit, &l2x_entry_out, 349 VIF__PORT_NUMf); 350 dest.gport_type = _SHR_GPORT_TYPE_MODPORT; 351 } 352 BCM_IF_ERROR_RETURN(_bcm_esw_gport_construct(unit, &dest, 353 &(iv_fwd_entry->dest_port))); 354 } else { 355 l2mc_index = soc_L2Xm_field32_get(unit, &l2x_entry_out, 356 VIF__L2MC_PTRf); 357 _BCM_MULTICAST_GROUP_SET(iv_fwd_entry->dest_multicast, 358 _BCM_MULTICAST_TYPE_L2, l2mc_index); 359 } 360 } 361 362 return rv; 363 } 364 365 /* 366 * Purpose: 367 * Traverse all valid NIV forward entries and call the 368 * supplied callback routine. 369 * Parameters: 370 * unit - Device Number 371 * cb - User callback function, called once per NIV forward entry. 372 * user_data - cookie 373 * Returns: 374 * BCM_E_XXX 375 */ 376 int 377 bcm_gh_niv_forward_traverse(int unit, 378 bcm_niv_forward_traverse_cb cb, 379 void *user_data) 380 { 381 int rv = BCM_E_NONE; 382 int chunk_entries, chunk_bytes; 383 uint8 *l2_tbl_chunk = NULL; 384 int chunk_idx_min, chunk_idx_max, chunk_end; 385 int ent_idx, mem_idx_min, mem_idx_max; 386 l2x_entry_t *l2x_entry; 387 bcm_niv_forward_t iv_fwd_entry; 388 int l2mc_index; 389 _bcm_gport_dest_t dest; 390 391 chunk_entries = soc_property_get(unit, spn_L2DELETE_CHUNKS, 392 L2_MEM_CHUNKS_DEFAULT); 393 chunk_bytes = 4 * SOC_MEM_WORDS(unit, L2Xm) * chunk_entries; 394 l2_tbl_chunk = soc_cm_salloc(unit, chunk_bytes, "niv forward traverse"); 395 if (NULL == l2_tbl_chunk) { 396 return BCM_E_MEMORY; 397 } 398 399 mem_idx_min = soc_mem_index_min(unit, L2Xm); 400 mem_idx_max = soc_mem_index_max(unit, L2Xm); 401 for (chunk_idx_min = mem_idx_min; chunk_idx_min <= mem_idx_max; 402 chunk_idx_min += chunk_entries) { 403 sal_memset(l2_tbl_chunk, 0, chunk_bytes); 404 405 chunk_idx_max = chunk_idx_min + chunk_entries - 1; 406 if (chunk_idx_max > mem_idx_max) { 407 chunk_idx_max = mem_idx_max; 408 } 409 410 rv = soc_mem_read_range(unit, L2Xm, MEM_BLOCK_ANY, 411 chunk_idx_min, chunk_idx_max, l2_tbl_chunk); 412 if (SOC_FAILURE(rv)) { 413 break; 414 } 415 416 chunk_end = (chunk_idx_max - chunk_idx_min); 417 for (ent_idx = 0; ent_idx <= chunk_end; ent_idx++) { 418 l2x_entry = soc_mem_table_idx_to_pointer(unit, L2Xm, 419 l2x_entry_t *, l2_tbl_chunk, ent_idx); 420 421 if (soc_L2Xm_field32_get(unit, l2x_entry, VALIDf) == 0) { 422 continue; 423 } 424 425 if (soc_L2Xm_field32_get(unit, l2x_entry, KEY_TYPEf) != 426 GH_L2_HASH_KEY_TYPE_VIF) { 427 continue; 428 } 429 430 bcm_niv_forward_t_init(&iv_fwd_entry); 431 432 iv_fwd_entry.name_space = soc_L2Xm_field32_get(unit, 433 l2x_entry, VIF__NAMESPACEf); 434 iv_fwd_entry.virtual_interface_id = soc_L2Xm_field32_get(unit, 435 l2x_entry, VIF__DST_VIFf); 436 437 if (soc_L2Xm_field32_get(unit, l2x_entry, VIF__Pf)) { 438 /* Multicast NIV forward entry */ 439 iv_fwd_entry.flags |= BCM_NIV_FORWARD_MULTICAST; 440 l2mc_index = soc_L2Xm_field32_get(unit, l2x_entry, 441 VIF__L2MC_PTRf); 442 _BCM_MULTICAST_GROUP_SET(iv_fwd_entry.dest_multicast, 443 _BCM_MULTICAST_TYPE_L2, l2mc_index); 444 } else { 445 if (soc_L2Xm_field32_get(unit, l2x_entry, 446 VIF__DEST_TYPEf)) { 447 dest.tgid = soc_L2Xm_field32_get(unit, l2x_entry, 448 VIF__TGIDf); 449 dest.gport_type = _SHR_GPORT_TYPE_TRUNK; 450 } else { 451 dest.modid = soc_L2Xm_field32_get(unit, l2x_entry, 452 VIF__MODULE_IDf); 453 dest.port = soc_L2Xm_field32_get(unit, l2x_entry, 454 VIF__PORT_NUMf); 455 dest.gport_type = _SHR_GPORT_TYPE_MODPORT; 456 } 457 rv = _bcm_esw_gport_construct(unit, &dest, 458 &(iv_fwd_entry.dest_port)); 459 if (BCM_FAILURE(rv)) { 460 break; 461 } 462 } 463 464 rv = cb(unit, &iv_fwd_entry, user_data); 465 if (BCM_FAILURE(rv)) { 466 break; 467 } 468 } 469 if (BCM_FAILURE(rv)) { 470 break; 471 } 472 } 473 soc_cm_sfree(unit, l2_tbl_chunk); 474 475 return rv; 476 } 477 478 479 /* 480 * Function: 481 * bcm_gh_niv_ethertype_set 482 * Purpose: 483 * Set NIV Ethertype. 484 * Parameters: 485 * unit - (IN) BCM device number 486 * ethertype - (IN) NIV Ethertype 487 * Returns: 488 * BCM_E_XXX 489 */ 490 int 491 bcm_gh_niv_ethertype_set(int unit, int ethertype) 492 { 493 494 if (ethertype < 0 || ethertype > 0xffff) { 495 return BCM_E_PARAM; 496 } 497 498 BCM_IF_ERROR_RETURN 499 (soc_reg_field32_modify(unit, NIV_ETHERTYPEr, 500 REG_PORT_ANY, ETHERTYPEf, ethertype)); 501 BCM_IF_ERROR_RETURN 502 (soc_reg_field32_modify(unit, NIV_ETHERTYPEr, 503 REG_PORT_ANY, ENABLEf, ethertype ? 1 : 0)); 504 505 BCM_IF_ERROR_RETURN 506 (soc_reg_field32_modify(unit, EGR_NIV_ETHERTYPEr, 507 REG_PORT_ANY, ETHERTYPEf, ethertype)); 508 BCM_IF_ERROR_RETURN 509 (soc_reg_field32_modify(unit, EGR_NIV_ETHERTYPEr, 510 REG_PORT_ANY, ENABLEf, ethertype ? 1 : 0)); 511 512 BCM_IF_ERROR_RETURN 513 (soc_reg_field32_modify(unit, EGR_NIV_ETHERTYPE_2r, 514 REG_PORT_ANY, ETHERTYPEf, ethertype)); 515 BCM_IF_ERROR_RETURN 516 (soc_reg_field32_modify(unit, EGR_NIV_ETHERTYPE_2r, 517 REG_PORT_ANY, ENABLEf, ethertype ? 1 : 0)); 518 519 return BCM_E_NONE; 520 } 521 522 /* 523 * Function: 524 * bcm_gh_niv_ethertype_get 525 * Purpose: 526 * Get NIV Ethertype. 527 * Parameters: 528 * unit - (IN) BCM device number 529 * ethertype - (OUT) NIV Ethertype 530 * Returns: 531 * BCM_E_XXX 532 */ 533 int 534 bcm_gh_niv_ethertype_get(int unit, int *ethertype) 535 { 536 uint32 rval; 537 538 if (ethertype == NULL) { 539 return BCM_E_PARAM; 540 } 541 542 BCM_IF_ERROR_RETURN(READ_NIV_ETHERTYPEr(unit, &rval)); 543 if (soc_reg_field_get(unit, NIV_ETHERTYPEr, rval, ENABLEf)) { 544 *ethertype = soc_reg_field_get(unit, NIV_ETHERTYPEr, rval, ETHERTYPEf); 545 } else { 546 *ethertype = 0; 547 } 548 549 return BCM_E_NONE; 550 } 551 552 #endif /* BCM_GREYHOUND_SUPPORT && INCLUDE_L3 */