auth.c (41814B)
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 * 802.1X 8 */ 9 10 #include <sal/core/libc.h> 11 12 #include <soc/drv.h> 13 14 #include <bcm/error.h> 15 #include <bcm/auth.h> 16 17 #include <bcm_int/esw/field.h> /* _bcm_field_setup_post_ethertype_udf() */ 18 #include <bcm_int/esw/port.h> 19 20 #include <bcm_int/esw_dispatch.h> 21 #if defined(BCM_KATANA2_SUPPORT) 22 #include <bcm_int/esw/katana2.h> 23 #endif 24 25 #define AUTH_INIT(unit) \ 26 if (!SOC_UNIT_VALID(unit)) { return (BCM_E_UNIT); } \ 27 else if (!(soc_feature(unit, soc_feature_field))) { \ 28 return (BCM_E_UNAVAIL); \ 29 } \ 30 else if (NUM_E_PORT(unit) <= 0) { return (BCM_E_BADID); } \ 31 else if (auth_cntl[unit] == NULL) { return (BCM_E_INIT); } 32 #define AUTH_INIT_NO_PORT(unit) \ 33 if (!SOC_UNIT_VALID(unit)) { return (BCM_E_UNIT); } \ 34 else if (!(soc_feature(unit, soc_feature_field))) { \ 35 return (BCM_E_UNAVAIL); \ 36 } \ 37 else if (auth_cntl[unit] == NULL) { return (BCM_E_INIT); } 38 #define AUTH_PORT(unit, port) \ 39 if (!SOC_PORT_VALID(unit, port) || !IS_E_PORT(unit, port)) \ 40 { return (BCM_E_PORT); } 41 42 #define AUTH_MODE_MASK \ 43 (BCM_AUTH_MODE_UNCONTROLLED | BCM_AUTH_MODE_AUTH | BCM_AUTH_MODE_UNAUTH) 44 45 #define _AUTH_ETHERTYPE_EAPOL 0x888e 46 #define _AUTH_ETHERTYPE_MASK 0xffff 47 48 typedef struct auth_mac_s *auth_mac_p; 49 50 typedef struct auth_mac_s { 51 bcm_mac_t mac; 52 bcm_field_entry_t entry; 53 pbmp_t pbmp; 54 auth_mac_p next; 55 } auth_mac_t; 56 57 typedef struct bcm_auth_cntl_s { 58 int mode; 59 int etmp; 60 int mac_set; 61 auth_mac_t *macList; 62 } bcm_auth_cntl_t; 63 64 typedef struct auth_cb_cntl_s { 65 int registered; 66 bcm_auth_cb_t auth_cbs; 67 void *auth_cb_data; 68 } auth_cb_cntl_t; 69 70 typedef struct auth_field_s { 71 int inited; 72 int count; 73 bcm_field_group_t group0; 74 auth_mac_t *macList; 75 bcm_field_group_t group1; 76 bcm_field_entry_t entry1; 77 bcm_field_group_t group2; 78 bcm_field_entry_t entry2; 79 pbmp_t group2_pbmp; 80 } auth_field_cntl_t; 81 82 static bcm_auth_cntl_t *auth_cntl[BCM_MAX_NUM_UNITS]; 83 static auth_cb_cntl_t cb_cntl[BCM_MAX_NUM_UNITS]; 84 static auth_field_cntl_t fp_cntl[BCM_MAX_NUM_UNITS]; 85 86 /* Forward declarations */ 87 STATIC void _auth_linkscan_cb(int unit, bcm_port_t port, bcm_port_info_t *info); 88 STATIC int _auth_field_install(int unit, int port, bcm_mac_t mac); 89 STATIC int _auth_field_remove(int unit, int port, bcm_mac_t mac); 90 STATIC int _auth_field_install_all(int unit, int port); 91 STATIC int _auth_field_remove_all(int unit, int port); 92 #if defined(BCM_FIELD_SUPPORT) 93 STATIC int _auth_maclist_insert(auth_mac_t **list, bcm_mac_t mac, auth_mac_p *ins); 94 STATIC int _auth_maclist_lookup(auth_mac_t **list, bcm_mac_t mac, auth_mac_p *entry); 95 #endif /* !BCM_FIELD_SUPPORT */ 96 STATIC int _auth_maclist_remove(auth_mac_t **list, bcm_mac_t mac, auth_mac_p *del); 97 STATIC int _auth_maclist_destroy(auth_mac_t **list); 98 #ifdef AUTH_DEBUG 99 STATIC int _auth_maclist_dump(auth_mac_t **list); 100 #endif 101 102 /* 103 * Function: 104 * bcm_auth_init 105 * Purpose: 106 * Initialize auth module. 107 * Parameters: 108 * unit - Device number 109 * Returns: 110 * BCM_E_NONE - Success 111 * BCM_E_UNIT - Invalid unit number 112 * BCM_E_UNAVAIL - Insufficient hardware support 113 * BCM_E_MEMORY - Allocation failure 114 * 115 * Notes: 116 * All ports are marked as being in the uncontrolled state. 117 */ 118 119 int 120 bcm_esw_auth_init(int unit) 121 { 122 bcm_port_t port; 123 int rv = BCM_E_NONE, max_num_port = 0; 124 125 if (!SOC_UNIT_VALID(unit)) { 126 return BCM_E_UNIT; 127 } 128 129 if (!(soc_feature(unit, soc_feature_field))) { 130 return (BCM_E_UNAVAIL); 131 } 132 133 if (auth_cntl[unit] != NULL) { 134 rv = bcm_esw_auth_detach(unit); 135 BCM_IF_ERROR_RETURN(rv); 136 } 137 138 max_num_port = SOC_MAX_NUM_PORTS; 139 140 #ifdef BCM_KATANA2_SUPPORT 141 if (soc_feature(unit, soc_feature_linkphy_coe) || 142 soc_feature(unit, soc_feature_subtag_coe)) { 143 max_num_port = SOC_MAX_NUM_PP_PORTS; 144 } 145 #endif 146 147 auth_cntl[unit] = sal_alloc(max_num_port * 148 sizeof(bcm_auth_cntl_t), "auth_cntl"); 149 if (auth_cntl[unit] == NULL) { 150 return BCM_E_MEMORY; 151 } 152 sal_memset(auth_cntl[unit], 0, max_num_port * 153 sizeof(bcm_auth_cntl_t)); 154 155 for (port = 0; port < max_num_port; port++) { 156 auth_cntl[unit][port].mode = BCM_AUTH_MODE_UNCONTROLLED; 157 if (soc_feature(unit, soc_feature_field)) { 158 BCM_IF_ERROR_RETURN(_auth_field_remove_all(unit, port)); 159 } 160 } 161 rv = bcm_esw_linkscan_register(unit, _auth_linkscan_cb); 162 BCM_IF_ERROR_RETURN(rv); 163 cb_cntl[unit].registered = TRUE; 164 165 return BCM_E_NONE; 166 } 167 168 /* 169 * Function: 170 * bcm_auth_detach 171 * Purpose: 172 * Stop all auth module processing and deallocate resources. 173 * Parameters: 174 * unit - Device number 175 * Returns: 176 * BCM_E_NONE - Success 177 * BCM_E_UNIT - Invalid unit number 178 * BCM_E_UNAVAIL - Insufficient hardware support 179 * Notes: 180 * All ports are moved to the uncontrolled state. All internal 181 * callbacks and filters are removed. 182 */ 183 184 int 185 bcm_esw_auth_detach(int unit) 186 { 187 bcm_port_t port; 188 int rv = BCM_E_NONE, max_num_port = 0; 189 bcm_pbmp_t temp_pbmp; 190 SOC_PBMP_CLEAR(temp_pbmp); 191 192 if (soc_feature(unit, soc_feature_field) == 0 || 193 auth_cntl[unit] == NULL) { 194 return (BCM_E_NONE); 195 } 196 197 AUTH_INIT_NO_PORT(unit); 198 199 max_num_port = SOC_MAX_NUM_PORTS; 200 BCM_PBMP_ASSIGN(temp_pbmp, PBMP_E_ALL(unit)); 201 202 #ifdef BCM_KATANA2_SUPPORT 203 if (soc_feature(unit, soc_feature_linkphy_coe) || 204 soc_feature(unit, soc_feature_subtag_coe)) { 205 _bcm_kt2_subport_pbmp_update(unit, &temp_pbmp); 206 max_num_port = SOC_MAX_NUM_PP_PORTS; 207 } 208 #endif 209 210 if (0 == SOC_HW_ACCESS_DISABLE(unit)) { 211 for (port = 0; port < max_num_port ; port++) { 212 if (BCM_PBMP_MEMBER(temp_pbmp, port)) { 213 if (soc_feature(unit, soc_feature_field)) { 214 BCM_IF_ERROR_RETURN(_auth_field_remove_all(unit, port)); 215 } 216 _auth_maclist_destroy(&auth_cntl[unit][port].macList); 217 bcm_esw_port_learn_set(unit, port, 218 BCM_PORT_LEARN_ARL | BCM_PORT_LEARN_FWD); 219 bcm_esw_port_stp_set(unit, port, BCM_STG_STP_FORWARD); 220 auth_cntl[unit][port].mode = BCM_AUTH_MODE_UNCONTROLLED; 221 auth_cntl[unit][port].etmp = FALSE; 222 } 223 } 224 } 225 226 for (port = 0; port < max_num_port; port++) { 227 _auth_maclist_destroy(&auth_cntl[unit][port].macList); 228 } 229 230 fp_cntl[unit].inited = FALSE; 231 fp_cntl[unit].count = 0; 232 233 if (cb_cntl[unit].registered) { 234 rv = bcm_esw_linkscan_unregister(unit, _auth_linkscan_cb); 235 /* If linkscan thread was restarted callback might be gone. */ 236 if ((BCM_FAILURE(rv)) && (BCM_E_NOT_FOUND != rv)) { 237 return (rv); 238 } 239 cb_cntl[unit].registered = FALSE; 240 } 241 sal_free(auth_cntl[unit]); 242 auth_cntl[unit] = NULL; 243 return BCM_E_NONE; 244 } 245 246 /* 247 * Function: 248 * bcm_auth_mode_set 249 * Purpose: 250 * Set the 802.1X operating mode 251 * Parameters: 252 * unit - Device number 253 * port - Port number, -1 to set all non-stack-ports 254 * mode - One of BCM_AUTH_MODE_XXX and other flags (see below) 255 * Returns: 256 * BCM_E_NONE - Success 257 * BCM_E_UNIT - Invalid unit number 258 * BCM_E_UNAVAIL - Insufficient hardware support 259 * BCM_E_PORT - Invalid port 260 * Notes: 261 * While in the uncontrolled state, any packets may flow in or out 262 * of the port and normal L2 learning takes place. 263 * 264 * If mode is BCM_AUTH_UNAUTH, a set of flags may be ORed into 265 * the mode word: 266 * BCM_AUTH_BLOCK_IN allow outgoing packets 267 * BCM_AUTH_BLOCK_INOUT do not allow in or out packets 268 * (default) 269 * While in the unauthorized state, all L2 MAC addresses 270 * associated with the port are removed, L2 learning is disabled, 271 * and packet transfer is blocked as specified by the 272 * BCM_AUTH_BLOCK_* flags. Incoming EAPOL frames are allowed 273 * either addressed as BPDUs or to the switch CPU's MAC address. 274 * Some hardware may forward all EAPOL frames regardless of the 275 * destination MAC address. These will be delivered to the CPU 276 * for processing. 277 * 278 * Outgoing EAPOL frames to be sent must be sent with a pair of 279 * bcm_auth_egress_set calls, enabling the egress before the 280 * EAPOL packet and disabling the egress after the packet is 281 * sent. If the BCM_AUTH_BLOCK_IN flag has been given, then the 282 * bcm_auth_egress_set calls will not do anything. 283 * 284 * If mode is BCM_AUTH_MODE_AUTH, a set of flags may be ORed into 285 * the mode word: 286 * BCM_AUTH_LEARN allow L2 learning while authorized 287 * BCM_AUTH_IGNORE_LINK do not unauthorize upon link down 288 * BCM_AUTH_IGNORE_VIOLATION do not unauth upon security 289 * violation 290 * After moving the port to the authorized state, one or more 291 * static L2 entries may be added using bcm_l2_addr_add with the 292 * auth field set. These L2 addresses would typically be for 293 * the source MAC address of the requesting EAPOL frame that was 294 * authorized, in as many VLANs as are configured for the 295 * authorized user. 296 * 297 * While in the authorized state, any packets incoming from source 298 * MAC addresses set by bcm_l2_addr_add will be accepted for 299 * transfer. Any other source MAC addresses will be accepted if 300 * BCM_AUTH_LEARN was set. If BCM_AUTH_LEARN was not set and the 301 * hardware supports it and BCM_AUTH_IGNORE_VIOLATION is not set, 302 * then unknown source MAC addresses will cause a security 303 * violation and move the port to the unauthorized state. 304 * 305 * If the link goes down on the port while in the authorized 306 * state and BCM_AUTH_IGNORE_LINK is not set, then the port will 307 * be moved to the unauthorized state. 308 */ 309 310 int 311 bcm_esw_auth_mode_set(int unit, int port, uint32 mode) 312 { 313 pbmp_t pbmp; 314 bcm_port_t p; 315 316 AUTH_INIT(unit); 317 318 if (port < 0) { 319 BCM_PBMP_ASSIGN(pbmp, PBMP_E_ALL(unit)); 320 #ifdef BCM_KATANA2_SUPPORT 321 if (soc_feature(unit, soc_feature_linkphy_coe) || 322 soc_feature(unit, soc_feature_subtag_coe)) { 323 _bcm_kt2_subport_pbmp_update(unit, &pbmp); 324 } 325 #endif 326 } else { /* port >= 0 */ 327 BCM_IF_ERROR_RETURN(_bcm_esw_port_gport_validate(unit, port, &port)); 328 AUTH_PORT(unit, port); 329 BCM_PBMP_PORT_SET(pbmp, port); 330 } 331 332 /* Remove stack ports from bitmap */ 333 BCM_PBMP_REMOVE(pbmp, SOC_PBMP_STACK_CURRENT(unit)); 334 335 BCM_PBMP_ITER(pbmp, p) { 336 switch (mode & AUTH_MODE_MASK) { 337 case BCM_AUTH_MODE_UNCONTROLLED: 338 if (soc_feature(unit, soc_feature_field)) { 339 BCM_IF_ERROR_RETURN(_auth_field_remove_all(unit, p)); 340 } 341 bcm_esw_port_learn_set(unit, p, BCM_PORT_LEARN_ARL | 342 BCM_PORT_LEARN_FWD); 343 bcm_esw_port_stp_set(unit, p, BCM_STG_STP_FORWARD); 344 auth_cntl[unit][p].etmp = FALSE; 345 break; 346 case BCM_AUTH_MODE_UNAUTH: 347 /* Disable learning on that port */ 348 bcm_esw_port_learn_set(unit, p, BCM_PORT_LEARN_FWD); 349 350 /* remove all L2 (MAC) addresses associated with the port */ 351 bcm_esw_l2_addr_delete_by_port(unit, -1, p, BCM_L2_DELETE_STATIC); 352 353 if (mode & BCM_AUTH_BLOCK_IN) { 354 if (soc_feature(unit, soc_feature_field)) { 355 BCM_IF_ERROR_RETURN(_auth_field_install_all(unit, p)); 356 } 357 /* Set STP state as forward for BLOCK_IN */ 358 BCM_IF_ERROR_RETURN(bcm_esw_port_stp_set(unit, p, 359 BCM_STG_STP_FORWARD)); 360 } 361 else { 362 /* unauthorized for both directions */ 363 if (soc_feature(unit, soc_feature_field)) { 364 BCM_IF_ERROR_RETURN(_auth_field_remove_all(unit, p)); 365 } 366 mode |= BCM_AUTH_BLOCK_INOUT; 367 BCM_IF_ERROR_RETURN(bcm_esw_port_stp_set(unit, p, 368 BCM_STG_STP_BLOCK)); 369 } 370 break; 371 case BCM_AUTH_MODE_AUTH: 372 /* Invalid for both hardware learning and SLF dropping */ 373 if ((mode & (BCM_AUTH_LEARN | BCM_AUTH_DROP_UNKNOWN)) == 374 (BCM_AUTH_LEARN | BCM_AUTH_DROP_UNKNOWN)) { 375 return BCM_E_PARAM; 376 } 377 if (mode & BCM_AUTH_DROP_UNKNOWN) { 378 /* Drop the packet */ 379 bcm_esw_port_learn_set(unit, p, 0); 380 } else { 381 /* No learn, Send to CPU, Drop the packet */ 382 bcm_esw_port_learn_set(unit, p, BCM_PORT_LEARN_CPU); 383 } 384 if (soc_feature(unit, soc_feature_field)) { 385 BCM_IF_ERROR_RETURN(_auth_field_remove_all(unit, p)); 386 } 387 bcm_esw_port_stp_set(unit, p, BCM_STG_STP_FORWARD); 388 if (mode & BCM_AUTH_LEARN) { 389 bcm_esw_port_learn_set(unit, p, BCM_PORT_LEARN_ARL 390 | BCM_PORT_LEARN_FWD); 391 } 392 auth_cntl[unit][p].etmp = FALSE; 393 break; 394 default: 395 return BCM_E_PARAM; 396 } 397 auth_cntl[unit][p].mode = mode; 398 } 399 400 return BCM_E_NONE; 401 } 402 403 /* 404 * Function: 405 * bcm_auth_mode_get 406 * Purpose: 407 * Get the 802.1X operating mode 408 * Parameters: 409 * unit - Device number 410 * port - Port number 411 * mode - (OUT) One of BCM_AUTH_MODE_XXX and other flags 412 * Returns: 413 * BCM_E_NONE - Success 414 * BCM_E_UNIT - Invalid unit number 415 * BCM_E_UNAVAIL - Insufficient hardware support 416 * BCM_E_PORT - Invalid port 417 * Notes: 418 */ 419 420 int 421 bcm_esw_auth_mode_get(int unit, int port, uint32 *modep) 422 { 423 424 AUTH_INIT(unit); 425 BCM_IF_ERROR_RETURN(_bcm_esw_port_gport_validate(unit, port, &port)); 426 AUTH_PORT(unit, port); 427 428 *modep = auth_cntl[unit][port].mode; 429 430 return BCM_E_NONE; 431 } 432 433 /* 434 * Function: 435 * bcm_auth_unauth_callback 436 * Purpose: 437 * Set the callback function for 802.1X notifications 438 * Parameters: 439 * unit - Device number 440 * func - Callback function 441 * cookie - Arbitrary value passed along to callback function 442 * Returns: 443 * BCM_E_NONE - Success 444 * BCM_E_UNIT - Invalid unit number 445 * BCM_E_UNAVAIL - Insufficient hardware support 446 * Notes: 447 * Calls func when a port on the unit has been moved from 448 * authorized to unauthorized state. Reason can be one of: 449 * BCM_AUTH_REASON_UNKNOWN 450 * BCM_AUTH_REASON_LINK 451 * BCM_AUTH_REASON_VIOLATION 452 */ 453 454 int 455 bcm_esw_auth_unauth_callback(int unit, bcm_auth_cb_t func, void *cookie) 456 { 457 AUTH_INIT_NO_PORT(unit); 458 459 cb_cntl[unit].auth_cbs = func; 460 cb_cntl[unit].auth_cb_data = cookie; 461 462 return BCM_E_NONE; 463 } 464 465 /* 466 * Function: 467 * bcm_auth_egress_set 468 * Purpose: 469 * Enable/disable the ability of packets to be sent out a port. 470 * Parameters: 471 * unit - Device number 472 * port - Port number 473 * enable - TRUE to enable, FALSE to disable 474 * Returns: 475 * BCM_E_NONE - Success 476 * BCM_E_UNIT - Invalid unit number 477 * BCM_E_UNAVAIL - Insufficient hardware support 478 * BCM_E_PORT - Invalid port 479 * Notes: 480 * This call should only be used around calls that a CPU uses to 481 * transmit an EAPOL frame out the port. If the port is in an 482 * unauthorized state with BCM_AUTH_BLOCK_IN set or is not in an 483 * unauthorized state, then this call does nothing. 484 */ 485 486 int 487 bcm_esw_auth_egress_set(int unit, int port, int enable) 488 { 489 AUTH_INIT(unit); 490 491 BCM_IF_ERROR_RETURN(_bcm_esw_port_gport_validate(unit, port, &port)); 492 AUTH_PORT(unit, port); 493 494 if (enable) { 495 if ((auth_cntl[unit][port].mode & BCM_AUTH_MODE_UNAUTH) && 496 !(auth_cntl[unit][port].mode & BCM_AUTH_BLOCK_IN)) { 497 bcm_esw_port_stp_set(unit, port, BCM_STG_STP_FORWARD); 498 if (soc_feature(unit, soc_feature_field)) { 499 _auth_field_install_all(unit, port); 500 } 501 auth_cntl[unit][port].mode &= ~BCM_AUTH_BLOCK_INOUT; 502 auth_cntl[unit][port].mode |= BCM_AUTH_BLOCK_IN; 503 auth_cntl[unit][port].etmp= TRUE; 504 } 505 } 506 else { 507 if ((auth_cntl[unit][port].mode & BCM_AUTH_MODE_UNAUTH) && 508 (auth_cntl[unit][port].mode & BCM_AUTH_BLOCK_IN)) { 509 if (soc_feature(unit, soc_feature_field)) { 510 BCM_IF_ERROR_RETURN(_auth_field_remove_all(unit, port)); 511 } 512 bcm_esw_port_stp_set(unit, port, BCM_STG_STP_BLOCK); 513 auth_cntl[unit][port].mode &= ~BCM_AUTH_BLOCK_IN; 514 auth_cntl[unit][port].mode |= BCM_AUTH_BLOCK_INOUT; 515 auth_cntl[unit][port].etmp= FALSE; 516 517 } 518 } 519 520 return BCM_E_NONE; 521 } 522 523 /* 524 * Function: 525 * bcm_auth_egress_get 526 * Purpose: 527 * Return enable/disable state of packets being sent out a port. 528 * Parameters: 529 * unit - Device number 530 * port - Port number 531 * enable - (OUT) TRUE if enabled, FALSE if disabled 532 * Returns: 533 * BCM_E_NONE - Success 534 * BCM_E_UNIT - Invalid unit number 535 * BCM_E_UNAVAIL - Insufficient hardware support 536 * BCM_E_PORT - Invalid port 537 * Notes: 538 */ 539 540 int 541 bcm_esw_auth_egress_get(int unit, int port, int *enable) 542 { 543 AUTH_INIT(unit); 544 545 BCM_IF_ERROR_RETURN(_bcm_esw_port_gport_validate(unit, port, &port)); 546 AUTH_PORT(unit, port); 547 548 *enable = auth_cntl[unit][port].etmp; 549 550 return BCM_E_NONE; 551 } 552 553 /* 554 * Function: 555 * bcm_auth_mac_add 556 * Purpose: 557 * Add switch's MAC addresses 558 * Parameters: 559 * unit - Device number 560 * port - Port number, -1 to all ports 561 * mac - Switch's MAC address 562 * Returns: 563 * BCM_E_NONE - Success 564 * BCM_E_UNIT - Invalid unit number 565 * BCM_E_UNAVAIL - Insufficient hardware support 566 * BCM_E_PORT - Invalid port 567 * BCM_E_PARAM - bad mac 568 * Notes: 569 */ 570 571 int 572 bcm_esw_auth_mac_add(int unit, int port, bcm_mac_t mac) 573 { 574 bcm_mac_t mac_zero = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; 575 bcm_mac_t mac_resv = {0x01, 0x80, 0xc2, 0x00, 0x00, 0x03}; 576 pbmp_t pbm; 577 #if defined(BCM_FIELD_SUPPORT) 578 auth_mac_p entry = NULL; 579 int rv; 580 bcm_port_t p; 581 #endif /* BCM_FIELD_SUPPORT */ 582 583 AUTH_INIT(unit); 584 585 if ((!sal_memcmp(mac, mac_zero, sizeof(bcm_mac_t))) || 586 (!sal_memcmp(mac, mac_resv, sizeof(bcm_mac_t)))) { 587 return BCM_E_PARAM; 588 } 589 590 if (port < 0) { 591 BCM_PBMP_ASSIGN(pbm, PBMP_E_ALL(unit)); 592 #ifdef BCM_KATANA2_SUPPORT 593 if (soc_feature(unit, soc_feature_linkphy_coe) || 594 soc_feature(unit, soc_feature_subtag_coe)) { 595 _bcm_kt2_subport_pbmp_update(unit, &pbm); 596 } 597 #endif 598 } else { /* port >= 0 */ 599 BCM_IF_ERROR_RETURN(_bcm_esw_port_gport_validate(unit, port, &port)); 600 AUTH_PORT(unit, port); 601 602 BCM_PBMP_PORT_SET(pbm, port); 603 } 604 605 #if defined(BCM_FIELD_SUPPORT) 606 BCM_PBMP_ITER(pbm, p) { 607 if ((rv = _auth_maclist_insert(&auth_cntl[unit][p].macList, 608 mac, &entry)) < 0) { 609 return rv; 610 } 611 612 if (auth_cntl[unit][p].mac_set) { 613 if (soc_feature(unit, soc_feature_field)) { 614 #ifdef BCM_FIELD_SUPPORT 615 if ((rv = _auth_field_install(unit, p, mac)) < 0) { 616 _auth_maclist_remove(&auth_cntl[unit][p].macList, 617 mac, &entry); 618 sal_free(entry); 619 return rv; 620 } 621 #endif /* BCM_FIELD_SUPPORT */ 622 } 623 } 624 } 625 626 return BCM_E_NONE; 627 #else /* !BCM_FIELD_SUPPORT */ 628 return BCM_E_UNAVAIL; 629 #endif /* !BCM_FIELD_SUPPORT */ 630 } 631 632 /* 633 * Function: 634 * bcm_auth_mac_delete 635 * Purpose: 636 * Delete switch's MAC address. 637 * Parameters: 638 * unit - Device number 639 * port - Port number 640 * mac - Switch's MAC address 641 * Returns: 642 * BCM_E_NONE - Success 643 * BCM_E_UNIT - Invalid unit number 644 * BCM_E_UNAVAIL - Insufficient hardware support 645 * BCM_E_PORT - Invalid port 646 * BCM_E_PARAM - bad mac 647 * BCM_E_NOT_FOUND - MAC address not found 648 * Notes: 649 */ 650 651 int 652 bcm_esw_auth_mac_delete(int unit, int port, bcm_mac_t mac) 653 { 654 auth_mac_p entry = NULL; 655 int rv; 656 657 AUTH_INIT(unit); 658 659 BCM_IF_ERROR_RETURN(_bcm_esw_port_gport_validate(unit, port, &port)); 660 AUTH_PORT(unit, port); 661 662 rv = _auth_maclist_remove(&auth_cntl[unit][port].macList, mac, &entry); 663 664 if (rv < 0) { 665 return rv; 666 } 667 668 if (auth_cntl[unit][port].mac_set) { 669 if (soc_feature(unit, soc_feature_field)) { 670 BCM_IF_ERROR_RETURN(_auth_field_remove(unit, port, mac)); 671 } 672 } 673 674 sal_free(entry); 675 676 return BCM_E_NONE; 677 } 678 679 /* 680 * Function: 681 * bcm_auth_mac_delete_all 682 * Purpose: 683 * Delete all switch's MAC addresses. 684 * Parameters: 685 * unit - Device number 686 * port - Port number 687 * Returns: 688 * BCM_E_XXX 689 * Notes: 690 */ 691 692 int 693 bcm_esw_auth_mac_delete_all(int unit, int port) 694 { 695 int tmp, rv; 696 697 AUTH_INIT(unit); 698 699 BCM_IF_ERROR_RETURN(_bcm_esw_port_gport_validate(unit, port, &port)); 700 AUTH_PORT(unit, port); 701 702 tmp = auth_cntl[unit][port].mac_set; 703 if (soc_feature(unit, soc_feature_field)) { 704 BCM_IF_ERROR_RETURN(_auth_field_remove_all(unit, port)); 705 } 706 rv = _auth_maclist_destroy(&auth_cntl[unit][port].macList); 707 auth_cntl[unit][port].mac_set = tmp; 708 709 return rv; 710 } 711 712 /* 713 * Function: 714 * _auth_linkscan_cb 715 * Description: 716 * Put authorized state to unauthorized state if link down, 717 * given BCM_AUTH_IGNORE_LINK not set 718 * Parameters: 719 * unit - Device number 720 * port - Port number 721 * info - pointer to structure giving status 722 * Returns: 723 * None 724 * Notes: 725 */ 726 727 STATIC void 728 _auth_linkscan_cb(int unit, bcm_port_t port, bcm_port_info_t *info) 729 { 730 if ((auth_cntl[unit] != NULL) && (IS_E_PORT(unit, port)) 731 && !(auth_cntl[unit][port].mode & BCM_AUTH_MODE_UNCONTROLLED)) { 732 if (info->linkstatus != BCM_PORT_LINK_STATUS_UP) { 733 if ((auth_cntl[unit][port].mode & BCM_AUTH_MODE_AUTH) && 734 !(auth_cntl[unit][port].mode & BCM_AUTH_IGNORE_LINK)) { 735 bcm_esw_auth_mode_set(unit, port, BCM_AUTH_MODE_UNAUTH); 736 if (cb_cntl[unit].auth_cbs) { 737 cb_cntl[unit].auth_cbs(cb_cntl[unit].auth_cb_data, 738 unit, port, BCM_AUTH_REASON_LINK); 739 } 740 } 741 } 742 } 743 } 744 745 /* 746 * Function: 747 * _auth_field_install 748 * Description: 749 * Install FP for accepting EAPOL frames 750 * destinated for switch CPU's MAC address 751 * Parameters: 752 * unit - Device number 753 * port - Port number 754 * mac - MAC address 755 * Returns: 756 * BCM_E_XXX 757 * Notes: 758 */ 759 760 STATIC int 761 _auth_field_install(int unit, int port, bcm_mac_t mac) 762 { 763 #ifdef BCM_FIELD_SUPPORT 764 _field_stage_t *stage_fc=NULL; /* Stage Field control structure. */ 765 bcm_port_config_t pc; /* Port Configuration structure. */ 766 bcm_field_group_config_t fg0; /* Group configuration structure. */ 767 bcm_field_group_config_t fg2; /* Group configuration structure. */ 768 int instance=0; /* Pipe instance. */ 769 bcm_pbmp_t mask_pbmp; /* IPBM mask. */ 770 int rv = BCM_E_NONE; 771 int rv2 = BCM_E_NONE; 772 pbmp_t pbm; 773 bcm_field_group_t group0; 774 bcm_field_entry_t entry0; 775 bcm_mac_t mac_all_ones; 776 auth_mac_p entry = NULL; 777 778 /* In Tomahawk, In global mode, Group is created with port bitmaps of all pipes. 779 * In PerPipe mode, Group is created with port bitmaps of only the 780 * pipe to which the input port belongs to. 781 */ 782 BCM_IF_ERROR_RETURN(_field_stage_control_get(unit, _BCM_FIELD_STAGE_INGRESS, &stage_fc)); 783 784 bcm_port_config_t_init(&pc); 785 BCM_IF_ERROR_RETURN(bcm_esw_port_config_get(unit, &pc)); 786 787 bcm_field_group_config_t_init(&fg0); 788 bcm_field_group_config_t_init(&fg2); 789 instance = SOC_INFO(unit).port_pipe[port]; 790 mask_pbmp = PBMP_E_ALL(unit); 791 792 if (SOC_IS_TOMAHAWKX(unit)) { 793 switch (stage_fc->oper_mode) { 794 case bcmFieldGroupOperModeGlobal: 795 break; 796 case bcmFieldGroupOperModePipeLocal: 797 fg0.ports = pc.per_pipe[instance]; 798 fg0.flags |= BCM_FIELD_GROUP_CREATE_WITH_PORT; 799 fg2.ports = pc.per_pipe[instance]; 800 fg2.flags |= BCM_FIELD_GROUP_CREATE_WITH_PORT; 801 mask_pbmp = PBMP_PIPE(unit,instance); 802 break; 803 default: 804 return (BCM_E_INTERNAL); 805 } 806 } 807 808 sal_memset(mac_all_ones, 0xff, sizeof(bcm_mac_t)); 809 810 if (!fp_cntl[unit].inited) { 811 bcm_field_group_t group2; 812 bcm_field_entry_t entry2; 813 814 BCM_FIELD_QSET_INIT(fg0.qset); 815 if (soc_feature(unit, soc_feature_ifp_no_inports_support)) { 816 BCM_FIELD_QSET_ADD(fg0.qset, bcmFieldQualifyInPort); 817 } else { 818 BCM_FIELD_QSET_ADD(fg0.qset, bcmFieldQualifyInPorts); 819 } 820 BCM_FIELD_QSET_ADD(fg0.qset, bcmFieldQualifyDstMac); 821 BCM_FIELD_QSET_ADD(fg0.qset, bcmFieldQualifyEtherType); 822 823 fg0.priority = 14; 824 BCM_IF_ERROR_RETURN(bcm_esw_field_group_config_create(unit, &fg0)); 825 group0 = fg0.group; 826 827 BCM_IF_ERROR_RETURN( 828 bcm_esw_field_entry_create(unit, group0, &entry0)); 829 BCM_PBMP_PORT_SET(pbm, port); 830 if (soc_feature(unit, soc_feature_ifp_no_inports_support)) { 831 BCM_IF_ERROR_RETURN( 832 bcm_esw_field_qualify_InPort(unit, entry0, port, -1)); 833 } else { 834 BCM_IF_ERROR_RETURN( 835 bcm_esw_field_qualify_InPorts(unit, entry0, pbm, mask_pbmp)); 836 } 837 BCM_IF_ERROR_RETURN( 838 bcm_esw_field_qualify_DstMac(unit, entry0, mac, 839 (uint8 *)mac_all_ones)); 840 BCM_IF_ERROR_RETURN( 841 bcm_esw_field_qualify_EtherType(unit, entry0, _AUTH_ETHERTYPE_EAPOL, 842 _AUTH_ETHERTYPE_MASK)); 843 BCM_IF_ERROR_RETURN( 844 bcm_esw_field_action_add(unit, entry0, bcmFieldActionCopyToCpu, 0, 0)); 845 846 BCM_FIELD_QSET_INIT(fg2.qset); 847 if (soc_feature(unit, soc_feature_ifp_no_inports_support)) { 848 BCM_FIELD_QSET_ADD(fg2.qset, bcmFieldQualifyInPort); 849 } else { 850 BCM_FIELD_QSET_ADD(fg2.qset, bcmFieldQualifyInPorts); 851 } 852 853 fg2.priority = 13; 854 BCM_IF_ERROR_RETURN(bcm_esw_field_group_config_create(unit, &fg2)); 855 group2 = fg2.group; 856 857 BCM_IF_ERROR_RETURN( 858 bcm_esw_field_entry_create(unit, group2, &entry2)); 859 if (soc_feature(unit, soc_feature_ifp_no_inports_support)) { 860 BCM_IF_ERROR_RETURN( 861 bcm_esw_field_qualify_InPort(unit, entry2, port, -1)); 862 } else { 863 BCM_IF_ERROR_RETURN( 864 bcm_esw_field_qualify_InPorts(unit, entry2, pbm, mask_pbmp)); 865 } 866 867 BCM_IF_ERROR_RETURN( 868 bcm_esw_field_action_add(unit, entry2, bcmFieldActionDrop, 0, 0)); 869 870 rv = bcm_esw_field_entry_install(unit, entry0); 871 rv2 = bcm_esw_field_entry_install(unit, entry2); 872 if (BCM_FAILURE(rv) || BCM_FAILURE(rv2)) { 873 BCM_IF_ERROR_RETURN(bcm_esw_field_entry_remove(unit, entry0)); 874 BCM_IF_ERROR_RETURN(bcm_esw_field_entry_destroy(unit, entry0)); 875 BCM_IF_ERROR_RETURN(bcm_esw_field_group_destroy(unit, group0)); 876 BCM_IF_ERROR_RETURN(bcm_esw_field_entry_remove(unit, entry2)); 877 BCM_IF_ERROR_RETURN(bcm_esw_field_entry_destroy(unit, entry2)); 878 BCM_IF_ERROR_RETURN(bcm_esw_field_group_destroy(unit, group2)); 879 return (rv != BCM_E_NONE ? rv : rv2); 880 } 881 882 fp_cntl[unit].group0 = group0; 883 rv2 = _auth_maclist_insert(&fp_cntl[unit].macList, mac, &entry); 884 if (rv2 == BCM_E_NONE) { 885 entry->entry = entry0; 886 BCM_PBMP_PORT_SET(entry->pbmp, port); 887 } 888 fp_cntl[unit].group2 = group2; 889 fp_cntl[unit].entry2 = entry2; 890 BCM_PBMP_PORT_SET(fp_cntl[unit].group2_pbmp, port); 891 fp_cntl[unit].inited = TRUE; 892 fp_cntl[unit].count++; 893 } else { 894 if ((rv = _auth_maclist_lookup(&fp_cntl[unit].macList, mac, &entry)) > 0) { 895 BCM_FIELD_QSET_INIT(fg0.qset); 896 if (soc_feature(unit, soc_feature_ifp_no_inports_support)) { 897 BCM_FIELD_QSET_ADD(fg0.qset, bcmFieldQualifyInPort); 898 } else { 899 BCM_FIELD_QSET_ADD(fg0.qset, bcmFieldQualifyInPorts); 900 } 901 pbm = entry->pbmp; 902 BCM_PBMP_PORT_ADD(pbm, port); 903 if (soc_feature(unit, soc_feature_ifp_no_inports_support)) { 904 BCM_IF_ERROR_RETURN( 905 bcm_esw_field_qualify_InPort(unit, entry->entry, port, -1)); 906 } else { 907 BCM_IF_ERROR_RETURN( 908 bcm_esw_field_qualify_InPorts(unit, entry->entry, pbm, 909 mask_pbmp)); 910 } 911 BCM_IF_ERROR_RETURN( 912 bcm_esw_field_entry_reinstall(unit, entry->entry)); 913 entry->pbmp = pbm; 914 } else { 915 BCM_FIELD_QSET_INIT(fg0.qset); 916 if (soc_feature(unit, soc_feature_ifp_no_inports_support)) { 917 BCM_FIELD_QSET_ADD(fg0.qset, bcmFieldQualifyInPort); 918 } else { 919 BCM_FIELD_QSET_ADD(fg0.qset, bcmFieldQualifyInPorts); 920 } 921 BCM_FIELD_QSET_ADD(fg0.qset, bcmFieldQualifyDstMac); 922 BCM_FIELD_QSET_ADD(fg0.qset, bcmFieldQualifyEtherType); 923 BCM_IF_ERROR_RETURN( 924 bcm_esw_field_entry_create(unit, fp_cntl[unit].group0, &entry0)); 925 BCM_PBMP_PORT_SET(pbm, port); 926 if (soc_feature(unit, soc_feature_ifp_no_inports_support)) { 927 BCM_IF_ERROR_RETURN( 928 bcm_esw_field_qualify_InPort(unit, entry0, port, -1)); 929 } else { 930 BCM_IF_ERROR_RETURN( 931 bcm_esw_field_qualify_InPorts(unit, entry0, pbm, mask_pbmp)); 932 } 933 BCM_IF_ERROR_RETURN( 934 bcm_esw_field_qualify_DstMac(unit, entry0, mac, 935 (uint8 *) mac_all_ones)); 936 BCM_IF_ERROR_RETURN( 937 bcm_esw_field_qualify_EtherType(unit, entry0, _AUTH_ETHERTYPE_EAPOL, 938 _AUTH_ETHERTYPE_MASK)); 939 BCM_IF_ERROR_RETURN( 940 bcm_esw_field_action_add(unit, entry0, bcmFieldActionCopyToCpu, 941 0, 0)); 942 rv = bcm_esw_field_entry_install(unit, entry0); 943 if (BCM_SUCCESS(rv)) { 944 auth_mac_p entry = NULL; 945 rv2 = _auth_maclist_insert(&fp_cntl[unit].macList, mac, &entry); 946 if (rv2 == BCM_E_NONE) { 947 entry->entry = entry0; 948 entry->pbmp = pbm; 949 } 950 fp_cntl[unit].count++; 951 } else { 952 BCM_IF_ERROR_RETURN(bcm_esw_field_entry_destroy(unit, entry0)); 953 } 954 } 955 956 /* Add port to Drop all group */ 957 pbm = fp_cntl[unit].group2_pbmp; 958 BCM_PBMP_PORT_ADD(pbm, port); 959 if (soc_feature(unit, soc_feature_ifp_no_inports_support)) { 960 BCM_IF_ERROR_RETURN( 961 bcm_esw_field_qualify_InPort(unit, fp_cntl[unit].entry2, port, -1)); 962 } else { 963 BCM_IF_ERROR_RETURN( 964 bcm_esw_field_qualify_InPorts(unit, fp_cntl[unit].entry2, pbm, 965 mask_pbmp)); 966 } 967 BCM_IF_ERROR_RETURN( 968 bcm_esw_field_entry_reinstall(unit, fp_cntl[unit].entry2)); 969 fp_cntl[unit].group2_pbmp = pbm; 970 971 } 972 973 return rv; 974 #else /* !BCM_FIELD_SUPPORT */ 975 return BCM_E_UNAVAIL; 976 #endif /* !BCM_FIELD_SUPPORT */ 977 } 978 979 /* 980 * Function: 981 * _auth_field_install_all 982 * Description: 983 * Install FP for accepting EAPOL frames 984 * destinated for switch CPU's MAC addresses 985 * Parameters: 986 * unit - Device number 987 * port - Port number 988 * Returns: 989 * BCM_E_XXX 990 * Notes: 991 */ 992 993 STATIC int 994 _auth_field_install_all(int unit, int port) 995 { 996 auth_mac_t **list=&auth_cntl[unit][port].macList; 997 auth_mac_p entry = NULL; 998 int rv = BCM_E_NONE; 999 bcm_mac_t mac_zero = {0}; 1000 1001 if (auth_cntl[unit][port].mac_set) { 1002 return BCM_E_EXISTS; 1003 } 1004 1005 /* No accepted MAC addresses, drop all for default */ 1006 if (*list == NULL) { 1007 rv = _auth_field_install(unit, port, mac_zero); 1008 if (rv < 0) { 1009 return rv; 1010 } 1011 } 1012 1013 while (*list != NULL) { 1014 rv = _auth_field_install(unit, port, (*list)->mac); 1015 if (rv < 0) { 1016 _auth_maclist_remove(list, (*list)->mac, &entry); 1017 sal_free(entry); 1018 } else { 1019 list = &(*list)->next; 1020 } 1021 } 1022 auth_cntl[unit][port].mac_set = TRUE; 1023 1024 return rv; 1025 } 1026 1027 /* 1028 * Function: 1029 * _auth_field_remove_all 1030 * Description: 1031 * Removed all installed FP in controlled state 1032 * Parameters: 1033 * unit - Device number 1034 * port - Port number 1035 * Returns: 1036 * BCM_E_XXX 1037 * Notes: 1038 */ 1039 1040 STATIC int 1041 _auth_field_remove_all(int unit, int port) 1042 { 1043 bcm_pbmp_t pbmp_mask; 1044 auth_mac_t **list=&fp_cntl[unit].macList; 1045 1046 if (!auth_cntl[unit][port].mac_set) { 1047 return BCM_E_NONE; 1048 } 1049 1050 BCM_PBMP_CLEAR(pbmp_mask); 1051 BCM_PBMP_ASSIGN (pbmp_mask, PBMP_E_ALL(unit)); 1052 #ifdef BCM_KATANA2_SUPPORT 1053 if (soc_feature(unit, soc_feature_linkphy_coe) || 1054 soc_feature(unit, soc_feature_subtag_coe)) { 1055 _bcm_kt2_subport_pbmp_update(unit, &pbmp_mask); 1056 } 1057 #endif 1058 1059 while (*list != NULL) { 1060 pbmp_t pbm; 1061 pbm = (*list)->pbmp; 1062 BCM_PBMP_PORT_REMOVE(pbm, port); 1063 if (BCM_PBMP_IS_NULL(pbm)) { 1064 BCM_IF_ERROR_RETURN 1065 (bcm_esw_field_entry_remove(unit, (*list)->entry)); 1066 BCM_IF_ERROR_RETURN 1067 (bcm_esw_field_entry_destroy(unit, (*list)->entry)); 1068 fp_cntl[unit].count--; 1069 (*list)->entry = -1; 1070 } else { 1071 if (!soc_feature(unit, soc_feature_ifp_no_inports_support)) { 1072 BCM_IF_ERROR_RETURN 1073 (bcm_esw_field_qualify_InPorts(unit, (*list)->entry, pbm, pbmp_mask)); 1074 } 1075 BCM_IF_ERROR_RETURN 1076 (bcm_esw_field_entry_reinstall(unit, (*list)->entry)); 1077 (*list)->pbmp = pbm; 1078 } 1079 list = &(*list)->next; 1080 } 1081 1082 if ((fp_cntl[unit].count==0) && (fp_cntl[unit].inited)) { 1083 BCM_IF_ERROR_RETURN 1084 (bcm_esw_field_entry_remove(unit, fp_cntl[unit].entry2)); 1085 BCM_IF_ERROR_RETURN 1086 (bcm_esw_field_entry_destroy(unit, fp_cntl[unit].entry2)); 1087 BCM_IF_ERROR_RETURN 1088 (bcm_esw_field_group_destroy(unit, fp_cntl[unit].group0)); 1089 BCM_IF_ERROR_RETURN 1090 (bcm_esw_field_group_destroy(unit, fp_cntl[unit].group2)); 1091 _auth_maclist_destroy(&fp_cntl[unit].macList); 1092 fp_cntl[unit].inited = FALSE; 1093 } else { 1094 auth_mac_p entry; 1095 list = &fp_cntl[unit].macList; 1096 while (*list != NULL) { 1097 if ((*list)->entry == -1) { 1098 entry = *list; 1099 *list = entry->next; 1100 sal_free(entry); 1101 } 1102 list = &(*list)->next; 1103 } 1104 } 1105 1106 auth_cntl[unit][port].mac_set = FALSE; 1107 1108 return BCM_E_NONE; 1109 } 1110 1111 /* 1112 * Function: 1113 * _auth_field_remove 1114 * Description: 1115 * Removed installed FP 1116 * Parameters: 1117 * unit - Device number 1118 * port - Port number 1119 * mac - Switch's MAC address 1120 * Returns: 1121 * BCM_E_XXX 1122 * Notes: 1123 */ 1124 1125 STATIC int 1126 _auth_field_remove(int unit, int port, bcm_mac_t mac) 1127 { 1128 #ifdef BCM_FIELD_SUPPORT 1129 pbmp_t pbm; 1130 bcm_field_qset_t qset0; 1131 auth_mac_p entry = NULL; 1132 bcm_pbmp_t pbmp_mask; 1133 1134 BCM_PBMP_CLEAR(pbmp_mask); 1135 BCM_PBMP_ASSIGN (pbmp_mask, PBMP_E_ALL(unit)); 1136 #ifdef BCM_KATANA2_SUPPORT 1137 if (soc_feature(unit, soc_feature_linkphy_coe) || 1138 soc_feature(unit, soc_feature_subtag_coe)) { 1139 _bcm_kt2_subport_pbmp_update(unit, &pbmp_mask); 1140 } 1141 #endif 1142 1143 if (_auth_maclist_lookup(&fp_cntl[unit].macList, mac, &entry) > 0) { 1144 BCM_FIELD_QSET_INIT(qset0); 1145 if (soc_feature(unit, soc_feature_ifp_no_inports_support)) { 1146 BCM_FIELD_QSET_ADD(qset0, bcmFieldQualifyInPort); 1147 } else { 1148 BCM_FIELD_QSET_ADD(qset0, bcmFieldQualifyInPorts); 1149 } 1150 pbm = entry->pbmp; 1151 BCM_PBMP_PORT_REMOVE(pbm, port); 1152 if (BCM_PBMP_IS_NULL(pbm)) { 1153 BCM_IF_ERROR_RETURN 1154 (bcm_esw_field_entry_remove(unit, entry->entry)); 1155 BCM_IF_ERROR_RETURN 1156 (bcm_esw_field_entry_destroy(unit, entry->entry)); 1157 fp_cntl[unit].count--; 1158 _auth_maclist_remove(&fp_cntl[unit].macList, mac, &entry); 1159 sal_free(entry); 1160 } else { 1161 if (soc_feature(unit, soc_feature_ifp_no_inports_support)) { 1162 BCM_IF_ERROR_RETURN 1163 (bcm_esw_field_qualify_InPort(unit, entry->entry, port, -1)); 1164 } else { 1165 BCM_IF_ERROR_RETURN 1166 (bcm_esw_field_qualify_InPorts(unit, entry->entry, pbm, pbmp_mask)); 1167 } 1168 BCM_IF_ERROR_RETURN( 1169 bcm_esw_field_entry_reinstall(unit, entry->entry)); 1170 entry->pbmp = pbm; 1171 } 1172 } 1173 1174 if ((fp_cntl[unit].count==0) && (fp_cntl[unit].inited)) { 1175 BCM_IF_ERROR_RETURN 1176 (bcm_esw_field_entry_remove(unit, fp_cntl[unit].entry2)); 1177 BCM_IF_ERROR_RETURN 1178 (bcm_esw_field_entry_destroy(unit, fp_cntl[unit].entry2)); 1179 BCM_IF_ERROR_RETURN 1180 (bcm_esw_field_group_destroy(unit, fp_cntl[unit].group0)); 1181 BCM_IF_ERROR_RETURN 1182 (bcm_esw_field_group_destroy(unit, fp_cntl[unit].group2)); 1183 _auth_maclist_destroy(&fp_cntl[unit].macList); 1184 fp_cntl[unit].inited = FALSE; 1185 } 1186 1187 return BCM_E_NONE; 1188 #else /* !BCM_FIELD_SUPPORT */ 1189 return BCM_E_UNAVAIL; 1190 #endif /* !BCM_FIELD_SUPPORT */ 1191 } 1192 1193 #if defined(BCM_FIELD_SUPPORT) 1194 /* 1195 * Function: 1196 * _auth_maclist_insert 1197 * Description: 1198 * Add a MAC address to the list 1199 * Parameters: 1200 * list - list to be inserted 1201 * mac - MAC address 1202 * ins - (OUT) entry inserted 1203 * Returns: 1204 * BCM_E_XXX 1205 * Notes: 1206 */ 1207 1208 STATIC int 1209 _auth_maclist_insert(auth_mac_t **list, bcm_mac_t mac, auth_mac_p *ins) 1210 { 1211 auth_mac_p entry = NULL; 1212 1213 if (_auth_maclist_lookup(list, mac, &entry) > 0) { 1214 return BCM_E_EXISTS; 1215 } 1216 1217 if ((entry = sal_alloc(sizeof(auth_mac_t), "maclist")) == NULL) { 1218 return BCM_E_MEMORY; 1219 } 1220 1221 sal_memset(entry, 0, sizeof(auth_mac_t)); 1222 sal_memcpy(entry->mac, mac, sizeof(bcm_mac_t)); 1223 entry->next = *list; 1224 *list = entry; 1225 *ins = entry; 1226 1227 return BCM_E_NONE; 1228 } 1229 #endif /* !BCM_FIELD_SUPPORT */ 1230 1231 /* 1232 * Function: 1233 * _auth_maclist_remove 1234 * Description: 1235 * Remove a MAC address from the list 1236 * Parameters: 1237 * list - list to be removed 1238 * mac - MAC address 1239 * ins - (OUT) entry deleted 1240 * Returns: 1241 * BCM_E_NONE - Success 1242 * BCM_E_NOT_FOUND - MAC not found in list 1243 * Notes: 1244 */ 1245 1246 STATIC int 1247 _auth_maclist_remove(auth_mac_t **list, bcm_mac_t mac, auth_mac_p *del) 1248 { 1249 auth_mac_p entry; 1250 1251 while (*list != NULL) { 1252 if (!sal_memcmp((*list)->mac, mac, sizeof(bcm_mac_t))) { 1253 entry = *list; 1254 *list = entry->next; 1255 *del = entry; 1256 return BCM_E_NONE; 1257 } 1258 list = &(*list)->next; 1259 } 1260 1261 return BCM_E_NOT_FOUND; 1262 } 1263 1264 #if defined(BCM_FIELD_SUPPORT) 1265 /* 1266 * Function: 1267 * _auth_maclist_lookup 1268 * Description: 1269 * Lookup a MAC address in the list 1270 * Parameters: 1271 * list - list to be lookuped 1272 * mac - MAC address 1273 * Returns: 1274 * BCM_E_XXX 1275 * Notes: 1276 */ 1277 1278 STATIC int 1279 _auth_maclist_lookup(auth_mac_t **list, bcm_mac_t mac, auth_mac_p *entry) 1280 { 1281 while (*list != NULL) { 1282 if (!sal_memcmp((*list)->mac, mac, sizeof(bcm_mac_t))) { 1283 *entry = *list; 1284 return TRUE; 1285 } 1286 list = &(*list)->next; 1287 } 1288 1289 return FALSE; 1290 } 1291 #endif /* !BCM_FIELD_SUPPORT */ 1292 1293 /* 1294 * Function: 1295 * _auth_maclist_destroy 1296 * Description: 1297 * Destroy all MAC addresses in the list 1298 * Parameters: 1299 * list - list to be destroyed 1300 * Returns: 1301 * BCM_E_XXX 1302 * Notes: 1303 */ 1304 1305 STATIC int 1306 _auth_maclist_destroy(auth_mac_t **list) 1307 { 1308 auth_mac_p entry = NULL; 1309 1310 if (*list == NULL) { 1311 return BCM_E_EMPTY; 1312 } 1313 1314 while (*list != NULL) { 1315 _auth_maclist_remove(list, (*list)->mac, &entry); 1316 sal_free(entry); 1317 } 1318 return BCM_E_NONE; 1319 } 1320 1321 #ifdef AUTH_DEBUG 1322 /* 1323 * Function: 1324 * _auth_maclist_dump 1325 * Description: 1326 * Dump all MAC addresses in the list 1327 * Parameters: 1328 * list - list to be dumped 1329 * Returns: 1330 * BCM_E_XXX 1331 * Notes: 1332 */ 1333 1334 STATIC int 1335 _auth_maclist_dump(auth_mac_t **list) 1336 { 1337 while (*list != NULL) { 1338 LOG_CLI((BSL_META_U(unit, 1339 "%02x:%02x:%02x:%02x:%02x:%02x\n"), 1340 (*list)->mac[0], (*list)->mac[1], 1341 (*list)->mac[2], (*list)->mac[3], 1342 (*list)->mac[4], (*list)->mac[5])); 1343 list = &(*list)->next; 1344 } 1345 1346 return BCM_E_NONE; 1347 } 1348 #endif /* AUTH_DEBUG */