1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2020 Intel Corporation 3 */ 4 5 #include <ctype.h> 6 #include <stdio.h> 7 #include <stdint.h> 8 #include <stdlib.h> 9 #include <string.h> 10 #include <unistd.h> 11 12 #include <rte_common.h> 13 #include <rte_ethdev.h> 14 #include <rte_ring.h> 15 #include <rte_swx_port_ethdev.h> 16 #include <rte_swx_port_ring.h> 17 #include <rte_swx_port_source_sink.h> 18 #include <rte_swx_port_fd.h> 19 #include <rte_swx_pipeline.h> 20 #include <rte_swx_ctl.h> 21 #include <rte_swx_ipsec.h> 22 23 #include "cli.h" 24 25 #include "obj.h" 26 #include "thread.h" 27 28 #ifndef CMD_MAX_TOKENS 29 #define CMD_MAX_TOKENS 256 30 #endif 31 32 #ifndef MAX_LINE_SIZE 33 #define MAX_LINE_SIZE 2048 34 #endif 35 36 #define MSG_OUT_OF_MEMORY "Not enough memory.\n" 37 #define MSG_CMD_UNKNOWN "Unknown command \"%s\".\n" 38 #define MSG_CMD_UNIMPLEM "Command \"%s\" not implemented.\n" 39 #define MSG_ARG_NOT_ENOUGH "Not enough arguments for command \"%s\".\n" 40 #define MSG_ARG_TOO_MANY "Too many arguments for command \"%s\".\n" 41 #define MSG_ARG_MISMATCH "Wrong number of arguments for command \"%s\".\n" 42 #define MSG_ARG_NOT_FOUND "Argument \"%s\" not found.\n" 43 #define MSG_ARG_INVALID "Invalid value for argument \"%s\".\n" 44 #define MSG_FILE_ERR "Error in file \"%s\" at line %u.\n" 45 #define MSG_FILE_NOT_ENOUGH "Not enough rules in file \"%s\".\n" 46 #define MSG_CMD_FAIL "Command \"%s\" failed.\n" 47 48 #define skip_white_spaces(pos) \ 49 ({ \ 50 __typeof__(pos) _p = (pos); \ 51 for ( ; isspace(*_p); _p++) \ 52 ; \ 53 _p; \ 54 }) 55 56 static int 57 parser_read_uint64(uint64_t *value, const char *p) 58 { 59 char *next; 60 uint64_t val; 61 62 p = skip_white_spaces(p); 63 if (!isdigit(*p)) 64 return -EINVAL; 65 66 val = strtoul(p, &next, 0); 67 if (p == next) 68 return -EINVAL; 69 70 p = next; 71 switch (*p) { 72 case 'T': 73 val *= 1024ULL; 74 /* fall through */ 75 case 'G': 76 val *= 1024ULL; 77 /* fall through */ 78 case 'M': 79 val *= 1024ULL; 80 /* fall through */ 81 case 'k': 82 case 'K': 83 val *= 1024ULL; 84 p++; 85 break; 86 } 87 88 p = skip_white_spaces(p); 89 if (*p != '\0') 90 return -EINVAL; 91 92 *value = val; 93 return 0; 94 } 95 96 static int 97 parser_read_uint32(uint32_t *value, const char *p) 98 { 99 uint64_t val = 0; 100 int ret = parser_read_uint64(&val, p); 101 102 if (ret < 0) 103 return ret; 104 105 if (val > UINT32_MAX) 106 return -ERANGE; 107 108 *value = val; 109 return 0; 110 } 111 112 #define PARSE_DELIMITER " \f\n\r\t\v" 113 114 static int 115 parse_tokenize_string(char *string, char *tokens[], uint32_t *n_tokens) 116 { 117 uint32_t i; 118 119 if ((string == NULL) || 120 (tokens == NULL) || 121 (*n_tokens < 1)) 122 return -EINVAL; 123 124 for (i = 0; i < *n_tokens; i++) { 125 tokens[i] = strtok_r(string, PARSE_DELIMITER, &string); 126 if (tokens[i] == NULL) 127 break; 128 } 129 130 if ((i == *n_tokens) && strtok_r(string, PARSE_DELIMITER, &string)) 131 return -E2BIG; 132 133 *n_tokens = i; 134 return 0; 135 } 136 137 static int 138 is_comment(char *in) 139 { 140 if ((strlen(in) && index("!#%;", in[0])) || 141 (strncmp(in, "//", 2) == 0) || 142 (strncmp(in, "--", 2) == 0)) 143 return 1; 144 145 return 0; 146 } 147 148 static void 149 table_entry_free(struct rte_swx_table_entry *entry) 150 { 151 if (!entry) 152 return; 153 154 free(entry->key); 155 free(entry->key_mask); 156 free(entry->action_data); 157 free(entry); 158 } 159 160 static struct rte_swx_table_entry * 161 parse_table_entry(struct rte_swx_ctl_pipeline *p, 162 char *table_name, 163 char **tokens, 164 uint32_t n_tokens) 165 { 166 struct rte_swx_table_entry *entry; 167 char *line; 168 uint32_t i; 169 170 /* Buffer allocation. */ 171 line = malloc(MAX_LINE_SIZE); 172 if (!line) 173 return NULL; 174 175 /* Copy tokens to buffer. Since the tokens were initially part of a buffer of size 176 * MAX_LINE_LENGTH, it is guaranteed that putting back some of them into a buffer of the 177 * same size separated by a single space will not result in buffer overrun. 178 */ 179 line[0] = 0; 180 for (i = 0; i < n_tokens; i++) { 181 if (i) 182 strcat(line, " "); 183 184 strcat(line, tokens[i]); 185 } 186 187 /* Read the table entry from the input buffer. */ 188 entry = rte_swx_ctl_pipeline_table_entry_read(p, table_name, line, NULL); 189 190 /* Buffer free. */ 191 free(line); 192 193 return entry; 194 } 195 196 static const char cmd_mempool_help[] = 197 "mempool <mempool_name> " 198 "meta <mbuf_private_size> " 199 "pkt <pkt_buffer_size> " 200 "pool <pool_size> " 201 "cache <cache_size> " 202 "numa <numa_node>\n"; 203 204 static void 205 cmd_mempool(char **tokens, 206 uint32_t n_tokens, 207 char *out, 208 size_t out_size, 209 void *obj __rte_unused) 210 { 211 struct rte_mempool *mp; 212 char *mempool_name; 213 uint32_t mbuf_private_size, pkt_buffer_size, pool_size, cache_size, numa_node; 214 215 if (n_tokens != 12) { 216 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 217 return; 218 } 219 220 mempool_name = tokens[1]; 221 222 if (strcmp(tokens[2], "meta")) { 223 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "meta"); 224 return; 225 } 226 227 if (parser_read_uint32(&mbuf_private_size, tokens[3])) { 228 snprintf(out, out_size, MSG_ARG_INVALID, "mbuf_private_size"); 229 return; 230 } 231 232 if (strcmp(tokens[4], "pkt")) { 233 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pkt"); 234 return; 235 } 236 237 if (parser_read_uint32(&pkt_buffer_size, tokens[5])) { 238 snprintf(out, out_size, MSG_ARG_INVALID, "pkt_buffer_size"); 239 return; 240 } 241 242 if (strcmp(tokens[6], "pool")) { 243 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pool"); 244 return; 245 } 246 247 if (parser_read_uint32(&pool_size, tokens[7])) { 248 snprintf(out, out_size, MSG_ARG_INVALID, "pool_size"); 249 return; 250 } 251 252 if (strcmp(tokens[8], "cache")) { 253 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "cache"); 254 return; 255 } 256 257 if (parser_read_uint32(&cache_size, tokens[9])) { 258 snprintf(out, out_size, MSG_ARG_INVALID, "cache_size"); 259 return; 260 } 261 262 if (strcmp(tokens[10], "numa")) { 263 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "numa"); 264 return; 265 } 266 267 if (parser_read_uint32(&numa_node, tokens[11])) { 268 snprintf(out, out_size, MSG_ARG_INVALID, "numa_node"); 269 return; 270 } 271 272 mp = rte_pktmbuf_pool_create(mempool_name, 273 pool_size, 274 cache_size, 275 mbuf_private_size, 276 pkt_buffer_size, 277 numa_node); 278 if (!mp) { 279 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 280 return; 281 } 282 } 283 284 static const char cmd_ethdev_help[] = 285 "ethdev <ethdev_name>\n" 286 " rxq <n_queues> <queue_size> <mempool_name>\n" 287 " txq <n_queues> <queue_size>\n" 288 " promiscuous on | off\n" 289 " [rss <qid_0> ... <qid_n>]\n"; 290 291 static void 292 cmd_ethdev(char **tokens, 293 uint32_t n_tokens, 294 char *out, 295 size_t out_size, 296 void *obj __rte_unused) 297 { 298 struct ethdev_params p; 299 struct ethdev_params_rss rss; 300 char *name; 301 int status; 302 303 memset(&p, 0, sizeof(p)); 304 memset(&rss, 0, sizeof(rss)); 305 306 if (n_tokens < 11 || n_tokens > 12 + ETHDEV_RXQ_RSS_MAX) { 307 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 308 return; 309 } 310 name = tokens[1]; 311 312 if (strcmp(tokens[2], "rxq") != 0) { 313 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rxq"); 314 return; 315 } 316 317 if (parser_read_uint32(&p.rx.n_queues, tokens[3]) != 0) { 318 snprintf(out, out_size, MSG_ARG_INVALID, "n_queues"); 319 return; 320 } 321 if (parser_read_uint32(&p.rx.queue_size, tokens[4]) != 0) { 322 snprintf(out, out_size, MSG_ARG_INVALID, "queue_size"); 323 return; 324 } 325 326 p.rx.mempool_name = tokens[5]; 327 328 if (strcmp(tokens[6], "txq") != 0) { 329 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "txq"); 330 return; 331 } 332 333 if (parser_read_uint32(&p.tx.n_queues, tokens[7]) != 0) { 334 snprintf(out, out_size, MSG_ARG_INVALID, "n_queues"); 335 return; 336 } 337 338 if (parser_read_uint32(&p.tx.queue_size, tokens[8]) != 0) { 339 snprintf(out, out_size, MSG_ARG_INVALID, "queue_size"); 340 return; 341 } 342 343 if (strcmp(tokens[9], "promiscuous") != 0) { 344 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "promiscuous"); 345 return; 346 } 347 348 if (strcmp(tokens[10], "on") == 0) 349 p.promiscuous = 1; 350 else if (strcmp(tokens[10], "off") == 0) 351 p.promiscuous = 0; 352 else { 353 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "on or off"); 354 return; 355 } 356 357 /* RSS */ 358 p.rx.rss = NULL; 359 if (n_tokens > 11) { 360 uint32_t queue_id, i; 361 362 if (strcmp(tokens[11], "rss") != 0) { 363 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rss"); 364 return; 365 } 366 367 p.rx.rss = &rss; 368 369 rss.n_queues = 0; 370 for (i = 12; i < n_tokens; i++) { 371 if (parser_read_uint32(&queue_id, tokens[i]) != 0) { 372 snprintf(out, out_size, MSG_ARG_INVALID, 373 "queue_id"); 374 return; 375 } 376 377 rss.queue_id[rss.n_queues] = queue_id; 378 rss.n_queues++; 379 } 380 } 381 382 status = ethdev_config(name, &p); 383 if (status) { 384 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 385 return; 386 } 387 } 388 389 static void 390 ethdev_show(uint16_t port_id, char **out, size_t *out_size) 391 { 392 char name[RTE_ETH_NAME_MAX_LEN]; 393 struct rte_eth_dev_info info; 394 struct rte_eth_stats stats; 395 struct rte_ether_addr addr; 396 struct rte_eth_link link; 397 uint32_t length; 398 uint16_t mtu = 0; 399 400 if (!rte_eth_dev_is_valid_port(port_id)) 401 return; 402 403 rte_eth_dev_get_name_by_port(port_id, name); 404 rte_eth_dev_info_get(port_id, &info); 405 rte_eth_stats_get(port_id, &stats); 406 rte_eth_macaddr_get(port_id, &addr); 407 rte_eth_link_get(port_id, &link); 408 rte_eth_dev_get_mtu(port_id, &mtu); 409 410 snprintf(*out, *out_size, 411 "%s: flags=<%s> mtu %u\n" 412 "\tether " RTE_ETHER_ADDR_PRT_FMT " rxqueues %u txqueues %u\n" 413 "\tport# %u speed %s\n" 414 "\tRX packets %" PRIu64" bytes %" PRIu64"\n" 415 "\tRX errors %" PRIu64" missed %" PRIu64" no-mbuf %" PRIu64"\n" 416 "\tTX packets %" PRIu64" bytes %" PRIu64"\n" 417 "\tTX errors %" PRIu64"\n\n", 418 name, 419 link.link_status ? "UP" : "DOWN", 420 mtu, 421 RTE_ETHER_ADDR_BYTES(&addr), 422 info.nb_rx_queues, 423 info.nb_tx_queues, 424 port_id, 425 rte_eth_link_speed_to_str(link.link_speed), 426 stats.ipackets, 427 stats.ibytes, 428 stats.ierrors, 429 stats.imissed, 430 stats.rx_nombuf, 431 stats.opackets, 432 stats.obytes, 433 stats.oerrors); 434 435 length = strlen(*out); 436 *out_size -= length; 437 *out += length; 438 } 439 440 441 static char cmd_ethdev_show_help[] = 442 "ethdev show [ <ethdev_name> ]\n"; 443 444 static void 445 cmd_ethdev_show(char **tokens, 446 uint32_t n_tokens, 447 char *out, 448 size_t out_size, 449 void *obj __rte_unused) 450 { 451 uint16_t port_id; 452 453 if (n_tokens != 2 && n_tokens != 3) { 454 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 455 return; 456 } 457 458 /* Single device. */ 459 if (n_tokens == 3) { 460 int status; 461 462 status = rte_eth_dev_get_port_by_name(tokens[2], &port_id); 463 if (status) 464 snprintf(out, out_size, "Error: Invalid Ethernet device name.\n"); 465 466 ethdev_show(port_id, &out, &out_size); 467 return; 468 } 469 470 /* All devices. */ 471 for (port_id = 0; port_id < RTE_MAX_ETHPORTS; port_id++) 472 if (rte_eth_dev_is_valid_port(port_id)) 473 ethdev_show(port_id, &out, &out_size); 474 } 475 476 static const char cmd_ring_help[] = 477 "ring <ring_name> size <size> numa <numa_node>\n"; 478 479 static void 480 cmd_ring(char **tokens, 481 uint32_t n_tokens, 482 char *out, 483 size_t out_size, 484 void *obj __rte_unused) 485 { 486 struct rte_ring *r; 487 char *name; 488 uint32_t size, numa_node; 489 490 if (n_tokens != 6) { 491 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 492 return; 493 } 494 495 name = tokens[1]; 496 497 if (strcmp(tokens[2], "size")) { 498 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "size"); 499 return; 500 } 501 502 if (parser_read_uint32(&size, tokens[3])) { 503 snprintf(out, out_size, MSG_ARG_INVALID, "size"); 504 return; 505 } 506 507 if (strcmp(tokens[4], "numa")) { 508 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "numa"); 509 return; 510 } 511 512 if (parser_read_uint32(&numa_node, tokens[5])) { 513 snprintf(out, out_size, MSG_ARG_INVALID, "numa_node"); 514 return; 515 } 516 517 r = rte_ring_create( 518 name, 519 size, 520 (int)numa_node, 521 RING_F_SP_ENQ | RING_F_SC_DEQ); 522 if (!r) { 523 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 524 return; 525 } 526 } 527 528 static const char cmd_cryptodev_help[] = 529 "cryptodev <cryptodev_name> queues <n_queue_pairs> qsize <queue_size>\n"; 530 531 static void 532 cmd_cryptodev(char **tokens, 533 uint32_t n_tokens, 534 char *out, 535 size_t out_size, 536 void *obj __rte_unused) 537 { 538 struct cryptodev_params params; 539 char *cryptodev_name; 540 int status; 541 542 if (n_tokens != 6) { 543 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 544 return; 545 } 546 547 if (strcmp(tokens[0], "cryptodev")) { 548 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "cryptodev"); 549 return; 550 } 551 552 cryptodev_name = tokens[1]; 553 554 if (strcmp(tokens[2], "queues")) { 555 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "queues"); 556 return; 557 } 558 559 if (parser_read_uint32(¶ms.n_queue_pairs, tokens[3])) { 560 snprintf(out, out_size, MSG_ARG_INVALID, "n_queue_pairs"); 561 return; 562 } 563 564 if (strcmp(tokens[4], "qsize")) { 565 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "qsize"); 566 return; 567 } 568 569 570 if (parser_read_uint32(¶ms.queue_size, tokens[5])) { 571 snprintf(out, out_size, MSG_ARG_INVALID, "queue_size"); 572 return; 573 } 574 575 status = cryptodev_config(cryptodev_name, ¶ms); 576 if (status) 577 snprintf(out, out_size, "Crypto device configuration failed (%d).\n", status); 578 } 579 580 static const char cmd_pipeline_codegen_help[] = 581 "pipeline codegen <spec_file> <code_file>\n"; 582 583 static void 584 cmd_pipeline_codegen(char **tokens, 585 uint32_t n_tokens, 586 char *out, 587 size_t out_size, 588 void *obj __rte_unused) 589 { 590 FILE *spec_file = NULL; 591 FILE *code_file = NULL; 592 uint32_t err_line; 593 const char *err_msg; 594 int status; 595 596 if (n_tokens != 4) { 597 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 598 return; 599 } 600 601 spec_file = fopen(tokens[2], "r"); 602 if (!spec_file) { 603 snprintf(out, out_size, "Cannot open file %s.\n", tokens[2]); 604 return; 605 } 606 607 code_file = fopen(tokens[3], "w"); 608 if (!code_file) { 609 snprintf(out, out_size, "Cannot open file %s.\n", tokens[3]); 610 fclose(spec_file); 611 return; 612 } 613 614 status = rte_swx_pipeline_codegen(spec_file, 615 code_file, 616 &err_line, 617 &err_msg); 618 619 fclose(spec_file); 620 fclose(code_file); 621 622 if (status) { 623 snprintf(out, out_size, "Error %d at line %u: %s\n.", 624 status, err_line, err_msg); 625 return; 626 } 627 } 628 629 static const char cmd_pipeline_libbuild_help[] = 630 "pipeline libbuild <code_file> <lib_file>\n"; 631 632 static void 633 cmd_pipeline_libbuild(char **tokens, 634 uint32_t n_tokens, 635 char *out, 636 size_t out_size, 637 void *obj __rte_unused) 638 { 639 char *code_file, *lib_file, *obj_file = NULL, *log_file = NULL; 640 char *install_dir, *cwd = NULL, *buffer = NULL; 641 size_t length; 642 int status = 0; 643 644 if (n_tokens != 4) { 645 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 646 goto free; 647 } 648 649 install_dir = getenv("RTE_INSTALL_DIR"); 650 if (!install_dir) { 651 cwd = malloc(MAX_LINE_SIZE); 652 if (!cwd) { 653 snprintf(out, out_size, MSG_OUT_OF_MEMORY); 654 goto free; 655 } 656 657 install_dir = getcwd(cwd, MAX_LINE_SIZE); 658 if (!install_dir) { 659 snprintf(out, out_size, "Error: Path too long.\n"); 660 goto free; 661 } 662 } 663 664 snprintf(out, out_size, "Using DPDK source code from \"%s\".\n", install_dir); 665 out_size -= strlen(out); 666 out += strlen(out); 667 668 code_file = tokens[2]; 669 length = strnlen(code_file, MAX_LINE_SIZE); 670 if ((length < 3) || 671 (code_file[length - 2] != '.') || 672 (code_file[length - 1] != 'c')) { 673 snprintf(out, out_size, MSG_ARG_INVALID, "code_file"); 674 goto free; 675 } 676 677 lib_file = tokens[3]; 678 length = strnlen(lib_file, MAX_LINE_SIZE); 679 if ((length < 4) || 680 (lib_file[length - 3] != '.') || 681 (lib_file[length - 2] != 's') || 682 (lib_file[length - 1] != 'o')) { 683 snprintf(out, out_size, MSG_ARG_INVALID, "lib_file"); 684 goto free; 685 } 686 687 obj_file = malloc(length); 688 log_file = malloc(length + 2); 689 if (!obj_file || !log_file) { 690 snprintf(out, out_size, MSG_OUT_OF_MEMORY); 691 goto free; 692 } 693 694 memcpy(obj_file, lib_file, length - 2); 695 obj_file[length - 2] = 'o'; 696 obj_file[length - 1] = 0; 697 698 memcpy(log_file, lib_file, length - 2); 699 log_file[length - 2] = 'l'; 700 log_file[length - 1] = 'o'; 701 log_file[length] = 'g'; 702 log_file[length + 1] = 0; 703 704 buffer = malloc(MAX_LINE_SIZE); 705 if (!buffer) { 706 snprintf(out, out_size, MSG_OUT_OF_MEMORY); 707 goto free; 708 } 709 710 snprintf(buffer, 711 MAX_LINE_SIZE, 712 "gcc -c -O3 -fpic -Wno-deprecated-declarations -o %s %s " 713 "-I %s/lib/pipeline " 714 "-I %s/lib/eal/include " 715 "-I %s/lib/eal/x86/include " 716 "-I %s/lib/eal/include/generic " 717 "-I %s/lib/meter " 718 "-I %s/lib/port " 719 "-I %s/lib/table " 720 "-I %s/lib/pipeline " 721 "-I %s/config " 722 "-I %s/build " 723 "-I %s/lib/eal/linux/include " 724 ">%s 2>&1 " 725 "&& " 726 "gcc -shared %s -o %s " 727 ">>%s 2>&1", 728 obj_file, 729 code_file, 730 install_dir, 731 install_dir, 732 install_dir, 733 install_dir, 734 install_dir, 735 install_dir, 736 install_dir, 737 install_dir, 738 install_dir, 739 install_dir, 740 install_dir, 741 log_file, 742 obj_file, 743 lib_file, 744 log_file); 745 746 status = system(buffer); 747 if (status) { 748 snprintf(out, 749 out_size, 750 "Library build failed, see file \"%s\" for details.\n", 751 log_file); 752 goto free; 753 } 754 755 free: 756 free(cwd); 757 free(obj_file); 758 free(log_file); 759 free(buffer); 760 } 761 762 static const char cmd_pipeline_build_help[] = 763 "pipeline <pipeline_name> build lib <lib_file> io <iospec_file> numa <numa_node>\n"; 764 765 static void 766 cmd_pipeline_build(char **tokens, 767 uint32_t n_tokens, 768 char *out, 769 size_t out_size, 770 void *obj __rte_unused) 771 { 772 struct rte_swx_pipeline *p = NULL; 773 struct rte_swx_ctl_pipeline *ctl = NULL; 774 char *pipeline_name, *lib_file_name, *iospec_file_name; 775 FILE *iospec_file = NULL; 776 uint32_t numa_node = 0; 777 int status = 0; 778 779 /* Parsing. */ 780 if (n_tokens != 9) { 781 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 782 return; 783 } 784 785 pipeline_name = tokens[1]; 786 787 if (strcmp(tokens[2], "build")) { 788 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "build"); 789 return; 790 } 791 792 if (strcmp(tokens[3], "lib")) { 793 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "lib"); 794 return; 795 } 796 797 lib_file_name = tokens[4]; 798 799 if (strcmp(tokens[5], "io")) { 800 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "io"); 801 return; 802 } 803 804 iospec_file_name = tokens[6]; 805 806 if (strcmp(tokens[7], "numa")) { 807 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "numa"); 808 return; 809 } 810 811 if (parser_read_uint32(&numa_node, tokens[8])) { 812 snprintf(out, out_size, MSG_ARG_INVALID, "numa_node"); 813 return; 814 } 815 816 /* I/O spec file open. */ 817 iospec_file = fopen(iospec_file_name, "r"); 818 if (!iospec_file) { 819 snprintf(out, out_size, "Cannot open file \"%s\".\n", iospec_file_name); 820 return; 821 } 822 823 status = rte_swx_pipeline_build_from_lib(&p, 824 pipeline_name, 825 lib_file_name, 826 iospec_file, 827 (int)numa_node); 828 if (status) { 829 snprintf(out, out_size, "Pipeline build failed (%d).", status); 830 goto free; 831 } 832 833 ctl = rte_swx_ctl_pipeline_create(p); 834 if (!ctl) { 835 snprintf(out, out_size, "Pipeline control create failed."); 836 goto free; 837 } 838 839 free: 840 if (status) 841 rte_swx_pipeline_free(p); 842 843 if (iospec_file) 844 fclose(iospec_file); 845 } 846 847 static int 848 pipeline_table_entries_add(struct rte_swx_ctl_pipeline *p, 849 const char *table_name, 850 FILE *file, 851 uint32_t *file_line_number) 852 { 853 char *line = NULL; 854 uint32_t line_id = 0; 855 int status = 0; 856 857 /* Buffer allocation. */ 858 line = malloc(MAX_LINE_SIZE); 859 if (!line) 860 return -ENOMEM; 861 862 /* File read. */ 863 for (line_id = 1; ; line_id++) { 864 struct rte_swx_table_entry *entry; 865 int is_blank_or_comment; 866 867 if (fgets(line, MAX_LINE_SIZE, file) == NULL) 868 break; 869 870 entry = rte_swx_ctl_pipeline_table_entry_read(p, 871 table_name, 872 line, 873 &is_blank_or_comment); 874 if (!entry) { 875 if (is_blank_or_comment) 876 continue; 877 878 status = -EINVAL; 879 goto error; 880 } 881 882 status = rte_swx_ctl_pipeline_table_entry_add(p, 883 table_name, 884 entry); 885 table_entry_free(entry); 886 if (status) 887 goto error; 888 } 889 890 error: 891 free(line); 892 *file_line_number = line_id; 893 return status; 894 } 895 896 static const char cmd_pipeline_table_add_help[] = 897 "pipeline <pipeline_name> table <table_name> add <file_name>\n"; 898 899 static void 900 cmd_pipeline_table_add(char **tokens, 901 uint32_t n_tokens, 902 char *out, 903 size_t out_size, 904 void *obj __rte_unused) 905 { 906 struct rte_swx_ctl_pipeline *ctl; 907 char *pipeline_name, *table_name, *file_name; 908 FILE *file = NULL; 909 uint32_t file_line_number = 0; 910 int status; 911 912 if (n_tokens != 6) { 913 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 914 return; 915 } 916 917 pipeline_name = tokens[1]; 918 ctl = rte_swx_ctl_pipeline_find(pipeline_name); 919 if (!ctl) { 920 snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name"); 921 return; 922 } 923 924 table_name = tokens[3]; 925 926 file_name = tokens[5]; 927 file = fopen(file_name, "r"); 928 if (!file) { 929 snprintf(out, out_size, "Cannot open file %s.\n", file_name); 930 return; 931 } 932 933 status = pipeline_table_entries_add(ctl, 934 table_name, 935 file, 936 &file_line_number); 937 if (status) 938 snprintf(out, out_size, "Invalid entry in file %s at line %u\n", 939 file_name, 940 file_line_number); 941 942 fclose(file); 943 } 944 945 static int 946 pipeline_table_entries_delete(struct rte_swx_ctl_pipeline *p, 947 const char *table_name, 948 FILE *file, 949 uint32_t *file_line_number) 950 { 951 char *line = NULL; 952 uint32_t line_id = 0; 953 int status = 0; 954 955 /* Buffer allocation. */ 956 line = malloc(MAX_LINE_SIZE); 957 if (!line) 958 return -ENOMEM; 959 960 /* File read. */ 961 for (line_id = 1; ; line_id++) { 962 struct rte_swx_table_entry *entry; 963 int is_blank_or_comment; 964 965 if (fgets(line, MAX_LINE_SIZE, file) == NULL) 966 break; 967 968 entry = rte_swx_ctl_pipeline_table_entry_read(p, 969 table_name, 970 line, 971 &is_blank_or_comment); 972 if (!entry) { 973 if (is_blank_or_comment) 974 continue; 975 976 status = -EINVAL; 977 goto error; 978 } 979 980 status = rte_swx_ctl_pipeline_table_entry_delete(p, 981 table_name, 982 entry); 983 table_entry_free(entry); 984 if (status) 985 goto error; 986 } 987 988 error: 989 *file_line_number = line_id; 990 free(line); 991 return status; 992 } 993 994 static const char cmd_pipeline_table_delete_help[] = 995 "pipeline <pipeline_name> table <table_name> delete <file_name>\n"; 996 997 static void 998 cmd_pipeline_table_delete(char **tokens, 999 uint32_t n_tokens, 1000 char *out, 1001 size_t out_size, 1002 void *obj __rte_unused) 1003 { 1004 struct rte_swx_ctl_pipeline *ctl; 1005 char *pipeline_name, *table_name, *file_name; 1006 FILE *file = NULL; 1007 uint32_t file_line_number = 0; 1008 int status; 1009 1010 if (n_tokens != 6) { 1011 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 1012 return; 1013 } 1014 1015 pipeline_name = tokens[1]; 1016 ctl = rte_swx_ctl_pipeline_find(pipeline_name); 1017 if (!ctl) { 1018 snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name"); 1019 return; 1020 } 1021 1022 table_name = tokens[3]; 1023 1024 file_name = tokens[5]; 1025 file = fopen(file_name, "r"); 1026 if (!file) { 1027 snprintf(out, out_size, "Cannot open file %s.\n", file_name); 1028 return; 1029 } 1030 1031 status = pipeline_table_entries_delete(ctl, 1032 table_name, 1033 file, 1034 &file_line_number); 1035 if (status) 1036 snprintf(out, out_size, "Invalid entry in file %s at line %u\n", 1037 file_name, 1038 file_line_number); 1039 1040 fclose(file); 1041 } 1042 1043 static int 1044 pipeline_table_default_entry_add(struct rte_swx_ctl_pipeline *p, 1045 const char *table_name, 1046 FILE *file, 1047 uint32_t *file_line_number) 1048 { 1049 char *line = NULL; 1050 uint32_t line_id = 0; 1051 int status = 0; 1052 1053 /* Buffer allocation. */ 1054 line = malloc(MAX_LINE_SIZE); 1055 if (!line) 1056 return -ENOMEM; 1057 1058 /* File read. */ 1059 for (line_id = 1; ; line_id++) { 1060 struct rte_swx_table_entry *entry; 1061 int is_blank_or_comment; 1062 1063 if (fgets(line, MAX_LINE_SIZE, file) == NULL) 1064 break; 1065 1066 entry = rte_swx_ctl_pipeline_table_entry_read(p, 1067 table_name, 1068 line, 1069 &is_blank_or_comment); 1070 if (!entry) { 1071 if (is_blank_or_comment) 1072 continue; 1073 1074 status = -EINVAL; 1075 goto error; 1076 } 1077 1078 status = rte_swx_ctl_pipeline_table_default_entry_add(p, 1079 table_name, 1080 entry); 1081 table_entry_free(entry); 1082 if (status) 1083 goto error; 1084 } 1085 1086 error: 1087 *file_line_number = line_id; 1088 free(line); 1089 return status; 1090 } 1091 1092 static const char cmd_pipeline_table_default_help[] = 1093 "pipeline <pipeline_name> table <table_name> default <file_name>\n"; 1094 1095 static void 1096 cmd_pipeline_table_default(char **tokens, 1097 uint32_t n_tokens, 1098 char *out, 1099 size_t out_size, 1100 void *obj __rte_unused) 1101 { 1102 struct rte_swx_ctl_pipeline *ctl; 1103 char *pipeline_name, *table_name, *file_name; 1104 FILE *file = NULL; 1105 uint32_t file_line_number = 0; 1106 int status; 1107 1108 if (n_tokens != 6) { 1109 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 1110 return; 1111 } 1112 1113 pipeline_name = tokens[1]; 1114 ctl = rte_swx_ctl_pipeline_find(pipeline_name); 1115 if (!ctl) { 1116 snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name"); 1117 return; 1118 } 1119 1120 table_name = tokens[3]; 1121 1122 file_name = tokens[5]; 1123 file = fopen(file_name, "r"); 1124 if (!file) { 1125 snprintf(out, out_size, "Cannot open file %s.\n", file_name); 1126 return; 1127 } 1128 1129 status = pipeline_table_default_entry_add(ctl, 1130 table_name, 1131 file, 1132 &file_line_number); 1133 if (status) 1134 snprintf(out, out_size, "Invalid entry in file %s at line %u\n", 1135 file_name, 1136 file_line_number); 1137 1138 fclose(file); 1139 } 1140 1141 static const char cmd_pipeline_table_show_help[] = 1142 "pipeline <pipeline_name> table <table_name> show [filename]\n"; 1143 1144 static void 1145 cmd_pipeline_table_show(char **tokens, 1146 uint32_t n_tokens, 1147 char *out, 1148 size_t out_size, 1149 void *obj __rte_unused) 1150 { 1151 struct rte_swx_ctl_pipeline *ctl; 1152 char *pipeline_name, *table_name; 1153 FILE *file = NULL; 1154 int status; 1155 1156 if (n_tokens != 5 && n_tokens != 6) { 1157 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 1158 return; 1159 } 1160 1161 pipeline_name = tokens[1]; 1162 ctl = rte_swx_ctl_pipeline_find(pipeline_name); 1163 if (!ctl) { 1164 snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name"); 1165 return; 1166 } 1167 1168 table_name = tokens[3]; 1169 file = (n_tokens == 6) ? fopen(tokens[5], "w") : stdout; 1170 if (!file) { 1171 snprintf(out, out_size, "Cannot open file %s.\n", tokens[5]); 1172 return; 1173 } 1174 1175 status = rte_swx_ctl_pipeline_table_fprintf(file, ctl, table_name); 1176 if (status) 1177 snprintf(out, out_size, MSG_ARG_INVALID, "table_name"); 1178 1179 if (file) 1180 fclose(file); 1181 } 1182 1183 static const char cmd_pipeline_selector_group_add_help[] = 1184 "pipeline <pipeline_name> selector <selector_name> group add\n"; 1185 1186 static void 1187 cmd_pipeline_selector_group_add(char **tokens, 1188 uint32_t n_tokens, 1189 char *out, 1190 size_t out_size, 1191 void *obj __rte_unused) 1192 { 1193 struct rte_swx_ctl_pipeline *ctl; 1194 char *pipeline_name, *selector_name; 1195 uint32_t group_id; 1196 int status; 1197 1198 if (n_tokens != 6) { 1199 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 1200 return; 1201 } 1202 1203 pipeline_name = tokens[1]; 1204 ctl = rte_swx_ctl_pipeline_find(pipeline_name); 1205 if (!ctl) { 1206 snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name"); 1207 return; 1208 } 1209 1210 if (strcmp(tokens[2], "selector") != 0) { 1211 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "selector"); 1212 return; 1213 } 1214 1215 selector_name = tokens[3]; 1216 1217 if (strcmp(tokens[4], "group") || 1218 strcmp(tokens[5], "add")) { 1219 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "group add"); 1220 return; 1221 } 1222 1223 status = rte_swx_ctl_pipeline_selector_group_add(ctl, 1224 selector_name, 1225 &group_id); 1226 if (status) 1227 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 1228 else 1229 snprintf(out, out_size, "Group ID: %u\n", group_id); 1230 } 1231 1232 static const char cmd_pipeline_selector_group_delete_help[] = 1233 "pipeline <pipeline_name> selector <selector_name> group delete <group_id>\n"; 1234 1235 static void 1236 cmd_pipeline_selector_group_delete(char **tokens, 1237 uint32_t n_tokens, 1238 char *out, 1239 size_t out_size, 1240 void *obj __rte_unused) 1241 { 1242 struct rte_swx_ctl_pipeline *ctl; 1243 char *pipeline_name, *selector_name; 1244 uint32_t group_id; 1245 int status; 1246 1247 if (n_tokens != 7) { 1248 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 1249 return; 1250 } 1251 1252 pipeline_name = tokens[1]; 1253 ctl = rte_swx_ctl_pipeline_find(pipeline_name); 1254 if (!ctl) { 1255 snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name"); 1256 return; 1257 } 1258 1259 if (strcmp(tokens[2], "selector") != 0) { 1260 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "selector"); 1261 return; 1262 } 1263 1264 selector_name = tokens[3]; 1265 1266 if (strcmp(tokens[4], "group") || 1267 strcmp(tokens[5], "delete")) { 1268 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "group delete"); 1269 return; 1270 } 1271 1272 if (parser_read_uint32(&group_id, tokens[6]) != 0) { 1273 snprintf(out, out_size, MSG_ARG_INVALID, "group_id"); 1274 return; 1275 } 1276 1277 status = rte_swx_ctl_pipeline_selector_group_delete(ctl, 1278 selector_name, 1279 group_id); 1280 if (status) 1281 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 1282 } 1283 1284 #define GROUP_MEMBER_INFO_TOKENS_MAX 6 1285 1286 static int 1287 token_is_comment(const char *token) 1288 { 1289 if ((token[0] == '#') || 1290 (token[0] == ';') || 1291 ((token[0] == '/') && (token[1] == '/'))) 1292 return 1; /* TRUE. */ 1293 1294 return 0; /* FALSE. */ 1295 } 1296 1297 static int 1298 pipeline_selector_group_member_read(const char *string, 1299 uint32_t *group_id, 1300 uint32_t *member_id, 1301 uint32_t *weight, 1302 int *is_blank_or_comment) 1303 { 1304 char *token_array[GROUP_MEMBER_INFO_TOKENS_MAX], **tokens; 1305 char *s0 = NULL, *s; 1306 uint32_t n_tokens = 0, group_id_val = 0, member_id_val = 0, weight_val = 0; 1307 int blank_or_comment = 0; 1308 1309 /* Check input arguments. */ 1310 if (!string || !string[0]) 1311 goto error; 1312 1313 /* Memory allocation. */ 1314 s0 = strdup(string); 1315 if (!s0) 1316 goto error; 1317 1318 /* Parse the string into tokens. */ 1319 for (s = s0; ; ) { 1320 char *token; 1321 1322 token = strtok_r(s, " \f\n\r\t\v", &s); 1323 if (!token || token_is_comment(token)) 1324 break; 1325 1326 if (n_tokens >= GROUP_MEMBER_INFO_TOKENS_MAX) 1327 goto error; 1328 1329 token_array[n_tokens] = token; 1330 n_tokens++; 1331 } 1332 1333 if (!n_tokens) { 1334 blank_or_comment = 1; 1335 goto error; 1336 } 1337 1338 tokens = token_array; 1339 1340 if (n_tokens < 4 || 1341 strcmp(tokens[0], "group") || 1342 strcmp(tokens[2], "member")) 1343 goto error; 1344 1345 /* 1346 * Group ID. 1347 */ 1348 if (parser_read_uint32(&group_id_val, tokens[1]) != 0) 1349 goto error; 1350 *group_id = group_id_val; 1351 1352 /* 1353 * Member ID. 1354 */ 1355 if (parser_read_uint32(&member_id_val, tokens[3]) != 0) 1356 goto error; 1357 *member_id = member_id_val; 1358 1359 tokens += 4; 1360 n_tokens -= 4; 1361 1362 /* 1363 * Weight. 1364 */ 1365 if (n_tokens && !strcmp(tokens[0], "weight")) { 1366 if (n_tokens < 2) 1367 goto error; 1368 1369 if (parser_read_uint32(&weight_val, tokens[1]) != 0) 1370 goto error; 1371 *weight = weight_val; 1372 1373 tokens += 2; 1374 n_tokens -= 2; 1375 } 1376 1377 if (n_tokens) 1378 goto error; 1379 1380 free(s0); 1381 return 0; 1382 1383 error: 1384 free(s0); 1385 if (is_blank_or_comment) 1386 *is_blank_or_comment = blank_or_comment; 1387 return -EINVAL; 1388 } 1389 1390 static int 1391 pipeline_selector_group_members_add(struct rte_swx_ctl_pipeline *p, 1392 const char *selector_name, 1393 FILE *file, 1394 uint32_t *file_line_number) 1395 { 1396 char *line = NULL; 1397 uint32_t line_id = 0; 1398 int status = 0; 1399 1400 /* Buffer allocation. */ 1401 line = malloc(MAX_LINE_SIZE); 1402 if (!line) 1403 return -ENOMEM; 1404 1405 /* File read. */ 1406 for (line_id = 1; ; line_id++) { 1407 uint32_t group_id, member_id, weight; 1408 int is_blank_or_comment; 1409 1410 if (fgets(line, MAX_LINE_SIZE, file) == NULL) 1411 break; 1412 1413 status = pipeline_selector_group_member_read(line, 1414 &group_id, 1415 &member_id, 1416 &weight, 1417 &is_blank_or_comment); 1418 if (status) { 1419 if (is_blank_or_comment) 1420 continue; 1421 1422 goto error; 1423 } 1424 1425 status = rte_swx_ctl_pipeline_selector_group_member_add(p, 1426 selector_name, 1427 group_id, 1428 member_id, 1429 weight); 1430 if (status) 1431 goto error; 1432 } 1433 1434 error: 1435 free(line); 1436 *file_line_number = line_id; 1437 return status; 1438 } 1439 1440 static const char cmd_pipeline_selector_group_member_add_help[] = 1441 "pipeline <pipeline_name> selector <selector_name> group member add <file_name>"; 1442 1443 static void 1444 cmd_pipeline_selector_group_member_add(char **tokens, 1445 uint32_t n_tokens, 1446 char *out, 1447 size_t out_size, 1448 void *obj __rte_unused) 1449 { 1450 struct rte_swx_ctl_pipeline *ctl; 1451 char *pipeline_name, *selector_name, *file_name; 1452 FILE *file = NULL; 1453 uint32_t file_line_number = 0; 1454 int status; 1455 1456 if (n_tokens != 8) { 1457 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 1458 return; 1459 } 1460 1461 pipeline_name = tokens[1]; 1462 ctl = rte_swx_ctl_pipeline_find(pipeline_name); 1463 if (!ctl) { 1464 snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name"); 1465 return; 1466 } 1467 1468 if (strcmp(tokens[2], "selector") != 0) { 1469 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "selector"); 1470 return; 1471 } 1472 1473 selector_name = tokens[3]; 1474 1475 if (strcmp(tokens[4], "group") || 1476 strcmp(tokens[5], "member") || 1477 strcmp(tokens[6], "add")) { 1478 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "group member add"); 1479 return; 1480 } 1481 1482 file_name = tokens[7]; 1483 file = fopen(file_name, "r"); 1484 if (!file) { 1485 snprintf(out, out_size, "Cannot open file %s.\n", file_name); 1486 return; 1487 } 1488 1489 status = pipeline_selector_group_members_add(ctl, 1490 selector_name, 1491 file, 1492 &file_line_number); 1493 if (status) 1494 snprintf(out, out_size, "Invalid entry in file %s at line %u\n", 1495 file_name, 1496 file_line_number); 1497 1498 fclose(file); 1499 } 1500 1501 static int 1502 pipeline_selector_group_members_delete(struct rte_swx_ctl_pipeline *p, 1503 const char *selector_name, 1504 FILE *file, 1505 uint32_t *file_line_number) 1506 { 1507 char *line = NULL; 1508 uint32_t line_id = 0; 1509 int status = 0; 1510 1511 /* Buffer allocation. */ 1512 line = malloc(MAX_LINE_SIZE); 1513 if (!line) 1514 return -ENOMEM; 1515 1516 /* File read. */ 1517 for (line_id = 1; ; line_id++) { 1518 uint32_t group_id, member_id, weight; 1519 int is_blank_or_comment; 1520 1521 if (fgets(line, MAX_LINE_SIZE, file) == NULL) 1522 break; 1523 1524 status = pipeline_selector_group_member_read(line, 1525 &group_id, 1526 &member_id, 1527 &weight, 1528 &is_blank_or_comment); 1529 if (status) { 1530 if (is_blank_or_comment) 1531 continue; 1532 1533 goto error; 1534 } 1535 1536 status = rte_swx_ctl_pipeline_selector_group_member_delete(p, 1537 selector_name, 1538 group_id, 1539 member_id); 1540 if (status) 1541 goto error; 1542 } 1543 1544 error: 1545 free(line); 1546 *file_line_number = line_id; 1547 return status; 1548 } 1549 1550 static const char cmd_pipeline_selector_group_member_delete_help[] = 1551 "pipeline <pipeline_name> selector <selector_name> group member delete <file_name>"; 1552 1553 static void 1554 cmd_pipeline_selector_group_member_delete(char **tokens, 1555 uint32_t n_tokens, 1556 char *out, 1557 size_t out_size, 1558 void *obj __rte_unused) 1559 { 1560 struct rte_swx_ctl_pipeline *ctl; 1561 char *pipeline_name, *selector_name, *file_name; 1562 FILE *file = NULL; 1563 uint32_t file_line_number = 0; 1564 int status; 1565 1566 if (n_tokens != 8) { 1567 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 1568 return; 1569 } 1570 1571 pipeline_name = tokens[1]; 1572 ctl = rte_swx_ctl_pipeline_find(pipeline_name); 1573 if (!ctl) { 1574 snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name"); 1575 return; 1576 } 1577 1578 if (strcmp(tokens[2], "selector") != 0) { 1579 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "selector"); 1580 return; 1581 } 1582 1583 selector_name = tokens[3]; 1584 1585 if (strcmp(tokens[4], "group") || 1586 strcmp(tokens[5], "member") || 1587 strcmp(tokens[6], "delete")) { 1588 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "group member delete"); 1589 return; 1590 } 1591 1592 file_name = tokens[7]; 1593 file = fopen(file_name, "r"); 1594 if (!file) { 1595 snprintf(out, out_size, "Cannot open file %s.\n", file_name); 1596 return; 1597 } 1598 1599 status = pipeline_selector_group_members_delete(ctl, 1600 selector_name, 1601 file, 1602 &file_line_number); 1603 if (status) 1604 snprintf(out, out_size, "Invalid entry in file %s at line %u\n", 1605 file_name, 1606 file_line_number); 1607 1608 fclose(file); 1609 } 1610 1611 static const char cmd_pipeline_selector_show_help[] = 1612 "pipeline <pipeline_name> selector <selector_name> show [filename]\n"; 1613 1614 static void 1615 cmd_pipeline_selector_show(char **tokens, 1616 uint32_t n_tokens, 1617 char *out, 1618 size_t out_size, 1619 void *obj __rte_unused) 1620 { 1621 struct rte_swx_ctl_pipeline *ctl; 1622 char *pipeline_name, *selector_name; 1623 FILE *file = NULL; 1624 int status; 1625 1626 if (n_tokens != 5 && n_tokens != 6) { 1627 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 1628 return; 1629 } 1630 1631 pipeline_name = tokens[1]; 1632 ctl = rte_swx_ctl_pipeline_find(pipeline_name); 1633 if (!ctl) { 1634 snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name"); 1635 return; 1636 } 1637 1638 selector_name = tokens[3]; 1639 1640 file = (n_tokens == 6) ? fopen(tokens[5], "w") : stdout; 1641 if (!file) { 1642 snprintf(out, out_size, "Cannot open file %s.\n", tokens[5]); 1643 return; 1644 } 1645 1646 status = rte_swx_ctl_pipeline_selector_fprintf(file, ctl, selector_name); 1647 if (status) 1648 snprintf(out, out_size, MSG_ARG_INVALID, "selector_name"); 1649 1650 if (file) 1651 fclose(file); 1652 } 1653 1654 static int 1655 pipeline_learner_default_entry_add(struct rte_swx_ctl_pipeline *p, 1656 const char *learner_name, 1657 FILE *file, 1658 uint32_t *file_line_number) 1659 { 1660 char *line = NULL; 1661 uint32_t line_id = 0; 1662 int status = 0; 1663 1664 /* Buffer allocation. */ 1665 line = malloc(MAX_LINE_SIZE); 1666 if (!line) 1667 return -ENOMEM; 1668 1669 /* File read. */ 1670 for (line_id = 1; ; line_id++) { 1671 struct rte_swx_table_entry *entry; 1672 int is_blank_or_comment; 1673 1674 if (fgets(line, MAX_LINE_SIZE, file) == NULL) 1675 break; 1676 1677 entry = rte_swx_ctl_pipeline_learner_default_entry_read(p, 1678 learner_name, 1679 line, 1680 &is_blank_or_comment); 1681 if (!entry) { 1682 if (is_blank_or_comment) 1683 continue; 1684 1685 status = -EINVAL; 1686 goto error; 1687 } 1688 1689 status = rte_swx_ctl_pipeline_learner_default_entry_add(p, 1690 learner_name, 1691 entry); 1692 table_entry_free(entry); 1693 if (status) 1694 goto error; 1695 } 1696 1697 error: 1698 *file_line_number = line_id; 1699 free(line); 1700 return status; 1701 } 1702 1703 static const char cmd_pipeline_learner_default_help[] = 1704 "pipeline <pipeline_name> learner <learner_name> default <file_name>\n"; 1705 1706 static void 1707 cmd_pipeline_learner_default(char **tokens, 1708 uint32_t n_tokens, 1709 char *out, 1710 size_t out_size, 1711 void *obj __rte_unused) 1712 { 1713 struct rte_swx_ctl_pipeline *ctl; 1714 char *pipeline_name, *learner_name, *file_name; 1715 FILE *file = NULL; 1716 uint32_t file_line_number = 0; 1717 int status; 1718 1719 if (n_tokens != 6) { 1720 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 1721 return; 1722 } 1723 1724 pipeline_name = tokens[1]; 1725 ctl = rte_swx_ctl_pipeline_find(pipeline_name); 1726 if (!ctl) { 1727 snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name"); 1728 return; 1729 } 1730 1731 learner_name = tokens[3]; 1732 1733 file_name = tokens[5]; 1734 file = fopen(file_name, "r"); 1735 if (!file) { 1736 snprintf(out, out_size, "Cannot open file %s.\n", file_name); 1737 return; 1738 } 1739 1740 status = pipeline_learner_default_entry_add(ctl, 1741 learner_name, 1742 file, 1743 &file_line_number); 1744 if (status) 1745 snprintf(out, out_size, "Invalid entry in file %s at line %u\n", 1746 file_name, 1747 file_line_number); 1748 1749 fclose(file); 1750 } 1751 1752 static const char cmd_pipeline_commit_help[] = 1753 "pipeline <pipeline_name> commit\n"; 1754 1755 static void 1756 cmd_pipeline_commit(char **tokens, 1757 uint32_t n_tokens, 1758 char *out, 1759 size_t out_size, 1760 void *obj __rte_unused) 1761 { 1762 struct rte_swx_ctl_pipeline *ctl; 1763 char *pipeline_name; 1764 int status; 1765 1766 if (n_tokens != 3) { 1767 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 1768 return; 1769 } 1770 1771 pipeline_name = tokens[1]; 1772 ctl = rte_swx_ctl_pipeline_find(pipeline_name); 1773 if (!ctl) { 1774 snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name"); 1775 return; 1776 } 1777 1778 status = rte_swx_ctl_pipeline_commit(ctl, 1); 1779 if (status) 1780 snprintf(out, out_size, "Commit failed. " 1781 "Use \"commit\" to retry or \"abort\" to discard the pending work.\n"); 1782 } 1783 1784 static const char cmd_pipeline_abort_help[] = 1785 "pipeline <pipeline_name> abort\n"; 1786 1787 static void 1788 cmd_pipeline_abort(char **tokens, 1789 uint32_t n_tokens, 1790 char *out, 1791 size_t out_size, 1792 void *obj __rte_unused) 1793 { 1794 struct rte_swx_ctl_pipeline *ctl; 1795 char *pipeline_name; 1796 1797 if (n_tokens != 3) { 1798 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 1799 return; 1800 } 1801 1802 pipeline_name = tokens[1]; 1803 ctl = rte_swx_ctl_pipeline_find(pipeline_name); 1804 if (!ctl) { 1805 snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name"); 1806 return; 1807 } 1808 1809 rte_swx_ctl_pipeline_abort(ctl); 1810 } 1811 1812 static const char cmd_pipeline_regrd_help[] = 1813 "pipeline <pipeline_name> regrd <register_array_name>\n" 1814 "index <index>\n" 1815 " | table <table_name> match <field0> ...\n"; 1816 1817 static void 1818 cmd_pipeline_regrd(char **tokens, 1819 uint32_t n_tokens, 1820 char *out, 1821 size_t out_size, 1822 void *obj __rte_unused) 1823 { 1824 struct rte_swx_pipeline *p; 1825 struct rte_swx_ctl_pipeline *ctl; 1826 const char *pipeline_name, *name; 1827 uint64_t value; 1828 int status; 1829 1830 if (n_tokens < 5) { 1831 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 1832 return; 1833 } 1834 1835 pipeline_name = tokens[1]; 1836 p = rte_swx_pipeline_find(pipeline_name); 1837 ctl = rte_swx_ctl_pipeline_find(pipeline_name); 1838 if (!p || !ctl) { 1839 snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name"); 1840 return; 1841 } 1842 1843 if (strcmp(tokens[2], "regrd")) { 1844 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "regrd"); 1845 return; 1846 } 1847 1848 name = tokens[3]; 1849 1850 /* index. */ 1851 if (!strcmp(tokens[4], "index")) { 1852 uint32_t idx = 0; 1853 1854 if (n_tokens != 6) { 1855 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 1856 return; 1857 } 1858 1859 if (parser_read_uint32(&idx, tokens[5])) { 1860 snprintf(out, out_size, MSG_ARG_INVALID, "index"); 1861 return; 1862 } 1863 1864 status = rte_swx_ctl_pipeline_regarray_read(p, name, idx, &value); 1865 if (status) { 1866 snprintf(out, out_size, "Command failed.\n"); 1867 return; 1868 } 1869 1870 snprintf(out, out_size, "0x%" PRIx64 "\n", value); 1871 return; 1872 } 1873 1874 /* table. */ 1875 if (!strcmp(tokens[4], "table")) { 1876 struct rte_swx_table_entry *entry; 1877 char *table_name; 1878 1879 if (n_tokens < 8) { 1880 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 1881 return; 1882 } 1883 1884 table_name = tokens[5]; 1885 1886 if (strcmp(tokens[6], "match")) { 1887 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "match"); 1888 return; 1889 } 1890 1891 entry = parse_table_entry(ctl, table_name, &tokens[6], n_tokens - 6); 1892 if (!entry) { 1893 snprintf(out, out_size, "Invalid match tokens.\n"); 1894 return; 1895 } 1896 1897 status = rte_swx_ctl_pipeline_regarray_read_with_key(p, 1898 name, 1899 table_name, 1900 entry->key, 1901 &value); 1902 table_entry_free(entry); 1903 if (status) { 1904 snprintf(out, out_size, "Command failed.\n"); 1905 return; 1906 } 1907 1908 snprintf(out, out_size, "0x%" PRIx64 "\n", value); 1909 return; 1910 } 1911 1912 /* anything else. */ 1913 snprintf(out, out_size, "Invalid token %s\n.", tokens[4]); 1914 return; 1915 } 1916 1917 static const char cmd_pipeline_regwr_help[] = 1918 "pipeline <pipeline_name> regwr <register_array_name> value <value>\n" 1919 "index <index>\n" 1920 " | table <table_name> match <field0> ...\n"; 1921 1922 static void 1923 cmd_pipeline_regwr(char **tokens, 1924 uint32_t n_tokens, 1925 char *out, 1926 size_t out_size, 1927 void *obj __rte_unused) 1928 { 1929 struct rte_swx_pipeline *p; 1930 struct rte_swx_ctl_pipeline *ctl; 1931 const char *pipeline_name, *name; 1932 uint64_t value = 0; 1933 int status; 1934 1935 if (n_tokens < 7) { 1936 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 1937 return; 1938 } 1939 1940 pipeline_name = tokens[1]; 1941 p = rte_swx_pipeline_find(pipeline_name); 1942 ctl = rte_swx_ctl_pipeline_find(pipeline_name); 1943 if (!p || !ctl) { 1944 snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name"); 1945 return; 1946 } 1947 1948 if (strcmp(tokens[2], "regwr")) { 1949 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "regwr"); 1950 return; 1951 } 1952 1953 name = tokens[3]; 1954 1955 if (strcmp(tokens[4], "value")) { 1956 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "value"); 1957 return; 1958 } 1959 1960 if (parser_read_uint64(&value, tokens[5])) { 1961 snprintf(out, out_size, MSG_ARG_INVALID, "value"); 1962 return; 1963 } 1964 1965 /* index. */ 1966 if (!strcmp(tokens[6], "index")) { 1967 uint32_t idx = 0; 1968 1969 if (n_tokens != 8) { 1970 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 1971 return; 1972 } 1973 1974 if (parser_read_uint32(&idx, tokens[7])) { 1975 snprintf(out, out_size, MSG_ARG_INVALID, "index"); 1976 return; 1977 } 1978 1979 status = rte_swx_ctl_pipeline_regarray_write(p, name, idx, value); 1980 if (status) { 1981 snprintf(out, out_size, "Command failed.\n"); 1982 return; 1983 } 1984 1985 snprintf(out, out_size, "0x%" PRIx64 "\n", value); 1986 return; 1987 } 1988 1989 /* table. */ 1990 if (!strcmp(tokens[6], "table")) { 1991 struct rte_swx_table_entry *entry; 1992 char *table_name; 1993 1994 if (n_tokens < 10) { 1995 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 1996 return; 1997 } 1998 1999 table_name = tokens[7]; 2000 2001 if (strcmp(tokens[8], "match")) { 2002 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "match"); 2003 return; 2004 } 2005 2006 entry = parse_table_entry(ctl, table_name, &tokens[8], n_tokens - 8); 2007 if (!entry) { 2008 snprintf(out, out_size, "Invalid match tokens.\n"); 2009 return; 2010 } 2011 2012 status = rte_swx_ctl_pipeline_regarray_write_with_key(p, 2013 name, 2014 table_name, 2015 entry->key, 2016 value); 2017 table_entry_free(entry); 2018 if (status) { 2019 snprintf(out, out_size, "Command failed.\n"); 2020 return; 2021 } 2022 2023 return; 2024 } 2025 2026 /* anything else. */ 2027 snprintf(out, out_size, "Invalid token %s\n.", tokens[6]); 2028 return; 2029 } 2030 2031 static const char cmd_pipeline_meter_profile_add_help[] = 2032 "pipeline <pipeline_name> meter profile <profile_name> add " 2033 "cir <cir> pir <pir> cbs <cbs> pbs <pbs>\n"; 2034 2035 static void 2036 cmd_pipeline_meter_profile_add(char **tokens, 2037 uint32_t n_tokens, 2038 char *out, 2039 size_t out_size, 2040 void *obj __rte_unused) 2041 { 2042 struct rte_meter_trtcm_params params; 2043 struct rte_swx_pipeline *p; 2044 const char *profile_name; 2045 int status; 2046 2047 if (n_tokens != 14) { 2048 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 2049 return; 2050 } 2051 2052 p = rte_swx_pipeline_find(tokens[1]); 2053 if (!p) { 2054 snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name"); 2055 return; 2056 } 2057 2058 if (strcmp(tokens[2], "meter")) { 2059 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "meter"); 2060 return; 2061 } 2062 2063 if (strcmp(tokens[3], "profile")) { 2064 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "profile"); 2065 return; 2066 } 2067 2068 profile_name = tokens[4]; 2069 2070 if (strcmp(tokens[5], "add")) { 2071 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "add"); 2072 return; 2073 } 2074 2075 if (strcmp(tokens[6], "cir")) { 2076 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "cir"); 2077 return; 2078 } 2079 2080 if (parser_read_uint64(¶ms.cir, tokens[7])) { 2081 snprintf(out, out_size, MSG_ARG_INVALID, "cir"); 2082 return; 2083 } 2084 2085 if (strcmp(tokens[8], "pir")) { 2086 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pir"); 2087 return; 2088 } 2089 2090 if (parser_read_uint64(¶ms.pir, tokens[9])) { 2091 snprintf(out, out_size, MSG_ARG_INVALID, "pir"); 2092 return; 2093 } 2094 2095 if (strcmp(tokens[10], "cbs")) { 2096 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "cbs"); 2097 return; 2098 } 2099 2100 if (parser_read_uint64(¶ms.cbs, tokens[11])) { 2101 snprintf(out, out_size, MSG_ARG_INVALID, "cbs"); 2102 return; 2103 } 2104 2105 if (strcmp(tokens[12], "pbs")) { 2106 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pbs"); 2107 return; 2108 } 2109 2110 if (parser_read_uint64(¶ms.pbs, tokens[13])) { 2111 snprintf(out, out_size, MSG_ARG_INVALID, "pbs"); 2112 return; 2113 } 2114 2115 status = rte_swx_ctl_meter_profile_add(p, profile_name, ¶ms); 2116 if (status) { 2117 snprintf(out, out_size, "Command failed.\n"); 2118 return; 2119 } 2120 } 2121 2122 static const char cmd_pipeline_meter_profile_delete_help[] = 2123 "pipeline <pipeline_name> meter profile <profile_name> delete\n"; 2124 2125 static void 2126 cmd_pipeline_meter_profile_delete(char **tokens, 2127 uint32_t n_tokens, 2128 char *out, 2129 size_t out_size, 2130 void *obj __rte_unused) 2131 { 2132 struct rte_swx_pipeline *p; 2133 const char *profile_name; 2134 int status; 2135 2136 if (n_tokens != 6) { 2137 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 2138 return; 2139 } 2140 2141 p = rte_swx_pipeline_find(tokens[1]); 2142 if (!p) { 2143 snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name"); 2144 return; 2145 } 2146 2147 if (strcmp(tokens[2], "meter")) { 2148 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "meter"); 2149 return; 2150 } 2151 2152 if (strcmp(tokens[3], "profile")) { 2153 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "profile"); 2154 return; 2155 } 2156 2157 profile_name = tokens[4]; 2158 2159 if (strcmp(tokens[5], "delete")) { 2160 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "delete"); 2161 return; 2162 } 2163 2164 status = rte_swx_ctl_meter_profile_delete(p, profile_name); 2165 if (status) { 2166 snprintf(out, out_size, "Command failed.\n"); 2167 return; 2168 } 2169 } 2170 2171 static const char cmd_pipeline_meter_reset_help[] = 2172 "pipeline <pipeline_name> meter <meter_array_name> reset\n" 2173 "index from <index0> to <index1>\n" 2174 " | table <table_name> match <field0> ...\n"; 2175 2176 static void 2177 cmd_pipeline_meter_reset(char **tokens, 2178 uint32_t n_tokens, 2179 char *out, 2180 size_t out_size, 2181 void *obj __rte_unused) 2182 { 2183 struct rte_swx_pipeline *p; 2184 struct rte_swx_ctl_pipeline *ctl; 2185 const char *pipeline_name, *name; 2186 2187 if (n_tokens < 6) { 2188 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 2189 return; 2190 } 2191 2192 pipeline_name = tokens[1]; 2193 p = rte_swx_pipeline_find(pipeline_name); 2194 ctl = rte_swx_ctl_pipeline_find(pipeline_name); 2195 if (!p || !ctl) { 2196 snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name"); 2197 return; 2198 } 2199 2200 if (strcmp(tokens[2], "meter")) { 2201 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "meter"); 2202 return; 2203 } 2204 2205 name = tokens[3]; 2206 2207 if (strcmp(tokens[4], "reset")) { 2208 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "reset"); 2209 return; 2210 } 2211 2212 /* index. */ 2213 if (!strcmp(tokens[5], "index")) { 2214 uint32_t idx0 = 0, idx1 = 0; 2215 2216 if (n_tokens != 10) { 2217 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 2218 return; 2219 } 2220 2221 if (strcmp(tokens[6], "from")) { 2222 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "from"); 2223 return; 2224 } 2225 2226 if (parser_read_uint32(&idx0, tokens[7])) { 2227 snprintf(out, out_size, MSG_ARG_INVALID, "index0"); 2228 return; 2229 } 2230 2231 if (strcmp(tokens[8], "to")) { 2232 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "to"); 2233 return; 2234 } 2235 2236 if (parser_read_uint32(&idx1, tokens[9]) || (idx1 < idx0)) { 2237 snprintf(out, out_size, MSG_ARG_INVALID, "index1"); 2238 return; 2239 } 2240 2241 for ( ; idx0 <= idx1; idx0++) { 2242 int status; 2243 2244 status = rte_swx_ctl_meter_reset(p, name, idx0); 2245 if (status) { 2246 snprintf(out, out_size, "Command failed for index %u.\n", idx0); 2247 return; 2248 } 2249 } 2250 2251 return; 2252 } 2253 2254 /* table. */ 2255 if (!strcmp(tokens[5], "table")) { 2256 struct rte_swx_table_entry *entry; 2257 char *table_name; 2258 int status; 2259 2260 if (n_tokens < 9) { 2261 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 2262 return; 2263 } 2264 2265 table_name = tokens[6]; 2266 2267 if (strcmp(tokens[7], "match")) { 2268 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "match"); 2269 return; 2270 } 2271 2272 entry = parse_table_entry(ctl, table_name, &tokens[7], n_tokens - 7); 2273 if (!entry) { 2274 snprintf(out, out_size, "Invalid match tokens.\n"); 2275 return; 2276 } 2277 2278 status = rte_swx_ctl_meter_reset_with_key(p, name, table_name, entry->key); 2279 table_entry_free(entry); 2280 if (status) { 2281 snprintf(out, out_size, "Command failed.\n"); 2282 return; 2283 } 2284 2285 return; 2286 } 2287 2288 /* anything else. */ 2289 snprintf(out, out_size, "Invalid token %s\n.", tokens[5]); 2290 return; 2291 } 2292 2293 static const char cmd_pipeline_meter_set_help[] = 2294 "pipeline <pipeline_name> meter <meter_array_name> set profile <profile_name>\n" 2295 "index from <index0> to <index1>\n" 2296 " | table <table_name> match <field0> ...\n"; 2297 2298 static void 2299 cmd_pipeline_meter_set(char **tokens, 2300 uint32_t n_tokens, 2301 char *out, 2302 size_t out_size, 2303 void *obj __rte_unused) 2304 { 2305 struct rte_swx_pipeline *p; 2306 struct rte_swx_ctl_pipeline *ctl; 2307 const char *pipeline_name, *name, *profile_name; 2308 2309 if (n_tokens < 8) { 2310 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 2311 return; 2312 } 2313 2314 pipeline_name = tokens[1]; 2315 p = rte_swx_pipeline_find(pipeline_name); 2316 ctl = rte_swx_ctl_pipeline_find(pipeline_name); 2317 if (!p || !ctl) { 2318 snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name"); 2319 return; 2320 } 2321 2322 if (strcmp(tokens[2], "meter")) { 2323 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "meter"); 2324 return; 2325 } 2326 2327 name = tokens[3]; 2328 2329 if (strcmp(tokens[4], "set")) { 2330 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "set"); 2331 return; 2332 } 2333 2334 if (strcmp(tokens[5], "profile")) { 2335 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "profile"); 2336 return; 2337 } 2338 2339 profile_name = tokens[6]; 2340 2341 /* index. */ 2342 if (!strcmp(tokens[7], "index")) { 2343 uint32_t idx0 = 0, idx1 = 0; 2344 2345 if (n_tokens != 12) { 2346 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 2347 return; 2348 } 2349 2350 if (strcmp(tokens[8], "from")) { 2351 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "from"); 2352 return; 2353 } 2354 2355 if (parser_read_uint32(&idx0, tokens[9])) { 2356 snprintf(out, out_size, MSG_ARG_INVALID, "index0"); 2357 return; 2358 } 2359 2360 if (strcmp(tokens[10], "to")) { 2361 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "to"); 2362 return; 2363 } 2364 2365 if (parser_read_uint32(&idx1, tokens[11]) || (idx1 < idx0)) { 2366 snprintf(out, out_size, MSG_ARG_INVALID, "index1"); 2367 return; 2368 } 2369 2370 for ( ; idx0 <= idx1; idx0++) { 2371 int status; 2372 2373 status = rte_swx_ctl_meter_set(p, name, idx0, profile_name); 2374 if (status) { 2375 snprintf(out, out_size, "Command failed for index %u.\n", idx0); 2376 return; 2377 } 2378 } 2379 2380 return; 2381 } 2382 2383 /* table. */ 2384 if (!strcmp(tokens[7], "table")) { 2385 struct rte_swx_table_entry *entry; 2386 char *table_name; 2387 int status; 2388 2389 if (n_tokens < 11) { 2390 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 2391 return; 2392 } 2393 2394 table_name = tokens[8]; 2395 2396 if (strcmp(tokens[9], "match")) { 2397 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "match"); 2398 return; 2399 } 2400 2401 entry = parse_table_entry(ctl, table_name, &tokens[9], n_tokens - 9); 2402 if (!entry) { 2403 snprintf(out, out_size, "Invalid match tokens.\n"); 2404 return; 2405 } 2406 2407 status = rte_swx_ctl_meter_set_with_key(p, 2408 name, 2409 table_name, 2410 entry->key, 2411 profile_name); 2412 table_entry_free(entry); 2413 if (status) { 2414 snprintf(out, out_size, "Command failed.\n"); 2415 return; 2416 } 2417 2418 return; 2419 } 2420 2421 /* anything else. */ 2422 snprintf(out, out_size, "Invalid token %s\n.", tokens[7]); 2423 return; 2424 } 2425 2426 static const char cmd_pipeline_meter_stats_help[] = 2427 "pipeline <pipeline_name> meter <meter_array_name> stats\n" 2428 "index from <index0> to <index1>\n" 2429 " | table <table_name> match <field0> ...\n"; 2430 2431 static void 2432 cmd_pipeline_meter_stats(char **tokens, 2433 uint32_t n_tokens, 2434 char *out, 2435 size_t out_size, 2436 void *obj __rte_unused) 2437 { 2438 struct rte_swx_ctl_meter_stats stats; 2439 struct rte_swx_pipeline *p; 2440 struct rte_swx_ctl_pipeline *ctl; 2441 const char *pipeline_name, *name; 2442 2443 if (n_tokens < 6) { 2444 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 2445 return; 2446 } 2447 2448 pipeline_name = tokens[1]; 2449 p = rte_swx_pipeline_find(pipeline_name); 2450 ctl = rte_swx_ctl_pipeline_find(pipeline_name); 2451 if (!p || !ctl) { 2452 snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name"); 2453 return; 2454 } 2455 2456 if (strcmp(tokens[2], "meter")) { 2457 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "meter"); 2458 return; 2459 } 2460 2461 name = tokens[3]; 2462 2463 if (strcmp(tokens[4], "stats")) { 2464 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "stats"); 2465 return; 2466 } 2467 2468 /* index. */ 2469 if (!strcmp(tokens[5], "index")) { 2470 uint32_t idx0 = 0, idx1 = 0; 2471 2472 if (n_tokens != 10) { 2473 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 2474 return; 2475 } 2476 2477 if (strcmp(tokens[6], "from")) { 2478 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "from"); 2479 return; 2480 } 2481 2482 if (parser_read_uint32(&idx0, tokens[7])) { 2483 snprintf(out, out_size, MSG_ARG_INVALID, "index0"); 2484 return; 2485 } 2486 2487 if (strcmp(tokens[8], "to")) { 2488 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "to"); 2489 return; 2490 } 2491 2492 if (parser_read_uint32(&idx1, tokens[9]) || (idx1 < idx0)) { 2493 snprintf(out, out_size, MSG_ARG_INVALID, "index1"); 2494 return; 2495 } 2496 2497 /* Table header. */ 2498 snprintf(out, out_size, "+-%7s-+-%16s-+-%16s-+-%16s-+-%16s-+-%16s-+-%16s-+\n", 2499 "-------", 2500 "----------------", "----------------", "----------------", 2501 "----------------", "----------------", "----------------"); 2502 out_size -= strlen(out); 2503 out += strlen(out); 2504 2505 snprintf(out, out_size, "| %4s | %16s | %16s | %16s | %16s | %16s | %16s |\n", 2506 "METER #", 2507 "GREEN (packets)", "YELLOW (packets)", "RED (packets)", 2508 "GREEN (bytes)", "YELLOW (bytes)", "RED (bytes)"); 2509 out_size -= strlen(out); 2510 out += strlen(out); 2511 2512 snprintf(out, out_size, "+-%7s-+-%16s-+-%16s-+-%16s-+-%16s-+-%16s-+-%16s-+\n", 2513 "-------", 2514 "----------------", "----------------", "----------------", 2515 "----------------", "----------------", "----------------"); 2516 out_size -= strlen(out); 2517 out += strlen(out); 2518 2519 /* Table rows. */ 2520 for ( ; idx0 <= idx1; idx0++) { 2521 int status; 2522 2523 status = rte_swx_ctl_meter_stats_read(p, name, idx0, &stats); 2524 if (status) { 2525 snprintf(out, out_size, "Meter stats error at index %u.\n", idx0); 2526 out_size -= strlen(out); 2527 out += strlen(out); 2528 return; 2529 } 2530 2531 snprintf(out, out_size, "| %7d | %16" PRIx64 " | %16" PRIx64 " | %16" PRIx64 2532 " | %16" PRIx64 " | %16" PRIx64 " | %16" PRIx64 " |\n", 2533 idx0, 2534 stats.n_pkts[RTE_COLOR_GREEN], 2535 stats.n_pkts[RTE_COLOR_YELLOW], 2536 stats.n_pkts[RTE_COLOR_RED], 2537 stats.n_bytes[RTE_COLOR_GREEN], 2538 stats.n_bytes[RTE_COLOR_YELLOW], 2539 stats.n_bytes[RTE_COLOR_RED]); 2540 out_size -= strlen(out); 2541 out += strlen(out); 2542 } 2543 2544 return; 2545 } 2546 2547 /* table. */ 2548 if (!strcmp(tokens[5], "table")) { 2549 struct rte_swx_table_entry *entry; 2550 char *table_name; 2551 int status; 2552 2553 if (n_tokens < 9) { 2554 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 2555 return; 2556 } 2557 2558 table_name = tokens[6]; 2559 2560 if (strcmp(tokens[7], "match")) { 2561 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "match"); 2562 return; 2563 } 2564 2565 entry = parse_table_entry(ctl, table_name, &tokens[7], n_tokens - 7); 2566 if (!entry) { 2567 snprintf(out, out_size, "Invalid match tokens.\n"); 2568 return; 2569 } 2570 2571 status = rte_swx_ctl_meter_stats_read_with_key(p, 2572 name, 2573 table_name, 2574 entry->key, 2575 &stats); 2576 table_entry_free(entry); 2577 if (status) { 2578 snprintf(out, out_size, "Command failed.\n"); 2579 return; 2580 } 2581 2582 /* Table header. */ 2583 snprintf(out, out_size, "+-%7s-+-%16s-+-%16s-+-%16s-+-%16s-+-%16s-+-%16s-+\n", 2584 "-------", 2585 "----------------", "----------------", "----------------", 2586 "----------------", "----------------", "----------------"); 2587 out_size -= strlen(out); 2588 out += strlen(out); 2589 2590 snprintf(out, out_size, "| %4s | %16s | %16s | %16s | %16s | %16s | %16s |\n", 2591 "METER #", 2592 "GREEN (packets)", "YELLOW (packets)", "RED (packets)", 2593 "GREEN (bytes)", "YELLOW (bytes)", "RED (bytes)"); 2594 out_size -= strlen(out); 2595 out += strlen(out); 2596 2597 snprintf(out, out_size, "+-%7s-+-%16s-+-%16s-+-%16s-+-%16s-+-%16s-+-%16s-+\n", 2598 "-------", 2599 "----------------", "----------------", "----------------", 2600 "----------------", "----------------", "----------------"); 2601 out_size -= strlen(out); 2602 out += strlen(out); 2603 2604 /* Table row. */ 2605 snprintf(out, out_size, "| %7d | %16" PRIx64 " | %16" PRIx64 " | %16" PRIx64 2606 " | %16" PRIx64 " | %16" PRIx64 " | %16" PRIx64 " |\n", 2607 0, 2608 stats.n_pkts[RTE_COLOR_GREEN], 2609 stats.n_pkts[RTE_COLOR_YELLOW], 2610 stats.n_pkts[RTE_COLOR_RED], 2611 stats.n_bytes[RTE_COLOR_GREEN], 2612 stats.n_bytes[RTE_COLOR_YELLOW], 2613 stats.n_bytes[RTE_COLOR_RED]); 2614 out_size -= strlen(out); 2615 out += strlen(out); 2616 2617 return; 2618 } 2619 2620 /* anything else. */ 2621 snprintf(out, out_size, "Invalid token %s\n.", tokens[5]); 2622 return; 2623 } 2624 2625 static const char cmd_pipeline_rss_help[] = 2626 "pipeline <pipeline_name> rss <rss_obj_name> key <key_byte0> ...\n"; 2627 2628 static void 2629 cmd_pipeline_rss(char **tokens, 2630 uint32_t n_tokens, 2631 char *out, 2632 size_t out_size, 2633 void *obj __rte_unused) 2634 { 2635 uint8_t rss_key[CMD_MAX_TOKENS]; 2636 struct rte_swx_pipeline *p; 2637 const char *rss_obj_name; 2638 uint32_t rss_key_size, i; 2639 int status; 2640 2641 if (n_tokens < 6) { 2642 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 2643 return; 2644 } 2645 2646 p = rte_swx_pipeline_find(tokens[1]); 2647 if (!p) { 2648 snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name"); 2649 return; 2650 } 2651 2652 if (strcmp(tokens[2], "rss")) { 2653 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rss"); 2654 return; 2655 } 2656 2657 rss_obj_name = tokens[3]; 2658 2659 if (strcmp(tokens[4], "key")) { 2660 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "key"); 2661 return; 2662 } 2663 2664 tokens += 5; 2665 n_tokens -= 5; 2666 rss_key_size = n_tokens; 2667 2668 for (i = 0; i < rss_key_size; i++) { 2669 uint32_t key_byte; 2670 2671 if (parser_read_uint32(&key_byte, tokens[i]) || (key_byte >= UINT8_MAX)) { 2672 snprintf(out, out_size, MSG_ARG_INVALID, "key byte"); 2673 return; 2674 } 2675 2676 rss_key[i] = (uint8_t)key_byte; 2677 } 2678 2679 status = rte_swx_ctl_pipeline_rss_key_write(p, rss_obj_name, rss_key_size, rss_key); 2680 if (status) { 2681 snprintf(out, out_size, "Command failed.\n"); 2682 return; 2683 } 2684 } 2685 2686 static const char cmd_pipeline_stats_help[] = 2687 "pipeline <pipeline_name> stats\n"; 2688 2689 static void 2690 cmd_pipeline_stats(char **tokens, 2691 uint32_t n_tokens, 2692 char *out, 2693 size_t out_size, 2694 void *obj __rte_unused) 2695 { 2696 struct rte_swx_ctl_pipeline_info info; 2697 struct rte_swx_pipeline *p; 2698 uint32_t i; 2699 int status; 2700 2701 if (n_tokens != 3) { 2702 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 2703 return; 2704 } 2705 2706 p = rte_swx_pipeline_find(tokens[1]); 2707 if (!p) { 2708 snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name"); 2709 return; 2710 } 2711 2712 if (strcmp(tokens[2], "stats")) { 2713 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "stats"); 2714 return; 2715 } 2716 2717 status = rte_swx_ctl_pipeline_info_get(p, &info); 2718 if (status) { 2719 snprintf(out, out_size, "Pipeline info get error."); 2720 return; 2721 } 2722 2723 snprintf(out, out_size, "Input ports:\n"); 2724 out_size -= strlen(out); 2725 out += strlen(out); 2726 2727 for (i = 0; i < info.n_ports_in; i++) { 2728 struct rte_swx_port_in_stats stats; 2729 2730 rte_swx_ctl_pipeline_port_in_stats_read(p, i, &stats); 2731 2732 snprintf(out, out_size, "\tPort %u:" 2733 " packets %" PRIu64 2734 " bytes %" PRIu64 2735 " empty %" PRIu64 "\n", 2736 i, stats.n_pkts, stats.n_bytes, stats.n_empty); 2737 out_size -= strlen(out); 2738 out += strlen(out); 2739 } 2740 2741 snprintf(out, out_size, "\nOutput ports:\n"); 2742 out_size -= strlen(out); 2743 out += strlen(out); 2744 2745 for (i = 0; i < info.n_ports_out; i++) { 2746 struct rte_swx_port_out_stats stats; 2747 2748 rte_swx_ctl_pipeline_port_out_stats_read(p, i, &stats); 2749 2750 if (i != info.n_ports_out - 1) 2751 snprintf(out, out_size, "\tPort %u:", i); 2752 else 2753 snprintf(out, out_size, "\tDROP:"); 2754 2755 out_size -= strlen(out); 2756 out += strlen(out); 2757 2758 snprintf(out, 2759 out_size, 2760 " packets %" PRIu64 2761 " bytes %" PRIu64 2762 " packets dropped %" PRIu64 2763 " bytes dropped %" PRIu64 2764 " clone %" PRIu64 2765 " clonerr %" PRIu64 "\n", 2766 stats.n_pkts, 2767 stats.n_bytes, 2768 stats.n_pkts_drop, 2769 stats.n_bytes_drop, 2770 stats.n_pkts_clone, 2771 stats.n_pkts_clone_err); 2772 2773 out_size -= strlen(out); 2774 out += strlen(out); 2775 } 2776 2777 snprintf(out, out_size, "\nTables:\n"); 2778 out_size -= strlen(out); 2779 out += strlen(out); 2780 2781 for (i = 0; i < info.n_tables; i++) { 2782 struct rte_swx_ctl_table_info table_info; 2783 uint64_t n_pkts_action[info.n_actions]; 2784 struct rte_swx_table_stats stats = { 2785 .n_pkts_hit = 0, 2786 .n_pkts_miss = 0, 2787 .n_pkts_action = n_pkts_action, 2788 }; 2789 uint32_t j; 2790 2791 status = rte_swx_ctl_table_info_get(p, i, &table_info); 2792 if (status) { 2793 snprintf(out, out_size, "Table info get error."); 2794 return; 2795 } 2796 2797 status = rte_swx_ctl_pipeline_table_stats_read(p, table_info.name, &stats); 2798 if (status) { 2799 snprintf(out, out_size, "Table stats read error."); 2800 return; 2801 } 2802 2803 snprintf(out, out_size, "\tTable %s:\n" 2804 "\t\tHit (packets): %" PRIu64 "\n" 2805 "\t\tMiss (packets): %" PRIu64 "\n", 2806 table_info.name, 2807 stats.n_pkts_hit, 2808 stats.n_pkts_miss); 2809 out_size -= strlen(out); 2810 out += strlen(out); 2811 2812 for (j = 0; j < info.n_actions; j++) { 2813 struct rte_swx_ctl_action_info action_info; 2814 2815 status = rte_swx_ctl_action_info_get(p, j, &action_info); 2816 if (status) { 2817 snprintf(out, out_size, "Action info get error."); 2818 return; 2819 } 2820 2821 snprintf(out, out_size, "\t\tAction %s (packets): %" PRIu64 "\n", 2822 action_info.name, 2823 stats.n_pkts_action[j]); 2824 out_size -= strlen(out); 2825 out += strlen(out); 2826 } 2827 } 2828 2829 snprintf(out, out_size, "\nLearner tables:\n"); 2830 out_size -= strlen(out); 2831 out += strlen(out); 2832 2833 for (i = 0; i < info.n_learners; i++) { 2834 struct rte_swx_ctl_learner_info learner_info; 2835 uint64_t n_pkts_action[info.n_actions]; 2836 struct rte_swx_learner_stats stats = { 2837 .n_pkts_hit = 0, 2838 .n_pkts_miss = 0, 2839 .n_pkts_action = n_pkts_action, 2840 }; 2841 uint32_t j; 2842 2843 status = rte_swx_ctl_learner_info_get(p, i, &learner_info); 2844 if (status) { 2845 snprintf(out, out_size, "Learner table info get error."); 2846 return; 2847 } 2848 2849 status = rte_swx_ctl_pipeline_learner_stats_read(p, learner_info.name, &stats); 2850 if (status) { 2851 snprintf(out, out_size, "Learner table stats read error."); 2852 return; 2853 } 2854 2855 snprintf(out, out_size, "\tLearner table %s:\n" 2856 "\t\tHit (packets): %" PRIu64 "\n" 2857 "\t\tMiss (packets): %" PRIu64 "\n" 2858 "\t\tLearn OK (packets): %" PRIu64 "\n" 2859 "\t\tLearn error (packets): %" PRIu64 "\n" 2860 "\t\tRearm (packets): %" PRIu64 "\n" 2861 "\t\tForget (packets): %" PRIu64 "\n", 2862 learner_info.name, 2863 stats.n_pkts_hit, 2864 stats.n_pkts_miss, 2865 stats.n_pkts_learn_ok, 2866 stats.n_pkts_learn_err, 2867 stats.n_pkts_rearm, 2868 stats.n_pkts_forget); 2869 out_size -= strlen(out); 2870 out += strlen(out); 2871 2872 for (j = 0; j < info.n_actions; j++) { 2873 struct rte_swx_ctl_action_info action_info; 2874 2875 status = rte_swx_ctl_action_info_get(p, j, &action_info); 2876 if (status) { 2877 snprintf(out, out_size, "Action info get error."); 2878 return; 2879 } 2880 2881 snprintf(out, out_size, "\t\tAction %s (packets): %" PRIu64 "\n", 2882 action_info.name, 2883 stats.n_pkts_action[j]); 2884 out_size -= strlen(out); 2885 out += strlen(out); 2886 } 2887 } 2888 } 2889 2890 static const char cmd_pipeline_mirror_session_help[] = 2891 "pipeline <pipeline_name> mirror session <session_id> port <port_id> clone fast | slow " 2892 "truncate <truncation_length>\n"; 2893 2894 static void 2895 cmd_pipeline_mirror_session(char **tokens, 2896 uint32_t n_tokens, 2897 char *out, 2898 size_t out_size, 2899 void *obj __rte_unused) 2900 { 2901 struct rte_swx_pipeline_mirroring_session_params params; 2902 struct rte_swx_pipeline *p; 2903 uint32_t session_id = 0; 2904 int status; 2905 2906 if (n_tokens != 11) { 2907 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 2908 return; 2909 } 2910 2911 if (strcmp(tokens[0], "pipeline")) { 2912 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pipeline"); 2913 return; 2914 } 2915 2916 p = rte_swx_pipeline_find(tokens[1]); 2917 if (!p) { 2918 snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name"); 2919 return; 2920 } 2921 2922 if (strcmp(tokens[2], "mirror")) { 2923 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "mirror"); 2924 return; 2925 } 2926 2927 if (strcmp(tokens[3], "session")) { 2928 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "session"); 2929 return; 2930 } 2931 2932 if (parser_read_uint32(&session_id, tokens[4])) { 2933 snprintf(out, out_size, MSG_ARG_INVALID, "session_id"); 2934 return; 2935 } 2936 2937 if (strcmp(tokens[5], "port")) { 2938 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port"); 2939 return; 2940 } 2941 2942 if (parser_read_uint32(¶ms.port_id, tokens[6])) { 2943 snprintf(out, out_size, MSG_ARG_INVALID, "port_id"); 2944 return; 2945 } 2946 2947 if (strcmp(tokens[7], "clone")) { 2948 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "clone"); 2949 return; 2950 } 2951 2952 if (!strcmp(tokens[8], "fast")) 2953 params.fast_clone = 1; 2954 else if (!strcmp(tokens[8], "slow")) 2955 params.fast_clone = 0; 2956 else { 2957 snprintf(out, out_size, MSG_ARG_INVALID, "clone"); 2958 return; 2959 } 2960 2961 if (strcmp(tokens[9], "truncate")) { 2962 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "truncate"); 2963 return; 2964 } 2965 2966 if (parser_read_uint32(¶ms.truncation_length, tokens[10])) { 2967 snprintf(out, out_size, MSG_ARG_INVALID, "truncation_length"); 2968 return; 2969 } 2970 2971 status = rte_swx_ctl_pipeline_mirroring_session_set(p, session_id, ¶ms); 2972 if (status) { 2973 snprintf(out, out_size, "Command failed!\n"); 2974 return; 2975 } 2976 } 2977 2978 static const char cmd_ipsec_create_help[] = 2979 "ipsec <ipsec_instance_name> create " 2980 "in <ring_in_name> out <ring_out_name> " 2981 "cryptodev <crypto_dev_name> cryptoq <crypto_dev_queue_pair_id> " 2982 "bsz <ring_rd_bsz> <ring_wr_bsz> <crypto_wr_bsz> <crypto_rd_bsz> " 2983 "samax <n_sa_max> " 2984 "numa <numa_node>\n"; 2985 2986 static void 2987 cmd_ipsec_create(char **tokens, 2988 uint32_t n_tokens, 2989 char *out, 2990 size_t out_size, 2991 void *obj __rte_unused) 2992 { 2993 struct rte_swx_ipsec_params p; 2994 struct rte_swx_ipsec *ipsec; 2995 char *ipsec_instance_name; 2996 uint32_t numa_node; 2997 int status; 2998 2999 if (n_tokens != 20) { 3000 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 3001 return; 3002 } 3003 3004 ipsec_instance_name = tokens[1]; 3005 3006 if (strcmp(tokens[2], "create")) { 3007 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "create"); 3008 return; 3009 } 3010 3011 if (strcmp(tokens[3], "in")) { 3012 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "in"); 3013 return; 3014 } 3015 3016 p.ring_in_name = tokens[4]; 3017 3018 if (strcmp(tokens[5], "out")) { 3019 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "out"); 3020 return; 3021 } 3022 3023 p.ring_out_name = tokens[6]; 3024 3025 if (strcmp(tokens[7], "cryptodev")) { 3026 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "cryptodev"); 3027 return; 3028 } 3029 3030 p.crypto_dev_name = tokens[8]; 3031 3032 if (strcmp(tokens[9], "cryptoq")) { 3033 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "cryptoq"); 3034 return; 3035 } 3036 3037 if (parser_read_uint32(&p.crypto_dev_queue_pair_id, tokens[10])) { 3038 snprintf(out, out_size, MSG_ARG_INVALID, "crypto_dev_queue_pair_id"); 3039 return; 3040 } 3041 3042 if (strcmp(tokens[11], "bsz")) { 3043 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "bsz"); 3044 return; 3045 } 3046 3047 if (parser_read_uint32(&p.bsz.ring_rd, tokens[12])) { 3048 snprintf(out, out_size, MSG_ARG_INVALID, "ring_rd_bsz"); 3049 return; 3050 } 3051 3052 if (parser_read_uint32(&p.bsz.ring_wr, tokens[13])) { 3053 snprintf(out, out_size, MSG_ARG_INVALID, "ring_wr_bsz"); 3054 return; 3055 } 3056 3057 if (parser_read_uint32(&p.bsz.crypto_wr, tokens[14])) { 3058 snprintf(out, out_size, MSG_ARG_INVALID, "crypto_wr_bsz"); 3059 return; 3060 } 3061 3062 if (parser_read_uint32(&p.bsz.crypto_rd, tokens[15])) { 3063 snprintf(out, out_size, MSG_ARG_INVALID, "crypto_rd_bsz"); 3064 return; 3065 } 3066 3067 if (strcmp(tokens[16], "samax")) { 3068 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "samax"); 3069 return; 3070 } 3071 3072 if (parser_read_uint32(&p.n_sa_max, tokens[17])) { 3073 snprintf(out, out_size, MSG_ARG_INVALID, "n_sa_max"); 3074 return; 3075 } 3076 3077 if (strcmp(tokens[18], "numa")) { 3078 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "numa"); 3079 return; 3080 } 3081 3082 if (parser_read_uint32(&numa_node, tokens[19])) { 3083 snprintf(out, out_size, MSG_ARG_INVALID, "numa_node"); 3084 return; 3085 } 3086 3087 status = rte_swx_ipsec_create(&ipsec, 3088 ipsec_instance_name, 3089 &p, 3090 (int)numa_node); 3091 if (status) 3092 snprintf(out, out_size, "IPsec instance creation failed (%d).\n", status); 3093 } 3094 3095 static const char cmd_ipsec_sa_add_help[] = 3096 "ipsec <ipsec_instance_name> sa add <file_name>\n"; 3097 3098 static void 3099 cmd_ipsec_sa_add(char **tokens, 3100 uint32_t n_tokens, 3101 char *out, 3102 size_t out_size, 3103 void *obj __rte_unused) 3104 { 3105 struct rte_swx_ipsec *ipsec; 3106 char *ipsec_instance_name, *file_name, *line = NULL; 3107 FILE *file = NULL; 3108 uint32_t line_id = 0; 3109 3110 if (n_tokens != 5) { 3111 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 3112 return; 3113 } 3114 3115 ipsec_instance_name = tokens[1]; 3116 ipsec = rte_swx_ipsec_find(ipsec_instance_name); 3117 if (!ipsec) { 3118 snprintf(out, out_size, MSG_ARG_INVALID, "ipsec_instance_name"); 3119 goto free; 3120 } 3121 3122 if (strcmp(tokens[2], "sa")) { 3123 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "sa"); 3124 goto free; 3125 } 3126 3127 if (strcmp(tokens[3], "add")) { 3128 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "add"); 3129 goto free; 3130 } 3131 3132 file_name = tokens[4]; 3133 file = fopen(file_name, "r"); 3134 if (!file) { 3135 snprintf(out, out_size, "Cannot open file %s.\n", file_name); 3136 goto free; 3137 } 3138 3139 /* Buffer allocation. */ 3140 line = malloc(MAX_LINE_SIZE); 3141 if (!line) { 3142 snprintf(out, out_size, MSG_OUT_OF_MEMORY); 3143 goto free; 3144 } 3145 3146 /* File read. */ 3147 for (line_id = 1; ; line_id++) { 3148 struct rte_swx_ipsec_sa_params *sa; 3149 const char *err_msg; 3150 uint32_t sa_id = 0; 3151 int is_blank_or_comment, status = 0; 3152 3153 if (fgets(line, MAX_LINE_SIZE, file) == NULL) 3154 break; 3155 3156 /* Read SA from file. */ 3157 sa = rte_swx_ipsec_sa_read(ipsec, line, &is_blank_or_comment, &err_msg); 3158 if (!sa) { 3159 if (is_blank_or_comment) 3160 continue; 3161 3162 snprintf(out, out_size, "Invalid SA in file \"%s\" at line %u: \"%s\"\n", 3163 file_name, line_id, err_msg); 3164 goto free; 3165 } 3166 3167 snprintf(out, out_size, "%s", line); 3168 out_size -= strlen(out); 3169 out += strlen(out); 3170 3171 /* Add the SA to the IPsec instance. Free the SA. */ 3172 status = rte_swx_ipsec_sa_add(ipsec, sa, &sa_id); 3173 if (status) 3174 snprintf(out, out_size, "\t: Error (%d)\n", status); 3175 else 3176 snprintf(out, out_size, "\t: OK (SA ID = %u)\n", sa_id); 3177 out_size -= strlen(out); 3178 out += strlen(out); 3179 3180 free(sa); 3181 if (status) 3182 goto free; 3183 } 3184 3185 free: 3186 if (file) 3187 fclose(file); 3188 free(line); 3189 } 3190 3191 static const char cmd_ipsec_sa_delete_help[] = 3192 "ipsec <ipsec_instance_name> sa delete <sa_id>\n"; 3193 3194 static void 3195 cmd_ipsec_sa_delete(char **tokens, 3196 uint32_t n_tokens, 3197 char *out, 3198 size_t out_size, 3199 void *obj __rte_unused) 3200 { 3201 struct rte_swx_ipsec *ipsec; 3202 char *ipsec_instance_name; 3203 uint32_t sa_id; 3204 3205 if (n_tokens != 5) { 3206 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 3207 return; 3208 } 3209 3210 ipsec_instance_name = tokens[1]; 3211 ipsec = rte_swx_ipsec_find(ipsec_instance_name); 3212 if (!ipsec) { 3213 snprintf(out, out_size, MSG_ARG_INVALID, "ipsec_instance_name"); 3214 return; 3215 } 3216 3217 if (strcmp(tokens[2], "sa")) { 3218 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "sa"); 3219 return; 3220 } 3221 3222 if (strcmp(tokens[3], "delete")) { 3223 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "delete"); 3224 return; 3225 } 3226 3227 if (parser_read_uint32(&sa_id, tokens[4])) { 3228 snprintf(out, out_size, MSG_ARG_INVALID, "sa_id"); 3229 return; 3230 } 3231 3232 rte_swx_ipsec_sa_delete(ipsec, sa_id); 3233 } 3234 3235 static const char cmd_pipeline_enable_help[] = 3236 "pipeline <pipeline_name> enable thread <thread_id>\n"; 3237 3238 static void 3239 cmd_pipeline_enable(char **tokens, 3240 uint32_t n_tokens, 3241 char *out, 3242 size_t out_size, 3243 void *obj __rte_unused) 3244 { 3245 char *pipeline_name; 3246 struct rte_swx_pipeline *p; 3247 uint32_t thread_id; 3248 int status; 3249 3250 if (n_tokens != 5) { 3251 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 3252 return; 3253 } 3254 3255 pipeline_name = tokens[1]; 3256 p = rte_swx_pipeline_find(pipeline_name); 3257 if (!p) { 3258 snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name"); 3259 return; 3260 } 3261 3262 if (strcmp(tokens[2], "enable") != 0) { 3263 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "enable"); 3264 return; 3265 } 3266 3267 if (strcmp(tokens[3], "thread") != 0) { 3268 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "thread"); 3269 return; 3270 } 3271 3272 if (parser_read_uint32(&thread_id, tokens[4]) != 0) { 3273 snprintf(out, out_size, MSG_ARG_INVALID, "thread_id"); 3274 return; 3275 } 3276 3277 status = pipeline_enable(p, thread_id); 3278 if (status) { 3279 snprintf(out, out_size, MSG_CMD_FAIL, "pipeline enable"); 3280 return; 3281 } 3282 } 3283 3284 static const char cmd_pipeline_disable_help[] = 3285 "pipeline <pipeline_name> disable\n"; 3286 3287 static void 3288 cmd_pipeline_disable(char **tokens, 3289 uint32_t n_tokens, 3290 char *out, 3291 size_t out_size, 3292 void *obj __rte_unused) 3293 { 3294 struct rte_swx_pipeline *p; 3295 char *pipeline_name; 3296 3297 if (n_tokens != 3) { 3298 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 3299 return; 3300 } 3301 3302 pipeline_name = tokens[1]; 3303 p = rte_swx_pipeline_find(pipeline_name); 3304 if (!p) { 3305 snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name"); 3306 return; 3307 } 3308 3309 if (strcmp(tokens[2], "disable") != 0) { 3310 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "disable"); 3311 return; 3312 } 3313 3314 pipeline_disable(p); 3315 } 3316 3317 static const char cmd_block_enable_help[] = 3318 "block type <block_type> instance <block_name> enable thread <thread_id>\n"; 3319 3320 static void 3321 cmd_block_enable(char **tokens, 3322 uint32_t n_tokens, 3323 char *out, 3324 size_t out_size, 3325 void *obj __rte_unused) 3326 { 3327 char *block_type, *block_name; 3328 block_run_f block_func = NULL; 3329 void *block = NULL; 3330 uint32_t thread_id; 3331 int status; 3332 3333 if (n_tokens != 8) { 3334 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 3335 return; 3336 } 3337 3338 if (strcmp(tokens[1], "type") != 0) { 3339 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "type"); 3340 return; 3341 } 3342 3343 block_type = tokens[2]; 3344 3345 if (strcmp(tokens[3], "instance") != 0) { 3346 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "instance"); 3347 return; 3348 } 3349 3350 block_name = tokens[4]; 3351 3352 if (strcmp(tokens[5], "enable") != 0) { 3353 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "enable"); 3354 return; 3355 } 3356 3357 if (strcmp(tokens[6], "thread") != 0) { 3358 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "thread"); 3359 return; 3360 } 3361 3362 if (parser_read_uint32(&thread_id, tokens[7]) != 0) { 3363 snprintf(out, out_size, MSG_ARG_INVALID, "thread_id"); 3364 return; 3365 } 3366 3367 if (!strcmp(block_type, "ipsec")) { 3368 struct rte_swx_ipsec *ipsec; 3369 3370 ipsec = rte_swx_ipsec_find(block_name); 3371 if (!ipsec) { 3372 snprintf(out, out_size, MSG_ARG_INVALID, "block_name"); 3373 return; 3374 } 3375 3376 block_func = (block_run_f)rte_swx_ipsec_run; 3377 block = (void *)ipsec; 3378 } else { 3379 snprintf(out, out_size, MSG_ARG_INVALID, "block_type"); 3380 return; 3381 } 3382 3383 status = block_enable(block_func, block, thread_id); 3384 if (status) { 3385 snprintf(out, out_size, MSG_CMD_FAIL, "block enable"); 3386 return; 3387 } 3388 } 3389 3390 static const char cmd_block_disable_help[] = 3391 "block type <block_type> instance <block_name> disable\n"; 3392 3393 static void 3394 cmd_block_disable(char **tokens, 3395 uint32_t n_tokens, 3396 char *out, 3397 size_t out_size, 3398 void *obj __rte_unused) 3399 { 3400 char *block_type, *block_name; 3401 void *block = NULL; 3402 3403 if (n_tokens != 6) { 3404 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 3405 return; 3406 } 3407 3408 if (strcmp(tokens[1], "type") != 0) { 3409 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "type"); 3410 return; 3411 } 3412 3413 block_type = tokens[2]; 3414 3415 if (strcmp(tokens[3], "instance") != 0) { 3416 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "instance"); 3417 return; 3418 } 3419 3420 block_name = tokens[4]; 3421 3422 if (strcmp(tokens[5], "disable") != 0) { 3423 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "disable"); 3424 return; 3425 } 3426 3427 if (!strcmp(block_type, "ipsec")) { 3428 struct rte_swx_ipsec *ipsec; 3429 3430 ipsec = rte_swx_ipsec_find(block_name); 3431 if (!ipsec) { 3432 snprintf(out, out_size, MSG_ARG_INVALID, "block_name"); 3433 return; 3434 } 3435 3436 block = (void *)ipsec; 3437 } else { 3438 snprintf(out, out_size, MSG_ARG_INVALID, "block_type"); 3439 return; 3440 } 3441 3442 block_disable(block); 3443 } 3444 3445 static void 3446 cmd_help(char **tokens, 3447 uint32_t n_tokens, 3448 char *out, 3449 size_t out_size, 3450 void *arg __rte_unused) 3451 { 3452 tokens++; 3453 n_tokens--; 3454 3455 if (n_tokens == 0) { 3456 snprintf(out, out_size, 3457 "Type 'help <command>' for command details.\n\n" 3458 "List of commands:\n" 3459 "\tmempool\n" 3460 "\tethdev\n" 3461 "\tethdev show\n" 3462 "\tring\n" 3463 "\tcryptodev\n" 3464 "\tpipeline codegen\n" 3465 "\tpipeline libbuild\n" 3466 "\tpipeline build\n" 3467 "\tpipeline table add\n" 3468 "\tpipeline table delete\n" 3469 "\tpipeline table default\n" 3470 "\tpipeline table show\n" 3471 "\tpipeline selector group add\n" 3472 "\tpipeline selector group delete\n" 3473 "\tpipeline selector group member add\n" 3474 "\tpipeline selector group member delete\n" 3475 "\tpipeline selector show\n" 3476 "\tpipeline learner default\n" 3477 "\tpipeline commit\n" 3478 "\tpipeline abort\n" 3479 "\tpipeline regrd\n" 3480 "\tpipeline regwr\n" 3481 "\tpipeline meter profile add\n" 3482 "\tpipeline meter profile delete\n" 3483 "\tpipeline meter reset\n" 3484 "\tpipeline meter set\n" 3485 "\tpipeline meter stats\n" 3486 "\tpipeline rss\n" 3487 "\tpipeline stats\n" 3488 "\tpipeline mirror session\n" 3489 "\tpipeline enable\n" 3490 "\tpipeline disable\n\n" 3491 "\tipsec create\n" 3492 "\tipsec sa add\n" 3493 "\tipsec sa delete\n" 3494 "\tblock enable\n" 3495 "\tblock disable\n" 3496 ); 3497 return; 3498 } 3499 3500 if (strcmp(tokens[0], "mempool") == 0) { 3501 snprintf(out, out_size, "\n%s\n", cmd_mempool_help); 3502 return; 3503 } 3504 3505 if (!strcmp(tokens[0], "ethdev")) { 3506 if (n_tokens == 1) { 3507 snprintf(out, out_size, "\n%s\n", cmd_ethdev_help); 3508 return; 3509 } 3510 3511 if (n_tokens == 2 && !strcmp(tokens[1], "show")) { 3512 snprintf(out, out_size, "\n%s\n", cmd_ethdev_show_help); 3513 return; 3514 } 3515 } 3516 3517 if (strcmp(tokens[0], "ring") == 0) { 3518 snprintf(out, out_size, "\n%s\n", cmd_ring_help); 3519 return; 3520 } 3521 3522 if (!strcmp(tokens[0], "cryptodev")) { 3523 snprintf(out, out_size, "\n%s\n", cmd_cryptodev_help); 3524 return; 3525 } 3526 3527 if ((strcmp(tokens[0], "pipeline") == 0) && 3528 (n_tokens == 2) && (strcmp(tokens[1], "codegen") == 0)) { 3529 snprintf(out, out_size, "\n%s\n", cmd_pipeline_codegen_help); 3530 return; 3531 } 3532 3533 if ((strcmp(tokens[0], "pipeline") == 0) && 3534 (n_tokens == 2) && (strcmp(tokens[1], "libbuild") == 0)) { 3535 snprintf(out, out_size, "\n%s\n", cmd_pipeline_libbuild_help); 3536 return; 3537 } 3538 3539 if ((strcmp(tokens[0], "pipeline") == 0) && 3540 (n_tokens == 2) && (strcmp(tokens[1], "build") == 0)) { 3541 snprintf(out, out_size, "\n%s\n", cmd_pipeline_build_help); 3542 return; 3543 } 3544 3545 if ((strcmp(tokens[0], "pipeline") == 0) && 3546 (n_tokens == 3) && 3547 (strcmp(tokens[1], "table") == 0) && 3548 (strcmp(tokens[2], "add") == 0)) { 3549 snprintf(out, out_size, "\n%s\n", 3550 cmd_pipeline_table_add_help); 3551 return; 3552 } 3553 3554 if ((strcmp(tokens[0], "pipeline") == 0) && 3555 (n_tokens == 3) && 3556 (strcmp(tokens[1], "table") == 0) && 3557 (strcmp(tokens[2], "delete") == 0)) { 3558 snprintf(out, out_size, "\n%s\n", 3559 cmd_pipeline_table_delete_help); 3560 return; 3561 } 3562 3563 if ((strcmp(tokens[0], "pipeline") == 0) && 3564 (n_tokens == 3) && 3565 (strcmp(tokens[1], "table") == 0) && 3566 (strcmp(tokens[2], "default") == 0)) { 3567 snprintf(out, out_size, "\n%s\n", 3568 cmd_pipeline_table_default_help); 3569 return; 3570 } 3571 3572 if ((strcmp(tokens[0], "pipeline") == 0) && 3573 (n_tokens == 3) && 3574 (strcmp(tokens[1], "table") == 0) && 3575 (strcmp(tokens[2], "show") == 0)) { 3576 snprintf(out, out_size, "\n%s\n", 3577 cmd_pipeline_table_show_help); 3578 return; 3579 } 3580 3581 if ((strcmp(tokens[0], "pipeline") == 0) && 3582 (n_tokens == 4) && 3583 (strcmp(tokens[1], "selector") == 0) && 3584 (strcmp(tokens[2], "group") == 0) && 3585 (strcmp(tokens[3], "add") == 0)) { 3586 snprintf(out, out_size, "\n%s\n", 3587 cmd_pipeline_selector_group_add_help); 3588 return; 3589 } 3590 3591 if ((strcmp(tokens[0], "pipeline") == 0) && 3592 (n_tokens == 4) && 3593 (strcmp(tokens[1], "selector") == 0) && 3594 (strcmp(tokens[2], "group") == 0) && 3595 (strcmp(tokens[3], "delete") == 0)) { 3596 snprintf(out, out_size, "\n%s\n", 3597 cmd_pipeline_selector_group_delete_help); 3598 return; 3599 } 3600 3601 if ((strcmp(tokens[0], "pipeline") == 0) && 3602 (n_tokens == 5) && 3603 (strcmp(tokens[1], "selector") == 0) && 3604 (strcmp(tokens[2], "group") == 0) && 3605 (strcmp(tokens[3], "member") == 0) && 3606 (strcmp(tokens[4], "add") == 0)) { 3607 snprintf(out, out_size, "\n%s\n", 3608 cmd_pipeline_selector_group_member_add_help); 3609 return; 3610 } 3611 3612 if ((strcmp(tokens[0], "pipeline") == 0) && 3613 (n_tokens == 5) && 3614 (strcmp(tokens[1], "selector") == 0) && 3615 (strcmp(tokens[2], "group") == 0) && 3616 (strcmp(tokens[3], "member") == 0) && 3617 (strcmp(tokens[4], "delete") == 0)) { 3618 snprintf(out, out_size, "\n%s\n", 3619 cmd_pipeline_selector_group_member_delete_help); 3620 return; 3621 } 3622 3623 if ((strcmp(tokens[0], "pipeline") == 0) && 3624 (n_tokens == 3) && 3625 (strcmp(tokens[1], "selector") == 0) && 3626 (strcmp(tokens[2], "show") == 0)) { 3627 snprintf(out, out_size, "\n%s\n", 3628 cmd_pipeline_selector_show_help); 3629 return; 3630 } 3631 3632 if ((strcmp(tokens[0], "pipeline") == 0) && 3633 (n_tokens == 3) && 3634 (strcmp(tokens[1], "learner") == 0) && 3635 (strcmp(tokens[2], "default") == 0)) { 3636 snprintf(out, out_size, "\n%s\n", 3637 cmd_pipeline_learner_default_help); 3638 return; 3639 } 3640 3641 if ((strcmp(tokens[0], "pipeline") == 0) && 3642 (n_tokens == 2) && 3643 (strcmp(tokens[1], "commit") == 0)) { 3644 snprintf(out, out_size, "\n%s\n", 3645 cmd_pipeline_commit_help); 3646 return; 3647 } 3648 3649 if ((strcmp(tokens[0], "pipeline") == 0) && 3650 (n_tokens == 2) && 3651 (strcmp(tokens[1], "abort") == 0)) { 3652 snprintf(out, out_size, "\n%s\n", 3653 cmd_pipeline_abort_help); 3654 return; 3655 } 3656 3657 if ((strcmp(tokens[0], "pipeline") == 0) && 3658 (n_tokens == 2) && (strcmp(tokens[1], "regrd") == 0)) { 3659 snprintf(out, out_size, "\n%s\n", cmd_pipeline_regrd_help); 3660 return; 3661 } 3662 3663 if ((strcmp(tokens[0], "pipeline") == 0) && 3664 (n_tokens == 2) && (strcmp(tokens[1], "regwr") == 0)) { 3665 snprintf(out, out_size, "\n%s\n", cmd_pipeline_regwr_help); 3666 return; 3667 } 3668 3669 if (!strcmp(tokens[0], "pipeline") && 3670 (n_tokens == 4) && !strcmp(tokens[1], "meter") 3671 && !strcmp(tokens[2], "profile") 3672 && !strcmp(tokens[3], "add")) { 3673 snprintf(out, out_size, "\n%s\n", cmd_pipeline_meter_profile_add_help); 3674 return; 3675 } 3676 3677 if (!strcmp(tokens[0], "pipeline") && 3678 (n_tokens == 4) && !strcmp(tokens[1], "meter") 3679 && !strcmp(tokens[2], "profile") 3680 && !strcmp(tokens[3], "delete")) { 3681 snprintf(out, out_size, "\n%s\n", cmd_pipeline_meter_profile_delete_help); 3682 return; 3683 } 3684 3685 if (!strcmp(tokens[0], "pipeline") && 3686 (n_tokens == 3) && !strcmp(tokens[1], "meter") 3687 && !strcmp(tokens[2], "reset")) { 3688 snprintf(out, out_size, "\n%s\n", cmd_pipeline_meter_reset_help); 3689 return; 3690 } 3691 3692 if (!strcmp(tokens[0], "pipeline") && 3693 (n_tokens == 3) && !strcmp(tokens[1], "meter") 3694 && !strcmp(tokens[2], "set")) { 3695 snprintf(out, out_size, "\n%s\n", cmd_pipeline_meter_set_help); 3696 return; 3697 } 3698 3699 if (!strcmp(tokens[0], "pipeline") && 3700 (n_tokens == 3) && !strcmp(tokens[1], "meter") 3701 && !strcmp(tokens[2], "stats")) { 3702 snprintf(out, out_size, "\n%s\n", cmd_pipeline_meter_stats_help); 3703 return; 3704 } 3705 3706 if (!strcmp(tokens[0], "pipeline") && 3707 (n_tokens == 2) && !strcmp(tokens[1], "rss")) { 3708 snprintf(out, out_size, "\n%s\n", cmd_pipeline_rss_help); 3709 return; 3710 } 3711 3712 if ((strcmp(tokens[0], "pipeline") == 0) && 3713 (n_tokens == 2) && (strcmp(tokens[1], "stats") == 0)) { 3714 snprintf(out, out_size, "\n%s\n", cmd_pipeline_stats_help); 3715 return; 3716 } 3717 3718 if (!strcmp(tokens[0], "pipeline") && 3719 (n_tokens == 3) && !strcmp(tokens[1], "mirror") 3720 && !strcmp(tokens[2], "session")) { 3721 snprintf(out, out_size, "\n%s\n", cmd_pipeline_mirror_session_help); 3722 return; 3723 } 3724 3725 if (!strcmp(tokens[0], "pipeline") && 3726 (n_tokens == 2) && !strcmp(tokens[1], "enable")) { 3727 snprintf(out, out_size, "\n%s\n", cmd_pipeline_enable_help); 3728 return; 3729 } 3730 3731 if (!strcmp(tokens[0], "pipeline") && 3732 (n_tokens == 2) && !strcmp(tokens[1], "disable")) { 3733 snprintf(out, out_size, "\n%s\n", cmd_pipeline_disable_help); 3734 return; 3735 } 3736 3737 if (!strcmp(tokens[0], "ipsec") && 3738 (n_tokens == 2) && !strcmp(tokens[1], "create")) { 3739 snprintf(out, out_size, "\n%s\n", cmd_ipsec_create_help); 3740 return; 3741 } 3742 3743 if (!strcmp(tokens[0], "ipsec") && 3744 (n_tokens == 3) && !strcmp(tokens[1], "sa") 3745 && !strcmp(tokens[2], "add")) { 3746 snprintf(out, out_size, "\n%s\n", cmd_ipsec_sa_add_help); 3747 return; 3748 } 3749 3750 if (!strcmp(tokens[0], "ipsec") && 3751 (n_tokens == 3) && !strcmp(tokens[1], "sa") 3752 && !strcmp(tokens[2], "delete")) { 3753 snprintf(out, out_size, "\n%s\n", cmd_ipsec_sa_delete_help); 3754 return; 3755 } 3756 3757 if (!strcmp(tokens[0], "block") && 3758 (n_tokens == 2) && !strcmp(tokens[1], "enable")) { 3759 snprintf(out, out_size, "\n%s\n", cmd_block_enable_help); 3760 return; 3761 } 3762 3763 if (!strcmp(tokens[0], "block") && 3764 (n_tokens == 2) && !strcmp(tokens[1], "disable")) { 3765 snprintf(out, out_size, "\n%s\n", cmd_block_disable_help); 3766 return; 3767 } 3768 3769 snprintf(out, out_size, "Invalid command\n"); 3770 } 3771 3772 void 3773 cli_process(char *in, char *out, size_t out_size, void *obj) 3774 { 3775 char *tokens[CMD_MAX_TOKENS]; 3776 uint32_t n_tokens = RTE_DIM(tokens); 3777 int status; 3778 3779 if (is_comment(in)) 3780 return; 3781 3782 status = parse_tokenize_string(in, tokens, &n_tokens); 3783 if (status) { 3784 snprintf(out, out_size, MSG_ARG_TOO_MANY, ""); 3785 return; 3786 } 3787 3788 if (n_tokens == 0) 3789 return; 3790 3791 if (strcmp(tokens[0], "help") == 0) { 3792 cmd_help(tokens, n_tokens, out, out_size, obj); 3793 return; 3794 } 3795 3796 if (strcmp(tokens[0], "mempool") == 0) { 3797 cmd_mempool(tokens, n_tokens, out, out_size, obj); 3798 return; 3799 } 3800 3801 if (strcmp(tokens[0], "ethdev") == 0) { 3802 if ((n_tokens >= 2) && (strcmp(tokens[1], "show") == 0)) { 3803 cmd_ethdev_show(tokens, n_tokens, out, out_size, obj); 3804 return; 3805 } 3806 3807 cmd_ethdev(tokens, n_tokens, out, out_size, obj); 3808 return; 3809 } 3810 3811 if (strcmp(tokens[0], "ring") == 0) { 3812 cmd_ring(tokens, n_tokens, out, out_size, obj); 3813 return; 3814 } 3815 3816 if (!strcmp(tokens[0], "cryptodev")) { 3817 cmd_cryptodev(tokens, n_tokens, out, out_size, obj); 3818 return; 3819 } 3820 3821 if (strcmp(tokens[0], "pipeline") == 0) { 3822 if ((n_tokens >= 3) && 3823 (strcmp(tokens[1], "codegen") == 0)) { 3824 cmd_pipeline_codegen(tokens, n_tokens, out, out_size, 3825 obj); 3826 return; 3827 } 3828 3829 if ((n_tokens >= 3) && 3830 (strcmp(tokens[1], "libbuild") == 0)) { 3831 cmd_pipeline_libbuild(tokens, n_tokens, out, out_size, 3832 obj); 3833 return; 3834 } 3835 3836 if ((n_tokens >= 3) && 3837 (strcmp(tokens[2], "build") == 0)) { 3838 cmd_pipeline_build(tokens, n_tokens, out, out_size, 3839 obj); 3840 return; 3841 } 3842 3843 if ((n_tokens >= 5) && 3844 (strcmp(tokens[2], "table") == 0) && 3845 (strcmp(tokens[4], "add") == 0)) { 3846 cmd_pipeline_table_add(tokens, n_tokens, out, 3847 out_size, obj); 3848 return; 3849 } 3850 3851 if ((n_tokens >= 5) && 3852 (strcmp(tokens[2], "table") == 0) && 3853 (strcmp(tokens[4], "delete") == 0)) { 3854 cmd_pipeline_table_delete(tokens, n_tokens, out, 3855 out_size, obj); 3856 return; 3857 } 3858 3859 if ((n_tokens >= 5) && 3860 (strcmp(tokens[2], "table") == 0) && 3861 (strcmp(tokens[4], "default") == 0)) { 3862 cmd_pipeline_table_default(tokens, n_tokens, out, 3863 out_size, obj); 3864 return; 3865 } 3866 3867 if ((n_tokens >= 5) && 3868 (strcmp(tokens[2], "table") == 0) && 3869 (strcmp(tokens[4], "show") == 0)) { 3870 cmd_pipeline_table_show(tokens, n_tokens, out, 3871 out_size, obj); 3872 return; 3873 } 3874 3875 if ((n_tokens >= 6) && 3876 (strcmp(tokens[2], "selector") == 0) && 3877 (strcmp(tokens[4], "group") == 0) && 3878 (strcmp(tokens[5], "add") == 0)) { 3879 cmd_pipeline_selector_group_add(tokens, n_tokens, out, 3880 out_size, obj); 3881 return; 3882 } 3883 3884 if ((n_tokens >= 6) && 3885 (strcmp(tokens[2], "selector") == 0) && 3886 (strcmp(tokens[4], "group") == 0) && 3887 (strcmp(tokens[5], "delete") == 0)) { 3888 cmd_pipeline_selector_group_delete(tokens, n_tokens, out, 3889 out_size, obj); 3890 return; 3891 } 3892 3893 if ((n_tokens >= 7) && 3894 (strcmp(tokens[2], "selector") == 0) && 3895 (strcmp(tokens[4], "group") == 0) && 3896 (strcmp(tokens[5], "member") == 0) && 3897 (strcmp(tokens[6], "add") == 0)) { 3898 cmd_pipeline_selector_group_member_add(tokens, n_tokens, out, 3899 out_size, obj); 3900 return; 3901 } 3902 3903 if ((n_tokens >= 7) && 3904 (strcmp(tokens[2], "selector") == 0) && 3905 (strcmp(tokens[4], "group") == 0) && 3906 (strcmp(tokens[5], "member") == 0) && 3907 (strcmp(tokens[6], "delete") == 0)) { 3908 cmd_pipeline_selector_group_member_delete(tokens, n_tokens, out, 3909 out_size, obj); 3910 return; 3911 } 3912 3913 if ((n_tokens >= 5) && 3914 (strcmp(tokens[2], "selector") == 0) && 3915 (strcmp(tokens[4], "show") == 0)) { 3916 cmd_pipeline_selector_show(tokens, n_tokens, out, 3917 out_size, obj); 3918 return; 3919 } 3920 3921 if ((n_tokens >= 5) && 3922 (strcmp(tokens[2], "learner") == 0) && 3923 (strcmp(tokens[4], "default") == 0)) { 3924 cmd_pipeline_learner_default(tokens, n_tokens, out, 3925 out_size, obj); 3926 return; 3927 } 3928 3929 if ((n_tokens >= 3) && 3930 (strcmp(tokens[2], "commit") == 0)) { 3931 cmd_pipeline_commit(tokens, n_tokens, out, 3932 out_size, obj); 3933 return; 3934 } 3935 3936 if ((n_tokens >= 3) && 3937 (strcmp(tokens[2], "abort") == 0)) { 3938 cmd_pipeline_abort(tokens, n_tokens, out, 3939 out_size, obj); 3940 return; 3941 } 3942 3943 if ((n_tokens >= 3) && 3944 (strcmp(tokens[2], "regrd") == 0)) { 3945 cmd_pipeline_regrd(tokens, n_tokens, out, out_size, obj); 3946 return; 3947 } 3948 3949 if ((n_tokens >= 3) && 3950 (strcmp(tokens[2], "regwr") == 0)) { 3951 cmd_pipeline_regwr(tokens, n_tokens, out, out_size, obj); 3952 return; 3953 } 3954 3955 if ((n_tokens >= 6) && 3956 (strcmp(tokens[2], "meter") == 0) && 3957 (strcmp(tokens[3], "profile") == 0) && 3958 (strcmp(tokens[5], "add") == 0)) { 3959 cmd_pipeline_meter_profile_add(tokens, n_tokens, out, out_size, obj); 3960 return; 3961 } 3962 3963 if ((n_tokens >= 6) && 3964 (strcmp(tokens[2], "meter") == 0) && 3965 (strcmp(tokens[3], "profile") == 0) && 3966 (strcmp(tokens[5], "delete") == 0)) { 3967 cmd_pipeline_meter_profile_delete(tokens, n_tokens, out, out_size, obj); 3968 return; 3969 } 3970 3971 if (n_tokens >= 9 && !strcmp(tokens[2], "meter") && !strcmp(tokens[4], "reset")) { 3972 cmd_pipeline_meter_reset(tokens, n_tokens, out, out_size, obj); 3973 return; 3974 } 3975 3976 if (n_tokens >= 9 && !strcmp(tokens[2], "meter") && !strcmp(tokens[4], "set")) { 3977 cmd_pipeline_meter_set(tokens, n_tokens, out, out_size, obj); 3978 return; 3979 } 3980 3981 if (n_tokens >= 9 && !strcmp(tokens[2], "meter") && !strcmp(tokens[4], "stats")) { 3982 cmd_pipeline_meter_stats(tokens, n_tokens, out, out_size, obj); 3983 return; 3984 } 3985 3986 if (n_tokens >= 3 && !strcmp(tokens[2], "rss")) { 3987 cmd_pipeline_rss(tokens, n_tokens, out, out_size, obj); 3988 return; 3989 } 3990 3991 if ((n_tokens >= 3) && 3992 (strcmp(tokens[2], "stats") == 0)) { 3993 cmd_pipeline_stats(tokens, n_tokens, out, out_size, 3994 obj); 3995 return; 3996 } 3997 3998 if ((n_tokens >= 4) && 3999 (strcmp(tokens[2], "mirror") == 0) && 4000 (strcmp(tokens[3], "session") == 0)) { 4001 cmd_pipeline_mirror_session(tokens, n_tokens, out, out_size, obj); 4002 return; 4003 } 4004 4005 if (n_tokens >= 3 && !strcmp(tokens[2], "enable")) { 4006 cmd_pipeline_enable(tokens, n_tokens, out, out_size, obj); 4007 return; 4008 } 4009 4010 if (n_tokens >= 3 && !strcmp(tokens[2], "disable")) { 4011 cmd_pipeline_disable(tokens, n_tokens, out, out_size, obj); 4012 return; 4013 } 4014 } 4015 4016 if (!strcmp(tokens[0], "ipsec")) { 4017 if (n_tokens >= 3 && !strcmp(tokens[2], "create")) { 4018 cmd_ipsec_create(tokens, n_tokens, out, out_size, obj); 4019 return; 4020 } 4021 4022 if (n_tokens >= 4 && !strcmp(tokens[2], "sa") && !strcmp(tokens[3], "add")) { 4023 cmd_ipsec_sa_add(tokens, n_tokens, out, out_size, obj); 4024 return; 4025 } 4026 4027 if (n_tokens >= 4 && !strcmp(tokens[2], "sa") && !strcmp(tokens[3], "delete")) { 4028 cmd_ipsec_sa_delete(tokens, n_tokens, out, out_size, obj); 4029 return; 4030 } 4031 } 4032 4033 if (!strcmp(tokens[0], "block")) { 4034 if (n_tokens >= 6 && !strcmp(tokens[5], "enable")) { 4035 cmd_block_enable(tokens, n_tokens, out, out_size, obj); 4036 return; 4037 } 4038 4039 if (n_tokens >= 6 && !strcmp(tokens[5], "disable")) { 4040 cmd_block_disable(tokens, n_tokens, out, out_size, obj); 4041 return; 4042 } 4043 } 4044 4045 snprintf(out, out_size, MSG_CMD_UNKNOWN, tokens[0]); 4046 } 4047 4048 int 4049 cli_script_process(const char *file_name, 4050 size_t msg_in_len_max, 4051 size_t msg_out_len_max, 4052 void *obj) 4053 { 4054 char *msg_in = NULL, *msg_out = NULL; 4055 FILE *f = NULL; 4056 4057 /* Check input arguments */ 4058 if ((file_name == NULL) || 4059 (strlen(file_name) == 0) || 4060 (msg_in_len_max == 0) || 4061 (msg_out_len_max == 0)) 4062 return -EINVAL; 4063 4064 msg_in = malloc(msg_in_len_max + 1); 4065 msg_out = malloc(msg_out_len_max + 1); 4066 if ((msg_in == NULL) || 4067 (msg_out == NULL)) { 4068 free(msg_out); 4069 free(msg_in); 4070 return -ENOMEM; 4071 } 4072 4073 /* Open input file */ 4074 f = fopen(file_name, "r"); 4075 if (f == NULL) { 4076 free(msg_out); 4077 free(msg_in); 4078 return -EIO; 4079 } 4080 4081 /* Read file */ 4082 for ( ; ; ) { 4083 if (fgets(msg_in, msg_in_len_max + 1, f) == NULL) 4084 break; 4085 4086 printf("%s", msg_in); 4087 msg_out[0] = 0; 4088 4089 cli_process(msg_in, 4090 msg_out, 4091 msg_out_len_max, 4092 obj); 4093 4094 if (strlen(msg_out)) 4095 printf("%s", msg_out); 4096 } 4097 4098 /* Close file */ 4099 fclose(f); 4100 free(msg_out); 4101 free(msg_in); 4102 return 0; 4103 } 4104