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

field.c (41846B)


      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:     field.c
      8  * Purpose:  BCMX Field commands
      9  */
     10 
     11 #include <sal/appl/io.h>
     12 #include <shared/bsl.h>
     13 #include <bcm/error.h>
     14 
     15 #include <bcmx/bcmx.h>
     16 #include <bcmx/field.h>
     17 
     18 #include <appl/diag/shell.h>
     19 #include <appl/diag/system.h>
     20 #include <appl/diag/parse.h>
     21 
     22 #ifdef INCLUDE_BCMX
     23 
     24 #include "bcmx.h"
     25 #include <appl/diag/diag.h>
     26 
     27 #ifdef BCM_FIELD_SUPPORT
     28 
     29 char bcmx_cmd_field_usage[] =
     30     "\n"
     31 #ifdef COMPILER_STRING_CONST_LIMIT
     32     "    field {action | counter | entry | group | list| init | meter | qset} "
     33     "<args>\n"
     34 #else
     35     "    field action {add | remove | show} <args> "
     36     "- Set actions for a field entry\n"
     37     "    field counter {create | destroy | set |   "
     38     "- Manage a field counter\n"
     39     "                   share | show} <args>\n"
     40     "    field entry {copy | create | destroy |    "
     41     "- Manage a field entry\n"
     42     "                 install | qualify |\n"
     43     "                 reinstall | remove} <args>\n"
     44     "    field group {create | destroy |           " 
     45     "- Manage a field group\n"
     46     "                 set | show} <args>\n"
     47     "    field list {actions | qualifiers}         "
     48     "- Display action or qualifier names\n"
     49     "    field init                                "
     50     "- Initialize the Field subsystem\n"
     51     "    field range {create | show | destroy}      "
     52     "- Manage a TCP/UDP port range checker\n"
     53     "    field meter {create | destroy | set |     "
     54     "- Manage a field meter\n"
     55     "                 share | show} <args>\n"
     56     "    field qset {create | destroy | set |      "
     57     "- Manage a field qualifier set\n"
     58     "                show} <args>\n"
     59 #endif
     60 ;
     61 
     62 static cmd_result_t action_cmd(int unit, args_t *args);
     63 static cmd_result_t action_add_cmd(int unit, args_t *args);
     64 static cmd_result_t action_remove_cmd(int unit, args_t *args);
     65 static cmd_result_t action_show_cmd(int unit, args_t *args);
     66 
     67 static cmd_result_t entry_cmd(int unit, args_t *args);
     68 static cmd_result_t entry_copy_cmd(int unit, args_t *args);
     69 static cmd_result_t entry_create_cmd(int unit, args_t *args);
     70 static cmd_result_t entry_destroy_cmd(int unit, args_t *args);
     71 static cmd_result_t entry_install_cmd(int unit, args_t *args);
     72 static cmd_result_t entry_qualify_cmd(int unit, args_t *args);
     73 static cmd_result_t entry_reinstall_cmd(int unit, args_t *args);
     74 static cmd_result_t entry_remove_cmd(int unit, args_t *args);
     75 
     76 static cmd_result_t group_cmd(int unit, args_t *args);
     77 static cmd_result_t group_create_cmd(int unit, args_t *args);
     78 static cmd_result_t group_destroy_cmd(int unit, args_t *args);
     79 static cmd_result_t group_set_cmd(int unit, args_t *args);
     80 static cmd_result_t group_show_cmd(int unit, args_t *args);
     81 
     82 static cmd_result_t init_cmd(int unit, args_t *args);
     83 
     84 static cmd_result_t list_cmd(int unit, args_t *args);
     85 static cmd_result_t list_actions_cmd(int unit, args_t *args);
     86 static cmd_result_t list_quals_cmd(int unit, args_t *args);
     87 
     88 static cmd_result_t range_cmd(int unit, args_t *args);
     89 
     90 static cmd_result_t qset_cmd(int unit, args_t *args);
     91 static cmd_result_t qset_create_cmd(int unit, args_t *args);
     92 static cmd_result_t qset_destroy_cmd(int unit, args_t *args);
     93 static cmd_result_t qset_set_cmd(int unit, args_t *args);
     94 static cmd_result_t qset_show_cmd(int unit, args_t *args);
     95 
     96 static cmd_t field_cmd_list[] = {
     97     {"Action", action_cmd,
     98      "field action {add | remove | show} <args>",
     99      "Set actions for a field processor entry."},
    100     {"Entry", entry_cmd,
    101      "field entry {copy | create | destroy | install | qualify |\n"
    102      "                  reinstall | remove} <args>", 
    103      "Manage a field processor entry."},
    104 
    105     {"Group", group_cmd,
    106      "field group {create | destroy | set | show} <args>",
    107      "Manage a field processor group."},
    108 
    109     {"Init", init_cmd, 
    110      "field init",
    111      "Initialize the Field Processor subsystem."},
    112 
    113     {"List", list_cmd, 
    114      "field list {actions | qualifiers}",
    115      "List action or qualfier names"},
    116 
    117     {"Range", range_cmd,
    118      "field range {create <flags> [Min= ] [Max= ] | show <range-id> | destroy <range-id>} ",
    119      "Create, destroy or display range checks."},
    120     {"QSET", qset_cmd,
    121      "field qset {create | destroy | set | show} <args>",
    122      "Manage a field qualifier set."}
    123 };
    124 
    125 static cmd_t field_action_cmd_list[] = {
    126     {"Add", action_add_cmd, 
    127      "field action add <entry-id> Action=<action-name> Param0=<value> "
    128      "Param1=<value>", 
    129      "Add an action for the specified field entry."},
    130 
    131     {"Remove", action_remove_cmd, 
    132      "field action remove <entry-id> Action=<action-name>", 
    133      "Remove the action(s) from the specified field entry."},
    134 
    135     {"SHOW", action_show_cmd, 
    136      "field action show <entry-id> Action=<action-name>",
    137      "Display the parameter values of the specified action for a field entry."}
    138 };
    139 
    140 static cmd_t field_entry_cmd_list[] = {
    141     {"CoPy", entry_copy_cmd, 
    142      "field entry copy <entry-id>", 
    143      "Create a copy of an existing field entry."},
    144 
    145     {"Create", entry_create_cmd, 
    146      "field entry create <group-id>", 
    147      "Create an empty field entry based on a field group."},
    148 
    149     {"Destroy", entry_destroy_cmd, 
    150      "field entry destroy {<entry-id> | ALL}", 
    151      "Destroy a field entry or all existing field entries."},
    152 
    153     {"Install", entry_install_cmd, 
    154      "field entry install <entry-id>", 
    155      "Install a field entry into the hardware tables."},
    156 
    157     {"Qualify", entry_qualify_cmd,
    158      "field entry qualify <entry-id> FieldQualifier=<qualifier-name>\n"
    159      "                                    <data> [<mask>]",
    160      "Set data and mask for the specified field qualifier."},
    161 
    162     {"ReInstall", entry_reinstall_cmd, 
    163      "field entry reinstall <entry-id>", 
    164      "Re-install a field entry into the hardware tables."},
    165 
    166     {"ReMove", entry_remove_cmd,
    167      "field entry remove <entry-id>",
    168      "Remove a field entry from the hardware tables."}
    169 };
    170 
    171 static cmd_t field_group_cmd_list[] = {
    172     {"Create", group_create_cmd, 
    173      "field group create QSET=<qset-number> PRI=<number>", 
    174      "Create a field group with specified priority and qualifier set."},
    175 
    176     {"Destroy", group_destroy_cmd, 
    177      "field group destroy <group-id>", 
    178      "Deallocate a field group.  All entries for this\n"
    179      "        group must have been previously destroyed."},
    180 
    181     {"Set", group_set_cmd, 
    182      "field group set <group-id> QSET=<qset-number>", 
    183      "Set the qualifier set for a field group."},
    184 
    185     {"SHOW", group_show_cmd, 
    186      "field group show <group-id>", 
    187      "Display the qualifier set for a field group."}
    188 };
    189 
    190 static cmd_t field_list_cmd_list[] = {
    191     {"ACTions", list_actions_cmd, 
    192      "field list actions",
    193      "Display Field actions."},
    194 
    195     {"QUALifiers", list_quals_cmd, 
    196      "field list qualifiers", 
    197      "Display Field qualifiers."},
    198 };
    199 
    200 static cmd_t field_qset_cmd_list[] = {
    201     {"Create", qset_create_cmd, 
    202      "field qset create", 
    203      "Create a field qualifier set.  No field qualifier will be selected\n"
    204      "        for the new set."},
    205 
    206     {"Destroy", qset_destroy_cmd, 
    207      "field qset destroy <qset-number>", 
    208      "Destroys a field qualifier set."},
    209 
    210     {"Set", qset_set_cmd, 
    211      "field qset set <qset-number> {<qualifier-name>=<on|off> ...}", 
    212      "Set or clear field qualifiers for the specified field qualifier set.\n"
    213      "        One or more qualifiers can be specified.  Qualifiers not\n"
    214      "        specified are left unchanged."},
    215 
    216     {"SHOW", qset_show_cmd, 
    217      "field qset show <qset-number>", 
    218      "Display a field qualifier set attributes."}
    219 };
    220 
    221 
    222 /* Static Globals and Defines */
    223 
    224 /* FP Qualifiers */
    225 #define FP_QUALIFIER_CNT  bcmFieldQualifyCount 
    226 static char *fp_qualifier_names[FP_QUALIFIER_CNT+1] = BCM_FIELD_QUALIFY_STRINGS;
    227 #define FP_QUALIFIER_NAME_GET(qid)    \
    228     ((((qid) < 0) || ((qid) >= FP_QUALIFIER_CNT)) ? \
    229      NULL : fp_qualifier_names[qid])
    230 
    231 /* FP Actions */
    232 #define FP_ACTION_CNT     bcmFieldActionCount
    233 static char *fp_action_names[FP_ACTION_CNT+1] = BCM_FIELD_ACTION_STRINGS;
    234 #define FP_ACTION_NAME_GET(action)    \
    235     ((((action) < 0) || ((action) >= FP_ACTION_CNT)) ? \
    236      NULL : fp_action_names[action])
    237 
    238 /* 
    239  * Table:   
    240  *     Array of SETS of field qualifier.
    241  * Element:  
    242  *     A set of field qualifiers contains the selection of qualifiers
    243  *     for the the specified set, and a flag indicating if the set was
    244  *     created.
    245  */
    246 typedef struct fp_qset_s {
    247     bcm_field_qset_t    qset;
    248     int                 created;    /* Qset is used and create */
    249 } fp_qset_t;
    250 
    251 #define MAX_QSETS    100
    252 static  fp_qset_t    fp_qset_tbl[MAX_QSETS];
    253 
    254 
    255 /* 
    256  * Function:    
    257  *     get_integer
    258  * Purpose:    
    259  *     Gets an integer value from a string, and, if specified, 
    260  *     checks that value is within allowed range.
    261  * Parameters:  
    262  *     cmd         - Command name string
    263  *     subcmd_str  - Subcommand name string
    264  *     param       - String that contains number to be parsed
    265  *     number      - Returns number parsed
    266  *     number_str  - Name of number (to use when displaying error message)
    267  *     check_range - Indicates whether to check value within range
    268  *     min         - Minimum value allowed
    269  *     max         - Maximum value allowed
    270  * Returns:     
    271  *     CMD_OK      - Success, valid integer
    272  *     CMD_FAIL    - Failure, could not parse integer from string,
    273  *                   or value is out of range.
    274  */
    275 static cmd_result_t
    276 get_integer(char *cmd, char *subcmd_str, 
    277             char *param, int *number, char *number_str,
    278             int check_range, int min, int max)
    279 {
    280     if (param == NULL) {
    281         sal_printf("%s: Need %s\n", cmd, number_str);
    282         return CMD_FAIL;
    283     }
    284 
    285     if (!isint(param)) {
    286         sal_printf("%s: Invalid %s '%s'\n", cmd, number_str, param);
    287         return CMD_FAIL;
    288     }
    289     *number = parse_integer(param);
    290 
    291     if (check_range) {
    292         if ((*number < min) || (*number > max)) {
    293             sal_printf("%s: %s failed: %s must be %d..%d\n",
    294                        cmd, subcmd_str, number_str, min, max);
    295             return CMD_FAIL;
    296         }
    297     }
    298 
    299     return CMD_OK;
    300 }
    301 
    302 
    303 static void
    304 display_qset(bcm_field_qset_t qset)
    305 {
    306     bcm_field_qualify_t  qid;
    307     char                 *qname_ptr;
    308     char                 *set = "X";
    309     char                 *clear = "-";
    310     char                 *str;
    311     int                  num_qualifiers_row = 3;
    312 
    313     sal_printf("     Qualifier settings   ('X'= set    '-'= clear)\n");
    314     sal_printf("    +---------------------+---------------------+"
    315                "---------------------+");
    316 
    317     for (qid = (bcm_field_qualify_t)0; qid < FP_QUALIFIER_CNT; qid++) {
    318         if ((qname_ptr = FP_QUALIFIER_NAME_GET(qid)) == NULL) {
    319             sal_printf("Could not find qualifier=%d\n", qid);
    320             continue;
    321         }
    322 
    323         if ((qid % num_qualifiers_row) == 0) {
    324             sal_printf("\n    |");
    325         }
    326         if (BCM_FIELD_QSET_TEST(qset, qid)) {
    327             str = set;
    328         } else {
    329             str = clear;
    330         }
    331         sal_printf(" %-18s%1s |", qname_ptr, str);
    332     }
    333 
    334     while ((qid++ % num_qualifiers_row) != 0) {
    335         sal_printf("%21s|", " ");
    336     }
    337     sal_printf("\n    +---------------------+---------------------+"
    338                "---------------------+\n\n");
    339 
    340     return;
    341 }
    342 
    343 cmd_result_t
    344 bcmx_cmd_field(int unit, args_t *args)
    345 {
    346     static int  first_time = TRUE;
    347 
    348     if (first_time) {
    349         memset(fp_qset_tbl, 0, sizeof(fp_qset_tbl));
    350         fp_qualifier_names[FP_QUALIFIER_CNT] = NULL;
    351         fp_action_names[FP_ACTION_CNT] = NULL;
    352         first_time = FALSE;
    353     }
    354 
    355     return subcommand_execute(unit, args, 
    356                               field_cmd_list, COUNTOF(field_cmd_list));
    357 }
    358 
    359 static cmd_result_t
    360 init_cmd(int unit, args_t *args)
    361 {
    362     int    rv;
    363     char   *cmd;
    364 
    365     cmd = ARG_CMD(args);
    366 
    367     if (ARG_CNT(args)) {
    368         sal_printf("%s: Invalid option %s\n", cmd, ARG_CUR(args));
    369         return CMD_FAIL;
    370     }
    371 
    372     rv = bcmx_field_init();
    373 
    374     if (BCM_FAILURE(rv)) {
    375         sal_printf("%s: Subsystem initialization failed: %s\n", cmd,
    376                    bcm_errmsg(rv));
    377         return CMD_FAIL;
    378     }
    379 
    380     return CMD_OK;
    381 }
    382 
    383 static cmd_result_t
    384 list_cmd(int unit, args_t *args)
    385 {
    386     return subcommand_execute(unit, args, 
    387                               field_list_cmd_list, 
    388                               COUNTOF(field_list_cmd_list));
    389 }
    390 
    391 static cmd_result_t
    392 list_actions_cmd(int unit, args_t *args)
    393 {
    394     bcm_field_action_t  action;
    395     char                buf[BCM_FIELD_ACTION_WIDTH_MAX];
    396 
    397     for (action = (bcm_field_action_t)0; action < bcmFieldActionCount; action++) {
    398         cli_out("\t%s\n", format_field_action(buf, action, 0));
    399     }
    400     return CMD_OK;
    401 }
    402 
    403 static cmd_result_t
    404 list_quals_cmd(int unit, args_t *args)
    405 {
    406     bcm_field_qualify_t qual;
    407     char                buf[BCM_FIELD_QUALIFY_WIDTH_MAX];
    408 
    409     for (qual = (bcm_field_qualify_t)0; qual < bcmFieldQualifyCount; qual++) {
    410         cli_out("\t%s\n", format_field_qualifier(buf, qual, 0));
    411     }
    412     return CMD_OK;
    413 }
    414 
    415 
    416 static cmd_result_t
    417 action_cmd(int unit, args_t *args)
    418 {
    419     return subcommand_execute(unit, args, 
    420                               field_action_cmd_list, 
    421                               COUNTOF(field_action_cmd_list));
    422 }
    423 
    424 static cmd_result_t
    425 action_add_cmd(int unit, args_t *args)
    426 {
    427     int                  rv;
    428     char                 *cmd;
    429     cmd_result_t         ret_code;
    430     bcm_field_entry_t    entry;
    431     uint32               param0 = 0, param1 = 0;
    432     int                  action = -1;
    433     bcm_field_action_t   action_id;
    434     parse_table_t        pt;
    435 
    436     cmd = ARG_CMD(args);
    437 
    438     if (get_integer(cmd, "Action add", 
    439                     ARG_GET(args), &entry, "entry id",
    440                     FALSE, 0, 0) != CMD_OK) {
    441         return CMD_FAIL;
    442     }
    443 
    444     /* Parse option */
    445     parse_table_init(0, &pt);
    446     parse_table_add(&pt, "Action",  PQ_DFL | PQ_MULTI, 
    447                     0, &action,  fp_action_names);
    448     parse_table_add(&pt, "Param0",  PQ_DFL | PQ_INT,
    449                     0, &param0, NULL);
    450     parse_table_add(&pt, "Param1",  PQ_DFL | PQ_INT,
    451                     0, &param1, NULL);
    452     if (!parseEndOk(args, &pt, &ret_code)) {
    453         return ret_code;
    454     }
    455 
    456     if ((action < 0) || (action >= FP_ACTION_CNT)) {
    457         sal_printf("%s: Invalid Field Action selection (%d)\n", cmd, action);
    458         return CMD_FAIL;
    459     }
    460 
    461     action_id = (bcm_field_action_t)action;
    462 
    463     rv = bcmx_field_action_add(entry, action_id, param0, param1);
    464 
    465     if (BCM_FAILURE(rv)) {
    466         sal_printf("%s: Action add failed: %s\n", cmd, bcm_errmsg(rv));
    467         return CMD_FAIL;
    468     }
    469 
    470     return CMD_OK;
    471 }
    472 
    473 static cmd_result_t
    474 action_remove_cmd(int unit, args_t *args)
    475 {
    476     int                  rv;
    477     char                 *cmd;
    478     char                 *param;
    479     bcm_field_entry_t    entry;
    480     int                  action = -1;
    481     parse_table_t        pt;
    482 
    483 
    484     cmd = ARG_CMD(args);
    485 
    486     if (get_integer(cmd, "Action remove", 
    487                     ARG_GET(args), &entry, "entry id",
    488                     FALSE, 0, 0) != CMD_OK) {
    489         return CMD_FAIL;
    490     }
    491 
    492     if (!ARG_CNT(args)) {
    493         sal_printf("%s: Need option\n", cmd);
    494         return CMD_FAIL;
    495     }
    496 
    497     /* Parse option */
    498     parse_table_init(0, &pt);
    499     parse_table_add(&pt, "Action",  PQ_DFL | PQ_MULTI,
    500                     0, &action,  fp_action_names);
    501     if ((parse_arg_eq(args, &pt) < 0)) {
    502         sal_printf("%s: Invalid option %s\n", cmd, ARG_CUR(args));
    503         parse_arg_eq_done(&pt);
    504         return CMD_FAIL;
    505     }
    506 
    507     parse_arg_eq_done(&pt);   /* No longer needed */
    508 
    509     if (action == -1) {    /* Check if 'ALL' was specified */
    510         param = ARG_GET(args);
    511         if (sal_strcasecmp(param, "all")) {
    512             sal_printf("%s: Invalid option %s\n", cmd, param);
    513             return CMD_FAIL;
    514         }
    515         rv = bcmx_field_action_remove_all(entry);
    516     } else {
    517         if ((action < 0) || (action >= FP_ACTION_CNT)) {
    518             sal_printf("%s: Invalid Field Action selection (%d)\n", 
    519                        cmd, action);
    520             return CMD_FAIL;
    521         }
    522         rv = bcmx_field_action_remove(entry, (bcm_field_action_t)action);
    523     }
    524 
    525     if (BCM_FAILURE(rv)) {
    526         sal_printf("%s: Action remove failed: %s\n", cmd, bcm_errmsg(rv));
    527         return CMD_FAIL;
    528     }
    529 
    530     return CMD_OK;
    531 }
    532 
    533 static cmd_result_t
    534 action_show_cmd(int unit, args_t *args)
    535 {
    536     int                  rv;
    537     char                 *cmd;
    538     cmd_result_t         ret_code;
    539     bcm_field_entry_t    entry;
    540     uint32               param0 = 0, param1 = 0;
    541     int                  action = -1;
    542     bcm_field_action_t   action_id;
    543     parse_table_t        pt;
    544 
    545     cmd = ARG_CMD(args);
    546 
    547     if (get_integer(cmd, "Action show",
    548                     ARG_GET(args), &entry, "entry id",
    549                     FALSE, 0, 0) != CMD_OK) {
    550         return CMD_FAIL;
    551     }
    552 
    553     /* Parse option */
    554     parse_table_init(0, &pt);
    555     parse_table_add(&pt, "Action",  PQ_DFL | PQ_MULTI,
    556                     0, &action,  fp_action_names);
    557     if (!parseEndOk(args, &pt, &ret_code)) {
    558         return ret_code;
    559     }
    560 
    561     if ((action < 0) || (action >= FP_ACTION_CNT)) {
    562         sal_printf("%s: Invalid Field Action selection (%d)\n", cmd, action);
    563         return CMD_FAIL;
    564     }
    565 
    566     action_id = (bcm_field_action_t)action;
    567 
    568     rv = bcmx_field_action_get(entry, action_id, &param0, &param1);
    569 
    570     if (BCM_FAILURE(rv)) {
    571         sal_printf("%s: Action show failed: %s\n", cmd, bcm_errmsg(rv));
    572         return CMD_FAIL;
    573     }
    574 
    575     sal_printf("%s: Parameter values for Entry=%d(0x%x), Action=%s are:\n"
    576                "                 Param0=%u\n"
    577                "                 Param1=%u\n",
    578                cmd, entry, entry, FP_ACTION_NAME_GET(action),
    579                param0, param1);
    580 
    581     return CMD_OK;
    582 }
    583 
    584 static cmd_result_t
    585 entry_cmd(int unit, args_t *args)
    586 {
    587     return subcommand_execute(unit, args, 
    588                               field_entry_cmd_list, 
    589                               COUNTOF(field_entry_cmd_list));
    590 }
    591 
    592 static cmd_result_t
    593 entry_create_cmd(int unit, args_t *args)
    594 {
    595     int                  rv;
    596     char                 *cmd;
    597     bcm_field_group_t    group;
    598     bcm_field_entry_t    entry = 0;
    599 
    600     cmd = ARG_CMD(args);
    601 
    602     if (get_integer(cmd, "Entry create", 
    603                     ARG_GET(args), &group, "group id",
    604                     FALSE, 0, 0) != CMD_OK) {
    605         return CMD_FAIL;
    606     }
    607 
    608     rv = bcmx_field_entry_create(group, &entry);
    609 
    610     if (BCM_FAILURE(rv)) {
    611         sal_printf("%s: Entry create failed: %s\n", cmd, bcm_errmsg(rv));
    612         return CMD_FAIL;
    613     }
    614 
    615     sal_printf("%s: Entry=%d(0x%x) created for group=%d(0x%x)\n",
    616                cmd, entry, entry, group, group);
    617 
    618     return CMD_OK;
    619 }
    620 
    621 static cmd_result_t
    622 entry_destroy_cmd(int unit, args_t *args)
    623 {
    624     int                  rv;
    625     char                 *cmd;
    626     char                 *param;
    627     bcm_field_entry_t    entry;
    628 
    629     cmd = ARG_CMD(args);
    630 
    631     if ((param = ARG_GET(args)) == NULL) {
    632         sal_printf("%s: Entry destroy failed: Entry id needed\n", cmd);
    633         return CMD_FAIL;
    634     }
    635 
    636     if (sal_strcasecmp(param, "all") == 0) {
    637         if (ARG_CNT(args)) {
    638             sal_printf("%s: Invalid option %s\n", cmd, ARG_CUR(args));
    639             return CMD_FAIL;
    640         }
    641         rv = bcmx_field_entry_destroy_all();
    642     } else {
    643         if (get_integer(cmd, "Entry destroy", 
    644                         param, &entry, "entry id",
    645                         FALSE, 0, 0) != CMD_OK) {
    646             return CMD_FAIL;
    647         }
    648 
    649         rv = bcmx_field_entry_destroy(entry);
    650     }
    651 
    652     if (BCM_FAILURE(rv)) {
    653         sal_printf("%s: Entry destroy failed: %s\n", cmd, bcm_errmsg(rv));
    654         return CMD_FAIL;
    655     }
    656 
    657     return CMD_OK;
    658 }
    659 
    660 static cmd_result_t
    661 entry_copy_cmd(int unit, args_t *args)
    662 {
    663     int                  rv;
    664     char                 *cmd;
    665     bcm_field_entry_t    src_entry, dst_entry = 0;
    666 
    667     cmd = ARG_CMD(args);
    668 
    669     if (get_integer(cmd, "Entry copy", 
    670                     ARG_GET(args), &src_entry, "entry id",
    671                     FALSE, 0, 0) != CMD_OK) {
    672         return CMD_FAIL;
    673     }
    674 
    675     rv = bcmx_field_entry_copy(src_entry, &dst_entry);    
    676 
    677     if (BCM_FAILURE(rv)) {
    678         sal_printf("%s: Entry copy failed: %s\n", cmd, bcm_errmsg(rv));
    679         return CMD_FAIL;
    680     }
    681 
    682     sal_printf("%s: src-entry=%d(0x%x) copied to dst-entry=%d(0x%x)\n",
    683                cmd, src_entry, src_entry, dst_entry, dst_entry);
    684 
    685     return CMD_OK;
    686 }
    687 
    688 static cmd_result_t
    689 entry_install_cmd(int unit, args_t *args)
    690 {
    691     int                  rv;
    692     char                 *cmd;
    693     bcm_field_entry_t    entry;
    694 
    695     cmd = ARG_CMD(args);
    696 
    697     if (get_integer(cmd, "Entry install", 
    698                     ARG_GET(args), &entry, "entry id",
    699                     FALSE, 0, 0) != CMD_OK) {
    700         return CMD_FAIL;
    701     }
    702 
    703     rv = bcmx_field_entry_install(entry);
    704 
    705     if (BCM_FAILURE(rv)) {
    706         sal_printf("%s: Entry install failed: %s\n", cmd, bcm_errmsg(rv));
    707         return CMD_FAIL;
    708     }
    709 
    710     return CMD_OK;
    711 }
    712 
    713 static cmd_result_t
    714 entry_qualify_cmd(int unit, args_t *args)
    715 {
    716     int                  rv = BCM_E_NONE;
    717     char                 *cmd;
    718     char                 *param;
    719     bcm_field_entry_t    entry;
    720     int                  qualifier = -1;
    721     bcm_field_qualify_t  qid;
    722     int                  data, mask;
    723     bcmx_lplist_t        lplist;
    724     bcm_trunk_t          trunk;
    725     bcmx_lport_t         lport;
    726     bcm_ip_t             ipaddr, ipaddr_mask;
    727     bcm_ip6_t            ip6addr, ip6addr_mask;
    728     bcm_mac_t            macaddr, macaddr_mask;
    729     parse_table_t        pt;
    730 
    731     cmd = ARG_CMD(args);
    732 
    733     if (get_integer(cmd, "Entry qualify", 
    734                     ARG_GET(args), &entry, "entry id",
    735                     FALSE, 0, 0) != CMD_OK) {
    736         return CMD_FAIL;
    737     }
    738 
    739     /* Parse option */
    740     parse_table_init(0, &pt);
    741     parse_table_add(&pt, "FieldQualifier",  PQ_DFL | PQ_MULTI,
    742                     0, &qualifier, fp_qualifier_names);
    743     if ((parse_arg_eq(args, &pt) < 0)) {
    744         sal_printf("%s: Invalid option %s\n", cmd, ARG_CUR(args));
    745         parse_arg_eq_done(&pt);
    746         return CMD_FAIL;
    747     }
    748 
    749     parse_arg_eq_done(&pt);   /* No longer needed */
    750 
    751     if ((qualifier < 0) || (qualifier >= FP_QUALIFIER_CNT)) {
    752         sal_printf("%s: Invalid Field Qualifier selection (%d)\n",
    753                    cmd, qualifier);
    754         return CMD_FAIL;
    755     }
    756 
    757     qid = (bcm_field_qualify_t)qualifier;
    758 
    759     switch (qid) {
    760     case bcmFieldQualifyInPorts:
    761         if ((param = ARG_GET(args)) == NULL) {
    762             sal_printf("%s: Need user port list\n", cmd);
    763             return CMD_FAIL;
    764         }
    765         bcmx_lplist_init(&lplist, 0, 0);
    766         if (bcmx_lplist_parse(&lplist, param) < 0) {
    767             sal_printf("%s: Invalid user port list %s\n", cmd, param);
    768             return CMD_FAIL;
    769         }
    770         rv = bcmx_field_qualify_InPorts(entry, lplist);
    771         break;
    772 
    773     case bcmFieldQualifySrcPort:
    774         if ((param = ARG_GET(args)) == NULL) {
    775             sal_printf("%s: Need source user port\n", cmd);
    776             return CMD_FAIL;
    777         }
    778         lport = bcmx_uport_to_lport(bcmx_uport_parse(param, NULL));
    779         if (lport == BCMX_NO_SUCH_LPORT) {
    780             sal_printf("%s: Invalid source user port %s\n", cmd,
    781                        bcmx_lport_to_uport_str(lport));
    782             return CMD_FAIL;
    783         }
    784         rv = bcmx_field_qualify_SrcPort(entry, lport);
    785         break;
    786 
    787     case bcmFieldQualifySrcTrunk:
    788         if (get_integer(cmd, "Entry qualify", 
    789                         ARG_GET(args), &trunk, "source trunk id",
    790                         FALSE, 0, 0) != CMD_OK) {
    791             return CMD_FAIL;
    792         }
    793         rv = bcmx_field_qualify_SrcTrunk(entry, trunk);
    794         break;
    795 
    796     case bcmFieldQualifyDstPort:
    797         if ((param = ARG_GET(args)) == NULL) {
    798             sal_printf("%s: Need destination user port\n", cmd);
    799             return CMD_FAIL;
    800         }
    801         lport = bcmx_uport_to_lport(bcmx_uport_parse(param, NULL));
    802         if (lport == BCMX_NO_SUCH_LPORT) {
    803             sal_printf("%s: Invalid destination user port %s\n", cmd,
    804                        bcmx_lport_to_uport_str(lport));
    805             return CMD_FAIL;
    806         }
    807         rv = bcmx_field_qualify_DstPort(entry, lport);
    808         break;
    809 
    810     case bcmFieldQualifyDstTrunk:
    811         if (get_integer(cmd, "Entry qualify", 
    812                         ARG_GET(args), &trunk, "destination trunk id",
    813                         FALSE, 0, 0) != CMD_OK) {
    814             return CMD_FAIL;
    815         }
    816         rv = bcmx_field_qualify_DstTrunk(entry, trunk);
    817         break;
    818 
    819     case bcmFieldQualifyEtherType:
    820     case bcmFieldQualifyIpProtocol:
    821     case bcmFieldQualifyIpInfo:
    822     case bcmFieldQualifyPacketRes:
    823     case bcmFieldQualifyDSCP:
    824     case bcmFieldQualifyIpFlags:
    825     case bcmFieldQualifyTcpControl:
    826     case bcmFieldQualifyTtl:
    827     case bcmFieldQualifyIp6FlowLabel:
    828     case bcmFieldQualifyMHOpcode:
    829     case bcmFieldQualifyL4SrcPort:
    830     case bcmFieldQualifyL4DstPort:
    831     case bcmFieldQualifyRangeCheck:
    832     case bcmFieldQualifyOuterVlan:
    833     case bcmFieldQualifyInnerVlan:
    834 
    835 
    836         if (get_integer(cmd, "Entry qualify", 
    837                         ARG_GET(args), &data, "data",
    838                         FALSE, 0, 0) != CMD_OK) {
    839             return CMD_FAIL;
    840         }
    841         if (get_integer(cmd, "Entry qualify",
    842                         ARG_GET(args), &mask, "mask",
    843                         FALSE, 0, 0) != CMD_OK) {
    844             return CMD_FAIL;
    845         }
    846 
    847         if (qid == bcmFieldQualifyEtherType) {
    848             rv = bcmx_field_qualify_EtherType(entry, data, mask);
    849         } else if (qid == bcmFieldQualifyIpProtocol) {
    850             rv = bcmx_field_qualify_IpProtocol(entry, data, mask);
    851         } else if (qid == bcmFieldQualifyIpInfo) {
    852             rv = bcmx_field_qualify_IpInfo(entry, data, mask);   
    853         } else if (qid == bcmFieldQualifyPacketRes) {
    854             rv = bcmx_field_qualify_PacketRes(entry, data, mask); 
    855         } else if (qid == bcmFieldQualifyDSCP) {
    856             rv = bcmx_field_qualify_DSCP(entry, data, mask);
    857         } else if (qid == bcmFieldQualifyIpFlags) {
    858             rv = bcmx_field_qualify_IpFlags(entry, data, mask);
    859         } else if (qid == bcmFieldQualifyTcpControl) {
    860             rv = bcmx_field_qualify_TcpControl(entry, data, mask);
    861         } else if (qid == bcmFieldQualifyTtl) {
    862             rv = bcmx_field_qualify_Ttl(entry, data, mask);
    863         } else if (qid == bcmFieldQualifyIp6FlowLabel) {
    864             rv = bcmx_field_qualify_Ip6FlowLabel(entry, data, mask);
    865         } else if (qid == bcmFieldQualifyMHOpcode) {
    866             rv = bcmx_field_qualify_MHOpcode(entry, data, mask);
    867         } else if (qid == bcmFieldQualifyL4SrcPort) {
    868             rv = bcmx_field_qualify_L4SrcPort(entry, data, mask);
    869         } else if (qid == bcmFieldQualifyL4DstPort) {
    870             rv = bcmx_field_qualify_L4DstPort(entry, data, mask);
    871         } else if (qid == bcmFieldQualifyRangeCheck) {
    872             rv = bcmx_field_qualify_RangeCheck(entry, data, mask);
    873         } else if (qid == bcmFieldQualifyOuterVlan) {
    874             rv = bcmx_field_qualify_OuterVlan(entry, data, mask);
    875         } else if (qid == bcmFieldQualifyInnerVlan) {
    876             rv = bcmx_field_qualify_InnerVlan(entry, data, mask);
    877         }
    878 
    879         break;
    880 
    881     case bcmFieldQualifySrcIp:
    882     case bcmFieldQualifyDstIp:
    883         if ((param = ARG_GET(args)) == NULL) {
    884             sal_printf("%s: IP address required\n", cmd);
    885             return CMD_FAIL;
    886         }
    887         if (parse_ipaddr(param, &ipaddr)) {
    888             sal_printf("%s: Invalid IP address %s\n", cmd, param);
    889             return CMD_FAIL;
    890         }
    891 
    892         if ((param = ARG_GET(args)) == NULL) {
    893             sal_printf("%s: IP address mask required\n", cmd);
    894             return CMD_FAIL;
    895         }
    896         if (parse_ipaddr(param, &ipaddr_mask)) {
    897             sal_printf("%s: Invalid IP address mask %s\n", cmd, param);
    898             return CMD_FAIL;
    899         }
    900 
    901         if (qid == bcmFieldQualifySrcIp) {
    902             rv = bcmx_field_qualify_SrcIp(entry, ipaddr, ipaddr_mask);
    903         } else if (qid == bcmFieldQualifyDstIp) {
    904             rv = bcmx_field_qualify_DstIp(entry, ipaddr, ipaddr_mask);
    905         }
    906 
    907         break;
    908 
    909     case bcmFieldQualifySrcIp6:
    910     case bcmFieldQualifyDstIp6:
    911     case bcmFieldQualifyDstIp6High:
    912         if ((param = ARG_GET(args)) == NULL) {
    913             sal_printf("%s: IPv6 address required\n", cmd);
    914             return CMD_FAIL;
    915         }
    916         if (parse_ip6addr(param, ip6addr)) {
    917             sal_printf("%s: Invalid IPv6 address %s\n", cmd, param);
    918             return CMD_FAIL;
    919         }
    920 
    921         if ((param = ARG_GET(args)) == NULL) {
    922             sal_printf("%s: IPv6 address mask required\n", cmd);
    923             return CMD_FAIL;
    924         }
    925         if (parse_ip6addr(param, ip6addr_mask)) {
    926             sal_printf("%s: Invalid IPv6 address mask %s\n", cmd, param);
    927             return CMD_FAIL;
    928         }
    929 
    930         if (qid == bcmFieldQualifySrcIp6) {
    931             rv = bcmx_field_qualify_SrcIp6(entry, ip6addr, ip6addr_mask);
    932         } else if (qid == bcmFieldQualifyDstIp6) {
    933             rv = bcmx_field_qualify_DstIp6(entry, ip6addr, ip6addr_mask);
    934         } else if (qid == bcmFieldQualifyDstIp6High) {
    935             rv = bcmx_field_qualify_DstIp6High(entry, ip6addr, ip6addr_mask);
    936         }
    937 
    938         break;
    939 
    940 
    941     case bcmFieldQualifySrcMac:
    942     case bcmFieldQualifyDstMac:
    943         if ((param = ARG_GET(args)) == NULL) {
    944             sal_printf("%s: MAC address required\n", cmd);
    945             return CMD_FAIL;
    946         }
    947         if (parse_macaddr(param, macaddr)) {
    948             sal_printf("%s: Invalid MAC address %s\n", cmd, param);
    949             return CMD_FAIL;
    950         }
    951 
    952         if ((param = ARG_GET(args)) == NULL) {
    953             sal_printf("%s: MAC address mask required\n", cmd);
    954             return CMD_FAIL;
    955         }
    956         if (parse_macaddr(param, macaddr_mask)) {
    957             sal_printf("%s: Invalid MAC address mask %s\n", cmd, param);
    958             return CMD_FAIL;
    959         }
    960 
    961         if (qid == bcmFieldQualifySrcMac) {
    962             rv = bcmx_field_qualify_SrcMac(entry, macaddr, macaddr_mask);
    963         } else if (qid == bcmFieldQualifyDstMac) {
    964             rv = bcmx_field_qualify_DstMac(entry, macaddr, macaddr_mask);
    965         }
    966 
    967         break;
    968 
    969     default:
    970         sal_printf("%s: Invalid Field Qualifier selection\n", cmd);
    971         return CMD_FAIL;
    972 
    973     }
    974         
    975     if (BCM_FAILURE(rv)) {
    976         sal_printf("%s: Entry qualify failed: %s\n", cmd, bcm_errmsg(rv));
    977         return CMD_FAIL;
    978     }
    979 
    980     return CMD_OK;
    981 }
    982 
    983 static cmd_result_t
    984 entry_reinstall_cmd(int unit, args_t *args)
    985 {
    986     int                  rv;
    987     char                 *cmd;
    988     bcm_field_entry_t    entry;
    989 
    990     cmd = ARG_CMD(args);
    991 
    992     if (get_integer(cmd, "Entry re-install", 
    993                     ARG_GET(args), &entry, "entry id",
    994                     FALSE, 0, 0) != CMD_OK) {
    995         return CMD_FAIL;
    996     }
    997 
    998     rv = bcmx_field_entry_reinstall(entry);
    999 
   1000     if (BCM_FAILURE(rv)) {
   1001         sal_printf("%s: Entry re-install failed: %s\n", cmd, bcm_errmsg(rv));
   1002         return CMD_FAIL;
   1003     }
   1004 
   1005     return CMD_OK;
   1006 }
   1007 
   1008 static cmd_result_t
   1009 entry_remove_cmd(int unit, args_t *args)
   1010 {
   1011     int                  rv;
   1012     char                 *cmd;
   1013     bcm_field_entry_t    entry;
   1014 
   1015     cmd = ARG_CMD(args);
   1016 
   1017     if (get_integer(cmd, "Entry remove", 
   1018                     ARG_GET(args), &entry, "entry id",
   1019                     FALSE, 0, 0) != CMD_OK) {
   1020         return CMD_FAIL;
   1021     }
   1022 
   1023     rv = bcmx_field_entry_remove(entry);
   1024 
   1025     if (BCM_FAILURE(rv)) {
   1026         sal_printf("%s: Entry remove failed: %s\n", cmd, bcm_errmsg(rv));
   1027         return CMD_FAIL;
   1028     }
   1029 
   1030     return CMD_OK;
   1031 }
   1032 
   1033 static cmd_result_t
   1034 group_cmd(int unit, args_t *args)
   1035 {
   1036     return subcommand_execute(unit, args, 
   1037                               field_group_cmd_list, 
   1038                               COUNTOF(field_group_cmd_list));
   1039 
   1040 }
   1041 
   1042 static cmd_result_t
   1043 group_create_cmd(int unit, args_t *args)
   1044 {
   1045     int                  rv;
   1046     char                 *cmd;
   1047     cmd_result_t         ret_code;
   1048     bcm_field_group_t    group = 0;
   1049     int                  qset_num = -1;
   1050     int                  pri = 0;
   1051     parse_table_t        pt;
   1052 
   1053     cmd = ARG_CMD(args);
   1054 
   1055     /* Parse option */
   1056     parse_table_init(0, &pt);
   1057     parse_table_add(&pt, "QSET", PQ_DFL | PQ_INT, 0, &qset_num,  NULL);
   1058     parse_table_add(&pt, "PRI",  PQ_DFL | PQ_INT, 0, &pri, NULL);
   1059     if (!parseEndOk(args, &pt, &ret_code)) {
   1060         return ret_code;
   1061     }
   1062 
   1063     if ((qset_num < 0) || (qset_num >= MAX_QSETS)) {
   1064         sal_printf("%s: Group create failed: Qualifier set number must be "
   1065                    "0..%d\n", cmd, (MAX_QSETS - 1));
   1066         return CMD_FAIL;
   1067     }
   1068 
   1069     if (!fp_qset_tbl[qset_num].created) {
   1070         sal_printf("%s: Group create failed: qset=%d has not been "
   1071                    "created\n", cmd, qset_num);
   1072         return CMD_FAIL;
   1073     }
   1074 
   1075     rv = bcmx_field_group_create(fp_qset_tbl[qset_num].qset, pri, &group);
   1076 
   1077     if (BCM_FAILURE(rv)) {
   1078         sal_printf("%s: Group create failed: %s\n", cmd, bcm_errmsg(rv));
   1079         return CMD_FAIL;
   1080     }
   1081 
   1082     sal_printf("%s: Group=%d(0x%x) created\n", cmd, group, group);
   1083 
   1084     return CMD_OK;
   1085 }
   1086 
   1087 static cmd_result_t
   1088 group_destroy_cmd(int unit, args_t *args)
   1089 {
   1090     int                  rv;
   1091     char                 *cmd;
   1092     bcm_field_group_t    group;
   1093 
   1094     cmd = ARG_CMD(args);
   1095 
   1096     if (get_integer(cmd, "Group destroy", 
   1097                     ARG_GET(args), &group, "group id",
   1098                     FALSE, 0, 0) != CMD_OK) {
   1099         return CMD_FAIL;
   1100     }
   1101 
   1102     rv = bcmx_field_group_destroy(group);
   1103 
   1104     if (BCM_FAILURE(rv)) {
   1105         sal_printf("%s: Group destroy failed: %s\n", cmd, bcm_errmsg(rv));
   1106         return CMD_FAIL;
   1107     }
   1108 
   1109     return CMD_OK;
   1110 }
   1111 
   1112 static cmd_result_t
   1113 group_set_cmd(int unit, args_t *args)
   1114 {
   1115     int                  rv;
   1116     char                 *cmd;
   1117     cmd_result_t         ret_code;
   1118     bcm_field_group_t    group;
   1119     int                  qset_num = -1;
   1120     parse_table_t        pt;
   1121 
   1122     cmd = ARG_CMD(args);
   1123 
   1124     if (get_integer(cmd, "Group qualifier set", 
   1125                     ARG_GET(args), &group, "group id",
   1126                     FALSE, 0, 0) != CMD_OK) {
   1127         return CMD_FAIL;
   1128     }
   1129 
   1130     /* Parse option */
   1131     parse_table_init(0, &pt);
   1132     parse_table_add(&pt, "QSET", PQ_DFL | PQ_INT, 0, &qset_num,  NULL);
   1133     if (!parseEndOk(args, &pt, &ret_code)) {
   1134         return ret_code;
   1135     }
   1136 
   1137     if ((qset_num < 0) || (qset_num >= MAX_QSETS)) {
   1138         sal_printf("%s: Group qualifier set failed: Qualifier set number "
   1139                    "must be 0..%d\n", cmd, (MAX_QSETS - 1));
   1140         return CMD_FAIL;
   1141     }
   1142 
   1143     if (!fp_qset_tbl[qset_num].created) {
   1144         sal_printf("%s: Group qualifier set failed: qset=%d "
   1145                    "has not been created\n", cmd, qset_num);
   1146         return CMD_FAIL;
   1147     }
   1148 
   1149     rv = bcmx_field_group_set(group, fp_qset_tbl[qset_num].qset);
   1150 
   1151     if (BCM_FAILURE(rv)) {
   1152         sal_printf("%s: Group qualifier set failed: %s\n", cmd, bcm_errmsg(rv));
   1153         return CMD_FAIL;
   1154     }
   1155 
   1156     return CMD_OK;
   1157 }
   1158 
   1159 typedef enum {
   1160     ra_create, ra_show, ra_destroy
   1161 } range_action_t;
   1162 
   1163 static cmd_result_t
   1164 range_cmd(int unit, args_t *args)
   1165 {
   1166     int                  rv = BCM_E_INTERNAL;
   1167     char                 *cmd;
   1168     cmd_result_t         ret_code;
   1169     char                 *param;
   1170     range_action_t       action;
   1171     int                  range = -1;
   1172     uint32               flags = 0;
   1173     bcm_l4_port_t        min = 0, max = 0;
   1174     parse_table_t        pt;
   1175     bcm_field_range_t    range_id;
   1176 
   1177     cmd = ARG_CMD(args);
   1178 
   1179     if ((param = ARG_GET(args)) == NULL) {
   1180         sal_printf("%s: Range subcommand needed\n", cmd);
   1181         return CMD_FAIL;
   1182     }
   1183 
   1184     if (sal_strcasecmp(param, "create") == 0) {
   1185         action = ra_create;
   1186     } else if (sal_strcasecmp(param, "show") == 0) {
   1187         action = ra_show;
   1188     } else if (sal_strcasecmp(param, "destroy") == 0) {
   1189         action = ra_destroy;
   1190     } else {
   1191         sal_printf("%s: Invalid option '%s'\n", cmd, param);
   1192         return CMD_FAIL;
   1193     }
   1194 
   1195 
   1196    /* Parse option */
   1197     parse_table_init(0, &pt);
   1198     parse_table_add(&pt, "Range", PQ_DFL | PQ_INT, 0, &range,  NULL);
   1199     parse_table_add(&pt, "Flags", PQ_DFL | PQ_INT, 0, &flags,  NULL);
   1200     parse_table_add(&pt, "MIN", PQ_DFL | PQ_INT, 0, &min,  NULL);
   1201     parse_table_add(&pt, "MAX", PQ_DFL | PQ_INT, 0, &max,  NULL);
   1202     if (!parseEndOk(args, &pt, &ret_code)) {
   1203         return ret_code;
   1204     }
   1205 
   1206     if (ARG_CNT(args) != 0) {
   1207         sal_printf("%s: Ignoring extra arguments beginning with %s\n",
   1208                    cmd, ARG_GET(args));
   1209     }
   1210 
   1211     if ((range < 0) && (action != ra_create)) {
   1212         sal_printf("%s: Range=<value> argument required\n", cmd);
   1213         return CMD_FAIL;
   1214     }
   1215     range_id = range;
   1216 
   1217     switch (action) {
   1218     case ra_create:
   1219         rv = bcmx_field_range_create(&range_id,
   1220                                      flags, min, max);
   1221         if (BCM_SUCCESS(rv)) {
   1222             sal_printf("%s: Created Range=0x%x, Flags=0x%x, Min=%d, Max=%d\n",
   1223                        cmd, range_id, flags, min, max);
   1224         }
   1225         break;
   1226     case ra_destroy:
   1227         rv = bcmx_field_range_destroy(range_id);
   1228         break;
   1229     case ra_show:
   1230         rv = bcmx_field_range_get(range_id,
   1231                                   &flags, &min, &max);
   1232         if (BCM_SUCCESS(rv)) {
   1233             sal_printf("%s: Range=0x%x, Flags=0x%x, Min=%d, Max=%d\n",
   1234                        cmd, range_id, flags, min, max);
   1235         }
   1236         break;
   1237     }
   1238 
   1239     if (BCM_FAILURE(rv)) {
   1240         sal_printf("%s: Range failed: %s\n", cmd, bcm_errmsg(rv));
   1241         return CMD_FAIL;
   1242     }
   1243 
   1244     return CMD_OK;
   1245 }
   1246 
   1247 static cmd_result_t
   1248 group_show_cmd(int unit, args_t *args)
   1249 {
   1250     int                  rv;
   1251     char                 *cmd;
   1252     bcm_field_group_t    group;
   1253     bcm_field_qset_t     qset;
   1254 
   1255     cmd = ARG_CMD(args);
   1256 
   1257     if (get_integer(cmd, "Group qualifier show", 
   1258                     ARG_GET(args), &group, "group id",
   1259                     FALSE, 0, 0) != CMD_OK) {
   1260         return CMD_FAIL;
   1261     }
   1262 
   1263     rv = bcmx_field_group_get(group, &qset);
   1264 
   1265     if (BCM_FAILURE(rv)) {
   1266         sal_printf("%s: Group qualifier show failed: %s\n", 
   1267                    cmd, bcm_errmsg(rv));
   1268         return CMD_FAIL;
   1269     }
   1270 
   1271     sal_printf("     GROUP = %d(0x%x)\n", group, group);
   1272     display_qset(qset);
   1273 
   1274     return CMD_OK;
   1275 }
   1276 
   1277 static cmd_result_t
   1278 qset_cmd(int unit, args_t *args)
   1279 {
   1280     return subcommand_execute(unit, args, 
   1281                               field_qset_cmd_list, 
   1282                               COUNTOF(field_qset_cmd_list));
   1283 }
   1284 
   1285 static cmd_result_t
   1286 qset_create_cmd(int unit, args_t *args)
   1287 {
   1288     char                 *cmd;
   1289     int                  qset_num = 0;
   1290 
   1291     cmd = ARG_CMD(args);
   1292 
   1293     /* Find an available qset index */
   1294     while ((fp_qset_tbl[qset_num].created)) {
   1295         if (++qset_num >= MAX_QSETS) {
   1296             sal_printf("%s: Qset create failed: Reached maximum number of "
   1297                        "qsets\n", cmd);
   1298             return CMD_FAIL;
   1299         }
   1300     }
   1301 
   1302     fp_qset_tbl[qset_num].created = TRUE;
   1303     BCM_FIELD_QSET_INIT(fp_qset_tbl[qset_num].qset);
   1304 
   1305     sal_printf("%s: Qset=%d created\n", cmd, qset_num);
   1306 
   1307     return CMD_OK;
   1308 }
   1309 
   1310 static cmd_result_t
   1311 qset_destroy_cmd(int unit, args_t *args)
   1312 {
   1313     int                  qset_num;
   1314 
   1315     if (get_integer(ARG_CMD(args), "Qset destroy", 
   1316                     ARG_GET(args), &qset_num, "qset number",
   1317                     TRUE, 0, (MAX_QSETS - 1)) != CMD_OK) {
   1318         return CMD_FAIL;
   1319     }
   1320 
   1321     fp_qset_tbl[qset_num].created = FALSE;
   1322 
   1323     return CMD_OK;
   1324 }
   1325 
   1326 static cmd_result_t
   1327 qset_set_cmd(int unit, args_t *args)
   1328 {
   1329     char                 *cmd;
   1330     cmd_result_t         ret_code;
   1331     int                  qset_num, i;
   1332     fp_qset_t            *qset_ptr;
   1333     int                  qualifier[FP_QUALIFIER_CNT];
   1334     parse_table_t        pt;
   1335 
   1336     cmd = ARG_CMD(args);
   1337 
   1338     if (get_integer(cmd, "Qset set",
   1339                     ARG_GET(args), &qset_num, "qset number",
   1340                     TRUE, 0, (MAX_QSETS - 1)) != CMD_OK) {
   1341         return CMD_FAIL;
   1342     }
   1343 
   1344     if (!fp_qset_tbl[qset_num].created) {
   1345         sal_printf("%s: Qset set failed: qset=%d has not been created\n",
   1346                    cmd, qset_num);
   1347         return CMD_FAIL;
   1348     }
   1349 
   1350     qset_ptr = &fp_qset_tbl[qset_num];
   1351 
   1352     /* Parse option */
   1353     parse_table_init(0, &pt);
   1354     for (i = 0; i < FP_QUALIFIER_CNT; i++) {
   1355         qualifier[i] = -1;     /* (-1) will indicate to leave unchanged */
   1356         parse_table_add(&pt, FP_QUALIFIER_NAME_GET(i), PQ_DFL | PQ_BOOL,
   1357                         0, &qualifier[i], NULL);
   1358     }
   1359     if (!parseEndOk(args, &pt, &ret_code)) {
   1360         return ret_code;
   1361     }
   1362 
   1363     
   1364     for (i = 0; i < FP_QUALIFIER_CNT; i++) {
   1365         /* If qualifier was not specified in command, leave it unchanged */
   1366         if (qualifier[i] == -1) {
   1367             continue;
   1368         }
   1369         if (qualifier[i] == 0) {
   1370             BCM_FIELD_QSET_REMOVE(qset_ptr->qset, i);
   1371         } else {
   1372             BCM_FIELD_QSET_ADD(qset_ptr->qset, i);
   1373         }
   1374     }
   1375 
   1376     return CMD_OK;
   1377 }
   1378 
   1379 static cmd_result_t
   1380 qset_show_cmd(int unit, args_t *args)
   1381 {
   1382     char                 *cmd;
   1383     int                  qset_num;
   1384 
   1385     cmd = ARG_CMD(args);
   1386 
   1387     if (get_integer(cmd, "Qset show", 
   1388                     ARG_GET(args), &qset_num, "qset number",
   1389                     TRUE, 0, (MAX_QSETS - 1)) != CMD_OK) {
   1390         return CMD_FAIL;
   1391     }
   1392 
   1393     if (!fp_qset_tbl[qset_num].created) {
   1394         sal_printf("%s: Qset show failed: qset=%d has not been created\n",
   1395                    cmd, qset_num);
   1396         return CMD_FAIL;
   1397     }
   1398 
   1399     sal_printf("     QSET = %d\n", qset_num);
   1400     display_qset(fp_qset_tbl[qset_num].qset);
   1401 
   1402     return CMD_OK;
   1403 }
   1404 
   1405 #endif  /* BCM_FIELD_SUPPORT */
   1406 #endif  /* INCLUDE_BCMX */