1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2010-2018 Intel Corporation 3 */ 4 5 #include <stdio.h> 6 #include <stdint.h> 7 #include <stdlib.h> 8 #include <string.h> 9 #include <unistd.h> 10 11 #include <rte_common.h> 12 #include <rte_cycles.h> 13 #include <rte_string_fns.h> 14 15 #include "rte_eth_softnic_internals.h" 16 17 #ifndef CMD_MAX_TOKENS 18 #define CMD_MAX_TOKENS 256 19 #endif 20 21 #ifndef MAX_LINE_SIZE 22 #define MAX_LINE_SIZE 2048 23 #endif 24 25 #define MSG_OUT_OF_MEMORY "Not enough memory.\n" 26 #define MSG_CMD_UNKNOWN "Unknown command \"%s\".\n" 27 #define MSG_CMD_UNIMPLEM "Command \"%s\" not implemented.\n" 28 #define MSG_ARG_NOT_ENOUGH "Not enough arguments for command \"%s\".\n" 29 #define MSG_ARG_TOO_MANY "Too many arguments for command \"%s\".\n" 30 #define MSG_ARG_MISMATCH "Wrong number of arguments for command \"%s\".\n" 31 #define MSG_ARG_NOT_FOUND "Argument \"%s\" not found.\n" 32 #define MSG_ARG_INVALID "Invalid value for argument \"%s\".\n" 33 #define MSG_FILE_ERR "Error in file \"%s\" at line %u.\n" 34 #define MSG_FILE_NOT_ENOUGH "Not enough rules in file \"%s\".\n" 35 #define MSG_CMD_FAIL "Command \"%s\" failed.\n" 36 37 static int 38 parser_read_uint64(uint64_t *value, char *p) 39 { 40 uint64_t val = 0; 41 42 if (!value || !p || !p[0]) 43 return -EINVAL; 44 45 val = strtoull(p, &p, 0); 46 if (p[0]) 47 return -EINVAL; 48 49 *value = val; 50 return 0; 51 } 52 53 static int 54 parser_read_uint32(uint32_t *value, char *p) 55 { 56 uint32_t val = 0; 57 58 if (!value || !p || !p[0]) 59 return -EINVAL; 60 61 val = strtoul(p, &p, 0); 62 if (p[0]) 63 return -EINVAL; 64 65 *value = val; 66 return 0; 67 } 68 69 #define PARSE_DELIMITER " \f\n\r\t\v" 70 71 static int 72 parse_tokenize_string(char *string, char *tokens[], uint32_t *n_tokens) 73 { 74 uint32_t i; 75 76 if (!string || !tokens || !n_tokens || !*n_tokens) 77 return -EINVAL; 78 79 for (i = 0; i < *n_tokens; i++) { 80 tokens[i] = strtok_r(string, PARSE_DELIMITER, &string); 81 if (!tokens[i]) 82 break; 83 } 84 85 if (i == *n_tokens && strtok_r(string, PARSE_DELIMITER, &string)) 86 return -E2BIG; 87 88 *n_tokens = i; 89 return 0; 90 } 91 92 static int 93 is_comment(char *in) 94 { 95 if ((strlen(in) && index("!#%;", in[0])) || 96 (strncmp(in, "//", 2) == 0) || 97 (strncmp(in, "--", 2) == 0)) 98 return 1; 99 100 return 0; 101 } 102 103 /** 104 * mempool <mempool_name> 105 * buffer <buffer_size> 106 * pool <pool_size> 107 * cache <cache_size> 108 */ 109 static void 110 cmd_mempool(struct pmd_internals *softnic, 111 char **tokens, 112 uint32_t n_tokens, 113 char *out, 114 size_t out_size) 115 { 116 struct softnic_mempool_params p; 117 char *name; 118 struct softnic_mempool *mempool; 119 120 if (n_tokens != 8) { 121 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 122 return; 123 } 124 125 name = tokens[1]; 126 127 if (strcmp(tokens[2], "buffer") != 0) { 128 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "buffer"); 129 return; 130 } 131 132 if (parser_read_uint32(&p.buffer_size, tokens[3]) != 0) { 133 snprintf(out, out_size, MSG_ARG_INVALID, "buffer_size"); 134 return; 135 } 136 137 if (strcmp(tokens[4], "pool") != 0) { 138 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pool"); 139 return; 140 } 141 142 if (parser_read_uint32(&p.pool_size, tokens[5]) != 0) { 143 snprintf(out, out_size, MSG_ARG_INVALID, "pool_size"); 144 return; 145 } 146 147 if (strcmp(tokens[6], "cache") != 0) { 148 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "cache"); 149 return; 150 } 151 152 if (parser_read_uint32(&p.cache_size, tokens[7]) != 0) { 153 snprintf(out, out_size, MSG_ARG_INVALID, "cache_size"); 154 return; 155 } 156 157 mempool = softnic_mempool_create(softnic, name, &p); 158 if (mempool == NULL) { 159 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 160 return; 161 } 162 } 163 164 /** 165 * swq <swq_name> 166 * size <size> 167 */ 168 static void 169 cmd_swq(struct pmd_internals *softnic, 170 char **tokens, 171 uint32_t n_tokens, 172 char *out, 173 size_t out_size) 174 { 175 struct softnic_swq_params p; 176 char *name; 177 struct softnic_swq *swq; 178 179 if (n_tokens != 4) { 180 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 181 return; 182 } 183 184 name = tokens[1]; 185 186 if (strcmp(tokens[2], "size") != 0) { 187 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "size"); 188 return; 189 } 190 191 if (parser_read_uint32(&p.size, tokens[3]) != 0) { 192 snprintf(out, out_size, MSG_ARG_INVALID, "size"); 193 return; 194 } 195 196 swq = softnic_swq_create(softnic, name, &p); 197 if (swq == NULL) { 198 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 199 return; 200 } 201 } 202 203 /** 204 * pipeline codegen <spec_file> <code_file> 205 */ 206 static void 207 cmd_softnic_pipeline_codegen(struct pmd_internals *softnic __rte_unused, 208 char **tokens, 209 uint32_t n_tokens, 210 char *out, 211 size_t out_size) 212 { 213 FILE *spec_file = NULL; 214 FILE *code_file = NULL; 215 uint32_t err_line; 216 const char *err_msg; 217 int status; 218 219 if (n_tokens != 4) { 220 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 221 return; 222 } 223 224 spec_file = fopen(tokens[2], "r"); 225 if (!spec_file) { 226 snprintf(out, out_size, "Cannot open file %s.\n", tokens[2]); 227 return; 228 } 229 230 code_file = fopen(tokens[3], "w"); 231 if (!code_file) { 232 snprintf(out, out_size, "Cannot open file %s.\n", tokens[3]); 233 fclose(spec_file); 234 return; 235 } 236 237 status = rte_swx_pipeline_codegen(spec_file, 238 code_file, 239 &err_line, 240 &err_msg); 241 242 fclose(spec_file); 243 fclose(code_file); 244 245 if (status) { 246 snprintf(out, out_size, "Error %d at line %u: %s\n.", 247 status, err_line, err_msg); 248 return; 249 } 250 } 251 252 /** 253 * pipeline libbuild <code_file> <lib_file> 254 */ 255 static void 256 cmd_softnic_pipeline_libbuild(struct pmd_internals *softnic __rte_unused, 257 char **tokens, 258 uint32_t n_tokens, 259 char *out, 260 size_t out_size) 261 { 262 char *code_file, *lib_file, *obj_file = NULL, *log_file = NULL; 263 char *install_dir, *cwd = NULL, *buffer = NULL; 264 size_t length; 265 int status = 0; 266 267 if (n_tokens != 4) { 268 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 269 goto free; 270 } 271 272 install_dir = getenv("RTE_INSTALL_DIR"); 273 if (!install_dir) { 274 cwd = malloc(MAX_LINE_SIZE); 275 if (!cwd) { 276 snprintf(out, out_size, MSG_OUT_OF_MEMORY); 277 goto free; 278 } 279 280 install_dir = getcwd(cwd, MAX_LINE_SIZE); 281 if (!install_dir) { 282 snprintf(out, out_size, "Error: Path too long.\n"); 283 goto free; 284 } 285 } 286 287 snprintf(out, out_size, "Using DPDK source code from \"%s\".\n", install_dir); 288 out_size -= strlen(out); 289 out += strlen(out); 290 291 code_file = tokens[2]; 292 length = strnlen(code_file, MAX_LINE_SIZE); 293 if (length < 3 || 294 code_file[length - 2] != '.' || 295 code_file[length - 1] != 'c') { 296 snprintf(out, out_size, MSG_ARG_INVALID, "code_file"); 297 goto free; 298 } 299 300 lib_file = tokens[3]; 301 length = strnlen(lib_file, MAX_LINE_SIZE); 302 if (length < 4 || 303 lib_file[length - 3] != '.' || 304 lib_file[length - 2] != 's' || 305 lib_file[length - 1] != 'o') { 306 snprintf(out, out_size, MSG_ARG_INVALID, "lib_file"); 307 goto free; 308 } 309 310 obj_file = malloc(length); 311 log_file = malloc(length + 2); 312 if (!obj_file || !log_file) { 313 snprintf(out, out_size, MSG_OUT_OF_MEMORY); 314 goto free; 315 } 316 317 memcpy(obj_file, lib_file, length - 2); 318 obj_file[length - 2] = 'o'; 319 obj_file[length - 1] = 0; 320 321 memcpy(log_file, lib_file, length - 2); 322 log_file[length - 2] = 'l'; 323 log_file[length - 1] = 'o'; 324 log_file[length] = 'g'; 325 log_file[length + 1] = 0; 326 327 buffer = malloc(MAX_LINE_SIZE); 328 if (!buffer) { 329 snprintf(out, out_size, MSG_OUT_OF_MEMORY); 330 goto free; 331 } 332 333 snprintf(buffer, 334 MAX_LINE_SIZE, 335 "gcc -c -O3 -fpic -Wno-deprecated-declarations -o %s %s " 336 "-I %s/lib/pipeline " 337 "-I %s/lib/eal/include " 338 "-I %s/lib/eal/x86/include " 339 "-I %s/lib/eal/include/generic " 340 "-I %s/lib/log " 341 "-I %s/lib/meter " 342 "-I %s/lib/port " 343 "-I %s/lib/table " 344 "-I %s/lib/pipeline " 345 "-I %s/config " 346 "-I %s/build " 347 "-I %s/lib/eal/linux/include " 348 ">%s 2>&1 " 349 "&& " 350 "gcc -shared %s -o %s " 351 ">>%s 2>&1", 352 obj_file, 353 code_file, 354 install_dir, 355 install_dir, 356 install_dir, 357 install_dir, 358 install_dir, 359 install_dir, 360 install_dir, 361 install_dir, 362 install_dir, 363 install_dir, 364 install_dir, 365 install_dir, 366 log_file, 367 obj_file, 368 lib_file, 369 log_file); 370 371 status = system(buffer); 372 if (status) { 373 snprintf(out, 374 out_size, 375 "Library build failed, see file \"%s\" for details.\n", 376 log_file); 377 goto free; 378 } 379 380 free: 381 free(cwd); 382 free(obj_file); 383 free(log_file); 384 free(buffer); 385 } 386 387 /** 388 * pipeline <pipeline_name> build lib <lib_file> io <iospec_file> numa <numa_node> 389 */ 390 static void 391 cmd_softnic_pipeline_build(struct pmd_internals *softnic, 392 char **tokens, 393 uint32_t n_tokens, 394 char *out, 395 size_t out_size) 396 { 397 struct pipeline *p = NULL; 398 char *pipeline_name, *lib_file_name, *iospec_file_name; 399 uint32_t numa_node = 0; 400 401 /* Parsing. */ 402 if (n_tokens != 9) { 403 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 404 return; 405 } 406 407 pipeline_name = tokens[1]; 408 409 if (strcmp(tokens[2], "build")) { 410 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "build"); 411 return; 412 } 413 414 if (strcmp(tokens[3], "lib")) { 415 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "lib"); 416 return; 417 } 418 419 lib_file_name = tokens[4]; 420 421 if (strcmp(tokens[5], "io")) { 422 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "io"); 423 return; 424 } 425 426 iospec_file_name = tokens[6]; 427 428 if (strcmp(tokens[7], "numa")) { 429 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "numa"); 430 return; 431 } 432 433 if (parser_read_uint32(&numa_node, tokens[8])) { 434 snprintf(out, out_size, MSG_ARG_INVALID, "numa_node"); 435 return; 436 } 437 438 /* Pipeline create. */ 439 p = softnic_pipeline_create(softnic, 440 pipeline_name, 441 lib_file_name, 442 iospec_file_name, 443 (int)numa_node); 444 if (!p) 445 snprintf(out, out_size, "Pipeline creation failed.\n"); 446 } 447 448 static void 449 table_entry_free(struct rte_swx_table_entry *entry) 450 { 451 if (!entry) 452 return; 453 454 free(entry->key); 455 free(entry->key_mask); 456 free(entry->action_data); 457 free(entry); 458 } 459 460 static int 461 pipeline_table_entries_add(struct rte_swx_ctl_pipeline *p, 462 const char *table_name, 463 FILE *file, 464 uint32_t *file_line_number) 465 { 466 char *line = NULL; 467 uint32_t line_id = 0; 468 int status = 0; 469 470 /* Buffer allocation. */ 471 line = malloc(MAX_LINE_SIZE); 472 if (!line) 473 return -ENOMEM; 474 475 /* File read. */ 476 for (line_id = 1; ; line_id++) { 477 struct rte_swx_table_entry *entry; 478 int is_blank_or_comment; 479 480 if (fgets(line, MAX_LINE_SIZE, file) == NULL) 481 break; 482 483 entry = rte_swx_ctl_pipeline_table_entry_read(p, 484 table_name, 485 line, 486 &is_blank_or_comment); 487 if (!entry) { 488 if (is_blank_or_comment) 489 continue; 490 491 status = -EINVAL; 492 goto error; 493 } 494 495 status = rte_swx_ctl_pipeline_table_entry_add(p, 496 table_name, 497 entry); 498 table_entry_free(entry); 499 if (status) 500 goto error; 501 } 502 503 error: 504 free(line); 505 *file_line_number = line_id; 506 return status; 507 } 508 509 /** 510 * pipeline <pipeline_name> table <table_name> add <file_name> 511 */ 512 static void 513 cmd_softnic_pipeline_table_add(struct pmd_internals *softnic, 514 char **tokens, 515 uint32_t n_tokens, 516 char *out, 517 size_t out_size) 518 { 519 struct pipeline *p; 520 char *pipeline_name, *table_name, *file_name; 521 FILE *file = NULL; 522 uint32_t file_line_number = 0; 523 int status; 524 525 if (n_tokens != 6) { 526 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 527 return; 528 } 529 530 pipeline_name = tokens[1]; 531 p = softnic_pipeline_find(softnic, pipeline_name); 532 if (!p) { 533 snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name"); 534 return; 535 } 536 537 table_name = tokens[3]; 538 539 file_name = tokens[5]; 540 file = fopen(file_name, "r"); 541 if (!file) { 542 snprintf(out, out_size, "Cannot open file %s.\n", file_name); 543 return; 544 } 545 546 status = pipeline_table_entries_add(p->ctl, 547 table_name, 548 file, 549 &file_line_number); 550 if (status) 551 snprintf(out, out_size, "Invalid entry in file %s at line %u\n", 552 file_name, 553 file_line_number); 554 555 fclose(file); 556 } 557 558 static int 559 pipeline_table_entries_delete(struct rte_swx_ctl_pipeline *p, 560 const char *table_name, 561 FILE *file, 562 uint32_t *file_line_number) 563 { 564 char *line = NULL; 565 uint32_t line_id = 0; 566 int status = 0; 567 568 /* Buffer allocation. */ 569 line = malloc(MAX_LINE_SIZE); 570 if (!line) 571 return -ENOMEM; 572 573 /* File read. */ 574 for (line_id = 1; ; line_id++) { 575 struct rte_swx_table_entry *entry; 576 int is_blank_or_comment; 577 578 if (fgets(line, MAX_LINE_SIZE, file) == NULL) 579 break; 580 581 entry = rte_swx_ctl_pipeline_table_entry_read(p, 582 table_name, 583 line, 584 &is_blank_or_comment); 585 if (!entry) { 586 if (is_blank_or_comment) 587 continue; 588 589 status = -EINVAL; 590 goto error; 591 } 592 593 status = rte_swx_ctl_pipeline_table_entry_delete(p, 594 table_name, 595 entry); 596 table_entry_free(entry); 597 if (status) 598 goto error; 599 } 600 601 error: 602 *file_line_number = line_id; 603 free(line); 604 return status; 605 } 606 607 /** 608 * pipeline <pipeline_name> table <table_name> delete <file_name> 609 */ 610 static void 611 cmd_softnic_pipeline_table_delete(struct pmd_internals *softnic, 612 char **tokens, 613 uint32_t n_tokens, 614 char *out, 615 size_t out_size) 616 { 617 struct pipeline *p; 618 char *pipeline_name, *table_name, *file_name; 619 FILE *file = NULL; 620 uint32_t file_line_number = 0; 621 int status; 622 623 if (n_tokens != 6) { 624 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 625 return; 626 } 627 628 pipeline_name = tokens[1]; 629 p = softnic_pipeline_find(softnic, pipeline_name); 630 if (!p) { 631 snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name"); 632 return; 633 } 634 635 table_name = tokens[3]; 636 637 file_name = tokens[5]; 638 file = fopen(file_name, "r"); 639 if (!file) { 640 snprintf(out, out_size, "Cannot open file %s.\n", file_name); 641 return; 642 } 643 644 status = pipeline_table_entries_delete(p->ctl, 645 table_name, 646 file, 647 &file_line_number); 648 if (status) 649 snprintf(out, out_size, "Invalid entry in file %s at line %u\n", 650 file_name, 651 file_line_number); 652 653 fclose(file); 654 } 655 656 static int 657 pipeline_table_default_entry_add(struct rte_swx_ctl_pipeline *p, 658 const char *table_name, 659 FILE *file, 660 uint32_t *file_line_number) 661 { 662 char *line = NULL; 663 uint32_t line_id = 0; 664 int status = 0; 665 666 /* Buffer allocation. */ 667 line = malloc(MAX_LINE_SIZE); 668 if (!line) 669 return -ENOMEM; 670 671 /* File read. */ 672 for (line_id = 1; ; line_id++) { 673 struct rte_swx_table_entry *entry; 674 int is_blank_or_comment; 675 676 if (fgets(line, MAX_LINE_SIZE, file) == NULL) 677 break; 678 679 entry = rte_swx_ctl_pipeline_table_entry_read(p, 680 table_name, 681 line, 682 &is_blank_or_comment); 683 if (!entry) { 684 if (is_blank_or_comment) 685 continue; 686 687 status = -EINVAL; 688 goto error; 689 } 690 691 status = rte_swx_ctl_pipeline_table_default_entry_add(p, 692 table_name, 693 entry); 694 table_entry_free(entry); 695 if (status) 696 goto error; 697 } 698 699 error: 700 *file_line_number = line_id; 701 free(line); 702 return status; 703 } 704 705 /** 706 * pipeline <pipeline_name> table <table_name> default <file_name> 707 */ 708 static void 709 cmd_softnic_pipeline_table_default(struct pmd_internals *softnic, 710 char **tokens, 711 uint32_t n_tokens, 712 char *out, 713 size_t out_size) 714 { 715 struct pipeline *p; 716 char *pipeline_name, *table_name, *file_name; 717 FILE *file = NULL; 718 uint32_t file_line_number = 0; 719 int status; 720 721 if (n_tokens != 6) { 722 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 723 return; 724 } 725 726 pipeline_name = tokens[1]; 727 p = softnic_pipeline_find(softnic, pipeline_name); 728 if (!p) { 729 snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name"); 730 return; 731 } 732 733 table_name = tokens[3]; 734 735 file_name = tokens[5]; 736 file = fopen(file_name, "r"); 737 if (!file) { 738 snprintf(out, out_size, "Cannot open file %s.\n", file_name); 739 return; 740 } 741 742 status = pipeline_table_default_entry_add(p->ctl, 743 table_name, 744 file, 745 &file_line_number); 746 if (status) 747 snprintf(out, out_size, "Invalid entry in file %s at line %u\n", 748 file_name, 749 file_line_number); 750 751 fclose(file); 752 } 753 754 /** 755 * pipeline <pipeline_name> table <table_name> show [filename] 756 */ 757 static void 758 cmd_softnic_pipeline_table_show(struct pmd_internals *softnic __rte_unused, 759 char **tokens, 760 uint32_t n_tokens, 761 char *out, 762 size_t out_size) 763 { 764 struct pipeline *p; 765 char *pipeline_name, *table_name; 766 FILE *file = NULL; 767 int status; 768 769 if (n_tokens != 5 && n_tokens != 6) { 770 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 771 return; 772 } 773 774 pipeline_name = tokens[1]; 775 p = softnic_pipeline_find(softnic, pipeline_name); 776 if (!p) { 777 snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name"); 778 return; 779 } 780 781 table_name = tokens[3]; 782 file = (n_tokens == 6) ? fopen(tokens[5], "w") : stdout; 783 if (!file) { 784 snprintf(out, out_size, "Cannot open file %s.\n", tokens[5]); 785 return; 786 } 787 788 status = rte_swx_ctl_pipeline_table_fprintf(file, p->ctl, table_name); 789 if (status) 790 snprintf(out, out_size, MSG_ARG_INVALID, "table_name"); 791 792 if (file) 793 fclose(file); 794 } 795 796 /** 797 * pipeline <pipeline_name> selector <selector_name> group add 798 */ 799 static void 800 cmd_softnic_pipeline_selector_group_add(struct pmd_internals *softnic, 801 char **tokens, 802 uint32_t n_tokens, 803 char *out, 804 size_t out_size) 805 { 806 struct pipeline *p; 807 char *pipeline_name, *selector_name; 808 uint32_t group_id; 809 int status; 810 811 if (n_tokens != 6) { 812 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 813 return; 814 } 815 816 pipeline_name = tokens[1]; 817 p = softnic_pipeline_find(softnic, pipeline_name); 818 if (!p) { 819 snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name"); 820 return; 821 } 822 823 if (strcmp(tokens[2], "selector") != 0) { 824 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "selector"); 825 return; 826 } 827 828 selector_name = tokens[3]; 829 830 if (strcmp(tokens[4], "group") || 831 strcmp(tokens[5], "add")) { 832 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "group add"); 833 return; 834 } 835 836 status = rte_swx_ctl_pipeline_selector_group_add(p->ctl, 837 selector_name, 838 &group_id); 839 if (status) 840 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 841 else 842 snprintf(out, out_size, "Group ID: %u\n", group_id); 843 } 844 845 /** 846 * pipeline <pipeline_name> selector <selector_name> group delete <group_id> 847 */ 848 static void 849 cmd_softnic_pipeline_selector_group_delete(struct pmd_internals *softnic, 850 char **tokens, 851 uint32_t n_tokens, 852 char *out, 853 size_t out_size) 854 { 855 struct pipeline *p; 856 char *pipeline_name, *selector_name; 857 uint32_t group_id; 858 int status; 859 860 if (n_tokens != 7) { 861 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 862 return; 863 } 864 865 pipeline_name = tokens[1]; 866 p = softnic_pipeline_find(softnic, pipeline_name); 867 if (!p) { 868 snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name"); 869 return; 870 } 871 872 if (strcmp(tokens[2], "selector") != 0) { 873 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "selector"); 874 return; 875 } 876 877 selector_name = tokens[3]; 878 879 if (strcmp(tokens[4], "group") || 880 strcmp(tokens[5], "delete")) { 881 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "group delete"); 882 return; 883 } 884 885 if (parser_read_uint32(&group_id, tokens[6]) != 0) { 886 snprintf(out, out_size, MSG_ARG_INVALID, "group_id"); 887 return; 888 } 889 890 status = rte_swx_ctl_pipeline_selector_group_delete(p->ctl, 891 selector_name, 892 group_id); 893 if (status) 894 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 895 } 896 897 #define GROUP_MEMBER_INFO_TOKENS_MAX 6 898 899 static int 900 token_is_comment(const char *token) 901 { 902 if ((token[0] == '#') || 903 (token[0] == ';') || 904 ((token[0] == '/') && (token[1] == '/'))) 905 return 1; /* TRUE. */ 906 907 return 0; /* FALSE. */ 908 } 909 910 static int 911 pipeline_selector_group_member_read(const char *string, 912 uint32_t *group_id, 913 uint32_t *member_id, 914 uint32_t *weight, 915 int *is_blank_or_comment) 916 { 917 char *token_array[GROUP_MEMBER_INFO_TOKENS_MAX], **tokens; 918 char *s0 = NULL, *s; 919 uint32_t n_tokens = 0, group_id_val = 0, member_id_val = 0, weight_val = 0; 920 int blank_or_comment = 0; 921 922 /* Check input arguments. */ 923 if (!string || !string[0]) 924 goto error; 925 926 /* Memory allocation. */ 927 s0 = strdup(string); 928 if (!s0) 929 goto error; 930 931 /* Parse the string into tokens. */ 932 for (s = s0; ; ) { 933 char *token; 934 935 token = strtok_r(s, " \f\n\r\t\v", &s); 936 if (!token || token_is_comment(token)) 937 break; 938 939 if (n_tokens >= GROUP_MEMBER_INFO_TOKENS_MAX) 940 goto error; 941 942 token_array[n_tokens] = token; 943 n_tokens++; 944 } 945 946 if (!n_tokens) { 947 blank_or_comment = 1; 948 goto error; 949 } 950 951 tokens = token_array; 952 953 if (n_tokens < 4 || 954 strcmp(tokens[0], "group") || 955 strcmp(tokens[2], "member")) 956 goto error; 957 958 /* 959 * Group ID. 960 */ 961 if (parser_read_uint32(&group_id_val, tokens[1]) != 0) 962 goto error; 963 *group_id = group_id_val; 964 965 /* 966 * Member ID. 967 */ 968 if (parser_read_uint32(&member_id_val, tokens[3]) != 0) 969 goto error; 970 *member_id = member_id_val; 971 972 tokens += 4; 973 n_tokens -= 4; 974 975 /* 976 * Weight. 977 */ 978 if (n_tokens && !strcmp(tokens[0], "weight")) { 979 if (n_tokens < 2) 980 goto error; 981 982 if (parser_read_uint32(&weight_val, tokens[1]) != 0) 983 goto error; 984 *weight = weight_val; 985 986 tokens += 2; 987 n_tokens -= 2; 988 } 989 990 if (n_tokens) 991 goto error; 992 993 free(s0); 994 return 0; 995 996 error: 997 free(s0); 998 if (is_blank_or_comment) 999 *is_blank_or_comment = blank_or_comment; 1000 return -EINVAL; 1001 } 1002 1003 static int 1004 pipeline_selector_group_members_add(struct rte_swx_ctl_pipeline *p, 1005 const char *selector_name, 1006 FILE *file, 1007 uint32_t *file_line_number) 1008 { 1009 char *line = NULL; 1010 uint32_t line_id = 0; 1011 int status = 0; 1012 1013 /* Buffer allocation. */ 1014 line = malloc(MAX_LINE_SIZE); 1015 if (!line) 1016 return -ENOMEM; 1017 1018 /* File read. */ 1019 for (line_id = 1; ; line_id++) { 1020 uint32_t group_id, member_id, weight; 1021 int is_blank_or_comment; 1022 1023 if (fgets(line, MAX_LINE_SIZE, file) == NULL) 1024 break; 1025 1026 status = pipeline_selector_group_member_read(line, 1027 &group_id, 1028 &member_id, 1029 &weight, 1030 &is_blank_or_comment); 1031 if (status) { 1032 if (is_blank_or_comment) 1033 continue; 1034 1035 goto error; 1036 } 1037 1038 status = rte_swx_ctl_pipeline_selector_group_member_add(p, 1039 selector_name, 1040 group_id, 1041 member_id, 1042 weight); 1043 if (status) 1044 goto error; 1045 } 1046 1047 error: 1048 free(line); 1049 *file_line_number = line_id; 1050 return status; 1051 } 1052 1053 /** 1054 * pipeline <pipeline_name> selector <selector_name> group member add <file_name> 1055 */ 1056 static void 1057 cmd_softnic_pipeline_selector_group_member_add(struct pmd_internals *softnic, 1058 char **tokens, 1059 uint32_t n_tokens, 1060 char *out, 1061 size_t out_size) 1062 { 1063 struct pipeline *p; 1064 char *pipeline_name, *selector_name, *file_name; 1065 FILE *file = NULL; 1066 uint32_t file_line_number = 0; 1067 int status; 1068 1069 if (n_tokens != 8) { 1070 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 1071 return; 1072 } 1073 1074 pipeline_name = tokens[1]; 1075 p = softnic_pipeline_find(softnic, pipeline_name); 1076 if (!p) { 1077 snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name"); 1078 return; 1079 } 1080 1081 if (strcmp(tokens[2], "selector") != 0) { 1082 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "selector"); 1083 return; 1084 } 1085 1086 selector_name = tokens[3]; 1087 1088 if (strcmp(tokens[4], "group") || 1089 strcmp(tokens[5], "member") || 1090 strcmp(tokens[6], "add")) { 1091 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "group member add"); 1092 return; 1093 } 1094 1095 file_name = tokens[7]; 1096 file = fopen(file_name, "r"); 1097 if (!file) { 1098 snprintf(out, out_size, "Cannot open file %s.\n", file_name); 1099 return; 1100 } 1101 1102 status = pipeline_selector_group_members_add(p->ctl, 1103 selector_name, 1104 file, 1105 &file_line_number); 1106 if (status) 1107 snprintf(out, out_size, "Invalid entry in file %s at line %u\n", 1108 file_name, 1109 file_line_number); 1110 1111 fclose(file); 1112 } 1113 1114 static int 1115 pipeline_selector_group_members_delete(struct rte_swx_ctl_pipeline *p, 1116 const char *selector_name, 1117 FILE *file, 1118 uint32_t *file_line_number) 1119 { 1120 char *line = NULL; 1121 uint32_t line_id = 0; 1122 int status = 0; 1123 1124 /* Buffer allocation. */ 1125 line = malloc(MAX_LINE_SIZE); 1126 if (!line) 1127 return -ENOMEM; 1128 1129 /* File read. */ 1130 for (line_id = 1; ; line_id++) { 1131 uint32_t group_id, member_id, weight; 1132 int is_blank_or_comment; 1133 1134 if (fgets(line, MAX_LINE_SIZE, file) == NULL) 1135 break; 1136 1137 status = pipeline_selector_group_member_read(line, 1138 &group_id, 1139 &member_id, 1140 &weight, 1141 &is_blank_or_comment); 1142 if (status) { 1143 if (is_blank_or_comment) 1144 continue; 1145 1146 goto error; 1147 } 1148 1149 status = rte_swx_ctl_pipeline_selector_group_member_delete(p, 1150 selector_name, 1151 group_id, 1152 member_id); 1153 if (status) 1154 goto error; 1155 } 1156 1157 error: 1158 free(line); 1159 *file_line_number = line_id; 1160 return status; 1161 } 1162 1163 /** 1164 * pipeline <pipeline_name> selector <selector_name> group member delete <file_name> 1165 */ 1166 static void 1167 cmd_softnic_pipeline_selector_group_member_delete(struct pmd_internals *softnic, 1168 char **tokens, 1169 uint32_t n_tokens, 1170 char *out, 1171 size_t out_size) 1172 { 1173 struct pipeline *p; 1174 char *pipeline_name, *selector_name, *file_name; 1175 FILE *file = NULL; 1176 uint32_t file_line_number = 0; 1177 int status; 1178 1179 if (n_tokens != 8) { 1180 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 1181 return; 1182 } 1183 1184 pipeline_name = tokens[1]; 1185 p = softnic_pipeline_find(softnic, pipeline_name); 1186 if (!p) { 1187 snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name"); 1188 return; 1189 } 1190 1191 if (strcmp(tokens[2], "selector") != 0) { 1192 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "selector"); 1193 return; 1194 } 1195 1196 selector_name = tokens[3]; 1197 1198 if (strcmp(tokens[4], "group") || 1199 strcmp(tokens[5], "member") || 1200 strcmp(tokens[6], "delete")) { 1201 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "group member delete"); 1202 return; 1203 } 1204 1205 file_name = tokens[7]; 1206 file = fopen(file_name, "r"); 1207 if (!file) { 1208 snprintf(out, out_size, "Cannot open file %s.\n", file_name); 1209 return; 1210 } 1211 1212 status = pipeline_selector_group_members_delete(p->ctl, 1213 selector_name, 1214 file, 1215 &file_line_number); 1216 if (status) 1217 snprintf(out, out_size, "Invalid entry in file %s at line %u\n", 1218 file_name, 1219 file_line_number); 1220 1221 fclose(file); 1222 } 1223 1224 /** 1225 * pipeline <pipeline_name> selector <selector_name> show [filename] 1226 */ 1227 static void 1228 cmd_softnic_pipeline_selector_show(struct pmd_internals *softnic, 1229 char **tokens, 1230 uint32_t n_tokens, 1231 char *out, 1232 size_t out_size) 1233 { 1234 struct pipeline *p; 1235 char *pipeline_name, *selector_name; 1236 FILE *file = NULL; 1237 int status; 1238 1239 if (n_tokens != 5 && n_tokens != 6) { 1240 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 1241 return; 1242 } 1243 1244 pipeline_name = tokens[1]; 1245 p = softnic_pipeline_find(softnic, pipeline_name); 1246 if (!p) { 1247 snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name"); 1248 return; 1249 } 1250 1251 selector_name = tokens[3]; 1252 1253 file = (n_tokens == 6) ? fopen(tokens[5], "w") : stdout; 1254 if (!file) { 1255 snprintf(out, out_size, "Cannot open file %s.\n", tokens[5]); 1256 return; 1257 } 1258 1259 status = rte_swx_ctl_pipeline_selector_fprintf(file, p->ctl, selector_name); 1260 if (status) 1261 snprintf(out, out_size, MSG_ARG_INVALID, "selector_name"); 1262 1263 if (file) 1264 fclose(file); 1265 } 1266 1267 static int 1268 pipeline_learner_default_entry_add(struct rte_swx_ctl_pipeline *p, 1269 const char *learner_name, 1270 FILE *file, 1271 uint32_t *file_line_number) 1272 { 1273 char *line = NULL; 1274 uint32_t line_id = 0; 1275 int status = 0; 1276 1277 /* Buffer allocation. */ 1278 line = malloc(MAX_LINE_SIZE); 1279 if (!line) 1280 return -ENOMEM; 1281 1282 /* File read. */ 1283 for (line_id = 1; ; line_id++) { 1284 struct rte_swx_table_entry *entry; 1285 int is_blank_or_comment; 1286 1287 if (fgets(line, MAX_LINE_SIZE, file) == NULL) 1288 break; 1289 1290 entry = rte_swx_ctl_pipeline_learner_default_entry_read(p, 1291 learner_name, 1292 line, 1293 &is_blank_or_comment); 1294 if (!entry) { 1295 if (is_blank_or_comment) 1296 continue; 1297 1298 status = -EINVAL; 1299 goto error; 1300 } 1301 1302 status = rte_swx_ctl_pipeline_learner_default_entry_add(p, 1303 learner_name, 1304 entry); 1305 table_entry_free(entry); 1306 if (status) 1307 goto error; 1308 } 1309 1310 error: 1311 *file_line_number = line_id; 1312 free(line); 1313 return status; 1314 } 1315 1316 /** 1317 * pipeline <pipeline_name> learner <learner_name> default <file_name> 1318 */ 1319 static void 1320 cmd_softnic_pipeline_learner_default(struct pmd_internals *softnic, 1321 char **tokens, 1322 uint32_t n_tokens, 1323 char *out, 1324 size_t out_size) 1325 { 1326 struct pipeline *p; 1327 char *pipeline_name, *learner_name, *file_name; 1328 FILE *file = NULL; 1329 uint32_t file_line_number = 0; 1330 int status; 1331 1332 if (n_tokens != 6) { 1333 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 1334 return; 1335 } 1336 1337 pipeline_name = tokens[1]; 1338 p = softnic_pipeline_find(softnic, pipeline_name); 1339 if (!p) { 1340 snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name"); 1341 return; 1342 } 1343 1344 learner_name = tokens[3]; 1345 1346 file_name = tokens[5]; 1347 file = fopen(file_name, "r"); 1348 if (!file) { 1349 snprintf(out, out_size, "Cannot open file %s.\n", file_name); 1350 return; 1351 } 1352 1353 status = pipeline_learner_default_entry_add(p->ctl, 1354 learner_name, 1355 file, 1356 &file_line_number); 1357 if (status) 1358 snprintf(out, out_size, "Invalid entry in file %s at line %u\n", 1359 file_name, 1360 file_line_number); 1361 1362 fclose(file); 1363 } 1364 1365 /** 1366 * pipeline <pipeline_name> commit 1367 */ 1368 static void 1369 cmd_softnic_pipeline_commit(struct pmd_internals *softnic, 1370 char **tokens, 1371 uint32_t n_tokens, 1372 char *out, 1373 size_t out_size) 1374 { 1375 struct pipeline *p; 1376 char *pipeline_name; 1377 int status; 1378 1379 if (n_tokens != 3) { 1380 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 1381 return; 1382 } 1383 1384 pipeline_name = tokens[1]; 1385 p = softnic_pipeline_find(softnic, pipeline_name); 1386 if (!p) { 1387 snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name"); 1388 return; 1389 } 1390 1391 status = rte_swx_ctl_pipeline_commit(p->ctl, 1); 1392 if (status) 1393 snprintf(out, out_size, "Commit failed. " 1394 "Use \"commit\" to retry or \"abort\" to discard the pending work.\n"); 1395 } 1396 1397 /** 1398 * pipeline <pipeline_name> abort 1399 */ 1400 static void 1401 cmd_softnic_pipeline_abort(struct pmd_internals *softnic, 1402 char **tokens, 1403 uint32_t n_tokens, 1404 char *out, 1405 size_t out_size) 1406 { 1407 struct pipeline *p; 1408 char *pipeline_name; 1409 1410 if (n_tokens != 3) { 1411 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 1412 return; 1413 } 1414 1415 pipeline_name = tokens[1]; 1416 p = softnic_pipeline_find(softnic, pipeline_name); 1417 if (!p) { 1418 snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name"); 1419 return; 1420 } 1421 1422 rte_swx_ctl_pipeline_abort(p->ctl); 1423 } 1424 1425 /** 1426 * pipeline <pipeline_name> regrd <register_array_name> <index> 1427 */ 1428 static void 1429 cmd_softnic_pipeline_regrd(struct pmd_internals *softnic, 1430 char **tokens, 1431 uint32_t n_tokens, 1432 char *out, 1433 size_t out_size) 1434 { 1435 struct pipeline *p; 1436 const char *pipeline_name, *name; 1437 uint64_t value; 1438 uint32_t idx; 1439 int status; 1440 1441 if (n_tokens != 5) { 1442 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 1443 return; 1444 } 1445 1446 pipeline_name = tokens[1]; 1447 p = softnic_pipeline_find(softnic, pipeline_name); 1448 if (!p) { 1449 snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name"); 1450 return; 1451 } 1452 1453 if (strcmp(tokens[2], "regrd")) { 1454 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "regrd"); 1455 return; 1456 } 1457 1458 name = tokens[3]; 1459 1460 if (parser_read_uint32(&idx, tokens[4])) { 1461 snprintf(out, out_size, MSG_ARG_INVALID, "index"); 1462 return; 1463 } 1464 1465 status = rte_swx_ctl_pipeline_regarray_read(p->p, name, idx, &value); 1466 if (status) { 1467 snprintf(out, out_size, "Command failed.\n"); 1468 return; 1469 } 1470 1471 snprintf(out, out_size, "0x%" PRIx64 "\n", value); 1472 } 1473 1474 /** 1475 * pipeline <pipeline_name> regwr <register_array_name> <index> <value> 1476 */ 1477 static void 1478 cmd_softnic_pipeline_regwr(struct pmd_internals *softnic, 1479 char **tokens, 1480 uint32_t n_tokens, 1481 char *out, 1482 size_t out_size) 1483 { 1484 struct pipeline *p; 1485 const char *pipeline_name, *name; 1486 uint64_t value; 1487 uint32_t idx; 1488 int status; 1489 1490 if (n_tokens != 6) { 1491 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 1492 return; 1493 } 1494 1495 pipeline_name = tokens[1]; 1496 p = softnic_pipeline_find(softnic, pipeline_name); 1497 if (!p) { 1498 snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name"); 1499 return; 1500 } 1501 1502 if (strcmp(tokens[2], "regwr")) { 1503 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "regwr"); 1504 return; 1505 } 1506 1507 name = tokens[3]; 1508 1509 if (parser_read_uint32(&idx, tokens[4])) { 1510 snprintf(out, out_size, MSG_ARG_INVALID, "index"); 1511 return; 1512 } 1513 1514 if (parser_read_uint64(&value, tokens[5])) { 1515 snprintf(out, out_size, MSG_ARG_INVALID, "value"); 1516 return; 1517 } 1518 1519 status = rte_swx_ctl_pipeline_regarray_write(p->p, name, idx, value); 1520 if (status) { 1521 snprintf(out, out_size, "Command failed.\n"); 1522 return; 1523 } 1524 } 1525 1526 /** 1527 * pipeline <pipeline_name> meter profile <profile_name> add cir <cir> pir <pir> cbs <cbs> pbs <pbs> 1528 */ 1529 static void 1530 cmd_softnic_pipeline_meter_profile_add(struct pmd_internals *softnic, 1531 char **tokens, 1532 uint32_t n_tokens, 1533 char *out, 1534 size_t out_size) 1535 { 1536 struct rte_meter_trtcm_params params; 1537 struct pipeline *p; 1538 const char *profile_name; 1539 int status; 1540 1541 if (n_tokens != 14) { 1542 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 1543 return; 1544 } 1545 1546 p = softnic_pipeline_find(softnic, tokens[1]); 1547 if (!p) { 1548 snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name"); 1549 return; 1550 } 1551 1552 if (strcmp(tokens[2], "meter")) { 1553 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "meter"); 1554 return; 1555 } 1556 1557 if (strcmp(tokens[3], "profile")) { 1558 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "profile"); 1559 return; 1560 } 1561 1562 profile_name = tokens[4]; 1563 1564 if (strcmp(tokens[5], "add")) { 1565 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "add"); 1566 return; 1567 } 1568 1569 if (strcmp(tokens[6], "cir")) { 1570 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "cir"); 1571 return; 1572 } 1573 1574 if (parser_read_uint64(¶ms.cir, tokens[7])) { 1575 snprintf(out, out_size, MSG_ARG_INVALID, "cir"); 1576 return; 1577 } 1578 1579 if (strcmp(tokens[8], "pir")) { 1580 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pir"); 1581 return; 1582 } 1583 1584 if (parser_read_uint64(¶ms.pir, tokens[9])) { 1585 snprintf(out, out_size, MSG_ARG_INVALID, "pir"); 1586 return; 1587 } 1588 1589 if (strcmp(tokens[10], "cbs")) { 1590 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "cbs"); 1591 return; 1592 } 1593 1594 if (parser_read_uint64(¶ms.cbs, tokens[11])) { 1595 snprintf(out, out_size, MSG_ARG_INVALID, "cbs"); 1596 return; 1597 } 1598 1599 if (strcmp(tokens[12], "pbs")) { 1600 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pbs"); 1601 return; 1602 } 1603 1604 if (parser_read_uint64(¶ms.pbs, tokens[13])) { 1605 snprintf(out, out_size, MSG_ARG_INVALID, "pbs"); 1606 return; 1607 } 1608 1609 status = rte_swx_ctl_meter_profile_add(p->p, profile_name, ¶ms); 1610 if (status) { 1611 snprintf(out, out_size, "Command failed.\n"); 1612 return; 1613 } 1614 } 1615 1616 /** 1617 * pipeline <pipeline_name> meter profile <profile_name> delete 1618 */ 1619 static void 1620 cmd_softnic_pipeline_meter_profile_delete(struct pmd_internals *softnic, 1621 char **tokens, 1622 uint32_t n_tokens, 1623 char *out, 1624 size_t out_size) 1625 { 1626 struct pipeline *p; 1627 const char *profile_name; 1628 int status; 1629 1630 if (n_tokens != 6) { 1631 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 1632 return; 1633 } 1634 1635 p = softnic_pipeline_find(softnic, tokens[1]); 1636 if (!p) { 1637 snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name"); 1638 return; 1639 } 1640 1641 if (strcmp(tokens[2], "meter")) { 1642 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "meter"); 1643 return; 1644 } 1645 1646 if (strcmp(tokens[3], "profile")) { 1647 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "profile"); 1648 return; 1649 } 1650 1651 profile_name = tokens[4]; 1652 1653 if (strcmp(tokens[5], "delete")) { 1654 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "delete"); 1655 return; 1656 } 1657 1658 status = rte_swx_ctl_meter_profile_delete(p->p, profile_name); 1659 if (status) { 1660 snprintf(out, out_size, "Command failed.\n"); 1661 return; 1662 } 1663 } 1664 1665 /** 1666 * pipeline <pipeline_name> meter <meter_array_name> from <index0> to <index1> reset 1667 */ 1668 static void 1669 cmd_softnic_pipeline_meter_reset(struct pmd_internals *softnic, 1670 char **tokens, 1671 uint32_t n_tokens, 1672 char *out, 1673 size_t out_size) 1674 { 1675 struct pipeline *p; 1676 const char *name; 1677 uint32_t idx0 = 0, idx1 = 0; 1678 1679 if (n_tokens != 9) { 1680 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 1681 return; 1682 } 1683 1684 p = softnic_pipeline_find(softnic, tokens[1]); 1685 if (!p) { 1686 snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name"); 1687 return; 1688 } 1689 1690 if (strcmp(tokens[2], "meter")) { 1691 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "meter"); 1692 return; 1693 } 1694 1695 name = tokens[3]; 1696 1697 if (strcmp(tokens[4], "from")) { 1698 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "from"); 1699 return; 1700 } 1701 1702 if (parser_read_uint32(&idx0, tokens[5])) { 1703 snprintf(out, out_size, MSG_ARG_INVALID, "index0"); 1704 return; 1705 } 1706 1707 if (strcmp(tokens[6], "to")) { 1708 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "to"); 1709 return; 1710 } 1711 1712 if (parser_read_uint32(&idx1, tokens[7]) || idx1 < idx0) { 1713 snprintf(out, out_size, MSG_ARG_INVALID, "index1"); 1714 return; 1715 } 1716 1717 if (strcmp(tokens[8], "reset")) { 1718 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "reset"); 1719 return; 1720 } 1721 1722 for ( ; idx0 <= idx1; idx0++) { 1723 int status; 1724 1725 status = rte_swx_ctl_meter_reset(p->p, name, idx0); 1726 if (status) { 1727 snprintf(out, out_size, "Command failed for index %u.\n", idx0); 1728 return; 1729 } 1730 } 1731 } 1732 1733 /** 1734 * pipeline <pipeline_name> meter <meter_array_name> from <index0> to <index1> set 1735 * profile <profile_name> 1736 */ 1737 static void 1738 cmd_softnic_pipeline_meter_set(struct pmd_internals *softnic, 1739 char **tokens, 1740 uint32_t n_tokens, 1741 char *out, 1742 size_t out_size) 1743 { 1744 struct pipeline *p; 1745 const char *name, *profile_name; 1746 uint32_t idx0 = 0, idx1 = 0; 1747 1748 if (n_tokens != 11) { 1749 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 1750 return; 1751 } 1752 1753 p = softnic_pipeline_find(softnic, tokens[1]); 1754 if (!p) { 1755 snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name"); 1756 return; 1757 } 1758 1759 if (strcmp(tokens[2], "meter")) { 1760 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "meter"); 1761 return; 1762 } 1763 1764 name = tokens[3]; 1765 1766 if (strcmp(tokens[4], "from")) { 1767 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "from"); 1768 return; 1769 } 1770 1771 if (parser_read_uint32(&idx0, tokens[5])) { 1772 snprintf(out, out_size, MSG_ARG_INVALID, "index0"); 1773 return; 1774 } 1775 1776 if (strcmp(tokens[6], "to")) { 1777 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "to"); 1778 return; 1779 } 1780 1781 if (parser_read_uint32(&idx1, tokens[7]) || idx1 < idx0) { 1782 snprintf(out, out_size, MSG_ARG_INVALID, "index1"); 1783 return; 1784 } 1785 1786 if (strcmp(tokens[8], "set")) { 1787 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "set"); 1788 return; 1789 } 1790 1791 if (strcmp(tokens[9], "profile")) { 1792 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "profile"); 1793 return; 1794 } 1795 1796 profile_name = tokens[10]; 1797 1798 for ( ; idx0 <= idx1; idx0++) { 1799 int status; 1800 1801 status = rte_swx_ctl_meter_set(p->p, name, idx0, profile_name); 1802 if (status) { 1803 snprintf(out, out_size, "Command failed for index %u.\n", idx0); 1804 return; 1805 } 1806 } 1807 } 1808 1809 /** 1810 * pipeline <pipeline_name> meter <meter_array_name> from <index0> to <index1> stats 1811 */ 1812 static void 1813 cmd_softnic_pipeline_meter_stats(struct pmd_internals *softnic, 1814 char **tokens, 1815 uint32_t n_tokens, 1816 char *out, 1817 size_t out_size) 1818 { 1819 struct rte_swx_ctl_meter_stats stats; 1820 struct pipeline *p; 1821 const char *name; 1822 uint32_t idx0 = 0, idx1 = 0; 1823 1824 if (n_tokens != 9) { 1825 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 1826 return; 1827 } 1828 1829 p = softnic_pipeline_find(softnic, tokens[1]); 1830 if (!p) { 1831 snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name"); 1832 return; 1833 } 1834 1835 if (strcmp(tokens[2], "meter")) { 1836 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "meter"); 1837 return; 1838 } 1839 1840 name = tokens[3]; 1841 1842 if (strcmp(tokens[4], "from")) { 1843 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "from"); 1844 return; 1845 } 1846 1847 if (parser_read_uint32(&idx0, tokens[5])) { 1848 snprintf(out, out_size, MSG_ARG_INVALID, "index0"); 1849 return; 1850 } 1851 1852 if (strcmp(tokens[6], "to")) { 1853 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "to"); 1854 return; 1855 } 1856 1857 if (parser_read_uint32(&idx1, tokens[7]) || idx1 < idx0) { 1858 snprintf(out, out_size, MSG_ARG_INVALID, "index1"); 1859 return; 1860 } 1861 1862 if (strcmp(tokens[8], "stats")) { 1863 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "stats"); 1864 return; 1865 } 1866 1867 /* Table header. */ 1868 snprintf(out, out_size, "+-%7s-+-%16s-+-%16s-+-%16s-+-%16s-+-%16s-+-%16s-+\n", 1869 "-------", 1870 "----------------", "----------------", "----------------", 1871 "----------------", "----------------", "----------------"); 1872 out_size -= strlen(out); 1873 out += strlen(out); 1874 1875 snprintf(out, out_size, "| %4s | %16s | %16s | %16s | %16s | %16s | %16s |\n", 1876 "METER #", 1877 "GREEN (packets)", "YELLOW (packets)", "RED (packets)", 1878 "GREEN (bytes)", "YELLOW (bytes)", "RED (bytes)"); 1879 out_size -= strlen(out); 1880 out += strlen(out); 1881 1882 snprintf(out, out_size, "+-%7s-+-%16s-+-%16s-+-%16s-+-%16s-+-%16s-+-%16s-+\n", 1883 "-------", 1884 "----------------", "----------------", "----------------", 1885 "----------------", "----------------", "----------------"); 1886 out_size -= strlen(out); 1887 out += strlen(out); 1888 1889 /* Table rows. */ 1890 for ( ; idx0 <= idx1; idx0++) { 1891 int status; 1892 1893 status = rte_swx_ctl_meter_stats_read(p->p, name, idx0, &stats); 1894 if (status) { 1895 snprintf(out, out_size, "Pipeline meter stats error at index %u.\n", idx0); 1896 out_size -= strlen(out); 1897 out += strlen(out); 1898 return; 1899 } 1900 1901 snprintf(out, out_size, "| %7d | %16" PRIx64 " | %16" PRIx64 " | %16" PRIx64 1902 " | %16" PRIx64 " | %16" PRIx64 " | %16" PRIx64 " |\n", 1903 idx0, 1904 stats.n_pkts[RTE_COLOR_GREEN], 1905 stats.n_pkts[RTE_COLOR_YELLOW], 1906 stats.n_pkts[RTE_COLOR_RED], 1907 stats.n_bytes[RTE_COLOR_GREEN], 1908 stats.n_bytes[RTE_COLOR_YELLOW], 1909 stats.n_bytes[RTE_COLOR_RED]); 1910 out_size -= strlen(out); 1911 out += strlen(out); 1912 } 1913 } 1914 1915 /** 1916 * pipeline <pipeline_name> stats 1917 */ 1918 static void 1919 cmd_softnic_pipeline_stats(struct pmd_internals *softnic, 1920 char **tokens, 1921 uint32_t n_tokens, 1922 char *out, 1923 size_t out_size) 1924 { 1925 struct rte_swx_ctl_pipeline_info info; 1926 struct pipeline *p; 1927 uint32_t i; 1928 int status; 1929 1930 if (n_tokens != 3) { 1931 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 1932 return; 1933 } 1934 1935 p = softnic_pipeline_find(softnic, tokens[1]); 1936 if (!p) { 1937 snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name"); 1938 return; 1939 } 1940 1941 if (strcmp(tokens[2], "stats")) { 1942 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "stats"); 1943 return; 1944 } 1945 1946 status = rte_swx_ctl_pipeline_info_get(p->p, &info); 1947 if (status) { 1948 snprintf(out, out_size, "Pipeline info get error."); 1949 return; 1950 } 1951 1952 snprintf(out, out_size, "Input ports:\n"); 1953 out_size -= strlen(out); 1954 out += strlen(out); 1955 1956 for (i = 0; i < info.n_ports_in; i++) { 1957 struct rte_swx_port_in_stats stats; 1958 1959 rte_swx_ctl_pipeline_port_in_stats_read(p->p, i, &stats); 1960 1961 snprintf(out, out_size, "\tPort %u:" 1962 " packets %" PRIu64 1963 " bytes %" PRIu64 1964 " empty %" PRIu64 "\n", 1965 i, stats.n_pkts, stats.n_bytes, stats.n_empty); 1966 out_size -= strlen(out); 1967 out += strlen(out); 1968 } 1969 1970 snprintf(out, out_size, "\nOutput ports:\n"); 1971 out_size -= strlen(out); 1972 out += strlen(out); 1973 1974 for (i = 0; i < info.n_ports_out; i++) { 1975 struct rte_swx_port_out_stats stats; 1976 1977 rte_swx_ctl_pipeline_port_out_stats_read(p->p, i, &stats); 1978 1979 if (i != info.n_ports_out - 1) 1980 snprintf(out, out_size, "\tPort %u:", i); 1981 else 1982 snprintf(out, out_size, "\tDROP:"); 1983 1984 out_size -= strlen(out); 1985 out += strlen(out); 1986 1987 snprintf(out, 1988 out_size, 1989 " packets %" PRIu64 1990 " bytes %" PRIu64 1991 " packets dropped %" PRIu64 1992 " bytes dropped %" PRIu64 1993 " clone %" PRIu64 1994 " clonerr %" PRIu64 "\n", 1995 stats.n_pkts, 1996 stats.n_bytes, 1997 stats.n_pkts_drop, 1998 stats.n_bytes_drop, 1999 stats.n_pkts_clone, 2000 stats.n_pkts_clone_err); 2001 2002 out_size -= strlen(out); 2003 out += strlen(out); 2004 } 2005 2006 snprintf(out, out_size, "\nTables:\n"); 2007 out_size -= strlen(out); 2008 out += strlen(out); 2009 2010 for (i = 0; i < info.n_tables; i++) { 2011 struct rte_swx_ctl_table_info table_info; 2012 uint64_t n_pkts_action[info.n_actions]; 2013 struct rte_swx_table_stats stats = { 2014 .n_pkts_hit = 0, 2015 .n_pkts_miss = 0, 2016 .n_pkts_action = n_pkts_action, 2017 }; 2018 uint32_t j; 2019 2020 status = rte_swx_ctl_table_info_get(p->p, i, &table_info); 2021 if (status) { 2022 snprintf(out, out_size, "Table info get error."); 2023 return; 2024 } 2025 2026 status = rte_swx_ctl_pipeline_table_stats_read(p->p, table_info.name, &stats); 2027 if (status) { 2028 snprintf(out, out_size, "Table stats read error."); 2029 return; 2030 } 2031 2032 snprintf(out, out_size, "\tTable %s:\n" 2033 "\t\tHit (packets): %" PRIu64 "\n" 2034 "\t\tMiss (packets): %" PRIu64 "\n", 2035 table_info.name, 2036 stats.n_pkts_hit, 2037 stats.n_pkts_miss); 2038 out_size -= strlen(out); 2039 out += strlen(out); 2040 2041 for (j = 0; j < info.n_actions; j++) { 2042 struct rte_swx_ctl_action_info action_info; 2043 2044 status = rte_swx_ctl_action_info_get(p->p, j, &action_info); 2045 if (status) { 2046 snprintf(out, out_size, "Action info get error."); 2047 return; 2048 } 2049 2050 snprintf(out, out_size, "\t\tAction %s (packets): %" PRIu64 "\n", 2051 action_info.name, 2052 stats.n_pkts_action[j]); 2053 out_size -= strlen(out); 2054 out += strlen(out); 2055 } 2056 } 2057 2058 snprintf(out, out_size, "\nLearner tables:\n"); 2059 out_size -= strlen(out); 2060 out += strlen(out); 2061 2062 for (i = 0; i < info.n_learners; i++) { 2063 struct rte_swx_ctl_learner_info learner_info; 2064 uint64_t n_pkts_action[info.n_actions]; 2065 struct rte_swx_learner_stats stats = { 2066 .n_pkts_hit = 0, 2067 .n_pkts_miss = 0, 2068 .n_pkts_action = n_pkts_action, 2069 }; 2070 uint32_t j; 2071 2072 status = rte_swx_ctl_learner_info_get(p->p, i, &learner_info); 2073 if (status) { 2074 snprintf(out, out_size, "Learner table info get error."); 2075 return; 2076 } 2077 2078 status = rte_swx_ctl_pipeline_learner_stats_read(p->p, learner_info.name, &stats); 2079 if (status) { 2080 snprintf(out, out_size, "Learner table stats read error."); 2081 return; 2082 } 2083 2084 snprintf(out, out_size, "\tLearner table %s:\n" 2085 "\t\tHit (packets): %" PRIu64 "\n" 2086 "\t\tMiss (packets): %" PRIu64 "\n" 2087 "\t\tLearn OK (packets): %" PRIu64 "\n" 2088 "\t\tLearn error (packets): %" PRIu64 "\n" 2089 "\t\tRearm (packets): %" PRIu64 "\n" 2090 "\t\tForget (packets): %" PRIu64 "\n", 2091 learner_info.name, 2092 stats.n_pkts_hit, 2093 stats.n_pkts_miss, 2094 stats.n_pkts_learn_ok, 2095 stats.n_pkts_learn_err, 2096 stats.n_pkts_rearm, 2097 stats.n_pkts_forget); 2098 out_size -= strlen(out); 2099 out += strlen(out); 2100 2101 for (j = 0; j < info.n_actions; j++) { 2102 struct rte_swx_ctl_action_info action_info; 2103 2104 status = rte_swx_ctl_action_info_get(p->p, j, &action_info); 2105 if (status) { 2106 snprintf(out, out_size, "Action info get error."); 2107 return; 2108 } 2109 2110 snprintf(out, out_size, "\t\tAction %s (packets): %" PRIu64 "\n", 2111 action_info.name, 2112 stats.n_pkts_action[j]); 2113 out_size -= strlen(out); 2114 out += strlen(out); 2115 } 2116 } 2117 } 2118 2119 /** 2120 * pipeline <pipeline_name> mirror session <session_id> port <port_id> clone fast | slow 2121 * truncate <truncation_length> 2122 */ 2123 static void 2124 cmd_softnic_pipeline_mirror_session(struct pmd_internals *softnic, 2125 char **tokens, 2126 uint32_t n_tokens, 2127 char *out, 2128 size_t out_size) 2129 { 2130 struct rte_swx_pipeline_mirroring_session_params params; 2131 struct pipeline *p; 2132 uint32_t session_id = 0; 2133 int status; 2134 2135 if (n_tokens != 11) { 2136 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 2137 return; 2138 } 2139 2140 if (strcmp(tokens[0], "pipeline")) { 2141 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pipeline"); 2142 return; 2143 } 2144 2145 p = softnic_pipeline_find(softnic, tokens[1]); 2146 if (!p) { 2147 snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name"); 2148 return; 2149 } 2150 2151 if (strcmp(tokens[2], "mirror")) { 2152 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "mirror"); 2153 return; 2154 } 2155 2156 if (strcmp(tokens[3], "session")) { 2157 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "session"); 2158 return; 2159 } 2160 2161 if (parser_read_uint32(&session_id, tokens[4])) { 2162 snprintf(out, out_size, MSG_ARG_INVALID, "session_id"); 2163 return; 2164 } 2165 2166 if (strcmp(tokens[5], "port")) { 2167 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port"); 2168 return; 2169 } 2170 2171 if (parser_read_uint32(¶ms.port_id, tokens[6])) { 2172 snprintf(out, out_size, MSG_ARG_INVALID, "port_id"); 2173 return; 2174 } 2175 2176 if (strcmp(tokens[7], "clone")) { 2177 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "clone"); 2178 return; 2179 } 2180 2181 if (!strcmp(tokens[8], "fast")) { 2182 params.fast_clone = 1; 2183 } else if (!strcmp(tokens[8], "slow")) { 2184 params.fast_clone = 0; 2185 } else { 2186 snprintf(out, out_size, MSG_ARG_INVALID, "clone"); 2187 return; 2188 } 2189 2190 if (strcmp(tokens[9], "truncate")) { 2191 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "truncate"); 2192 return; 2193 } 2194 2195 if (parser_read_uint32(¶ms.truncation_length, tokens[10])) { 2196 snprintf(out, out_size, MSG_ARG_INVALID, "truncation_length"); 2197 return; 2198 } 2199 2200 status = rte_swx_ctl_pipeline_mirroring_session_set(p->p, session_id, ¶ms); 2201 if (status) { 2202 snprintf(out, out_size, "Command failed!\n"); 2203 return; 2204 } 2205 } 2206 2207 /** 2208 * thread <thread_id> pipeline <pipeline_name> enable [ period <timer_period_ms> ] 2209 */ 2210 static void 2211 cmd_softnic_thread_pipeline_enable(struct pmd_internals *softnic, 2212 char **tokens, 2213 uint32_t n_tokens, 2214 char *out, 2215 size_t out_size) 2216 { 2217 char *pipeline_name; 2218 struct pipeline *p; 2219 uint32_t thread_id; 2220 int status; 2221 2222 if (n_tokens != 5) { 2223 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 2224 return; 2225 } 2226 2227 if (parser_read_uint32(&thread_id, tokens[1]) != 0) { 2228 snprintf(out, out_size, MSG_ARG_INVALID, "thread_id"); 2229 return; 2230 } 2231 2232 if (strcmp(tokens[2], "pipeline") != 0) { 2233 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pipeline"); 2234 return; 2235 } 2236 2237 pipeline_name = tokens[3]; 2238 p = softnic_pipeline_find(softnic, pipeline_name); 2239 if (!p) { 2240 snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name"); 2241 return; 2242 } 2243 2244 if (strcmp(tokens[4], "enable") != 0) { 2245 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "enable"); 2246 return; 2247 } 2248 2249 status = softnic_thread_pipeline_enable(softnic, thread_id, p); 2250 if (status) { 2251 snprintf(out, out_size, MSG_CMD_FAIL, "thread pipeline enable"); 2252 return; 2253 } 2254 } 2255 2256 /** 2257 * thread <thread_id> pipeline <pipeline_name> disable 2258 */ 2259 static void 2260 cmd_softnic_thread_pipeline_disable(struct pmd_internals *softnic, 2261 char **tokens, 2262 uint32_t n_tokens, 2263 char *out, 2264 size_t out_size) 2265 { 2266 char *pipeline_name; 2267 struct pipeline *p; 2268 uint32_t thread_id; 2269 int status; 2270 2271 if (n_tokens != 5) { 2272 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 2273 return; 2274 } 2275 2276 if (parser_read_uint32(&thread_id, tokens[1]) != 0) { 2277 snprintf(out, out_size, MSG_ARG_INVALID, "thread_id"); 2278 return; 2279 } 2280 2281 if (strcmp(tokens[2], "pipeline") != 0) { 2282 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pipeline"); 2283 return; 2284 } 2285 2286 pipeline_name = tokens[3]; 2287 p = softnic_pipeline_find(softnic, pipeline_name); 2288 if (!p) { 2289 snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name"); 2290 return; 2291 } 2292 2293 if (strcmp(tokens[4], "disable") != 0) { 2294 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "disable"); 2295 return; 2296 } 2297 2298 status = softnic_thread_pipeline_disable(softnic, thread_id, p); 2299 if (status) { 2300 snprintf(out, out_size, MSG_CMD_FAIL, 2301 "thread pipeline disable"); 2302 return; 2303 } 2304 } 2305 2306 void 2307 softnic_cli_process(char *in, char *out, size_t out_size, void *arg) 2308 { 2309 char *tokens[CMD_MAX_TOKENS]; 2310 uint32_t n_tokens = RTE_DIM(tokens); 2311 struct pmd_internals *softnic = arg; 2312 int status; 2313 2314 if (is_comment(in)) 2315 return; 2316 2317 status = parse_tokenize_string(in, tokens, &n_tokens); 2318 if (status) { 2319 snprintf(out, out_size, MSG_ARG_TOO_MANY, ""); 2320 return; 2321 } 2322 2323 if (n_tokens == 0) 2324 return; 2325 2326 if (strcmp(tokens[0], "mempool") == 0) { 2327 cmd_mempool(softnic, tokens, n_tokens, out, out_size); 2328 return; 2329 } 2330 2331 if (strcmp(tokens[0], "swq") == 0) { 2332 cmd_swq(softnic, tokens, n_tokens, out, out_size); 2333 return; 2334 } 2335 2336 if (!strcmp(tokens[0], "pipeline")) { 2337 if (n_tokens >= 2 && !strcmp(tokens[1], "codegen")) { 2338 cmd_softnic_pipeline_codegen(softnic, tokens, n_tokens, out, out_size); 2339 return; 2340 } 2341 2342 if (n_tokens >= 3 && !strcmp(tokens[1], "libbuild")) { 2343 cmd_softnic_pipeline_libbuild(softnic, tokens, n_tokens, out, out_size); 2344 return; 2345 } 2346 2347 if (n_tokens >= 3 && !strcmp(tokens[2], "build")) { 2348 cmd_softnic_pipeline_build(softnic, tokens, n_tokens, out, out_size); 2349 return; 2350 } 2351 2352 if (n_tokens >= 5 && !strcmp(tokens[2], "table") && !strcmp(tokens[4], "add")) { 2353 cmd_softnic_pipeline_table_add(softnic, tokens, n_tokens, out, out_size); 2354 return; 2355 } 2356 2357 if (n_tokens >= 5 && !strcmp(tokens[2], "table") && !strcmp(tokens[4], "delete")) { 2358 cmd_softnic_pipeline_table_delete(softnic, tokens, n_tokens, 2359 out, out_size); 2360 return; 2361 } 2362 2363 if (n_tokens >= 5 && !strcmp(tokens[2], "table") && !strcmp(tokens[4], "default")) { 2364 cmd_softnic_pipeline_table_default(softnic, tokens, n_tokens, 2365 out, out_size); 2366 return; 2367 } 2368 2369 if (n_tokens >= 5 && !strcmp(tokens[2], "table") && !strcmp(tokens[4], "show")) { 2370 cmd_softnic_pipeline_table_show(softnic, tokens, n_tokens, out, out_size); 2371 return; 2372 } 2373 2374 if (n_tokens >= 6 && 2375 !strcmp(tokens[2], "selector") && 2376 !strcmp(tokens[4], "group") && 2377 !strcmp(tokens[5], "add")) { 2378 cmd_softnic_pipeline_selector_group_add(softnic, tokens, n_tokens, 2379 out, out_size); 2380 return; 2381 } 2382 2383 if (n_tokens >= 6 && 2384 !strcmp(tokens[2], "selector") && 2385 !strcmp(tokens[4], "group") && 2386 !strcmp(tokens[5], "delete")) { 2387 cmd_softnic_pipeline_selector_group_delete(softnic, tokens, n_tokens, 2388 out, out_size); 2389 return; 2390 } 2391 2392 if (n_tokens >= 7 && 2393 !strcmp(tokens[2], "selector") && 2394 !strcmp(tokens[4], "group") && 2395 !strcmp(tokens[5], "member") && 2396 !strcmp(tokens[6], "add")) { 2397 cmd_softnic_pipeline_selector_group_member_add(softnic, tokens, n_tokens, 2398 out, out_size); 2399 return; 2400 } 2401 2402 if (n_tokens >= 7 && 2403 !strcmp(tokens[2], "selector") && 2404 !strcmp(tokens[4], "group") && 2405 !strcmp(tokens[5], "member") && 2406 !strcmp(tokens[6], "delete")) { 2407 cmd_softnic_pipeline_selector_group_member_delete(softnic, tokens, n_tokens, 2408 out, out_size); 2409 return; 2410 } 2411 2412 if (n_tokens >= 5 && 2413 !strcmp(tokens[2], "selector") && 2414 !strcmp(tokens[4], "show")) { 2415 cmd_softnic_pipeline_selector_show(softnic, tokens, n_tokens, 2416 out, out_size); 2417 return; 2418 } 2419 2420 if (n_tokens >= 5 && 2421 !strcmp(tokens[2], "learner") && 2422 !strcmp(tokens[4], "default")) { 2423 cmd_softnic_pipeline_learner_default(softnic, tokens, n_tokens, 2424 out, out_size); 2425 return; 2426 } 2427 2428 if (n_tokens >= 3 && !strcmp(tokens[2], "commit")) { 2429 cmd_softnic_pipeline_commit(softnic, tokens, n_tokens, out, out_size); 2430 return; 2431 } 2432 2433 if (n_tokens >= 3 && !strcmp(tokens[2], "abort")) { 2434 cmd_softnic_pipeline_abort(softnic, tokens, n_tokens, out, out_size); 2435 return; 2436 } 2437 2438 if (n_tokens >= 3 && !strcmp(tokens[2], "regrd")) { 2439 cmd_softnic_pipeline_regrd(softnic, tokens, n_tokens, out, out_size); 2440 return; 2441 } 2442 2443 if (n_tokens >= 3 && !strcmp(tokens[2], "regwr")) { 2444 cmd_softnic_pipeline_regwr(softnic, tokens, n_tokens, out, out_size); 2445 return; 2446 } 2447 2448 if (n_tokens >= 6 && 2449 !strcmp(tokens[2], "meter") && 2450 !strcmp(tokens[3], "profile") && 2451 !strcmp(tokens[5], "add")) { 2452 cmd_softnic_pipeline_meter_profile_add(softnic, tokens, n_tokens, 2453 out, out_size); 2454 return; 2455 } 2456 2457 if (n_tokens >= 6 && 2458 !strcmp(tokens[2], "meter") && 2459 !strcmp(tokens[3], "profile") && 2460 !strcmp(tokens[5], "delete")) { 2461 cmd_softnic_pipeline_meter_profile_delete(softnic, tokens, n_tokens, 2462 out, out_size); 2463 return; 2464 } 2465 2466 if (n_tokens >= 9 && !strcmp(tokens[2], "meter") && !strcmp(tokens[8], "reset")) { 2467 cmd_softnic_pipeline_meter_reset(softnic, tokens, n_tokens, out, out_size); 2468 return; 2469 } 2470 2471 if (n_tokens >= 9 && !strcmp(tokens[2], "meter") && !strcmp(tokens[8], "set")) { 2472 cmd_softnic_pipeline_meter_set(softnic, tokens, n_tokens, out, out_size); 2473 return; 2474 } 2475 2476 if (n_tokens >= 9 && !strcmp(tokens[2], "meter") && !strcmp(tokens[8], "stats")) { 2477 cmd_softnic_pipeline_meter_stats(softnic, tokens, n_tokens, out, out_size); 2478 return; 2479 } 2480 2481 if (n_tokens >= 3 && !strcmp(tokens[2], "stats")) { 2482 cmd_softnic_pipeline_stats(softnic, tokens, n_tokens, out, out_size); 2483 return; 2484 } 2485 2486 if (n_tokens >= 4 && 2487 !strcmp(tokens[2], "mirror") && 2488 !strcmp(tokens[3], "session")) { 2489 cmd_softnic_pipeline_mirror_session(softnic, tokens, n_tokens, 2490 out, out_size); 2491 return; 2492 } 2493 } 2494 2495 if (strcmp(tokens[0], "thread") == 0) { 2496 if (n_tokens >= 5 && 2497 (strcmp(tokens[4], "enable") == 0)) { 2498 cmd_softnic_thread_pipeline_enable(softnic, tokens, n_tokens, 2499 out, out_size); 2500 return; 2501 } 2502 2503 if (n_tokens >= 5 && 2504 (strcmp(tokens[4], "disable") == 0)) { 2505 cmd_softnic_thread_pipeline_disable(softnic, tokens, n_tokens, 2506 out, out_size); 2507 return; 2508 } 2509 } 2510 2511 snprintf(out, out_size, MSG_CMD_UNKNOWN, tokens[0]); 2512 } 2513 2514 int 2515 softnic_cli_script_process(struct pmd_internals *softnic, 2516 const char *file_name, 2517 size_t msg_in_len_max, 2518 size_t msg_out_len_max) 2519 { 2520 char *msg_in = NULL, *msg_out = NULL; 2521 FILE *f = NULL; 2522 2523 /* Check input arguments */ 2524 if (file_name == NULL || 2525 (strlen(file_name) == 0) || 2526 msg_in_len_max == 0 || 2527 msg_out_len_max == 0) 2528 return -EINVAL; 2529 2530 msg_in = malloc(msg_in_len_max + 1); 2531 msg_out = malloc(msg_out_len_max + 1); 2532 if (msg_in == NULL || 2533 msg_out == NULL) { 2534 free(msg_out); 2535 free(msg_in); 2536 return -ENOMEM; 2537 } 2538 2539 /* Open input file */ 2540 f = fopen(file_name, "r"); 2541 if (f == NULL) { 2542 free(msg_out); 2543 free(msg_in); 2544 return -EIO; 2545 } 2546 2547 /* Read file */ 2548 for ( ; ; ) { 2549 if (fgets(msg_in, msg_in_len_max + 1, f) == NULL) 2550 break; 2551 2552 printf("%s", msg_in); 2553 msg_out[0] = 0; 2554 2555 softnic_cli_process(msg_in, 2556 msg_out, 2557 msg_out_len_max, 2558 softnic); 2559 2560 if (strlen(msg_out)) 2561 printf("%s", msg_out); 2562 } 2563 2564 /* Close file */ 2565 fclose(f); 2566 free(msg_out); 2567 free(msg_in); 2568 return 0; 2569 } 2570