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

regex.c (36704B)


      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:        txrx.c
      8  * Purpose:
      9  * Requires:    
     10  */
     11 
     12 #ifdef INCLUDE_REGEX
     13 #include <sal/types.h>
     14 #include <sal/core/time.h>
     15 #include <sal/core/thread.h>
     16 #include <sal/core/libc.h>
     17 #include <sal/appl/sal.h>
     18 #include <sal/appl/io.h>
     19 #include <shared/bsl.h>
     20 #include <soc/types.h>
     21 #include <soc/debug.h>
     22 
     23 #ifdef __KERNEL__
     24 #include <linux/kernel.h>
     25 #include <linux/net.h>
     26 #include <linux/in.h>
     27 #define atoi _shr_ctoi 
     28 #else
     29 #include <stdlib.h>
     30 #include <sys/types.h>
     31 #include <sys/socket.h>
     32 #include <net/if.h>
     33 #include <netinet/in.h>
     34 #endif
     35 
     36 #include <bcm/port.h>
     37 #include <bcm/error.h>
     38 
     39 #include <appl/diag/system.h>
     40 #include <bcm/bregex.h>
     41 
     42 #ifndef NO_FILEIO 
     43 char cmd_regex_usage[] = 
     44 "Parameters\n"
     45 "\tcreate <file> -- load the patterns from file\n"
     46 "\tdestroy [engine] -- destroy all engines or [specific engine]\n"
     47 "\tmonitor [start|stop|verbose|silent] -- send reports for flows/matches\n"
     48 "\tlist -- list configured regex engines\n"
     49 "\tshow [engine [engineid] | dfa [engineid] | info [engineid] | policer [id] | policy [id] | session [stats] | match stats | axp]\n"
     50 ;
     51 
     52 typedef struct xd_s {  
     53     pbmp_t      pbmp; 
     54     char        *xd_file;
     55 } xd_t;
     56 
     57 #define MAX_PATTERN_PER_ENGINE 128
     58 
     59 typedef struct diag_regex_engine_info_s {
     60     char                filename[256];
     61     int                 num_match;
     62     char                app_name[MAX_PATTERN_PER_ENGINE][64];
     63     bcm_regex_match_t   match[MAX_PATTERN_PER_ENGINE];
     64     bcm_regex_engine_t  engid;
     65     struct diag_regex_engine_info_s *next;
     66 } diag_regex_engine_info_t;
     67 
     68 static diag_regex_engine_info_t *engine_info_list[BCM_MAX_NUM_UNITS];
     69 #define MAX_ENGINE_PER_UNIT     64
     70 static bcm_regex_engine_t re_engines[BCM_MAX_NUM_UNITS][MAX_ENGINE_PER_UNIT];
     71 static int engine_count[BCM_MAX_NUM_UNITS];
     72 static int unit_inited[BCM_MAX_NUM_UNITS];
     73 static int re_inited = 0;
     74 
     75 /*
     76 Memory to store engines not created by the BCM command interface
     77 */
     78 static bcm_regex_engine_t   l_re_engines[BCM_MAX_NUM_UNITS][MAX_ENGINE_PER_UNIT];
     79 static int                  l_engine_count[BCM_MAX_NUM_UNITS];
     80 
     81 static int regex_cmd_init(void)
     82 {
     83     if (re_inited) {
     84         return 0;
     85     }
     86     
     87     sal_memset(engine_info_list, 0, sizeof(diag_regex_engine_info_t*)*BCM_MAX_NUM_UNITS);
     88     sal_memset(engine_count, 0, sizeof(int)*BCM_MAX_NUM_UNITS);
     89     re_inited = 1;
     90     return 0;
     91 }
     92 
     93 static int initialize_regex(int unit, int init)
     94 {
     95     bcm_regex_config_t  recfg;
     96     int i, rv, port;
     97     soc_pbmp_t  pbmp_temp;
     98     
     99     /* Set default configuration */
    100     recfg.flags = BCM_REGEX_CONFIG_ENABLE | BCM_REGEX_CONFIG_IP4 |
    101                   BCM_REGEX_CONFIG_IP6 | BCM_REGEX_CONFIG_TCP_SESSION_DETECT;
    102     recfg.max_flows = -1; /* max flows */
    103     recfg.payload_depth = -1;
    104     recfg.inspect_num_pkt = -1;
    105     recfg.inactivity_timeout_usec = 100;
    106     recfg.report_flags = BCM_REGEX_REPORT_NEW | BCM_REGEX_REPORT_MATCHED | 
    107                          BCM_REGEX_REPORT_END;
    108     recfg.dst_mac[0] = 0x00;
    109     for (i=1;i<6;i++) {
    110         recfg.dst_mac[i] = 0xa0 + i;
    111     }
    112     recfg.src_mac[0] = 0x00;
    113     for (i=1;i<6;i++) {
    114         recfg.src_mac[i] = 0xb0 + i;
    115     }
    116     recfg.ethertype = 0x0531;
    117     rv = bcm_regex_config_set(unit, &recfg);
    118     if (rv) {
    119         return CMD_FAIL;
    120     }
    121 
    122     /* Enable regex on the ports */
    123     BCM_PBMP_ASSIGN(pbmp_temp, PBMP_GE_ALL(unit));
    124     BCM_PBMP_ITER(pbmp_temp, port) {
    125         bcm_port_control_set(unit, port, bcmPortControlRegex, init ? 1 : 0);
    126     }
    127 
    128     unit_inited[unit] = !!init;
    129     return 0;
    130 }
    131 
    132 
    133 static cmd_result_t
    134 regex_parse_args(int u, args_t *a, xd_t *xd)
    135 {
    136     parse_table_t       pt;
    137     char                *xfile = NULL;
    138 
    139     parse_table_init(u, &pt);
    140 
    141     parse_table_add(&pt, "Filename", PQ_DFL|PQ_STRING,0, &xfile,NULL);
    142 
    143     if (parse_arg_eq(a, &pt) < 0) {
    144         sal_printf("Error: Unknown option: %s\n", ARG_CUR(a));
    145         parse_arg_eq_done(&pt);
    146         return(CMD_FAIL);
    147     }
    148 
    149     if (xfile) {
    150         xd->xd_file = sal_strdup(xfile);
    151     } else {
    152         xd->xd_file = NULL;
    153     }
    154 
    155     parse_arg_eq_done(&pt);
    156     return(0);
    157 }
    158 
    159 static int _read_line(FILE *fp, char *b, int *len)
    160 {
    161     int c;
    162     int l = 0;  
    163 
    164     c = getc(fp);
    165     while (!((c == EOF) || (c == '\n') || (c == '\r'))) {
    166         b[l++] = c;
    167         c = getc(fp);
    168     }
    169 
    170     *len = l;
    171     b[l] = '\0';
    172     if (l) {
    173         return 0;
    174     }
    175 
    176     return (c == EOF) ? -1 : 0;
    177 }
    178 
    179 static char* _strip_front(char *l, int len)
    180 {
    181     int i=0;
    182 
    183     /* skip leading spaces. */
    184     while (i < len) {
    185         if ((l[i] == ' ') || (l[i] == '\t')) {
    186             i++;
    187             continue;
    188         }
    189         return &l[i];
    190     }
    191     return NULL;
    192 }
    193 
    194 static int decode_app_name(char* s, diag_regex_engine_info_t *app)
    195 {
    196     sal_strcpy(&app->app_name[app->num_match][0], s);
    197     return 0;
    198 }
    199 
    200 static int decode_match_id(char* s, diag_regex_engine_info_t *app)
    201 {
    202     app->match[app->num_match].match_id = atoi(s);
    203     return 0;
    204 }
    205 
    206 static int decode_flow_timeout(char* s, diag_regex_engine_info_t *app)
    207 {
    208     app->match[app->num_match].inactivity_timeout_usec = atoi(s);
    209     return 0;
    210 }
    211 
    212 static int decode_pattern(char* s, diag_regex_engine_info_t *app)
    213 {
    214     int j = 0, esc = 0;
    215 
    216     if (s[0] != '/') {
    217         return -1;
    218     }
    219 
    220     s++;
    221     sal_memset(app->match[app->num_match].pattern, 0, BCM_REGEX_MAX_PATTERN_SIZE);
    222     while (*s) {
    223         if (!esc && (*s == '/')) {
    224             return 0;
    225         }
    226         app->match[app->num_match].pattern[j] = *s;
    227         if (*s == '\\') {
    228             esc = !!esc;
    229         }
    230         j++;
    231         s++;
    232     }
    233 
    234     if (app->match[app->num_match].pattern[j-1] == '/') {
    235         app->match[app->num_match].pattern[j-1] = '\0';
    236         return 0;
    237     }
    238 
    239     return 1;
    240 }
    241 
    242 typedef struct regex_cmd_str_to_flag_s {
    243     char *name;
    244     unsigned int flag;
    245 } regex_cmd_str_to_flag_t;
    246 
    247 static regex_cmd_str_to_flag_t *
    248 regex_flag_get(char *str, regex_cmd_str_to_flag_t *tbl)
    249 {
    250     while (tbl->name) {
    251         if (!sal_strcasecmp(str, tbl->name)) {
    252             return tbl;
    253         }
    254         tbl++;
    255     }
    256     return NULL;
    257 }
    258 
    259 static int decode_flags_cmn(char* s, diag_regex_engine_info_t *app, 
    260                             regex_cmd_str_to_flag_t *tbl, 
    261                             unsigned int *pflag)
    262 {
    263     char *ts;
    264     int done = 0;
    265     regex_cmd_str_to_flag_t *ps2f;
    266 
    267     *pflag = 0;
    268 
    269     ts = s;
    270     while (!done) {
    271         /* skip leading spaces */
    272         while (*s && ((*s == ' ') || (*s == '\t'))) {
    273             s++;
    274         }
    275         if (!*s) {
    276             return 0;
    277         }
    278         ts = s;
    279         while (*s && (!((*s == ' ') || (*s == ',')))) {
    280             s++;
    281         }
    282         if (!*s) {
    283             done = 1;
    284         } else {
    285             *s = '\0';
    286             s++;
    287         }
    288         ps2f = regex_flag_get(ts, tbl);
    289         if (!ps2f) {
    290             cli_out("unknown regex action: %s\n", ts);
    291             return -1;
    292         }
    293         *pflag |= ps2f->flag;
    294     }
    295     return 0;
    296 }
    297 
    298 static int decode_enums(char* s, diag_regex_engine_info_t *app, 
    299                         regex_cmd_str_to_flag_t *tbl, 
    300                         unsigned int *value)
    301 {
    302     char *ts;
    303     int done = 0;
    304     regex_cmd_str_to_flag_t *ps2f;
    305 
    306     ts = s;
    307     while (!done) {
    308         /* skip leading spaces */
    309         while (*s && ((*s == ' ') || (*s == '\t'))) {
    310             s++;
    311         }
    312         if (!*s) {
    313             return 0;
    314         }
    315         ts = s;
    316         while (*s && (!((*s == ' ') || (*s == ',')))) {
    317             s++;
    318         }
    319         if (!*s) {
    320             done = 1;
    321         } else {
    322             *s = '\0';
    323             s++;
    324         }
    325         ps2f = regex_flag_get(ts, tbl);
    326         if (!ps2f) {
    327             cli_out("unknown regex action: %s\n", ts);
    328             return -1;
    329         }
    330         *value = ps2f->flag;
    331     }
    332     return 0;
    333 }
    334 static regex_cmd_str_to_flag_t flow_options[] = {
    335     { "to_server", BCM_REGEX_MATCH_TO_SERVER },
    336     { "to_client", BCM_REGEX_MATCH_TO_CLIENT },
    337     { "case", BCM_REGEX_MATCH_CASE_INSENSITIVE },
    338     { "http", BCM_REGEX_MATCH_MULTI_FLOW },
    339     { "none", 0 },
    340     { NULL, 0 }
    341 };
    342 
    343 static int decode_flowopt(char* s, diag_regex_engine_info_t *app)
    344 {
    345     int rv;
    346     
    347     rv = decode_flags_cmn( s, app, flow_options, 
    348                             &app->match[app->num_match].flags);
    349     if (rv) {
    350         return CMD_FAIL;
    351     }
    352     return 0;
    353 }
    354 
    355 static regex_cmd_str_to_flag_t flow_sequence[] = {
    356     { "first", 0},
    357     { "any", -1 },
    358     { NULL, 0 }
    359 };
    360 
    361 static int decode_flow_sequence(char* s, diag_regex_engine_info_t *app)
    362 {
    363     unsigned int val = 0;
    364     
    365     decode_enums(s, app, flow_sequence, &val);
    366     app->match[app->num_match].sequence = val;
    367     return 0;
    368 }
    369 
    370 static regex_cmd_str_to_flag_t match_actions[] = {
    371     { "ignore", BCM_REGEX_MATCH_ACTION_IGNORE },
    372     { "to_cpu", BCM_REGEX_MATCH_ACTION_COPY_TO_CPU },
    373     { "drop", BCM_REGEX_MATCH_ACTION_DROP },
    374     { "none", 0 },
    375     { NULL, 0 }
    376 };
    377 
    378 static int decode_action(char* s, diag_regex_engine_info_t *app)
    379 {
    380     int rv;
    381     
    382     rv = decode_flags_cmn( s, app, match_actions, 
    383                             &app->match[app->num_match].action_flags);
    384     if (rv) {
    385         return CMD_FAIL;
    386     }
    387     return 0;
    388 }
    389 
    390 static int decode_previous_tag(char* s, diag_regex_engine_info_t *app)
    391 {
    392     app->match[app->num_match].requires = atoi(s);
    393     return 0;
    394 }
    395 
    396 static int decode_next_tag(char* s, diag_regex_engine_info_t *app)
    397 {
    398     app->match[app->num_match].provides = atoi(s);
    399     return 0;
    400 }
    401 
    402 typedef int (*decode_tag_value)(char *buf, diag_regex_engine_info_t *app);
    403 
    404 typedef struct regex_xml_data_s {
    405     char            *tag_name;
    406     decode_tag_value decode_value;
    407 } regex_xml_data_t;
    408 
    409 static regex_xml_data_t regex_match_info[] = {
    410     { "engine", NULL},
    411     { "signature", NULL},
    412     { "application", decode_app_name },
    413     { "matchid", decode_match_id },
    414     { "pattern", decode_pattern },
    415     { "flowopt", decode_flowopt },
    416     { "sequence", decode_flow_sequence },
    417     { "timeout", decode_flow_timeout},
    418     { "previous_match_tag", decode_previous_tag },
    419     { "next_match_tag", decode_next_tag },
    420     { "action", decode_action},
    421     { NULL, NULL },
    422 };
    423 
    424 static regex_xml_data_t *regex_cmd_get_xml_tag(char *name)
    425 {
    426     regex_xml_data_t *ptag = regex_match_info;
    427     char *s = name;
    428 
    429     while(*s) {
    430         if (*s == '>') {
    431             *s = '\0';
    432         }
    433         s++;
    434     }
    435 
    436     while (ptag->tag_name) {
    437         if (!sal_strcasecmp(name, ptag->tag_name)) {
    438             return ptag;
    439         }
    440         ptag++;
    441     }
    442     return NULL;
    443 }
    444 
    445 /* each input line should be in the format:
    446  *  /pattern/id/action/
    447  */
    448 static int _parse_a_xml_line(char *l, int len, 
    449                              diag_regex_engine_info_t *einfo,
    450                              regex_xml_data_t **pptag, int *tag_start)
    451 {
    452     char *b;
    453     regex_xml_data_t *ptag;
    454 
    455     b = _strip_front(l, len);
    456     if (!b) { 
    457         return 0;
    458     }
    459 
    460     /* check if the line is commented */
    461     if (b[0] == '#') {
    462         return 0; /* line is commenetd */
    463     }
    464 
    465     if (b[0] == '<') {
    466         b++;
    467         *tag_start = 1;
    468         if (*b == '/') {
    469             *tag_start = 0;
    470             b++;
    471         }
    472         ptag = regex_cmd_get_xml_tag(b);
    473         if (!ptag) {
    474             cli_out("Unknown XML tag: %s\n", b);
    475             return -1;
    476         }
    477         *pptag = ptag;
    478         return 0;
    479     }
    480 
    481     ptag = *pptag;
    482     if (!ptag) {
    483         cli_out("Invalid tag");
    484         return -1;
    485     }
    486 
    487     /* decode the line accouding to provided tag */
    488     if (ptag->decode_value && (ptag->decode_value(b, einfo))) {
    489         cli_out("Failed to decode the line: %s\n", b);
    490         return -1;
    491     }
    492 
    493     return 0;
    494 }
    495 
    496 static cmd_result_t
    497 cmd_create_regex_engine(int unit, args_t *a)
    498 {
    499     FILE                *fp;
    500     char                line[512];
    501     int                 llen, rv, nume=0;
    502     xd_t                xd;
    503     diag_regex_engine_info_t    einfo[32], *papp;
    504     bcm_regex_match_t   match[64];
    505     regex_xml_data_t *ptag = NULL;
    506     int              tstart = 0, i, e, line_num = 0;
    507     bcm_regex_engine_t  reid;
    508     bcm_regex_engine_config_t eng_cfg;
    509 
    510     if (!SOC_UNIT_VALID(unit)) {
    511         return (CMD_FAIL);
    512     }
    513     sal_memset(&xd, 0, sizeof(xd_t));
    514     if (CMD_OK != (rv = regex_parse_args(unit, a, &xd))) {
    515         return(rv);
    516     }
    517 
    518     if (!xd.xd_file) {
    519         return CMD_FAIL;
    520     }
    521 
    522     if ((fp = sal_fopen(xd.xd_file, "r")) == NULL) {
    523         cli_out("Failed to open file: %s\n", xd.xd_file);
    524         return CMD_FAIL;
    525     }
    526 
    527     sal_memset(einfo, 0, sizeof(diag_regex_engine_info_t)*32);
    528     for (i = 0; i < sizeof(einfo)/sizeof(einfo[0]); i++) {
    529         for (e = 0; e < MAX_PATTERN_PER_ENGINE; e++) {
    530             bcm_regex_match_t_init(&einfo[i].match[e]);
    531         }
    532     }
    533 
    534     while(1) {
    535         /* parse the regex patterns from the file */
    536         line_num++;
    537         if (_read_line(fp, line, &llen)) {
    538             break;
    539         }
    540         if (_parse_a_xml_line(line, llen, &einfo[nume], &ptag, &tstart)) {
    541             cli_out("Error on line : %d\n", line_num);
    542             return CMD_FAIL;
    543         }
    544         if (ptag && (!sal_strcasecmp(ptag->tag_name, "signature")) &&
    545             tstart == 0) {
    546             sal_strcpy(einfo[nume].filename, xd.xd_file);
    547             einfo[nume].num_match++;
    548             ptag = NULL;
    549             tstart = 1;
    550         }
    551         if (ptag && (!sal_strcasecmp(ptag->tag_name, "engine")) &&
    552             tstart == 0) {
    553             nume++;
    554             ptag = NULL;
    555             tstart = 1;
    556         }
    557     }
    558 
    559     if (unit_inited[unit] == 0) {
    560         initialize_regex(unit, 1);
    561     }
    562 
    563     /* create an engine */
    564     eng_cfg.flags = 0;
    565     for (e=0; e<nume; e++) {
    566         rv = bcm_regex_engine_create(unit, &eng_cfg, &reid);
    567         if (rv) {
    568             cli_out("Failed to create regex engine : %d", rv);
    569             return CMD_FAIL;
    570         }
    571 
    572         re_engines[unit][engine_count[unit]++] = reid;
    573 
    574         /* Install the patterens */
    575         for (i = 0; i < einfo[e].num_match; i++) {
    576             sal_memcpy(&match[i], &einfo[e].match[i], sizeof(bcm_regex_match_t));
    577         }
    578         rv = bcm_regex_match_set(unit, reid, match, einfo[e].num_match);
    579         if (rv) {
    580             cli_out("Failed to install patterns : %d", rv);
    581             bcm_regex_engine_destroy(unit, reid);
    582             engine_count[unit]--;
    583             return CMD_FAIL;
    584         }
    585 
    586         einfo[e].engid = reid;
    587 
    588         /* store the match objects */
    589         for (i = 0; i< einfo[e].num_match; i++) {
    590             papp = sal_alloc(sizeof(diag_regex_engine_info_t), "einfo info");
    591             sal_memcpy(papp, &einfo[e], sizeof(diag_regex_engine_info_t));
    592             papp->engid = reid;
    593             papp->next = NULL;
    594             /* add to list  to corelate the event notifications */
    595             papp->next = engine_info_list[unit];
    596             engine_info_list[unit] = papp;
    597         }
    598     }
    599 
    600     if (xd.xd_file) {
    601         sal_free(xd.xd_file);
    602     }
    603     return (CMD_OK);
    604 }
    605 
    606 static int 
    607 _regex_diag_remove_engine_from_db(int unit, bcm_regex_engine_t engid)
    608 {
    609   int i, j;
    610     diag_regex_engine_info_t **ppapp, *papp;
    611 
    612     for (i = 0; i < engine_count[unit]; i++) {
    613         if (re_engines[unit][i] == engid) {
    614             for (j = i+1; j<engine_count[unit]; j++) {
    615                 re_engines[unit][j-1] = re_engines[unit][j];
    616             }
    617             engine_count[unit]--;
    618 
    619             /* remove from applist */
    620             ppapp = &engine_info_list[unit];
    621             while(*ppapp) {
    622                 papp = *ppapp;
    623                 if (papp->engid == engid) {
    624                     *ppapp = papp->next;
    625                     sal_free(papp);
    626                     return 0;
    627                 }
    628                 ppapp = &(*ppapp)->next;
    629             }
    630         }
    631     }
    632     return -1;
    633 }
    634 
    635 static int 
    636 _regex_destroy_engine_with_id(int unit, bcm_regex_engine_t engid,
    637                               bcm_regex_engine_config_t *config,
    638                               void *user_data)
    639 {
    640     int rv;
    641     bcm_regex_engine_t del_id = *((bcm_regex_engine_t*) user_data);
    642 
    643     if ((del_id == -1) || (del_id == engid)) {
    644         rv = bcm_regex_engine_destroy(unit, engid);
    645         if (rv) {
    646             cli_out("Failed to destroy engine: %d\n", engid);
    647             return -1;
    648         }
    649         _regex_diag_remove_engine_from_db(unit, engid);
    650     }
    651     return CMD_OK;
    652 }
    653 
    654 static cmd_result_t
    655 cmd_destroy_regex_engine(int unit, int engidx)
    656 {
    657     int rv;
    658     bcm_regex_engine_t eng_id = -1;
    659 
    660     if (engidx >= 0) {
    661         if (engidx >= engine_count[unit]) {
    662             cli_out("Invalid engine index. Not found\n");
    663             return CMD_FAIL;
    664         }
    665         eng_id = re_engines[unit][engidx];
    666     }
    667    
    668     rv = bcm_regex_engine_traverse(unit, 
    669                                   _regex_destroy_engine_with_id, (void*) &eng_id);
    670     if (engine_count[unit] == 0) {
    671         initialize_regex(unit, 0);
    672     }
    673     return rv ? CMD_FAIL : CMD_OK;
    674 }
    675 
    676 static int verbose = 1;
    677 static void bcm_regex_diag_report_cb(int unit, bcm_regex_report_t *report, 
    678                                     void *user_data)
    679 {
    680     int valid_flag = 0;
    681     char flow_type[64], *pos = flow_type;
    682 
    683     if (!verbose) {
    684         return;
    685     }
    686     
    687     cli_out("-----------------------------------\n");
    688     if (report->flags & BCM_REGEX_REPORT_NEW)
    689     {
    690         strcpy(pos, "New ");
    691         valid_flag = 1;
    692         pos += 4;
    693     }
    694     if (report->flags & BCM_REGEX_REPORT_MATCHED)
    695     {
    696         strcpy(pos, "Matched ");
    697         valid_flag = 1;
    698         pos += 8;
    699     }
    700     if (report->flags & BCM_REGEX_REPORT_END)
    701     {
    702         strcpy(pos, "End ");
    703         valid_flag = 1;
    704         pos += 4;
    705     }
    706     if (0 == valid_flag)
    707     {
    708         strcpy(pos, "Unknown-Event");
    709         cli_out("Unknown-Event");
    710         pos += 13;
    711     }
    712     *pos = '\0';
    713     cli_out("Flow is: %s\n", flow_type);
    714     cli_out("\n");
    715     cli_out("matchID   = %d\n", report->match_id);
    716     cli_out("match_flags     =   0x%08x\n", report->match_flags);
    717     cli_out("flags           =   0x%08x\n", report->flags);
    718     cli_out("direction       =   %s\n", report->match_flags & BCM_REGEX_MATCH_TO_SERVER ? "To server" : "To client");
    719     cli_out("protocol        =   %d (0x%02x)\n", report->protocol, report->protocol);
    720     cli_out("src_port        =   %d (0x%04x)\n", report->src_port, report->src_port);
    721     cli_out("dst_port        =   %d (0x%04x)\n", report->dst_port, report->dst_port);
    722     cli_out("src_ip          =   %d.%d.%d.%d\n",
    723             
    724             (report->sip >> 24) & 0xff,
    725             (report->sip >> 16) & 0xff,
    726             (report->sip >> 8) & 0xff,
    727             (report->sip >> 0) & 0xff);
    728     cli_out("dst_ip          =   %d.%d.%d.%d\n",
    729             (report->dip >> 24) & 0xff,
    730             (report->dip >> 16) & 0xff,
    731             (report->dip >> 8) & 0xff,
    732             (report->dip >> 0) & 0xff);
    733     cli_out("sip6            =   %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
    734             report->sip6[0], report->sip6[1], report->sip6[2], report->sip6[3],
    735             report->sip6[4], report->sip6[5], report->sip6[6], report->sip6[7],
    736             report->sip6[8], report->sip6[9], report->sip6[10], report->sip6[11],
    737             report->sip6[12], report->sip6[13], report->sip6[14], report->sip6[15]);
    738     cli_out("dip6            =   %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
    739             report->dip6[0], report->dip6[1], report->dip6[2], report->dip6[3],
    740             report->dip6[4], report->dip6[5], report->dip6[6], report->dip6[7],
    741             report->dip6[8], report->dip6[9], report->dip6[10], report->dip6[11],
    742             report->dip6[12], report->dip6[13], report->dip6[14], report->dip6[15]);
    743     cli_out("start_timestamp =   %d, x10 ms\n", report->start_timestamp);
    744     cli_out("last_timestamp  =   %d, x10 ms\n", report->last_timestamp);
    745     cli_out("refresh_timestamp = %d, x10 ms\n", report->last_timestamp);
    746     return;
    747 }
    748 
    749 static int remon_registered = 0;
    750 
    751 static cmd_result_t
    752 cmd_regex_monitor(int unit, int start)
    753 {
    754     int rv = 0;
    755 
    756     if (start) {
    757         if (!remon_registered) {
    758             rv = bcm_regex_report_register(unit,
    759                                    (BCM_REGEX_REPORT_NEW | \
    760                                     BCM_REGEX_REPORT_MATCHED | \
    761                                     BCM_REGEX_REPORT_END),
    762                                     bcm_regex_diag_report_cb, NULL);
    763             if (rv) {
    764                 cli_out("Error(%d) Starting ReMon\n", rv);
    765             } else {
    766                 remon_registered = 1;
    767             }
    768         }
    769     } else {
    770             rv = bcm_regex_report_unregister(unit,
    771                                    (BCM_REGEX_REPORT_NEW | \
    772                                     BCM_REGEX_REPORT_MATCHED | \
    773                                     BCM_REGEX_REPORT_END),
    774                                     bcm_regex_diag_report_cb, NULL);
    775             remon_registered = 0;
    776     }
    777     return CMD_OK;
    778 }
    779 
    780 extern void
    781 _bcm_regex_sw_engine_hwid(int unit, bcm_regex_engine_t engid,
    782                             int32 *enghwid);
    783 
    784 static int regex_cmd_engine_dump(int unit, 
    785                                  bcm_regex_engine_t engine, 
    786                                  bcm_regex_engine_config_t *config, 
    787                                  void *user_data)
    788 {
    789 #if defined(BCM_TRIUMPH3_SUPPORT)
    790     int enghwid;
    791 
    792     _bcm_regex_sw_engine_hwid(unit, engine, &enghwid);
    793 
    794     cli_out("------------------------------------------\n");
    795     cli_out("\tEngine-ID: 0x%x, HW index %d\n", engine, enghwid);
    796     if (config->flags & BCM_REGEX_ENGINE_CONFIG_MULTI_PACKET) {
    797         cli_out("\tMode : Multipacket");
    798     }
    799     cli_out("------------------------------------------\n");
    800 #endif
    801 
    802     return 0;
    803 }
    804 
    805 static cmd_result_t dump_regex(int unit)
    806 {
    807     bcm_regex_config_t recfg;
    808 
    809     if (bcm_regex_config_get(unit, &recfg)) {
    810         return CMD_FAIL;
    811     }
    812 
    813     /* display configuration */
    814     if (recfg.flags & BCM_REGEX_CONFIG_ENABLE) {
    815         cli_out("Regex : Enabled\n");
    816     } else {
    817         cli_out("Regex : Disabled\n");
    818         return CMD_OK;
    819     }
    820 
    821     cli_out("Max flow : %d\n", recfg.max_flows);
    822     cli_out("Max payload inspection size : %d\n", recfg.payload_depth);
    823     cli_out("Max packets to inspect: %d\n", recfg.inspect_num_pkt);
    824     cli_out("Report generation enabled for: ");
    825     if (recfg.report_flags & BCM_REGEX_REPORT_NEW) {
    826         cli_out("New Flow,");
    827     }
    828     if (recfg.report_flags & BCM_REGEX_REPORT_MATCHED) {
    829         cli_out("Flow match,");
    830     }
    831     if (recfg.report_flags & BCM_REGEX_REPORT_END) {
    832         cli_out("Flow terminated");
    833     }
    834     cli_out("%s\n", recfg.report_flags ? "" : "None");
    835 
    836     /* iterate over all the engines and display their configuration */
    837     bcm_regex_engine_traverse(unit, regex_cmd_engine_dump, NULL);
    838     return CMD_OK;
    839 }
    840 
    841 extern void 
    842 _bcm_regex_sw_dump_engine(int unit, bcm_regex_engine_t engid,
    843                             uint32 f);
    844 static int 
    845 _regex_dump_engine_cb(int unit, bcm_regex_engine_t engid,
    846                       bcm_regex_engine_config_t *config,
    847                       void *user_data)
    848 {
    849     bcm_regex_engine_t did = *((bcm_regex_engine_t*) user_data);
    850 
    851     if ((did == -1) || (did == engid)) {
    852 #if defined(BCM_TRIUMPH3_SUPPORT)
    853         _bcm_regex_sw_dump_engine(unit, engid, 0);
    854 #else
    855         return CMD_NOTIMPL;
    856 #endif
    857     }
    858     return CMD_OK;
    859 }
    860 
    861 extern void
    862 _bcm_regex_sw_load_engine(int unit, bcm_regex_engine_t engid,
    863                             uint32 f, int *eng_hwidx);
    864 static int
    865 _regex_load_engine_cb(int unit, bcm_regex_engine_t engid,
    866                       bcm_regex_engine_config_t *config,
    867                       void *user_data)
    868 {
    869 #if defined(BCM_TRIUMPH3_SUPPORT)
    870     int eng_hwidx = -1;
    871 
    872     _bcm_regex_sw_load_engine(unit, engid, 0, &eng_hwidx);
    873     if (eng_hwidx >= 0) {
    874         l_engine_count[unit]++;
    875         l_re_engines[unit][engid] = eng_hwidx;
    876         /*
    877         cli_out("Engine ID %d, hw index %d, engine count %d\n", engid, eng_hwidx, l_engine_count[unit]);
    878         */
    879     }
    880 #else
    881     return CMD_NOTIMPL;
    882 #endif
    883     return CMD_OK;
    884 }
    885 
    886 static int dump_regex_engine(int unit, int engidx)
    887 {
    888     bcm_regex_engine_t eng_id = -1;
    889 
    890     if (engidx >= 0) {
    891         if (engidx >= l_engine_count[unit]) {
    892             cli_out("Invalid engine index. Not found\n");
    893             return CMD_FAIL;
    894         }
    895         eng_id = l_re_engines[unit][engidx];
    896     }
    897     bcm_regex_engine_traverse(unit, _regex_dump_engine_cb, (void*) &eng_id);
    898     return CMD_OK;
    899 }
    900 
    901 static int dump_load_regex_engine(int unit)
    902 {
    903     int i;
    904     bcm_regex_engine_t eng_id = -1;
    905 
    906     for (i = 0; i < MAX_ENGINE_PER_UNIT; i++) {
    907         l_re_engines[unit][i] = -1;
    908     }
    909     l_engine_count[unit] = 0;
    910     bcm_regex_engine_traverse(unit, _regex_load_engine_cb, (void*) &eng_id);
    911 
    912     return CMD_OK;
    913 }
    914 
    915 static int dump_regex_engine_info(int unit, int engid)
    916 {
    917     bcm_regex_engine_info_t regex_engine_info;
    918     int rv;
    919 
    920     rv = bcm_regex_engine_info_get(unit, engid, &regex_engine_info);
    921 
    922     if (rv != 0) {
    923         cli_out("Invalid engine index. Not found\n");
    924         return CMD_FAIL;
    925     } else if (engid >= 0) {
    926         printf("Engine %d Size = 0x%x, %d\n", engid, regex_engine_info.size, regex_engine_info.size);
    927         printf("Engine %d Free Size = 0x%x, %d\n", engid, regex_engine_info.free_size, regex_engine_info.free_size);
    928     } else {
    929         cli_out("SME Size = 0x%x, %d\n", regex_engine_info.size, regex_engine_info.size);
    930         cli_out("SME Free Size = 0x%x, %d\n", regex_engine_info.free_size, regex_engine_info.free_size);
    931     }
    932 
    933     return CMD_OK;
    934 }
    935 
    936 static int dump_regex_session_info(int unit)
    937 {
    938     bcm_regex_info_t regex_info;
    939     int rv;
    940 
    941     rv = bcm_regex_info_get(unit, &regex_info);
    942 
    943     if (rv != 0) {
    944         cli_out("Session info not found\n");
    945     } else {
    946         cli_out("Session Table Size      = %d\n", regex_info.session_size);
    947         cli_out("Session Table IPv4 Free = %d\n", regex_info.session_free_size_ipv4);
    948         cli_out("Session Table IPv6 Free = %d\n", regex_info.session_free_size_ipv6);
    949         cli_out("Policy Table Size       = %d\n", regex_info.policy_size);
    950         cli_out("Policy Table Free Size  = %d\n", regex_info.policy_free_size);
    951     }
    952 
    953     return CMD_OK;
    954 }
    955 
    956 static int dump_regex_session_stats(int unit)
    957 {
    958     int rv, i;
    959     uint64 val[bcmStatRegexSessionLast+1];
    960 
    961     for (i = 0; i <= bcmStatRegexSessionLast; i++)
    962     {
    963         rv = bcm_regex_stat_get(unit, i, &val[i]);
    964         if (rv != 0) {
    965             cli_out("Stat value %d not found\n", i);
    966             return CMD_OK;
    967         }
    968     }
    969 
    970     cli_out("Session entries in use      = %08x:%08x\n", COMPILER_64_HI(val[0]), COMPILER_64_LO(val[0]));
    971     cli_out("Session flows created       = %08x:%08x\n", COMPILER_64_HI(val[1]), COMPILER_64_LO(val[1]));
    972     cli_out("Session max flows in use    = %08x:%08x\n", COMPILER_64_HI(val[2]), COMPILER_64_LO(val[2]));
    973     cli_out("Session flows missed TCP    = %08x:%08x\n", COMPILER_64_HI(val[3]), COMPILER_64_LO(val[3]));
    974     cli_out("Session flows missed UDP    = %08x:%08x\n", COMPILER_64_HI(val[4]), COMPILER_64_LO(val[4]));
    975     cli_out("Session cmdwait timeouts    = %08x:%08x\n", COMPILER_64_HI(val[5]), COMPILER_64_LO(val[5]));
    976     cli_out("Session unused results      = %08x:%08x\n", COMPILER_64_HI(val[6]), COMPILER_64_LO(val[6]));
    977     cli_out("Session suppressed actions  = %08x:%08x\n", COMPILER_64_HI(val[7]), COMPILER_64_LO(val[7]));
    978     cli_out("Session TCP SYN data        = %08x:%08x\n", COMPILER_64_HI(val[8]), COMPILER_64_LO(val[8]));
    979     cli_out("Session L4 invalid          = %08x:%08x\n", COMPILER_64_HI(val[9]), COMPILER_64_LO(val[9]));
    980     cli_out("Session L4 ports excluded   = %08x:%08x\n", COMPILER_64_HI(val[10]), COMPILER_64_LO(val[10]));
    981 
    982     return CMD_OK;
    983 }
    984 
    985 static int dump_regex_match_stats(int unit)
    986 {
    987     int rv, i;
    988     uint64 val[bcmStatRegexLast+1];
    989 
    990     for (i = bcmStatRegexSigMatchFirst; i <= bcmStatRegexSigMatchLast; i++)
    991     {
    992         rv = bcm_regex_stat_get(unit, i, &val[i]);
    993         if (rv != 0) {
    994             cli_out("Stat value %d not found\n", i);
    995             return CMD_OK;
    996         }
    997     }
    998 
    999     i = bcmStatRegexSigMatchFirst;
   1000 
   1001     cli_out("Sig match packets received      = %08x:%08x\n", COMPILER_64_HI(val[i]), COMPILER_64_LO(val[i])); i++;
   1002     cli_out("Sig match packets sent          = %08x:%08x\n", COMPILER_64_HI(val[i]), COMPILER_64_LO(val[i])); i++;
   1003     cli_out("Sig match packets dropped       = %08x:%08x\n", COMPILER_64_HI(val[i]), COMPILER_64_LO(val[i])); i++;
   1004     cli_out("Sig match bytes matched         = %08x:%08x\n", COMPILER_64_HI(val[i]), COMPILER_64_LO(val[i])); i++;
   1005     cli_out("Sig match matched flows         = %08x:%08x\n", COMPILER_64_HI(val[i]), COMPILER_64_LO(val[i])); i++;
   1006     cli_out("Sig match unmatched flows       = %08x:%08x\n", COMPILER_64_HI(val[i]), COMPILER_64_LO(val[i])); i++;
   1007     cli_out("Sig match total match           = %08x:%08x\n", COMPILER_64_HI(val[i]), COMPILER_64_LO(val[i])); i++;
   1008     cli_out("Sig match cross sig flags       = %08x:%08x\n", COMPILER_64_HI(val[i]), COMPILER_64_LO(val[i])); i++;
   1009     cli_out("Sig match fragments received    = %08x:%08x\n", COMPILER_64_HI(val[i]), COMPILER_64_LO(val[i])); i++;
   1010     cli_out("Sig match in packet error       = %08x:%08x\n", COMPILER_64_HI(val[i]), COMPILER_64_LO(val[i])); i++;
   1011     cli_out("Sig match flow tracker error    = %08x:%08x\n", COMPILER_64_HI(val[i]), COMPILER_64_LO(val[i])); i++;
   1012     cli_out("Sig match packet length error   = %08x:%08x\n", COMPILER_64_HI(val[i]), COMPILER_64_LO(val[i])); i++;
   1013     cli_out("Sig match L4 checksum error     = %08x:%08x\n", COMPILER_64_HI(val[i]), COMPILER_64_LO(val[i])); i++;
   1014     cli_out("Sig match flow done packet drop = %08x:%08x\n", COMPILER_64_HI(val[i]), COMPILER_64_LO(val[i])); i++;
   1015     cli_out("Sig match flow timestamp error  = %08x:%08x\n", COMPILER_64_HI(val[i]), COMPILER_64_LO(val[i])); i++;
   1016     cli_out("Sig match flow packet num error = %08x:%08x\n", COMPILER_64_HI(val[i]), COMPILER_64_LO(val[i])); i++;
   1017     cli_out("Sig match ECC error             = %08x:%08x\n", COMPILER_64_HI(val[i]), COMPILER_64_LO(val[i])); i++;
   1018 
   1019     return CMD_OK;
   1020 }
   1021 
   1022 extern int _bcm_tr3_regex_dump_axp(int unit);
   1023 
   1024 static int
   1025 _regex_dump_axp(int unit)
   1026 {
   1027 #if defined(BCM_TRIUMPH3_SUPPORT)
   1028     int rv;
   1029 
   1030     rv = _bcm_tr3_regex_dump_axp(unit);
   1031     if (rv != 0) {
   1032         rv = CMD_FAIL;
   1033     }
   1034 #else
   1035     return CMD_NOTIMPL;
   1036 #endif
   1037     return CMD_OK;
   1038 }
   1039 
   1040 static int 
   1041 _regex_dump_engine_dfa_cb(int unit, bcm_regex_engine_t engid,
   1042                               bcm_regex_engine_config_t *config,
   1043                               void *user_data)
   1044 {
   1045     bcm_regex_engine_t did = *((bcm_regex_engine_t*) user_data);
   1046 
   1047     if ((did == -1) || (did == engid)) {
   1048 #if defined(BCM_TRIUMPH3_SUPPORT)
   1049         _bcm_regex_sw_dump_engine(unit, engid,1);
   1050 #else
   1051         return CMD_NOTIMPL;
   1052 #endif
   1053     }
   1054     return CMD_OK;
   1055 }
   1056 
   1057 static int dump_regex_engine_dfa(int unit, int engidx)
   1058 {
   1059     bcm_regex_engine_t eng_id = -1;
   1060 
   1061     if (engidx >= 0) {
   1062         if (engidx >= l_engine_count[unit]) {
   1063             cli_out("Invalid engine index. Not found\n");
   1064             return CMD_FAIL;
   1065         }
   1066         eng_id = l_re_engines[unit][engidx];
   1067     }
   1068     bcm_regex_engine_traverse(unit, _regex_dump_engine_dfa_cb, (void*) &eng_id);
   1069     return CMD_OK;
   1070 }
   1071 
   1072 typedef struct re_diag_ud_s {
   1073     bcm_regex_engine_t engid;
   1074     int found;
   1075 } re_diag_ud_t;
   1076 
   1077 #if 0
   1078 static int
   1079 _regex_engine_present_in_hw(int unit, bcm_regex_engine_t engid,
   1080                               bcm_regex_engine_config_t *config,
   1081                               void *user_data)
   1082 {
   1083     re_diag_ud_t *ud = (re_diag_ud_t*) user_data;
   1084 
   1085     if (ud->engid == engid) {
   1086         ud->found = 1;
   1087     }
   1088 
   1089     return CMD_OK;
   1090 }
   1091 
   1092 static int _regex_engine_sync(int unit, bcm_regex_engine_t engid)
   1093 {
   1094     re_diag_ud_t ud;
   1095 
   1096     ud.engid = engid;
   1097     ud.found = 0;
   1098     bcm_regex_engine_traverse(unit, _regex_engine_present_in_hw, (void*)&ud);
   1099     if (ud.found == 0) {
   1100         _regex_diag_remove_engine_from_db(unit, engid);
   1101     }
   1102     return 0;
   1103 }
   1104 #endif /* 0 */
   1105 
   1106 static int _regex_dump_app_info(int unit, bcm_regex_engine_t engid)
   1107 {
   1108     diag_regex_engine_info_t *papp;
   1109     int i;
   1110 
   1111     /* remove from applist */
   1112     papp = engine_info_list[unit];
   1113     while(papp) {
   1114         if (papp->engid == engid) {
   1115             cli_out("\t File: %s\n", papp->filename);
   1116             cli_out("\t Number of patterns : %d\n", papp->num_match);
   1117             for (i = 0; i < papp->num_match; i++) {
   1118                 cli_out("\t Pattern %d : %s\n", i, papp->match[i].pattern);
   1119             }
   1120             return 0;
   1121         }
   1122         papp = papp->next;
   1123     }
   1124     return -1;
   1125 }
   1126 
   1127 extern void _bcm_esw_policer_dump(int unit, bcm_policer_t policer_id);
   1128 extern void _bcm_esw_policy_dump(int unit, bcm_regex_policy_t policy);
   1129 
   1130 cmd_result_t cmd_regex(int unit, args_t *a)
   1131 {
   1132     char		*subcmd, *param;
   1133     int                 mon_start = 0, eindex, i;
   1134     bcm_regex_policy_t  policy;
   1135     bcm_policer_t       policer_id;
   1136 
   1137     if (!soc_feature(unit, soc_feature_regex)) {
   1138         return CMD_NOTIMPL;
   1139     }
   1140 
   1141     if (re_inited == 0) {
   1142         regex_cmd_init();
   1143     }
   1144 
   1145     if ((subcmd = ARG_GET(a)) == NULL) {
   1146         return dump_regex(unit);
   1147     }
   1148 
   1149     if (sal_strcasecmp(subcmd, "create") == 0) {
   1150         return cmd_create_regex_engine(unit, a);
   1151     } else if (sal_strcasecmp(subcmd, "destroy") == 0) {
   1152         eindex = -1;
   1153         if ((subcmd = ARG_GET(a))) {
   1154             eindex = atoi(subcmd);
   1155         } else {
   1156             eindex = -1;
   1157         }
   1158         return cmd_destroy_regex_engine(unit, eindex);
   1159     } else if (sal_strcasecmp(subcmd, "monitor") == 0) {
   1160         if ((subcmd = ARG_GET(a)) == NULL) {
   1161 	    mon_start = 1;
   1162         } else {
   1163             if (sal_strcasecmp(subcmd, "start") == 0) {
   1164                 mon_start = 1;
   1165             } else if (sal_strcasecmp(subcmd, "stop") == 0) {
   1166                 mon_start = 0;
   1167             } else if (sal_strcasecmp(subcmd, "verbose") == 0) {
   1168                 verbose = 1;
   1169                 return 0;
   1170             } else if (sal_strcasecmp(subcmd, "silent") == 0) {
   1171                 verbose = 0;
   1172                 return 0;
   1173             } else {
   1174                 mon_start = 0;
   1175             }
   1176         }
   1177         return cmd_regex_monitor(unit, mon_start);
   1178     } else if (sal_strcasecmp(subcmd, "list") == 0) {
   1179         dump_load_regex_engine(unit);
   1180         /* list all the engines on this unit */
   1181         cli_out("Total %d engines installed.\n", l_engine_count[unit]);
   1182         for (i = 0; i < l_engine_count[unit]; i++) {
   1183             cli_out("----- engine %d hw idx %d --------\n", i, l_re_engines[unit][i]);
   1184             _regex_dump_app_info(unit, l_re_engines[unit][i]);
   1185         }
   1186         return CMD_OK;
   1187     } else if (sal_strcasecmp(subcmd, "show") == 0) {
   1188         dump_load_regex_engine(unit);
   1189         subcmd = ARG_GET(a);
   1190         if (!subcmd) {
   1191             return dump_regex(unit);
   1192         }
   1193 
   1194         param = ARG_GET(a);
   1195         if (sal_strcasecmp(subcmd, "engine") == 0) {
   1196             eindex = -1;
   1197             if (param) {
   1198                 eindex = atoi(param);
   1199             }
   1200             return dump_regex_engine(unit, eindex);
   1201         } else if (sal_strcasecmp(subcmd, "dfa") == 0) {
   1202             eindex = -1;
   1203             if (param) {
   1204                 eindex = atoi(param);
   1205             }
   1206             return dump_regex_engine_dfa(unit, eindex);
   1207         } else if (sal_strcasecmp(subcmd, "policer") == 0) {
   1208             policer_id = -1;
   1209             if (param) {
   1210                 policer_id = atoi(param);
   1211             }
   1212             _bcm_esw_policer_dump(unit, policer_id);
   1213         } else if (sal_strcasecmp(subcmd, "policy") == 0) {
   1214             policy = -1;
   1215             if (param) {
   1216                 policy = atoi(param);
   1217             }
   1218             _bcm_esw_policy_dump(unit, policy);
   1219         } else if (sal_strcasecmp(subcmd, "info") == 0) {
   1220             eindex = -1;
   1221             if (param) {
   1222                 eindex = atoi(param);
   1223             }
   1224             return dump_regex_engine_info(unit, eindex);
   1225         } else if (sal_strcasecmp(subcmd, "session") == 0) {
   1226             if (!param) {
   1227                 return dump_regex_session_info(unit);
   1228             }
   1229             if (sal_strcasecmp(param, "stats") == 0) {
   1230                 return dump_regex_session_stats(unit);
   1231             }
   1232         } else if (sal_strcasecmp(subcmd, "match") == 0) {
   1233             if (!param) {
   1234                 return CMD_OK;
   1235             }
   1236             if (sal_strcasecmp(param, "stats") == 0) {
   1237                 return dump_regex_match_stats(unit);
   1238             }
   1239         } else if (sal_strcasecmp(subcmd, "axp") == 0) {
   1240             return _regex_dump_axp(unit);
   1241         }
   1242         return CMD_OK;
   1243     }
   1244     return CMD_USAGE;
   1245 }
   1246 #endif 
   1247 
   1248 #else
   1249 int _diag_esw_regex_not_empty;
   1250 #endif