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