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