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