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, ®ex_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, ®ex_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