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