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

knetctrl.c (20554B)


      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:        knetctrl.c
      8  * Purpose:     Kernel network control
      9  * Requires:    
     10  */
     11 
     12 
     13 #ifdef INCLUDE_KNET
     14 
     15 #include <sal/appl/sal.h>
     16 
     17 #include <soc/knet.h>
     18 
     19 #include <bcm/knet.h>
     20 
     21 #include <appl/diag/shell.h>
     22 #include <appl/diag/parse.h>
     23 #include <appl/diag/system.h>
     24 
     25 #include <shared/bsl.h>
     26 
     27 char cmd_knet_ctrl_usage[] =
     28     "Usages:\n"
     29 #ifdef COMPILER_STRING_CONST_LIMIT
     30     "  knetctrl <subcmd> [options]\n"
     31 #else
     32     "  knetctrl netif create [Vlan=<vlan>] [Port=<port>] [RCPU=yes|no]\n"
     33     "        Create a virtual network interface.\n"
     34     "        Supported options:\n"
     35     "          [AddTag=yes|no]      - Add tag before sending to switch port\n"
     36     "          [KeepRxTag=yes|no]   - Keep tag of packets which are sent to this netif\n"
     37     "          [IFName=<str>]       - Optional network device name\n"
     38     "          [CBData=<val>]       - User data for knet rx cb\n"
     39     "  knetctrl netif destroy <id>\n"
     40     "        Destroy a virtual network interface.\n"
     41     "  knetctrl netif show\n"
     42     "        Show virtual network interfaces.\n"
     43     "  knetctrl filter create DestType=Null|NetIF|RxAPI [DestID=<id>] [options]\n"
     44     "        Create a packet filter.\n"
     45     "        DestID is required for DestType=NetIF only.\n"
     46     "        Supported options:\n"
     47     "          [DESCription=<str>]  - Optional filter description\n"
     48     "          [PRIOrity=<prio>]    - Filter match order priority (0 is highest)\n"
     49     "          [StripTag=yes|no]    - Strip VLAN tag before sending packet to NetIF\n"
     50     "          [Mirror=yes|no]      - Copy packet to RxAPI (if DestType=NetIF)\n"
     51     "          [DestProto=<proto>]  - Override default protocol (if DestType=NetIF)\n"
     52     "          [Vlan=<vlan>]        - Match specified VLAN ID\n"
     53     "          [IngPort=<port>]     - Match specified local ingress port\n"
     54     "          [SrcPort=<port>]     - Match specified module port\n"
     55     "          [SrcModid=<modid>]   - Match specified module ID\n"
     56     "          [Reason=<reason>]    - Match specified reason for copy to CPU\n"
     57     "          [FPRule=<rule>]      - Match specified FP rule number (if FP match)\n"
     58     "          [PktOffset=<offet>]  - Match packet data starting at this offset\n"
     59     "          [PktByteX=<val>]     - Match packet data byte X (X=[0..7] supported)\n"
     60     "          [PktByte0=<val>]     - Match packet data byte 0 (example)\n"
     61     "          [CBData=<val>]       - User data for knet rx cb\n"
     62     "  knetctrl filter destroy <id>\n"
     63     "        Destroy a packet filter.\n"
     64     "  knetctrl filter show\n"
     65     "        Show all packet filters.\n"
     66     "  knetctrl debugpkt [on|off|show]\n"
     67     "        Enable/Disable debugging packet function.\n"
     68     "        Once enabling this function, there will be one packet copy being\n"
     69     "        sent/mirrored to RX API for debugging usage.\n"
     70 #endif
     71     ;
     72 
     73 /* Note:  See knet.h, BCM_KNET_NETIF_T_xxx */
     74 STATIC char *netif_type[] = {
     75     "unknown", "Vlan", "Port", "Meta", NULL
     76 };
     77 
     78 /* Note:  See knet.h, BCM_KNET_DEST_T_xxx */
     79 STATIC char *filter_dest_type[] = {
     80     "Null", "NetIF", "RxAPI", "CallBack", NULL
     81 };
     82 
     83 STATIC char *reason_str[bcmRxReasonCount+1] = BCM_RX_REASON_NAMES_INITIALIZER;
     84 
     85 STATIC void
     86 _show_netif(int unit, bcm_knet_netif_t *netif)
     87 {
     88     char *type_str = "?";
     89     char *port_str = "n/a";
     90 
     91     switch (netif->type) {
     92     case BCM_KNET_NETIF_T_TX_CPU_INGRESS:
     93     case BCM_KNET_NETIF_T_TX_META_DATA:
     94         type_str = netif_type[netif->type];
     95         break;
     96     case BCM_KNET_NETIF_T_TX_LOCAL_PORT:
     97         type_str = netif_type[netif->type];
     98         port_str = BCM_PORT_NAME(unit, netif->port);
     99         break;
    100     default:
    101         break;
    102     }
    103 
    104     cli_out("Interface ID %d: name=%s type=%s vlan=%d port=%s",
    105             netif->id, netif->name, type_str, netif->vlan, port_str);
    106 
    107     if (netif->flags & BCM_KNET_NETIF_F_ADD_TAG) {
    108         cli_out(" addtag");
    109     }
    110     if (netif->flags & BCM_KNET_NETIF_F_RCPU_ENCAP) {
    111         cli_out(" rcpu");
    112     }
    113     if (netif->flags & BCM_KNET_NETIF_F_KEEP_RX_TAG) {
    114         cli_out(" keeprxtag");
    115     }
    116     cli_out("\n");
    117 }
    118 
    119 STATIC int
    120 _trav_netif(int unit, bcm_knet_netif_t *netif, void *user_data)
    121 {
    122     int *count = (int *)user_data;
    123 
    124     _show_netif(unit, netif);
    125 
    126     if (count) {
    127         (*count)++;
    128     }
    129 
    130     return BCM_E_NONE;
    131 }
    132 
    133 static void
    134 _show_filter(int unit, bcm_knet_filter_t *filter)
    135 {
    136     char *dest_str = "?";
    137     char proto_str[16];
    138     int idx, edx;
    139 
    140     switch (filter->dest_type) {
    141     case BCM_KNET_DEST_T_NULL:
    142     case BCM_KNET_DEST_T_NETIF:
    143     case BCM_KNET_DEST_T_BCM_RX_API:
    144     case BCM_KNET_DEST_T_CALLBACK:
    145         dest_str = filter_dest_type[filter->dest_type];
    146         break;
    147     default:
    148         break;
    149     }
    150 
    151     proto_str[0] = 0;
    152     if (filter->dest_proto) {
    153         sal_sprintf(proto_str, "[0x%04x]", filter->dest_proto);
    154     }
    155         cli_out("Filter ID %d: prio=%d dest=%s(%d)%s desc='%s'",
    156                 filter->id, filter->priority, dest_str,
    157                 filter->dest_id, proto_str, filter->desc);
    158     if (filter->mirror_type ==  BCM_KNET_DEST_T_BCM_RX_API) {
    159         cli_out(" mirror=rxapi");
    160     } else if (filter->mirror_type ==  BCM_KNET_DEST_T_NETIF) {
    161         proto_str[0] = 0;
    162         if (filter->mirror_proto) {
    163             sal_sprintf(proto_str, "[0x%04x]", filter->mirror_proto);
    164         }
    165         cli_out(" mirror=netif(%d)%s", filter->mirror_id, proto_str);
    166     }
    167     if (filter->flags & BCM_KNET_FILTER_F_STRIP_TAG) {
    168         cli_out(" striptag");
    169     }
    170     if (filter->match_flags & BCM_KNET_FILTER_M_VLAN) {
    171         cli_out(" vlan=%d", filter->m_vlan);
    172     }
    173     if (filter->match_flags & BCM_KNET_FILTER_M_INGPORT) {
    174         cli_out(" ingport=%s", BCM_PORT_NAME(unit, filter->m_ingport));
    175     }
    176     if (filter->match_flags & BCM_KNET_FILTER_M_SRC_MODID) {
    177         cli_out(" srcmod=%d", filter->m_src_modid);
    178     }
    179     if (filter->match_flags & BCM_KNET_FILTER_M_SRC_MODPORT) {
    180         cli_out(" srcport=%d", filter->m_src_modport);
    181     }
    182     if (filter->match_flags & BCM_KNET_FILTER_M_FP_RULE) {
    183         cli_out(" fprule=%d", filter->m_fp_rule);
    184     }
    185     if (filter->match_flags & BCM_KNET_FILTER_M_REASON) {
    186         cli_out(" reason=");
    187         for (idx = 0; idx < bcmRxReasonCount; idx++) {
    188             if (BCM_RX_REASON_GET(filter->m_reason, idx)) {
    189                 cli_out("%s", reason_str[idx]);
    190                 break;
    191             }
    192         }
    193     }
    194     if (filter->match_flags & BCM_KNET_FILTER_M_RAW) {
    195         cli_out(" rawdata");
    196         for (idx = 0; idx < filter->raw_size; idx++) {
    197             if (filter->m_raw_mask[idx]) {
    198                 break;
    199             }
    200         }
    201         for (edx = filter->raw_size - 1; edx > idx; edx--) {
    202             if (filter->m_raw_mask[edx]) {
    203                 break;
    204             }
    205         }
    206         if (edx < idx) {
    207             /* Entire mask is empty - should not happen */
    208             cli_out("?");
    209         } else {
    210             /* Show offset of first valid byte */
    211             cli_out("[%d]", idx);
    212             /* Dump data */
    213             for (; idx <= edx; idx++) {
    214                 if (filter->m_raw_mask[idx]) {
    215                     cli_out(":0x%02x", filter->m_raw_data[idx]);
    216                     if (filter->m_raw_mask[idx] != 0xff) {
    217                         cli_out("/0x%02x", filter->m_raw_mask[idx]);
    218                     }
    219                 } else {
    220                     cli_out(":-"); 
    221                 }
    222             }
    223         }
    224     }
    225     cli_out("\n");
    226 }
    227 
    228 STATIC int
    229 _trav_filter(int unit, bcm_knet_filter_t *filter, void *user_data)
    230 {
    231     int *count = (int *)user_data;
    232 
    233     _show_filter(unit, filter);
    234 
    235     if (count) {
    236         (*count)++;
    237     }
    238 
    239     return BCM_E_NONE;
    240 }
    241 
    242 cmd_result_t
    243 cmd_knet_ctrl(int unit, args_t *args)
    244 {
    245     parse_table_t  pt;
    246     char *subcmd;
    247     int rv;
    248     int idx, pdx, count;
    249     int if_id;
    250     int if_type;
    251     int if_vlan;
    252     int if_port;
    253     int if_addtag;
    254     int if_rcpu;
    255     char *if_name;
    256     int pf_id;
    257     int pf_prio;
    258     int pf_dest_type;
    259     int pf_dest_id;
    260     int pf_striptag;
    261     int pf_mirror;
    262     int pf_mirror_id;
    263     int pf_vlan;
    264     int pf_ingport;
    265     int pf_src_modport;
    266     int pf_src_modid;
    267     int pf_reason;
    268     int pf_fp_rule;
    269     char *pf_desc;
    270     uint32 pkt_offset;
    271     int pkt_data[8];
    272     bcm_knet_netif_t netif;
    273     bcm_knet_filter_t filter;
    274     int pf_dest_proto;
    275     int pf_mirror_proto;
    276     int if_keeprxtag;
    277     int if_cb_user_data;
    278     int pf_cb_user_data;
    279 
    280     if ((subcmd = ARG_GET(args)) == NULL) {
    281         cli_out("Requires string argument\n");
    282         return CMD_USAGE;
    283     }
    284     if (sal_strcasecmp(subcmd, "netif") == 0) {
    285         if ((subcmd = ARG_GET(args)) == NULL) {
    286             cli_out("Requires additional string argument\n");
    287             return CMD_USAGE;
    288         }
    289         if (sal_strcasecmp(subcmd, "create") == 0) {
    290             if_type = BCM_KNET_NETIF_T_TX_CPU_INGRESS;
    291             if_vlan = 1;
    292             if_port = -1;
    293             if_addtag = 0;
    294             if_rcpu = 0;
    295             if_name = NULL;
    296             if_keeprxtag = 0;
    297             if_cb_user_data = 0;
    298             parse_table_init(unit, &pt);
    299             parse_table_add(&pt, "Type", PQ_DFL|PQ_MULTI, 0, &if_type, netif_type);
    300             parse_table_add(&pt, "Vlan", PQ_DFL|PQ_INT, 0, &if_vlan, 0);
    301             parse_table_add(&pt, "Port", PQ_DFL|PQ_PORT, 0, &if_port, 0);
    302             parse_table_add(&pt, "AddTag", PQ_DFL|PQ_BOOL, 0, &if_addtag, 0);
    303             parse_table_add(&pt, "KeepRxTag", PQ_DFL|PQ_BOOL, 0, &if_keeprxtag, 0);
    304             parse_table_add(&pt, "RCPU", PQ_DFL|PQ_BOOL, 0, &if_rcpu, 0);
    305             parse_table_add(&pt, "IFName", PQ_DFL|PQ_STRING, 0, &if_name, 0);
    306             parse_table_add(&pt, "CBData", PQ_DFL|PQ_INT, 0, &if_cb_user_data, 0);
    307             if (parse_arg_eq(args, &pt) < 0) {
    308                 parse_arg_eq_done(&pt);
    309                 return CMD_USAGE;
    310             }
    311             bcm_knet_netif_t_init(&netif);
    312             if (if_name) {
    313                 sal_strncpy(netif.name, if_name, sizeof(netif.name) - 1);
    314             }
    315             parse_arg_eq_done(&pt);
    316             /* Force port mode if port was specified */
    317             if (if_port >= 0) {
    318                 if_type = BCM_KNET_NETIF_T_TX_LOCAL_PORT;
    319             }
    320             /* Force meta mode if RCPU was specified */
    321             if (if_rcpu) {
    322                 if_type = BCM_KNET_NETIF_T_TX_META_DATA;
    323             }
    324             netif.type = if_type;
    325             netif.vlan = if_vlan;
    326             if (if_port >= 0) {
    327                 netif.port = if_port;
    328             }
    329             if (if_addtag) {
    330                 netif.flags |= BCM_KNET_NETIF_F_ADD_TAG;
    331             }
    332             if (if_rcpu) {
    333                 netif.flags |= BCM_KNET_NETIF_F_RCPU_ENCAP;
    334             }
    335             if (if_keeprxtag) {
    336                 netif.flags |= BCM_KNET_NETIF_F_KEEP_RX_TAG;
    337             }
    338             netif.cb_user_data = if_cb_user_data;
    339             if ((rv = bcm_knet_netif_create(unit, &netif)) < 0) {
    340                 cli_out("Error creating network interface: %s\n",
    341                         bcm_errmsg(rv));
    342                 return CMD_FAIL;
    343             }
    344             _show_netif(unit, &netif);
    345         } else if (sal_strcasecmp(subcmd, "destroy") == 0) {
    346             if (!ARG_CNT(args) || !isint(ARG_CUR(args))) {
    347                 return(CMD_USAGE);
    348             }
    349             if_id = parse_integer(ARG_GET(args));
    350             if ((rv = bcm_knet_netif_destroy(unit, if_id)) < 0) {
    351                 cli_out("Error destroying network interface: %s\n",
    352                         bcm_errmsg(rv));
    353                 return CMD_FAIL;
    354             }
    355         } else if (sal_strcasecmp(subcmd, "show") == 0) {
    356             count = 0;
    357             if (bcm_knet_netif_traverse(unit, _trav_netif, &count) < 0) {
    358                 return CMD_FAIL;
    359             }
    360             if (count == 0) {
    361                 cli_out("<no network interfaces>\n");
    362             }
    363         } else {
    364             cli_out("Subcommand not found: %s\n", subcmd);
    365             return CMD_USAGE;
    366         }
    367     } else if (sal_strcasecmp(subcmd, "filter") == 0) {
    368         if ((subcmd = ARG_GET(args)) == NULL) {
    369             cli_out("Requires string argument\n");
    370             return CMD_USAGE;
    371         }
    372         if (sal_strcasecmp(subcmd, "create") == 0) {
    373             pf_dest_type = BCM_KNET_DEST_T_NULL;
    374             pf_dest_id = -1;
    375             pf_mirror = 0;
    376             pf_mirror_id = 0;
    377             pf_vlan = -1;
    378             pf_ingport = -1;
    379             pf_src_modport = -1;
    380             pf_src_modid = -1;
    381             pf_reason = bcmRxReasonInvalid;
    382             pf_fp_rule = -1;
    383             pkt_offset = 0;
    384             for (idx = 0; idx < COUNTOF(pkt_data); idx++) {
    385                 pkt_data[idx] = -1;
    386             }
    387             pf_desc = NULL;
    388             pf_prio = 0;
    389             pf_striptag = 1;
    390             pf_dest_proto = 0;
    391             pf_mirror_proto = 0;
    392             pf_cb_user_data = 0;
    393             parse_table_init(unit, &pt);
    394             parse_table_add(&pt, "DestType", PQ_DFL|PQ_MULTI, 0, &pf_dest_type,
    395                             filter_dest_type);
    396             parse_table_add(&pt, "DestID", PQ_DFL|PQ_INT, 0, &pf_dest_id, 0);
    397             parse_table_add(&pt, "PRIOrity", PQ_DFL|PQ_INT, 0, &pf_prio, 0);
    398             parse_table_add(&pt, "DESCription", PQ_DFL|PQ_STRING, 0, &pf_desc, 0);
    399             parse_table_add(&pt, "StripTag", PQ_DFL|PQ_BOOL, 0, &pf_striptag, 0);
    400             parse_table_add(&pt, "Mirror", PQ_DFL|PQ_BOOL, 0, &pf_mirror, 0);
    401             parse_table_add(&pt, "MirrorID", PQ_DFL|PQ_INT, 0, &pf_mirror_id, 0);
    402             parse_table_add(&pt, "Vlan", PQ_DFL|PQ_INT, 0, &pf_vlan, 0);
    403             parse_table_add(&pt, "IngPort", PQ_DFL|PQ_PORT, 0, &pf_ingport, 0);
    404             parse_table_add(&pt, "SrcPort", PQ_DFL|PQ_INT, 0, &pf_src_modport, 0);
    405             parse_table_add(&pt, "SrcModid", PQ_DFL|PQ_INT, 0, &pf_src_modid, 0);
    406             parse_table_add(&pt, "Reason", PQ_DFL|PQ_MULTI, 0, &pf_reason,
    407                             reason_str);
    408             parse_table_add(&pt, "FPRule", PQ_DFL|PQ_INT, 0, &pf_fp_rule, 0);
    409             parse_table_add(&pt, "PktOffset", PQ_DFL|PQ_HEX, 0, &pkt_offset, 0);
    410             parse_table_add(&pt, "PktByte0", PQ_DFL|PQ_INT, 0, &pkt_data[0], 0);
    411             parse_table_add(&pt, "PktByte1", PQ_DFL|PQ_INT, 0, &pkt_data[1], 0);
    412             parse_table_add(&pt, "PktByte2", PQ_DFL|PQ_INT, 0, &pkt_data[2], 0);
    413             parse_table_add(&pt, "PktByte3", PQ_DFL|PQ_INT, 0, &pkt_data[3], 0);
    414             parse_table_add(&pt, "PktByte4", PQ_DFL|PQ_INT, 0, &pkt_data[4], 0);
    415             parse_table_add(&pt, "PktByte5", PQ_DFL|PQ_INT, 0, &pkt_data[5], 0);
    416             parse_table_add(&pt, "PktByte6", PQ_DFL|PQ_INT, 0, &pkt_data[6], 0);
    417             parse_table_add(&pt, "PktByte7", PQ_DFL|PQ_INT, 0, &pkt_data[7], 0);
    418             parse_table_add(&pt, "DestProto", PQ_DFL|PQ_INT, 0, &pf_dest_proto, 0);
    419             parse_table_add(&pt, "MirrorProto", PQ_DFL|PQ_INT, 0, &pf_mirror_proto, 0);
    420             parse_table_add(&pt, "CBData", PQ_DFL|PQ_INT, 0, &pf_cb_user_data, 0);
    421             if (parse_arg_eq(args, &pt) < 0) {
    422                 parse_arg_eq_done(&pt);
    423                 return CMD_USAGE;
    424             }
    425             bcm_knet_filter_t_init(&filter);
    426             filter.type = BCM_KNET_FILTER_T_RX_PKT;
    427             if (pf_desc) {
    428                 sal_strncpy(filter.desc, pf_desc, sizeof(filter.desc) - 1);
    429             }
    430             parse_arg_eq_done(&pt);
    431 
    432             filter.priority = pf_prio;
    433             filter.dest_type = pf_dest_type;
    434             filter.dest_id = pf_dest_id;
    435             filter.dest_proto = pf_dest_proto;
    436             /*
    437              * Specifying a mirror ID implies mirroring to another
    438              * netif.  Enabling mirroring while leaving mirror ID at
    439              * zero implies mirroring to the Rx API.
    440              */
    441             if (pf_mirror_id) {
    442                 pf_mirror = 1;
    443             }
    444             if (pf_dest_type == BCM_KNET_DEST_T_NETIF && pf_mirror) {
    445                 filter.mirror_type = BCM_KNET_DEST_T_BCM_RX_API;
    446                 if (pf_mirror_id) {
    447                     filter.mirror_type = BCM_KNET_DEST_T_NETIF;
    448                     filter.mirror_id = pf_mirror_id;
    449                     filter.mirror_proto = pf_mirror_proto;
    450                 }
    451             }
    452             if (pf_striptag) {
    453                 filter.flags |= BCM_KNET_FILTER_F_STRIP_TAG;
    454             }
    455             filter.cb_user_data = pf_cb_user_data;
    456             if (pf_vlan >= 0) {
    457                 filter.m_vlan = pf_vlan;
    458                 filter.match_flags |= BCM_KNET_FILTER_M_VLAN;
    459             }
    460             if (pf_ingport >= 0) {
    461                 filter.m_ingport = pf_ingport;
    462                 filter.match_flags |= BCM_KNET_FILTER_M_INGPORT;
    463             }
    464             if (pf_src_modport >= 0) {
    465                 filter.m_src_modport = pf_src_modport;
    466                 filter.match_flags |= BCM_KNET_FILTER_M_SRC_MODPORT;
    467             }
    468             if (pf_src_modid >= 0) {
    469                 filter.m_src_modid = pf_src_modid;
    470                 filter.match_flags |= BCM_KNET_FILTER_M_SRC_MODID;
    471             }
    472             if (pf_reason != bcmRxReasonInvalid) {
    473                 BCM_RX_REASON_SET(filter.m_reason, pf_reason);
    474                 filter.match_flags |= BCM_KNET_FILTER_M_REASON;
    475             }
    476             if (pf_fp_rule >= 0) {
    477                 filter.m_fp_rule = pf_fp_rule;
    478                 filter.match_flags |= BCM_KNET_FILTER_M_FP_RULE;
    479             }
    480             for (idx = 0; idx < COUNTOF(pkt_data); idx++) {
    481                 pdx = pkt_offset + idx;
    482                 if (pdx >= sizeof(filter.m_raw_data)) {
    483                     cli_out("PktOffset too large - max is %d\n",
    484                             (int)sizeof(filter.m_raw_data) - COUNTOF(pkt_data));
    485                     return CMD_USAGE;
    486                 }
    487                 if (pkt_data[idx] >= 0) {
    488                     filter.raw_size = pdx + 1;
    489                     filter.match_flags |= BCM_KNET_FILTER_M_RAW;
    490                     filter.m_raw_data[pdx] = (uint8)pkt_data[idx];
    491                     filter.m_raw_mask[pdx] = 0xff;
    492                 }
    493             }
    494             if ((rv = bcm_knet_filter_create(unit, &filter)) < 0) {
    495                 cli_out("Error creating packet filter: %s\n",
    496                         bcm_errmsg(rv));
    497                 return CMD_FAIL;
    498             }
    499             _show_filter(unit, &filter);
    500         } else if (sal_strcasecmp(subcmd, "destroy") == 0) {
    501             if (!ARG_CNT(args) || !isint(ARG_CUR(args))) {
    502                 return(CMD_USAGE);
    503             }
    504             pf_id = parse_integer(ARG_GET(args));
    505             if ((rv = bcm_knet_filter_destroy(unit, pf_id)) < 0) {
    506                 cli_out("Error destroying packet filter: %s\n",
    507                         bcm_errmsg(rv));
    508                 return CMD_FAIL;
    509             }
    510         } else if (sal_strcasecmp(subcmd, "show") == 0) {
    511             count = 0;
    512             if (bcm_knet_filter_traverse(unit, _trav_filter, &count) < 0) {
    513                 return CMD_FAIL;
    514             }
    515             if (count == 0) {
    516                 cli_out("<no filters>\n");
    517             }
    518         } else {
    519             cli_out("Subcommand not found: %s\n", subcmd);
    520             return CMD_USAGE;
    521         }
    522     } else if (sal_strcasecmp(subcmd, "debugpkt") == 0) {
    523         if ((subcmd = ARG_GET(args)) == NULL) {
    524             cli_out("Requires string argument\n");
    525             return CMD_USAGE;
    526         }
    527 
    528         if (sal_strcasecmp(subcmd, "on") == 0) {
    529             if (soc_knet_debug_pkt_set(unit, TRUE) < 0) {
    530                 return CMD_FAIL;
    531             }
    532         } else if (sal_strcasecmp(subcmd, "off") == 0) {
    533             if (soc_knet_debug_pkt_set(unit, FALSE) < 0) {
    534                 return CMD_FAIL;
    535             }
    536         } else if (sal_strcasecmp(subcmd, "show") == 0) {
    537             int value = 0;
    538             if (soc_knet_debug_pkt_get(unit, &value) < 0) {
    539                 return CMD_FAIL;
    540             }
    541 
    542             if (TRUE == value) {
    543                 cli_out("Knet debugging packet function is on!\n");
    544             } else {
    545                 cli_out("Knet debugging packet function is off!\n");
    546             }
    547         } else {
    548             cli_out("Subcommand not found: %s\n", subcmd);
    549             return CMD_USAGE;
    550         }
    551     } else {
    552         cli_out("Subcommand not found: %s\n", subcmd);
    553         return CMD_USAGE;
    554     }
    555     return CMD_OK;
    556 }
    557 
    558 #else
    559 int _knetctrl_not_empty;
    560 #endif