acl.c (52874B)
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: acl.c 8 * Purpose: 9 * Advanced ContentAware Enhanced Software (ACES) implementation. 10 */ 11 12 #if defined(INCLUDE_ACL) 13 14 #include <shared/bsl.h> 15 16 #include <bcm/error.h> 17 18 #include <sal/core/libc.h> 19 20 #include <shared/util.h> 21 22 #include <bcmx/lport.h> 23 #include <bcmx/lplist.h> 24 25 #include <appl/acl/acl.h> 26 #include <appl/diag/system.h> 27 28 #include "acl_field.h" 29 #include "acl_util.h" 30 31 /* Macros */ 32 33 /* 34 * Macro: ACL_IS_INIT (internal) 35 * 36 * Purpose: 37 * Confirm that the ACL functions are initialized. 38 * 39 * Parameters: 40 * 41 * Notes: 42 * Results in return(BCM_E_UNAVAIL), or 43 * return(BCM_E_INIT) if fails. 44 */ 45 #define ACL_IS_INIT() do { \ 46 if (_acl_control == NULL) { \ 47 LOG_ERROR(BSL_LS_APPL_ACCESSCTRLLIST, \ 48 (BSL_META("ACL Error: ACL not initialized\n"))); \ 49 return BCM_E_INIT; \ 50 } \ 51 } while (0) 52 53 /* 54 * Macro: 55 * ACL_LOCK/ACL_UNLOCK (internal) 56 * Purpose: 57 * Lock the ACL module. 58 * 59 * Parameters: 60 */ 61 #define ACL_LOCK() \ 62 sal_mutex_take(_acl_control->acl_lock, sal_mutex_FOREVER) 63 64 #define ACL_UNLOCK(_c_) \ 65 sal_mutex_give((_c_)->acl_lock) 66 67 68 #define ACL_RETVAL_REPLACE(_retval_temp, _retval) \ 69 if ((_retval_temp) == BCM_E_INIT) { \ 70 (_retval_temp) = BCM_E_UNAVAIL; \ 71 } \ 72 if ((_retval_temp) < 0 && (_retval_temp) != BCM_E_UNAVAIL) { \ 73 (_retval) = (_retval_temp); \ 74 } 75 76 77 78 /* Local Prototypes */ 79 STATIC int _acl_rule_validate (const bcma_acl_rule_t *rule); 80 STATIC _acl_link_t* _acl_find(bcma_acl_list_id_t list_id); 81 STATIC _acl_link_t* _acl_link_alloc(void); 82 83 STATIC _acl_rule_link_t *_acl_rule_find(bcma_acl_rule_id_t rule_id); 84 STATIC _acl_rule_link_t *_acl_rule_link_alloc(void); 85 86 STATIC int _acl_sort(void); 87 STATIC int _acl_cmp(void *a, void *b); 88 STATIC int _acl_merge(void); 89 STATIC int _acl_range_reduce(uint16 min, uint16 max, acl_node_t **list); 90 91 /* Control Globals */ 92 static _acl_control_t *_acl_control; 93 94 #ifdef BROADCOM_DEBUG 95 static char *bcma_acl_ip_protocol_text[256] = { 96 "HOPBYHOP", "ICMP", "IGMP", "GGP", 97 "IP", "ST", "TCP", "UCL", 98 "EGP", "IGP", "BBN-RCC-MON", "NVP_II", 99 "PUP", "ARGUS", "EMCON", "XNET", 100 "CHAOS", "UDP", "MUX", "DCN_MEAS", 101 "HMP", "PRM", "XNS_IDP", "TRUNK-1", 102 "TRUNK-2", "LEAF1", "LEAF2", "RDP", 103 "IRTP", "ISO_TP4", "NETBLT", "MFE-NSP", 104 "MERIT_INP", "SEP", "3PC", "IDRP", 105 "XTP", "DDP", "IDPR_CMTP", "TP++", 106 "IL", "SIP", "SDRP", "SIP-SR", 107 "SIP-FRAG", "IDRP", "RSVP", "GRE", 108 "MHRP", "BNA", "SIPP_ESP", "SIPP_AH", 109 "I-NLSP", "SWIPE", "NHRP", "", 110 "", "", "", "", 111 "", "AHIP", "CFTP", "HI", 112 "SAT_EXPAK", "KRYPTOLAN", "RVD", "IPPC", 113 "ADFS", "SAT_MON", "VISA", "IPCV", 114 "CPNX", "CPHB", "WSN", "PVP", 115 "BR_SAT_MON", "SUN_ND", "WB_MON", "WB_EXPAK", 116 "ISO_IP", "VMTP", "SECURE_VMTP", "VINES", 117 "TTP", "NSFNET_IGP", "DGP", "TCF", 118 "IGRP", "OSPFIGP", "SPRITE_RPC", "LARP", 119 "MTP", "AX_25", "IPIP", "MICP", 120 "SCC_SP", "ETHERIP", "ENCAP", "APES", 121 "GMTP", "", "", "", 122 "", "", "", "", 123 "", "", "", "", 124 "", "", "", "", 125 "", "", "", "", 126 "", "", "", "", 127 "", "", "", "", 128 "", "", "", "", 129 "", "", "", "", 130 "", "", "", "", 131 "", "", "", "", 132 "", "", "", "", 133 "", "", "", "", 134 "", "", "", "", 135 "", "", "", "", 136 "", "", "", "", 137 "", "", "", "", 138 "", "", "", "", 139 "", "", "", "", 140 "", "", "", "", 141 "", "", "", "", 142 "", "", "", "", 143 "", "", "", "", 144 "", "", "", "", 145 "", "", "", "", 146 "", "", "", "", 147 "", "", "", "", 148 "", "", "", "", 149 "", "", "", "", 150 "", "", "", "", 151 "", "", "", "", 152 "", "", "", "", 153 "", "", "", "", 154 "", "", "", "", 155 "", "", "", "", 156 "", "", "", "", 157 "", "", "", "", 158 "", "", "", "", 159 "", "", "", "ANY" 160 }; 161 #endif /* BROADCOM_DEBUG */ 162 163 /* Section: Constructor and destructor for ACL (ACES) module */ 164 165 /* 166 * Function: bcma_acl_init 167 * 168 * Purpose: 169 * Initializes ACES. 170 * 171 * Parameters: 172 * none 173 * 174 * Returns: 175 * BCM_E_NONE - Success 176 * BCM_E_MEMORY - Allocation failure 177 */ 178 int 179 bcma_acl_init(void) 180 { 181 _acl_control_t *control; 182 int retval = BCM_E_NONE; 183 184 LOG_DEBUG(BSL_LS_APPL_ACCESSCTRLLIST, 185 (BSL_META("ACL bcma_acl_init()\n"))); 186 187 /* Detach first if it has been previously initialized. */ 188 if (_acl_control != NULL) { 189 BCM_IF_ERROR_RETURN(bcma_acl_uninstall()); 190 BCM_IF_ERROR_RETURN(bcma_acl_detach()); 191 } 192 193 control = sal_alloc(sizeof(_acl_control_t), "ACL Control"); 194 if (control == NULL) { 195 LOG_ERROR(BSL_LS_APPL_ACCESSCTRLLIST, 196 (BSL_META("ACL Error: allocation failure for ACL control.\n"))); 197 return BCM_E_MEMORY; 198 } 199 sal_memset(control, 0, sizeof(_acl_control_t)); 200 201 control->acl_lock = sal_mutex_create("ACL_control.lock"); 202 if (control->acl_lock == NULL) { 203 sal_free(control); 204 LOG_ERROR(BSL_LS_APPL_ACCESSCTRLLIST, 205 (BSL_META("ACL Error: creation failure for ACL lock.\n"))); 206 return BCM_E_MEMORY; 207 } 208 209 /* Initialize control structure. */ 210 _acl_control = control; 211 ACL_LOCK(); 212 control->head.next = NULL; 213 214 #ifdef BCM_FIELD_SUPPORT 215 { 216 int retval_temp; 217 retval_temp = _acl_field_init(); 218 ACL_RETVAL_REPLACE(retval_temp, retval); 219 } 220 #endif /* BCM_FIELD_SUPPORT */ 221 222 ACL_UNLOCK(_acl_control); 223 224 return retval; 225 } 226 227 /* 228 * Function: bcma_acl_detach 229 * 230 * Purpose: 231 * Remove any lists and free lock and control. 232 * 233 * Parameters: 234 * none 235 * 236 * Returns: 237 * BCM_E_NONE - Success 238 * BCM_E_INIT - ACL module not initialized 239 * BCM_E_XXX - from bcma_acl_remove() 240 */ 241 int 242 bcma_acl_detach(void) 243 { 244 _acl_control_t *control; 245 int retval = BCM_E_NONE, retval_temp; 246 247 LOG_DEBUG(BSL_LS_APPL_ACCESSCTRLLIST, 248 (BSL_META("ACL bcma_acl_detach()\n"))); 249 ACL_IS_INIT(); 250 251 control = _acl_control; 252 253 ACL_LOCK(); 254 255 /* Do hardware specific detach. */ 256 #ifdef BCM_FIELD_SUPPORT 257 retval_temp = _acl_field_detach(); 258 ACL_RETVAL_REPLACE(retval_temp, retval); 259 #endif /* BCM_FIELD_SUPPORT */ 260 261 /* Remove lists . */ 262 while (_acl_control->head.next != NULL && BCM_SUCCESS(retval)) { 263 retval_temp = bcma_acl_remove(_acl_control->head.next->list->list_id); 264 ACL_RETVAL_REPLACE(retval_temp, retval); 265 } 266 267 _acl_control = NULL; 268 269 ACL_UNLOCK(control); 270 271 sal_mutex_destroy(control->acl_lock); 272 sal_free(control); 273 274 return retval; 275 } 276 277 /* Section: List accessor functions. */ 278 279 /* 280 * Function: bcma_acl_add 281 * 282 * Purpose: 283 * Adds a new ACL to ACES. 284 * 285 * Parameters: 286 * list - pointer to ACL data 287 * 288 * Returns: 289 * BCM_E_NONE - Success 290 * BCM_E_INIT - ACL module not initialized 291 * BCM_E_EXISTS - Duplicate list ID already exists 292 * BCM_E_MEMORY - Allocation failure for list link. 293 */ 294 int 295 bcma_acl_add(bcma_acl_t *list) 296 { 297 _acl_link_t *list_link; 298 299 LOG_DEBUG(BSL_LS_APPL_ACCESSCTRLLIST, 300 (BSL_META("ACL bcma_acl_add()\n"))); 301 ACL_IS_INIT(); 302 303 if (list == NULL) { 304 LOG_ERROR(BSL_LS_APPL_ACCESSCTRLLIST, 305 (BSL_META("ACL Error: null list pointer in bcma_acl_add()\n"))); 306 return BCM_E_PARAM; 307 } 308 309 /* Confirm that list ID does not already exist. */ 310 if (_acl_find(list->list_id) != NULL) { 311 LOG_ERROR(BSL_LS_APPL_ACCESSCTRLLIST, 312 (BSL_META("ACL Error: List ID=%d already exists\n"), 313 list->list_id)); 314 return BCM_E_EXISTS; 315 } 316 317 /* Allocate a node for linked-list of ACLs and copy list. */ 318 list_link = _acl_link_alloc(); 319 if (list_link == NULL) { 320 LOG_ERROR(BSL_LS_APPL_ACCESSCTRLLIST, 321 (BSL_META("ACL Error: allocation failure for new list node.\n"))); 322 return BCM_E_MEMORY; 323 } 324 list_link->list = list; 325 326 /* Link the new list and add it to the linked-list. */ 327 ACL_LOCK(); 328 329 /* Test for no lists. */ 330 if (_acl_control->head.next == NULL) { 331 _acl_control->head.next = list_link; 332 list_link->prev = &_acl_control->head; 333 } else { 334 list_link->next = _acl_control->head.next; 335 /* Insert at head. */ 336 if (_acl_control->head.next != NULL) { 337 _acl_control->head.next->prev = list_link; 338 } 339 340 _acl_control->head.next = list_link; 341 list_link->prev = &_acl_control->head; 342 } 343 344 _acl_control->cur = list_link; 345 ACL_UNLOCK(_acl_control); 346 347 return BCM_E_NONE; 348 } 349 350 /* 351 * Function: bcma_acl_rule_add 352 * 353 * Purpose: 354 * Add a rule to a list of rules. 355 * 356 * Parameters: 357 * list_id - List ID 358 * *rule - rule to be added to List 359 * 360 * Returns: 361 * BCM_E_NONE - Success 362 * BCM_E_INIT - ACL module not initialized 363 * BCM_E_PARAM - NULL rule pointer. 364 * BCM_E_NOT_FOUND - List ID not found 365 * BCM_E_MEMORY - Allocation failure for rule. 366 * BCM_E_EXISTS - Rule ID already exists. 367 */ 368 int 369 bcma_acl_rule_add(bcma_acl_list_id_t list_id, bcma_acl_rule_t *rule) 370 { 371 _acl_link_t *list_link; 372 _acl_rule_link_t *rule_link_iter = NULL, 373 *rule_link = NULL; 374 375 LOG_DEBUG(BSL_LS_APPL_ACCESSCTRLLIST, 376 (BSL_META("ACL bcma_acl_rule_add(list_id=%d, rule=%p)\n"), 377 list_id, (void *)rule)); 378 ACL_IS_INIT(); 379 380 BCM_IF_ERROR_RETURN(_acl_rule_validate(rule)); 381 382 ACL_LOCK(); 383 /* Find the list to add this rule to. */ 384 list_link = _acl_find(list_id); 385 if (list_link == NULL) { 386 ACL_UNLOCK(_acl_control); 387 LOG_ERROR(BSL_LS_APPL_ACCESSCTRLLIST, 388 (BSL_META("ACL Error: List ID=%d not found\n"), 389 list_id)); 390 return BCM_E_NOT_FOUND; 391 } 392 393 if (_acl_rule_find(rule->rule_id) != NULL) { 394 ACL_UNLOCK(_acl_control); 395 LOG_ERROR(BSL_LS_APPL_ACCESSCTRLLIST, 396 (BSL_META("ACL Error: Rule ID=%d already exists\n"), 397 rule->rule_id)); 398 return BCM_E_EXISTS; 399 } 400 401 /* Make a copy of the input rule. */ 402 /* Create a rule link. */ 403 rule_link = _acl_rule_link_alloc(); 404 if (rule_link == NULL) { 405 ACL_UNLOCK(_acl_control); 406 LOG_ERROR(BSL_LS_APPL_ACCESSCTRLLIST, 407 (BSL_META("ACL Error: Allocation failure in _acl_rule_link_alloc()\n"))); 408 return BCM_E_MEMORY; 409 } 410 rule_link->rule = rule; 411 rule_link->next = NULL; 412 413 /* If list has no rules, add new rule link to the head. */ 414 if (list_link->rules == NULL) { 415 list_link->rules = rule_link; 416 ACL_UNLOCK(_acl_control); 417 LOG_DEBUG(BSL_LS_APPL_ACCESSCTRLLIST, 418 (BSL_META("ACL bcma_acl_rule_add() END\n"))); 419 return BCM_E_NONE; 420 } 421 422 /* Find the tail. */ 423 rule_link_iter = list_link->rules; 424 while (rule_link_iter->next != NULL) { 425 rule_link_iter = rule_link_iter->next; 426 } 427 428 /* Put new rule link at tail of linked-list */ 429 rule_link_iter->next = rule_link; 430 431 /* Make this the current rule (for iterator functions). */ 432 list_link->cur = rule_link; 433 434 ACL_UNLOCK(_acl_control); 435 436 LOG_DEBUG(BSL_LS_APPL_ACCESSCTRLLIST, 437 (BSL_META("ACL bcma_acl_rule_add() END\n"))); 438 return BCM_E_NONE; 439 } 440 441 #define _ACL_L4_MIN (0) 442 #define _ACL_L4_MAX ((1 << 16) - 1) 443 444 #define _ACL_L4_PORT_VALIDATE(_port_) \ 445 do { \ 446 if ((_port_) < _ACL_L4_MIN || _ACL_L4_MAX < (_port_)) { \ 447 LOG_ERROR(BSL_LS_APPL_ACCESSCTRLLIST, \ 448 (BSL_META("ACL Error: L4 port=%d out of range\n"), \ 449 (_port_))); \ 450 return BCM_E_PARAM; \ 451 } \ 452 } while (0) 453 454 /* 455 * Function: 456 * _acl_rule_validate 457 * 458 * Purpose: 459 * Confirms fields within the rule are in acceptible ranges. 460 * 461 * Parameters: 462 * rule - rule structure to be evaluated. 463 * 464 * Returns: 465 * BCM_E_NONE - Success 466 * BCM_E_PARAM - Out-of-range field(s) in rule 467 */ 468 STATIC int 469 _acl_rule_validate(const bcma_acl_rule_t *rule) 470 { 471 if (rule == NULL) { 472 LOG_ERROR(BSL_LS_APPL_ACCESSCTRLLIST, 473 (BSL_META("ACL Error: rule=NULL\n"))); 474 return BCM_E_PARAM; 475 } 476 477 _ACL_L4_PORT_VALIDATE(rule->src_port_min); 478 _ACL_L4_PORT_VALIDATE(rule->src_port_max); 479 _ACL_L4_PORT_VALIDATE(rule->dst_port_min); 480 _ACL_L4_PORT_VALIDATE(rule->dst_port_max); 481 482 return BCM_E_NONE; 483 } 484 #undef _ACL_L4_MIN 485 #undef _ACL_L4_MAX 486 #undef _ACL_L4_PORT_VALIDATE 487 488 /* 489 * Function: bcma_acl_rule_remove 490 * 491 * Purpose: 492 * Remove an rule from a list. 493 * 494 * Parameters: 495 * list_id - List ID where rule exists 496 * rule_id - Rule ID to be removed 497 * 498 * Returns: 499 * BCM_E_NONE - Success 500 * BCM_E_INIT - ACL module not initialized 501 * BCM_E_NOT_FOUND - List ID or Rule ID not found 502 */ 503 int 504 bcma_acl_rule_remove(bcma_acl_list_id_t list_id, bcma_acl_rule_id_t rule_id) 505 { 506 _acl_link_t *list_link; 507 _acl_rule_link_t *rule_link_cur, *rule_link_prev; 508 int retval = BCM_E_NONE; 509 510 LOG_DEBUG(BSL_LS_APPL_ACCESSCTRLLIST, 511 (BSL_META("ACL bcma_acl_rule_remove(list_id=%d, rule_id=%d)\n"), 512 list_id, rule_id)); 513 ACL_IS_INIT(); 514 515 ACL_LOCK(); 516 list_link = _acl_find(list_id); 517 518 if (list_link == NULL) { 519 ACL_UNLOCK(_acl_control); 520 LOG_ERROR(BSL_LS_APPL_ACCESSCTRLLIST, 521 (BSL_META("ACL Error: List ID=%d not found\n"), 522 list_id)); 523 return BCM_E_NOT_FOUND; 524 } 525 526 /* Traverse the list of rule links, looking for matching RID to remove. */ 527 for (rule_link_prev = NULL, rule_link_cur = list_link->rules; 528 rule_link_cur != NULL; 529 rule_link_prev = rule_link_cur, rule_link_cur = rule_link_cur->next) { 530 if (rule_link_cur->rule->rule_id == rule_id) { 531 /* Point around old rule_link */ 532 if (rule_link_prev == NULL) { 533 /* At head of list. */ 534 list_link->rules = rule_link_cur->next; 535 } else { 536 /* Somewhere within list. */ 537 rule_link_prev->next = rule_link_cur->next; 538 } 539 /* Remove the Rule ID from hardware. */ 540 #ifdef BCM_FIELD_SUPPORT 541 { 542 int retval_temp; 543 retval_temp = _acl_field_rule_remove(rule_id); 544 ACL_RETVAL_REPLACE(retval_temp, retval); 545 } 546 #endif /* BCM_FIELD_SUPPORT */ 547 548 /* Remove the rule_link from software. */ 549 sal_free(rule_link_cur); 550 ACL_UNLOCK(_acl_control); 551 return retval; 552 } 553 } 554 555 ACL_UNLOCK(_acl_control); 556 LOG_ERROR(BSL_LS_APPL_ACCESSCTRLLIST, 557 (BSL_META("ACL Error: Rule ID=%d not found in List ID=%d\n"), 558 rule_id, list_id)); 559 return BCM_E_NOT_FOUND; 560 } 561 562 /* 563 * Function: bcma_acl_rule_get 564 * 565 * Purpose: 566 * Accessor function to get a Rule 567 * 568 * Parameters: 569 * rule_id - Rule ID 570 * rule - (OUT) returned rule info 571 * 572 * Returns: 573 * BCM_E_NONE - Success 574 * BCM_E_INIT - ACL module not initialized 575 * BCM_E_PARAM - rule pointer is NULL 576 * BCM_E_NOT_FOUND - Rule ID not found 577 */ 578 int 579 bcma_acl_rule_get(bcma_acl_rule_id_t rule_id, bcma_acl_rule_t **rule) 580 { 581 _acl_rule_link_t *rule_link; 582 583 LOG_DEBUG(BSL_LS_APPL_ACCESSCTRLLIST, 584 (BSL_META("ACL bcma_acl_rule_get(rule_id=%d, rule=%p)\n"), 585 rule_id, (void *)rule)); 586 ACL_IS_INIT(); 587 588 if (*rule == NULL) { 589 LOG_ERROR(BSL_LS_APPL_ACCESSCTRLLIST, 590 (BSL_META("ACL Error: *rule is NULL\n"))); 591 return BCM_E_PARAM; 592 } 593 594 rule_link = _acl_rule_find(rule_id); 595 596 if (rule_link == NULL) { 597 LOG_ERROR(BSL_LS_APPL_ACCESSCTRLLIST, 598 (BSL_META("ACL Error: Rule ID=%d not found\n"), 599 rule_id)); 600 return BCM_E_NOT_FOUND; 601 } 602 603 *rule = rule_link->rule; 604 605 return BCM_E_NONE; 606 } 607 608 /* 609 * Function: bcma_acl_remove 610 * 611 * Purpose: 612 * Remove ACL from list of ACLs. This removes the Filter and Field entries 613 * used to support any rules in this list. Then it frees internal link 614 * memory used by ACL, including the rule links in the list. 615 * 616 * Parameters: 617 * list_id - List ID to be removed 618 * 619 * Returns: 620 * BCM_E_NONE - Success 621 * BCM_E_INIT - ACL module not initialized 622 * BCM_E_NOT_FOUND - List ID not found 623 */ 624 int 625 bcma_acl_remove(bcma_acl_list_id_t list_id) 626 { 627 _acl_link_t *link_cur; 628 int retval; 629 630 LOG_DEBUG(BSL_LS_APPL_ACCESSCTRLLIST, 631 (BSL_META("ACL bcma_acl_remove(list_id=%d)\n"), 632 list_id)); 633 ACL_IS_INIT(); 634 635 ACL_LOCK(); 636 link_cur = _acl_find(list_id); 637 if (link_cur == NULL) { 638 LOG_ERROR(BSL_LS_APPL_ACCESSCTRLLIST, 639 (BSL_META("ACL Error: List ID=%d not found\n"), 640 list_id)); 641 ACL_UNLOCK(_acl_control); 642 return BCM_E_NOT_FOUND; 643 } 644 645 /* Remove rules in list. */ 646 while (link_cur->rules != NULL) { 647 retval = bcma_acl_rule_remove(list_id, link_cur->rules->rule->rule_id); 648 if (BCM_FAILURE(retval)) { 649 ACL_UNLOCK(_acl_control); 650 return retval; 651 } 652 } 653 654 /* Remove the list link node itself. */ 655 if (link_cur->next != NULL) { 656 link_cur->next->prev = link_cur->prev; 657 } 658 link_cur->prev->next = link_cur->next; 659 sal_free(link_cur); 660 661 ACL_UNLOCK(_acl_control); 662 return BCM_E_NONE; 663 } 664 665 /* 666 * Function: bcma_acl_get 667 * 668 * Purpose: 669 * Accessor function for a ACL 670 * 671 * Parameters: 672 * list_id - List ID 673 * list - (OUT) returned list info 674 * 675 * Returns: 676 * BCM_E_NONE - Success 677 * BCM_E_INIT - ACL module not initialized 678 * BCM_E_PARAM - list pointer is NULL 679 * BCM_E_NOT_FOUND - List ID not found 680 */ 681 int 682 bcma_acl_get(bcma_acl_list_id_t list_id, bcma_acl_t *list) 683 { 684 _acl_link_t *list_link; 685 686 LOG_DEBUG(BSL_LS_APPL_ACCESSCTRLLIST, 687 (BSL_META("ACL bcma_acl_get(list_id=%d, list=%p)\n"), 688 list_id, 689 (void *)list)); 690 ACL_IS_INIT(); 691 692 if (list == NULL) { 693 LOG_ERROR(BSL_LS_APPL_ACCESSCTRLLIST, 694 (BSL_META("ACL Error: *list is NULL\n"))); 695 return BCM_E_PARAM; 696 } 697 698 list_link = _acl_find(list_id); 699 if (list_link == NULL) { 700 LOG_ERROR(BSL_LS_APPL_ACCESSCTRLLIST, 701 (BSL_META("ACL Error: List ID=%d not found\n"), 702 list_id)); 703 return BCM_E_NOT_FOUND; 704 } 705 706 sal_memcpy(list, &list_link->list, sizeof(bcma_acl_t)); 707 return BCM_E_NONE; 708 } 709 710 /* 711 * Function: 712 * _acl_control_find 713 * 714 * Purpose: 715 * Find a ACL control 716 * 717 * Parameters: 718 * 719 * Returns: 720 * pointer to _acl_control_t on success 721 * NULL on failure 722 */ 723 _acl_control_t * 724 _acl_control_find(void) { 725 return _acl_control; 726 } 727 728 /* 729 * Function: 730 * _acl_first 731 * 732 * Purpose: 733 * Return the first link in list of ACLs. Along with _acl_next(), 734 * it is meant to be used in a for() loop as the initializer. 735 * 736 * Parameters: 737 * *control - ACES control 738 * 739 * Returns: 740 * pointer to the first _acl_link_t structure. 741 * NULL on failure 742 */ 743 _acl_link_t * 744 _acl_first(_acl_control_t *control) { 745 assert(control != NULL); 746 assert(control != (_acl_control_t*)0xffffffff); 747 748 control->cur = control->head.next; 749 return control->cur; 750 } 751 /* 752 * Function: 753 * _acl_next 754 * 755 * Purpose: 756 * Return the next link in list of ACLs. 757 * 758 * Parameters: 759 * control - ACES control 760 * 761 * Returns: 762 * pointer to the first _acl_link_t structure. 763 * NULL at end of list 764 */ 765 766 _acl_link_t * 767 _acl_next(_acl_control_t *control) { 768 assert(control != NULL); 769 assert(control != (_acl_control_t*)0xffffffff); 770 assert(control->cur != NULL); 771 772 control->cur = control->cur->next; 773 return control->cur; 774 } 775 776 777 /* 778 * Function: 779 * _acl_find 780 * 781 * Purpose: 782 * Find an ACL given on its ID. 783 * 784 * Parameters: 785 * list_id - ACL identifier 786 * 787 * Returns: 788 * pointer to bcma_acl_struct on success 789 * NULL on failure 790 */ 791 STATIC _acl_link_t* 792 _acl_find(bcma_acl_list_id_t list_id) { 793 _acl_link_t *acl_iter; 794 795 acl_iter = _acl_control->head.next; 796 797 while (acl_iter != NULL) { 798 if (acl_iter->list->list_id == list_id) { 799 return acl_iter; 800 } 801 acl_iter = acl_iter->next; 802 } 803 804 return NULL; 805 } 806 807 /* 808 * Function: 809 * _acl_link_alloc 810 * 811 * Purpose: 812 * Allocates the space for a list node and performs a deep copy of input 813 * list. 814 * 815 * Parameters: 816 * list - pointer to Access Control List to add to ACL. 817 * 818 * Returns: 819 * pointer to _acl_link_t struct on success 820 * NULL on failure 821 */ 822 STATIC _acl_link_t* 823 _acl_link_alloc(void) { 824 _acl_link_t *list_link; 825 826 LOG_DEBUG(BSL_LS_APPL_ACCESSCTRLLIST, 827 (BSL_META("ACL _acl_link_alloc()\n"))); 828 list_link = sal_alloc(sizeof(_acl_link_t), "ACL list node"); 829 if (list_link == NULL) { 830 return list_link; 831 } 832 833 sal_memset(list_link, 0, sizeof(_acl_link_t)); 834 list_link->rules = NULL; 835 836 return list_link; 837 } 838 839 /* 840 * Function: 841 * _acl_rule_find 842 * 843 * Purpose: 844 * Find a rule link given an Rule ID. This searches all lists 845 * and returns the first rule link that has a matching rule ID. 846 * 847 * Parameters: 848 * rule_id - Rule identifier 849 * 850 * Returns: 851 * pointer to _acl_rule_link_t on success 852 * NULL on failure 853 */ 854 STATIC _acl_rule_link_t* 855 _acl_rule_find(bcma_acl_rule_id_t rule_id) { 856 _acl_link_t *list_link = NULL; 857 _acl_rule_link_t *rule_link = NULL; 858 859 /* Traverse the lists. */ 860 for (list_link = _acl_control->head.next; 861 list_link != NULL; 862 list_link = list_link->next) { 863 for (rule_link = list_link->rules; 864 rule_link != NULL; 865 rule_link = rule_link->next) { 866 if (rule_link->rule->rule_id == rule_id) { 867 break; 868 } 869 } 870 } 871 872 return rule_link; 873 } 874 875 /* 876 * Function: 877 * _acl_rule_first 878 * 879 * Purpose: 880 * Get the first rule in the list. This also moves the current rule pointer 881 * to the first rule. 882 * 883 * Parameters: 884 * list_link - Wrapper to ACL where rule is. 885 * 886 * Returns: 887 * pointer to _acl_rule_link_t on success 888 * NULL on failure 889 */ 890 bcma_acl_rule_t * 891 _acl_rule_first(_acl_link_t *list_link) 892 { 893 assert(list_link != NULL); 894 895 list_link->cur = list_link->rules; 896 897 if (list_link->cur != NULL) { 898 return list_link->rules->rule; 899 } 900 901 return NULL; 902 } 903 904 /* 905 * Function: 906 * _acl_rule_next 907 * 908 * Purpose: 909 * Get the next rule in the list. This also increments the current rule 910 * pointer. 911 * 912 * Parameters: 913 * list_link - Wrapper to ACL where rule is. 914 * 915 * Returns: 916 * pointer to _acl_rule_link_t on success 917 * NULL on failure 918 */ 919 bcma_acl_rule_t * 920 _acl_rule_next(_acl_link_t *list_link) 921 { 922 assert(list_link != NULL); 923 assert(list_link->cur != NULL); 924 925 list_link->cur = list_link->cur->next; 926 927 if (list_link->cur != NULL) { 928 return list_link->cur->rule; 929 } 930 931 return NULL; 932 } 933 934 _acl_rule_link_t * 935 _acl_rule_link_find(bcma_acl_rule_id_t rule_id) 936 { 937 _acl_link_t *acl_link; 938 _acl_rule_link_t *rule_link; 939 940 /* For each ACL */ 941 for (acl_link = _acl_first(_acl_control); 942 acl_link != NULL; 943 acl_link = _acl_next(_acl_control)) 944 { 945 /* For each rule_link in list...*/ 946 for (rule_link = acl_link->rules; 947 rule_link != NULL; 948 rule_link = rule_link->next) 949 { 950 if (rule_link->rule->rule_id == rule_id) { 951 return rule_link; 952 } 953 954 } 955 } 956 957 return NULL; 958 } 959 960 /* 961 * Function: 962 * _acl_rule_link_alloc 963 * 964 * Purpose: 965 * Allocate a rule link and copy the source rule data into it. 966 * 967 * Parameters: 968 * none 969 * 970 * Returns: 971 * pointer to newly allocated duplicate rule 972 * NULL on allocation failure 973 * 974 * Note: 975 * next pointer of copy is NULL 976 */ 977 STATIC _acl_rule_link_t * 978 _acl_rule_link_alloc(void) { 979 _acl_rule_link_t *rule_link; 980 981 LOG_DEBUG(BSL_LS_APPL_ACCESSCTRLLIST, 982 (BSL_META("ACL _acl_rule_link_alloc()\n"))); 983 rule_link = sal_alloc(sizeof(_acl_rule_link_t), "ACL rule link"); 984 if (rule_link == NULL) { 985 return NULL; 986 } 987 sal_memset(rule_link, 0, sizeof(_acl_rule_link_t)); 988 989 LOG_DEBUG(BSL_LS_APPL_ACCESSCTRLLIST, 990 (BSL_META("ACL _acl_rule_link_alloc() returning=%p\n"), 991 (void *)rule_link)); 992 return rule_link; 993 } 994 995 /* Section: Installation */ 996 /* 997 * Function: _acl_sort 998 * 999 * Purpose: 1000 * Sorting of link list of ACLs into descending ordr of priorities. This 1001 * is necessary because priority values can be changed by the client code. 1002 * Even if they're inserted in order, the priorities are not guarranteed 1003 * to be correct at install time. 1004 * 1005 * Parameters: 1006 * none 1007 * 1008 * Returns: 1009 * BCM_E_NONE - Success 1010 * BCM_E_MEMORY - Allocation failure 1011 */ 1012 STATIC int 1013 _acl_sort(void) 1014 { 1015 _acl_link_t *array; /* Array of links to be sorted. */ 1016 int count = 0; /* Number of ACLs. */ 1017 int idx; 1018 1019 /* Count the number of ACLs. */ 1020 for (_acl_control->cur = _acl_control->head.next, count = 0; 1021 _acl_control->cur != NULL; 1022 _acl_control->cur = _acl_control->cur->next, count++) { 1023 } 1024 1025 /* Create an array of pointers to _acl_link_t structures. */ 1026 array = (_acl_link_t*)sal_alloc(sizeof(_acl_link_t) * count, 1027 "ACL_sort_array"); 1028 if (array == NULL) { 1029 return BCM_E_MEMORY; 1030 } 1031 1032 /* Copy to the array for sorting */ 1033 _acl_control->cur = &_acl_control->head; 1034 for (idx = 0; idx < count; idx++) { 1035 assert(_acl_control->cur != NULL); 1036 sal_memcpy(&array[idx], _acl_control->cur->next, sizeof(_acl_link_t)); 1037 1038 /* We borrow the 'prev' pointer in the sorting array for 1039 * identifying the element 1040 */ 1041 array[idx].prev = _acl_control->cur->next; 1042 1043 _acl_control->cur = _acl_control->cur->next; 1044 } 1045 1046 /* Sort the array. */ 1047 _shr_sort(array, count, sizeof(_acl_link_t), _acl_cmp); 1048 1049 /* Rewire the linked list in sorted order. */ 1050 _acl_control->cur = &_acl_control->head; 1051 if (count) { 1052 /* 1053 * head->next should be set to the element with highest 1054 * priority after sorted. 1055 */ 1056 _acl_control->cur->next = array[0].prev; 1057 } 1058 1059 /* Re-construct the chain */ 1060 for (idx = 0; idx < count; idx++) { 1061 sal_memcpy(_acl_control->cur->next, &array[idx], sizeof(_acl_link_t)); 1062 if (idx == 0) { 1063 _acl_control->cur->next->prev = &_acl_control->head; 1064 } else { 1065 /* Remember we borrow the 'prev' to locate the actual element */ 1066 _acl_control->cur->next->prev = array[idx - 1].prev; 1067 } 1068 if (idx < count - 1) { 1069 /* Remember we borrow the 'prev' to locate the actual element */ 1070 _acl_control->cur->next->next = array[idx + 1].prev; 1071 } else { 1072 _acl_control->cur->next->next = NULL; 1073 } 1074 _acl_control->cur = _acl_control->cur->next; 1075 } 1076 1077 /* Destroy the array. */ 1078 sal_free(array); 1079 1080 LOG_DEBUG(BSL_LS_APPL_ACCESSCTRLLIST, 1081 (BSL_META("ACL END _acl_sort()\n"))); 1082 1083 return BCM_E_NONE; 1084 } 1085 1086 /* 1087 * Function: _acl_cmp 1088 * 1089 * Purpose: 1090 * Callback function for _shr_sort(). This compares two lists and returns 1091 * the usual Unix -1, 0, or +1 values. The only difference is that the -1 1092 * and +1 are reversed so the list will be arranged highest priority first. 1093 * 1094 * Parameters: 1095 * a - Pointer to first list link 1096 * b - Pointer to second list link 1097 * 1098 * Returns: 1099 * -1 - if A has higher priority than B 1100 * 0 - if A and B have equal priority 1101 * +1 - if B has higher priority than A 1102 */ 1103 STATIC int 1104 _acl_cmp(void *a, void *b) 1105 { 1106 _acl_link_t *list_first, *list_second; 1107 1108 list_first = (_acl_link_t*)a; 1109 list_second = (_acl_link_t*)b; 1110 1111 if (list_first->list->prio > list_second->list->prio) { 1112 return -1; 1113 } else if (list_first->list->prio < list_second->list->prio) { 1114 return 1; 1115 } 1116 1117 return 0; 1118 } 1119 1120 /* 1121 * Function: _acl_merge 1122 * 1123 * Purpose: 1124 * Build a solution ready to install in the hardware. The main purpose of 1125 * this is to test if the current set of ACLs will fit in hardware. 1126 * 1127 * Parameters: 1128 * 1129 * Returns: 1130 * BCM_E_NONE - Success 1131 * BCM_E_INIT - ACL module not initialized 1132 * BCM_E_RESOURCE - Insufficient hardware resources for current Lists. 1133 */ 1134 STATIC int 1135 _acl_merge(void) 1136 { 1137 int retval = BCM_E_NONE; 1138 1139 LOG_DEBUG(BSL_LS_APPL_ACCESSCTRLLIST, 1140 (BSL_META("ACL _acl_merge()\n"))); 1141 ACL_IS_INIT(); 1142 1143 ACL_LOCK(); 1144 1145 #ifdef BCM_FIELD_SUPPORT 1146 { 1147 int retval_temp; 1148 1149 retval_temp = _acl_field_merge(_acl_control); 1150 ACL_RETVAL_REPLACE(retval_temp, retval); 1151 } 1152 #endif /* BCM_FIELD_SUPPORT */ 1153 1154 ACL_UNLOCK(_acl_control); 1155 LOG_DEBUG(BSL_LS_APPL_ACCESSCTRLLIST, 1156 (BSL_META("ACL END _acl_merge()\n"))); 1157 1158 return retval; 1159 } 1160 1161 /* 1162 * Function: bcma_acl_install 1163 * 1164 * Purpose: 1165 * Write current ACL solution to hardware. Take working solution calculated 1166 * by _acl_merge() and commit it to hardware. This may be an expensive 1167 * operation if multiple rules must be shuffled to maintain atomicity. 1168 * 1169 * Parameters: 1170 * none 1171 * 1172 * Returns: 1173 * BCM_E_NONE - Success 1174 * BCM_E_INIT - ACL module not initialized 1175 * BCM_E_RESOURCE - Insufficient hardware resources to support current 1176 * Lists. 1177 * BCM_E_MEMORY - Allocation failure 1178 */ 1179 int 1180 bcma_acl_install(void) 1181 { 1182 int retval = BCM_E_NONE; 1183 1184 LOG_DEBUG(BSL_LS_APPL_ACCESSCTRLLIST, 1185 (BSL_META("ACL bcma_acl_install()\n"))); 1186 ACL_IS_INIT(); 1187 1188 ACL_LOCK(); 1189 1190 BCM_IF_ERROR_RETURN(bcma_acl_uninstall()); 1191 BCM_IF_ERROR_RETURN(_acl_sort()); 1192 BCM_IF_ERROR_RETURN(_acl_merge()); 1193 1194 #ifdef BCM_FIELD_SUPPORT 1195 { 1196 int retval_temp; 1197 retval_temp = _acl_field_install(); 1198 ACL_RETVAL_REPLACE(retval_temp, retval); 1199 } 1200 #endif /* BCM_FIELD_SUPPORT */ 1201 1202 ACL_UNLOCK(_acl_control); 1203 1204 return retval; 1205 } 1206 1207 /* 1208 * Function: bcma_acl_uninstall 1209 * 1210 * Purpose: 1211 * Remove the current set of ACLs from the hardware. 1212 * 1213 * Parameters: 1214 * 1215 * Returns: 1216 * BCM_E_NONE - Success 1217 * BCM_E_INIT - ACL module not initialized 1218 */ 1219 int 1220 bcma_acl_uninstall(void) 1221 { 1222 int retval = BCM_E_NONE; 1223 1224 LOG_DEBUG(BSL_LS_APPL_ACCESSCTRLLIST, 1225 (BSL_META("ACL bcma_acl_uninstall()\n"))); 1226 ACL_IS_INIT(); 1227 ACL_LOCK(); 1228 1229 #ifdef BCM_FIELD_SUPPORT 1230 { 1231 int retval_temp; 1232 retval_temp = _acl_field_uninstall(); 1233 ACL_RETVAL_REPLACE(retval_temp, retval); 1234 } 1235 #endif /* BCM_FIELD_SUPPORT */ 1236 1237 ACL_UNLOCK(_acl_control); 1238 return retval; 1239 } 1240 1241 /* 1242 * Function: acl_range_to_list 1243 * 1244 * Purpose: 1245 * Generate a mininal linked list of data/mask pairs that cover the 1246 * specified range. 1247 * 1248 * Parameters: 1249 * min - lower limit of range 1250 * max - upper limit of range 1251 * list - (OUT) pointer to head of list 1252 * count - (OUT) number of nodes in list 1253 * 1254 * Returns: 1255 * BCM_E_NONE - Success 1256 * BCM_E_MEMORY - Allocation failure. 1257 */ 1258 int 1259 acl_range_to_list(uint16 min, uint16 max, acl_node_t **list_p, int *count) { 1260 acl_node_t **list_temp; 1261 int idx; 1262 1263 if (list_p == NULL || count == NULL) { 1264 LOG_ERROR(BSL_LS_APPL_ACCESSCTRLLIST, 1265 (BSL_META("ACL Error: list or count is NULL\n"))); 1266 return BCM_E_PARAM; 1267 } 1268 LOG_DEBUG(BSL_LS_APPL_ACCESSCTRLLIST, 1269 (BSL_META("ACL acl_range_to_list(min=%d, max=%d)\n"), 1270 min, max)); 1271 *list_p = NULL; 1272 1273 *count = _acl_range_reduce(min, max, (acl_node_t **)NULL); 1274 1275 /* Allocate a temporary array of pointers to nodes. */ 1276 list_temp = (acl_node_t **)sal_alloc(*count * sizeof(acl_node_t *), 1277 "ACL temp_list"); 1278 if (list_temp == NULL) { 1279 return BCM_E_MEMORY; 1280 } 1281 sal_memset(list_temp, 0, *count * sizeof(acl_node_t *)); 1282 1283 /* Allocate nodes. */ 1284 for (idx = 0; idx < *count; idx++) { 1285 list_temp[idx] = (acl_node_t *)sal_alloc(sizeof(acl_node_t), 1286 "ACL range node"); 1287 sal_memset(list_temp[idx], 0, sizeof(acl_node_t)); 1288 if (list_temp[idx] == NULL) { 1289 return BCM_E_MEMORY; 1290 } 1291 1292 /* Link nodes into list. */ 1293 if (idx > 0) { 1294 list_temp[idx - 1]->next = list_temp[idx]; 1295 } 1296 } 1297 1298 *list_p = list_temp[0]; 1299 (void) _acl_range_reduce(min, max, list_temp); 1300 1301 sal_free(list_temp); 1302 1303 return BCM_E_NONE; 1304 } 1305 1306 /* 1307 * Function: 1308 * _acl_range_reduce 1309 * 1310 * Purpose: 1311 * Create a minimum set of data/mask nodes given a min and max range. 1312 * This function needs to be called twice. First it should be called with 1313 * list==NULL to establish the count. Then it should be called to fill 1314 * in the list array with data/mask nodes. 1315 * 1316 * Parameters: 1317 * min - lower limit of range 1318 * max - upper limit of range 1319 * list - (OUT) pointer to head of list of nodes 1320 * 1321 * Returns: 1322 * number of element data/mask nodes 1323 */ 1324 STATIC int 1325 _acl_range_reduce(uint16 min, uint16 max, acl_node_t **list) 1326 { 1327 int nentry; 1328 uint16 temp, mask; 1329 1330 nentry = 0; 1331 1332 while (min <= max) { 1333 /* count low order 0 bits in min */ 1334 if (min == 0) { 1335 mask = 0xffff; 1336 } else { 1337 for (temp = min, mask = 0; (temp & 1) == 0; temp >>= 1) { 1338 mask = (mask << 1) | 1; 1339 } 1340 } 1341 temp = (min & ~mask) | mask; 1342 if (temp <= max) { 1343 ; 1344 } else { 1345 while (temp > max) { 1346 mask >>= 1; 1347 temp = (min & ~mask) | mask; 1348 } 1349 } 1350 if (list) { 1351 list[nentry]->data = min; 1352 list[nentry]->mask = ~mask & 0xffff; 1353 } 1354 nentry += 1; 1355 if (temp >= max) { 1356 break; 1357 } 1358 min = temp + 1; 1359 } 1360 1361 return nentry; 1362 } 1363 1364 /* 1365 * Function: acl_range_destroy 1366 * 1367 * Purpose: 1368 * Deallocate memory used by previously allocated range list of nodes. 1369 * 1370 * Parameters: 1371 * list - pointer to head of list of nodes 1372 * count - number of nodes in list 1373 * 1374 * Returns: 1375 * BCM_E_NONE - Success 1376 * BCM_E_PARAM - null list or count is wrong 1377 */ 1378 int acl_range_destroy(acl_node_t *list, int count) { 1379 acl_node_t *node_cur = NULL; 1380 acl_node_t *node_prev = NULL; 1381 1382 if (list == NULL) { 1383 LOG_ERROR(BSL_LS_APPL_ACCESSCTRLLIST, 1384 (BSL_META("ACL Error: list is NULL\n"))); 1385 return BCM_E_PARAM; 1386 } 1387 1388 node_cur = list; 1389 while (count > 0) { 1390 node_prev = node_cur; 1391 if (node_prev == NULL) { 1392 LOG_ERROR(BSL_LS_APPL_ACCESSCTRLLIST, 1393 (BSL_META("ACL Error: count is wrong\n"))); 1394 return BCM_E_PARAM; 1395 } 1396 node_cur = node_prev->next; 1397 sal_free(node_prev); 1398 count--; 1399 } 1400 1401 /* Confirm that list is empty. */ 1402 if (node_cur != NULL) { 1403 LOG_ERROR(BSL_LS_APPL_ACCESSCTRLLIST, 1404 (BSL_META("ACL Error: count is wrong\n"))); 1405 return BCM_E_PARAM; 1406 } 1407 1408 return BCM_E_NONE; 1409 } 1410 1411 #ifdef BROADCOM_DEBUG 1412 /* 1413 * Function: bcma_acl_show 1414 * 1415 * Purpose: 1416 * Display access control lists currently in ACES. 1417 * 1418 * Parameters: 1419 * 1420 * Returns: 1421 * BCM_E_NONE - Success 1422 * BCM_E_XXX - return value from bcma_acl_list_show() 1423 */ 1424 int 1425 bcma_acl_show(void) 1426 { 1427 int retval = BCM_E_NONE; 1428 _acl_link_t *list_link; 1429 1430 LOG_DEBUG(BSL_LS_APPL_ACCESSCTRLLIST, 1431 (BSL_META("ACL bcma_acl_show()\n"))); 1432 ACL_IS_INIT(); 1433 1434 for (list_link = _acl_control->head.next; 1435 list_link != NULL; 1436 list_link = list_link->next) { 1437 BCM_IF_ERROR_RETURN(bcma_acl_list_show(list_link->list->list_id)); 1438 } 1439 1440 #ifdef BCM_FIELD_SUPPORT 1441 { 1442 int retval_temp; 1443 retval_temp = _acl_field_show(); 1444 ACL_RETVAL_REPLACE(retval_temp, retval); 1445 } 1446 #endif /* BCM_FIELD_SUPPORT */ 1447 1448 if (BCM_FAILURE(retval)) { 1449 LOG_ERROR(BSL_LS_APPL_ACCESSCTRLLIST, 1450 (BSL_META("ACL Error: Device specific acl_show() failed\n"))); 1451 return retval; 1452 } 1453 1454 return BCM_E_NONE; 1455 } 1456 1457 #define ACL_SHOW_RANGE(rule, name, flag) do { \ 1458 if ((rule)->flags & (flag)) { \ 1459 switch (flag) { \ 1460 case BCMA_ACL_RULE_L4_SRC_PORT: \ 1461 LOG_INFO(BSL_LS_APPL_ACCESSCTRLLIST, \ 1462 (BSL_META("%s=%d-%d, "), \ 1463 (name), (rule)->src_port_min, \ 1464 (rule)->src_port_max)); \ 1465 break; \ 1466 case BCMA_ACL_RULE_L4_DST_PORT: \ 1467 LOG_INFO(BSL_LS_APPL_ACCESSCTRLLIST, \ 1468 (BSL_META("%s=%d-%d, "), \ 1469 (name), (rule)->dst_port_min, \ 1470 (rule)->dst_port_max)); \ 1471 break; \ 1472 case BCMA_ACL_RULE_VLAN: \ 1473 LOG_INFO(BSL_LS_APPL_ACCESSCTRLLIST, \ 1474 (BSL_META("%s=%d-%d, "), \ 1475 (name), (rule)->vlan_min, \ 1476 (rule)->vlan_max)); \ 1477 break; \ 1478 } \ 1479 } \ 1480 } while (0) 1481 1482 #define ACL_SHOW_MAC(rule, name, mac_str, flag) do { \ 1483 if ((rule)->flags & (flag)) { \ 1484 if ((flag) == BCMA_ACL_RULE_SRC_MAC) { \ 1485 format_macaddr((mac_str), (rule)->src_mac); \ 1486 } else if (flag == BCMA_ACL_RULE_DST_MAC) { \ 1487 format_macaddr((mac_str), (rule->dst_mac)); \ 1488 } \ 1489 LOG_INFO(BSL_LS_APPL_ACCESSCTRLLIST, \ 1490 (BSL_META("%s=%s, "), \ 1491 (name), (mac_str))); \ 1492 } \ 1493 } while (0) 1494 1495 #define ACL_SHOW_IP(rule, name, str_p, flag) do { \ 1496 if ((rule)->flags & flag) { \ 1497 if (flag == BCMA_ACL_RULE_SRC_IP4) { \ 1498 format_ipaddr((str_p), (rule->src_ip)); \ 1499 LOG_INFO(BSL_LS_APPL_ACCESSCTRLLIST, \ 1500 (BSL_META("%s=%s, "), \ 1501 (name), (str_p))); \ 1502 format_ipaddr((str_p), (rule->src_ip_mask)); \ 1503 LOG_INFO(BSL_LS_APPL_ACCESSCTRLLIST, \ 1504 (BSL_META("%sMask=%s, "), \ 1505 (name), (str_p))); \ 1506 } \ 1507 if (flag == BCMA_ACL_RULE_DST_IP4) { \ 1508 format_ipaddr((str_p), (rule->dst_ip)); \ 1509 LOG_INFO(BSL_LS_APPL_ACCESSCTRLLIST, \ 1510 (BSL_META("%s=%s, "), \ 1511 (name), (str_p))); \ 1512 format_ipaddr((str_p), (rule->dst_ip_mask)); \ 1513 LOG_INFO(BSL_LS_APPL_ACCESSCTRLLIST, \ 1514 (BSL_META("%sMask=%s, "), \ 1515 (name), (str_p))); \ 1516 } \ 1517 if (flag == BCMA_ACL_RULE_SRC_IP6) { \ 1518 format_ip6addr((str_p), (rule->src_ip6)); \ 1519 LOG_INFO(BSL_LS_APPL_ACCESSCTRLLIST, \ 1520 (BSL_META("%s=%s,\n"), \ 1521 (name), (str_p))); \ 1522 format_ip6addr((str_p), (rule->src_ip6_mask)); \ 1523 LOG_INFO(BSL_LS_APPL_ACCESSCTRLLIST, \ 1524 (BSL_META("\t\t%sMask=%s, "), \ 1525 (name), (str_p))); \ 1526 } \ 1527 if (flag == BCMA_ACL_RULE_DST_IP6) { \ 1528 format_ip6addr((str_p), (rule->dst_ip6)); \ 1529 LOG_INFO(BSL_LS_APPL_ACCESSCTRLLIST, \ 1530 (BSL_META("%s=%s,\n"), \ 1531 (name), (str_p))); \ 1532 format_ip6addr((str_p), (rule->dst_ip6_mask)); \ 1533 LOG_INFO(BSL_LS_APPL_ACCESSCTRLLIST, \ 1534 (BSL_META("\t\t%sMask=%s, "), \ 1535 (name), (str_p))); \ 1536 } \ 1537 } \ 1538 } while (0) 1539 1540 #define ACL_SHOW_ETHERTYPE(rule, name) do { \ 1541 if ((rule)->flags & (BCMA_ACL_RULE_ETHERTYPE)) { \ 1542 LOG_INFO(BSL_LS_APPL_ACCESSCTRLLIST, \ 1543 (BSL_META("%s=0x%04x, "), \ 1544 (name), rule->ether_type)); \ 1545 } \ 1546 } while (0) 1547 1548 #define ACL_SEPARATOR(first_print) do { \ 1549 if ((first_print) == 1) { \ 1550 (first_print) = 0; \ 1551 } else { \ 1552 LOG_INFO(BSL_LS_APPL_ACCESSCTRLLIST, \ 1553 (BSL_META(", "))); \ 1554 } \ 1555 } while (0) 1556 1557 /* 1558 * Function: bcma_acl_list_show 1559 * 1560 * Purpose: 1561 * Display a single access control list. 1562 * 1563 * Parameters: 1564 * list_id - List ID 1565 * 1566 * Returns: 1567 * BCM_E_NONE - Success 1568 * BCM_E_NOT_FOUND - List ID not found 1569 * BCM_E_XXX - return value from bcma_acl_rule_show() 1570 */ 1571 int 1572 bcma_acl_list_show(bcma_acl_list_id_t list_id) 1573 { 1574 int count; 1575 bcmx_lport_t lport; 1576 _acl_link_t *list_link; 1577 _acl_rule_link_t *rule_link; 1578 int first_print = TRUE; 1579 1580 LOG_DEBUG(BSL_LS_APPL_ACCESSCTRLLIST, 1581 (BSL_META("ACL bcma_acl_list_show(list_id=%d)\n"), 1582 list_id)); 1583 ACL_IS_INIT(); 1584 1585 list_link = _acl_find(list_id); 1586 if (list_link == NULL) { 1587 LOG_ERROR(BSL_LS_APPL_ACCESSCTRLLIST, 1588 (BSL_META("ACL Error: list ID=%d not found\n"), 1589 list_id)); 1590 return BCM_E_NOT_FOUND; 1591 } 1592 LOG_INFO(BSL_LS_APPL_ACCESSCTRLLIST, 1593 (BSL_META("acl={id=%d, lplist={"), 1594 list_link->list->list_id)); 1595 1596 if ((BCMX_LPLIST_IS_EMPTY(&list_link->list->lplist))) { 1597 LOG_INFO(BSL_LS_APPL_ACCESSCTRLLIST, 1598 (BSL_META("None"))); 1599 } else { 1600 count = BCMX_LPLIST_COUNT(&list_link->list->lplist); 1601 BCMX_LPLIST_ITER(list_link->list->lplist, lport, count) { 1602 if (first_print == TRUE) { 1603 LOG_INFO(BSL_LS_APPL_ACCESSCTRLLIST, 1604 (BSL_META("%d"), 1605 lport)); 1606 first_print = FALSE; 1607 } else { 1608 LOG_INFO(BSL_LS_APPL_ACCESSCTRLLIST, 1609 (BSL_META(", %d"), 1610 lport)); 1611 } 1612 } 1613 } 1614 1615 LOG_INFO(BSL_LS_APPL_ACCESSCTRLLIST, 1616 (BSL_META("}"))); 1617 1618 for (rule_link = list_link->rules; 1619 rule_link != NULL; 1620 rule_link = rule_link->next) { 1621 LOG_INFO(BSL_LS_APPL_ACCESSCTRLLIST, 1622 (BSL_META("\n\t"))); 1623 BCM_IF_ERROR_RETURN(bcma_acl_rule_show(rule_link->rule)); 1624 LOG_INFO(BSL_LS_APPL_ACCESSCTRLLIST, 1625 (BSL_META(","))); 1626 } 1627 LOG_INFO(BSL_LS_APPL_ACCESSCTRLLIST, 1628 (BSL_META("\n}\n"))); 1629 1630 return BCM_E_NONE; 1631 } 1632 1633 char * 1634 _acl_ip_protocol_name(bcma_acl_ip_protocol_t ip_protocol) 1635 { 1636 return ip_protocol >= BCMA_ACL_IPPROTO_ANY ? 1637 "??" : bcma_acl_ip_protocol_text[ip_protocol]; 1638 } 1639 1640 /* 1641 * Function: bcma_acl_rule_show_id 1642 * 1643 * Purpose: 1644 * Display a single rule. 1645 * 1646 * Parameters: 1647 * rule_id - Rule ID 1648 * 1649 * Returns: 1650 * BCM_E_NONE - Success 1651 * BCM_E_NOT_FOUND - Rule ID not found 1652 */ 1653 int 1654 bcma_acl_rule_show_id(bcma_acl_rule_id_t rule_id) 1655 { 1656 _acl_rule_link_t *rule_link; 1657 1658 LOG_DEBUG(BSL_LS_APPL_ACCESSCTRLLIST, 1659 (BSL_META("ACL bcma_acl_rule_show_id(rule_id=%d)\n"), 1660 rule_id)); 1661 ACL_IS_INIT(); 1662 1663 rule_link = _acl_rule_find(rule_id); 1664 if (rule_link == NULL) { 1665 LOG_ERROR(BSL_LS_APPL_ACCESSCTRLLIST, 1666 (BSL_META("ACL Error: Rule ID=%d not found\n"), 1667 rule_id)); 1668 return BCM_E_NOT_FOUND; 1669 } 1670 1671 return bcma_acl_rule_show(rule_link->rule); 1672 } 1673 1674 /* 1675 * Function: bcma_acl_rule_show 1676 * 1677 * Purpose: 1678 * Display a single rule given a pointer to the rule struct. 1679 * 1680 * Parameters: 1681 * rule - pointer to rule structure to be displayed 1682 * 1683 * Returns: 1684 * BCM_E_NONE - Success 1685 * BCM_E_PARAM - rule pointer is NULL 1686 */ 1687 int 1688 bcma_acl_rule_show(bcma_acl_rule_t *rule) 1689 { 1690 char mac_str[MACADDR_STR_LEN + 3]; 1691 char ip4_str[IPADDR_STR_LEN + 3]; 1692 char ip6_str[IP6ADDR_STR_LEN + 3]; 1693 1694 LOG_DEBUG(BSL_LS_APPL_ACCESSCTRLLIST, 1695 (BSL_META("ACL bcma_acl_rule_show(rule=%p)\n"), 1696 (void *)rule)); 1697 ACL_IS_INIT(); 1698 1699 if (rule == NULL) { 1700 LOG_ERROR(BSL_LS_APPL_ACCESSCTRLLIST, 1701 (BSL_META("ACL Error: null rule passed to bcma_acl_rule_show()\n"))); 1702 return BCM_E_PARAM; 1703 } 1704 1705 LOG_DEBUG(BSL_LS_APPL_ACCESSCTRLLIST, 1706 (BSL_META("ACL bcma_acl_rule_show(rule_id=%d)\n"), 1707 rule->rule_id)); 1708 1709 LOG_INFO(BSL_LS_APPL_ACCESSCTRLLIST, 1710 (BSL_META("rule={id=%d, "), 1711 rule->rule_id)); 1712 1713 LOG_VERBOSE(BSL_LS_APPL_ACCESSCTRLLIST, 1714 (BSL_META("flags=0x%03x, "), 1715 rule->flags)); 1716 1717 /* Show L4 source and destination port ranges. */ 1718 ACL_SHOW_RANGE(rule, "SrcPort", BCMA_ACL_RULE_L4_SRC_PORT); 1719 ACL_SHOW_RANGE(rule, "DstPort", BCMA_ACL_RULE_L4_DST_PORT); 1720 1721 /* Show Source and Destination MAC addresses. */ 1722 ACL_SHOW_MAC(rule, "SrcMac", mac_str, BCMA_ACL_RULE_SRC_MAC); 1723 ACL_SHOW_MAC(rule, "DstMac", mac_str, BCMA_ACL_RULE_DST_MAC); 1724 1725 /* Show Source IPv4 address */ 1726 ACL_SHOW_IP(rule, "SrcIp4", ip4_str, BCMA_ACL_RULE_SRC_IP4); 1727 1728 /* Show Destination IPv4 address */ 1729 ACL_SHOW_IP(rule, "DstIp4", ip4_str, BCMA_ACL_RULE_DST_IP4); 1730 1731 /* Show Source and Destination IPv6 addresses & masks. */ 1732 ACL_SHOW_IP(rule, "SrcIp6", ip6_str, BCMA_ACL_RULE_SRC_IP6); 1733 ACL_SHOW_IP(rule, "DstIp6", ip6_str, BCMA_ACL_RULE_DST_IP6); 1734 1735 /* Show Vlan range. */ 1736 ACL_SHOW_RANGE(rule, "Vlan", BCMA_ACL_RULE_VLAN); 1737 1738 if (rule->ip_protocol != BCMA_ACL_IPPROTO_ANY) { 1739 LOG_INFO(BSL_LS_APPL_ACCESSCTRLLIST, 1740 (BSL_META("IpProtocol=%s (%d), "), 1741 _acl_ip_protocol_name(rule->ip_protocol), rule->ip_protocol)); 1742 } 1743 1744 /* Show EtherType. */ 1745 ACL_SHOW_ETHERTYPE(rule, "EtherType"); 1746 1747 bcma_acl_action_show(&rule->actions); 1748 LOG_INFO(BSL_LS_APPL_ACCESSCTRLLIST, 1749 (BSL_META("}"))); 1750 1751 return BCM_E_NONE; 1752 } 1753 1754 /* 1755 * Function: bcma_acl_action_show 1756 * 1757 * Purpose: 1758 * Display a set of actions for a rule. 1759 * 1760 * Parameters: 1761 * action - pointer to action structure to be displayed 1762 * 1763 * Returns: 1764 * BCM_E_NONE - Success 1765 * BCM_E_PARAM - action pointer is NULL 1766 */ 1767 int 1768 bcma_acl_action_show(bcma_acl_action_t *action) 1769 { 1770 uint8 first_print = 1; 1771 1772 LOG_DEBUG(BSL_LS_APPL_ACCESSCTRLLIST, 1773 (BSL_META("ACL bcma_acl_action_show(action=%p)\n"), 1774 (void *)action)); 1775 ACL_IS_INIT(); 1776 1777 if (action == NULL) { 1778 LOG_ERROR(BSL_LS_APPL_ACCESSCTRLLIST, 1779 (BSL_META("ACL Error: null action passed to bcma_acl_action_show()\n"))); 1780 return BCM_E_PARAM; 1781 } 1782 1783 LOG_DEBUG(BSL_LS_APPL_ACCESSCTRLLIST, 1784 (BSL_META("ACL bcma_acl_action_show(action=%p)\n"), 1785 (void *)action)); 1786 1787 LOG_INFO(BSL_LS_APPL_ACCESSCTRLLIST, 1788 (BSL_META("action={"))); 1789 LOG_VERBOSE(BSL_LS_APPL_ACCESSCTRLLIST, 1790 (BSL_META("flags=0x%x, "), 1791 action->flags)); 1792 if (action->flags & BCMA_ACL_ACTION_PERMIT) { 1793 LOG_INFO(BSL_LS_APPL_ACCESSCTRLLIST, 1794 (BSL_META("Permit"))); 1795 first_print = 0; 1796 } 1797 1798 if (action->flags & BCMA_ACL_ACTION_DENY) { 1799 ACL_SEPARATOR(first_print); 1800 LOG_INFO(BSL_LS_APPL_ACCESSCTRLLIST, 1801 (BSL_META("Deny"))); 1802 } 1803 1804 if (action->flags & BCMA_ACL_ACTION_LOG) { 1805 ACL_SEPARATOR(first_print); 1806 LOG_INFO(BSL_LS_APPL_ACCESSCTRLLIST, 1807 (BSL_META("Log"))); 1808 } 1809 1810 if (action->flags & BCMA_ACL_ACTION_REDIR) { 1811 ACL_SEPARATOR(first_print); 1812 LOG_INFO(BSL_LS_APPL_ACCESSCTRLLIST, 1813 (BSL_META("Redirect={lport=%d}"), 1814 action->redir_port)); 1815 } 1816 1817 if (action->flags & BCMA_ACL_ACTION_MIRROR) { 1818 ACL_SEPARATOR(first_print); 1819 LOG_INFO(BSL_LS_APPL_ACCESSCTRLLIST, 1820 (BSL_META("Mirror={lport=%d}"), 1821 action->mirror_port)); 1822 } 1823 1824 LOG_INFO(BSL_LS_APPL_ACCESSCTRLLIST, 1825 (BSL_META("}"))); 1826 return BCM_E_NONE; 1827 } 1828 #undef ACL_SEPARATOR 1829 1830 #endif /* BROADCOM_DEBUG */ 1831 #endif /* INCLUDE_ACL */ 1832