port.c (32001B)
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: port.c 8 * Purpose: Manages untagged priority setting for port 9 */ 10 11 #include <shared/bsl.h> 12 13 #include <assert.h> 14 15 #include <soc/mem.h> 16 #include <soc/debug.h> 17 #include <soc/drv.h> 18 #include <soc/memory.h> 19 #include <bcm/error.h> 20 21 #include <bcm_int/esw_dispatch.h> 22 #include <bcm_int/esw/port.h> 23 #include <bcm_int/esw/firebolt.h> 24 #include <bcm_int/esw/xgs3.h> 25 26 27 /* 28 * Function: 29 * bcm_port_untagged_priority_set 30 * Purpose: 31 * Set the 802.1P priority for untagged packets coming in on a 32 * port. This value will be written into the priority field of the 33 * tag that is added at the ingress. 34 * Parameters: 35 * unit - StrataSwitch Unit #. 36 * port - StrataSwitch port #. 37 * priority - Priority to be set in 802.1p priority tag, from 0 to 7. 38 * A negative priority leaves the ingress port priority as 39 * is, but disables it from overriding ARL-based priorities. 40 * (on those devices that support ARL-based priority). 41 * Returns: 42 * BCM_E_NONE 43 * BCM_E_XXX 44 */ 45 46 int 47 bcm_shadow_port_untagged_priority_set(int unit, bcm_port_t port, int priority) 48 { 49 port_tab_entry_t ptab_entry; /* Port table entry. */ 50 int rv = BCM_E_NONE; 51 52 if (priority > 7 || priority < 0) { 53 return BCM_E_PARAM; 54 } 55 56 BCM_IF_ERROR_RETURN(_bcm_esw_port_gport_validate(unit, port, &port)); 57 58 soc_mem_lock(unit, PORT_TABm); 59 60 rv = BCM_XGS3_MEM_READ(unit, PORT_TABm, port, &ptab_entry); 61 if (BCM_FAILURE(rv)) { 62 soc_mem_unlock(unit, PORT_TABm); 63 return (rv); 64 } 65 66 soc_mem_field32_set(unit, PORT_TABm, &ptab_entry, PORT_INT_PRIf, 67 priority); 68 rv = BCM_XGS3_MEM_WRITE(unit, PORT_TABm, port, &ptab_entry); 69 if (BCM_FAILURE(rv)) { 70 soc_mem_unlock(unit, PORT_TABm); 71 return (rv); 72 } 73 74 soc_mem_unlock(unit, PORT_TABm); 75 76 LOG_INFO(BSL_LS_BCM_PORT, 77 (BSL_META_U(unit, 78 "bcm_shadow_port_untagged_priority_set: u=%d p=%d pri=%d rv=%d\n"), 79 unit, port, priority, rv)); 80 81 return rv; 82 } 83 84 /* 85 * Function: 86 * bcm_port_untagged_priority_get 87 * Purpose: 88 * Returns priority being assigned to untagged receive packets 89 * Parameters: 90 * unit - StrataSwitch Unit #. 91 * port - StrataSwitch port #. 92 * priority - Pointer to an int in which priority value is returned. 93 * Returns: 94 * BCM_E_NONE 95 * BCM_E_XXX 96 */ 97 98 int 99 bcm_shadow_port_untagged_priority_get(int unit, bcm_port_t port, int *priority) 100 { 101 port_tab_entry_t ptab_entry; /* Port table entry. */ 102 int rv = BCM_E_NONE; 103 104 if (priority != NULL) { 105 soc_mem_lock(unit, PORT_TABm); 106 rv = BCM_XGS3_MEM_READ(unit, PORT_TABm, port, &ptab_entry); 107 if (BCM_FAILURE(rv)) { 108 soc_mem_unlock(unit, PORT_TABm); 109 return (rv); 110 } 111 soc_mem_unlock(unit, PORT_TABm); 112 113 *priority = soc_mem_field32_get(unit, PORT_TABm, &ptab_entry, PORT_INT_PRIf); 114 LOG_INFO(BSL_LS_BCM_PORT, 115 (BSL_META_U(unit, 116 "bcm_shadow_port_untagged_priority_get: u=%d p=%d pri=%d\n"), 117 unit, port, *priority)); 118 } 119 120 return BCM_E_NONE; 121 } 122 123 /* 124 * Function: 125 * _bcm_shadow_port_dscp_map_set 126 * Purpose: 127 * Internal implementation for bcm_port_dscp_map_set 128 * Parameters: 129 * unit - switch device 130 * port - switch port or -1 for global table 131 * srccp - src code point or -1 132 * mapcp - mapped code point or -1 133 * prio - priority value for mapped code point 134 * -1 to use port default untagged priority 135 * BCM_PRIO_RED can be or'ed into the priority 136 * BCM_PRIO_YELLOW can be or'ed into the priority 137 * Returns: 138 * BCM_E_XXX 139 */ 140 141 STATIC int 142 _bcm_shadow_port_dscp_map_set(int unit, bcm_port_t port, 143 int srccp, int mapcp, int prio) 144 { 145 int i, cng; 146 dscp_table_entry_t de; 147 int max_index; 148 int min_index; 149 150 #define DSCP_CODE_POINT_CNT 256 /* for IPV6 */ 151 #define DSCP_CODE_POINT_MAX (DSCP_CODE_POINT_CNT - 1) 152 153 if (mapcp < -1 || mapcp > DSCP_CODE_POINT_MAX) { 154 return BCM_E_PARAM; 155 } 156 157 158 if (srccp < -1 || srccp > DSCP_CODE_POINT_MAX) { 159 return BCM_E_PARAM; 160 } 161 /* Extract cng bits and check for valid priority. */ 162 163 cng = 0; /* Green */ 164 if (prio < 0) { 165 return BCM_E_PARAM; 166 } 167 if (prio & BCM_PRIO_RED) { 168 cng = 0x01; /* Red */ 169 prio &= ~BCM_PRIO_RED; 170 } else if (prio & BCM_PRIO_YELLOW) { 171 cng = 0x03; /* Yellow */ 172 prio &= ~BCM_PRIO_YELLOW; 173 } 174 if ((prio & ~BCM_PRIO_MASK) != 0) { 175 return BCM_E_PARAM; 176 } 177 if (srccp < 0 && mapcp < 0) { 178 /* No mapping */ 179 return BCM_E_NONE; 180 } else if (srccp < 0) { 181 /* fill all entries in DSCP_TABLEm with mapcp */ 182 sal_memset(&de, 0, sizeof(de)); 183 soc_DSCP_TABLEm_field32_set(unit, &de, PRIf, prio); 184 soc_DSCP_TABLEm_field32_set(unit, &de, CNGf, cng); 185 min_index = port * 512; 186 max_index = min_index + DSCP_CODE_POINT_MAX; 187 for (i = min_index; i < max_index; i++) { 188 SOC_IF_ERROR_RETURN 189 (WRITE_DSCP_TABLEm(unit, MEM_BLOCK_ALL, i, &de)); 190 } 191 } else { 192 sal_memset(&de, 0, sizeof(de)); 193 /* fill specific srccp entry/entries in DSCP_TABLEm with mapcp */ 194 soc_DSCP_TABLEm_field32_set(unit, &de, PRIf, prio); 195 soc_DSCP_TABLEm_field32_set(unit, &de, CNGf, cng); 196 /* The table storage is, 256 for IPv4 + 256 for IPv6 per port */ 197 if (srccp < 64) { 198 SOC_IF_ERROR_RETURN 199 (WRITE_DSCP_TABLEm(unit, MEM_BLOCK_ALL, 200 (port * 512) + (srccp << 2), &de)); /* IPV4 */ 201 } 202 SOC_IF_ERROR_RETURN 203 (WRITE_DSCP_TABLEm(unit, MEM_BLOCK_ALL, 204 (port * 512) + 256 + srccp, &de)); /* IPV6 */ 205 } 206 return BCM_E_NONE; 207 } 208 209 /* 210 * Function: 211 * bcm_port_dscp_map_set 212 * Purpose: 213 * Define a mapping for diffserv code points 214 * The mapping enable/disable is controlled by a seperate API 215 * bcm_port_dscp_map_enable_set/get 216 * Also Enable/Disable control for DSCP mapping for tunnels 217 * are available in the respective tunnel create APIs. 218 * Parameters: 219 * unit - switch device 220 * port - switch port or -1 to setup global mapping table. 221 * srccp - src code point or -1 222 * mapcp - mapped code point or -1 223 * prio - priority value for mapped code point 224 * -1 to use port default untagged priority 225 * BCM_PRIO_DROP_FIRST can be or'ed into the priority 226 * Returns: 227 * BCM_E_XXX 228 * Notes: 229 * On most xgs switches there are a limited set 230 * of mappings that are possible: 231 * srccp -1, mapcp -1: no mapping 232 * srccp -1, mapcp 0..63: map all packets 233 * srccp 0, mapcp 0..63: map packets with cp 0 234 * On Firebolt/Helix/Felix, there is no per port mapping table. 235 * Only a global mapping table is available. 236 */ 237 238 int 239 bcm_shadow_port_dscp_map_set(int unit, bcm_port_t port, int srccp, int mapcp, 240 int prio) 241 { 242 int rv = BCM_E_NONE; 243 244 if (port != -1) { 245 BCM_IF_ERROR_RETURN(_bcm_esw_port_gport_validate(unit, port, &port)); 246 } 247 248 soc_mem_lock(unit, PORT_TABm); 249 250 if (port < 0) { 251 for (port = 0; port <= 16; port++) { /* for all ports */ 252 rv = _bcm_shadow_port_dscp_map_set(unit, port, srccp, mapcp, prio); 253 if (BCM_FAILURE(rv)) { 254 soc_mem_unlock(unit, PORT_TABm); 255 return rv; 256 } 257 } 258 } else { 259 if ((port >= 1) && (port <= 16)) { /*Specific port */ 260 rv = _bcm_shadow_port_dscp_map_set(unit, port, srccp, mapcp, prio); 261 } else { 262 rv = BCM_E_PORT; 263 } 264 } 265 soc_mem_unlock(unit, PORT_TABm); 266 267 return rv; 268 } 269 270 /* 271 * Function: 272 * _bcm_shadow_port_dscp_map_get 273 * Purpose: 274 * Get a mapping for diffserv code points 275 * Parameters: 276 * unit - switch device 277 * port - switch port 278 * srccp - src code point or -1 279 * mapcp - (OUT) pointer to returned mapped code point 280 * prio - (OUT) Priority value for mapped code point or -1 281 * May have BCM_PRIO_DROP_FIRST or'ed into it 282 * Returns: 283 * BCM_E_XXX 284 */ 285 286 STATIC int 287 _bcm_shadow_port_dscp_map_get(int unit, bcm_port_t port, int srccp, int *mapcp, 288 int *prio) 289 { 290 int base; 291 dscp_table_entry_t de; 292 293 if (srccp < -1 || srccp > DSCP_CODE_POINT_MAX || 294 mapcp == NULL || prio == NULL) { 295 return BCM_E_PARAM; 296 } 297 298 /* look up in DSCP_TABLEm */ 299 if (srccp < 0) { 300 srccp = 0; 301 } 302 base = (port * 512) + 256; /* Always retrive IPV6 settings */ 303 /* IPv4 and IPv6 are both set to same value */ 304 SOC_IF_ERROR_RETURN 305 (READ_DSCP_TABLEm(unit, MEM_BLOCK_ANY, base + srccp, &de)); 306 *prio = soc_DSCP_TABLEm_field32_get(unit, &de, PRIf); 307 if (soc_DSCP_TABLEm_field32_get(unit, &de, CNGf)) { 308 309 *prio |= BCM_PRIO_DROP_FIRST; 310 } 311 return BCM_E_NONE; 312 313 } 314 315 /* 316 * Function: 317 * bcm_port_dscp_map_get 318 * Purpose: 319 * Get a mapping for diffserv code points 320 * Parameters: 321 * unit - switch device 322 * port - switch port 323 * srccp - src code point or -1 324 * mapcp - (OUT) pointer to returned mapped code point 325 * prio - (OUT) Priority value for mapped code point or -1 326 * May have BCM_PRIO_DROP_FIRST or'ed into it 327 * Returns: 328 * BCM_E_XXX 329 */ 330 331 int 332 bcm_shadow_port_dscp_map_get(int unit, bcm_port_t port, int srccp, int *mapcp, 333 int *prio) 334 { 335 int rv; 336 337 if (port != -1) { 338 BCM_IF_ERROR_RETURN(_bcm_esw_port_gport_validate(unit, port, &port)); 339 } 340 341 soc_mem_lock(unit, PORT_TABm); 342 343 /* Get device port configuration. */ 344 if ((port >= 1) && (port <=16)) { 345 rv = _bcm_shadow_port_dscp_map_get(unit, port, srccp, mapcp, prio); 346 } else { 347 rv = BCM_E_PORT; 348 } 349 350 soc_mem_unlock(unit, PORT_TABm); 351 return rv; 352 } 353 354 355 /* 356 * Function: 357 * bcm_shadow_port_vlan_priority_map_set 358 * Description: 359 * Define the mapping of incomming port, packet priority, and cfi bit to 360 * switch internal priority and color. 361 * Parameters: 362 * unit - (IN) Device number 363 * port - (IN) Port number 364 * pkt_pri - (IN) Packet priority 365 * cfi - (IN) Packet CFI 366 * internal_pri - (IN) Internal priority 367 * color - (IN) color 368 * Return Value: 369 * BCM_E_XXX 370 * Note: 371 * This API programs only the mapping table. 372 */ 373 int 374 bcm_shadow_port_vlan_priority_map_set(int unit, bcm_port_t port, int pkt_pri, 375 int cfi, int internal_pri, bcm_color_t color) 376 { 377 int index; 378 ing_pri_cng_map_entry_t pri_map; 379 380 BCM_IF_ERROR_RETURN(_bcm_esw_port_gport_validate(unit, port, &port)); 381 if (pkt_pri < 0 || pkt_pri > 7 || cfi < 0 || cfi > 1 || internal_pri < 0 || 382 internal_pri >= 383 (1 << soc_mem_field_length(unit, ING_PRI_CNG_MAPm, PRIf))) { 384 return BCM_E_PARAM; 385 } 386 387 /* ING_PRI_CNG_MAP table is indexed with 388 * port[0:4] incoming priority[2:0] incoming CFI[0] 389 */ 390 index = (port << 4) | (pkt_pri << 1) | cfi; 391 392 memset(&pri_map, 0, sizeof(pri_map)); 393 soc_mem_field32_set(unit, ING_PRI_CNG_MAPm, &pri_map, PRIf, 394 internal_pri); 395 soc_mem_field32_set(unit, ING_PRI_CNG_MAPm, &pri_map, CNGf, 396 _BCM_COLOR_ENCODING(unit, color)); 397 SOC_IF_ERROR_RETURN 398 (WRITE_ING_PRI_CNG_MAPm(unit, MEM_BLOCK_ALL, index, &pri_map)); 399 return BCM_E_NONE; 400 } 401 402 /* 403 * Function: 404 * bcm_shadow_port_vlan_priority_map_get 405 * Description: 406 * Get the mapping of incomming port, packet priority, and cfi bit to 407 * switch internal priority and color. 408 * Parameters: 409 * unit - (IN) Device number 410 * port - (IN) Port number 411 * pkt_pri - (IN) Packet priority 412 * cfi - (IN) Packet CFI 413 * internal_pri - (OUT) Internal priority 414 * color - (OUT) color 415 * Return Value: 416 * BCM_E_XXX 417 * Note: 418 * This API programs only the mapping table. 419 */ 420 int 421 bcm_shadow_port_vlan_priority_map_get(int unit, bcm_port_t port, int pkt_pri, 422 int cfi, int *internal_pri, 423 bcm_color_t *color) 424 { 425 426 int index, hw_color; 427 ing_pri_cng_map_entry_t pri_map; 428 429 /* Input parameters check. */ 430 if ((NULL == internal_pri) || (NULL == color)) { 431 return (BCM_E_PARAM); 432 } 433 434 BCM_IF_ERROR_RETURN(_bcm_esw_port_gport_validate(unit, port, &port)); 435 436 if (pkt_pri < 0 || pkt_pri > 7 || cfi < 0 || cfi > 1) { 437 return BCM_E_PARAM; 438 } 439 440 /* ING_PRI_CNG_MAP table is indexed with 441 * port[4:0] incoming priority[2:0] incoming CFI[0] 442 */ 443 index = (port << 4) | (pkt_pri << 1) | cfi; 444 LOG_INFO(BSL_LS_BCM_PORT, 445 (BSL_META_U(unit, 446 "bcm_shadow_port_vlan_priority_map_get: u=%d p=%d index=%d\n"), 447 unit, port, index)); 448 449 SOC_IF_ERROR_RETURN 450 (READ_ING_PRI_CNG_MAPm(unit, MEM_BLOCK_ANY, index, &pri_map)); 451 *internal_pri = soc_mem_field32_get(unit, ING_PRI_CNG_MAPm, &pri_map, 452 PRIf); 453 hw_color = soc_mem_field32_get(unit, ING_PRI_CNG_MAPm, &pri_map, CNGf); 454 *color = _BCM_COLOR_DECODING(unit, hw_color); 455 return BCM_E_NONE; 456 } 457 458 /* 459 * Function: 460 * bcm_shadow_port_management_packet_config_set 461 * Description: 462 * Set Management packet classification for Ethertype and/or Dest MAC 463 * Parameters: 464 * unit - (IN) Device number 465 * port - (IN) Port number 466 * config - (IN) Pointer to bcm_port_management_packet_config_t 467 * Return Value: 468 * BCM_E_XXX 469 * Note: 470 * This API programs MGMT_FRAME_CTRL register 471 */ 472 int 473 bcm_shadow_port_management_packet_config_set(int unit, bcm_port_t port, 474 bcm_port_management_packet_config_t *config) 475 { 476 int rv = BCM_E_NONE; 477 bcm_mac_t dest_mac; 478 soc_reg_t reg[5] = {CTRL_DA1r, CTRL_DA2r, CTRL_DA3r, CTRL_DA4r, 479 CTRL_DA5r}; 480 soc_field_t field[5] = {CTRL_DA1f, CTRL_DA2f, CTRL_DA3f, CTRL_DA4f, 481 CTRL_DA5f}; 482 uint64 mac_field; 483 bcm_ethertype_t etype; 484 uint32 val; 485 uint64 val64; 486 int enable, i, p, empty = 0; 487 488 if (config == NULL) { 489 return BCM_E_PARAM; 490 } 491 if (port < 0 || port > 16) { 492 return BCM_E_PARAM; 493 } 494 soc_mem_lock(unit, PORT_TABm); 495 if ((config->flags & 496 (BCM_PORT_MANAGEMENT_PACKET_DEST_MAC | 497 BCM_PORT_MANAGEMENT_PACKET_ETHERTYPE)) == 498 (BCM_PORT_MANAGEMENT_PACKET_DEST_MAC | 499 BCM_PORT_MANAGEMENT_PACKET_ETHERTYPE)) { 500 if (config->flags & BCM_PORT_MANAGEMENT_PACKET_CLEAR) { 501 /* Clear the config */ 502 rv = READ_CTRL_ETHERTYPE2r(unit, &val); 503 etype = soc_reg_field_get(unit, CTRL_ETHERTYPE2r, val, 504 ETHERTYPEf); 505 if (BCM_SUCCESS(rv)) { 506 rv = soc_reg_get(unit, CTRL_DA6r, port, 0, &mac_field); 507 SAL_MAC_ADDR_FROM_UINT64(dest_mac, mac_field); 508 if (BCM_SUCCESS(rv)) { 509 if ((ENET_CMP_MACADDR(dest_mac, config->dest_mac) == 0) && 510 (etype == config->ethertype)) { 511 rv = (soc_reg_field32_modify(unit, MGMT_FRAME_ENABLEr, port, 512 CTRL_ETHERTYPE2f, 0)); 513 rv = (soc_reg_field32_modify(unit, MGMT_FRAME_ENABLEr, port, 514 CTRL_DA6f, 0)); 515 for (i = 0; i <= 16; i++) { 516 /* check if any other ports are still using ethtype */ 517 rv = READ_MGMT_FRAME_ENABLEr(unit, i, &val); 518 if (BCM_SUCCESS(rv)) { 519 enable = soc_reg_field_get(unit, MGMT_FRAME_ENABLEr, val, CTRL_ETHERTYPE2f); 520 if (enable) { 521 break; 522 } 523 } 524 } 525 if (BCM_SUCCESS(rv) && i >= 16) { /* No ports using ethertype, clear it */ 526 rv = soc_reg_field32_modify(unit, CTRL_ETHERTYPE2r, port, 527 ETHERTYPEf, 0); 528 COMPILER_64_ZERO(val64); 529 rv = soc_reg_set(unit, CTRL_DA6r, port, 0, val64); 530 } 531 } else { 532 rv = BCM_E_NOT_FOUND; 533 } 534 } 535 } 536 } else { 537 rv = READ_CTRL_ETHERTYPE2r(unit, &val); 538 etype = soc_reg_field_get(unit, CTRL_ETHERTYPE2r, val, 539 ETHERTYPEf); 540 if (BCM_SUCCESS(rv)) { 541 rv = soc_reg_get(unit, CTRL_DA6r, port, 0, &mac_field); 542 SAL_MAC_ADDR_FROM_UINT64(dest_mac, mac_field); 543 if (BCM_SUCCESS(rv)) { 544 if ((ENET_CMP_MACADDR(dest_mac, config->dest_mac) == 0) && 545 (etype == config->ethertype)) { 546 rv = (soc_reg_field32_modify(unit, MGMT_FRAME_ENABLEr, port, 547 CTRL_ETHERTYPE2f, 1)); 548 rv = (soc_reg_field32_modify(unit, MGMT_FRAME_ENABLEr, port, 549 CTRL_DA6f, 1)); 550 } else if ((etype == 0) && COMPILER_64_IS_ZERO(mac_field)) { 551 rv = (soc_reg_field32_modify(unit, CTRL_ETHERTYPE2r, port, 552 ETHERTYPEf, config->ethertype)); 553 SAL_MAC_ADDR_TO_UINT64(config->dest_mac, mac_field); 554 rv = soc_reg_set(unit, CTRL_DA6r, port, 0, mac_field); 555 556 rv = (soc_reg_field32_modify(unit, MGMT_FRAME_ENABLEr, port, 557 CTRL_ETHERTYPE2f, 1)); 558 rv = (soc_reg_field32_modify(unit, MGMT_FRAME_ENABLEr, port, 559 CTRL_DA6f, 1)); 560 } else { 561 rv = BCM_E_RESOURCE; 562 } 563 } 564 } 565 } 566 } else if ((config->flags & BCM_PORT_MANAGEMENT_PACKET_ETHERTYPE) == 567 BCM_PORT_MANAGEMENT_PACKET_ETHERTYPE) { 568 if (config->flags & BCM_PORT_MANAGEMENT_PACKET_CLEAR) { 569 /* Clear the config */ 570 rv = READ_CTRL_ETHERTYPE1r(unit, &val); 571 etype = soc_reg_field_get(unit, CTRL_ETHERTYPE1r, val, 572 ETHERTYPEf); 573 if (BCM_SUCCESS(rv)) { 574 if (etype == config->ethertype) { 575 rv = soc_reg_field32_modify(unit, MGMT_FRAME_ENABLEr, port, 576 CTRL_ETHERTYPE1f, 0); 577 for (i = 0; i <= 16; i++) { 578 /* check if any other ports are still using ethtype */ 579 rv = READ_MGMT_FRAME_ENABLEr(unit, i, &val); 580 if (BCM_SUCCESS(rv)) { 581 enable = soc_reg_field_get(unit, MGMT_FRAME_ENABLEr, val, CTRL_ETHERTYPE1f); 582 if (enable) { 583 break; 584 } 585 } 586 } 587 if (BCM_SUCCESS(rv) && i >= 16) { /* No ports using ethertype, clear it */ 588 rv = soc_reg_field32_modify(unit, CTRL_ETHERTYPE1r, port, 589 ETHERTYPEf, 0); 590 } 591 } else { 592 rv = BCM_E_NOT_FOUND; 593 } 594 } 595 } else { 596 /* Only Ether type is valid */ 597 rv = READ_MGMT_FRAME_ENABLEr(unit, port, &val); 598 if (BCM_SUCCESS(rv)) { 599 enable = soc_reg_field_get(unit, MGMT_FRAME_ENABLEr, val, CTRL_ETHERTYPE1f); 600 rv = READ_CTRL_ETHERTYPE1r(unit, &val); 601 etype = soc_reg_field_get(unit, CTRL_ETHERTYPE1r, val, ETHERTYPEf); 602 if (BCM_SUCCESS(rv)) { 603 if ((etype == config->ethertype)) { 604 /* Other ports have already added the ether type */ 605 rv = soc_reg_field32_modify(unit, MGMT_FRAME_ENABLEr, port, 606 CTRL_ETHERTYPE1f, 1); 607 } else if ((etype == 0x0)) { 608 BCM_IF_ERROR_RETURN 609 (soc_reg_field32_modify(unit, CTRL_ETHERTYPE1r, port, 610 ETHERTYPEf, config->ethertype)); 611 BCM_IF_ERROR_RETURN 612 (soc_reg_field32_modify(unit, MGMT_FRAME_ENABLEr, port, 613 CTRL_ETHERTYPE1f, 1)); 614 } else { 615 rv = BCM_E_RESOURCE; 616 } 617 } 618 } 619 } 620 } else if ((config->flags & BCM_PORT_MANAGEMENT_PACKET_DEST_MAC) == 621 BCM_PORT_MANAGEMENT_PACKET_DEST_MAC) { 622 /* check if the DA is CDP multicast */ 623 bcm_mac_t neigh_disc_da = {0x33, 0x33, 0x00, 0x00, 0x00, 0x00}; 624 bcm_mac_t cdp_da = {0x01, 0x00, 0x0C, 0xCC, 0xCC, 0xCC}; 625 bcm_mac_t sstp_da = {0x01, 0x00, 0x0C, 0xCC, 0xCC, 0xCD}; 626 if (config->flags & BCM_PORT_MANAGEMENT_PACKET_CLEAR) { 627 628 if (ENET_CMP_MACADDR(cdp_da, config->dest_mac) == 0) { 629 /* Clear the MGMT Frame classification */ 630 rv = soc_reg_field32_modify(unit, MGMT_FRAME_ENABLEr, port, 631 C_MC_DMAC_Af, 0); 632 } else if (ENET_CMP_MACADDR(sstp_da, config->dest_mac) == 0) { 633 /* Clear the MGMT Frame classification */ 634 rv = soc_reg_field32_modify(unit, MGMT_FRAME_ENABLEr, port, 635 C_MC_DMAC_Bf, 0); 636 } else if (ENET_CMP_MACADDR(neigh_disc_da, config->dest_mac) == 0) { 637 /* Clear the MGMT Frame classification */ 638 rv = soc_reg_field32_modify(unit, MGMT_FRAME_ENABLEr, port, 639 NEIGHBOR_DISCf, 0); 640 } else { 641 /* Clear the config */ 642 for (i = 0; i < 5; i++) { 643 rv = soc_reg_get(unit, reg[i], port, 0, &mac_field); 644 SAL_MAC_ADDR_FROM_UINT64(dest_mac, mac_field); 645 if (BCM_SUCCESS(rv) && (ENET_CMP_MACADDR(dest_mac, 646 config->dest_mac) == 0)) { 647 rv = soc_reg_field32_modify(unit, MGMT_FRAME_ENABLEr, port, 648 field[i], 0); 649 for (p = 0; p <= 16; p++) { 650 /* check if any other ports are still using ethtype */ 651 rv = READ_MGMT_FRAME_ENABLEr(unit, p, &val); 652 if (BCM_SUCCESS(rv)) { 653 enable = soc_reg_field_get(unit, MGMT_FRAME_ENABLEr, val, field[i]); 654 if (enable) { 655 break; 656 } 657 } 658 } 659 if (BCM_SUCCESS(rv) && i >= 16) { /* No ports using dest-da, clear it */ 660 COMPILER_64_ZERO(val64); 661 rv = soc_reg_set(unit, reg[i], port, 0, val64); 662 } 663 break; 664 } 665 } 666 if (i >= 5) { 667 rv = BCM_E_NOT_FOUND; 668 } 669 } 670 } else { 671 if (ENET_CMP_MACADDR(cdp_da, config->dest_mac) == 0) { 672 /* Clear the MGMT Frame classification */ 673 rv = soc_reg_field32_modify(unit, MGMT_FRAME_ENABLEr, port, 674 C_MC_DMAC_Af, 1); 675 } else if (ENET_CMP_MACADDR(sstp_da, config->dest_mac) == 0) { 676 /* Clear the MGMT Frame classification */ 677 rv = soc_reg_field32_modify(unit, MGMT_FRAME_ENABLEr, port, 678 C_MC_DMAC_Bf, 1); 679 } else if (ENET_CMP_MACADDR(neigh_disc_da, config->dest_mac) == 0) { 680 /* Clear the MGMT Frame classification */ 681 rv = soc_reg_field32_modify(unit, MGMT_FRAME_ENABLEr, port, 682 NEIGHBOR_DISCf, 1); 683 } else { 684 empty = -1; 685 for (i = 0; i < 5; i++) { /* find a matching Dest-DA */ 686 rv = soc_reg_get(unit, reg[i], port, 0, &mac_field); 687 SAL_MAC_ADDR_FROM_UINT64(dest_mac, mac_field); 688 if (BCM_SUCCESS(rv) && (ENET_CMP_MACADDR(dest_mac, config->dest_mac) == 0)) { 689 rv = soc_reg_field32_modify(unit, MGMT_FRAME_ENABLEr, port, 690 field[i], 1); 691 break; 692 } 693 if (BCM_SUCCESS(rv) && COMPILER_64_IS_ZERO(mac_field)) { 694 empty = i; /* found an empty slot */ 695 } 696 } 697 698 if (i >= 5 && empty != -1) { /* no match found, but found an empty slot */ 699 SAL_MAC_ADDR_TO_UINT64(config->dest_mac, mac_field); 700 rv = soc_reg64_set(unit, reg[empty], port, 0, mac_field); 701 if (BCM_SUCCESS(rv)) { 702 rv = soc_reg_field32_modify(unit, MGMT_FRAME_ENABLEr, port, 703 field[empty], 1); 704 } 705 } else if (i >= 5 && empty == -1) { /* no empty slot found */ 706 rv = BCM_E_RESOURCE; 707 } 708 } 709 } 710 } else { 711 rv = BCM_E_PARAM; 712 } 713 soc_mem_unlock(unit, PORT_TABm); 714 715 return rv; 716 } 717 718 /* 719 * Function: 720 * bcm_shadow_port_management_packet_config_get 721 * Description: 722 * Get Management packet classification for Ethertype and/or Dest MAC 723 * Parameters: 724 * unit - (IN) Device number 725 * port - (IN) Port number 726 * config_array - (OUT) Pointer to bcm_port_management_packet_config_t 727 * max_config - (IN) Max number of Management Packet classifications requested 728 * config_count - (OUT) Actual number of Management Packet classifcations 729 * Return Value: 730 * BCM_E_XXX 731 * Note: 732 */ 733 int 734 bcm_shadow_port_management_packet_config_get(int unit, bcm_port_t port, 735 bcm_port_management_packet_config_t *config, 736 int max_config, int *config_count) 737 738 { 739 int rv = BCM_E_NONE; 740 bcm_mac_t dest_mac; 741 soc_reg_t reg[5] = {CTRL_DA1r, CTRL_DA2r, CTRL_DA3r, CTRL_DA4r, 742 CTRL_DA5r}; 743 soc_field_t field[5] = {CTRL_DA1f, CTRL_DA2f, CTRL_DA3f, CTRL_DA4f, 744 CTRL_DA5f}; 745 uint64 mac_field; 746 bcm_ethertype_t etype; 747 uint32 val; 748 int enable, i = 0, cnt = 0; 749 bcm_mac_t neigh_disc_da = {0x33, 0x33, 0x00, 0x00, 0x00, 0x00}; 750 bcm_mac_t cdp_da = {0x01, 0x00, 0x0C, 0xCC, 0xCC, 0xCC}; 751 bcm_mac_t sstp_da = {0x01, 0x00, 0x0C, 0xCC, 0xCC, 0xCD}; 752 753 if ((config == NULL) || (max_config == 0)) { 754 return BCM_E_PARAM; 755 } 756 if (port < 0 || port > 16) { 757 return BCM_E_PARAM; 758 } 759 *config_count = 0; 760 soc_mem_lock(unit, PORT_TABm); 761 rv = READ_MGMT_FRAME_ENABLEr(unit, port, &val); 762 if (BCM_SUCCESS(rv)) { 763 enable = soc_reg_field_get(unit, MGMT_FRAME_ENABLEr, val, CTRL_ETHERTYPE1f); 764 if (enable) { 765 rv = READ_CTRL_ETHERTYPE1r(unit, &val); 766 etype = soc_reg_field_get(unit, CTRL_ETHERTYPE1r, val, 767 ETHERTYPEf); 768 config[cnt].ethertype = etype; 769 config[cnt].flags = BCM_PORT_MANAGEMENT_PACKET_ETHERTYPE; 770 cnt++; 771 if (cnt >= max_config) { 772 soc_mem_unlock(unit, PORT_TABm); 773 *config_count = cnt; 774 return BCM_E_NONE; 775 } 776 } 777 enable = soc_reg_field_get(unit, MGMT_FRAME_ENABLEr, val, CTRL_ETHERTYPE2f); 778 if (enable) { 779 rv = READ_CTRL_ETHERTYPE2r(unit, &val); 780 etype = soc_reg_field_get(unit, CTRL_ETHERTYPE2r, val, 781 ETHERTYPEf); 782 config[cnt].ethertype = etype; 783 config[cnt].flags = BCM_PORT_MANAGEMENT_PACKET_ETHERTYPE; 784 785 rv = soc_reg_get(unit, CTRL_DA6r, port, 0, &mac_field); 786 SAL_MAC_ADDR_FROM_UINT64(dest_mac, mac_field); 787 ENET_SET_MACADDR(config[cnt].dest_mac, dest_mac); 788 config[cnt].flags = BCM_PORT_MANAGEMENT_PACKET_ETHERTYPE | 789 BCM_PORT_MANAGEMENT_PACKET_DEST_MAC; 790 cnt++; 791 if (cnt >= max_config) { 792 soc_mem_unlock(unit, PORT_TABm); 793 *config_count = cnt; 794 return BCM_E_NONE; 795 } 796 } 797 enable = soc_reg_field_get(unit, MGMT_FRAME_ENABLEr, val, NEIGHBOR_DISCf); 798 if (enable) { 799 ENET_SET_MACADDR(config[cnt].dest_mac, neigh_disc_da); 800 config[cnt].flags = BCM_PORT_MANAGEMENT_PACKET_DEST_MAC; 801 cnt++; 802 if (cnt >= max_config) { 803 soc_mem_unlock(unit, PORT_TABm); 804 *config_count = cnt; 805 return BCM_E_NONE; 806 } 807 } 808 enable = soc_reg_field_get(unit, MGMT_FRAME_ENABLEr, val, C_MC_DMAC_Af); 809 if (enable) { 810 ENET_SET_MACADDR(config[cnt].dest_mac, cdp_da); 811 config[cnt].flags = BCM_PORT_MANAGEMENT_PACKET_DEST_MAC; 812 cnt++; 813 if (cnt >= max_config) { 814 soc_mem_unlock(unit, PORT_TABm); 815 *config_count = cnt; 816 return BCM_E_NONE; 817 } 818 } 819 enable = soc_reg_field_get(unit, MGMT_FRAME_ENABLEr, val, C_MC_DMAC_Bf); 820 if (enable) { 821 ENET_SET_MACADDR(config[cnt].dest_mac, sstp_da); 822 config[cnt].flags = BCM_PORT_MANAGEMENT_PACKET_DEST_MAC; 823 cnt++; 824 if (cnt >= max_config) { 825 soc_mem_unlock(unit, PORT_TABm); 826 *config_count = cnt; 827 return BCM_E_NONE; 828 } 829 } 830 831 for (i = 0; i < 5; i++) { 832 enable = soc_reg_field_get(unit, MGMT_FRAME_ENABLEr, val, field[i]); 833 if (enable) { 834 rv = soc_reg_get(unit, reg[i], port, 0, &mac_field); 835 SAL_MAC_ADDR_FROM_UINT64(dest_mac, mac_field); 836 ENET_SET_MACADDR(config[cnt].dest_mac, dest_mac); 837 config[cnt].flags = BCM_PORT_MANAGEMENT_PACKET_DEST_MAC; 838 cnt++; 839 if (cnt >= max_config) { 840 *config_count = cnt; 841 break; 842 } 843 } 844 } 845 } 846 soc_mem_unlock(unit, PORT_TABm); 847 return rv; 848 }