1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2010-2018 Intel Corporation 3 */ 4 5 #include <stdio.h> 6 #include <stdint.h> 7 #include <stdlib.h> 8 #include <string.h> 9 10 #include <rte_common.h> 11 #include <rte_cycles.h> 12 #include <rte_ethdev.h> 13 14 #include "cli.h" 15 16 #include "cryptodev.h" 17 #include "kni.h" 18 #include "link.h" 19 #include "mempool.h" 20 #include "parser.h" 21 #include "pipeline.h" 22 #include "swq.h" 23 #include "tap.h" 24 #include "thread.h" 25 #include "tmgr.h" 26 27 #ifndef CMD_MAX_TOKENS 28 #define CMD_MAX_TOKENS 256 29 #endif 30 31 #define MSG_OUT_OF_MEMORY "Not enough memory.\n" 32 #define MSG_CMD_UNKNOWN "Unknown command \"%s\".\n" 33 #define MSG_CMD_UNIMPLEM "Command \"%s\" not implemented.\n" 34 #define MSG_ARG_NOT_ENOUGH "Not enough arguments for command \"%s\".\n" 35 #define MSG_ARG_TOO_MANY "Too many arguments for command \"%s\".\n" 36 #define MSG_ARG_MISMATCH "Wrong number of arguments for command \"%s\".\n" 37 #define MSG_ARG_NOT_FOUND "Argument \"%s\" not found.\n" 38 #define MSG_ARG_INVALID "Invalid value for argument \"%s\".\n" 39 #define MSG_FILE_ERR "Error in file \"%s\" at line %u.\n" 40 #define MSG_FILE_NOT_ENOUGH "Not enough rules in file \"%s\".\n" 41 #define MSG_CMD_FAIL "Command \"%s\" failed.\n" 42 43 static int 44 is_comment(char *in) 45 { 46 if ((strlen(in) && index("!#%;", in[0])) || 47 (strncmp(in, "//", 2) == 0) || 48 (strncmp(in, "--", 2) == 0)) 49 return 1; 50 51 return 0; 52 } 53 54 static const char cmd_mempool_help[] = 55 "mempool <mempool_name>\n" 56 " buffer <buffer_size>\n" 57 " pool <pool_size>\n" 58 " cache <cache_size>\n" 59 " cpu <cpu_id>\n"; 60 61 static void 62 cmd_mempool(char **tokens, 63 uint32_t n_tokens, 64 char *out, 65 size_t out_size) 66 { 67 struct mempool_params p; 68 char *name; 69 struct mempool *mempool; 70 71 if (n_tokens != 10) { 72 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 73 return; 74 } 75 76 name = tokens[1]; 77 78 if (strcmp(tokens[2], "buffer") != 0) { 79 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "buffer"); 80 return; 81 } 82 83 if (parser_read_uint32(&p.buffer_size, tokens[3]) != 0) { 84 snprintf(out, out_size, MSG_ARG_INVALID, "buffer_size"); 85 return; 86 } 87 88 if (strcmp(tokens[4], "pool") != 0) { 89 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pool"); 90 return; 91 } 92 93 if (parser_read_uint32(&p.pool_size, tokens[5]) != 0) { 94 snprintf(out, out_size, MSG_ARG_INVALID, "pool_size"); 95 return; 96 } 97 98 if (strcmp(tokens[6], "cache") != 0) { 99 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "cache"); 100 return; 101 } 102 103 if (parser_read_uint32(&p.cache_size, tokens[7]) != 0) { 104 snprintf(out, out_size, MSG_ARG_INVALID, "cache_size"); 105 return; 106 } 107 108 if (strcmp(tokens[8], "cpu") != 0) { 109 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "cpu"); 110 return; 111 } 112 113 if (parser_read_uint32(&p.cpu_id, tokens[9]) != 0) { 114 snprintf(out, out_size, MSG_ARG_INVALID, "cpu_id"); 115 return; 116 } 117 118 mempool = mempool_create(name, &p); 119 if (mempool == NULL) { 120 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 121 return; 122 } 123 } 124 125 static const char cmd_link_help[] = 126 "link <link_name>\n" 127 " dev <device_name> | port <port_id>\n" 128 " rxq <n_queues> <queue_size> <mempool_name>\n" 129 " txq <n_queues> <queue_size>\n" 130 " promiscuous on | off\n" 131 " [rss <qid_0> ... <qid_n>]\n"; 132 133 static void 134 cmd_link(char **tokens, 135 uint32_t n_tokens, 136 char *out, 137 size_t out_size) 138 { 139 struct link_params p; 140 struct link_params_rss rss; 141 struct link *link; 142 char *name; 143 144 memset(&p, 0, sizeof(p)); 145 146 if ((n_tokens < 13) || (n_tokens > 14 + LINK_RXQ_RSS_MAX)) { 147 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 148 return; 149 } 150 name = tokens[1]; 151 152 if (strcmp(tokens[2], "dev") == 0) 153 p.dev_name = tokens[3]; 154 else if (strcmp(tokens[2], "port") == 0) { 155 p.dev_name = NULL; 156 157 if (parser_read_uint16(&p.port_id, tokens[3]) != 0) { 158 snprintf(out, out_size, MSG_ARG_INVALID, "port_id"); 159 return; 160 } 161 } else { 162 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "dev or port"); 163 return; 164 } 165 166 if (strcmp(tokens[4], "rxq") != 0) { 167 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rxq"); 168 return; 169 } 170 171 if (parser_read_uint32(&p.rx.n_queues, tokens[5]) != 0) { 172 snprintf(out, out_size, MSG_ARG_INVALID, "n_queues"); 173 return; 174 } 175 if (parser_read_uint32(&p.rx.queue_size, tokens[6]) != 0) { 176 snprintf(out, out_size, MSG_ARG_INVALID, "queue_size"); 177 return; 178 } 179 180 p.rx.mempool_name = tokens[7]; 181 182 if (strcmp(tokens[8], "txq") != 0) { 183 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "txq"); 184 return; 185 } 186 187 if (parser_read_uint32(&p.tx.n_queues, tokens[9]) != 0) { 188 snprintf(out, out_size, MSG_ARG_INVALID, "n_queues"); 189 return; 190 } 191 192 if (parser_read_uint32(&p.tx.queue_size, tokens[10]) != 0) { 193 snprintf(out, out_size, MSG_ARG_INVALID, "queue_size"); 194 return; 195 } 196 197 if (strcmp(tokens[11], "promiscuous") != 0) { 198 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "promiscuous"); 199 return; 200 } 201 202 if (strcmp(tokens[12], "on") == 0) 203 p.promiscuous = 1; 204 else if (strcmp(tokens[12], "off") == 0) 205 p.promiscuous = 0; 206 else { 207 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "on or off"); 208 return; 209 } 210 211 /* RSS */ 212 p.rx.rss = NULL; 213 if (n_tokens > 13) { 214 uint32_t queue_id, i; 215 216 if (strcmp(tokens[13], "rss") != 0) { 217 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rss"); 218 return; 219 } 220 221 p.rx.rss = &rss; 222 223 rss.n_queues = 0; 224 for (i = 14; i < n_tokens; i++) { 225 if (parser_read_uint32(&queue_id, tokens[i]) != 0) { 226 snprintf(out, out_size, MSG_ARG_INVALID, 227 "queue_id"); 228 return; 229 } 230 231 rss.queue_id[rss.n_queues] = queue_id; 232 rss.n_queues++; 233 } 234 } 235 236 link = link_create(name, &p); 237 if (link == NULL) { 238 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 239 return; 240 } 241 } 242 243 /* Print the link stats and info */ 244 static void 245 print_link_info(struct link *link, char *out, size_t out_size) 246 { 247 struct rte_eth_stats stats; 248 struct rte_ether_addr mac_addr; 249 struct rte_eth_link eth_link; 250 uint16_t mtu; 251 int ret; 252 253 memset(&stats, 0, sizeof(stats)); 254 rte_eth_stats_get(link->port_id, &stats); 255 256 ret = rte_eth_macaddr_get(link->port_id, &mac_addr); 257 if (ret != 0) { 258 snprintf(out, out_size, "\n%s: MAC address get failed: %s", 259 link->name, rte_strerror(-ret)); 260 return; 261 } 262 263 ret = rte_eth_link_get(link->port_id, ð_link); 264 if (ret < 0) { 265 snprintf(out, out_size, "\n%s: link get failed: %s", 266 link->name, rte_strerror(-ret)); 267 return; 268 } 269 270 rte_eth_dev_get_mtu(link->port_id, &mtu); 271 272 snprintf(out, out_size, 273 "\n" 274 "%s: flags=<%s> mtu %u\n" 275 "\tether " RTE_ETHER_ADDR_PRT_FMT " rxqueues %u txqueues %u\n" 276 "\tport# %u speed %s\n" 277 "\tRX packets %" PRIu64" bytes %" PRIu64"\n" 278 "\tRX errors %" PRIu64" missed %" PRIu64" no-mbuf %" PRIu64"\n" 279 "\tTX packets %" PRIu64" bytes %" PRIu64"\n" 280 "\tTX errors %" PRIu64"\n", 281 link->name, 282 eth_link.link_status == 0 ? "DOWN" : "UP", 283 mtu, 284 RTE_ETHER_ADDR_BYTES(&mac_addr), 285 link->n_rxq, 286 link->n_txq, 287 link->port_id, 288 rte_eth_link_speed_to_str(eth_link.link_speed), 289 stats.ipackets, 290 stats.ibytes, 291 stats.ierrors, 292 stats.imissed, 293 stats.rx_nombuf, 294 stats.opackets, 295 stats.obytes, 296 stats.oerrors); 297 } 298 299 /* 300 * link show [<link_name>] 301 */ 302 static void 303 cmd_link_show(char **tokens, uint32_t n_tokens, char *out, size_t out_size) 304 { 305 struct link *link; 306 char *link_name; 307 308 if (n_tokens != 2 && n_tokens != 3) { 309 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 310 return; 311 } 312 313 if (n_tokens == 2) { 314 link = link_next(NULL); 315 316 while (link != NULL) { 317 out_size = out_size - strlen(out); 318 out = &out[strlen(out)]; 319 320 print_link_info(link, out, out_size); 321 link = link_next(link); 322 } 323 } else { 324 out_size = out_size - strlen(out); 325 out = &out[strlen(out)]; 326 327 link_name = tokens[2]; 328 link = link_find(link_name); 329 330 if (link == NULL) { 331 snprintf(out, out_size, MSG_ARG_INVALID, 332 "Link does not exist"); 333 return; 334 } 335 print_link_info(link, out, out_size); 336 } 337 } 338 339 static const char cmd_swq_help[] = 340 "swq <swq_name>\n" 341 " size <size>\n" 342 " cpu <cpu_id>\n"; 343 344 static void 345 cmd_swq(char **tokens, 346 uint32_t n_tokens, 347 char *out, 348 size_t out_size) 349 { 350 struct swq_params p; 351 char *name; 352 struct swq *swq; 353 354 if (n_tokens != 6) { 355 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 356 return; 357 } 358 359 name = tokens[1]; 360 361 if (strcmp(tokens[2], "size") != 0) { 362 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "size"); 363 return; 364 } 365 366 if (parser_read_uint32(&p.size, tokens[3]) != 0) { 367 snprintf(out, out_size, MSG_ARG_INVALID, "size"); 368 return; 369 } 370 371 if (strcmp(tokens[4], "cpu") != 0) { 372 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "cpu"); 373 return; 374 } 375 376 if (parser_read_uint32(&p.cpu_id, tokens[5]) != 0) { 377 snprintf(out, out_size, MSG_ARG_INVALID, "cpu_id"); 378 return; 379 } 380 381 swq = swq_create(name, &p); 382 if (swq == NULL) { 383 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 384 return; 385 } 386 } 387 388 static const char cmd_tmgr_subport_profile_help[] = 389 "tmgr subport profile\n" 390 " <tb_rate> <tb_size>\n" 391 " <tc0_rate> <tc1_rate> <tc2_rate> <tc3_rate> <tc4_rate>" 392 " <tc5_rate> <tc6_rate> <tc7_rate> <tc8_rate>" 393 " <tc9_rate> <tc10_rate> <tc11_rate> <tc12_rate>\n" 394 " <tc_period>\n"; 395 396 static void 397 cmd_tmgr_subport_profile(char **tokens, 398 uint32_t n_tokens, 399 char *out, 400 size_t out_size) 401 { 402 struct rte_sched_subport_profile_params subport_profile; 403 int status, i; 404 405 if (n_tokens != 19) { 406 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 407 return; 408 } 409 410 if (parser_read_uint64(&subport_profile.tb_rate, tokens[3]) != 0) { 411 snprintf(out, out_size, MSG_ARG_INVALID, "tb_rate"); 412 return; 413 } 414 415 if (parser_read_uint64(&subport_profile.tb_size, tokens[4]) != 0) { 416 snprintf(out, out_size, MSG_ARG_INVALID, "tb_size"); 417 return; 418 } 419 420 for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) 421 if (parser_read_uint64(&subport_profile.tc_rate[i], 422 tokens[5 + i]) != 0) { 423 snprintf(out, out_size, MSG_ARG_INVALID, "tc_rate"); 424 return; 425 } 426 427 if (parser_read_uint64(&subport_profile.tc_period, tokens[18]) != 0) { 428 snprintf(out, out_size, MSG_ARG_INVALID, "tc_period"); 429 return; 430 } 431 432 status = tmgr_subport_profile_add(&subport_profile); 433 if (status != 0) { 434 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 435 return; 436 } 437 } 438 439 static const char cmd_tmgr_pipe_profile_help[] = 440 "tmgr pipe profile\n" 441 " <tb_rate> <tb_size>\n" 442 " <tc0_rate> <tc1_rate> <tc2_rate> <tc3_rate> <tc4_rate>" 443 " <tc5_rate> <tc6_rate> <tc7_rate> <tc8_rate>" 444 " <tc9_rate> <tc10_rate> <tc11_rate> <tc12_rate>\n" 445 " <tc_period>\n" 446 " <tc_ov_weight>\n" 447 " <wrr_weight0..3>\n"; 448 449 static void 450 cmd_tmgr_pipe_profile(char **tokens, 451 uint32_t n_tokens, 452 char *out, 453 size_t out_size) 454 { 455 struct rte_sched_pipe_params p; 456 int status, i; 457 458 if (n_tokens != 24) { 459 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 460 return; 461 } 462 463 if (parser_read_uint64(&p.tb_rate, tokens[3]) != 0) { 464 snprintf(out, out_size, MSG_ARG_INVALID, "tb_rate"); 465 return; 466 } 467 468 if (parser_read_uint64(&p.tb_size, tokens[4]) != 0) { 469 snprintf(out, out_size, MSG_ARG_INVALID, "tb_size"); 470 return; 471 } 472 473 for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) 474 if (parser_read_uint64(&p.tc_rate[i], tokens[5 + i]) != 0) { 475 snprintf(out, out_size, MSG_ARG_INVALID, "tc_rate"); 476 return; 477 } 478 479 if (parser_read_uint64(&p.tc_period, tokens[18]) != 0) { 480 snprintf(out, out_size, MSG_ARG_INVALID, "tc_period"); 481 return; 482 } 483 484 if (parser_read_uint8(&p.tc_ov_weight, tokens[19]) != 0) { 485 snprintf(out, out_size, MSG_ARG_INVALID, "tc_ov_weight"); 486 return; 487 } 488 489 for (i = 0; i < RTE_SCHED_BE_QUEUES_PER_PIPE; i++) 490 if (parser_read_uint8(&p.wrr_weights[i], tokens[20 + i]) != 0) { 491 snprintf(out, out_size, MSG_ARG_INVALID, "wrr_weights"); 492 return; 493 } 494 495 status = tmgr_pipe_profile_add(&p); 496 if (status != 0) { 497 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 498 return; 499 } 500 } 501 502 static const char cmd_tmgr_help[] = 503 "tmgr <tmgr_name>\n" 504 " rate <rate>\n" 505 " spp <n_subports_per_port>\n" 506 " pps <n_pipes_per_subport>\n" 507 " fo <frame_overhead>\n" 508 " mtu <mtu>\n" 509 " cpu <cpu_id>\n"; 510 511 static void 512 cmd_tmgr(char **tokens, 513 uint32_t n_tokens, 514 char *out, 515 size_t out_size) 516 { 517 struct tmgr_port_params p; 518 char *name; 519 struct tmgr_port *tmgr_port; 520 521 if (n_tokens != 14) { 522 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 523 return; 524 } 525 526 name = tokens[1]; 527 528 if (strcmp(tokens[2], "rate") != 0) { 529 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rate"); 530 return; 531 } 532 533 if (parser_read_uint64(&p.rate, tokens[3]) != 0) { 534 snprintf(out, out_size, MSG_ARG_INVALID, "rate"); 535 return; 536 } 537 538 if (strcmp(tokens[4], "spp") != 0) { 539 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "spp"); 540 return; 541 } 542 543 if (parser_read_uint32(&p.n_subports_per_port, tokens[5]) != 0) { 544 snprintf(out, out_size, MSG_ARG_INVALID, "n_subports_per_port"); 545 return; 546 } 547 548 if (strcmp(tokens[6], "pps") != 0) { 549 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "spp"); 550 return; 551 } 552 553 if (parser_read_uint32(&p.n_pipes_per_subport, tokens[7]) != 0) { 554 snprintf(out, out_size, MSG_ARG_INVALID, "n_pipes_per_subport"); 555 return; 556 } 557 558 if (strcmp(tokens[8], "fo") != 0) { 559 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "fo"); 560 return; 561 } 562 563 if (parser_read_uint32(&p.frame_overhead, tokens[9]) != 0) { 564 snprintf(out, out_size, MSG_ARG_INVALID, "frame_overhead"); 565 return; 566 } 567 568 if (strcmp(tokens[10], "mtu") != 0) { 569 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "mtu"); 570 return; 571 } 572 573 if (parser_read_uint32(&p.mtu, tokens[11]) != 0) { 574 snprintf(out, out_size, MSG_ARG_INVALID, "mtu"); 575 return; 576 } 577 578 if (strcmp(tokens[12], "cpu") != 0) { 579 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "cpu"); 580 return; 581 } 582 583 if (parser_read_uint32(&p.cpu_id, tokens[13]) != 0) { 584 snprintf(out, out_size, MSG_ARG_INVALID, "cpu_id"); 585 return; 586 } 587 588 tmgr_port = tmgr_port_create(name, &p); 589 if (tmgr_port == NULL) { 590 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 591 return; 592 } 593 } 594 595 static const char cmd_tmgr_subport_help[] = 596 "tmgr <tmgr_name> subport <subport_id>\n" 597 " profile <subport_profile_id>\n"; 598 599 static void 600 cmd_tmgr_subport(char **tokens, 601 uint32_t n_tokens, 602 char *out, 603 size_t out_size) 604 { 605 uint32_t subport_id, subport_profile_id; 606 int status; 607 char *name; 608 609 if (n_tokens != 6) { 610 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 611 return; 612 } 613 614 name = tokens[1]; 615 616 if (parser_read_uint32(&subport_id, tokens[3]) != 0) { 617 snprintf(out, out_size, MSG_ARG_INVALID, "subport_id"); 618 return; 619 } 620 621 if (parser_read_uint32(&subport_profile_id, tokens[5]) != 0) { 622 snprintf(out, out_size, MSG_ARG_INVALID, "subport_profile_id"); 623 return; 624 } 625 626 status = tmgr_subport_config(name, subport_id, subport_profile_id); 627 if (status) { 628 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 629 return; 630 } 631 } 632 633 634 static const char cmd_tmgr_subport_pipe_help[] = 635 "tmgr <tmgr_name> subport <subport_id> pipe\n" 636 " from <pipe_id_first> to <pipe_id_last>\n" 637 " profile <pipe_profile_id>\n"; 638 639 static void 640 cmd_tmgr_subport_pipe(char **tokens, 641 uint32_t n_tokens, 642 char *out, 643 size_t out_size) 644 { 645 uint32_t subport_id, pipe_id_first, pipe_id_last, pipe_profile_id; 646 int status; 647 char *name; 648 649 if (n_tokens != 11) { 650 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 651 return; 652 } 653 654 name = tokens[1]; 655 656 if (parser_read_uint32(&subport_id, tokens[3]) != 0) { 657 snprintf(out, out_size, MSG_ARG_INVALID, "subport_id"); 658 return; 659 } 660 661 if (strcmp(tokens[4], "pipe") != 0) { 662 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pipe"); 663 return; 664 } 665 666 if (strcmp(tokens[5], "from") != 0) { 667 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "from"); 668 return; 669 } 670 671 if (parser_read_uint32(&pipe_id_first, tokens[6]) != 0) { 672 snprintf(out, out_size, MSG_ARG_INVALID, "pipe_id_first"); 673 return; 674 } 675 676 if (strcmp(tokens[7], "to") != 0) { 677 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "to"); 678 return; 679 } 680 681 if (parser_read_uint32(&pipe_id_last, tokens[8]) != 0) { 682 snprintf(out, out_size, MSG_ARG_INVALID, "pipe_id_last"); 683 return; 684 } 685 686 if (strcmp(tokens[9], "profile") != 0) { 687 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "profile"); 688 return; 689 } 690 691 if (parser_read_uint32(&pipe_profile_id, tokens[10]) != 0) { 692 snprintf(out, out_size, MSG_ARG_INVALID, "pipe_profile_id"); 693 return; 694 } 695 696 status = tmgr_pipe_config(name, subport_id, pipe_id_first, 697 pipe_id_last, pipe_profile_id); 698 if (status) { 699 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 700 return; 701 } 702 } 703 704 705 static const char cmd_tap_help[] = 706 "tap <tap_name>\n"; 707 708 static void 709 cmd_tap(char **tokens, 710 uint32_t n_tokens, 711 char *out, 712 size_t out_size) 713 { 714 char *name; 715 struct tap *tap; 716 717 if (n_tokens != 2) { 718 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 719 return; 720 } 721 722 name = tokens[1]; 723 724 tap = tap_create(name); 725 if (tap == NULL) { 726 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 727 return; 728 } 729 } 730 731 static const char cmd_kni_help[] = 732 "kni <kni_name>\n" 733 " link <link_name>\n" 734 " mempool <mempool_name>\n" 735 " [thread <thread_id>]\n"; 736 737 static void 738 cmd_kni(char **tokens, 739 uint32_t n_tokens, 740 char *out, 741 size_t out_size) 742 { 743 struct kni_params p; 744 char *name; 745 struct kni *kni; 746 747 memset(&p, 0, sizeof(p)); 748 if ((n_tokens != 6) && (n_tokens != 8)) { 749 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 750 return; 751 } 752 753 name = tokens[1]; 754 755 if (strcmp(tokens[2], "link") != 0) { 756 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "link"); 757 return; 758 } 759 760 p.link_name = tokens[3]; 761 762 if (strcmp(tokens[4], "mempool") != 0) { 763 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "mempool"); 764 return; 765 } 766 767 p.mempool_name = tokens[5]; 768 769 if (n_tokens == 8) { 770 if (strcmp(tokens[6], "thread") != 0) { 771 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "thread"); 772 return; 773 } 774 775 if (parser_read_uint32(&p.thread_id, tokens[7]) != 0) { 776 snprintf(out, out_size, MSG_ARG_INVALID, "thread_id"); 777 return; 778 } 779 780 p.force_bind = 1; 781 } else 782 p.force_bind = 0; 783 784 kni = kni_create(name, &p); 785 if (kni == NULL) { 786 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 787 return; 788 } 789 } 790 791 static const char cmd_cryptodev_help[] = 792 "cryptodev <cryptodev_name>\n" 793 " dev <device_name> | dev_id <device_id>\n" 794 " queue <n_queues> <queue_size>\n" 795 " max_sessions <n_sessions>"; 796 797 static void 798 cmd_cryptodev(char **tokens, 799 uint32_t n_tokens, 800 char *out, 801 size_t out_size) 802 { 803 struct cryptodev_params params; 804 char *name; 805 806 memset(¶ms, 0, sizeof(params)); 807 if (n_tokens != 9) { 808 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 809 return; 810 } 811 812 name = tokens[1]; 813 814 if (strcmp(tokens[2], "dev") == 0) 815 params.dev_name = tokens[3]; 816 else if (strcmp(tokens[2], "dev_id") == 0) { 817 if (parser_read_uint32(¶ms.dev_id, tokens[3]) < 0) { 818 snprintf(out, out_size, MSG_ARG_INVALID, 819 "dev_id"); 820 return; 821 } 822 } else { 823 snprintf(out, out_size, MSG_ARG_INVALID, 824 "cryptodev"); 825 return; 826 } 827 828 if (strcmp(tokens[4], "queue")) { 829 snprintf(out, out_size, MSG_ARG_NOT_FOUND, 830 "queue"); 831 return; 832 } 833 834 if (parser_read_uint32(¶ms.n_queues, tokens[5]) < 0) { 835 snprintf(out, out_size, MSG_ARG_INVALID, 836 "q"); 837 return; 838 } 839 840 if (parser_read_uint32(¶ms.queue_size, tokens[6]) < 0) { 841 snprintf(out, out_size, MSG_ARG_INVALID, 842 "queue_size"); 843 return; 844 } 845 846 if (strcmp(tokens[7], "max_sessions")) { 847 snprintf(out, out_size, MSG_ARG_NOT_FOUND, 848 "max_sessions"); 849 return; 850 } 851 852 if (parser_read_uint32(¶ms.session_pool_size, tokens[8]) < 0) { 853 snprintf(out, out_size, MSG_ARG_INVALID, 854 "queue_size"); 855 return; 856 } 857 858 if (cryptodev_create(name, ¶ms) == NULL) { 859 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 860 return; 861 } 862 } 863 864 static const char cmd_port_in_action_profile_help[] = 865 "port in action profile <profile_name>\n" 866 " [filter match | mismatch offset <key_offset> mask <key_mask> key <key_value> port <port_id>]\n" 867 " [balance offset <key_offset> mask <key_mask> port <port_id0> ... <port_id15>]\n"; 868 869 static void 870 cmd_port_in_action_profile(char **tokens, 871 uint32_t n_tokens, 872 char *out, 873 size_t out_size) 874 { 875 struct port_in_action_profile_params p; 876 struct port_in_action_profile *ap; 877 char *name; 878 uint32_t t0; 879 880 memset(&p, 0, sizeof(p)); 881 882 if (n_tokens < 5) { 883 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 884 return; 885 } 886 887 if (strcmp(tokens[1], "in") != 0) { 888 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "in"); 889 return; 890 } 891 892 if (strcmp(tokens[2], "action") != 0) { 893 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "action"); 894 return; 895 } 896 897 if (strcmp(tokens[3], "profile") != 0) { 898 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "profile"); 899 return; 900 } 901 902 name = tokens[4]; 903 904 t0 = 5; 905 906 if ((t0 < n_tokens) && (strcmp(tokens[t0], "filter") == 0)) { 907 uint32_t size; 908 909 if (n_tokens < t0 + 10) { 910 snprintf(out, out_size, MSG_ARG_MISMATCH, "port in action profile filter"); 911 return; 912 } 913 914 if (strcmp(tokens[t0 + 1], "match") == 0) 915 p.fltr.filter_on_match = 1; 916 else if (strcmp(tokens[t0 + 1], "mismatch") == 0) 917 p.fltr.filter_on_match = 0; 918 else { 919 snprintf(out, out_size, MSG_ARG_INVALID, "match or mismatch"); 920 return; 921 } 922 923 if (strcmp(tokens[t0 + 2], "offset") != 0) { 924 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset"); 925 return; 926 } 927 928 if (parser_read_uint32(&p.fltr.key_offset, tokens[t0 + 3]) != 0) { 929 snprintf(out, out_size, MSG_ARG_INVALID, "key_offset"); 930 return; 931 } 932 933 if (strcmp(tokens[t0 + 4], "mask") != 0) { 934 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "mask"); 935 return; 936 } 937 938 size = RTE_PORT_IN_ACTION_FLTR_KEY_SIZE; 939 if ((parse_hex_string(tokens[t0 + 5], p.fltr.key_mask, &size) != 0) || 940 (size != RTE_PORT_IN_ACTION_FLTR_KEY_SIZE)) { 941 snprintf(out, out_size, MSG_ARG_INVALID, "key_mask"); 942 return; 943 } 944 945 if (strcmp(tokens[t0 + 6], "key") != 0) { 946 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "key"); 947 return; 948 } 949 950 size = RTE_PORT_IN_ACTION_FLTR_KEY_SIZE; 951 if ((parse_hex_string(tokens[t0 + 7], p.fltr.key, &size) != 0) || 952 (size != RTE_PORT_IN_ACTION_FLTR_KEY_SIZE)) { 953 snprintf(out, out_size, MSG_ARG_INVALID, "key_value"); 954 return; 955 } 956 957 if (strcmp(tokens[t0 + 8], "port") != 0) { 958 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port"); 959 return; 960 } 961 962 if (parser_read_uint32(&p.fltr.port_id, tokens[t0 + 9]) != 0) { 963 snprintf(out, out_size, MSG_ARG_INVALID, "port_id"); 964 return; 965 } 966 967 p.action_mask |= 1LLU << RTE_PORT_IN_ACTION_FLTR; 968 t0 += 10; 969 } /* filter */ 970 971 if ((t0 < n_tokens) && (strcmp(tokens[t0], "balance") == 0)) { 972 uint32_t i; 973 974 if (n_tokens < t0 + 22) { 975 snprintf(out, out_size, MSG_ARG_MISMATCH, 976 "port in action profile balance"); 977 return; 978 } 979 980 if (strcmp(tokens[t0 + 1], "offset") != 0) { 981 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset"); 982 return; 983 } 984 985 if (parser_read_uint32(&p.lb.key_offset, tokens[t0 + 2]) != 0) { 986 snprintf(out, out_size, MSG_ARG_INVALID, "key_offset"); 987 return; 988 } 989 990 if (strcmp(tokens[t0 + 3], "mask") != 0) { 991 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "mask"); 992 return; 993 } 994 995 p.lb.key_size = RTE_PORT_IN_ACTION_LB_KEY_SIZE_MAX; 996 if (parse_hex_string(tokens[t0 + 4], p.lb.key_mask, &p.lb.key_size) != 0) { 997 snprintf(out, out_size, MSG_ARG_INVALID, "key_mask"); 998 return; 999 } 1000 1001 if (strcmp(tokens[t0 + 5], "port") != 0) { 1002 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port"); 1003 return; 1004 } 1005 1006 for (i = 0; i < 16; i++) 1007 if (parser_read_uint32(&p.lb.port_id[i], tokens[t0 + 6 + i]) != 0) { 1008 snprintf(out, out_size, MSG_ARG_INVALID, "port_id"); 1009 return; 1010 } 1011 1012 p.action_mask |= 1LLU << RTE_PORT_IN_ACTION_LB; 1013 t0 += 22; 1014 } /* balance */ 1015 1016 if (t0 < n_tokens) { 1017 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 1018 return; 1019 } 1020 1021 ap = port_in_action_profile_create(name, &p); 1022 if (ap == NULL) { 1023 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 1024 return; 1025 } 1026 } 1027 1028 1029 static const char cmd_table_action_profile_help[] = 1030 "table action profile <profile_name>\n" 1031 " ipv4 | ipv6\n" 1032 " offset <ip_offset>\n" 1033 " fwd\n" 1034 " [balance offset <key_offset> mask <key_mask> outoffset <out_offset>]\n" 1035 " [meter srtcm | trtcm\n" 1036 " tc <n_tc>\n" 1037 " stats none | pkts | bytes | both]\n" 1038 " [tm spp <n_subports_per_port> pps <n_pipes_per_subport>]\n" 1039 " [encap ether | vlan | qinq | mpls | pppoe | qinq_pppoe \n" 1040 " vxlan offset <ether_offset> ipv4 | ipv6 vlan on | off]\n" 1041 " [nat src | dst\n" 1042 " proto udp | tcp]\n" 1043 " [ttl drop | fwd\n" 1044 " stats none | pkts]\n" 1045 " [stats pkts | bytes | both]\n" 1046 " [time]\n" 1047 " [sym_crypto dev <CRYPTODEV_NAME> offset <op_offset>]\n" 1048 " [tag]\n" 1049 " [decap]\n"; 1050 1051 static void 1052 cmd_table_action_profile(char **tokens, 1053 uint32_t n_tokens, 1054 char *out, 1055 size_t out_size) 1056 { 1057 struct table_action_profile_params p; 1058 struct table_action_profile *ap; 1059 char *name; 1060 uint32_t t0; 1061 1062 memset(&p, 0, sizeof(p)); 1063 1064 if (n_tokens < 8) { 1065 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 1066 return; 1067 } 1068 1069 if (strcmp(tokens[1], "action") != 0) { 1070 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "action"); 1071 return; 1072 } 1073 1074 if (strcmp(tokens[2], "profile") != 0) { 1075 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "profile"); 1076 return; 1077 } 1078 1079 name = tokens[3]; 1080 1081 if (strcmp(tokens[4], "ipv4") == 0) 1082 p.common.ip_version = 1; 1083 else if (strcmp(tokens[4], "ipv6") == 0) 1084 p.common.ip_version = 0; 1085 else { 1086 snprintf(out, out_size, MSG_ARG_INVALID, "ipv4 or ipv6"); 1087 return; 1088 } 1089 1090 if (strcmp(tokens[5], "offset") != 0) { 1091 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset"); 1092 return; 1093 } 1094 1095 if (parser_read_uint32(&p.common.ip_offset, tokens[6]) != 0) { 1096 snprintf(out, out_size, MSG_ARG_INVALID, "ip_offset"); 1097 return; 1098 } 1099 1100 if (strcmp(tokens[7], "fwd") != 0) { 1101 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "fwd"); 1102 return; 1103 } 1104 1105 p.action_mask |= 1LLU << RTE_TABLE_ACTION_FWD; 1106 1107 t0 = 8; 1108 if ((t0 < n_tokens) && (strcmp(tokens[t0], "balance") == 0)) { 1109 if (n_tokens < t0 + 7) { 1110 snprintf(out, out_size, MSG_ARG_MISMATCH, "table action profile balance"); 1111 return; 1112 } 1113 1114 if (strcmp(tokens[t0 + 1], "offset") != 0) { 1115 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset"); 1116 return; 1117 } 1118 1119 if (parser_read_uint32(&p.lb.key_offset, tokens[t0 + 2]) != 0) { 1120 snprintf(out, out_size, MSG_ARG_INVALID, "key_offset"); 1121 return; 1122 } 1123 1124 if (strcmp(tokens[t0 + 3], "mask") != 0) { 1125 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "mask"); 1126 return; 1127 } 1128 1129 p.lb.key_size = RTE_PORT_IN_ACTION_LB_KEY_SIZE_MAX; 1130 if (parse_hex_string(tokens[t0 + 4], p.lb.key_mask, &p.lb.key_size) != 0) { 1131 snprintf(out, out_size, MSG_ARG_INVALID, "key_mask"); 1132 return; 1133 } 1134 1135 if (strcmp(tokens[t0 + 5], "outoffset") != 0) { 1136 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "outoffset"); 1137 return; 1138 } 1139 1140 if (parser_read_uint32(&p.lb.out_offset, tokens[t0 + 6]) != 0) { 1141 snprintf(out, out_size, MSG_ARG_INVALID, "out_offset"); 1142 return; 1143 } 1144 1145 p.action_mask |= 1LLU << RTE_TABLE_ACTION_LB; 1146 t0 += 7; 1147 } /* balance */ 1148 1149 if ((t0 < n_tokens) && (strcmp(tokens[t0], "meter") == 0)) { 1150 if (n_tokens < t0 + 6) { 1151 snprintf(out, out_size, MSG_ARG_MISMATCH, 1152 "table action profile meter"); 1153 return; 1154 } 1155 1156 if (strcmp(tokens[t0 + 1], "srtcm") == 0) 1157 p.mtr.alg = RTE_TABLE_ACTION_METER_SRTCM; 1158 else if (strcmp(tokens[t0 + 1], "trtcm") == 0) 1159 p.mtr.alg = RTE_TABLE_ACTION_METER_TRTCM; 1160 else { 1161 snprintf(out, out_size, MSG_ARG_NOT_FOUND, 1162 "srtcm or trtcm"); 1163 return; 1164 } 1165 1166 if (strcmp(tokens[t0 + 2], "tc") != 0) { 1167 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc"); 1168 return; 1169 } 1170 1171 if (parser_read_uint32(&p.mtr.n_tc, tokens[t0 + 3]) != 0) { 1172 snprintf(out, out_size, MSG_ARG_INVALID, "n_tc"); 1173 return; 1174 } 1175 1176 if (strcmp(tokens[t0 + 4], "stats") != 0) { 1177 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "stats"); 1178 return; 1179 } 1180 1181 if (strcmp(tokens[t0 + 5], "none") == 0) { 1182 p.mtr.n_packets_enabled = 0; 1183 p.mtr.n_bytes_enabled = 0; 1184 } else if (strcmp(tokens[t0 + 5], "pkts") == 0) { 1185 p.mtr.n_packets_enabled = 1; 1186 p.mtr.n_bytes_enabled = 0; 1187 } else if (strcmp(tokens[t0 + 5], "bytes") == 0) { 1188 p.mtr.n_packets_enabled = 0; 1189 p.mtr.n_bytes_enabled = 1; 1190 } else if (strcmp(tokens[t0 + 5], "both") == 0) { 1191 p.mtr.n_packets_enabled = 1; 1192 p.mtr.n_bytes_enabled = 1; 1193 } else { 1194 snprintf(out, out_size, MSG_ARG_NOT_FOUND, 1195 "none or pkts or bytes or both"); 1196 return; 1197 } 1198 1199 p.action_mask |= 1LLU << RTE_TABLE_ACTION_MTR; 1200 t0 += 6; 1201 } /* meter */ 1202 1203 if ((t0 < n_tokens) && (strcmp(tokens[t0], "tm") == 0)) { 1204 if (n_tokens < t0 + 5) { 1205 snprintf(out, out_size, MSG_ARG_MISMATCH, 1206 "table action profile tm"); 1207 return; 1208 } 1209 1210 if (strcmp(tokens[t0 + 1], "spp") != 0) { 1211 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "spp"); 1212 return; 1213 } 1214 1215 if (parser_read_uint32(&p.tm.n_subports_per_port, 1216 tokens[t0 + 2]) != 0) { 1217 snprintf(out, out_size, MSG_ARG_INVALID, 1218 "n_subports_per_port"); 1219 return; 1220 } 1221 1222 if (strcmp(tokens[t0 + 3], "pps") != 0) { 1223 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pps"); 1224 return; 1225 } 1226 1227 if (parser_read_uint32(&p.tm.n_pipes_per_subport, 1228 tokens[t0 + 4]) != 0) { 1229 snprintf(out, out_size, MSG_ARG_INVALID, 1230 "n_pipes_per_subport"); 1231 return; 1232 } 1233 1234 p.action_mask |= 1LLU << RTE_TABLE_ACTION_TM; 1235 t0 += 5; 1236 } /* tm */ 1237 1238 if ((t0 < n_tokens) && (strcmp(tokens[t0], "encap") == 0)) { 1239 uint32_t n_extra_tokens = 0; 1240 1241 if (n_tokens < t0 + 2) { 1242 snprintf(out, out_size, MSG_ARG_MISMATCH, 1243 "action profile encap"); 1244 return; 1245 } 1246 1247 if (strcmp(tokens[t0 + 1], "ether") == 0) 1248 p.encap.encap_mask = 1LLU << RTE_TABLE_ACTION_ENCAP_ETHER; 1249 else if (strcmp(tokens[t0 + 1], "vlan") == 0) 1250 p.encap.encap_mask = 1LLU << RTE_TABLE_ACTION_ENCAP_VLAN; 1251 else if (strcmp(tokens[t0 + 1], "qinq") == 0) 1252 p.encap.encap_mask = 1LLU << RTE_TABLE_ACTION_ENCAP_QINQ; 1253 else if (strcmp(tokens[t0 + 1], "mpls") == 0) 1254 p.encap.encap_mask = 1LLU << RTE_TABLE_ACTION_ENCAP_MPLS; 1255 else if (strcmp(tokens[t0 + 1], "pppoe") == 0) 1256 p.encap.encap_mask = 1LLU << RTE_TABLE_ACTION_ENCAP_PPPOE; 1257 else if (strcmp(tokens[t0 + 1], "vxlan") == 0) { 1258 if (n_tokens < t0 + 2 + 5) { 1259 snprintf(out, out_size, MSG_ARG_MISMATCH, 1260 "action profile encap vxlan"); 1261 return; 1262 } 1263 1264 if (strcmp(tokens[t0 + 2], "offset") != 0) { 1265 snprintf(out, out_size, MSG_ARG_NOT_FOUND, 1266 "vxlan: offset"); 1267 return; 1268 } 1269 1270 if (parser_read_uint32(&p.encap.vxlan.data_offset, 1271 tokens[t0 + 2 + 1]) != 0) { 1272 snprintf(out, out_size, MSG_ARG_INVALID, 1273 "vxlan: ether_offset"); 1274 return; 1275 } 1276 1277 if (strcmp(tokens[t0 + 2 + 2], "ipv4") == 0) 1278 p.encap.vxlan.ip_version = 1; 1279 else if (strcmp(tokens[t0 + 2 + 2], "ipv6") == 0) 1280 p.encap.vxlan.ip_version = 0; 1281 else { 1282 snprintf(out, out_size, MSG_ARG_INVALID, 1283 "vxlan: ipv4 or ipv6"); 1284 return; 1285 } 1286 1287 if (strcmp(tokens[t0 + 2 + 3], "vlan") != 0) { 1288 snprintf(out, out_size, MSG_ARG_NOT_FOUND, 1289 "vxlan: vlan"); 1290 return; 1291 } 1292 1293 if (strcmp(tokens[t0 + 2 + 4], "on") == 0) 1294 p.encap.vxlan.vlan = 1; 1295 else if (strcmp(tokens[t0 + 2 + 4], "off") == 0) 1296 p.encap.vxlan.vlan = 0; 1297 else { 1298 snprintf(out, out_size, MSG_ARG_INVALID, 1299 "vxlan: on or off"); 1300 return; 1301 } 1302 1303 p.encap.encap_mask = 1LLU << RTE_TABLE_ACTION_ENCAP_VXLAN; 1304 n_extra_tokens = 5; 1305 } else if (strcmp(tokens[t0 + 1], "qinq_pppoe") == 0) 1306 p.encap.encap_mask = 1307 1LLU << RTE_TABLE_ACTION_ENCAP_QINQ_PPPOE; 1308 else { 1309 snprintf(out, out_size, MSG_ARG_MISMATCH, "encap"); 1310 return; 1311 } 1312 1313 p.action_mask |= 1LLU << RTE_TABLE_ACTION_ENCAP; 1314 t0 += 2 + n_extra_tokens; 1315 } /* encap */ 1316 1317 if ((t0 < n_tokens) && (strcmp(tokens[t0], "nat") == 0)) { 1318 if (n_tokens < t0 + 4) { 1319 snprintf(out, out_size, MSG_ARG_MISMATCH, 1320 "table action profile nat"); 1321 return; 1322 } 1323 1324 if (strcmp(tokens[t0 + 1], "src") == 0) 1325 p.nat.source_nat = 1; 1326 else if (strcmp(tokens[t0 + 1], "dst") == 0) 1327 p.nat.source_nat = 0; 1328 else { 1329 snprintf(out, out_size, MSG_ARG_NOT_FOUND, 1330 "src or dst"); 1331 return; 1332 } 1333 1334 if (strcmp(tokens[t0 + 2], "proto") != 0) { 1335 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "proto"); 1336 return; 1337 } 1338 1339 if (strcmp(tokens[t0 + 3], "tcp") == 0) 1340 p.nat.proto = 0x06; 1341 else if (strcmp(tokens[t0 + 3], "udp") == 0) 1342 p.nat.proto = 0x11; 1343 else { 1344 snprintf(out, out_size, MSG_ARG_NOT_FOUND, 1345 "tcp or udp"); 1346 return; 1347 } 1348 1349 p.action_mask |= 1LLU << RTE_TABLE_ACTION_NAT; 1350 t0 += 4; 1351 } /* nat */ 1352 1353 if ((t0 < n_tokens) && (strcmp(tokens[t0], "ttl") == 0)) { 1354 if (n_tokens < t0 + 4) { 1355 snprintf(out, out_size, MSG_ARG_MISMATCH, 1356 "table action profile ttl"); 1357 return; 1358 } 1359 1360 if (strcmp(tokens[t0 + 1], "drop") == 0) 1361 p.ttl.drop = 1; 1362 else if (strcmp(tokens[t0 + 1], "fwd") == 0) 1363 p.ttl.drop = 0; 1364 else { 1365 snprintf(out, out_size, MSG_ARG_NOT_FOUND, 1366 "drop or fwd"); 1367 return; 1368 } 1369 1370 if (strcmp(tokens[t0 + 2], "stats") != 0) { 1371 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "stats"); 1372 return; 1373 } 1374 1375 if (strcmp(tokens[t0 + 3], "none") == 0) 1376 p.ttl.n_packets_enabled = 0; 1377 else if (strcmp(tokens[t0 + 3], "pkts") == 0) 1378 p.ttl.n_packets_enabled = 1; 1379 else { 1380 snprintf(out, out_size, MSG_ARG_NOT_FOUND, 1381 "none or pkts"); 1382 return; 1383 } 1384 1385 p.action_mask |= 1LLU << RTE_TABLE_ACTION_TTL; 1386 t0 += 4; 1387 } /* ttl */ 1388 1389 if ((t0 < n_tokens) && (strcmp(tokens[t0], "stats") == 0)) { 1390 if (n_tokens < t0 + 2) { 1391 snprintf(out, out_size, MSG_ARG_MISMATCH, 1392 "table action profile stats"); 1393 return; 1394 } 1395 1396 if (strcmp(tokens[t0 + 1], "pkts") == 0) { 1397 p.stats.n_packets_enabled = 1; 1398 p.stats.n_bytes_enabled = 0; 1399 } else if (strcmp(tokens[t0 + 1], "bytes") == 0) { 1400 p.stats.n_packets_enabled = 0; 1401 p.stats.n_bytes_enabled = 1; 1402 } else if (strcmp(tokens[t0 + 1], "both") == 0) { 1403 p.stats.n_packets_enabled = 1; 1404 p.stats.n_bytes_enabled = 1; 1405 } else { 1406 snprintf(out, out_size, MSG_ARG_NOT_FOUND, 1407 "pkts or bytes or both"); 1408 return; 1409 } 1410 1411 p.action_mask |= 1LLU << RTE_TABLE_ACTION_STATS; 1412 t0 += 2; 1413 } /* stats */ 1414 1415 if ((t0 < n_tokens) && (strcmp(tokens[t0], "time") == 0)) { 1416 p.action_mask |= 1LLU << RTE_TABLE_ACTION_TIME; 1417 t0 += 1; 1418 } /* time */ 1419 1420 if ((t0 < n_tokens) && (strcmp(tokens[t0], "sym_crypto") == 0)) { 1421 struct cryptodev *cryptodev; 1422 1423 if (n_tokens < t0 + 5 || 1424 strcmp(tokens[t0 + 1], "dev") || 1425 strcmp(tokens[t0 + 3], "offset")) { 1426 snprintf(out, out_size, MSG_ARG_MISMATCH, 1427 "table action profile sym_crypto"); 1428 return; 1429 } 1430 1431 cryptodev = cryptodev_find(tokens[t0 + 2]); 1432 if (cryptodev == NULL) { 1433 snprintf(out, out_size, MSG_ARG_INVALID, 1434 "table action profile sym_crypto"); 1435 return; 1436 } 1437 1438 p.sym_crypto.cryptodev_id = cryptodev->dev_id; 1439 1440 if (parser_read_uint32(&p.sym_crypto.op_offset, 1441 tokens[t0 + 4]) != 0) { 1442 snprintf(out, out_size, MSG_ARG_INVALID, 1443 "table action profile sym_crypto"); 1444 return; 1445 } 1446 1447 p.sym_crypto.mp_create = cryptodev->mp_create; 1448 p.sym_crypto.mp_init = cryptodev->mp_init; 1449 1450 p.action_mask |= 1LLU << RTE_TABLE_ACTION_SYM_CRYPTO; 1451 1452 t0 += 5; 1453 } /* sym_crypto */ 1454 1455 if ((t0 < n_tokens) && (strcmp(tokens[t0], "tag") == 0)) { 1456 p.action_mask |= 1LLU << RTE_TABLE_ACTION_TAG; 1457 t0 += 1; 1458 } /* tag */ 1459 1460 if ((t0 < n_tokens) && (strcmp(tokens[t0], "decap") == 0)) { 1461 p.action_mask |= 1LLU << RTE_TABLE_ACTION_DECAP; 1462 t0 += 1; 1463 } /* decap */ 1464 1465 if (t0 < n_tokens) { 1466 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 1467 return; 1468 } 1469 1470 ap = table_action_profile_create(name, &p); 1471 if (ap == NULL) { 1472 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 1473 return; 1474 } 1475 } 1476 1477 static const char cmd_pipeline_help[] = 1478 "pipeline <pipeline_name>\n" 1479 " period <timer_period_ms>\n" 1480 " offset_port_id <offset_port_id>\n" 1481 " cpu <cpu_id>\n"; 1482 1483 static void 1484 cmd_pipeline(char **tokens, 1485 uint32_t n_tokens, 1486 char *out, 1487 size_t out_size) 1488 { 1489 struct pipeline_params p; 1490 char *name; 1491 struct pipeline *pipeline; 1492 1493 if (n_tokens != 8) { 1494 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 1495 return; 1496 } 1497 1498 name = tokens[1]; 1499 1500 if (strcmp(tokens[2], "period") != 0) { 1501 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "period"); 1502 return; 1503 } 1504 1505 if (parser_read_uint32(&p.timer_period_ms, tokens[3]) != 0) { 1506 snprintf(out, out_size, MSG_ARG_INVALID, "timer_period_ms"); 1507 return; 1508 } 1509 1510 if (strcmp(tokens[4], "offset_port_id") != 0) { 1511 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset_port_id"); 1512 return; 1513 } 1514 1515 if (parser_read_uint32(&p.offset_port_id, tokens[5]) != 0) { 1516 snprintf(out, out_size, MSG_ARG_INVALID, "offset_port_id"); 1517 return; 1518 } 1519 1520 if (strcmp(tokens[6], "cpu") != 0) { 1521 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "cpu"); 1522 return; 1523 } 1524 1525 if (parser_read_uint32(&p.cpu_id, tokens[7]) != 0) { 1526 snprintf(out, out_size, MSG_ARG_INVALID, "cpu_id"); 1527 return; 1528 } 1529 1530 pipeline = pipeline_create(name, &p); 1531 if (pipeline == NULL) { 1532 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 1533 return; 1534 } 1535 } 1536 1537 static const char cmd_pipeline_port_in_help[] = 1538 "pipeline <pipeline_name> port in\n" 1539 " bsz <burst_size>\n" 1540 " link <link_name> rxq <queue_id>\n" 1541 " | swq <swq_name>\n" 1542 " | tmgr <tmgr_name>\n" 1543 " | tap <tap_name> mempool <mempool_name> mtu <mtu>\n" 1544 " | kni <kni_name>\n" 1545 " | source mempool <mempool_name> file <file_name> bpp <n_bytes_per_pkt>\n" 1546 " | cryptodev <cryptodev_name> rxq <queue_id>\n" 1547 " [action <port_in_action_profile_name>]\n" 1548 " [disabled]\n"; 1549 1550 static void 1551 cmd_pipeline_port_in(char **tokens, 1552 uint32_t n_tokens, 1553 char *out, 1554 size_t out_size) 1555 { 1556 struct port_in_params p; 1557 char *pipeline_name; 1558 uint32_t t0; 1559 int enabled, status; 1560 1561 if (n_tokens < 7) { 1562 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 1563 return; 1564 } 1565 1566 pipeline_name = tokens[1]; 1567 1568 if (strcmp(tokens[2], "port") != 0) { 1569 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port"); 1570 return; 1571 } 1572 1573 if (strcmp(tokens[3], "in") != 0) { 1574 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "in"); 1575 return; 1576 } 1577 1578 if (strcmp(tokens[4], "bsz") != 0) { 1579 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "bsz"); 1580 return; 1581 } 1582 1583 if (parser_read_uint32(&p.burst_size, tokens[5]) != 0) { 1584 snprintf(out, out_size, MSG_ARG_INVALID, "burst_size"); 1585 return; 1586 } 1587 1588 t0 = 6; 1589 1590 if (strcmp(tokens[t0], "link") == 0) { 1591 if (n_tokens < t0 + 4) { 1592 snprintf(out, out_size, MSG_ARG_MISMATCH, 1593 "pipeline port in link"); 1594 return; 1595 } 1596 1597 p.type = PORT_IN_RXQ; 1598 1599 p.dev_name = tokens[t0 + 1]; 1600 1601 if (strcmp(tokens[t0 + 2], "rxq") != 0) { 1602 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rxq"); 1603 return; 1604 } 1605 1606 if (parser_read_uint16(&p.rxq.queue_id, tokens[t0 + 3]) != 0) { 1607 snprintf(out, out_size, MSG_ARG_INVALID, 1608 "queue_id"); 1609 return; 1610 } 1611 t0 += 4; 1612 } else if (strcmp(tokens[t0], "swq") == 0) { 1613 if (n_tokens < t0 + 2) { 1614 snprintf(out, out_size, MSG_ARG_MISMATCH, 1615 "pipeline port in swq"); 1616 return; 1617 } 1618 1619 p.type = PORT_IN_SWQ; 1620 1621 p.dev_name = tokens[t0 + 1]; 1622 1623 t0 += 2; 1624 } else if (strcmp(tokens[t0], "tmgr") == 0) { 1625 if (n_tokens < t0 + 2) { 1626 snprintf(out, out_size, MSG_ARG_MISMATCH, 1627 "pipeline port in tmgr"); 1628 return; 1629 } 1630 1631 p.type = PORT_IN_TMGR; 1632 1633 p.dev_name = tokens[t0 + 1]; 1634 1635 t0 += 2; 1636 } else if (strcmp(tokens[t0], "tap") == 0) { 1637 if (n_tokens < t0 + 6) { 1638 snprintf(out, out_size, MSG_ARG_MISMATCH, 1639 "pipeline port in tap"); 1640 return; 1641 } 1642 1643 p.type = PORT_IN_TAP; 1644 1645 p.dev_name = tokens[t0 + 1]; 1646 1647 if (strcmp(tokens[t0 + 2], "mempool") != 0) { 1648 snprintf(out, out_size, MSG_ARG_NOT_FOUND, 1649 "mempool"); 1650 return; 1651 } 1652 1653 p.tap.mempool_name = tokens[t0 + 3]; 1654 1655 if (strcmp(tokens[t0 + 4], "mtu") != 0) { 1656 snprintf(out, out_size, MSG_ARG_NOT_FOUND, 1657 "mtu"); 1658 return; 1659 } 1660 1661 if (parser_read_uint32(&p.tap.mtu, tokens[t0 + 5]) != 0) { 1662 snprintf(out, out_size, MSG_ARG_INVALID, "mtu"); 1663 return; 1664 } 1665 1666 t0 += 6; 1667 } else if (strcmp(tokens[t0], "kni") == 0) { 1668 if (n_tokens < t0 + 2) { 1669 snprintf(out, out_size, MSG_ARG_MISMATCH, 1670 "pipeline port in kni"); 1671 return; 1672 } 1673 1674 p.type = PORT_IN_KNI; 1675 1676 p.dev_name = tokens[t0 + 1]; 1677 1678 t0 += 2; 1679 } else if (strcmp(tokens[t0], "source") == 0) { 1680 if (n_tokens < t0 + 6) { 1681 snprintf(out, out_size, MSG_ARG_MISMATCH, 1682 "pipeline port in source"); 1683 return; 1684 } 1685 1686 p.type = PORT_IN_SOURCE; 1687 1688 p.dev_name = NULL; 1689 1690 if (strcmp(tokens[t0 + 1], "mempool") != 0) { 1691 snprintf(out, out_size, MSG_ARG_NOT_FOUND, 1692 "mempool"); 1693 return; 1694 } 1695 1696 p.source.mempool_name = tokens[t0 + 2]; 1697 1698 if (strcmp(tokens[t0 + 3], "file") != 0) { 1699 snprintf(out, out_size, MSG_ARG_NOT_FOUND, 1700 "file"); 1701 return; 1702 } 1703 1704 p.source.file_name = tokens[t0 + 4]; 1705 1706 if (strcmp(tokens[t0 + 5], "bpp") != 0) { 1707 snprintf(out, out_size, MSG_ARG_NOT_FOUND, 1708 "bpp"); 1709 return; 1710 } 1711 1712 if (parser_read_uint32(&p.source.n_bytes_per_pkt, tokens[t0 + 6]) != 0) { 1713 snprintf(out, out_size, MSG_ARG_INVALID, 1714 "n_bytes_per_pkt"); 1715 return; 1716 } 1717 1718 t0 += 7; 1719 } else if (strcmp(tokens[t0], "cryptodev") == 0) { 1720 if (n_tokens < t0 + 3) { 1721 snprintf(out, out_size, MSG_ARG_MISMATCH, 1722 "pipeline port in cryptodev"); 1723 return; 1724 } 1725 1726 p.type = PORT_IN_CRYPTODEV; 1727 1728 p.dev_name = tokens[t0 + 1]; 1729 if (parser_read_uint16(&p.rxq.queue_id, tokens[t0 + 3]) != 0) { 1730 snprintf(out, out_size, MSG_ARG_INVALID, 1731 "rxq"); 1732 return; 1733 } 1734 1735 p.cryptodev.arg_callback = NULL; 1736 p.cryptodev.f_callback = NULL; 1737 1738 t0 += 4; 1739 } else { 1740 snprintf(out, out_size, MSG_ARG_INVALID, tokens[0]); 1741 return; 1742 } 1743 1744 p.action_profile_name = NULL; 1745 if ((n_tokens > t0) && (strcmp(tokens[t0], "action") == 0)) { 1746 if (n_tokens < t0 + 2) { 1747 snprintf(out, out_size, MSG_ARG_MISMATCH, "action"); 1748 return; 1749 } 1750 1751 p.action_profile_name = tokens[t0 + 1]; 1752 1753 t0 += 2; 1754 } 1755 1756 enabled = 1; 1757 if ((n_tokens > t0) && 1758 (strcmp(tokens[t0], "disabled") == 0)) { 1759 enabled = 0; 1760 1761 t0 += 1; 1762 } 1763 1764 if (n_tokens != t0) { 1765 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 1766 return; 1767 } 1768 1769 status = pipeline_port_in_create(pipeline_name, 1770 &p, enabled); 1771 if (status) { 1772 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 1773 return; 1774 } 1775 } 1776 1777 static const char cmd_pipeline_port_out_help[] = 1778 "pipeline <pipeline_name> port out\n" 1779 " bsz <burst_size>\n" 1780 " link <link_name> txq <txq_id>\n" 1781 " | swq <swq_name>\n" 1782 " | tmgr <tmgr_name>\n" 1783 " | tap <tap_name>\n" 1784 " | kni <kni_name>\n" 1785 " | sink [file <file_name> pkts <max_n_pkts>]\n" 1786 " | cryptodev <cryptodev_name> txq <txq_id> offset <crypto_op_offset>\n"; 1787 1788 static void 1789 cmd_pipeline_port_out(char **tokens, 1790 uint32_t n_tokens, 1791 char *out, 1792 size_t out_size) 1793 { 1794 struct port_out_params p; 1795 char *pipeline_name; 1796 int status; 1797 1798 memset(&p, 0, sizeof(p)); 1799 1800 if (n_tokens < 7) { 1801 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 1802 return; 1803 } 1804 1805 pipeline_name = tokens[1]; 1806 1807 if (strcmp(tokens[2], "port") != 0) { 1808 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port"); 1809 return; 1810 } 1811 1812 if (strcmp(tokens[3], "out") != 0) { 1813 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "out"); 1814 return; 1815 } 1816 1817 if (strcmp(tokens[4], "bsz") != 0) { 1818 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "bsz"); 1819 return; 1820 } 1821 1822 if (parser_read_uint32(&p.burst_size, tokens[5]) != 0) { 1823 snprintf(out, out_size, MSG_ARG_INVALID, "burst_size"); 1824 return; 1825 } 1826 1827 if (strcmp(tokens[6], "link") == 0) { 1828 if (n_tokens != 10) { 1829 snprintf(out, out_size, MSG_ARG_MISMATCH, 1830 "pipeline port out link"); 1831 return; 1832 } 1833 1834 p.type = PORT_OUT_TXQ; 1835 1836 p.dev_name = tokens[7]; 1837 1838 if (strcmp(tokens[8], "txq") != 0) { 1839 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "txq"); 1840 return; 1841 } 1842 1843 if (parser_read_uint16(&p.txq.queue_id, tokens[9]) != 0) { 1844 snprintf(out, out_size, MSG_ARG_INVALID, "queue_id"); 1845 return; 1846 } 1847 } else if (strcmp(tokens[6], "swq") == 0) { 1848 if (n_tokens != 8) { 1849 snprintf(out, out_size, MSG_ARG_MISMATCH, 1850 "pipeline port out swq"); 1851 return; 1852 } 1853 1854 p.type = PORT_OUT_SWQ; 1855 1856 p.dev_name = tokens[7]; 1857 } else if (strcmp(tokens[6], "tmgr") == 0) { 1858 if (n_tokens != 8) { 1859 snprintf(out, out_size, MSG_ARG_MISMATCH, 1860 "pipeline port out tmgr"); 1861 return; 1862 } 1863 1864 p.type = PORT_OUT_TMGR; 1865 1866 p.dev_name = tokens[7]; 1867 } else if (strcmp(tokens[6], "tap") == 0) { 1868 if (n_tokens != 8) { 1869 snprintf(out, out_size, MSG_ARG_MISMATCH, 1870 "pipeline port out tap"); 1871 return; 1872 } 1873 1874 p.type = PORT_OUT_TAP; 1875 1876 p.dev_name = tokens[7]; 1877 } else if (strcmp(tokens[6], "kni") == 0) { 1878 if (n_tokens != 8) { 1879 snprintf(out, out_size, MSG_ARG_MISMATCH, 1880 "pipeline port out kni"); 1881 return; 1882 } 1883 1884 p.type = PORT_OUT_KNI; 1885 1886 p.dev_name = tokens[7]; 1887 } else if (strcmp(tokens[6], "sink") == 0) { 1888 if ((n_tokens != 7) && (n_tokens != 11)) { 1889 snprintf(out, out_size, MSG_ARG_MISMATCH, 1890 "pipeline port out sink"); 1891 return; 1892 } 1893 1894 p.type = PORT_OUT_SINK; 1895 1896 p.dev_name = NULL; 1897 1898 if (n_tokens == 7) { 1899 p.sink.file_name = NULL; 1900 p.sink.max_n_pkts = 0; 1901 } else { 1902 if (strcmp(tokens[7], "file") != 0) { 1903 snprintf(out, out_size, MSG_ARG_NOT_FOUND, 1904 "file"); 1905 return; 1906 } 1907 1908 p.sink.file_name = tokens[8]; 1909 1910 if (strcmp(tokens[9], "pkts") != 0) { 1911 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pkts"); 1912 return; 1913 } 1914 1915 if (parser_read_uint32(&p.sink.max_n_pkts, tokens[10]) != 0) { 1916 snprintf(out, out_size, MSG_ARG_INVALID, "max_n_pkts"); 1917 return; 1918 } 1919 } 1920 1921 } else if (strcmp(tokens[6], "cryptodev") == 0) { 1922 if (n_tokens != 12) { 1923 snprintf(out, out_size, MSG_ARG_MISMATCH, 1924 "pipeline port out cryptodev"); 1925 return; 1926 } 1927 1928 p.type = PORT_OUT_CRYPTODEV; 1929 1930 p.dev_name = tokens[7]; 1931 1932 if (strcmp(tokens[8], "txq")) { 1933 snprintf(out, out_size, MSG_ARG_MISMATCH, 1934 "pipeline port out cryptodev"); 1935 return; 1936 } 1937 1938 if (parser_read_uint16(&p.cryptodev.queue_id, tokens[9]) 1939 != 0) { 1940 snprintf(out, out_size, MSG_ARG_INVALID, "queue_id"); 1941 return; 1942 } 1943 1944 if (strcmp(tokens[10], "offset")) { 1945 snprintf(out, out_size, MSG_ARG_MISMATCH, 1946 "pipeline port out cryptodev"); 1947 return; 1948 } 1949 1950 if (parser_read_uint32(&p.cryptodev.op_offset, tokens[11]) 1951 != 0) { 1952 snprintf(out, out_size, MSG_ARG_INVALID, "queue_id"); 1953 return; 1954 } 1955 } else { 1956 snprintf(out, out_size, MSG_ARG_INVALID, tokens[0]); 1957 return; 1958 } 1959 1960 status = pipeline_port_out_create(pipeline_name, &p); 1961 if (status) { 1962 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 1963 return; 1964 } 1965 } 1966 1967 static const char cmd_pipeline_table_help[] = 1968 "pipeline <pipeline_name> table\n" 1969 " match\n" 1970 " acl\n" 1971 " ipv4 | ipv6\n" 1972 " offset <ip_header_offset>\n" 1973 " size <n_rules>\n" 1974 " | array\n" 1975 " offset <key_offset>\n" 1976 " size <n_keys>\n" 1977 " | hash\n" 1978 " ext | lru\n" 1979 " key <key_size>\n" 1980 " mask <key_mask>\n" 1981 " offset <key_offset>\n" 1982 " buckets <n_buckets>\n" 1983 " size <n_keys>\n" 1984 " | lpm\n" 1985 " ipv4 | ipv6\n" 1986 " offset <ip_header_offset>\n" 1987 " size <n_rules>\n" 1988 " | stub\n" 1989 " [action <table_action_profile_name>]\n"; 1990 1991 static void 1992 cmd_pipeline_table(char **tokens, 1993 uint32_t n_tokens, 1994 char *out, 1995 size_t out_size) 1996 { 1997 uint8_t key_mask[TABLE_RULE_MATCH_SIZE_MAX]; 1998 struct table_params p; 1999 char *pipeline_name; 2000 uint32_t t0; 2001 int status; 2002 2003 if (n_tokens < 5) { 2004 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 2005 return; 2006 } 2007 2008 pipeline_name = tokens[1]; 2009 2010 if (strcmp(tokens[2], "table") != 0) { 2011 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "table"); 2012 return; 2013 } 2014 2015 if (strcmp(tokens[3], "match") != 0) { 2016 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "match"); 2017 return; 2018 } 2019 2020 t0 = 4; 2021 if (strcmp(tokens[t0], "acl") == 0) { 2022 if (n_tokens < t0 + 6) { 2023 snprintf(out, out_size, MSG_ARG_MISMATCH, 2024 "pipeline table acl"); 2025 return; 2026 } 2027 2028 p.match_type = TABLE_ACL; 2029 2030 if (strcmp(tokens[t0 + 1], "ipv4") == 0) 2031 p.match.acl.ip_version = 1; 2032 else if (strcmp(tokens[t0 + 1], "ipv6") == 0) 2033 p.match.acl.ip_version = 0; 2034 else { 2035 snprintf(out, out_size, MSG_ARG_NOT_FOUND, 2036 "ipv4 or ipv6"); 2037 return; 2038 } 2039 2040 if (strcmp(tokens[t0 + 2], "offset") != 0) { 2041 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset"); 2042 return; 2043 } 2044 2045 if (parser_read_uint32(&p.match.acl.ip_header_offset, 2046 tokens[t0 + 3]) != 0) { 2047 snprintf(out, out_size, MSG_ARG_INVALID, 2048 "ip_header_offset"); 2049 return; 2050 } 2051 2052 if (strcmp(tokens[t0 + 4], "size") != 0) { 2053 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "size"); 2054 return; 2055 } 2056 2057 if (parser_read_uint32(&p.match.acl.n_rules, 2058 tokens[t0 + 5]) != 0) { 2059 snprintf(out, out_size, MSG_ARG_INVALID, "n_rules"); 2060 return; 2061 } 2062 2063 t0 += 6; 2064 } else if (strcmp(tokens[t0], "array") == 0) { 2065 if (n_tokens < t0 + 5) { 2066 snprintf(out, out_size, MSG_ARG_MISMATCH, 2067 "pipeline table array"); 2068 return; 2069 } 2070 2071 p.match_type = TABLE_ARRAY; 2072 2073 if (strcmp(tokens[t0 + 1], "offset") != 0) { 2074 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset"); 2075 return; 2076 } 2077 2078 if (parser_read_uint32(&p.match.array.key_offset, 2079 tokens[t0 + 2]) != 0) { 2080 snprintf(out, out_size, MSG_ARG_INVALID, "key_offset"); 2081 return; 2082 } 2083 2084 if (strcmp(tokens[t0 + 3], "size") != 0) { 2085 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "size"); 2086 return; 2087 } 2088 2089 if (parser_read_uint32(&p.match.array.n_keys, 2090 tokens[t0 + 4]) != 0) { 2091 snprintf(out, out_size, MSG_ARG_INVALID, "n_keys"); 2092 return; 2093 } 2094 2095 t0 += 5; 2096 } else if (strcmp(tokens[t0], "hash") == 0) { 2097 uint32_t key_mask_size = TABLE_RULE_MATCH_SIZE_MAX; 2098 2099 if (n_tokens < t0 + 12) { 2100 snprintf(out, out_size, MSG_ARG_MISMATCH, 2101 "pipeline table hash"); 2102 return; 2103 } 2104 2105 p.match_type = TABLE_HASH; 2106 2107 if (strcmp(tokens[t0 + 1], "ext") == 0) 2108 p.match.hash.extendable_bucket = 1; 2109 else if (strcmp(tokens[t0 + 1], "lru") == 0) 2110 p.match.hash.extendable_bucket = 0; 2111 else { 2112 snprintf(out, out_size, MSG_ARG_NOT_FOUND, 2113 "ext or lru"); 2114 return; 2115 } 2116 2117 if (strcmp(tokens[t0 + 2], "key") != 0) { 2118 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "key"); 2119 return; 2120 } 2121 2122 if ((parser_read_uint32(&p.match.hash.key_size, 2123 tokens[t0 + 3]) != 0) || 2124 (p.match.hash.key_size == 0) || 2125 (p.match.hash.key_size > TABLE_RULE_MATCH_SIZE_MAX)) { 2126 snprintf(out, out_size, MSG_ARG_INVALID, "key_size"); 2127 return; 2128 } 2129 2130 if (strcmp(tokens[t0 + 4], "mask") != 0) { 2131 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "mask"); 2132 return; 2133 } 2134 2135 if ((parse_hex_string(tokens[t0 + 5], 2136 key_mask, &key_mask_size) != 0) || 2137 (key_mask_size != p.match.hash.key_size)) { 2138 snprintf(out, out_size, MSG_ARG_INVALID, "key_mask"); 2139 return; 2140 } 2141 p.match.hash.key_mask = key_mask; 2142 2143 if (strcmp(tokens[t0 + 6], "offset") != 0) { 2144 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset"); 2145 return; 2146 } 2147 2148 if (parser_read_uint32(&p.match.hash.key_offset, 2149 tokens[t0 + 7]) != 0) { 2150 snprintf(out, out_size, MSG_ARG_INVALID, "key_offset"); 2151 return; 2152 } 2153 2154 if (strcmp(tokens[t0 + 8], "buckets") != 0) { 2155 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "buckets"); 2156 return; 2157 } 2158 2159 if (parser_read_uint32(&p.match.hash.n_buckets, 2160 tokens[t0 + 9]) != 0) { 2161 snprintf(out, out_size, MSG_ARG_INVALID, "n_buckets"); 2162 return; 2163 } 2164 2165 if (strcmp(tokens[t0 + 10], "size") != 0) { 2166 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "size"); 2167 return; 2168 } 2169 2170 if (parser_read_uint32(&p.match.hash.n_keys, 2171 tokens[t0 + 11]) != 0) { 2172 snprintf(out, out_size, MSG_ARG_INVALID, "n_keys"); 2173 return; 2174 } 2175 2176 t0 += 12; 2177 } else if (strcmp(tokens[t0], "lpm") == 0) { 2178 if (n_tokens < t0 + 6) { 2179 snprintf(out, out_size, MSG_ARG_MISMATCH, 2180 "pipeline table lpm"); 2181 return; 2182 } 2183 2184 p.match_type = TABLE_LPM; 2185 2186 if (strcmp(tokens[t0 + 1], "ipv4") == 0) 2187 p.match.lpm.key_size = 4; 2188 else if (strcmp(tokens[t0 + 1], "ipv6") == 0) 2189 p.match.lpm.key_size = 16; 2190 else { 2191 snprintf(out, out_size, MSG_ARG_NOT_FOUND, 2192 "ipv4 or ipv6"); 2193 return; 2194 } 2195 2196 if (strcmp(tokens[t0 + 2], "offset") != 0) { 2197 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset"); 2198 return; 2199 } 2200 2201 if (parser_read_uint32(&p.match.lpm.key_offset, 2202 tokens[t0 + 3]) != 0) { 2203 snprintf(out, out_size, MSG_ARG_INVALID, "key_offset"); 2204 return; 2205 } 2206 2207 if (strcmp(tokens[t0 + 4], "size") != 0) { 2208 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "size"); 2209 return; 2210 } 2211 2212 if (parser_read_uint32(&p.match.lpm.n_rules, 2213 tokens[t0 + 5]) != 0) { 2214 snprintf(out, out_size, MSG_ARG_INVALID, "n_rules"); 2215 return; 2216 } 2217 2218 t0 += 6; 2219 } else if (strcmp(tokens[t0], "stub") == 0) { 2220 p.match_type = TABLE_STUB; 2221 2222 t0 += 1; 2223 } else { 2224 snprintf(out, out_size, MSG_ARG_INVALID, tokens[0]); 2225 return; 2226 } 2227 2228 p.action_profile_name = NULL; 2229 if ((n_tokens > t0) && (strcmp(tokens[t0], "action") == 0)) { 2230 if (n_tokens < t0 + 2) { 2231 snprintf(out, out_size, MSG_ARG_MISMATCH, "action"); 2232 return; 2233 } 2234 2235 p.action_profile_name = tokens[t0 + 1]; 2236 2237 t0 += 2; 2238 } 2239 2240 if (n_tokens > t0) { 2241 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 2242 return; 2243 } 2244 2245 status = pipeline_table_create(pipeline_name, &p); 2246 if (status) { 2247 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 2248 return; 2249 } 2250 } 2251 2252 static const char cmd_pipeline_port_in_table_help[] = 2253 "pipeline <pipeline_name> port in <port_id> table <table_id>\n"; 2254 2255 static void 2256 cmd_pipeline_port_in_table(char **tokens, 2257 uint32_t n_tokens, 2258 char *out, 2259 size_t out_size) 2260 { 2261 char *pipeline_name; 2262 uint32_t port_id, table_id; 2263 int status; 2264 2265 if (n_tokens != 7) { 2266 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 2267 return; 2268 } 2269 2270 pipeline_name = tokens[1]; 2271 2272 if (strcmp(tokens[2], "port") != 0) { 2273 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port"); 2274 return; 2275 } 2276 2277 if (strcmp(tokens[3], "in") != 0) { 2278 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "in"); 2279 return; 2280 } 2281 2282 if (parser_read_uint32(&port_id, tokens[4]) != 0) { 2283 snprintf(out, out_size, MSG_ARG_INVALID, "port_id"); 2284 return; 2285 } 2286 2287 if (strcmp(tokens[5], "table") != 0) { 2288 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "table"); 2289 return; 2290 } 2291 2292 if (parser_read_uint32(&table_id, tokens[6]) != 0) { 2293 snprintf(out, out_size, MSG_ARG_INVALID, "table_id"); 2294 return; 2295 } 2296 2297 status = pipeline_port_in_connect_to_table(pipeline_name, 2298 port_id, 2299 table_id); 2300 if (status) { 2301 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 2302 return; 2303 } 2304 } 2305 2306 2307 static const char cmd_pipeline_port_in_stats_help[] = 2308 "pipeline <pipeline_name> port in <port_id> stats read [clear]\n"; 2309 2310 #define MSG_PIPELINE_PORT_IN_STATS \ 2311 "Pkts in: %" PRIu64 "\n" \ 2312 "Pkts dropped by AH: %" PRIu64 "\n" \ 2313 "Pkts dropped by other: %" PRIu64 "\n" 2314 2315 static void 2316 cmd_pipeline_port_in_stats(char **tokens, 2317 uint32_t n_tokens, 2318 char *out, 2319 size_t out_size) 2320 { 2321 struct rte_pipeline_port_in_stats stats; 2322 char *pipeline_name; 2323 uint32_t port_id; 2324 int clear, status; 2325 2326 if ((n_tokens != 7) && (n_tokens != 8)) { 2327 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 2328 return; 2329 } 2330 2331 pipeline_name = tokens[1]; 2332 2333 if (strcmp(tokens[2], "port") != 0) { 2334 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port"); 2335 return; 2336 } 2337 2338 if (strcmp(tokens[3], "in") != 0) { 2339 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "in"); 2340 return; 2341 } 2342 2343 if (parser_read_uint32(&port_id, tokens[4]) != 0) { 2344 snprintf(out, out_size, MSG_ARG_INVALID, "port_id"); 2345 return; 2346 } 2347 2348 if (strcmp(tokens[5], "stats") != 0) { 2349 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "stats"); 2350 return; 2351 } 2352 2353 if (strcmp(tokens[6], "read") != 0) { 2354 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "read"); 2355 return; 2356 } 2357 2358 clear = 0; 2359 if (n_tokens == 8) { 2360 if (strcmp(tokens[7], "clear") != 0) { 2361 snprintf(out, out_size, MSG_ARG_INVALID, "clear"); 2362 return; 2363 } 2364 2365 clear = 1; 2366 } 2367 2368 status = pipeline_port_in_stats_read(pipeline_name, 2369 port_id, 2370 &stats, 2371 clear); 2372 if (status) { 2373 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 2374 return; 2375 } 2376 2377 snprintf(out, out_size, MSG_PIPELINE_PORT_IN_STATS, 2378 stats.stats.n_pkts_in, 2379 stats.n_pkts_dropped_by_ah, 2380 stats.stats.n_pkts_drop); 2381 } 2382 2383 2384 static const char cmd_pipeline_port_in_enable_help[] = 2385 "pipeline <pipeline_name> port in <port_id> enable\n"; 2386 2387 static void 2388 cmd_pipeline_port_in_enable(char **tokens, 2389 uint32_t n_tokens, 2390 char *out, 2391 size_t out_size) 2392 { 2393 char *pipeline_name; 2394 uint32_t port_id; 2395 int status; 2396 2397 if (n_tokens != 6) { 2398 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 2399 return; 2400 } 2401 2402 pipeline_name = tokens[1]; 2403 2404 if (strcmp(tokens[2], "port") != 0) { 2405 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port"); 2406 return; 2407 } 2408 2409 if (strcmp(tokens[3], "in") != 0) { 2410 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "in"); 2411 return; 2412 } 2413 2414 if (parser_read_uint32(&port_id, tokens[4]) != 0) { 2415 snprintf(out, out_size, MSG_ARG_INVALID, "port_id"); 2416 return; 2417 } 2418 2419 if (strcmp(tokens[5], "enable") != 0) { 2420 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "enable"); 2421 return; 2422 } 2423 2424 status = pipeline_port_in_enable(pipeline_name, port_id); 2425 if (status) { 2426 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 2427 return; 2428 } 2429 } 2430 2431 2432 static const char cmd_pipeline_port_in_disable_help[] = 2433 "pipeline <pipeline_name> port in <port_id> disable\n"; 2434 2435 static void 2436 cmd_pipeline_port_in_disable(char **tokens, 2437 uint32_t n_tokens, 2438 char *out, 2439 size_t out_size) 2440 { 2441 char *pipeline_name; 2442 uint32_t port_id; 2443 int status; 2444 2445 if (n_tokens != 6) { 2446 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 2447 return; 2448 } 2449 2450 pipeline_name = tokens[1]; 2451 2452 if (strcmp(tokens[2], "port") != 0) { 2453 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port"); 2454 return; 2455 } 2456 2457 if (strcmp(tokens[3], "in") != 0) { 2458 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "in"); 2459 return; 2460 } 2461 2462 if (parser_read_uint32(&port_id, tokens[4]) != 0) { 2463 snprintf(out, out_size, MSG_ARG_INVALID, "port_id"); 2464 return; 2465 } 2466 2467 if (strcmp(tokens[5], "disable") != 0) { 2468 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "disable"); 2469 return; 2470 } 2471 2472 status = pipeline_port_in_disable(pipeline_name, port_id); 2473 if (status) { 2474 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 2475 return; 2476 } 2477 } 2478 2479 2480 static const char cmd_pipeline_port_out_stats_help[] = 2481 "pipeline <pipeline_name> port out <port_id> stats read [clear]\n"; 2482 2483 #define MSG_PIPELINE_PORT_OUT_STATS \ 2484 "Pkts in: %" PRIu64 "\n" \ 2485 "Pkts dropped by AH: %" PRIu64 "\n" \ 2486 "Pkts dropped by other: %" PRIu64 "\n" 2487 2488 static void 2489 cmd_pipeline_port_out_stats(char **tokens, 2490 uint32_t n_tokens, 2491 char *out, 2492 size_t out_size) 2493 { 2494 struct rte_pipeline_port_out_stats stats; 2495 char *pipeline_name; 2496 uint32_t port_id; 2497 int clear, status; 2498 2499 if ((n_tokens != 7) && (n_tokens != 8)) { 2500 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 2501 return; 2502 } 2503 2504 pipeline_name = tokens[1]; 2505 2506 if (strcmp(tokens[2], "port") != 0) { 2507 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port"); 2508 return; 2509 } 2510 2511 if (strcmp(tokens[3], "out") != 0) { 2512 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "out"); 2513 return; 2514 } 2515 2516 if (parser_read_uint32(&port_id, tokens[4]) != 0) { 2517 snprintf(out, out_size, MSG_ARG_INVALID, "port_id"); 2518 return; 2519 } 2520 2521 if (strcmp(tokens[5], "stats") != 0) { 2522 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "stats"); 2523 return; 2524 } 2525 2526 if (strcmp(tokens[6], "read") != 0) { 2527 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "read"); 2528 return; 2529 } 2530 2531 clear = 0; 2532 if (n_tokens == 8) { 2533 if (strcmp(tokens[7], "clear") != 0) { 2534 snprintf(out, out_size, MSG_ARG_INVALID, "clear"); 2535 return; 2536 } 2537 2538 clear = 1; 2539 } 2540 2541 status = pipeline_port_out_stats_read(pipeline_name, 2542 port_id, 2543 &stats, 2544 clear); 2545 if (status) { 2546 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 2547 return; 2548 } 2549 2550 snprintf(out, out_size, MSG_PIPELINE_PORT_OUT_STATS, 2551 stats.stats.n_pkts_in, 2552 stats.n_pkts_dropped_by_ah, 2553 stats.stats.n_pkts_drop); 2554 } 2555 2556 2557 static const char cmd_pipeline_table_stats_help[] = 2558 "pipeline <pipeline_name> table <table_id> stats read [clear]\n"; 2559 2560 #define MSG_PIPELINE_TABLE_STATS \ 2561 "Pkts in: %" PRIu64 "\n" \ 2562 "Pkts in with lookup miss: %" PRIu64 "\n" \ 2563 "Pkts in with lookup hit dropped by AH: %" PRIu64 "\n" \ 2564 "Pkts in with lookup hit dropped by others: %" PRIu64 "\n" \ 2565 "Pkts in with lookup miss dropped by AH: %" PRIu64 "\n" \ 2566 "Pkts in with lookup miss dropped by others: %" PRIu64 "\n" 2567 2568 static void 2569 cmd_pipeline_table_stats(char **tokens, 2570 uint32_t n_tokens, 2571 char *out, 2572 size_t out_size) 2573 { 2574 struct rte_pipeline_table_stats stats; 2575 char *pipeline_name; 2576 uint32_t table_id; 2577 int clear, status; 2578 2579 if ((n_tokens != 6) && (n_tokens != 7)) { 2580 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 2581 return; 2582 } 2583 2584 pipeline_name = tokens[1]; 2585 2586 if (strcmp(tokens[2], "table") != 0) { 2587 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port"); 2588 return; 2589 } 2590 2591 if (parser_read_uint32(&table_id, tokens[3]) != 0) { 2592 snprintf(out, out_size, MSG_ARG_INVALID, "table_id"); 2593 return; 2594 } 2595 2596 if (strcmp(tokens[4], "stats") != 0) { 2597 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "stats"); 2598 return; 2599 } 2600 2601 if (strcmp(tokens[5], "read") != 0) { 2602 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "read"); 2603 return; 2604 } 2605 2606 clear = 0; 2607 if (n_tokens == 7) { 2608 if (strcmp(tokens[6], "clear") != 0) { 2609 snprintf(out, out_size, MSG_ARG_INVALID, "clear"); 2610 return; 2611 } 2612 2613 clear = 1; 2614 } 2615 2616 status = pipeline_table_stats_read(pipeline_name, 2617 table_id, 2618 &stats, 2619 clear); 2620 if (status) { 2621 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 2622 return; 2623 } 2624 2625 snprintf(out, out_size, MSG_PIPELINE_TABLE_STATS, 2626 stats.stats.n_pkts_in, 2627 stats.stats.n_pkts_lookup_miss, 2628 stats.n_pkts_dropped_by_lkp_hit_ah, 2629 stats.n_pkts_dropped_lkp_hit, 2630 stats.n_pkts_dropped_by_lkp_miss_ah, 2631 stats.n_pkts_dropped_lkp_miss); 2632 } 2633 2634 /** 2635 * <match> ::= 2636 * 2637 * match 2638 * acl 2639 * priority <priority> 2640 * ipv4 | ipv6 <sa> <sa_depth> <da> <da_depth> 2641 * <sp0> <sp1> <dp0> <dp1> <proto> 2642 * | array <pos> 2643 * | hash 2644 * raw <key> 2645 * | ipv4_5tuple <sa> <da> <sp> <dp> <proto> 2646 * | ipv6_5tuple <sa> <da> <sp> <dp> <proto> 2647 * | ipv4_addr <addr> 2648 * | ipv6_addr <addr> 2649 * | qinq <svlan> <cvlan> 2650 * | lpm 2651 * ipv4 | ipv6 <addr> <depth> 2652 */ 2653 struct pkt_key_qinq { 2654 uint16_t ethertype_svlan; 2655 uint16_t svlan; 2656 uint16_t ethertype_cvlan; 2657 uint16_t cvlan; 2658 } __rte_packed; 2659 2660 struct pkt_key_ipv4_5tuple { 2661 uint8_t time_to_live; 2662 uint8_t proto; 2663 uint16_t hdr_checksum; 2664 uint32_t sa; 2665 uint32_t da; 2666 uint16_t sp; 2667 uint16_t dp; 2668 } __rte_packed; 2669 2670 struct pkt_key_ipv6_5tuple { 2671 uint16_t payload_length; 2672 uint8_t proto; 2673 uint8_t hop_limit; 2674 uint8_t sa[16]; 2675 uint8_t da[16]; 2676 uint16_t sp; 2677 uint16_t dp; 2678 } __rte_packed; 2679 2680 struct pkt_key_ipv4_addr { 2681 uint32_t addr; 2682 } __rte_packed; 2683 2684 struct pkt_key_ipv6_addr { 2685 uint8_t addr[16]; 2686 } __rte_packed; 2687 2688 static uint32_t 2689 parse_match(char **tokens, 2690 uint32_t n_tokens, 2691 char *out, 2692 size_t out_size, 2693 struct table_rule_match *m) 2694 { 2695 memset(m, 0, sizeof(*m)); 2696 2697 if (n_tokens < 2) 2698 return 0; 2699 2700 if (strcmp(tokens[0], "match") != 0) { 2701 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "match"); 2702 return 0; 2703 } 2704 2705 if (strcmp(tokens[1], "acl") == 0) { 2706 if (n_tokens < 14) { 2707 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 2708 return 0; 2709 } 2710 2711 m->match_type = TABLE_ACL; 2712 2713 if (strcmp(tokens[2], "priority") != 0) { 2714 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "priority"); 2715 return 0; 2716 } 2717 2718 if (parser_read_uint32(&m->match.acl.priority, 2719 tokens[3]) != 0) { 2720 snprintf(out, out_size, MSG_ARG_INVALID, "priority"); 2721 return 0; 2722 } 2723 2724 if (strcmp(tokens[4], "ipv4") == 0) { 2725 struct in_addr saddr, daddr; 2726 2727 m->match.acl.ip_version = 1; 2728 2729 if (parse_ipv4_addr(tokens[5], &saddr) != 0) { 2730 snprintf(out, out_size, MSG_ARG_INVALID, "sa"); 2731 return 0; 2732 } 2733 m->match.acl.ipv4.sa = rte_be_to_cpu_32(saddr.s_addr); 2734 2735 if (parse_ipv4_addr(tokens[7], &daddr) != 0) { 2736 snprintf(out, out_size, MSG_ARG_INVALID, "da"); 2737 return 0; 2738 } 2739 m->match.acl.ipv4.da = rte_be_to_cpu_32(daddr.s_addr); 2740 } else if (strcmp(tokens[4], "ipv6") == 0) { 2741 struct in6_addr saddr, daddr; 2742 2743 m->match.acl.ip_version = 0; 2744 2745 if (parse_ipv6_addr(tokens[5], &saddr) != 0) { 2746 snprintf(out, out_size, MSG_ARG_INVALID, "sa"); 2747 return 0; 2748 } 2749 memcpy(m->match.acl.ipv6.sa, saddr.s6_addr, 16); 2750 2751 if (parse_ipv6_addr(tokens[7], &daddr) != 0) { 2752 snprintf(out, out_size, MSG_ARG_INVALID, "da"); 2753 return 0; 2754 } 2755 memcpy(m->match.acl.ipv6.da, daddr.s6_addr, 16); 2756 } else { 2757 snprintf(out, out_size, MSG_ARG_NOT_FOUND, 2758 "ipv4 or ipv6"); 2759 return 0; 2760 } 2761 2762 if (parser_read_uint32(&m->match.acl.sa_depth, 2763 tokens[6]) != 0) { 2764 snprintf(out, out_size, MSG_ARG_INVALID, "sa_depth"); 2765 return 0; 2766 } 2767 2768 if (parser_read_uint32(&m->match.acl.da_depth, 2769 tokens[8]) != 0) { 2770 snprintf(out, out_size, MSG_ARG_INVALID, "da_depth"); 2771 return 0; 2772 } 2773 2774 if (parser_read_uint16(&m->match.acl.sp0, tokens[9]) != 0) { 2775 snprintf(out, out_size, MSG_ARG_INVALID, "sp0"); 2776 return 0; 2777 } 2778 2779 if (parser_read_uint16(&m->match.acl.sp1, tokens[10]) != 0) { 2780 snprintf(out, out_size, MSG_ARG_INVALID, "sp1"); 2781 return 0; 2782 } 2783 2784 if (parser_read_uint16(&m->match.acl.dp0, tokens[11]) != 0) { 2785 snprintf(out, out_size, MSG_ARG_INVALID, "dp0"); 2786 return 0; 2787 } 2788 2789 if (parser_read_uint16(&m->match.acl.dp1, tokens[12]) != 0) { 2790 snprintf(out, out_size, MSG_ARG_INVALID, "dp1"); 2791 return 0; 2792 } 2793 2794 if (parser_read_uint8(&m->match.acl.proto, tokens[13]) != 0) { 2795 snprintf(out, out_size, MSG_ARG_INVALID, "proto"); 2796 return 0; 2797 } 2798 2799 m->match.acl.proto_mask = 0xff; 2800 2801 return 14; 2802 } /* acl */ 2803 2804 if (strcmp(tokens[1], "array") == 0) { 2805 if (n_tokens < 3) { 2806 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 2807 return 0; 2808 } 2809 2810 m->match_type = TABLE_ARRAY; 2811 2812 if (parser_read_uint32(&m->match.array.pos, tokens[2]) != 0) { 2813 snprintf(out, out_size, MSG_ARG_INVALID, "pos"); 2814 return 0; 2815 } 2816 2817 return 3; 2818 } /* array */ 2819 2820 if (strcmp(tokens[1], "hash") == 0) { 2821 if (n_tokens < 3) { 2822 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 2823 return 0; 2824 } 2825 2826 m->match_type = TABLE_HASH; 2827 2828 if (strcmp(tokens[2], "raw") == 0) { 2829 uint32_t key_size = TABLE_RULE_MATCH_SIZE_MAX; 2830 2831 if (n_tokens < 4) { 2832 snprintf(out, out_size, MSG_ARG_MISMATCH, 2833 tokens[0]); 2834 return 0; 2835 } 2836 2837 if (parse_hex_string(tokens[3], 2838 m->match.hash.key, &key_size) != 0) { 2839 snprintf(out, out_size, MSG_ARG_INVALID, "key"); 2840 return 0; 2841 } 2842 2843 return 4; 2844 } /* hash raw */ 2845 2846 if (strcmp(tokens[2], "ipv4_5tuple") == 0) { 2847 struct pkt_key_ipv4_5tuple *ipv4 = 2848 (struct pkt_key_ipv4_5tuple *) m->match.hash.key; 2849 struct in_addr saddr, daddr; 2850 uint16_t sp, dp; 2851 uint8_t proto; 2852 2853 if (n_tokens < 8) { 2854 snprintf(out, out_size, MSG_ARG_MISMATCH, 2855 tokens[0]); 2856 return 0; 2857 } 2858 2859 if (parse_ipv4_addr(tokens[3], &saddr) != 0) { 2860 snprintf(out, out_size, MSG_ARG_INVALID, "sa"); 2861 return 0; 2862 } 2863 2864 if (parse_ipv4_addr(tokens[4], &daddr) != 0) { 2865 snprintf(out, out_size, MSG_ARG_INVALID, "da"); 2866 return 0; 2867 } 2868 2869 if (parser_read_uint16(&sp, tokens[5]) != 0) { 2870 snprintf(out, out_size, MSG_ARG_INVALID, "sp"); 2871 return 0; 2872 } 2873 2874 if (parser_read_uint16(&dp, tokens[6]) != 0) { 2875 snprintf(out, out_size, MSG_ARG_INVALID, "dp"); 2876 return 0; 2877 } 2878 2879 if (parser_read_uint8(&proto, tokens[7]) != 0) { 2880 snprintf(out, out_size, MSG_ARG_INVALID, 2881 "proto"); 2882 return 0; 2883 } 2884 2885 ipv4->sa = saddr.s_addr; 2886 ipv4->da = daddr.s_addr; 2887 ipv4->sp = rte_cpu_to_be_16(sp); 2888 ipv4->dp = rte_cpu_to_be_16(dp); 2889 ipv4->proto = proto; 2890 2891 return 8; 2892 } /* hash ipv4_5tuple */ 2893 2894 if (strcmp(tokens[2], "ipv6_5tuple") == 0) { 2895 struct pkt_key_ipv6_5tuple *ipv6 = 2896 (struct pkt_key_ipv6_5tuple *) m->match.hash.key; 2897 struct in6_addr saddr, daddr; 2898 uint16_t sp, dp; 2899 uint8_t proto; 2900 2901 if (n_tokens < 8) { 2902 snprintf(out, out_size, MSG_ARG_MISMATCH, 2903 tokens[0]); 2904 return 0; 2905 } 2906 2907 if (parse_ipv6_addr(tokens[3], &saddr) != 0) { 2908 snprintf(out, out_size, MSG_ARG_INVALID, "sa"); 2909 return 0; 2910 } 2911 2912 if (parse_ipv6_addr(tokens[4], &daddr) != 0) { 2913 snprintf(out, out_size, MSG_ARG_INVALID, "da"); 2914 return 0; 2915 } 2916 2917 if (parser_read_uint16(&sp, tokens[5]) != 0) { 2918 snprintf(out, out_size, MSG_ARG_INVALID, "sp"); 2919 return 0; 2920 } 2921 2922 if (parser_read_uint16(&dp, tokens[6]) != 0) { 2923 snprintf(out, out_size, MSG_ARG_INVALID, "dp"); 2924 return 0; 2925 } 2926 2927 if (parser_read_uint8(&proto, tokens[7]) != 0) { 2928 snprintf(out, out_size, MSG_ARG_INVALID, 2929 "proto"); 2930 return 0; 2931 } 2932 2933 memcpy(ipv6->sa, saddr.s6_addr, 16); 2934 memcpy(ipv6->da, daddr.s6_addr, 16); 2935 ipv6->sp = rte_cpu_to_be_16(sp); 2936 ipv6->dp = rte_cpu_to_be_16(dp); 2937 ipv6->proto = proto; 2938 2939 return 8; 2940 } /* hash ipv6_5tuple */ 2941 2942 if (strcmp(tokens[2], "ipv4_addr") == 0) { 2943 struct pkt_key_ipv4_addr *ipv4_addr = 2944 (struct pkt_key_ipv4_addr *) m->match.hash.key; 2945 struct in_addr addr; 2946 2947 if (n_tokens < 4) { 2948 snprintf(out, out_size, MSG_ARG_MISMATCH, 2949 tokens[0]); 2950 return 0; 2951 } 2952 2953 if (parse_ipv4_addr(tokens[3], &addr) != 0) { 2954 snprintf(out, out_size, MSG_ARG_INVALID, 2955 "addr"); 2956 return 0; 2957 } 2958 2959 ipv4_addr->addr = addr.s_addr; 2960 2961 return 4; 2962 } /* hash ipv4_addr */ 2963 2964 if (strcmp(tokens[2], "ipv6_addr") == 0) { 2965 struct pkt_key_ipv6_addr *ipv6_addr = 2966 (struct pkt_key_ipv6_addr *) m->match.hash.key; 2967 struct in6_addr addr; 2968 2969 if (n_tokens < 4) { 2970 snprintf(out, out_size, MSG_ARG_MISMATCH, 2971 tokens[0]); 2972 return 0; 2973 } 2974 2975 if (parse_ipv6_addr(tokens[3], &addr) != 0) { 2976 snprintf(out, out_size, MSG_ARG_INVALID, 2977 "addr"); 2978 return 0; 2979 } 2980 2981 memcpy(ipv6_addr->addr, addr.s6_addr, 16); 2982 2983 return 4; 2984 } /* hash ipv6_5tuple */ 2985 2986 if (strcmp(tokens[2], "qinq") == 0) { 2987 struct pkt_key_qinq *qinq = 2988 (struct pkt_key_qinq *) m->match.hash.key; 2989 uint16_t svlan, cvlan; 2990 2991 if (n_tokens < 5) { 2992 snprintf(out, out_size, MSG_ARG_MISMATCH, 2993 tokens[0]); 2994 return 0; 2995 } 2996 2997 if ((parser_read_uint16(&svlan, tokens[3]) != 0) || 2998 (svlan > 0xFFF)) { 2999 snprintf(out, out_size, MSG_ARG_INVALID, 3000 "svlan"); 3001 return 0; 3002 } 3003 3004 if ((parser_read_uint16(&cvlan, tokens[4]) != 0) || 3005 (cvlan > 0xFFF)) { 3006 snprintf(out, out_size, MSG_ARG_INVALID, 3007 "cvlan"); 3008 return 0; 3009 } 3010 3011 qinq->svlan = rte_cpu_to_be_16(svlan); 3012 qinq->cvlan = rte_cpu_to_be_16(cvlan); 3013 3014 return 5; 3015 } /* hash qinq */ 3016 3017 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 3018 return 0; 3019 } /* hash */ 3020 3021 if (strcmp(tokens[1], "lpm") == 0) { 3022 if (n_tokens < 5) { 3023 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 3024 return 0; 3025 } 3026 3027 m->match_type = TABLE_LPM; 3028 3029 if (strcmp(tokens[2], "ipv4") == 0) { 3030 struct in_addr addr; 3031 3032 m->match.lpm.ip_version = 1; 3033 3034 if (parse_ipv4_addr(tokens[3], &addr) != 0) { 3035 snprintf(out, out_size, MSG_ARG_INVALID, 3036 "addr"); 3037 return 0; 3038 } 3039 3040 m->match.lpm.ipv4 = rte_be_to_cpu_32(addr.s_addr); 3041 } else if (strcmp(tokens[2], "ipv6") == 0) { 3042 struct in6_addr addr; 3043 3044 m->match.lpm.ip_version = 0; 3045 3046 if (parse_ipv6_addr(tokens[3], &addr) != 0) { 3047 snprintf(out, out_size, MSG_ARG_INVALID, 3048 "addr"); 3049 return 0; 3050 } 3051 3052 memcpy(m->match.lpm.ipv6, addr.s6_addr, 16); 3053 } else { 3054 snprintf(out, out_size, MSG_ARG_MISMATCH, 3055 "ipv4 or ipv6"); 3056 return 0; 3057 } 3058 3059 if (parser_read_uint8(&m->match.lpm.depth, tokens[4]) != 0) { 3060 snprintf(out, out_size, MSG_ARG_INVALID, "depth"); 3061 return 0; 3062 } 3063 3064 return 5; 3065 } /* lpm */ 3066 3067 snprintf(out, out_size, MSG_ARG_MISMATCH, 3068 "acl or array or hash or lpm"); 3069 return 0; 3070 } 3071 3072 /** 3073 * table_action ::= 3074 * 3075 * action 3076 * fwd 3077 * drop 3078 * | port <port_id> 3079 * | meta 3080 * | table <table_id> 3081 * [balance <out0> ... <out7>] 3082 * [meter 3083 * tc0 meter <meter_profile_id> policer g <pa> y <pa> r <pa> 3084 * [tc1 meter <meter_profile_id> policer g <pa> y <pa> r <pa> 3085 * tc2 meter <meter_profile_id> policer g <pa> y <pa> r <pa> 3086 * tc3 meter <meter_profile_id> policer g <pa> y <pa> r <pa>]] 3087 * [tm subport <subport_id> pipe <pipe_id>] 3088 * [encap 3089 * ether <da> <sa> 3090 * | vlan <da> <sa> <pcp> <dei> <vid> 3091 * | qinq <da> <sa> <pcp> <dei> <vid> <pcp> <dei> <vid> 3092 * | qinq_pppoe <da> <sa> <pcp> <dei> <vid> <pcp> <dei> <vid> <session_id> 3093 * | mpls unicast | multicast 3094 * <da> <sa> 3095 * label0 <label> <tc> <ttl> 3096 * [label1 <label> <tc> <ttl> 3097 * [label2 <label> <tc> <ttl> 3098 * [label3 <label> <tc> <ttl>]]] 3099 * | pppoe <da> <sa> <session_id> 3100 * | vxlan ether <da> <sa> 3101 * [vlan <pcp> <dei> <vid>] 3102 * ipv4 <sa> <da> <dscp> <ttl> 3103 * | ipv6 <sa> <da> <flow_label> <dscp> <hop_limit> 3104 * udp <sp> <dp> 3105 * vxlan <vni>] 3106 * [nat ipv4 | ipv6 <addr> <port>] 3107 * [ttl dec | keep] 3108 * [stats] 3109 * [time] 3110 * [sym_crypto 3111 * encrypt | decrypt 3112 * type 3113 * | cipher 3114 * cipher_algo <algo> cipher_key <key> cipher_iv <iv> 3115 * | cipher_auth 3116 * cipher_algo <algo> cipher_key <key> cipher_iv <iv> 3117 * auth_algo <algo> auth_key <key> digest_size <size> 3118 * | aead 3119 * aead_algo <algo> aead_key <key> aead_iv <iv> aead_aad <aad> 3120 * digest_size <size> 3121 * data_offset <data_offset>] 3122 * [tag <tag>] 3123 * [decap <n>] 3124 * 3125 * where: 3126 * <pa> ::= g | y | r | drop 3127 */ 3128 static uint32_t 3129 parse_table_action_fwd(char **tokens, 3130 uint32_t n_tokens, 3131 struct table_rule_action *a) 3132 { 3133 if ((n_tokens == 0) || (strcmp(tokens[0], "fwd") != 0)) 3134 return 0; 3135 3136 tokens++; 3137 n_tokens--; 3138 3139 if (n_tokens && (strcmp(tokens[0], "drop") == 0)) { 3140 a->fwd.action = RTE_PIPELINE_ACTION_DROP; 3141 a->action_mask |= 1 << RTE_TABLE_ACTION_FWD; 3142 return 1 + 1; 3143 } 3144 3145 if (n_tokens && (strcmp(tokens[0], "port") == 0)) { 3146 uint32_t id; 3147 3148 if ((n_tokens < 2) || 3149 parser_read_uint32(&id, tokens[1])) 3150 return 0; 3151 3152 a->fwd.action = RTE_PIPELINE_ACTION_PORT; 3153 a->fwd.id = id; 3154 a->action_mask |= 1 << RTE_TABLE_ACTION_FWD; 3155 return 1 + 2; 3156 } 3157 3158 if (n_tokens && (strcmp(tokens[0], "meta") == 0)) { 3159 a->fwd.action = RTE_PIPELINE_ACTION_PORT_META; 3160 a->action_mask |= 1 << RTE_TABLE_ACTION_FWD; 3161 return 1 + 1; 3162 } 3163 3164 if (n_tokens && (strcmp(tokens[0], "table") == 0)) { 3165 uint32_t id; 3166 3167 if ((n_tokens < 2) || 3168 parser_read_uint32(&id, tokens[1])) 3169 return 0; 3170 3171 a->fwd.action = RTE_PIPELINE_ACTION_TABLE; 3172 a->fwd.id = id; 3173 a->action_mask |= 1 << RTE_TABLE_ACTION_FWD; 3174 return 1 + 2; 3175 } 3176 3177 return 0; 3178 } 3179 3180 static uint32_t 3181 parse_table_action_balance(char **tokens, 3182 uint32_t n_tokens, 3183 struct table_rule_action *a) 3184 { 3185 uint32_t i; 3186 3187 if ((n_tokens == 0) || (strcmp(tokens[0], "balance") != 0)) 3188 return 0; 3189 3190 tokens++; 3191 n_tokens--; 3192 3193 if (n_tokens < RTE_TABLE_ACTION_LB_TABLE_SIZE) 3194 return 0; 3195 3196 for (i = 0; i < RTE_TABLE_ACTION_LB_TABLE_SIZE; i++) 3197 if (parser_read_uint32(&a->lb.out[i], tokens[i]) != 0) 3198 return 0; 3199 3200 a->action_mask |= 1 << RTE_TABLE_ACTION_LB; 3201 return 1 + RTE_TABLE_ACTION_LB_TABLE_SIZE; 3202 3203 } 3204 3205 static int 3206 parse_policer_action(char *token, enum rte_table_action_policer *a) 3207 { 3208 if (strcmp(token, "g") == 0) { 3209 *a = RTE_TABLE_ACTION_POLICER_COLOR_GREEN; 3210 return 0; 3211 } 3212 3213 if (strcmp(token, "y") == 0) { 3214 *a = RTE_TABLE_ACTION_POLICER_COLOR_YELLOW; 3215 return 0; 3216 } 3217 3218 if (strcmp(token, "r") == 0) { 3219 *a = RTE_TABLE_ACTION_POLICER_COLOR_RED; 3220 return 0; 3221 } 3222 3223 if (strcmp(token, "drop") == 0) { 3224 *a = RTE_TABLE_ACTION_POLICER_DROP; 3225 return 0; 3226 } 3227 3228 return -1; 3229 } 3230 3231 static uint32_t 3232 parse_table_action_meter_tc(char **tokens, 3233 uint32_t n_tokens, 3234 struct rte_table_action_mtr_tc_params *mtr) 3235 { 3236 if ((n_tokens < 9) || 3237 strcmp(tokens[0], "meter") || 3238 parser_read_uint32(&mtr->meter_profile_id, tokens[1]) || 3239 strcmp(tokens[2], "policer") || 3240 strcmp(tokens[3], "g") || 3241 parse_policer_action(tokens[4], &mtr->policer[RTE_COLOR_GREEN]) || 3242 strcmp(tokens[5], "y") || 3243 parse_policer_action(tokens[6], &mtr->policer[RTE_COLOR_YELLOW]) || 3244 strcmp(tokens[7], "r") || 3245 parse_policer_action(tokens[8], &mtr->policer[RTE_COLOR_RED])) 3246 return 0; 3247 3248 return 9; 3249 } 3250 3251 static uint32_t 3252 parse_table_action_meter(char **tokens, 3253 uint32_t n_tokens, 3254 struct table_rule_action *a) 3255 { 3256 if ((n_tokens == 0) || strcmp(tokens[0], "meter")) 3257 return 0; 3258 3259 tokens++; 3260 n_tokens--; 3261 3262 if ((n_tokens < 10) || 3263 strcmp(tokens[0], "tc0") || 3264 (parse_table_action_meter_tc(tokens + 1, 3265 n_tokens - 1, 3266 &a->mtr.mtr[0]) == 0)) 3267 return 0; 3268 3269 tokens += 10; 3270 n_tokens -= 10; 3271 3272 if ((n_tokens == 0) || strcmp(tokens[0], "tc1")) { 3273 a->mtr.tc_mask = 1; 3274 a->action_mask |= 1 << RTE_TABLE_ACTION_MTR; 3275 return 1 + 10; 3276 } 3277 3278 if ((n_tokens < 30) || 3279 (parse_table_action_meter_tc(tokens + 1, 3280 n_tokens - 1, &a->mtr.mtr[1]) == 0) || 3281 strcmp(tokens[10], "tc2") || 3282 (parse_table_action_meter_tc(tokens + 11, 3283 n_tokens - 11, &a->mtr.mtr[2]) == 0) || 3284 strcmp(tokens[20], "tc3") || 3285 (parse_table_action_meter_tc(tokens + 21, 3286 n_tokens - 21, &a->mtr.mtr[3]) == 0)) 3287 return 0; 3288 3289 a->mtr.tc_mask = 0xF; 3290 a->action_mask |= 1 << RTE_TABLE_ACTION_MTR; 3291 return 1 + 10 + 3 * 10; 3292 } 3293 3294 static uint32_t 3295 parse_table_action_tm(char **tokens, 3296 uint32_t n_tokens, 3297 struct table_rule_action *a) 3298 { 3299 uint32_t subport_id, pipe_id; 3300 3301 if ((n_tokens < 5) || 3302 strcmp(tokens[0], "tm") || 3303 strcmp(tokens[1], "subport") || 3304 parser_read_uint32(&subport_id, tokens[2]) || 3305 strcmp(tokens[3], "pipe") || 3306 parser_read_uint32(&pipe_id, tokens[4])) 3307 return 0; 3308 3309 a->tm.subport_id = subport_id; 3310 a->tm.pipe_id = pipe_id; 3311 a->action_mask |= 1 << RTE_TABLE_ACTION_TM; 3312 return 5; 3313 } 3314 3315 static uint32_t 3316 parse_table_action_encap(char **tokens, 3317 uint32_t n_tokens, 3318 struct table_rule_action *a) 3319 { 3320 if ((n_tokens == 0) || strcmp(tokens[0], "encap")) 3321 return 0; 3322 3323 tokens++; 3324 n_tokens--; 3325 3326 /* ether */ 3327 if (n_tokens && (strcmp(tokens[0], "ether") == 0)) { 3328 if ((n_tokens < 3) || 3329 parse_mac_addr(tokens[1], &a->encap.ether.ether.da) || 3330 parse_mac_addr(tokens[2], &a->encap.ether.ether.sa)) 3331 return 0; 3332 3333 a->encap.type = RTE_TABLE_ACTION_ENCAP_ETHER; 3334 a->action_mask |= 1 << RTE_TABLE_ACTION_ENCAP; 3335 return 1 + 3; 3336 } 3337 3338 /* vlan */ 3339 if (n_tokens && (strcmp(tokens[0], "vlan") == 0)) { 3340 uint32_t pcp, dei, vid; 3341 3342 if ((n_tokens < 6) || 3343 parse_mac_addr(tokens[1], &a->encap.vlan.ether.da) || 3344 parse_mac_addr(tokens[2], &a->encap.vlan.ether.sa) || 3345 parser_read_uint32(&pcp, tokens[3]) || 3346 (pcp > 0x7) || 3347 parser_read_uint32(&dei, tokens[4]) || 3348 (dei > 0x1) || 3349 parser_read_uint32(&vid, tokens[5]) || 3350 (vid > 0xFFF)) 3351 return 0; 3352 3353 a->encap.vlan.vlan.pcp = pcp & 0x7; 3354 a->encap.vlan.vlan.dei = dei & 0x1; 3355 a->encap.vlan.vlan.vid = vid & 0xFFF; 3356 a->encap.type = RTE_TABLE_ACTION_ENCAP_VLAN; 3357 a->action_mask |= 1 << RTE_TABLE_ACTION_ENCAP; 3358 return 1 + 6; 3359 } 3360 3361 /* qinq */ 3362 if (n_tokens && (strcmp(tokens[0], "qinq") == 0)) { 3363 uint32_t svlan_pcp, svlan_dei, svlan_vid; 3364 uint32_t cvlan_pcp, cvlan_dei, cvlan_vid; 3365 3366 if ((n_tokens < 9) || 3367 parse_mac_addr(tokens[1], &a->encap.qinq.ether.da) || 3368 parse_mac_addr(tokens[2], &a->encap.qinq.ether.sa) || 3369 parser_read_uint32(&svlan_pcp, tokens[3]) || 3370 (svlan_pcp > 0x7) || 3371 parser_read_uint32(&svlan_dei, tokens[4]) || 3372 (svlan_dei > 0x1) || 3373 parser_read_uint32(&svlan_vid, tokens[5]) || 3374 (svlan_vid > 0xFFF) || 3375 parser_read_uint32(&cvlan_pcp, tokens[6]) || 3376 (cvlan_pcp > 0x7) || 3377 parser_read_uint32(&cvlan_dei, tokens[7]) || 3378 (cvlan_dei > 0x1) || 3379 parser_read_uint32(&cvlan_vid, tokens[8]) || 3380 (cvlan_vid > 0xFFF)) 3381 return 0; 3382 3383 a->encap.qinq.svlan.pcp = svlan_pcp & 0x7; 3384 a->encap.qinq.svlan.dei = svlan_dei & 0x1; 3385 a->encap.qinq.svlan.vid = svlan_vid & 0xFFF; 3386 a->encap.qinq.cvlan.pcp = cvlan_pcp & 0x7; 3387 a->encap.qinq.cvlan.dei = cvlan_dei & 0x1; 3388 a->encap.qinq.cvlan.vid = cvlan_vid & 0xFFF; 3389 a->encap.type = RTE_TABLE_ACTION_ENCAP_QINQ; 3390 a->action_mask |= 1 << RTE_TABLE_ACTION_ENCAP; 3391 return 1 + 9; 3392 } 3393 3394 /* qinq_pppoe */ 3395 if (n_tokens && (strcmp(tokens[0], "qinq_pppoe") == 0)) { 3396 uint32_t svlan_pcp, svlan_dei, svlan_vid; 3397 uint32_t cvlan_pcp, cvlan_dei, cvlan_vid; 3398 3399 if ((n_tokens < 10) || 3400 parse_mac_addr(tokens[1], 3401 &a->encap.qinq_pppoe.ether.da) || 3402 parse_mac_addr(tokens[2], 3403 &a->encap.qinq_pppoe.ether.sa) || 3404 parser_read_uint32(&svlan_pcp, tokens[3]) || 3405 (svlan_pcp > 0x7) || 3406 parser_read_uint32(&svlan_dei, tokens[4]) || 3407 (svlan_dei > 0x1) || 3408 parser_read_uint32(&svlan_vid, tokens[5]) || 3409 (svlan_vid > 0xFFF) || 3410 parser_read_uint32(&cvlan_pcp, tokens[6]) || 3411 (cvlan_pcp > 0x7) || 3412 parser_read_uint32(&cvlan_dei, tokens[7]) || 3413 (cvlan_dei > 0x1) || 3414 parser_read_uint32(&cvlan_vid, tokens[8]) || 3415 (cvlan_vid > 0xFFF) || 3416 parser_read_uint16(&a->encap.qinq_pppoe.pppoe.session_id, 3417 tokens[9])) 3418 return 0; 3419 3420 a->encap.qinq_pppoe.svlan.pcp = svlan_pcp & 0x7; 3421 a->encap.qinq_pppoe.svlan.dei = svlan_dei & 0x1; 3422 a->encap.qinq_pppoe.svlan.vid = svlan_vid & 0xFFF; 3423 a->encap.qinq_pppoe.cvlan.pcp = cvlan_pcp & 0x7; 3424 a->encap.qinq_pppoe.cvlan.dei = cvlan_dei & 0x1; 3425 a->encap.qinq_pppoe.cvlan.vid = cvlan_vid & 0xFFF; 3426 a->encap.type = RTE_TABLE_ACTION_ENCAP_QINQ_PPPOE; 3427 a->action_mask |= 1 << RTE_TABLE_ACTION_ENCAP; 3428 return 1 + 10; 3429 3430 } 3431 3432 /* mpls */ 3433 if (n_tokens && (strcmp(tokens[0], "mpls") == 0)) { 3434 uint32_t label, tc, ttl; 3435 3436 if (n_tokens < 8) 3437 return 0; 3438 3439 if (strcmp(tokens[1], "unicast") == 0) 3440 a->encap.mpls.unicast = 1; 3441 else if (strcmp(tokens[1], "multicast") == 0) 3442 a->encap.mpls.unicast = 0; 3443 else 3444 return 0; 3445 3446 if (parse_mac_addr(tokens[2], &a->encap.mpls.ether.da) || 3447 parse_mac_addr(tokens[3], &a->encap.mpls.ether.sa) || 3448 strcmp(tokens[4], "label0") || 3449 parser_read_uint32(&label, tokens[5]) || 3450 (label > 0xFFFFF) || 3451 parser_read_uint32(&tc, tokens[6]) || 3452 (tc > 0x7) || 3453 parser_read_uint32(&ttl, tokens[7]) || 3454 (ttl > 0x3F)) 3455 return 0; 3456 3457 a->encap.mpls.mpls[0].label = label; 3458 a->encap.mpls.mpls[0].tc = tc; 3459 a->encap.mpls.mpls[0].ttl = ttl; 3460 3461 tokens += 8; 3462 n_tokens -= 8; 3463 3464 if ((n_tokens == 0) || strcmp(tokens[0], "label1")) { 3465 a->encap.mpls.mpls_count = 1; 3466 a->encap.type = RTE_TABLE_ACTION_ENCAP_MPLS; 3467 a->action_mask |= 1 << RTE_TABLE_ACTION_ENCAP; 3468 return 1 + 8; 3469 } 3470 3471 if ((n_tokens < 4) || 3472 parser_read_uint32(&label, tokens[1]) || 3473 (label > 0xFFFFF) || 3474 parser_read_uint32(&tc, tokens[2]) || 3475 (tc > 0x7) || 3476 parser_read_uint32(&ttl, tokens[3]) || 3477 (ttl > 0x3F)) 3478 return 0; 3479 3480 a->encap.mpls.mpls[1].label = label; 3481 a->encap.mpls.mpls[1].tc = tc; 3482 a->encap.mpls.mpls[1].ttl = ttl; 3483 3484 tokens += 4; 3485 n_tokens -= 4; 3486 3487 if ((n_tokens == 0) || strcmp(tokens[0], "label2")) { 3488 a->encap.mpls.mpls_count = 2; 3489 a->encap.type = RTE_TABLE_ACTION_ENCAP_MPLS; 3490 a->action_mask |= 1 << RTE_TABLE_ACTION_ENCAP; 3491 return 1 + 8 + 4; 3492 } 3493 3494 if ((n_tokens < 4) || 3495 parser_read_uint32(&label, tokens[1]) || 3496 (label > 0xFFFFF) || 3497 parser_read_uint32(&tc, tokens[2]) || 3498 (tc > 0x7) || 3499 parser_read_uint32(&ttl, tokens[3]) || 3500 (ttl > 0x3F)) 3501 return 0; 3502 3503 a->encap.mpls.mpls[2].label = label; 3504 a->encap.mpls.mpls[2].tc = tc; 3505 a->encap.mpls.mpls[2].ttl = ttl; 3506 3507 tokens += 4; 3508 n_tokens -= 4; 3509 3510 if ((n_tokens == 0) || strcmp(tokens[0], "label3")) { 3511 a->encap.mpls.mpls_count = 3; 3512 a->encap.type = RTE_TABLE_ACTION_ENCAP_MPLS; 3513 a->action_mask |= 1 << RTE_TABLE_ACTION_ENCAP; 3514 return 1 + 8 + 4 + 4; 3515 } 3516 3517 if ((n_tokens < 4) || 3518 parser_read_uint32(&label, tokens[1]) || 3519 (label > 0xFFFFF) || 3520 parser_read_uint32(&tc, tokens[2]) || 3521 (tc > 0x7) || 3522 parser_read_uint32(&ttl, tokens[3]) || 3523 (ttl > 0x3F)) 3524 return 0; 3525 3526 a->encap.mpls.mpls[3].label = label; 3527 a->encap.mpls.mpls[3].tc = tc; 3528 a->encap.mpls.mpls[3].ttl = ttl; 3529 3530 a->encap.mpls.mpls_count = 4; 3531 a->encap.type = RTE_TABLE_ACTION_ENCAP_MPLS; 3532 a->action_mask |= 1 << RTE_TABLE_ACTION_ENCAP; 3533 return 1 + 8 + 4 + 4 + 4; 3534 } 3535 3536 /* pppoe */ 3537 if (n_tokens && (strcmp(tokens[0], "pppoe") == 0)) { 3538 if ((n_tokens < 4) || 3539 parse_mac_addr(tokens[1], &a->encap.pppoe.ether.da) || 3540 parse_mac_addr(tokens[2], &a->encap.pppoe.ether.sa) || 3541 parser_read_uint16(&a->encap.pppoe.pppoe.session_id, 3542 tokens[3])) 3543 return 0; 3544 3545 a->encap.type = RTE_TABLE_ACTION_ENCAP_PPPOE; 3546 a->action_mask |= 1 << RTE_TABLE_ACTION_ENCAP; 3547 return 1 + 4; 3548 } 3549 3550 /* vxlan */ 3551 if (n_tokens && (strcmp(tokens[0], "vxlan") == 0)) { 3552 uint32_t n = 0; 3553 3554 n_tokens--; 3555 tokens++; 3556 n++; 3557 3558 /* ether <da> <sa> */ 3559 if ((n_tokens < 3) || 3560 strcmp(tokens[0], "ether") || 3561 parse_mac_addr(tokens[1], &a->encap.vxlan.ether.da) || 3562 parse_mac_addr(tokens[2], &a->encap.vxlan.ether.sa)) 3563 return 0; 3564 3565 n_tokens -= 3; 3566 tokens += 3; 3567 n += 3; 3568 3569 /* [vlan <pcp> <dei> <vid>] */ 3570 if (strcmp(tokens[0], "vlan") == 0) { 3571 uint32_t pcp, dei, vid; 3572 3573 if ((n_tokens < 4) || 3574 parser_read_uint32(&pcp, tokens[1]) || 3575 (pcp > 7) || 3576 parser_read_uint32(&dei, tokens[2]) || 3577 (dei > 1) || 3578 parser_read_uint32(&vid, tokens[3]) || 3579 (vid > 0xFFF)) 3580 return 0; 3581 3582 a->encap.vxlan.vlan.pcp = pcp; 3583 a->encap.vxlan.vlan.dei = dei; 3584 a->encap.vxlan.vlan.vid = vid; 3585 3586 n_tokens -= 4; 3587 tokens += 4; 3588 n += 4; 3589 } 3590 3591 /* ipv4 <sa> <da> <dscp> <ttl> 3592 | ipv6 <sa> <da> <flow_label> <dscp> <hop_limit> */ 3593 if (strcmp(tokens[0], "ipv4") == 0) { 3594 struct in_addr sa, da; 3595 uint8_t dscp, ttl; 3596 3597 if ((n_tokens < 5) || 3598 parse_ipv4_addr(tokens[1], &sa) || 3599 parse_ipv4_addr(tokens[2], &da) || 3600 parser_read_uint8(&dscp, tokens[3]) || 3601 (dscp > 64) || 3602 parser_read_uint8(&ttl, tokens[4])) 3603 return 0; 3604 3605 a->encap.vxlan.ipv4.sa = rte_be_to_cpu_32(sa.s_addr); 3606 a->encap.vxlan.ipv4.da = rte_be_to_cpu_32(da.s_addr); 3607 a->encap.vxlan.ipv4.dscp = dscp; 3608 a->encap.vxlan.ipv4.ttl = ttl; 3609 3610 n_tokens -= 5; 3611 tokens += 5; 3612 n += 5; 3613 } else if (strcmp(tokens[0], "ipv6") == 0) { 3614 struct in6_addr sa, da; 3615 uint32_t flow_label; 3616 uint8_t dscp, hop_limit; 3617 3618 if ((n_tokens < 6) || 3619 parse_ipv6_addr(tokens[1], &sa) || 3620 parse_ipv6_addr(tokens[2], &da) || 3621 parser_read_uint32(&flow_label, tokens[3]) || 3622 parser_read_uint8(&dscp, tokens[4]) || 3623 (dscp > 64) || 3624 parser_read_uint8(&hop_limit, tokens[5])) 3625 return 0; 3626 3627 memcpy(a->encap.vxlan.ipv6.sa, sa.s6_addr, 16); 3628 memcpy(a->encap.vxlan.ipv6.da, da.s6_addr, 16); 3629 a->encap.vxlan.ipv6.flow_label = flow_label; 3630 a->encap.vxlan.ipv6.dscp = dscp; 3631 a->encap.vxlan.ipv6.hop_limit = hop_limit; 3632 3633 n_tokens -= 6; 3634 tokens += 6; 3635 n += 6; 3636 } else 3637 return 0; 3638 3639 /* udp <sp> <dp> */ 3640 if ((n_tokens < 3) || 3641 strcmp(tokens[0], "udp") || 3642 parser_read_uint16(&a->encap.vxlan.udp.sp, tokens[1]) || 3643 parser_read_uint16(&a->encap.vxlan.udp.dp, tokens[2])) 3644 return 0; 3645 3646 n_tokens -= 3; 3647 tokens += 3; 3648 n += 3; 3649 3650 /* vxlan <vni> */ 3651 if ((n_tokens < 2) || 3652 strcmp(tokens[0], "vxlan") || 3653 parser_read_uint32(&a->encap.vxlan.vxlan.vni, tokens[1]) || 3654 (a->encap.vxlan.vxlan.vni > 0xFFFFFF)) 3655 return 0; 3656 3657 n_tokens -= 2; 3658 tokens += 2; 3659 n += 2; 3660 3661 a->encap.type = RTE_TABLE_ACTION_ENCAP_VXLAN; 3662 a->action_mask |= 1 << RTE_TABLE_ACTION_ENCAP; 3663 return 1 + n; 3664 } 3665 3666 return 0; 3667 } 3668 3669 static uint32_t 3670 parse_table_action_nat(char **tokens, 3671 uint32_t n_tokens, 3672 struct table_rule_action *a) 3673 { 3674 if ((n_tokens < 4) || 3675 strcmp(tokens[0], "nat")) 3676 return 0; 3677 3678 if (strcmp(tokens[1], "ipv4") == 0) { 3679 struct in_addr addr; 3680 uint16_t port; 3681 3682 if (parse_ipv4_addr(tokens[2], &addr) || 3683 parser_read_uint16(&port, tokens[3])) 3684 return 0; 3685 3686 a->nat.ip_version = 1; 3687 a->nat.addr.ipv4 = rte_be_to_cpu_32(addr.s_addr); 3688 a->nat.port = port; 3689 a->action_mask |= 1 << RTE_TABLE_ACTION_NAT; 3690 return 4; 3691 } 3692 3693 if (strcmp(tokens[1], "ipv6") == 0) { 3694 struct in6_addr addr; 3695 uint16_t port; 3696 3697 if (parse_ipv6_addr(tokens[2], &addr) || 3698 parser_read_uint16(&port, tokens[3])) 3699 return 0; 3700 3701 a->nat.ip_version = 0; 3702 memcpy(a->nat.addr.ipv6, addr.s6_addr, 16); 3703 a->nat.port = port; 3704 a->action_mask |= 1 << RTE_TABLE_ACTION_NAT; 3705 return 4; 3706 } 3707 3708 return 0; 3709 } 3710 3711 static uint32_t 3712 parse_table_action_ttl(char **tokens, 3713 uint32_t n_tokens, 3714 struct table_rule_action *a) 3715 { 3716 if ((n_tokens < 2) || 3717 strcmp(tokens[0], "ttl")) 3718 return 0; 3719 3720 if (strcmp(tokens[1], "dec") == 0) 3721 a->ttl.decrement = 1; 3722 else if (strcmp(tokens[1], "keep") == 0) 3723 a->ttl.decrement = 0; 3724 else 3725 return 0; 3726 3727 a->action_mask |= 1 << RTE_TABLE_ACTION_TTL; 3728 return 2; 3729 } 3730 3731 static uint32_t 3732 parse_table_action_stats(char **tokens, 3733 uint32_t n_tokens, 3734 struct table_rule_action *a) 3735 { 3736 if ((n_tokens < 1) || 3737 strcmp(tokens[0], "stats")) 3738 return 0; 3739 3740 a->stats.n_packets = 0; 3741 a->stats.n_bytes = 0; 3742 a->action_mask |= 1 << RTE_TABLE_ACTION_STATS; 3743 return 1; 3744 } 3745 3746 static uint32_t 3747 parse_table_action_time(char **tokens, 3748 uint32_t n_tokens, 3749 struct table_rule_action *a) 3750 { 3751 if ((n_tokens < 1) || 3752 strcmp(tokens[0], "time")) 3753 return 0; 3754 3755 a->time.time = rte_rdtsc(); 3756 a->action_mask |= 1 << RTE_TABLE_ACTION_TIME; 3757 return 1; 3758 } 3759 3760 static void 3761 parse_free_sym_crypto_param_data(struct rte_table_action_sym_crypto_params *p) 3762 { 3763 struct rte_crypto_sym_xform *xform[2] = {NULL}; 3764 uint32_t i; 3765 3766 xform[0] = p->xform; 3767 if (xform[0]) 3768 xform[1] = xform[0]->next; 3769 3770 for (i = 0; i < 2; i++) { 3771 if (xform[i] == NULL) 3772 continue; 3773 3774 switch (xform[i]->type) { 3775 case RTE_CRYPTO_SYM_XFORM_CIPHER: 3776 if (p->cipher_auth.cipher_iv.val) 3777 free(p->cipher_auth.cipher_iv.val); 3778 if (p->cipher_auth.cipher_iv_update.val) 3779 free(p->cipher_auth.cipher_iv_update.val); 3780 break; 3781 case RTE_CRYPTO_SYM_XFORM_AUTH: 3782 if (p->cipher_auth.auth_iv.val) 3783 free(p->cipher_auth.cipher_iv.val); 3784 if (p->cipher_auth.auth_iv_update.val) 3785 free(p->cipher_auth.cipher_iv_update.val); 3786 break; 3787 case RTE_CRYPTO_SYM_XFORM_AEAD: 3788 if (p->aead.iv.val) 3789 free(p->aead.iv.val); 3790 if (p->aead.aad.val) 3791 free(p->aead.aad.val); 3792 break; 3793 default: 3794 continue; 3795 } 3796 } 3797 3798 } 3799 3800 static struct rte_crypto_sym_xform * 3801 parse_table_action_cipher(struct rte_table_action_sym_crypto_params *p, 3802 uint8_t *key, uint32_t max_key_len, char **tokens, 3803 uint32_t n_tokens, uint32_t encrypt, uint32_t *used_n_tokens) 3804 { 3805 struct rte_crypto_sym_xform *xform_cipher; 3806 int status; 3807 size_t len; 3808 3809 if (n_tokens < 7 || strcmp(tokens[1], "cipher_algo") || 3810 strcmp(tokens[3], "cipher_key") || 3811 strcmp(tokens[5], "cipher_iv")) 3812 return NULL; 3813 3814 xform_cipher = calloc(1, sizeof(*xform_cipher)); 3815 if (xform_cipher == NULL) 3816 return NULL; 3817 3818 xform_cipher->type = RTE_CRYPTO_SYM_XFORM_CIPHER; 3819 xform_cipher->cipher.op = encrypt ? RTE_CRYPTO_CIPHER_OP_ENCRYPT : 3820 RTE_CRYPTO_CIPHER_OP_DECRYPT; 3821 3822 /* cipher_algo */ 3823 status = rte_cryptodev_get_cipher_algo_enum( 3824 &xform_cipher->cipher.algo, tokens[2]); 3825 if (status < 0) 3826 goto error_exit; 3827 3828 /* cipher_key */ 3829 len = strlen(tokens[4]); 3830 if (len / 2 > max_key_len) { 3831 status = -ENOMEM; 3832 goto error_exit; 3833 } 3834 3835 status = parse_hex_string(tokens[4], key, (uint32_t *)&len); 3836 if (status < 0) 3837 goto error_exit; 3838 3839 xform_cipher->cipher.key.data = key; 3840 xform_cipher->cipher.key.length = (uint16_t)len; 3841 3842 /* cipher_iv */ 3843 len = strlen(tokens[6]); 3844 3845 p->cipher_auth.cipher_iv.val = calloc(1, len / 2 + 1); 3846 if (p->cipher_auth.cipher_iv.val == NULL) 3847 goto error_exit; 3848 3849 status = parse_hex_string(tokens[6], 3850 p->cipher_auth.cipher_iv.val, 3851 (uint32_t *)&len); 3852 if (status < 0) 3853 goto error_exit; 3854 3855 xform_cipher->cipher.iv.length = (uint16_t)len; 3856 xform_cipher->cipher.iv.offset = RTE_TABLE_ACTION_SYM_CRYPTO_IV_OFFSET; 3857 p->cipher_auth.cipher_iv.length = (uint32_t)len; 3858 *used_n_tokens = 7; 3859 3860 return xform_cipher; 3861 3862 error_exit: 3863 if (p->cipher_auth.cipher_iv.val) { 3864 free(p->cipher_auth.cipher_iv.val); 3865 p->cipher_auth.cipher_iv.val = NULL; 3866 } 3867 3868 free(xform_cipher); 3869 3870 return NULL; 3871 } 3872 3873 static struct rte_crypto_sym_xform * 3874 parse_table_action_cipher_auth(struct rte_table_action_sym_crypto_params *p, 3875 uint8_t *key, uint32_t max_key_len, char **tokens, 3876 uint32_t n_tokens, uint32_t encrypt, uint32_t *used_n_tokens) 3877 { 3878 struct rte_crypto_sym_xform *xform_cipher; 3879 struct rte_crypto_sym_xform *xform_auth; 3880 int status; 3881 size_t len; 3882 3883 if (n_tokens < 13 || 3884 strcmp(tokens[7], "auth_algo") || 3885 strcmp(tokens[9], "auth_key") || 3886 strcmp(tokens[11], "digest_size")) 3887 return NULL; 3888 3889 xform_auth = calloc(1, sizeof(*xform_auth)); 3890 if (xform_auth == NULL) 3891 return NULL; 3892 3893 xform_auth->type = RTE_CRYPTO_SYM_XFORM_AUTH; 3894 xform_auth->auth.op = encrypt ? RTE_CRYPTO_AUTH_OP_GENERATE : 3895 RTE_CRYPTO_AUTH_OP_VERIFY; 3896 3897 /* auth_algo */ 3898 status = rte_cryptodev_get_auth_algo_enum(&xform_auth->auth.algo, 3899 tokens[8]); 3900 if (status < 0) 3901 goto error_exit; 3902 3903 /* auth_key */ 3904 len = strlen(tokens[10]); 3905 if (len / 2 > max_key_len) { 3906 status = -ENOMEM; 3907 goto error_exit; 3908 } 3909 3910 status = parse_hex_string(tokens[10], key, (uint32_t *)&len); 3911 if (status < 0) 3912 goto error_exit; 3913 3914 xform_auth->auth.key.data = key; 3915 xform_auth->auth.key.length = (uint16_t)len; 3916 3917 key += xform_auth->auth.key.length; 3918 max_key_len -= xform_auth->auth.key.length; 3919 3920 if (strcmp(tokens[11], "digest_size")) 3921 goto error_exit; 3922 3923 status = parser_read_uint16(&xform_auth->auth.digest_length, 3924 tokens[12]); 3925 if (status < 0) 3926 goto error_exit; 3927 3928 xform_cipher = parse_table_action_cipher(p, key, max_key_len, tokens, 3929 7, encrypt, used_n_tokens); 3930 if (xform_cipher == NULL) 3931 goto error_exit; 3932 3933 *used_n_tokens += 6; 3934 3935 if (encrypt) { 3936 xform_cipher->next = xform_auth; 3937 return xform_cipher; 3938 } else { 3939 xform_auth->next = xform_cipher; 3940 return xform_auth; 3941 } 3942 3943 error_exit: 3944 if (p->cipher_auth.auth_iv.val) { 3945 free(p->cipher_auth.auth_iv.val); 3946 p->cipher_auth.auth_iv.val = 0; 3947 } 3948 3949 free(xform_auth); 3950 3951 return NULL; 3952 } 3953 3954 static struct rte_crypto_sym_xform * 3955 parse_table_action_aead(struct rte_table_action_sym_crypto_params *p, 3956 uint8_t *key, uint32_t max_key_len, char **tokens, 3957 uint32_t n_tokens, uint32_t encrypt, uint32_t *used_n_tokens) 3958 { 3959 struct rte_crypto_sym_xform *xform_aead; 3960 int status; 3961 size_t len; 3962 3963 if (n_tokens < 11 || strcmp(tokens[1], "aead_algo") || 3964 strcmp(tokens[3], "aead_key") || 3965 strcmp(tokens[5], "aead_iv") || 3966 strcmp(tokens[7], "aead_aad") || 3967 strcmp(tokens[9], "digest_size")) 3968 return NULL; 3969 3970 xform_aead = calloc(1, sizeof(*xform_aead)); 3971 if (xform_aead == NULL) 3972 return NULL; 3973 3974 xform_aead->type = RTE_CRYPTO_SYM_XFORM_AEAD; 3975 xform_aead->aead.op = encrypt ? RTE_CRYPTO_AEAD_OP_ENCRYPT : 3976 RTE_CRYPTO_AEAD_OP_DECRYPT; 3977 3978 /* aead_algo */ 3979 status = rte_cryptodev_get_aead_algo_enum(&xform_aead->aead.algo, 3980 tokens[2]); 3981 if (status < 0) 3982 goto error_exit; 3983 3984 /* aead_key */ 3985 len = strlen(tokens[4]); 3986 if (len / 2 > max_key_len) { 3987 status = -ENOMEM; 3988 goto error_exit; 3989 } 3990 3991 status = parse_hex_string(tokens[4], key, (uint32_t *)&len); 3992 if (status < 0) 3993 goto error_exit; 3994 3995 xform_aead->aead.key.data = key; 3996 xform_aead->aead.key.length = (uint16_t)len; 3997 3998 /* aead_iv */ 3999 len = strlen(tokens[6]); 4000 p->aead.iv.val = calloc(1, len / 2 + 1); 4001 if (p->aead.iv.val == NULL) 4002 goto error_exit; 4003 4004 status = parse_hex_string(tokens[6], p->aead.iv.val, 4005 (uint32_t *)&len); 4006 if (status < 0) 4007 goto error_exit; 4008 4009 xform_aead->aead.iv.length = (uint16_t)len; 4010 xform_aead->aead.iv.offset = RTE_TABLE_ACTION_SYM_CRYPTO_IV_OFFSET; 4011 p->aead.iv.length = (uint32_t)len; 4012 4013 /* aead_aad */ 4014 len = strlen(tokens[8]); 4015 p->aead.aad.val = calloc(1, len / 2 + 1); 4016 if (p->aead.aad.val == NULL) 4017 goto error_exit; 4018 4019 status = parse_hex_string(tokens[8], p->aead.aad.val, (uint32_t *)&len); 4020 if (status < 0) 4021 goto error_exit; 4022 4023 xform_aead->aead.aad_length = (uint16_t)len; 4024 p->aead.aad.length = (uint32_t)len; 4025 4026 /* digest_size */ 4027 status = parser_read_uint16(&xform_aead->aead.digest_length, 4028 tokens[10]); 4029 if (status < 0) 4030 goto error_exit; 4031 4032 *used_n_tokens = 11; 4033 4034 return xform_aead; 4035 4036 error_exit: 4037 if (p->aead.iv.val) { 4038 free(p->aead.iv.val); 4039 p->aead.iv.val = NULL; 4040 } 4041 if (p->aead.aad.val) { 4042 free(p->aead.aad.val); 4043 p->aead.aad.val = NULL; 4044 } 4045 4046 free(xform_aead); 4047 4048 return NULL; 4049 } 4050 4051 4052 static uint32_t 4053 parse_table_action_sym_crypto(char **tokens, 4054 uint32_t n_tokens, 4055 struct table_rule_action *a) 4056 { 4057 struct rte_table_action_sym_crypto_params *p = &a->sym_crypto; 4058 struct rte_crypto_sym_xform *xform = NULL; 4059 uint8_t *key = a->sym_crypto_key; 4060 uint32_t max_key_len = SYM_CRYPTO_MAX_KEY_SIZE; 4061 uint32_t used_n_tokens; 4062 uint32_t encrypt; 4063 int status; 4064 4065 if ((n_tokens < 12) || 4066 strcmp(tokens[0], "sym_crypto") || 4067 strcmp(tokens[2], "type")) 4068 return 0; 4069 4070 memset(p, 0, sizeof(*p)); 4071 4072 if (strcmp(tokens[1], "encrypt") == 0) 4073 encrypt = 1; 4074 else 4075 encrypt = 0; 4076 4077 status = parser_read_uint32(&p->data_offset, tokens[n_tokens - 1]); 4078 if (status < 0) 4079 return 0; 4080 4081 if (strcmp(tokens[3], "cipher") == 0) { 4082 tokens += 3; 4083 n_tokens -= 3; 4084 4085 xform = parse_table_action_cipher(p, key, max_key_len, tokens, 4086 n_tokens, encrypt, &used_n_tokens); 4087 } else if (strcmp(tokens[3], "cipher_auth") == 0) { 4088 tokens += 3; 4089 n_tokens -= 3; 4090 4091 xform = parse_table_action_cipher_auth(p, key, max_key_len, 4092 tokens, n_tokens, encrypt, &used_n_tokens); 4093 } else if (strcmp(tokens[3], "aead") == 0) { 4094 tokens += 3; 4095 n_tokens -= 3; 4096 4097 xform = parse_table_action_aead(p, key, max_key_len, tokens, 4098 n_tokens, encrypt, &used_n_tokens); 4099 } 4100 4101 if (xform == NULL) 4102 return 0; 4103 4104 p->xform = xform; 4105 4106 if (strcmp(tokens[used_n_tokens], "data_offset")) { 4107 parse_free_sym_crypto_param_data(p); 4108 return 0; 4109 } 4110 4111 a->action_mask |= 1 << RTE_TABLE_ACTION_SYM_CRYPTO; 4112 4113 return used_n_tokens + 5; 4114 } 4115 4116 static uint32_t 4117 parse_table_action_tag(char **tokens, 4118 uint32_t n_tokens, 4119 struct table_rule_action *a) 4120 { 4121 if ((n_tokens < 2) || 4122 strcmp(tokens[0], "tag")) 4123 return 0; 4124 4125 if (parser_read_uint32(&a->tag.tag, tokens[1])) 4126 return 0; 4127 4128 a->action_mask |= 1 << RTE_TABLE_ACTION_TAG; 4129 return 2; 4130 } 4131 4132 static uint32_t 4133 parse_table_action_decap(char **tokens, 4134 uint32_t n_tokens, 4135 struct table_rule_action *a) 4136 { 4137 if ((n_tokens < 2) || 4138 strcmp(tokens[0], "decap")) 4139 return 0; 4140 4141 if (parser_read_uint16(&a->decap.n, tokens[1])) 4142 return 0; 4143 4144 a->action_mask |= 1 << RTE_TABLE_ACTION_DECAP; 4145 return 2; 4146 } 4147 4148 static uint32_t 4149 parse_table_action(char **tokens, 4150 uint32_t n_tokens, 4151 char *out, 4152 size_t out_size, 4153 struct table_rule_action *a) 4154 { 4155 uint32_t n_tokens0 = n_tokens; 4156 4157 memset(a, 0, sizeof(*a)); 4158 4159 if ((n_tokens < 2) || 4160 strcmp(tokens[0], "action")) 4161 return 0; 4162 4163 tokens++; 4164 n_tokens--; 4165 4166 if (n_tokens && (strcmp(tokens[0], "fwd") == 0)) { 4167 uint32_t n; 4168 4169 n = parse_table_action_fwd(tokens, n_tokens, a); 4170 if (n == 0) { 4171 snprintf(out, out_size, MSG_ARG_INVALID, 4172 "action fwd"); 4173 return 0; 4174 } 4175 4176 tokens += n; 4177 n_tokens -= n; 4178 } 4179 4180 if (n_tokens && (strcmp(tokens[0], "balance") == 0)) { 4181 uint32_t n; 4182 4183 n = parse_table_action_balance(tokens, n_tokens, a); 4184 if (n == 0) { 4185 snprintf(out, out_size, MSG_ARG_INVALID, 4186 "action balance"); 4187 return 0; 4188 } 4189 4190 tokens += n; 4191 n_tokens -= n; 4192 } 4193 4194 if (n_tokens && (strcmp(tokens[0], "meter") == 0)) { 4195 uint32_t n; 4196 4197 n = parse_table_action_meter(tokens, n_tokens, a); 4198 if (n == 0) { 4199 snprintf(out, out_size, MSG_ARG_INVALID, 4200 "action meter"); 4201 return 0; 4202 } 4203 4204 tokens += n; 4205 n_tokens -= n; 4206 } 4207 4208 if (n_tokens && (strcmp(tokens[0], "tm") == 0)) { 4209 uint32_t n; 4210 4211 n = parse_table_action_tm(tokens, n_tokens, a); 4212 if (n == 0) { 4213 snprintf(out, out_size, MSG_ARG_INVALID, 4214 "action tm"); 4215 return 0; 4216 } 4217 4218 tokens += n; 4219 n_tokens -= n; 4220 } 4221 4222 if (n_tokens && (strcmp(tokens[0], "encap") == 0)) { 4223 uint32_t n; 4224 4225 n = parse_table_action_encap(tokens, n_tokens, a); 4226 if (n == 0) { 4227 snprintf(out, out_size, MSG_ARG_INVALID, 4228 "action encap"); 4229 return 0; 4230 } 4231 4232 tokens += n; 4233 n_tokens -= n; 4234 } 4235 4236 if (n_tokens && (strcmp(tokens[0], "nat") == 0)) { 4237 uint32_t n; 4238 4239 n = parse_table_action_nat(tokens, n_tokens, a); 4240 if (n == 0) { 4241 snprintf(out, out_size, MSG_ARG_INVALID, 4242 "action nat"); 4243 return 0; 4244 } 4245 4246 tokens += n; 4247 n_tokens -= n; 4248 } 4249 4250 if (n_tokens && (strcmp(tokens[0], "ttl") == 0)) { 4251 uint32_t n; 4252 4253 n = parse_table_action_ttl(tokens, n_tokens, a); 4254 if (n == 0) { 4255 snprintf(out, out_size, MSG_ARG_INVALID, 4256 "action ttl"); 4257 return 0; 4258 } 4259 4260 tokens += n; 4261 n_tokens -= n; 4262 } 4263 4264 if (n_tokens && (strcmp(tokens[0], "stats") == 0)) { 4265 uint32_t n; 4266 4267 n = parse_table_action_stats(tokens, n_tokens, a); 4268 if (n == 0) { 4269 snprintf(out, out_size, MSG_ARG_INVALID, 4270 "action stats"); 4271 return 0; 4272 } 4273 4274 tokens += n; 4275 n_tokens -= n; 4276 } 4277 4278 if (n_tokens && (strcmp(tokens[0], "time") == 0)) { 4279 uint32_t n; 4280 4281 n = parse_table_action_time(tokens, n_tokens, a); 4282 if (n == 0) { 4283 snprintf(out, out_size, MSG_ARG_INVALID, 4284 "action time"); 4285 return 0; 4286 } 4287 4288 tokens += n; 4289 n_tokens -= n; 4290 } 4291 4292 if (n_tokens && (strcmp(tokens[0], "sym_crypto") == 0)) { 4293 uint32_t n; 4294 4295 n = parse_table_action_sym_crypto(tokens, n_tokens, a); 4296 if (n == 0) { 4297 snprintf(out, out_size, MSG_ARG_INVALID, 4298 "action sym_crypto"); 4299 } 4300 4301 tokens += n; 4302 n_tokens -= n; 4303 } 4304 4305 if (n_tokens && (strcmp(tokens[0], "tag") == 0)) { 4306 uint32_t n; 4307 4308 n = parse_table_action_tag(tokens, n_tokens, a); 4309 if (n == 0) { 4310 snprintf(out, out_size, MSG_ARG_INVALID, 4311 "action tag"); 4312 return 0; 4313 } 4314 4315 tokens += n; 4316 n_tokens -= n; 4317 } 4318 4319 if (n_tokens && (strcmp(tokens[0], "decap") == 0)) { 4320 uint32_t n; 4321 4322 n = parse_table_action_decap(tokens, n_tokens, a); 4323 if (n == 0) { 4324 snprintf(out, out_size, MSG_ARG_INVALID, 4325 "action decap"); 4326 return 0; 4327 } 4328 4329 tokens += n; 4330 n_tokens -= n; 4331 } 4332 4333 if (n_tokens0 - n_tokens == 1) { 4334 snprintf(out, out_size, MSG_ARG_INVALID, "action"); 4335 return 0; 4336 } 4337 4338 return n_tokens0 - n_tokens; 4339 } 4340 4341 4342 static const char cmd_pipeline_table_rule_add_help[] = 4343 "pipeline <pipeline_name> table <table_id> rule add\n" 4344 " match <match>\n" 4345 " action <table_action>\n"; 4346 4347 static void 4348 cmd_pipeline_table_rule_add(char **tokens, 4349 uint32_t n_tokens, 4350 char *out, 4351 size_t out_size) 4352 { 4353 struct table_rule_match m; 4354 struct table_rule_action a; 4355 char *pipeline_name; 4356 uint32_t table_id, t0, n_tokens_parsed; 4357 int status; 4358 4359 if (n_tokens < 8) { 4360 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 4361 return; 4362 } 4363 4364 pipeline_name = tokens[1]; 4365 4366 if (strcmp(tokens[2], "table") != 0) { 4367 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "table"); 4368 return; 4369 } 4370 4371 if (parser_read_uint32(&table_id, tokens[3]) != 0) { 4372 snprintf(out, out_size, MSG_ARG_INVALID, "table_id"); 4373 return; 4374 } 4375 4376 if (strcmp(tokens[4], "rule") != 0) { 4377 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rule"); 4378 return; 4379 } 4380 4381 if (strcmp(tokens[5], "add") != 0) { 4382 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "add"); 4383 return; 4384 } 4385 4386 t0 = 6; 4387 4388 /* match */ 4389 n_tokens_parsed = parse_match(tokens + t0, 4390 n_tokens - t0, 4391 out, 4392 out_size, 4393 &m); 4394 if (n_tokens_parsed == 0) 4395 return; 4396 t0 += n_tokens_parsed; 4397 4398 /* action */ 4399 n_tokens_parsed = parse_table_action(tokens + t0, 4400 n_tokens - t0, 4401 out, 4402 out_size, 4403 &a); 4404 if (n_tokens_parsed == 0) 4405 return; 4406 t0 += n_tokens_parsed; 4407 4408 if (t0 != n_tokens) { 4409 snprintf(out, out_size, MSG_ARG_INVALID, tokens[0]); 4410 return; 4411 } 4412 4413 status = pipeline_table_rule_add(pipeline_name, table_id, &m, &a); 4414 if (status) { 4415 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 4416 return; 4417 } 4418 4419 if (a.action_mask & 1 << RTE_TABLE_ACTION_SYM_CRYPTO) 4420 parse_free_sym_crypto_param_data(&a.sym_crypto); 4421 } 4422 4423 4424 static const char cmd_pipeline_table_rule_add_default_help[] = 4425 "pipeline <pipeline_name> table <table_id> rule add\n" 4426 " match\n" 4427 " default\n" 4428 " action\n" 4429 " fwd\n" 4430 " drop\n" 4431 " | port <port_id>\n" 4432 " | meta\n" 4433 " | table <table_id>\n"; 4434 4435 static void 4436 cmd_pipeline_table_rule_add_default(char **tokens, 4437 uint32_t n_tokens, 4438 char *out, 4439 size_t out_size) 4440 { 4441 struct table_rule_action action; 4442 char *pipeline_name; 4443 uint32_t table_id; 4444 int status; 4445 4446 if ((n_tokens != 11) && (n_tokens != 12)) { 4447 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 4448 return; 4449 } 4450 4451 pipeline_name = tokens[1]; 4452 4453 if (strcmp(tokens[2], "table") != 0) { 4454 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "table"); 4455 return; 4456 } 4457 4458 if (parser_read_uint32(&table_id, tokens[3]) != 0) { 4459 snprintf(out, out_size, MSG_ARG_INVALID, "table_id"); 4460 return; 4461 } 4462 4463 if (strcmp(tokens[4], "rule") != 0) { 4464 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rule"); 4465 return; 4466 } 4467 4468 if (strcmp(tokens[5], "add") != 0) { 4469 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "add"); 4470 return; 4471 } 4472 4473 if (strcmp(tokens[6], "match") != 0) { 4474 snprintf(out, out_size, MSG_ARG_INVALID, "match"); 4475 return; 4476 } 4477 4478 if (strcmp(tokens[7], "default") != 0) { 4479 snprintf(out, out_size, MSG_ARG_INVALID, "default"); 4480 return; 4481 } 4482 4483 if (strcmp(tokens[8], "action") != 0) { 4484 snprintf(out, out_size, MSG_ARG_INVALID, "action"); 4485 return; 4486 } 4487 4488 if (strcmp(tokens[9], "fwd") != 0) { 4489 snprintf(out, out_size, MSG_ARG_INVALID, "fwd"); 4490 return; 4491 } 4492 4493 action.action_mask = 1 << RTE_TABLE_ACTION_FWD; 4494 4495 if (strcmp(tokens[10], "drop") == 0) { 4496 if (n_tokens != 11) { 4497 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 4498 return; 4499 } 4500 4501 action.fwd.action = RTE_PIPELINE_ACTION_DROP; 4502 } else if (strcmp(tokens[10], "port") == 0) { 4503 uint32_t id; 4504 4505 if (n_tokens != 12) { 4506 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 4507 return; 4508 } 4509 4510 if (parser_read_uint32(&id, tokens[11]) != 0) { 4511 snprintf(out, out_size, MSG_ARG_INVALID, "port_id"); 4512 return; 4513 } 4514 4515 action.fwd.action = RTE_PIPELINE_ACTION_PORT; 4516 action.fwd.id = id; 4517 } else if (strcmp(tokens[10], "meta") == 0) { 4518 if (n_tokens != 11) { 4519 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 4520 return; 4521 } 4522 4523 action.fwd.action = RTE_PIPELINE_ACTION_PORT_META; 4524 } else if (strcmp(tokens[10], "table") == 0) { 4525 uint32_t id; 4526 4527 if (n_tokens != 12) { 4528 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 4529 return; 4530 } 4531 4532 if (parser_read_uint32(&id, tokens[11]) != 0) { 4533 snprintf(out, out_size, MSG_ARG_INVALID, "table_id"); 4534 return; 4535 } 4536 4537 action.fwd.action = RTE_PIPELINE_ACTION_TABLE; 4538 action.fwd.id = id; 4539 } else { 4540 snprintf(out, out_size, MSG_ARG_INVALID, 4541 "drop or port or meta or table"); 4542 return; 4543 } 4544 4545 status = pipeline_table_rule_add_default(pipeline_name, 4546 table_id, 4547 &action); 4548 if (status) { 4549 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 4550 return; 4551 } 4552 } 4553 4554 4555 static const char cmd_pipeline_table_rule_add_bulk_help[] = 4556 "pipeline <pipeline_name> table <table_id> rule add bulk <file_name>\n" 4557 "\n" 4558 " File <file_name>:\n" 4559 " - line format: match <match> action <action>\n"; 4560 4561 static int 4562 cli_rule_file_process(const char *file_name, 4563 size_t line_len_max, 4564 struct table_rule_list **rule_list, 4565 uint32_t *n_rules, 4566 uint32_t *line_number, 4567 char *out, 4568 size_t out_size); 4569 4570 static void 4571 cmd_pipeline_table_rule_add_bulk(char **tokens, 4572 uint32_t n_tokens, 4573 char *out, 4574 size_t out_size) 4575 { 4576 struct table_rule_list *list = NULL; 4577 char *pipeline_name, *file_name; 4578 uint32_t table_id, n_rules, n_rules_added, n_rules_not_added, line_number; 4579 int status; 4580 4581 if (n_tokens != 8) { 4582 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 4583 return; 4584 } 4585 4586 pipeline_name = tokens[1]; 4587 4588 if (strcmp(tokens[2], "table") != 0) { 4589 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "table"); 4590 return; 4591 } 4592 4593 if (parser_read_uint32(&table_id, tokens[3]) != 0) { 4594 snprintf(out, out_size, MSG_ARG_INVALID, "table_id"); 4595 return; 4596 } 4597 4598 if (strcmp(tokens[4], "rule") != 0) { 4599 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rule"); 4600 return; 4601 } 4602 4603 if (strcmp(tokens[5], "add") != 0) { 4604 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "add"); 4605 return; 4606 } 4607 4608 if (strcmp(tokens[6], "bulk") != 0) { 4609 snprintf(out, out_size, MSG_ARG_INVALID, "bulk"); 4610 return; 4611 } 4612 4613 file_name = tokens[7]; 4614 4615 /* Load rules from file. */ 4616 status = cli_rule_file_process(file_name, 4617 1024, 4618 &list, 4619 &n_rules, 4620 &line_number, 4621 out, 4622 out_size); 4623 if (status) { 4624 snprintf(out, out_size, MSG_FILE_ERR, file_name, line_number); 4625 return; 4626 } 4627 4628 /* Rule bulk add */ 4629 status = pipeline_table_rule_add_bulk(pipeline_name, 4630 table_id, 4631 list, 4632 &n_rules_added, 4633 &n_rules_not_added); 4634 if (status) { 4635 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 4636 return; 4637 } 4638 4639 snprintf(out, out_size, "Added %u rules out of %u.\n", 4640 n_rules_added, 4641 n_rules); 4642 } 4643 4644 4645 static const char cmd_pipeline_table_rule_delete_help[] = 4646 "pipeline <pipeline_name> table <table_id> rule delete\n" 4647 " match <match>\n"; 4648 4649 static void 4650 cmd_pipeline_table_rule_delete(char **tokens, 4651 uint32_t n_tokens, 4652 char *out, 4653 size_t out_size) 4654 { 4655 struct table_rule_match m; 4656 char *pipeline_name; 4657 uint32_t table_id, n_tokens_parsed, t0; 4658 int status; 4659 4660 if (n_tokens < 8) { 4661 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 4662 return; 4663 } 4664 4665 pipeline_name = tokens[1]; 4666 4667 if (strcmp(tokens[2], "table") != 0) { 4668 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "table"); 4669 return; 4670 } 4671 4672 if (parser_read_uint32(&table_id, tokens[3]) != 0) { 4673 snprintf(out, out_size, MSG_ARG_INVALID, "table_id"); 4674 return; 4675 } 4676 4677 if (strcmp(tokens[4], "rule") != 0) { 4678 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rule"); 4679 return; 4680 } 4681 4682 if (strcmp(tokens[5], "delete") != 0) { 4683 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "delete"); 4684 return; 4685 } 4686 4687 t0 = 6; 4688 4689 /* match */ 4690 n_tokens_parsed = parse_match(tokens + t0, 4691 n_tokens - t0, 4692 out, 4693 out_size, 4694 &m); 4695 if (n_tokens_parsed == 0) 4696 return; 4697 t0 += n_tokens_parsed; 4698 4699 if (n_tokens != t0) { 4700 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 4701 return; 4702 } 4703 4704 status = pipeline_table_rule_delete(pipeline_name, 4705 table_id, 4706 &m); 4707 if (status) { 4708 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 4709 return; 4710 } 4711 } 4712 4713 4714 static const char cmd_pipeline_table_rule_delete_default_help[] = 4715 "pipeline <pipeline_name> table <table_id> rule delete\n" 4716 " match\n" 4717 " default\n"; 4718 4719 static void 4720 cmd_pipeline_table_rule_delete_default(char **tokens, 4721 uint32_t n_tokens, 4722 char *out, 4723 size_t out_size) 4724 { 4725 char *pipeline_name; 4726 uint32_t table_id; 4727 int status; 4728 4729 if (n_tokens != 8) { 4730 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 4731 return; 4732 } 4733 4734 pipeline_name = tokens[1]; 4735 4736 if (strcmp(tokens[2], "table") != 0) { 4737 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "table"); 4738 return; 4739 } 4740 4741 if (parser_read_uint32(&table_id, tokens[3]) != 0) { 4742 snprintf(out, out_size, MSG_ARG_INVALID, "table_id"); 4743 return; 4744 } 4745 4746 if (strcmp(tokens[4], "rule") != 0) { 4747 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rule"); 4748 return; 4749 } 4750 4751 if (strcmp(tokens[5], "delete") != 0) { 4752 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "delete"); 4753 return; 4754 } 4755 4756 if (strcmp(tokens[6], "match") != 0) { 4757 snprintf(out, out_size, MSG_ARG_INVALID, "match"); 4758 return; 4759 } 4760 4761 if (strcmp(tokens[7], "default") != 0) { 4762 snprintf(out, out_size, MSG_ARG_INVALID, "default"); 4763 return; 4764 } 4765 4766 status = pipeline_table_rule_delete_default(pipeline_name, 4767 table_id); 4768 if (status) { 4769 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 4770 return; 4771 } 4772 } 4773 4774 static void 4775 ether_addr_show(FILE *f, struct rte_ether_addr *addr) 4776 { 4777 fprintf(f, RTE_ETHER_ADDR_PRT_FMT, RTE_ETHER_ADDR_BYTES(addr)); 4778 } 4779 4780 static void 4781 ipv4_addr_show(FILE *f, uint32_t addr) 4782 { 4783 fprintf(f, "%u.%u.%u.%u", 4784 addr >> 24, 4785 (addr >> 16) & 0xFF, 4786 (addr >> 8) & 0xFF, 4787 addr & 0xFF); 4788 } 4789 4790 static void 4791 ipv6_addr_show(FILE *f, uint8_t *addr) 4792 { 4793 fprintf(f, "%02x%02x:%02x%02x:%02x%02x:%02x%02x:" 4794 "%02x%02x:%02x%02x:%02x%02x:%02x%02x:", 4795 (uint32_t)addr[0], (uint32_t)addr[1], 4796 (uint32_t)addr[2], (uint32_t)addr[3], 4797 (uint32_t)addr[4], (uint32_t)addr[5], 4798 (uint32_t)addr[6], (uint32_t)addr[7], 4799 (uint32_t)addr[8], (uint32_t)addr[9], 4800 (uint32_t)addr[10], (uint32_t)addr[11], 4801 (uint32_t)addr[12], (uint32_t)addr[13], 4802 (uint32_t)addr[14], (uint32_t)addr[15]); 4803 } 4804 4805 static const char * 4806 policer_action_string(enum rte_table_action_policer action) { 4807 switch (action) { 4808 case RTE_TABLE_ACTION_POLICER_COLOR_GREEN: return "G"; 4809 case RTE_TABLE_ACTION_POLICER_COLOR_YELLOW: return "Y"; 4810 case RTE_TABLE_ACTION_POLICER_COLOR_RED: return "R"; 4811 case RTE_TABLE_ACTION_POLICER_DROP: return "D"; 4812 default: return "?"; 4813 } 4814 } 4815 4816 static int 4817 table_rule_show(const char *pipeline_name, 4818 uint32_t table_id, 4819 const char *file_name) 4820 { 4821 struct pipeline *p; 4822 struct table *table; 4823 struct table_rule *rule; 4824 FILE *f = NULL; 4825 uint32_t i; 4826 4827 /* Check input params. */ 4828 if ((pipeline_name == NULL) || 4829 (file_name == NULL)) 4830 return -1; 4831 4832 p = pipeline_find(pipeline_name); 4833 if ((p == NULL) || 4834 (table_id >= p->n_tables)) 4835 return -1; 4836 4837 table = &p->table[table_id]; 4838 4839 /* Open file. */ 4840 f = fopen(file_name, "w"); 4841 if (f == NULL) 4842 return -1; 4843 4844 /* Write table rules to file. */ 4845 TAILQ_FOREACH(rule, &table->rules, node) { 4846 struct table_rule_match *m = &rule->match; 4847 struct table_rule_action *a = &rule->action; 4848 4849 fprintf(f, "match "); 4850 switch (m->match_type) { 4851 case TABLE_ACL: 4852 fprintf(f, "acl priority %u ", 4853 m->match.acl.priority); 4854 4855 fprintf(f, m->match.acl.ip_version ? "ipv4 " : "ipv6 "); 4856 4857 if (m->match.acl.ip_version) 4858 ipv4_addr_show(f, m->match.acl.ipv4.sa); 4859 else 4860 ipv6_addr_show(f, m->match.acl.ipv6.sa); 4861 4862 fprintf(f, "%u", m->match.acl.sa_depth); 4863 4864 if (m->match.acl.ip_version) 4865 ipv4_addr_show(f, m->match.acl.ipv4.da); 4866 else 4867 ipv6_addr_show(f, m->match.acl.ipv6.da); 4868 4869 fprintf(f, "%u", m->match.acl.da_depth); 4870 4871 fprintf(f, "%u %u %u %u %u ", 4872 (uint32_t)m->match.acl.sp0, 4873 (uint32_t)m->match.acl.sp1, 4874 (uint32_t)m->match.acl.dp0, 4875 (uint32_t)m->match.acl.dp1, 4876 (uint32_t)m->match.acl.proto); 4877 break; 4878 4879 case TABLE_ARRAY: 4880 fprintf(f, "array %u ", 4881 m->match.array.pos); 4882 break; 4883 4884 case TABLE_HASH: 4885 fprintf(f, "hash raw "); 4886 for (i = 0; i < table->params.match.hash.key_size; i++) 4887 fprintf(f, "%02x", m->match.hash.key[i]); 4888 fprintf(f, " "); 4889 break; 4890 4891 case TABLE_LPM: 4892 fprintf(f, "lpm "); 4893 4894 fprintf(f, m->match.lpm.ip_version ? "ipv4 " : "ipv6 "); 4895 4896 if (m->match.acl.ip_version) 4897 ipv4_addr_show(f, m->match.lpm.ipv4); 4898 else 4899 ipv6_addr_show(f, m->match.lpm.ipv6); 4900 4901 fprintf(f, "%u ", 4902 (uint32_t)m->match.lpm.depth); 4903 break; 4904 4905 default: 4906 fprintf(f, "unknown "); 4907 } 4908 4909 fprintf(f, "action "); 4910 if (a->action_mask & (1LLU << RTE_TABLE_ACTION_FWD)) { 4911 fprintf(f, "fwd "); 4912 switch (a->fwd.action) { 4913 case RTE_PIPELINE_ACTION_DROP: 4914 fprintf(f, "drop "); 4915 break; 4916 4917 case RTE_PIPELINE_ACTION_PORT: 4918 fprintf(f, "port %u ", a->fwd.id); 4919 break; 4920 4921 case RTE_PIPELINE_ACTION_PORT_META: 4922 fprintf(f, "meta "); 4923 break; 4924 4925 case RTE_PIPELINE_ACTION_TABLE: 4926 default: 4927 fprintf(f, "table %u ", a->fwd.id); 4928 } 4929 } 4930 4931 if (a->action_mask & (1LLU << RTE_TABLE_ACTION_LB)) { 4932 fprintf(f, "balance "); 4933 for (i = 0; i < RTE_DIM(a->lb.out); i++) 4934 fprintf(f, "%u ", a->lb.out[i]); 4935 } 4936 4937 if (a->action_mask & (1LLU << RTE_TABLE_ACTION_MTR)) { 4938 fprintf(f, "mtr "); 4939 for (i = 0; i < RTE_TABLE_ACTION_TC_MAX; i++) 4940 if (a->mtr.tc_mask & (1 << i)) { 4941 struct rte_table_action_mtr_tc_params *p = 4942 &a->mtr.mtr[i]; 4943 enum rte_table_action_policer ga = 4944 p->policer[RTE_COLOR_GREEN]; 4945 enum rte_table_action_policer ya = 4946 p->policer[RTE_COLOR_YELLOW]; 4947 enum rte_table_action_policer ra = 4948 p->policer[RTE_COLOR_RED]; 4949 4950 fprintf(f, "tc%u meter %u policer g %s y %s r %s ", 4951 i, 4952 a->mtr.mtr[i].meter_profile_id, 4953 policer_action_string(ga), 4954 policer_action_string(ya), 4955 policer_action_string(ra)); 4956 } 4957 } 4958 4959 if (a->action_mask & (1LLU << RTE_TABLE_ACTION_TM)) 4960 fprintf(f, "tm subport %u pipe %u ", 4961 a->tm.subport_id, 4962 a->tm.pipe_id); 4963 4964 if (a->action_mask & (1LLU << RTE_TABLE_ACTION_ENCAP)) { 4965 fprintf(f, "encap "); 4966 switch (a->encap.type) { 4967 case RTE_TABLE_ACTION_ENCAP_ETHER: 4968 fprintf(f, "ether "); 4969 ether_addr_show(f, &a->encap.ether.ether.da); 4970 fprintf(f, " "); 4971 ether_addr_show(f, &a->encap.ether.ether.sa); 4972 fprintf(f, " "); 4973 break; 4974 4975 case RTE_TABLE_ACTION_ENCAP_VLAN: 4976 fprintf(f, "vlan "); 4977 ether_addr_show(f, &a->encap.vlan.ether.da); 4978 fprintf(f, " "); 4979 ether_addr_show(f, &a->encap.vlan.ether.sa); 4980 fprintf(f, " pcp %u dei %u vid %u ", 4981 a->encap.vlan.vlan.pcp, 4982 a->encap.vlan.vlan.dei, 4983 a->encap.vlan.vlan.vid); 4984 break; 4985 4986 case RTE_TABLE_ACTION_ENCAP_QINQ: 4987 fprintf(f, "qinq "); 4988 ether_addr_show(f, &a->encap.qinq.ether.da); 4989 fprintf(f, " "); 4990 ether_addr_show(f, &a->encap.qinq.ether.sa); 4991 fprintf(f, " pcp %u dei %u vid %u pcp %u dei %u vid %u ", 4992 a->encap.qinq.svlan.pcp, 4993 a->encap.qinq.svlan.dei, 4994 a->encap.qinq.svlan.vid, 4995 a->encap.qinq.cvlan.pcp, 4996 a->encap.qinq.cvlan.dei, 4997 a->encap.qinq.cvlan.vid); 4998 break; 4999 5000 case RTE_TABLE_ACTION_ENCAP_MPLS: 5001 fprintf(f, "mpls %s ", (a->encap.mpls.unicast) ? 5002 "unicast " : "multicast "); 5003 ether_addr_show(f, &a->encap.mpls.ether.da); 5004 fprintf(f, " "); 5005 ether_addr_show(f, &a->encap.mpls.ether.sa); 5006 fprintf(f, " "); 5007 for (i = 0; i < a->encap.mpls.mpls_count; i++) { 5008 struct rte_table_action_mpls_hdr *l = 5009 &a->encap.mpls.mpls[i]; 5010 5011 fprintf(f, "label%u %u %u %u ", 5012 i, 5013 l->label, 5014 l->tc, 5015 l->ttl); 5016 } 5017 break; 5018 5019 case RTE_TABLE_ACTION_ENCAP_PPPOE: 5020 fprintf(f, "pppoe "); 5021 ether_addr_show(f, &a->encap.pppoe.ether.da); 5022 fprintf(f, " "); 5023 ether_addr_show(f, &a->encap.pppoe.ether.sa); 5024 fprintf(f, " %u ", a->encap.pppoe.pppoe.session_id); 5025 break; 5026 5027 case RTE_TABLE_ACTION_ENCAP_VXLAN: 5028 fprintf(f, "vxlan ether "); 5029 ether_addr_show(f, &a->encap.vxlan.ether.da); 5030 fprintf(f, " "); 5031 ether_addr_show(f, &a->encap.vxlan.ether.sa); 5032 if (table->ap->params.encap.vxlan.vlan) 5033 fprintf(f, " vlan pcp %u dei %u vid %u ", 5034 a->encap.vxlan.vlan.pcp, 5035 a->encap.vxlan.vlan.dei, 5036 a->encap.vxlan.vlan.vid); 5037 if (table->ap->params.encap.vxlan.ip_version) { 5038 fprintf(f, " ipv4 "); 5039 ipv4_addr_show(f, a->encap.vxlan.ipv4.sa); 5040 fprintf(f, " "); 5041 ipv4_addr_show(f, a->encap.vxlan.ipv4.da); 5042 fprintf(f, " %u %u ", 5043 (uint32_t)a->encap.vxlan.ipv4.dscp, 5044 (uint32_t)a->encap.vxlan.ipv4.ttl); 5045 } else { 5046 fprintf(f, " ipv6 "); 5047 ipv6_addr_show(f, a->encap.vxlan.ipv6.sa); 5048 fprintf(f, " "); 5049 ipv6_addr_show(f, a->encap.vxlan.ipv6.da); 5050 fprintf(f, " %u %u %u ", 5051 a->encap.vxlan.ipv6.flow_label, 5052 (uint32_t)a->encap.vxlan.ipv6.dscp, 5053 (uint32_t)a->encap.vxlan.ipv6.hop_limit); 5054 fprintf(f, " udp %u %u vxlan %u ", 5055 a->encap.vxlan.udp.sp, 5056 a->encap.vxlan.udp.dp, 5057 a->encap.vxlan.vxlan.vni); 5058 } 5059 break; 5060 5061 default: 5062 fprintf(f, "unknown "); 5063 } 5064 } 5065 5066 if (a->action_mask & (1LLU << RTE_TABLE_ACTION_NAT)) { 5067 fprintf(f, "nat %s ", (a->nat.ip_version) ? "ipv4 " : "ipv6 "); 5068 if (a->nat.ip_version) 5069 ipv4_addr_show(f, a->nat.addr.ipv4); 5070 else 5071 ipv6_addr_show(f, a->nat.addr.ipv6); 5072 fprintf(f, " %u ", (uint32_t)(a->nat.port)); 5073 } 5074 5075 if (a->action_mask & (1LLU << RTE_TABLE_ACTION_TTL)) 5076 fprintf(f, "ttl %s ", (a->ttl.decrement) ? "dec" : "keep"); 5077 5078 if (a->action_mask & (1LLU << RTE_TABLE_ACTION_STATS)) 5079 fprintf(f, "stats "); 5080 5081 if (a->action_mask & (1LLU << RTE_TABLE_ACTION_TIME)) 5082 fprintf(f, "time "); 5083 5084 if (a->action_mask & (1LLU << RTE_TABLE_ACTION_SYM_CRYPTO)) 5085 fprintf(f, "sym_crypto "); 5086 5087 if (a->action_mask & (1LLU << RTE_TABLE_ACTION_TAG)) 5088 fprintf(f, "tag %u ", a->tag.tag); 5089 5090 if (a->action_mask & (1LLU << RTE_TABLE_ACTION_DECAP)) 5091 fprintf(f, "decap %u ", a->decap.n); 5092 5093 /* end */ 5094 fprintf(f, "\n"); 5095 } 5096 5097 /* Write table default rule to file. */ 5098 if (table->rule_default) { 5099 struct table_rule_action *a = &table->rule_default->action; 5100 5101 fprintf(f, "# match default action fwd "); 5102 5103 switch (a->fwd.action) { 5104 case RTE_PIPELINE_ACTION_DROP: 5105 fprintf(f, "drop "); 5106 break; 5107 5108 case RTE_PIPELINE_ACTION_PORT: 5109 fprintf(f, "port %u ", a->fwd.id); 5110 break; 5111 5112 case RTE_PIPELINE_ACTION_PORT_META: 5113 fprintf(f, "meta "); 5114 break; 5115 5116 case RTE_PIPELINE_ACTION_TABLE: 5117 default: 5118 fprintf(f, "table %u ", a->fwd.id); 5119 } 5120 } else 5121 fprintf(f, "# match default action fwd drop "); 5122 5123 fprintf(f, "\n"); 5124 5125 /* Close file. */ 5126 fclose(f); 5127 5128 return 0; 5129 } 5130 5131 static const char cmd_pipeline_table_rule_show_help[] = 5132 "pipeline <pipeline_name> table <table_id> rule show\n" 5133 " file <file_name>\n"; 5134 5135 static void 5136 cmd_pipeline_table_rule_show(char **tokens, 5137 uint32_t n_tokens, 5138 char *out, 5139 size_t out_size) 5140 { 5141 char *file_name = NULL, *pipeline_name; 5142 uint32_t table_id; 5143 int status; 5144 5145 if (n_tokens != 8) { 5146 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 5147 return; 5148 } 5149 5150 pipeline_name = tokens[1]; 5151 5152 if (strcmp(tokens[2], "table") != 0) { 5153 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "table"); 5154 return; 5155 } 5156 5157 if (parser_read_uint32(&table_id, tokens[3]) != 0) { 5158 snprintf(out, out_size, MSG_ARG_INVALID, "table_id"); 5159 return; 5160 } 5161 5162 if (strcmp(tokens[4], "rule") != 0) { 5163 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rule"); 5164 return; 5165 } 5166 5167 if (strcmp(tokens[5], "show") != 0) { 5168 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "show"); 5169 return; 5170 } 5171 5172 if (strcmp(tokens[6], "file") != 0) { 5173 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "file"); 5174 return; 5175 } 5176 5177 file_name = tokens[7]; 5178 5179 status = table_rule_show(pipeline_name, table_id, file_name); 5180 if (status) { 5181 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 5182 return; 5183 } 5184 } 5185 5186 static const char cmd_pipeline_table_rule_stats_read_help[] = 5187 "pipeline <pipeline_name> table <table_id> rule read stats [clear]\n" 5188 " match <match>\n"; 5189 5190 static void 5191 cmd_pipeline_table_rule_stats_read(char **tokens, 5192 uint32_t n_tokens, 5193 char *out, 5194 size_t out_size) 5195 { 5196 struct table_rule_match m; 5197 struct rte_table_action_stats_counters stats; 5198 char *pipeline_name; 5199 uint32_t table_id, n_tokens_parsed; 5200 int clear = 0, status; 5201 5202 if (n_tokens < 7) { 5203 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 5204 return; 5205 } 5206 5207 pipeline_name = tokens[1]; 5208 5209 if (strcmp(tokens[2], "table") != 0) { 5210 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "table"); 5211 return; 5212 } 5213 5214 if (parser_read_uint32(&table_id, tokens[3]) != 0) { 5215 snprintf(out, out_size, MSG_ARG_INVALID, "table_id"); 5216 return; 5217 } 5218 5219 if (strcmp(tokens[4], "rule") != 0) { 5220 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rule"); 5221 return; 5222 } 5223 5224 if (strcmp(tokens[5], "read") != 0) { 5225 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "read"); 5226 return; 5227 } 5228 5229 if (strcmp(tokens[6], "stats") != 0) { 5230 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "stats"); 5231 return; 5232 } 5233 5234 n_tokens -= 7; 5235 tokens += 7; 5236 5237 /* clear */ 5238 if (n_tokens && (strcmp(tokens[0], "clear") == 0)) { 5239 clear = 1; 5240 5241 n_tokens--; 5242 tokens++; 5243 } 5244 5245 /* match */ 5246 if ((n_tokens == 0) || strcmp(tokens[0], "match")) { 5247 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "match"); 5248 return; 5249 } 5250 5251 n_tokens_parsed = parse_match(tokens, 5252 n_tokens, 5253 out, 5254 out_size, 5255 &m); 5256 if (n_tokens_parsed == 0) 5257 return; 5258 n_tokens -= n_tokens_parsed; 5259 tokens += n_tokens_parsed; 5260 5261 /* end */ 5262 if (n_tokens) { 5263 snprintf(out, out_size, MSG_ARG_INVALID, tokens[0]); 5264 return; 5265 } 5266 5267 /* Read table rule stats. */ 5268 status = pipeline_table_rule_stats_read(pipeline_name, 5269 table_id, 5270 &m, 5271 &stats, 5272 clear); 5273 if (status) { 5274 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 5275 return; 5276 } 5277 5278 /* Print stats. */ 5279 if (stats.n_packets_valid && stats.n_bytes_valid) 5280 snprintf(out, out_size, "Packets: %" PRIu64 "; Bytes: %" PRIu64 "\n", 5281 stats.n_packets, 5282 stats.n_bytes); 5283 5284 if (stats.n_packets_valid && !stats.n_bytes_valid) 5285 snprintf(out, out_size, "Packets: %" PRIu64 "; Bytes: N/A\n", 5286 stats.n_packets); 5287 5288 if (!stats.n_packets_valid && stats.n_bytes_valid) 5289 snprintf(out, out_size, "Packets: N/A; Bytes: %" PRIu64 "\n", 5290 stats.n_bytes); 5291 5292 if (!stats.n_packets_valid && !stats.n_bytes_valid) 5293 snprintf(out, out_size, "Packets: N/A ; Bytes: N/A\n"); 5294 } 5295 5296 static const char cmd_pipeline_table_meter_profile_add_help[] = 5297 "pipeline <pipeline_name> table <table_id> meter profile <meter_profile_id>\n" 5298 " add srtcm cir <cir> cbs <cbs> ebs <ebs>\n" 5299 " | trtcm cir <cir> pir <pir> cbs <cbs> pbs <pbs>\n"; 5300 5301 static void 5302 cmd_pipeline_table_meter_profile_add(char **tokens, 5303 uint32_t n_tokens, 5304 char *out, 5305 size_t out_size) 5306 { 5307 struct rte_table_action_meter_profile p; 5308 char *pipeline_name; 5309 uint32_t table_id, meter_profile_id; 5310 int status; 5311 5312 if (n_tokens < 9) { 5313 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 5314 return; 5315 } 5316 5317 pipeline_name = tokens[1]; 5318 5319 if (strcmp(tokens[2], "table") != 0) { 5320 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port"); 5321 return; 5322 } 5323 5324 if (parser_read_uint32(&table_id, tokens[3]) != 0) { 5325 snprintf(out, out_size, MSG_ARG_INVALID, "table_id"); 5326 return; 5327 } 5328 5329 if (strcmp(tokens[4], "meter") != 0) { 5330 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "meter"); 5331 return; 5332 } 5333 5334 if (strcmp(tokens[5], "profile") != 0) { 5335 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "profile"); 5336 return; 5337 } 5338 5339 if (parser_read_uint32(&meter_profile_id, tokens[6]) != 0) { 5340 snprintf(out, out_size, MSG_ARG_INVALID, "meter_profile_id"); 5341 return; 5342 } 5343 5344 if (strcmp(tokens[7], "add") != 0) { 5345 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "add"); 5346 return; 5347 } 5348 5349 if (strcmp(tokens[8], "srtcm") == 0) { 5350 if (n_tokens != 15) { 5351 snprintf(out, out_size, MSG_ARG_MISMATCH, 5352 tokens[0]); 5353 return; 5354 } 5355 5356 p.alg = RTE_TABLE_ACTION_METER_SRTCM; 5357 5358 if (strcmp(tokens[9], "cir") != 0) { 5359 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "cir"); 5360 return; 5361 } 5362 5363 if (parser_read_uint64(&p.srtcm.cir, tokens[10]) != 0) { 5364 snprintf(out, out_size, MSG_ARG_INVALID, "cir"); 5365 return; 5366 } 5367 5368 if (strcmp(tokens[11], "cbs") != 0) { 5369 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "cbs"); 5370 return; 5371 } 5372 5373 if (parser_read_uint64(&p.srtcm.cbs, tokens[12]) != 0) { 5374 snprintf(out, out_size, MSG_ARG_INVALID, "cbs"); 5375 return; 5376 } 5377 5378 if (strcmp(tokens[13], "ebs") != 0) { 5379 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "ebs"); 5380 return; 5381 } 5382 5383 if (parser_read_uint64(&p.srtcm.ebs, tokens[14]) != 0) { 5384 snprintf(out, out_size, MSG_ARG_INVALID, "ebs"); 5385 return; 5386 } 5387 } else if (strcmp(tokens[8], "trtcm") == 0) { 5388 if (n_tokens != 17) { 5389 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 5390 return; 5391 } 5392 5393 p.alg = RTE_TABLE_ACTION_METER_TRTCM; 5394 5395 if (strcmp(tokens[9], "cir") != 0) { 5396 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "cir"); 5397 return; 5398 } 5399 5400 if (parser_read_uint64(&p.trtcm.cir, tokens[10]) != 0) { 5401 snprintf(out, out_size, MSG_ARG_INVALID, "cir"); 5402 return; 5403 } 5404 5405 if (strcmp(tokens[11], "pir") != 0) { 5406 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pir"); 5407 return; 5408 } 5409 5410 if (parser_read_uint64(&p.trtcm.pir, tokens[12]) != 0) { 5411 snprintf(out, out_size, MSG_ARG_INVALID, "pir"); 5412 return; 5413 } 5414 if (strcmp(tokens[13], "cbs") != 0) { 5415 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "cbs"); 5416 return; 5417 } 5418 5419 if (parser_read_uint64(&p.trtcm.cbs, tokens[14]) != 0) { 5420 snprintf(out, out_size, MSG_ARG_INVALID, "cbs"); 5421 return; 5422 } 5423 5424 if (strcmp(tokens[15], "pbs") != 0) { 5425 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pbs"); 5426 return; 5427 } 5428 5429 if (parser_read_uint64(&p.trtcm.pbs, tokens[16]) != 0) { 5430 snprintf(out, out_size, MSG_ARG_INVALID, "pbs"); 5431 return; 5432 } 5433 } else { 5434 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 5435 return; 5436 } 5437 5438 status = pipeline_table_mtr_profile_add(pipeline_name, 5439 table_id, 5440 meter_profile_id, 5441 &p); 5442 if (status) { 5443 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 5444 return; 5445 } 5446 } 5447 5448 5449 static const char cmd_pipeline_table_meter_profile_delete_help[] = 5450 "pipeline <pipeline_name> table <table_id>\n" 5451 " meter profile <meter_profile_id> delete\n"; 5452 5453 static void 5454 cmd_pipeline_table_meter_profile_delete(char **tokens, 5455 uint32_t n_tokens, 5456 char *out, 5457 size_t out_size) 5458 { 5459 char *pipeline_name; 5460 uint32_t table_id, meter_profile_id; 5461 int status; 5462 5463 if (n_tokens != 8) { 5464 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 5465 return; 5466 } 5467 5468 pipeline_name = tokens[1]; 5469 5470 if (strcmp(tokens[2], "table") != 0) { 5471 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port"); 5472 return; 5473 } 5474 5475 if (parser_read_uint32(&table_id, tokens[3]) != 0) { 5476 snprintf(out, out_size, MSG_ARG_INVALID, "table_id"); 5477 return; 5478 } 5479 5480 if (strcmp(tokens[4], "meter") != 0) { 5481 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "meter"); 5482 return; 5483 } 5484 5485 if (strcmp(tokens[5], "profile") != 0) { 5486 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "profile"); 5487 return; 5488 } 5489 5490 if (parser_read_uint32(&meter_profile_id, tokens[6]) != 0) { 5491 snprintf(out, out_size, MSG_ARG_INVALID, "meter_profile_id"); 5492 return; 5493 } 5494 5495 if (strcmp(tokens[7], "delete") != 0) { 5496 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "delete"); 5497 return; 5498 } 5499 5500 status = pipeline_table_mtr_profile_delete(pipeline_name, 5501 table_id, 5502 meter_profile_id); 5503 if (status) { 5504 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 5505 return; 5506 } 5507 } 5508 5509 5510 static const char cmd_pipeline_table_rule_meter_read_help[] = 5511 "pipeline <pipeline_name> table <table_id> rule read meter [clear]\n" 5512 " match <match>\n"; 5513 5514 static void 5515 cmd_pipeline_table_rule_meter_read(char **tokens, 5516 uint32_t n_tokens, 5517 char *out, 5518 size_t out_size) 5519 { 5520 struct table_rule_match m; 5521 struct rte_table_action_mtr_counters stats; 5522 char *pipeline_name; 5523 uint32_t table_id, n_tokens_parsed; 5524 int clear = 0, status; 5525 5526 if (n_tokens < 7) { 5527 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 5528 return; 5529 } 5530 5531 pipeline_name = tokens[1]; 5532 5533 if (strcmp(tokens[2], "table") != 0) { 5534 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "table"); 5535 return; 5536 } 5537 5538 if (parser_read_uint32(&table_id, tokens[3]) != 0) { 5539 snprintf(out, out_size, MSG_ARG_INVALID, "table_id"); 5540 return; 5541 } 5542 5543 if (strcmp(tokens[4], "rule") != 0) { 5544 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rule"); 5545 return; 5546 } 5547 5548 if (strcmp(tokens[5], "read") != 0) { 5549 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "read"); 5550 return; 5551 } 5552 5553 if (strcmp(tokens[6], "meter") != 0) { 5554 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "meter"); 5555 return; 5556 } 5557 5558 n_tokens -= 7; 5559 tokens += 7; 5560 5561 /* clear */ 5562 if (n_tokens && (strcmp(tokens[0], "clear") == 0)) { 5563 clear = 1; 5564 5565 n_tokens--; 5566 tokens++; 5567 } 5568 5569 /* match */ 5570 if ((n_tokens == 0) || strcmp(tokens[0], "match")) { 5571 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "match"); 5572 return; 5573 } 5574 5575 n_tokens_parsed = parse_match(tokens, 5576 n_tokens, 5577 out, 5578 out_size, 5579 &m); 5580 if (n_tokens_parsed == 0) 5581 return; 5582 n_tokens -= n_tokens_parsed; 5583 tokens += n_tokens_parsed; 5584 5585 /* end */ 5586 if (n_tokens) { 5587 snprintf(out, out_size, MSG_ARG_INVALID, tokens[0]); 5588 return; 5589 } 5590 5591 /* Read table rule meter stats. */ 5592 status = pipeline_table_rule_mtr_read(pipeline_name, 5593 table_id, 5594 &m, 5595 &stats, 5596 clear); 5597 if (status) { 5598 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 5599 return; 5600 } 5601 5602 /* Print stats. */ 5603 } 5604 5605 5606 static const char cmd_pipeline_table_dscp_help[] = 5607 "pipeline <pipeline_name> table <table_id> dscp <file_name>\n" 5608 "\n" 5609 " File <file_name>:\n" 5610 " - exactly 64 lines\n" 5611 " - line format: <tc_id> <tc_queue_id> <color>, with <color> as: g | y | r\n"; 5612 5613 static int 5614 load_dscp_table(struct rte_table_action_dscp_table *dscp_table, 5615 const char *file_name, 5616 uint32_t *line_number) 5617 { 5618 FILE *f = NULL; 5619 uint32_t dscp, l; 5620 5621 /* Check input arguments */ 5622 if ((dscp_table == NULL) || 5623 (file_name == NULL) || 5624 (line_number == NULL)) { 5625 if (line_number) 5626 *line_number = 0; 5627 return -EINVAL; 5628 } 5629 5630 /* Open input file */ 5631 f = fopen(file_name, "r"); 5632 if (f == NULL) { 5633 *line_number = 0; 5634 return -EINVAL; 5635 } 5636 5637 /* Read file */ 5638 for (dscp = 0, l = 1; ; l++) { 5639 char line[64]; 5640 char *tokens[3]; 5641 enum rte_color color; 5642 uint32_t tc_id, tc_queue_id, n_tokens = RTE_DIM(tokens); 5643 5644 if (fgets(line, sizeof(line), f) == NULL) 5645 break; 5646 5647 if (is_comment(line)) 5648 continue; 5649 5650 if (parse_tokenize_string(line, tokens, &n_tokens)) { 5651 *line_number = l; 5652 fclose(f); 5653 return -EINVAL; 5654 } 5655 5656 if (n_tokens == 0) 5657 continue; 5658 5659 if ((dscp >= RTE_DIM(dscp_table->entry)) || 5660 (n_tokens != RTE_DIM(tokens)) || 5661 parser_read_uint32(&tc_id, tokens[0]) || 5662 (tc_id >= RTE_TABLE_ACTION_TC_MAX) || 5663 parser_read_uint32(&tc_queue_id, tokens[1]) || 5664 (tc_queue_id >= RTE_TABLE_ACTION_TC_QUEUE_MAX) || 5665 (strlen(tokens[2]) != 1)) { 5666 *line_number = l; 5667 fclose(f); 5668 return -EINVAL; 5669 } 5670 5671 switch (tokens[2][0]) { 5672 case 'g': 5673 case 'G': 5674 color = RTE_COLOR_GREEN; 5675 break; 5676 5677 case 'y': 5678 case 'Y': 5679 color = RTE_COLOR_YELLOW; 5680 break; 5681 5682 case 'r': 5683 case 'R': 5684 color = RTE_COLOR_RED; 5685 break; 5686 5687 default: 5688 *line_number = l; 5689 fclose(f); 5690 return -EINVAL; 5691 } 5692 5693 dscp_table->entry[dscp].tc_id = tc_id; 5694 dscp_table->entry[dscp].tc_queue_id = tc_queue_id; 5695 dscp_table->entry[dscp].color = color; 5696 dscp++; 5697 } 5698 5699 /* Close file */ 5700 fclose(f); 5701 return 0; 5702 } 5703 5704 static void 5705 cmd_pipeline_table_dscp(char **tokens, 5706 uint32_t n_tokens, 5707 char *out, 5708 size_t out_size) 5709 { 5710 struct rte_table_action_dscp_table dscp_table; 5711 char *pipeline_name, *file_name; 5712 uint32_t table_id, line_number; 5713 int status; 5714 5715 if (n_tokens != 6) { 5716 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 5717 return; 5718 } 5719 5720 pipeline_name = tokens[1]; 5721 5722 if (strcmp(tokens[2], "table") != 0) { 5723 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port"); 5724 return; 5725 } 5726 5727 if (parser_read_uint32(&table_id, tokens[3]) != 0) { 5728 snprintf(out, out_size, MSG_ARG_INVALID, "table_id"); 5729 return; 5730 } 5731 5732 if (strcmp(tokens[4], "dscp") != 0) { 5733 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "dscp"); 5734 return; 5735 } 5736 5737 file_name = tokens[5]; 5738 5739 status = load_dscp_table(&dscp_table, file_name, &line_number); 5740 if (status) { 5741 snprintf(out, out_size, MSG_FILE_ERR, file_name, line_number); 5742 return; 5743 } 5744 5745 status = pipeline_table_dscp_table_update(pipeline_name, 5746 table_id, 5747 UINT64_MAX, 5748 &dscp_table); 5749 if (status) { 5750 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 5751 return; 5752 } 5753 } 5754 5755 5756 static const char cmd_pipeline_table_rule_ttl_read_help[] = 5757 "pipeline <pipeline_name> table <table_id> rule read ttl [clear]\n" 5758 " match <match>\n"; 5759 5760 static void 5761 cmd_pipeline_table_rule_ttl_read(char **tokens, 5762 uint32_t n_tokens, 5763 char *out, 5764 size_t out_size) 5765 { 5766 struct table_rule_match m; 5767 struct rte_table_action_ttl_counters stats; 5768 char *pipeline_name; 5769 uint32_t table_id, n_tokens_parsed; 5770 int clear = 0, status; 5771 5772 if (n_tokens < 7) { 5773 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 5774 return; 5775 } 5776 5777 pipeline_name = tokens[1]; 5778 5779 if (strcmp(tokens[2], "table") != 0) { 5780 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "table"); 5781 return; 5782 } 5783 5784 if (parser_read_uint32(&table_id, tokens[3]) != 0) { 5785 snprintf(out, out_size, MSG_ARG_INVALID, "table_id"); 5786 return; 5787 } 5788 5789 if (strcmp(tokens[4], "rule") != 0) { 5790 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rule"); 5791 return; 5792 } 5793 5794 if (strcmp(tokens[5], "read") != 0) { 5795 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "read"); 5796 return; 5797 } 5798 5799 if (strcmp(tokens[6], "ttl") != 0) { 5800 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "ttl"); 5801 return; 5802 } 5803 5804 n_tokens -= 7; 5805 tokens += 7; 5806 5807 /* clear */ 5808 if (n_tokens && (strcmp(tokens[0], "clear") == 0)) { 5809 clear = 1; 5810 5811 n_tokens--; 5812 tokens++; 5813 } 5814 5815 /* match */ 5816 if ((n_tokens == 0) || strcmp(tokens[0], "match")) { 5817 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "match"); 5818 return; 5819 } 5820 5821 n_tokens_parsed = parse_match(tokens, 5822 n_tokens, 5823 out, 5824 out_size, 5825 &m); 5826 if (n_tokens_parsed == 0) 5827 return; 5828 n_tokens -= n_tokens_parsed; 5829 tokens += n_tokens_parsed; 5830 5831 /* end */ 5832 if (n_tokens) { 5833 snprintf(out, out_size, MSG_ARG_INVALID, tokens[0]); 5834 return; 5835 } 5836 5837 /* Read table rule TTL stats. */ 5838 status = pipeline_table_rule_ttl_read(pipeline_name, 5839 table_id, 5840 &m, 5841 &stats, 5842 clear); 5843 if (status) { 5844 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 5845 return; 5846 } 5847 5848 /* Print stats. */ 5849 snprintf(out, out_size, "Packets: %" PRIu64 "\n", 5850 stats.n_packets); 5851 } 5852 5853 static const char cmd_pipeline_table_rule_time_read_help[] = 5854 "pipeline <pipeline_name> table <table_id> rule read time\n" 5855 " match <match>\n"; 5856 5857 static void 5858 cmd_pipeline_table_rule_time_read(char **tokens, 5859 uint32_t n_tokens, 5860 char *out, 5861 size_t out_size) 5862 { 5863 struct table_rule_match m; 5864 char *pipeline_name; 5865 uint64_t timestamp; 5866 uint32_t table_id, n_tokens_parsed; 5867 int status; 5868 5869 if (n_tokens < 7) { 5870 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 5871 return; 5872 } 5873 5874 pipeline_name = tokens[1]; 5875 5876 if (strcmp(tokens[2], "table") != 0) { 5877 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "table"); 5878 return; 5879 } 5880 5881 if (parser_read_uint32(&table_id, tokens[3]) != 0) { 5882 snprintf(out, out_size, MSG_ARG_INVALID, "table_id"); 5883 return; 5884 } 5885 5886 if (strcmp(tokens[4], "rule") != 0) { 5887 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rule"); 5888 return; 5889 } 5890 5891 if (strcmp(tokens[5], "read") != 0) { 5892 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "read"); 5893 return; 5894 } 5895 5896 if (strcmp(tokens[6], "time") != 0) { 5897 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "time"); 5898 return; 5899 } 5900 5901 n_tokens -= 7; 5902 tokens += 7; 5903 5904 /* match */ 5905 if ((n_tokens == 0) || strcmp(tokens[0], "match")) { 5906 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "match"); 5907 return; 5908 } 5909 5910 n_tokens_parsed = parse_match(tokens, 5911 n_tokens, 5912 out, 5913 out_size, 5914 &m); 5915 if (n_tokens_parsed == 0) 5916 return; 5917 n_tokens -= n_tokens_parsed; 5918 tokens += n_tokens_parsed; 5919 5920 /* end */ 5921 if (n_tokens) { 5922 snprintf(out, out_size, MSG_ARG_INVALID, tokens[0]); 5923 return; 5924 } 5925 5926 /* Read table rule timestamp. */ 5927 status = pipeline_table_rule_time_read(pipeline_name, 5928 table_id, 5929 &m, 5930 ×tamp); 5931 if (status) { 5932 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 5933 return; 5934 } 5935 5936 /* Print stats. */ 5937 snprintf(out, out_size, "Packets: %" PRIu64 "\n", timestamp); 5938 } 5939 5940 static const char cmd_thread_pipeline_enable_help[] = 5941 "thread <thread_id> pipeline <pipeline_name> enable\n"; 5942 5943 static void 5944 cmd_thread_pipeline_enable(char **tokens, 5945 uint32_t n_tokens, 5946 char *out, 5947 size_t out_size) 5948 { 5949 char *pipeline_name; 5950 uint32_t thread_id; 5951 int status; 5952 5953 if (n_tokens != 5) { 5954 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 5955 return; 5956 } 5957 5958 if (parser_read_uint32(&thread_id, tokens[1]) != 0) { 5959 snprintf(out, out_size, MSG_ARG_INVALID, "thread_id"); 5960 return; 5961 } 5962 5963 if (strcmp(tokens[2], "pipeline") != 0) { 5964 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pipeline"); 5965 return; 5966 } 5967 5968 pipeline_name = tokens[3]; 5969 5970 if (strcmp(tokens[4], "enable") != 0) { 5971 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "enable"); 5972 return; 5973 } 5974 5975 status = thread_pipeline_enable(thread_id, pipeline_name); 5976 if (status) { 5977 snprintf(out, out_size, MSG_CMD_FAIL, "thread pipeline enable"); 5978 return; 5979 } 5980 } 5981 5982 5983 static const char cmd_thread_pipeline_disable_help[] = 5984 "thread <thread_id> pipeline <pipeline_name> disable\n"; 5985 5986 static void 5987 cmd_thread_pipeline_disable(char **tokens, 5988 uint32_t n_tokens, 5989 char *out, 5990 size_t out_size) 5991 { 5992 char *pipeline_name; 5993 uint32_t thread_id; 5994 int status; 5995 5996 if (n_tokens != 5) { 5997 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 5998 return; 5999 } 6000 6001 if (parser_read_uint32(&thread_id, tokens[1]) != 0) { 6002 snprintf(out, out_size, MSG_ARG_INVALID, "thread_id"); 6003 return; 6004 } 6005 6006 if (strcmp(tokens[2], "pipeline") != 0) { 6007 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pipeline"); 6008 return; 6009 } 6010 6011 pipeline_name = tokens[3]; 6012 6013 if (strcmp(tokens[4], "disable") != 0) { 6014 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "disable"); 6015 return; 6016 } 6017 6018 status = thread_pipeline_disable(thread_id, pipeline_name); 6019 if (status) { 6020 snprintf(out, out_size, MSG_CMD_FAIL, 6021 "thread pipeline disable"); 6022 return; 6023 } 6024 } 6025 6026 static void 6027 cmd_help(char **tokens, uint32_t n_tokens, char *out, size_t out_size) 6028 { 6029 tokens++; 6030 n_tokens--; 6031 6032 if (n_tokens == 0) { 6033 snprintf(out, out_size, 6034 "Type 'help <command>' for details on each command.\n\n" 6035 "List of commands:\n" 6036 "\tmempool\n" 6037 "\tlink\n" 6038 "\tswq\n" 6039 "\ttmgr subport profile\n" 6040 "\ttmgr pipe profile\n" 6041 "\ttmgr\n" 6042 "\ttmgr subport\n" 6043 "\ttmgr subport pipe\n" 6044 "\ttap\n" 6045 "\tkni\n" 6046 "\tport in action profile\n" 6047 "\ttable action profile\n" 6048 "\tpipeline\n" 6049 "\tpipeline port in\n" 6050 "\tpipeline port out\n" 6051 "\tpipeline table\n" 6052 "\tpipeline port in table\n" 6053 "\tpipeline port in stats\n" 6054 "\tpipeline port in enable\n" 6055 "\tpipeline port in disable\n" 6056 "\tpipeline port out stats\n" 6057 "\tpipeline table stats\n" 6058 "\tpipeline table rule add\n" 6059 "\tpipeline table rule add default\n" 6060 "\tpipeline table rule add bulk\n" 6061 "\tpipeline table rule delete\n" 6062 "\tpipeline table rule delete default\n" 6063 "\tpipeline table rule show\n" 6064 "\tpipeline table rule stats read\n" 6065 "\tpipeline table meter profile add\n" 6066 "\tpipeline table meter profile delete\n" 6067 "\tpipeline table rule meter read\n" 6068 "\tpipeline table dscp\n" 6069 "\tpipeline table rule ttl read\n" 6070 "\tpipeline table rule time read\n" 6071 "\tthread pipeline enable\n" 6072 "\tthread pipeline disable\n\n"); 6073 return; 6074 } 6075 6076 if (strcmp(tokens[0], "mempool") == 0) { 6077 snprintf(out, out_size, "\n%s\n", cmd_mempool_help); 6078 return; 6079 } 6080 6081 if (strcmp(tokens[0], "link") == 0) { 6082 snprintf(out, out_size, "\n%s\n", cmd_link_help); 6083 return; 6084 } 6085 6086 if (strcmp(tokens[0], "swq") == 0) { 6087 snprintf(out, out_size, "\n%s\n", cmd_swq_help); 6088 return; 6089 } 6090 6091 if (strcmp(tokens[0], "tmgr") == 0) { 6092 if (n_tokens == 1) { 6093 snprintf(out, out_size, "\n%s\n", cmd_tmgr_help); 6094 return; 6095 } 6096 6097 if ((n_tokens == 2) && 6098 (strcmp(tokens[1], "subport")) == 0) { 6099 snprintf(out, out_size, "\n%s\n", cmd_tmgr_subport_help); 6100 return; 6101 } 6102 6103 if ((n_tokens == 3) && 6104 (strcmp(tokens[1], "subport") == 0) && 6105 (strcmp(tokens[2], "profile") == 0)) { 6106 snprintf(out, out_size, "\n%s\n", 6107 cmd_tmgr_subport_profile_help); 6108 return; 6109 } 6110 6111 if ((n_tokens == 3) && 6112 (strcmp(tokens[1], "subport") == 0) && 6113 (strcmp(tokens[2], "pipe") == 0)) { 6114 snprintf(out, out_size, "\n%s\n", cmd_tmgr_subport_pipe_help); 6115 return; 6116 } 6117 6118 if ((n_tokens == 3) && 6119 (strcmp(tokens[1], "pipe") == 0) && 6120 (strcmp(tokens[2], "profile") == 0)) { 6121 snprintf(out, out_size, "\n%s\n", cmd_tmgr_pipe_profile_help); 6122 return; 6123 } 6124 } 6125 6126 if (strcmp(tokens[0], "tap") == 0) { 6127 snprintf(out, out_size, "\n%s\n", cmd_tap_help); 6128 return; 6129 } 6130 6131 if (strcmp(tokens[0], "kni") == 0) { 6132 snprintf(out, out_size, "\n%s\n", cmd_kni_help); 6133 return; 6134 } 6135 6136 if (strcmp(tokens[0], "cryptodev") == 0) { 6137 snprintf(out, out_size, "\n%s\n", cmd_cryptodev_help); 6138 return; 6139 } 6140 6141 if ((n_tokens == 4) && 6142 (strcmp(tokens[0], "port") == 0) && 6143 (strcmp(tokens[1], "in") == 0) && 6144 (strcmp(tokens[2], "action") == 0) && 6145 (strcmp(tokens[3], "profile") == 0)) { 6146 snprintf(out, out_size, "\n%s\n", cmd_port_in_action_profile_help); 6147 return; 6148 } 6149 6150 if ((n_tokens == 3) && 6151 (strcmp(tokens[0], "table") == 0) && 6152 (strcmp(tokens[1], "action") == 0) && 6153 (strcmp(tokens[2], "profile") == 0)) { 6154 snprintf(out, out_size, "\n%s\n", cmd_table_action_profile_help); 6155 return; 6156 } 6157 6158 if ((strcmp(tokens[0], "pipeline") == 0) && (n_tokens == 1)) { 6159 snprintf(out, out_size, "\n%s\n", cmd_pipeline_help); 6160 return; 6161 } 6162 6163 if ((strcmp(tokens[0], "pipeline") == 0) && 6164 (strcmp(tokens[1], "port") == 0)) { 6165 if ((n_tokens == 3) && (strcmp(tokens[2], "in")) == 0) { 6166 snprintf(out, out_size, "\n%s\n", cmd_pipeline_port_in_help); 6167 return; 6168 } 6169 6170 if ((n_tokens == 3) && (strcmp(tokens[2], "out")) == 0) { 6171 snprintf(out, out_size, "\n%s\n", cmd_pipeline_port_out_help); 6172 return; 6173 } 6174 6175 if ((n_tokens == 4) && 6176 (strcmp(tokens[2], "in") == 0) && 6177 (strcmp(tokens[3], "table") == 0)) { 6178 snprintf(out, out_size, "\n%s\n", 6179 cmd_pipeline_port_in_table_help); 6180 return; 6181 } 6182 6183 if ((n_tokens == 4) && 6184 (strcmp(tokens[2], "in") == 0) && 6185 (strcmp(tokens[3], "stats") == 0)) { 6186 snprintf(out, out_size, "\n%s\n", 6187 cmd_pipeline_port_in_stats_help); 6188 return; 6189 } 6190 6191 if ((n_tokens == 4) && 6192 (strcmp(tokens[2], "in") == 0) && 6193 (strcmp(tokens[3], "enable") == 0)) { 6194 snprintf(out, out_size, "\n%s\n", 6195 cmd_pipeline_port_in_enable_help); 6196 return; 6197 } 6198 6199 if ((n_tokens == 4) && 6200 (strcmp(tokens[2], "in") == 0) && 6201 (strcmp(tokens[3], "disable") == 0)) { 6202 snprintf(out, out_size, "\n%s\n", 6203 cmd_pipeline_port_in_disable_help); 6204 return; 6205 } 6206 6207 if ((n_tokens == 4) && 6208 (strcmp(tokens[2], "out") == 0) && 6209 (strcmp(tokens[3], "stats") == 0)) { 6210 snprintf(out, out_size, "\n%s\n", 6211 cmd_pipeline_port_out_stats_help); 6212 return; 6213 } 6214 } 6215 6216 if ((strcmp(tokens[0], "pipeline") == 0) && 6217 (strcmp(tokens[1], "table") == 0)) { 6218 if (n_tokens == 2) { 6219 snprintf(out, out_size, "\n%s\n", cmd_pipeline_table_help); 6220 return; 6221 } 6222 6223 if ((n_tokens == 3) && strcmp(tokens[2], "stats") == 0) { 6224 snprintf(out, out_size, "\n%s\n", 6225 cmd_pipeline_table_stats_help); 6226 return; 6227 } 6228 6229 if ((n_tokens == 3) && strcmp(tokens[2], "dscp") == 0) { 6230 snprintf(out, out_size, "\n%s\n", 6231 cmd_pipeline_table_dscp_help); 6232 return; 6233 } 6234 6235 if ((n_tokens == 4) && 6236 (strcmp(tokens[2], "rule") == 0) && 6237 (strcmp(tokens[3], "add") == 0)) { 6238 snprintf(out, out_size, "\n%s\n", 6239 cmd_pipeline_table_rule_add_help); 6240 return; 6241 } 6242 6243 if ((n_tokens == 5) && 6244 (strcmp(tokens[2], "rule") == 0) && 6245 (strcmp(tokens[3], "add") == 0) && 6246 (strcmp(tokens[4], "default") == 0)) { 6247 snprintf(out, out_size, "\n%s\n", 6248 cmd_pipeline_table_rule_add_default_help); 6249 return; 6250 } 6251 6252 if ((n_tokens == 5) && 6253 (strcmp(tokens[2], "rule") == 0) && 6254 (strcmp(tokens[3], "add") == 0) && 6255 (strcmp(tokens[4], "bulk") == 0)) { 6256 snprintf(out, out_size, "\n%s\n", 6257 cmd_pipeline_table_rule_add_bulk_help); 6258 return; 6259 } 6260 6261 if ((n_tokens == 4) && 6262 (strcmp(tokens[2], "rule") == 0) && 6263 (strcmp(tokens[3], "delete") == 0)) { 6264 snprintf(out, out_size, "\n%s\n", 6265 cmd_pipeline_table_rule_delete_help); 6266 return; 6267 } 6268 6269 if ((n_tokens == 5) && 6270 (strcmp(tokens[2], "rule") == 0) && 6271 (strcmp(tokens[3], "delete") == 0) && 6272 (strcmp(tokens[4], "default") == 0)) { 6273 snprintf(out, out_size, "\n%s\n", 6274 cmd_pipeline_table_rule_delete_default_help); 6275 return; 6276 } 6277 6278 if ((n_tokens == 4) && 6279 (strcmp(tokens[2], "rule") == 0) && 6280 (strcmp(tokens[3], "show") == 0)) { 6281 snprintf(out, out_size, "\n%s\n", 6282 cmd_pipeline_table_rule_show_help); 6283 return; 6284 } 6285 6286 if ((n_tokens == 5) && 6287 (strcmp(tokens[2], "rule") == 0) && 6288 (strcmp(tokens[3], "stats") == 0) && 6289 (strcmp(tokens[4], "read") == 0)) { 6290 snprintf(out, out_size, "\n%s\n", 6291 cmd_pipeline_table_rule_stats_read_help); 6292 return; 6293 } 6294 6295 if ((n_tokens == 5) && 6296 (strcmp(tokens[2], "meter") == 0) && 6297 (strcmp(tokens[3], "profile") == 0) && 6298 (strcmp(tokens[4], "add") == 0)) { 6299 snprintf(out, out_size, "\n%s\n", 6300 cmd_pipeline_table_meter_profile_add_help); 6301 return; 6302 } 6303 6304 if ((n_tokens == 5) && 6305 (strcmp(tokens[2], "meter") == 0) && 6306 (strcmp(tokens[3], "profile") == 0) && 6307 (strcmp(tokens[4], "delete") == 0)) { 6308 snprintf(out, out_size, "\n%s\n", 6309 cmd_pipeline_table_meter_profile_delete_help); 6310 return; 6311 } 6312 6313 if ((n_tokens == 5) && 6314 (strcmp(tokens[2], "rule") == 0) && 6315 (strcmp(tokens[3], "meter") == 0) && 6316 (strcmp(tokens[4], "read") == 0)) { 6317 snprintf(out, out_size, "\n%s\n", 6318 cmd_pipeline_table_rule_meter_read_help); 6319 return; 6320 } 6321 6322 if ((n_tokens == 5) && 6323 (strcmp(tokens[2], "rule") == 0) && 6324 (strcmp(tokens[3], "ttl") == 0) && 6325 (strcmp(tokens[4], "read") == 0)) { 6326 snprintf(out, out_size, "\n%s\n", 6327 cmd_pipeline_table_rule_ttl_read_help); 6328 return; 6329 } 6330 6331 if ((n_tokens == 5) && 6332 (strcmp(tokens[2], "rule") == 0) && 6333 (strcmp(tokens[3], "time") == 0) && 6334 (strcmp(tokens[4], "read") == 0)) { 6335 snprintf(out, out_size, "\n%s\n", 6336 cmd_pipeline_table_rule_time_read_help); 6337 return; 6338 } 6339 } 6340 6341 if ((n_tokens == 3) && 6342 (strcmp(tokens[0], "thread") == 0) && 6343 (strcmp(tokens[1], "pipeline") == 0)) { 6344 if (strcmp(tokens[2], "enable") == 0) { 6345 snprintf(out, out_size, "\n%s\n", 6346 cmd_thread_pipeline_enable_help); 6347 return; 6348 } 6349 6350 if (strcmp(tokens[2], "disable") == 0) { 6351 snprintf(out, out_size, "\n%s\n", 6352 cmd_thread_pipeline_disable_help); 6353 return; 6354 } 6355 } 6356 6357 snprintf(out, out_size, "Invalid command\n"); 6358 } 6359 6360 void 6361 cli_process(char *in, char *out, size_t out_size) 6362 { 6363 char *tokens[CMD_MAX_TOKENS]; 6364 uint32_t n_tokens = RTE_DIM(tokens); 6365 int status; 6366 6367 if (is_comment(in)) 6368 return; 6369 6370 status = parse_tokenize_string(in, tokens, &n_tokens); 6371 if (status) { 6372 snprintf(out, out_size, MSG_ARG_TOO_MANY, ""); 6373 return; 6374 } 6375 6376 if (n_tokens == 0) 6377 return; 6378 6379 if (strcmp(tokens[0], "help") == 0) { 6380 cmd_help(tokens, n_tokens, out, out_size); 6381 return; 6382 } 6383 6384 if (strcmp(tokens[0], "mempool") == 0) { 6385 cmd_mempool(tokens, n_tokens, out, out_size); 6386 return; 6387 } 6388 6389 if (strcmp(tokens[0], "link") == 0) { 6390 if (strcmp(tokens[1], "show") == 0) { 6391 cmd_link_show(tokens, n_tokens, out, out_size); 6392 return; 6393 } 6394 6395 cmd_link(tokens, n_tokens, out, out_size); 6396 return; 6397 } 6398 6399 if (strcmp(tokens[0], "swq") == 0) { 6400 cmd_swq(tokens, n_tokens, out, out_size); 6401 return; 6402 } 6403 6404 if (strcmp(tokens[0], "tmgr") == 0) { 6405 if ((n_tokens >= 3) && 6406 (strcmp(tokens[1], "subport") == 0) && 6407 (strcmp(tokens[2], "profile") == 0)) { 6408 cmd_tmgr_subport_profile(tokens, n_tokens, 6409 out, out_size); 6410 return; 6411 } 6412 6413 if ((n_tokens >= 3) && 6414 (strcmp(tokens[1], "pipe") == 0) && 6415 (strcmp(tokens[2], "profile") == 0)) { 6416 cmd_tmgr_pipe_profile(tokens, n_tokens, out, out_size); 6417 return; 6418 } 6419 6420 if ((n_tokens >= 5) && 6421 (strcmp(tokens[2], "subport") == 0) && 6422 (strcmp(tokens[4], "profile") == 0)) { 6423 cmd_tmgr_subport(tokens, n_tokens, out, out_size); 6424 return; 6425 } 6426 6427 if ((n_tokens >= 5) && 6428 (strcmp(tokens[2], "subport") == 0) && 6429 (strcmp(tokens[4], "pipe") == 0)) { 6430 cmd_tmgr_subport_pipe(tokens, n_tokens, out, out_size); 6431 return; 6432 } 6433 6434 cmd_tmgr(tokens, n_tokens, out, out_size); 6435 return; 6436 } 6437 6438 if (strcmp(tokens[0], "tap") == 0) { 6439 cmd_tap(tokens, n_tokens, out, out_size); 6440 return; 6441 } 6442 6443 if (strcmp(tokens[0], "kni") == 0) { 6444 cmd_kni(tokens, n_tokens, out, out_size); 6445 return; 6446 } 6447 6448 if (strcmp(tokens[0], "cryptodev") == 0) { 6449 cmd_cryptodev(tokens, n_tokens, out, out_size); 6450 return; 6451 } 6452 6453 if (strcmp(tokens[0], "port") == 0) { 6454 cmd_port_in_action_profile(tokens, n_tokens, out, out_size); 6455 return; 6456 } 6457 6458 if (strcmp(tokens[0], "table") == 0) { 6459 cmd_table_action_profile(tokens, n_tokens, out, out_size); 6460 return; 6461 } 6462 6463 if (strcmp(tokens[0], "pipeline") == 0) { 6464 if ((n_tokens >= 3) && 6465 (strcmp(tokens[2], "period") == 0)) { 6466 cmd_pipeline(tokens, n_tokens, out, out_size); 6467 return; 6468 } 6469 6470 if ((n_tokens >= 5) && 6471 (strcmp(tokens[2], "port") == 0) && 6472 (strcmp(tokens[3], "in") == 0) && 6473 (strcmp(tokens[4], "bsz") == 0)) { 6474 cmd_pipeline_port_in(tokens, n_tokens, out, out_size); 6475 return; 6476 } 6477 6478 if ((n_tokens >= 5) && 6479 (strcmp(tokens[2], "port") == 0) && 6480 (strcmp(tokens[3], "out") == 0) && 6481 (strcmp(tokens[4], "bsz") == 0)) { 6482 cmd_pipeline_port_out(tokens, n_tokens, out, out_size); 6483 return; 6484 } 6485 6486 if ((n_tokens >= 4) && 6487 (strcmp(tokens[2], "table") == 0) && 6488 (strcmp(tokens[3], "match") == 0)) { 6489 cmd_pipeline_table(tokens, n_tokens, out, out_size); 6490 return; 6491 } 6492 6493 if ((n_tokens >= 6) && 6494 (strcmp(tokens[2], "port") == 0) && 6495 (strcmp(tokens[3], "in") == 0) && 6496 (strcmp(tokens[5], "table") == 0)) { 6497 cmd_pipeline_port_in_table(tokens, n_tokens, 6498 out, out_size); 6499 return; 6500 } 6501 6502 if ((n_tokens >= 6) && 6503 (strcmp(tokens[2], "port") == 0) && 6504 (strcmp(tokens[3], "in") == 0) && 6505 (strcmp(tokens[5], "stats") == 0)) { 6506 cmd_pipeline_port_in_stats(tokens, n_tokens, 6507 out, out_size); 6508 return; 6509 } 6510 6511 if ((n_tokens >= 6) && 6512 (strcmp(tokens[2], "port") == 0) && 6513 (strcmp(tokens[3], "in") == 0) && 6514 (strcmp(tokens[5], "enable") == 0)) { 6515 cmd_pipeline_port_in_enable(tokens, n_tokens, 6516 out, out_size); 6517 return; 6518 } 6519 6520 if ((n_tokens >= 6) && 6521 (strcmp(tokens[2], "port") == 0) && 6522 (strcmp(tokens[3], "in") == 0) && 6523 (strcmp(tokens[5], "disable") == 0)) { 6524 cmd_pipeline_port_in_disable(tokens, n_tokens, 6525 out, out_size); 6526 return; 6527 } 6528 6529 if ((n_tokens >= 6) && 6530 (strcmp(tokens[2], "port") == 0) && 6531 (strcmp(tokens[3], "out") == 0) && 6532 (strcmp(tokens[5], "stats") == 0)) { 6533 cmd_pipeline_port_out_stats(tokens, n_tokens, 6534 out, out_size); 6535 return; 6536 } 6537 6538 if ((n_tokens >= 5) && 6539 (strcmp(tokens[2], "table") == 0) && 6540 (strcmp(tokens[4], "stats") == 0)) { 6541 cmd_pipeline_table_stats(tokens, n_tokens, 6542 out, out_size); 6543 return; 6544 } 6545 6546 if ((n_tokens >= 7) && 6547 (strcmp(tokens[2], "table") == 0) && 6548 (strcmp(tokens[4], "rule") == 0) && 6549 (strcmp(tokens[5], "add") == 0) && 6550 (strcmp(tokens[6], "match") == 0)) { 6551 if ((n_tokens >= 8) && 6552 (strcmp(tokens[7], "default") == 0)) { 6553 cmd_pipeline_table_rule_add_default(tokens, 6554 n_tokens, out, out_size); 6555 return; 6556 } 6557 6558 cmd_pipeline_table_rule_add(tokens, n_tokens, 6559 out, out_size); 6560 return; 6561 } 6562 6563 if ((n_tokens >= 7) && 6564 (strcmp(tokens[2], "table") == 0) && 6565 (strcmp(tokens[4], "rule") == 0) && 6566 (strcmp(tokens[5], "add") == 0) && 6567 (strcmp(tokens[6], "bulk") == 0)) { 6568 cmd_pipeline_table_rule_add_bulk(tokens, 6569 n_tokens, out, out_size); 6570 return; 6571 } 6572 6573 if ((n_tokens >= 7) && 6574 (strcmp(tokens[2], "table") == 0) && 6575 (strcmp(tokens[4], "rule") == 0) && 6576 (strcmp(tokens[5], "delete") == 0) && 6577 (strcmp(tokens[6], "match") == 0)) { 6578 if ((n_tokens >= 8) && 6579 (strcmp(tokens[7], "default") == 0)) { 6580 cmd_pipeline_table_rule_delete_default(tokens, 6581 n_tokens, out, out_size); 6582 return; 6583 } 6584 6585 cmd_pipeline_table_rule_delete(tokens, n_tokens, 6586 out, out_size); 6587 return; 6588 } 6589 6590 if ((n_tokens >= 6) && 6591 (strcmp(tokens[2], "table") == 0) && 6592 (strcmp(tokens[4], "rule") == 0) && 6593 (strcmp(tokens[5], "show") == 0)) { 6594 cmd_pipeline_table_rule_show(tokens, n_tokens, 6595 out, out_size); 6596 return; 6597 } 6598 6599 if ((n_tokens >= 7) && 6600 (strcmp(tokens[2], "table") == 0) && 6601 (strcmp(tokens[4], "rule") == 0) && 6602 (strcmp(tokens[5], "read") == 0) && 6603 (strcmp(tokens[6], "stats") == 0)) { 6604 cmd_pipeline_table_rule_stats_read(tokens, n_tokens, 6605 out, out_size); 6606 return; 6607 } 6608 6609 if ((n_tokens >= 8) && 6610 (strcmp(tokens[2], "table") == 0) && 6611 (strcmp(tokens[4], "meter") == 0) && 6612 (strcmp(tokens[5], "profile") == 0) && 6613 (strcmp(tokens[7], "add") == 0)) { 6614 cmd_pipeline_table_meter_profile_add(tokens, n_tokens, 6615 out, out_size); 6616 return; 6617 } 6618 6619 if ((n_tokens >= 8) && 6620 (strcmp(tokens[2], "table") == 0) && 6621 (strcmp(tokens[4], "meter") == 0) && 6622 (strcmp(tokens[5], "profile") == 0) && 6623 (strcmp(tokens[7], "delete") == 0)) { 6624 cmd_pipeline_table_meter_profile_delete(tokens, 6625 n_tokens, out, out_size); 6626 return; 6627 } 6628 6629 if ((n_tokens >= 7) && 6630 (strcmp(tokens[2], "table") == 0) && 6631 (strcmp(tokens[4], "rule") == 0) && 6632 (strcmp(tokens[5], "read") == 0) && 6633 (strcmp(tokens[6], "meter") == 0)) { 6634 cmd_pipeline_table_rule_meter_read(tokens, n_tokens, 6635 out, out_size); 6636 return; 6637 } 6638 6639 if ((n_tokens >= 5) && 6640 (strcmp(tokens[2], "table") == 0) && 6641 (strcmp(tokens[4], "dscp") == 0)) { 6642 cmd_pipeline_table_dscp(tokens, n_tokens, 6643 out, out_size); 6644 return; 6645 } 6646 6647 if ((n_tokens >= 7) && 6648 (strcmp(tokens[2], "table") == 0) && 6649 (strcmp(tokens[4], "rule") == 0) && 6650 (strcmp(tokens[5], "read") == 0) && 6651 (strcmp(tokens[6], "ttl") == 0)) { 6652 cmd_pipeline_table_rule_ttl_read(tokens, n_tokens, 6653 out, out_size); 6654 return; 6655 } 6656 6657 if ((n_tokens >= 7) && 6658 (strcmp(tokens[2], "table") == 0) && 6659 (strcmp(tokens[4], "rule") == 0) && 6660 (strcmp(tokens[5], "read") == 0) && 6661 (strcmp(tokens[6], "time") == 0)) { 6662 cmd_pipeline_table_rule_time_read(tokens, n_tokens, 6663 out, out_size); 6664 return; 6665 } 6666 } 6667 6668 if (strcmp(tokens[0], "thread") == 0) { 6669 if ((n_tokens >= 5) && 6670 (strcmp(tokens[4], "enable") == 0)) { 6671 cmd_thread_pipeline_enable(tokens, n_tokens, 6672 out, out_size); 6673 return; 6674 } 6675 6676 if ((n_tokens >= 5) && 6677 (strcmp(tokens[4], "disable") == 0)) { 6678 cmd_thread_pipeline_disable(tokens, n_tokens, 6679 out, out_size); 6680 return; 6681 } 6682 } 6683 6684 snprintf(out, out_size, MSG_CMD_UNKNOWN, tokens[0]); 6685 } 6686 6687 int 6688 cli_script_process(const char *file_name, 6689 size_t msg_in_len_max, 6690 size_t msg_out_len_max) 6691 { 6692 char *msg_in = NULL, *msg_out = NULL; 6693 FILE *f = NULL; 6694 6695 /* Check input arguments */ 6696 if ((file_name == NULL) || 6697 (strlen(file_name) == 0) || 6698 (msg_in_len_max == 0) || 6699 (msg_out_len_max == 0)) 6700 return -EINVAL; 6701 6702 msg_in = malloc(msg_in_len_max + 1); 6703 msg_out = malloc(msg_out_len_max + 1); 6704 if ((msg_in == NULL) || 6705 (msg_out == NULL)) { 6706 free(msg_out); 6707 free(msg_in); 6708 return -ENOMEM; 6709 } 6710 6711 /* Open input file */ 6712 f = fopen(file_name, "r"); 6713 if (f == NULL) { 6714 free(msg_out); 6715 free(msg_in); 6716 return -EIO; 6717 } 6718 6719 /* Read file */ 6720 for ( ; ; ) { 6721 if (fgets(msg_in, msg_in_len_max + 1, f) == NULL) 6722 break; 6723 6724 printf("%s", msg_in); 6725 msg_out[0] = 0; 6726 6727 cli_process(msg_in, 6728 msg_out, 6729 msg_out_len_max); 6730 6731 if (strlen(msg_out)) 6732 printf("%s", msg_out); 6733 } 6734 6735 /* Close file */ 6736 fclose(f); 6737 free(msg_out); 6738 free(msg_in); 6739 return 0; 6740 } 6741 6742 static int 6743 cli_rule_file_process(const char *file_name, 6744 size_t line_len_max, 6745 struct table_rule_list **rule_list, 6746 uint32_t *n_rules, 6747 uint32_t *line_number, 6748 char *out, 6749 size_t out_size) 6750 { 6751 struct table_rule_list *list = NULL; 6752 char *line = NULL; 6753 FILE *f = NULL; 6754 uint32_t rule_id = 0, line_id = 0; 6755 int status = 0; 6756 6757 /* Check input arguments */ 6758 if ((file_name == NULL) || 6759 (strlen(file_name) == 0) || 6760 (line_len_max == 0) || 6761 (rule_list == NULL) || 6762 (n_rules == NULL) || 6763 (line_number == NULL) || 6764 (out == NULL)) { 6765 status = -EINVAL; 6766 goto cli_rule_file_process_free; 6767 } 6768 6769 /* Memory allocation */ 6770 list = malloc(sizeof(struct table_rule_list)); 6771 if (list == NULL) { 6772 status = -ENOMEM; 6773 goto cli_rule_file_process_free; 6774 } 6775 6776 TAILQ_INIT(list); 6777 6778 line = malloc(line_len_max + 1); 6779 if (line == NULL) { 6780 status = -ENOMEM; 6781 goto cli_rule_file_process_free; 6782 } 6783 6784 /* Open file */ 6785 f = fopen(file_name, "r"); 6786 if (f == NULL) { 6787 status = -EIO; 6788 goto cli_rule_file_process_free; 6789 } 6790 6791 /* Read file */ 6792 for (line_id = 1, rule_id = 0; ; line_id++) { 6793 char *tokens[CMD_MAX_TOKENS]; 6794 struct table_rule *rule = NULL; 6795 uint32_t n_tokens, n_tokens_parsed, t0; 6796 6797 /* Read next line from file. */ 6798 if (fgets(line, line_len_max + 1, f) == NULL) 6799 break; 6800 6801 /* Comment. */ 6802 if (is_comment(line)) 6803 continue; 6804 6805 /* Parse line. */ 6806 n_tokens = RTE_DIM(tokens); 6807 status = parse_tokenize_string(line, tokens, &n_tokens); 6808 if (status) { 6809 status = -EINVAL; 6810 goto cli_rule_file_process_free; 6811 } 6812 6813 /* Empty line. */ 6814 if (n_tokens == 0) 6815 continue; 6816 t0 = 0; 6817 6818 /* Rule alloc and insert. */ 6819 rule = calloc(1, sizeof(struct table_rule)); 6820 if (rule == NULL) { 6821 status = -ENOMEM; 6822 goto cli_rule_file_process_free; 6823 } 6824 6825 TAILQ_INSERT_TAIL(list, rule, node); 6826 6827 /* Rule match. */ 6828 n_tokens_parsed = parse_match(tokens + t0, 6829 n_tokens - t0, 6830 out, 6831 out_size, 6832 &rule->match); 6833 if (n_tokens_parsed == 0) { 6834 status = -EINVAL; 6835 goto cli_rule_file_process_free; 6836 } 6837 t0 += n_tokens_parsed; 6838 6839 /* Rule action. */ 6840 n_tokens_parsed = parse_table_action(tokens + t0, 6841 n_tokens - t0, 6842 out, 6843 out_size, 6844 &rule->action); 6845 if (n_tokens_parsed == 0) { 6846 status = -EINVAL; 6847 goto cli_rule_file_process_free; 6848 } 6849 t0 += n_tokens_parsed; 6850 6851 /* Line completed. */ 6852 if (t0 < n_tokens) { 6853 status = -EINVAL; 6854 goto cli_rule_file_process_free; 6855 } 6856 6857 /* Increment rule count */ 6858 rule_id++; 6859 } 6860 6861 /* Close file */ 6862 fclose(f); 6863 6864 /* Memory free */ 6865 free(line); 6866 6867 *rule_list = list; 6868 *n_rules = rule_id; 6869 *line_number = line_id; 6870 return 0; 6871 6872 cli_rule_file_process_free: 6873 if (rule_list != NULL) 6874 *rule_list = NULL; 6875 6876 if (n_rules != NULL) 6877 *n_rules = rule_id; 6878 6879 if (line_number != NULL) 6880 *line_number = line_id; 6881 6882 if (list != NULL) 6883 for ( ; ; ) { 6884 struct table_rule *rule; 6885 6886 rule = TAILQ_FIRST(list); 6887 if (rule == NULL) 6888 break; 6889 6890 TAILQ_REMOVE(list, rule, node); 6891 free(rule); 6892 } 6893 6894 if (f) 6895 fclose(f); 6896 free(line); 6897 free(list); 6898 6899 return status; 6900 } 6901