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