openbcm

Git mirror of https://github.com/Broadcom-Network-Switching-Software/OpenBCM
git clone git://git.finwo.net/mirror/broadcom/openbcm
Log | Files | Refs | README

acl.c (23904B)


      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  * Access Control Lists (ACL) related CLI commands.
      8  */
      9 
     10 #include <shared/bsl.h>
     11 #include <appl/diag/shell.h>
     12 #include <appl/diag/system.h>
     13 #include <appl/diag/parse.h>
     14 #include <appl/acl/acl.h>
     15 #include <appl/diag/diag.h>
     16 #include "../../acl/acl_util.h"
     17 
     18 #include <bcmx/lplist.h>
     19 #include <bcmx/lport.h>
     20 #include <bcmx/port.h>
     21 #include <bcm/error.h>
     22 
     23 #include "bcmx.h"
     24 
     25 #if defined(INCLUDE_ACL)
     26 
     27 #define BCMA_ACL_NUMB_LISTS  16 /* Max. number of lists in diag. code. */
     28 #define BCMA_ACL_NUMB_RULES  16 /* Max. number of rules in each list.  */
     29 
     30 /*
     31  * Macro:
     32  *     ACL_CHECK_RETURN
     33  * Purpose:
     34  *     Check the return value from an API call. Output either a failed
     35  *     message or okay along with the function name.
     36  */
     37 #define ACL_CHECK_RETURN(retval, funct_name) \
     38     if ((retval) != BCM_E_NONE) { \
     39         cli_out("%s() failed: %s\n", (funct_name), bcm_errmsg(retval)); \
     40         return CMD_FAIL; \
     41     } \
     42     cli_out("%s() okay\n", (funct_name));
     43 
     44 /*
     45  * Macro:
     46  *     ACL_GET_NUMB
     47  * Purpose:
     48  *     Get a numerical value from stdin.
     49  */
     50 #define ACL_GET_NUMB(numb, str, args) \
     51     if (((str) = ARG_GET(args)) == NULL) { \
     52         return CMD_USAGE; \
     53     } \
     54     (numb) = parse_integer(str);
     55 
     56 /*
     57  * Macro:
     58  *     ACL_GET_PORT
     59  * Purpose:
     60  *     Get a numerical value from stdin.
     61  */
     62 #define ACL_GET_PORT(_unit, _port, _str, _args)                   \
     63     if (((_str) = ARG_GET(_args)) == NULL) {                     \
     64         return CMD_USAGE;                                        \
     65     }                                                            \
     66     if (parse_port((_unit), (_str), &(_port)) < 0) {             \
     67        ACL_ERR(("ERROR: invalid port string: \"%s\"\n", (_str))); \
     68        return CMD_FAIL;                                          \
     69     }
     70 
     71 #define MAC_IS_CLEAR(mac)                                                 \
     72 ((mac)[5] == 0 && (mac)[4] == 0 && (mac)[3] == 0 && (mac)[2] == 0 &&      \
     73  (mac)[1] == 0 && (mac)[0] == 0  ? TRUE : FALSE)
     74 
     75 #define IP6_IS_CLEAR(ip6)                                                 \
     76 ((ip6)[15] == 0 && (ip6)[14] == 0 && (ip6)[13] == 0 && (ip6)[12] == 0 &&  \
     77  (ip6)[11] == 0 && (ip6)[10] == 0 && (ip6)[ 9] == 0 && (ip6)[ 8] == 0 &&  \
     78  (ip6)[ 7] == 0 && (ip6)[ 6] == 0 && (ip6)[ 5] == 0 && (ip6)[ 4] == 0 &&  \
     79  (ip6)[ 3] == 0 && (ip6)[ 2] == 0 && (ip6)[ 1] == 0 && (ip6)[ 0] == 0     \
     80   ? TRUE : FALSE)
     81 
     82 
     83 /*
     84  * Marker for last element in qualification table 
     85  */
     86 #define ACL_TABLE_END_STR "tbl_end"
     87 
     88 #define ACL_STAT_STR_SZ 256
     89 
     90 /*
     91  * local typedefs
     92  */
     93 
     94 typedef struct cmd_acl_list_s {
     95     bcma_acl_t          list;
     96     bcma_acl_rule_t     *rules[BCMA_ACL_NUMB_RULES];
     97 } cmd_acl_list_t;
     98 
     99 
    100 cmd_acl_list_t *acl_lists[BCMA_ACL_NUMB_LISTS];
    101 
    102 
    103 /*
    104  * local function prototypes
    105  */
    106 cmd_result_t bcmx_cmd_aclcreate(int unit, args_t *args) ;
    107 cmd_result_t bcmx_cmd_acldetach(int unit, args_t *args) ;
    108 cmd_result_t bcmx_cmd_aclinit(int unit, args_t *args);
    109 cmd_result_t bcmx_cmd_aclinstall(int unit, args_t *args);
    110 cmd_result_t bcmx_cmd_acluninstall(int unit, args_t *args);
    111 
    112 #ifdef BROADCOM_DEBUG
    113 cmd_result_t bcmx_cmd_aclshow(int unit, args_t *args) ;
    114 #endif /*BROADCOM_DEBUG*/
    115 
    116 cmd_result_t bcmx_cmd_acl_list(int unit, args_t *args);
    117 cmd_result_t bcmx_cmd_acl_list_create(int unit, args_t *args);
    118 cmd_result_t bcmx_cmd_acl_list_destroy(int unit, args_t *args);
    119 
    120 cmd_result_t bcmx_cmd_aclrule(int unit, args_t *args);
    121 
    122 STATIC void _cmd_acl_list_destroy(cmd_acl_list_t *list);
    123 STATIC bcma_acl_t *_cmd_acl_list_alloc(bcma_acl_list_id_t list_id);
    124 STATIC int _bcmx_acl_rule_id_get(void);
    125 int _bcmx_acl_rule_add(bcma_acl_list_id_t list_id, bcma_acl_rule_t *rule);
    126 STATIC bcma_acl_rule_t * _bcmx_acl_rule_alloc(void);
    127 
    128 #define BCMA_ACL_LIST_NUMB 4
    129 
    130 static int acl_init_flg = FALSE;
    131 static int list_id_cur, list_id_max;
    132 static int rule_id_max;
    133 
    134 char bcmx_cmd_acl_usage[] =
    135 #ifdef COMPILER_STRING_CONST_LIMIT
    136 "Parameters: [acl_id] <cmd> <opt>\n"
    137 #else /* !COMPILER_STRING_CONST_LIMIT */
    138 "Parameters: [acl_id] <cmd> <opt>\n"
    139 " Where <cmd> is:\n"
    140 "\tlist  create  <list_id> <user-port-list>\t- Create an ACL on a set of ports\n"
    141 "\t      destroy id=<list_id>\n"
    142 "\trule {Permit=<T/F>|Deny=<T/F>|Log=<T/F>}\n"
    143 "\t       [RedirPort=<user-port>] [MirrorPort=<user-port>]\n"
    144 "\t       [SrcMac=<val>] [DstMac=<val>]\n"
    145 "\t       [SrcIp=<val>]  [SrcIpMask=<val>]  [DstIp=<val>]  [DstIpMask=<val>]\n"
    146 "\t       [SrcIp6=<val>] [SrcIp6Mask=<val>] [DstIp6=<val>] [DstIp6Mask=<val>]\n"
    147 "\t       [SrcPortMIn=<val>] [SrcPortMAx=<val>]\n"
    148 "\t       [DstPortMIn=<val>] [DstPortMAx=<val>]\n"
    149 "\t       [VlanMIn=<id>] [VlanMAx=<id>\n"
    150 "\t       [IpProtocol=<protocol>] [EtherType=<type>\n"
    151 "\tdetach\n"
    152 "\tinit\n"
    153 "\tinstall\n"
    154 "\tuninstall\n"
    155 "\tshow\n"
    156 #endif /* !COMPILER_STRING_CONST_LIMIT */
    157 ;
    158 
    159 static cmd_t acl_cmd_list[] = {
    160     {"Init", bcmx_cmd_aclinit,
    161      "acl init",
    162      "Initialize ACL"},
    163 
    164     {"Detach",  bcmx_cmd_acldetach,
    165      "acl detach",
    166      "Detach ACL"},
    167 
    168     {"Rule",   bcmx_cmd_aclrule,
    169      "acl rule {Permit|Deny|Redirect|Log}",
    170      "Specify an access control list rule"},
    171 
    172     {"List", bcmx_cmd_acl_list,
    173      "acl list {create | destroy}",
    174      "Create or destroy access control list"},
    175 
    176 #ifdef BROADCOM_DEBUG
    177     {"Show", bcmx_cmd_aclshow,
    178      "acl show",
    179      "Show an access control list" },
    180 #endif /* BROADCOM_DEBUG */
    181 
    182     {"Install", bcmx_cmd_aclinstall,
    183      "acl install",
    184      "Install the ACL lists in harware"},
    185 
    186     {"Uninstall", bcmx_cmd_acluninstall,
    187      "acl uninstall",
    188      "Remove the ACL lists from harware"}
    189 };
    190 
    191 static cmd_t acl_list_cmd_list[] = {
    192     {"Create", bcmx_cmd_acl_list_create,
    193      "acl list create",
    194      "Create an ACL list" },
    195 
    196      {"Destroy",  bcmx_cmd_acl_list_destroy,
    197      "acl list destroy",
    198      "destroy an ACL list" }
    199 };
    200 
    201 static
    202 char *bcma_acl_ip_protocol_text[256] = {
    203     "0",     "ICMP",  "IGMP",  "GGP",     "IP",     "ST",    "TCP",  "UCL",
    204     "EGP",    "IGP",    "10",   "11",     "PUP", "ARGUS",  "EMCON", "XNET",
    205     "CHAOS",  "UDP",   "MUX",   "19",     "HMP",   "PRM",     "22",   "23",
    206     "24",   "LEAF1", "LEAF2",  "RDP",     "IRTP",   "29", "NETBLT",   "31",
    207     "32",     "SEP",   "3PC", "IDRP",     "XTP",   "DDP",     "38", "TP++",
    208     "IL",     "SIP",  "SDRP",   "43",     "44",   "IDRP",   "RSVP",  "GRE",
    209     "48",      "49",    "50",   "51",     "52",     "53",     "54",   "55",
    210 };
    211 
    212 /* Section: top level commands */
    213 
    214 /*
    215  * Function:
    216  *      bcmx_cmd_acl
    217  * Purpose:
    218  *      Access Control List CLI interface
    219  * Parameters:
    220  *      unit - SOC unit #
    221  *      args - pointer to command line arguments      
    222  * Returns:
    223  *    CMD_OK
    224  */
    225 cmd_result_t
    226 bcmx_cmd_acl(int unit, args_t *args) {
    227     char            *initial_cmd = ARG_CMD(args);
    228     char            *key;
    229     cmd_t           *cmd;
    230     char            *param;
    231     cmd_result_t    retval = CMD_OK;
    232 
    233     if ((key = ARG_GET(args)) == NULL) {
    234         sal_printf("%s:  Subcommand required\n", initial_cmd);
    235         return CMD_USAGE;
    236     }
    237 
    238     if (isint(key)) {
    239         list_id_cur = parse_integer(key);
    240         if ((key = ARG_GET(args)) == NULL) {
    241             sal_printf("%s:  Subcommand required\n", initial_cmd);
    242             return CMD_USAGE;
    243         }
    244     }
    245 
    246     cmd = (cmd_t *) parse_lookup(key, acl_cmd_list, sizeof(cmd_t), 
    247                                  COUNTOF(acl_cmd_list));
    248 
    249     if (cmd == NULL)
    250     {
    251         sal_printf("%s: Unknown subcommand %s\n", initial_cmd, key);
    252         return CMD_USAGE;
    253     }
    254 
    255     /* If next param is "?", just display help for command */    
    256     param = ARG_CUR(args);
    257     if (param != NULL) {
    258         if (sal_strcmp(param, "?") == 0)
    259         {
    260             ARG_GET(args);    /* Consume "?" */
    261             if ((cmd->c_usage != NULL) &&
    262                 (soc_property_get(unit, spn_HELP_CLI_ENABLE, 1))) {
    263                 sal_printf("Usage:  %s\n", cmd->c_usage);
    264             }
    265             if ((cmd->c_help != NULL) && 
    266                 (soc_property_get(unit, spn_HELP_CLI_ENABLE, 1))){
    267                 sal_printf("Help :  %s\n", cmd->c_help);
    268             }
    269             return retval;
    270         }
    271     }
    272 
    273     return cmd->c_f(unit, args);
    274 }
    275 
    276 
    277 /* Section: 2nd level commands */
    278 
    279 /*
    280  * Function: bcmx_cmd_acldetach
    281  *
    282  * Purpose:
    283  *
    284  * Parameters:
    285  *
    286  * Returns:
    287  */
    288 cmd_result_t
    289 bcmx_cmd_acldetach(int unit, args_t *args) {
    290     int                 retval;
    291     int                 idx;
    292 
    293     /* Do the actual ACL detach. */
    294     retval = bcma_acl_detach();
    295     ACL_CHECK_RETURN(retval, "bcma_acl_detach");
    296 
    297     /* Get rid of any locally allocated lists. */
    298     for (idx = 0; idx < BCMA_ACL_NUMB_LISTS; idx++) {
    299         if (acl_lists[idx] != NULL) {
    300             _cmd_acl_list_destroy(acl_lists[idx]);
    301             acl_lists[idx] = NULL;
    302         }
    303     }
    304 
    305     acl_init_flg = FALSE;
    306 
    307     return CMD_OK;
    308 }
    309 
    310 /*
    311  * Function: _cmd_acl_list_destroy
    312  *
    313  * Purpose:
    314  *     free any locally allocated ACL lists, including all rules in list.
    315  *
    316  * Parameters:
    317  *
    318  * Returns:
    319  */
    320 STATIC void
    321 _cmd_acl_list_destroy(cmd_acl_list_t *cmd_list)
    322 {
    323     int                 idx;
    324 
    325     assert(cmd_list != NULL);
    326 
    327     for (idx = 0; idx < BCMA_ACL_NUMB_RULES; idx++) {
    328         if (cmd_list->rules[idx] != NULL) {
    329             bcma_acl_rule_remove(cmd_list->list.list_id, cmd_list->rules[idx]->rule_id);
    330             sal_free(cmd_list->rules[idx]);
    331             cmd_list->rules[idx] = NULL;
    332         }
    333     }
    334     sal_free(cmd_list);
    335 }
    336 
    337 /*
    338  * Function: bcmx_cmd_aclinit
    339  *
    340  * Purpose:
    341  *
    342  * Parameters:
    343  *
    344  * Returns:
    345  */
    346 cmd_result_t
    347 bcmx_cmd_aclinit(int unit, args_t *args) {
    348     int                idx;
    349 
    350     /* Clean up first, if previously initialized. */
    351     if (acl_init_flg == TRUE) {
    352         /* Get rid of any locally allocated lists. */
    353         for (idx = 0; idx < BCMA_ACL_NUMB_LISTS; idx++) {
    354             if (acl_lists[idx] != NULL) {
    355                 _cmd_acl_list_destroy(acl_lists[idx]);
    356                 acl_lists[idx] = NULL;
    357             }
    358         }
    359     }
    360 
    361     /* Zero out local list data. */
    362     sal_memset(acl_lists, 0, sizeof(cmd_acl_list_t*) * BCMA_ACL_NUMB_LISTS);
    363     list_id_cur = list_id_max = 1;
    364     rule_id_max = 1;
    365 
    366     /* Initialize the ACL module itself. */ 
    367     bcma_acl_init();
    368     acl_init_flg = TRUE;
    369     return CMD_OK;
    370 }
    371 
    372 /*
    373  * Function: bcmx_cmd_aclinstall
    374  *
    375  * Purpose:
    376  *
    377  * Parameters:
    378  *
    379  * Returns:
    380  */
    381 cmd_result_t
    382 bcmx_cmd_aclinstall(int unit, args_t *args) {
    383     int                 retval;
    384 
    385     retval = bcma_acl_install();
    386     ACL_CHECK_RETURN(retval, "bcma_acl_install");
    387 
    388     return CMD_OK;
    389 }
    390 /*
    391  * Function: bcmx_cmd_acluninstall
    392  *
    393  * Purpose:
    394  *
    395  * Parameters:
    396  *
    397  * Returns:
    398  */
    399 cmd_result_t
    400 bcmx_cmd_acluninstall(int unit, args_t *args) {
    401     int                 retval;
    402 
    403     retval = bcma_acl_uninstall();
    404     ACL_CHECK_RETURN(retval, "bcma_acl_install");
    405 
    406     return CMD_OK;
    407 }
    408 
    409 
    410 #ifdef BROADCOM_DEBUG
    411 /*
    412  * Function: bcmx_cmd_aclshow
    413  *
    414  * Purpose:
    415  *
    416  * Parameters:
    417  *
    418  * Returns:
    419  */
    420 cmd_result_t
    421 bcmx_cmd_aclshow(int unit, args_t *args) {
    422     int                 retval;
    423     char                *subcmd = NULL;
    424 
    425     if ((subcmd = ARG_GET(args)) == NULL) {
    426         /* If no List ID specified, show all lists. */
    427         retval = bcma_acl_show();
    428         ACL_CHECK_RETURN(retval, "bcma_acl_show");
    429         return CMD_OK;
    430     }
    431 
    432     /* Use the command line List ID. */
    433     if (!isint(subcmd)) {
    434         return CMD_USAGE;
    435     }
    436 
    437     retval = bcma_acl_list_show(parse_integer(subcmd));
    438     ACL_CHECK_RETURN(retval, "bcma_acl_list_show");
    439 
    440     return CMD_OK;
    441 }
    442 #endif /*BROADCOM_DEBUG*/
    443 
    444 
    445 /* Section: List Commands {Create | Destroy} */
    446 cmd_result_t
    447 bcmx_cmd_acl_list(int unit, args_t *args) {
    448     return subcommand_execute(unit, args, 
    449                               acl_list_cmd_list, 
    450                               COUNTOF(acl_list_cmd_list));
    451 }
    452 
    453 /*
    454  * Function: bcmx_cmd_acl_list_create
    455  *
    456  * Purpose:
    457  *    CLI handler to create an ACL list.
    458  *
    459  * Parameters:
    460  *
    461  * Returns:
    462  *     CMD_OK - Success
    463  *     CMD_FAIL - could not initialize port list or list add failure.
    464  *     CMD_USAGE - improper CLI
    465  */
    466 cmd_result_t
    467 bcmx_cmd_acl_list_create(int unit, args_t *args) {
    468     bcma_acl_list_id_t  list_id = list_id_max + 1;
    469     bcma_acl_t          *list_p;
    470     char                *str;
    471 
    472     /* Read the List ID. */
    473     str = ARG_GET(args);
    474     if (str) {
    475         list_id = parse_integer(str);
    476     } else {
    477         return CMD_USAGE;
    478     }
    479 
    480     list_p = _cmd_acl_list_alloc(list_id);
    481     if (list_p == NULL) {
    482         cli_out("ACL: list ID=%d allocation failure\n", list_id);
    483         return CMD_FAIL;
    484     }
    485 
    486     /* Read the user port list. */
    487     str = ARG_GET(args);
    488     if (str) {
    489         if (BCM_FAILURE(bcmx_lplist_parse(&list_p->lplist, str))) {
    490             cli_out("Can't parse UserPortList \"%s\"\n", str);
    491             return CMD_USAGE;
    492         }
    493         /* Read the priority */
    494         str = ARG_GET(args);
    495         list_p->prio = (str) ? parse_integer(str) : 0;
    496     } else {
    497        bcmx_port_lplist_populate(&list_p->lplist, BCMX_PORT_LP_ALL);
    498     }
    499 
    500     list_id_cur    = list_id;
    501     list_p->list_id    = list_id;
    502 
    503     if (BCM_FAILURE(bcma_acl_add(list_p))) {
    504         return CMD_FAIL;
    505     }
    506 
    507     cli_out("ACL: list ID=%d created\n", list_id);
    508 
    509     return CMD_OK;
    510 }
    511 
    512 /*
    513  * Function: _cmd_acl_list_alloc
    514  *
    515  * Purpose:
    516  *     Allocate a command list struct from local array
    517  *
    518  * Parameters:
    519  *     none
    520  *
    521  * Returns:
    522  *     pointer to bcma_acl_t list
    523  *     or
    524  *     NULL on allocation failure
    525  */
    526 STATIC bcma_acl_t *
    527 _cmd_acl_list_alloc(bcma_acl_list_id_t list_id)
    528 {
    529     int                 idx;
    530     cmd_acl_list_t      *list = NULL;
    531 
    532     /* Find an unused slot in acl_list array. */
    533     for (idx = 0; idx < BCMA_ACL_NUMB_LISTS; idx++) {
    534         if (acl_lists[idx] == NULL) {
    535             /* Allocate the cmd_list struct. */
    536             list = sal_alloc(sizeof(cmd_acl_list_t), "CMD ACL");
    537             if (list == NULL) {
    538                 return NULL;
    539             }
    540             /* Put it in acl_list array. */
    541             acl_lists[idx] = list;
    542 
    543             /* Zero out cmd_list struct. */
    544             sal_memset(list, 0, sizeof(cmd_acl_list_t));
    545 
    546             bcmx_lplist_init(&list->list.lplist, 0, 0);
    547 	    list->list.list_id = list_id;
    548 
    549             /* Return pointer to bcma_acl_t list. */
    550             return &list->list;
    551 	}
    552     }
    553 
    554     /* Return pointer to bcma_acl_t list. */
    555     return NULL;
    556 }
    557 
    558 cmd_result_t
    559 bcmx_cmd_acl_list_destroy(int unit, args_t *args) {
    560     parse_table_t       pt;
    561     cmd_result_t     retval;
    562     bcma_acl_list_id_t   list_id;
    563 
    564     parse_table_init(unit, &pt);
    565     parse_table_add(&pt, "id", PQ_DFL | PQ_INT, 0,
    566                     (void *)&list_id, 0);
    567 
    568     if(!parseEndOk(args, &pt, &retval)) {
    569         return CMD_USAGE;
    570     }
    571 
    572     if (BCM_FAILURE(bcma_acl_remove(list_id))) {
    573         cli_out("ACL: failed to destroy list ID=%d \n", list_id);
    574         return CMD_FAIL;
    575     }
    576 
    577     cli_out("ACL: List ID=%d destroyed\n", list_id);
    578 
    579     return CMD_OK;
    580 }
    581 
    582 /* Section: rule Commands {Create | Destroy} */
    583 
    584 STATIC int
    585 _bcmx_acl_rule_id_get(void) {
    586     int                 rule_id; /* output */
    587 
    588     rule_id_max++;
    589     rule_id     = rule_id_max;
    590     
    591     return rule_id;
    592 }
    593 
    594 /*
    595  * Function: bcmx_cmd_aclrule
    596  *
    597  * Purpose:
    598  *    Create a list rule.
    599  *
    600  * Parameters:
    601  *
    602  * Returns:
    603  */
    604 cmd_result_t
    605 bcmx_cmd_aclrule(int unit, args_t *args) {
    606     bcma_acl_rule_t     *rule;
    607     parse_table_t       pt;
    608     cmd_result_t        retval;
    609     uint32              permit_flag=0, deny_flag=0, log_flag=0;
    610     char                *redir_port_str = NULL;
    611     char                *mirror_port_str = NULL;
    612     bcmx_lport_t        lport;
    613     bcmx_uport_t        uport;
    614     uint32              vlan_min = 0, vlan_max = 0;
    615     uint32              ethertype = 0;
    616 
    617     LOG_DEBUG(BSL_LS_APPL_ACCESSCTRLLIST,
    618               (BSL_META_U(unit,
    619                           "BEGIN bcmx_cmd_aclrule()\n")));
    620 
    621     rule = _bcmx_acl_rule_alloc();
    622     if (rule == NULL) {
    623         return CMD_FAIL;
    624     }
    625 
    626     rule->rule_id             = _bcmx_acl_rule_id_get() ;
    627     rule->ip_protocol         = BCMA_ACL_IPPROTO_ANY;
    628     rule->actions.redir_port  = -1;
    629     rule->actions.mirror_port = -1;
    630 
    631     parse_table_init(unit, &pt);
    632 
    633     /* Actions */
    634     parse_table_add(&pt, "Permit", PQ_DFL | PQ_NO_EQ_OPT | PQ_BOOL, 0,
    635                     (void *)&permit_flag, 0);
    636     parse_table_add(&pt, "Deny",   PQ_DFL | PQ_NO_EQ_OPT | PQ_BOOL, 0,
    637                     (void *)&deny_flag, 0);
    638     parse_table_add(&pt, "Log",    PQ_DFL | PQ_NO_EQ_OPT | PQ_BOOL, 0,
    639                     (void *)&log_flag, 0);
    640 
    641     parse_table_add(&pt, "RedirPort", PQ_DFL | PQ_STRING, 0,
    642                     (void *)&redir_port_str, NULL);
    643     parse_table_add(&pt, "MirrorPort", PQ_DFL | PQ_STRING, 0,
    644                     (void *)&mirror_port_str, NULL);
    645 
    646     /* Matching parameters */
    647     parse_table_add(&pt, "SrcMac", PQ_DFL | PQ_MAC, 0,
    648                     (void *)&rule->src_mac, 0);
    649     parse_table_add(&pt, "DstMac", PQ_DFL | PQ_MAC, 0,
    650                     (void *)&rule->dst_mac, 0);
    651 
    652     parse_table_add(&pt, "SrcIp", PQ_DFL | PQ_IP, 0,
    653                     (void *)&rule->src_ip, 0);
    654     parse_table_add(&pt, "SrcIpMask", PQ_DFL | PQ_IP, 0,
    655                     (void *)&rule->src_ip_mask, 0);
    656     parse_table_add(&pt, "DstIp", PQ_DFL | PQ_IP, 0,
    657                     (void *)&rule->dst_ip, 0);
    658     parse_table_add(&pt, "DstIpMask", PQ_DFL | PQ_IP, 0,
    659                     (void *)&rule->dst_ip_mask, 0);
    660  
    661     parse_table_add(&pt, "SrcIp6", PQ_DFL | PQ_IP6, 0,
    662                     (void *)&rule->src_ip6, 0);
    663     parse_table_add(&pt, "SrcIp6Mask", PQ_DFL | PQ_IP6, 0,
    664                     (void *)&rule->src_ip6_mask, 0);
    665     parse_table_add(&pt, "DstIp6", PQ_DFL | PQ_IP6, 0,
    666                     (void *)&rule->dst_ip6, 0);
    667     parse_table_add(&pt, "DstIp6Mask", PQ_DFL | PQ_IP6, 0,
    668                     (void *)&rule->dst_ip6_mask, 0);
    669 
    670     parse_table_add(&pt, "SrcPortMIn", PQ_DFL | PQ_INT, 0,
    671                     (void *)&rule->src_port_min, 0);
    672     parse_table_add(&pt, "SrcPortMAx", PQ_DFL | PQ_INT, 0,
    673                     (void *)&rule->src_port_max, 0);
    674 
    675     parse_table_add(&pt, "DstPortMIn", PQ_DFL | PQ_INT, 0,
    676                     (void *)&rule->dst_port_min, 0);
    677     parse_table_add(&pt, "DstPortMAx", PQ_DFL | PQ_INT, 0,
    678                     (void *)&rule->dst_port_max, 0);
    679 
    680     parse_table_add(&pt, "VlanMIn",    PQ_DFL | PQ_INT, 0,
    681                     (void *)&vlan_min, 0);
    682     parse_table_add(&pt, "VlanMAx",    PQ_DFL | PQ_INT, 0,
    683                     (void *)&vlan_max, 0);
    684 
    685     parse_table_add(&pt, "IpProtocol", PQ_DFL | PQ_MULTI , 0,
    686                     (void *)&rule->ip_protocol, bcma_acl_ip_protocol_text);
    687     parse_table_add(&pt, "EtherType", PQ_DFL | PQ_HEX, 0,
    688                     (void *)&ethertype, 0);
    689  
    690     /* Parse redirection port, if specified. */
    691     if (pt.pt_entries[3].pq_type & PQ_PARSED && redir_port_str != NULL) {
    692         uport = bcmx_uport_parse(redir_port_str, NULL);
    693         lport = bcmx_uport_to_lport(uport);
    694         
    695         if (lport == BCMX_NO_SUCH_LPORT) {
    696                 sal_printf("%s: bad redirection port given: %s\n",
    697                            ARG_CMD(args), redir_port_str);
    698                 parse_arg_eq_done(&pt);
    699                 return CMD_FAIL;
    700         } else {
    701             rule->actions.flags |= BCMA_ACL_ACTION_REDIR;
    702             rule->actions.redir_port = lport;
    703         }
    704     }
    705 
    706     /* Parse mirror-to-port, if specified. */
    707     if (pt.pt_entries[4].pq_type & PQ_PARSED && mirror_port_str != NULL) {
    708         uport = bcmx_uport_parse(mirror_port_str, NULL);
    709         lport = bcmx_uport_to_lport(uport);
    710         
    711         if (lport == BCMX_NO_SUCH_LPORT) {
    712                 sal_printf("%s: bad mirror port given: %s\n",
    713                            ARG_CMD(args), mirror_port_str);
    714                 parse_arg_eq_done(&pt);
    715                 return CMD_FAIL;
    716         } else {
    717             rule->actions.flags |= BCMA_ACL_ACTION_MIRROR;
    718             rule->actions.mirror_port = lport;
    719         }
    720     }
    721 
    722     if(!parseEndOk(args, &pt, &retval)) {
    723         return retval;
    724     }
    725     if (permit_flag) {
    726        rule->actions.flags |= BCMA_ACL_ACTION_PERMIT;
    727     }
    728     if (deny_flag) {
    729        rule->actions.flags |= BCMA_ACL_ACTION_DENY;
    730     }
    731  
    732     if (log_flag) {
    733        rule->actions.flags |= BCMA_ACL_ACTION_LOG;
    734     }
    735 
    736 
    737     if (!MAC_IS_CLEAR(rule->src_mac)) {
    738 	rule->flags |= BCMA_ACL_RULE_SRC_MAC;
    739     }
    740 
    741     if (!MAC_IS_CLEAR(rule->dst_mac)) {
    742 	rule->flags |= BCMA_ACL_RULE_DST_MAC;
    743     }
    744 
    745     if (rule->src_port_min != 0) {
    746         rule->flags |= BCMA_ACL_RULE_L4_SRC_PORT;
    747         if (rule->src_port_max == 0) {
    748             rule->src_port_max = rule->src_port_min;
    749         }
    750     }
    751 
    752     if (rule->src_port_max != 0) {
    753         rule->flags |= BCMA_ACL_RULE_L4_SRC_PORT;
    754         if (rule->src_port_min == 0) {
    755             rule->src_port_min = rule->src_port_max;
    756         }
    757     }
    758 
    759     if (rule->dst_port_min != 0) {
    760         rule->flags |= BCMA_ACL_RULE_L4_DST_PORT;
    761         if (rule->dst_port_max == 0) {
    762             rule->dst_port_max = rule->dst_port_min;
    763         }
    764     }
    765 
    766     if (rule->dst_port_max != 0) {
    767         rule->flags |= BCMA_ACL_RULE_L4_DST_PORT;
    768         if (rule->dst_port_min == 0) {
    769             rule->dst_port_min = rule->dst_port_max;
    770         }
    771     }
    772 
    773     if (rule->src_ip || rule->src_ip_mask) {
    774        rule->flags |= BCMA_ACL_RULE_SRC_IP4;
    775     }
    776 
    777     if (rule->dst_ip || rule->dst_ip_mask) {
    778        rule->flags |= BCMA_ACL_RULE_DST_IP4;
    779     }
    780 
    781     if (!IP6_IS_CLEAR(rule->src_ip6)) {
    782        rule->flags |= BCMA_ACL_RULE_SRC_IP6;
    783     }
    784 
    785     if (!IP6_IS_CLEAR(rule->dst_ip6)) {
    786        rule->flags |= BCMA_ACL_RULE_DST_IP6;
    787     }
    788 
    789     if (vlan_min || vlan_max) {
    790         rule->flags |= BCMA_ACL_RULE_VLAN;
    791         rule->vlan_min = vlan_min;
    792 	rule->vlan_max = vlan_max;
    793     }
    794 
    795     if (rule->ip_protocol != BCMA_ACL_IPPROTO_ANY) {
    796         rule->flags |= BCMA_ACL_RULE_IPPROTOCOL;
    797     }
    798 
    799     if (ethertype > 0xffff) {
    800         cli_out("Ethertype=%#x too large (>0xffff).\n", ethertype);
    801         sal_free(rule);
    802         return CMD_FAIL;
    803     }
    804 
    805     if (ethertype != 0) {
    806         rule->flags |= BCMA_ACL_RULE_ETHERTYPE;
    807         rule->ether_type = ethertype;
    808     }
    809 
    810     if (BCM_FAILURE(bcma_acl_rule_add(list_id_cur, rule))) {
    811         cli_out("ACL: rule add failed (rule_id=%d).\n", rule->rule_id);
    812         sal_free(rule);
    813         return CMD_FAIL;
    814     }
    815 
    816     return CMD_OK;
    817 }
    818 
    819 /* 
    820  * Function:
    821  *     _bcmx_acl_rule_add
    822  * Purpose:
    823  *     
    824  * Returns:
    825  *     pointer to new rule or NULL on error
    826  */
    827 int
    828 _bcmx_acl_rule_add(bcma_acl_list_id_t list_id, bcma_acl_rule_t *rule)
    829 {
    830     int                 idx1, idx2;
    831 
    832     assert(rule != NULL);
    833 
    834     /* Find the corresponding cmd_acl_list_t */
    835     for (idx1 = 0; idx1 < BCMA_ACL_NUMB_LISTS; idx1++) {
    836         if (acl_lists[idx1] == NULL) {
    837             continue;
    838 	}
    839         if (acl_lists[idx1]->list.list_id == list_id) {
    840             /* find an unused rule in list. */
    841             for (idx2 = 0; idx2 < BCMA_ACL_NUMB_LISTS; idx2++) {
    842 	        if (acl_lists[idx1]->rules[idx2] == NULL) {
    843                     acl_lists[idx1]->rules[idx2] = rule;
    844                     return BCM_E_NONE;
    845 		}
    846 	    }
    847             return BCM_E_RESOURCE;
    848 	}
    849     }
    850     return BCM_E_NOT_FOUND;
    851 }
    852 
    853 
    854 /* 
    855  * Function:
    856  *     _bcmx_acl_rule_alloc
    857  * Purpose:
    858  *     Allocate a new rule and zero it out.
    859  * Returns:
    860  *     pointer to new rule or NULL on error
    861  */
    862 STATIC bcma_acl_rule_t *
    863 _bcmx_acl_rule_alloc(void) {
    864     bcma_acl_rule_t     *rule_new;
    865 
    866     LOG_DEBUG(BSL_LS_APPL_ACCESSCTRLLIST,
    867               (BSL_META("BEGIN _bcmx_acl_rule_alloc()\n")));
    868     rule_new = sal_alloc(sizeof(bcma_acl_rule_t), "acl rule");
    869     if (rule_new == NULL) {
    870         cli_out("ACL Error: allocation failure\n");
    871         return NULL;
    872     }
    873     sal_memset(rule_new, 0, sizeof(bcma_acl_rule_t));
    874 
    875     return rule_new;
    876 }
    877 
    878 #endif /* INCLUDE_ACL */