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 free(p->cipher_auth.cipher_iv.val); 3777 free(p->cipher_auth.cipher_iv_update.val); 3778 break; 3779 case RTE_CRYPTO_SYM_XFORM_AUTH: 3780 if (p->cipher_auth.auth_iv.val) 3781 free(p->cipher_auth.cipher_iv.val); 3782 if (p->cipher_auth.auth_iv_update.val) 3783 free(p->cipher_auth.cipher_iv_update.val); 3784 break; 3785 case RTE_CRYPTO_SYM_XFORM_AEAD: 3786 free(p->aead.iv.val); 3787 free(p->aead.aad.val); 3788 break; 3789 default: 3790 continue; 3791 } 3792 } 3793 3794 } 3795 3796 static struct rte_crypto_sym_xform * 3797 parse_table_action_cipher(struct rte_table_action_sym_crypto_params *p, 3798 uint8_t *key, uint32_t max_key_len, char **tokens, 3799 uint32_t n_tokens, uint32_t encrypt, uint32_t *used_n_tokens) 3800 { 3801 struct rte_crypto_sym_xform *xform_cipher; 3802 int status; 3803 size_t len; 3804 3805 if (n_tokens < 7 || strcmp(tokens[1], "cipher_algo") || 3806 strcmp(tokens[3], "cipher_key") || 3807 strcmp(tokens[5], "cipher_iv")) 3808 return NULL; 3809 3810 xform_cipher = calloc(1, sizeof(*xform_cipher)); 3811 if (xform_cipher == NULL) 3812 return NULL; 3813 3814 xform_cipher->type = RTE_CRYPTO_SYM_XFORM_CIPHER; 3815 xform_cipher->cipher.op = encrypt ? RTE_CRYPTO_CIPHER_OP_ENCRYPT : 3816 RTE_CRYPTO_CIPHER_OP_DECRYPT; 3817 3818 /* cipher_algo */ 3819 status = rte_cryptodev_get_cipher_algo_enum( 3820 &xform_cipher->cipher.algo, tokens[2]); 3821 if (status < 0) 3822 goto error_exit; 3823 3824 /* cipher_key */ 3825 len = strlen(tokens[4]); 3826 if (len / 2 > max_key_len) { 3827 status = -ENOMEM; 3828 goto error_exit; 3829 } 3830 3831 status = parse_hex_string(tokens[4], key, (uint32_t *)&len); 3832 if (status < 0) 3833 goto error_exit; 3834 3835 xform_cipher->cipher.key.data = key; 3836 xform_cipher->cipher.key.length = (uint16_t)len; 3837 3838 /* cipher_iv */ 3839 len = strlen(tokens[6]); 3840 3841 p->cipher_auth.cipher_iv.val = calloc(1, len / 2 + 1); 3842 if (p->cipher_auth.cipher_iv.val == NULL) 3843 goto error_exit; 3844 3845 status = parse_hex_string(tokens[6], 3846 p->cipher_auth.cipher_iv.val, 3847 (uint32_t *)&len); 3848 if (status < 0) 3849 goto error_exit; 3850 3851 xform_cipher->cipher.iv.length = (uint16_t)len; 3852 xform_cipher->cipher.iv.offset = RTE_TABLE_ACTION_SYM_CRYPTO_IV_OFFSET; 3853 p->cipher_auth.cipher_iv.length = (uint32_t)len; 3854 *used_n_tokens = 7; 3855 3856 return xform_cipher; 3857 3858 error_exit: 3859 if (p->cipher_auth.cipher_iv.val) { 3860 free(p->cipher_auth.cipher_iv.val); 3861 p->cipher_auth.cipher_iv.val = NULL; 3862 } 3863 3864 free(xform_cipher); 3865 3866 return NULL; 3867 } 3868 3869 static struct rte_crypto_sym_xform * 3870 parse_table_action_cipher_auth(struct rte_table_action_sym_crypto_params *p, 3871 uint8_t *key, uint32_t max_key_len, char **tokens, 3872 uint32_t n_tokens, uint32_t encrypt, uint32_t *used_n_tokens) 3873 { 3874 struct rte_crypto_sym_xform *xform_cipher; 3875 struct rte_crypto_sym_xform *xform_auth; 3876 int status; 3877 size_t len; 3878 3879 if (n_tokens < 13 || 3880 strcmp(tokens[7], "auth_algo") || 3881 strcmp(tokens[9], "auth_key") || 3882 strcmp(tokens[11], "digest_size")) 3883 return NULL; 3884 3885 xform_auth = calloc(1, sizeof(*xform_auth)); 3886 if (xform_auth == NULL) 3887 return NULL; 3888 3889 xform_auth->type = RTE_CRYPTO_SYM_XFORM_AUTH; 3890 xform_auth->auth.op = encrypt ? RTE_CRYPTO_AUTH_OP_GENERATE : 3891 RTE_CRYPTO_AUTH_OP_VERIFY; 3892 3893 /* auth_algo */ 3894 status = rte_cryptodev_get_auth_algo_enum(&xform_auth->auth.algo, 3895 tokens[8]); 3896 if (status < 0) 3897 goto error_exit; 3898 3899 /* auth_key */ 3900 len = strlen(tokens[10]); 3901 if (len / 2 > max_key_len) { 3902 status = -ENOMEM; 3903 goto error_exit; 3904 } 3905 3906 status = parse_hex_string(tokens[10], key, (uint32_t *)&len); 3907 if (status < 0) 3908 goto error_exit; 3909 3910 xform_auth->auth.key.data = key; 3911 xform_auth->auth.key.length = (uint16_t)len; 3912 3913 key += xform_auth->auth.key.length; 3914 max_key_len -= xform_auth->auth.key.length; 3915 3916 if (strcmp(tokens[11], "digest_size")) 3917 goto error_exit; 3918 3919 status = parser_read_uint16(&xform_auth->auth.digest_length, 3920 tokens[12]); 3921 if (status < 0) 3922 goto error_exit; 3923 3924 xform_cipher = parse_table_action_cipher(p, key, max_key_len, tokens, 3925 7, encrypt, used_n_tokens); 3926 if (xform_cipher == NULL) 3927 goto error_exit; 3928 3929 *used_n_tokens += 6; 3930 3931 if (encrypt) { 3932 xform_cipher->next = xform_auth; 3933 return xform_cipher; 3934 } else { 3935 xform_auth->next = xform_cipher; 3936 return xform_auth; 3937 } 3938 3939 error_exit: 3940 if (p->cipher_auth.auth_iv.val) { 3941 free(p->cipher_auth.auth_iv.val); 3942 p->cipher_auth.auth_iv.val = 0; 3943 } 3944 3945 free(xform_auth); 3946 3947 return NULL; 3948 } 3949 3950 static struct rte_crypto_sym_xform * 3951 parse_table_action_aead(struct rte_table_action_sym_crypto_params *p, 3952 uint8_t *key, uint32_t max_key_len, char **tokens, 3953 uint32_t n_tokens, uint32_t encrypt, uint32_t *used_n_tokens) 3954 { 3955 struct rte_crypto_sym_xform *xform_aead; 3956 int status; 3957 size_t len; 3958 3959 if (n_tokens < 11 || strcmp(tokens[1], "aead_algo") || 3960 strcmp(tokens[3], "aead_key") || 3961 strcmp(tokens[5], "aead_iv") || 3962 strcmp(tokens[7], "aead_aad") || 3963 strcmp(tokens[9], "digest_size")) 3964 return NULL; 3965 3966 xform_aead = calloc(1, sizeof(*xform_aead)); 3967 if (xform_aead == NULL) 3968 return NULL; 3969 3970 xform_aead->type = RTE_CRYPTO_SYM_XFORM_AEAD; 3971 xform_aead->aead.op = encrypt ? RTE_CRYPTO_AEAD_OP_ENCRYPT : 3972 RTE_CRYPTO_AEAD_OP_DECRYPT; 3973 3974 /* aead_algo */ 3975 status = rte_cryptodev_get_aead_algo_enum(&xform_aead->aead.algo, 3976 tokens[2]); 3977 if (status < 0) 3978 goto error_exit; 3979 3980 /* aead_key */ 3981 len = strlen(tokens[4]); 3982 if (len / 2 > max_key_len) { 3983 status = -ENOMEM; 3984 goto error_exit; 3985 } 3986 3987 status = parse_hex_string(tokens[4], key, (uint32_t *)&len); 3988 if (status < 0) 3989 goto error_exit; 3990 3991 xform_aead->aead.key.data = key; 3992 xform_aead->aead.key.length = (uint16_t)len; 3993 3994 /* aead_iv */ 3995 len = strlen(tokens[6]); 3996 p->aead.iv.val = calloc(1, len / 2 + 1); 3997 if (p->aead.iv.val == NULL) 3998 goto error_exit; 3999 4000 status = parse_hex_string(tokens[6], p->aead.iv.val, 4001 (uint32_t *)&len); 4002 if (status < 0) 4003 goto error_exit; 4004 4005 xform_aead->aead.iv.length = (uint16_t)len; 4006 xform_aead->aead.iv.offset = RTE_TABLE_ACTION_SYM_CRYPTO_IV_OFFSET; 4007 p->aead.iv.length = (uint32_t)len; 4008 4009 /* aead_aad */ 4010 len = strlen(tokens[8]); 4011 p->aead.aad.val = calloc(1, len / 2 + 1); 4012 if (p->aead.aad.val == NULL) 4013 goto error_exit; 4014 4015 status = parse_hex_string(tokens[8], p->aead.aad.val, (uint32_t *)&len); 4016 if (status < 0) 4017 goto error_exit; 4018 4019 xform_aead->aead.aad_length = (uint16_t)len; 4020 p->aead.aad.length = (uint32_t)len; 4021 4022 /* digest_size */ 4023 status = parser_read_uint16(&xform_aead->aead.digest_length, 4024 tokens[10]); 4025 if (status < 0) 4026 goto error_exit; 4027 4028 *used_n_tokens = 11; 4029 4030 return xform_aead; 4031 4032 error_exit: 4033 if (p->aead.iv.val) { 4034 free(p->aead.iv.val); 4035 p->aead.iv.val = NULL; 4036 } 4037 if (p->aead.aad.val) { 4038 free(p->aead.aad.val); 4039 p->aead.aad.val = NULL; 4040 } 4041 4042 free(xform_aead); 4043 4044 return NULL; 4045 } 4046 4047 4048 static uint32_t 4049 parse_table_action_sym_crypto(char **tokens, 4050 uint32_t n_tokens, 4051 struct table_rule_action *a) 4052 { 4053 struct rte_table_action_sym_crypto_params *p = &a->sym_crypto; 4054 struct rte_crypto_sym_xform *xform = NULL; 4055 uint8_t *key = a->sym_crypto_key; 4056 uint32_t max_key_len = SYM_CRYPTO_MAX_KEY_SIZE; 4057 uint32_t used_n_tokens; 4058 uint32_t encrypt; 4059 int status; 4060 4061 if ((n_tokens < 12) || 4062 strcmp(tokens[0], "sym_crypto") || 4063 strcmp(tokens[2], "type")) 4064 return 0; 4065 4066 memset(p, 0, sizeof(*p)); 4067 4068 if (strcmp(tokens[1], "encrypt") == 0) 4069 encrypt = 1; 4070 else 4071 encrypt = 0; 4072 4073 status = parser_read_uint32(&p->data_offset, tokens[n_tokens - 1]); 4074 if (status < 0) 4075 return 0; 4076 4077 if (strcmp(tokens[3], "cipher") == 0) { 4078 tokens += 3; 4079 n_tokens -= 3; 4080 4081 xform = parse_table_action_cipher(p, key, max_key_len, tokens, 4082 n_tokens, encrypt, &used_n_tokens); 4083 } else if (strcmp(tokens[3], "cipher_auth") == 0) { 4084 tokens += 3; 4085 n_tokens -= 3; 4086 4087 xform = parse_table_action_cipher_auth(p, key, max_key_len, 4088 tokens, n_tokens, encrypt, &used_n_tokens); 4089 } else if (strcmp(tokens[3], "aead") == 0) { 4090 tokens += 3; 4091 n_tokens -= 3; 4092 4093 xform = parse_table_action_aead(p, key, max_key_len, tokens, 4094 n_tokens, encrypt, &used_n_tokens); 4095 } 4096 4097 if (xform == NULL) 4098 return 0; 4099 4100 p->xform = xform; 4101 4102 if (strcmp(tokens[used_n_tokens], "data_offset")) { 4103 parse_free_sym_crypto_param_data(p); 4104 return 0; 4105 } 4106 4107 a->action_mask |= 1 << RTE_TABLE_ACTION_SYM_CRYPTO; 4108 4109 return used_n_tokens + 5; 4110 } 4111 4112 static uint32_t 4113 parse_table_action_tag(char **tokens, 4114 uint32_t n_tokens, 4115 struct table_rule_action *a) 4116 { 4117 if ((n_tokens < 2) || 4118 strcmp(tokens[0], "tag")) 4119 return 0; 4120 4121 if (parser_read_uint32(&a->tag.tag, tokens[1])) 4122 return 0; 4123 4124 a->action_mask |= 1 << RTE_TABLE_ACTION_TAG; 4125 return 2; 4126 } 4127 4128 static uint32_t 4129 parse_table_action_decap(char **tokens, 4130 uint32_t n_tokens, 4131 struct table_rule_action *a) 4132 { 4133 if ((n_tokens < 2) || 4134 strcmp(tokens[0], "decap")) 4135 return 0; 4136 4137 if (parser_read_uint16(&a->decap.n, tokens[1])) 4138 return 0; 4139 4140 a->action_mask |= 1 << RTE_TABLE_ACTION_DECAP; 4141 return 2; 4142 } 4143 4144 static uint32_t 4145 parse_table_action(char **tokens, 4146 uint32_t n_tokens, 4147 char *out, 4148 size_t out_size, 4149 struct table_rule_action *a) 4150 { 4151 uint32_t n_tokens0 = n_tokens; 4152 4153 memset(a, 0, sizeof(*a)); 4154 4155 if ((n_tokens < 2) || 4156 strcmp(tokens[0], "action")) 4157 return 0; 4158 4159 tokens++; 4160 n_tokens--; 4161 4162 if (n_tokens && (strcmp(tokens[0], "fwd") == 0)) { 4163 uint32_t n; 4164 4165 n = parse_table_action_fwd(tokens, n_tokens, a); 4166 if (n == 0) { 4167 snprintf(out, out_size, MSG_ARG_INVALID, 4168 "action fwd"); 4169 return 0; 4170 } 4171 4172 tokens += n; 4173 n_tokens -= n; 4174 } 4175 4176 if (n_tokens && (strcmp(tokens[0], "balance") == 0)) { 4177 uint32_t n; 4178 4179 n = parse_table_action_balance(tokens, n_tokens, a); 4180 if (n == 0) { 4181 snprintf(out, out_size, MSG_ARG_INVALID, 4182 "action balance"); 4183 return 0; 4184 } 4185 4186 tokens += n; 4187 n_tokens -= n; 4188 } 4189 4190 if (n_tokens && (strcmp(tokens[0], "meter") == 0)) { 4191 uint32_t n; 4192 4193 n = parse_table_action_meter(tokens, n_tokens, a); 4194 if (n == 0) { 4195 snprintf(out, out_size, MSG_ARG_INVALID, 4196 "action meter"); 4197 return 0; 4198 } 4199 4200 tokens += n; 4201 n_tokens -= n; 4202 } 4203 4204 if (n_tokens && (strcmp(tokens[0], "tm") == 0)) { 4205 uint32_t n; 4206 4207 n = parse_table_action_tm(tokens, n_tokens, a); 4208 if (n == 0) { 4209 snprintf(out, out_size, MSG_ARG_INVALID, 4210 "action tm"); 4211 return 0; 4212 } 4213 4214 tokens += n; 4215 n_tokens -= n; 4216 } 4217 4218 if (n_tokens && (strcmp(tokens[0], "encap") == 0)) { 4219 uint32_t n; 4220 4221 n = parse_table_action_encap(tokens, n_tokens, a); 4222 if (n == 0) { 4223 snprintf(out, out_size, MSG_ARG_INVALID, 4224 "action encap"); 4225 return 0; 4226 } 4227 4228 tokens += n; 4229 n_tokens -= n; 4230 } 4231 4232 if (n_tokens && (strcmp(tokens[0], "nat") == 0)) { 4233 uint32_t n; 4234 4235 n = parse_table_action_nat(tokens, n_tokens, a); 4236 if (n == 0) { 4237 snprintf(out, out_size, MSG_ARG_INVALID, 4238 "action nat"); 4239 return 0; 4240 } 4241 4242 tokens += n; 4243 n_tokens -= n; 4244 } 4245 4246 if (n_tokens && (strcmp(tokens[0], "ttl") == 0)) { 4247 uint32_t n; 4248 4249 n = parse_table_action_ttl(tokens, n_tokens, a); 4250 if (n == 0) { 4251 snprintf(out, out_size, MSG_ARG_INVALID, 4252 "action ttl"); 4253 return 0; 4254 } 4255 4256 tokens += n; 4257 n_tokens -= n; 4258 } 4259 4260 if (n_tokens && (strcmp(tokens[0], "stats") == 0)) { 4261 uint32_t n; 4262 4263 n = parse_table_action_stats(tokens, n_tokens, a); 4264 if (n == 0) { 4265 snprintf(out, out_size, MSG_ARG_INVALID, 4266 "action stats"); 4267 return 0; 4268 } 4269 4270 tokens += n; 4271 n_tokens -= n; 4272 } 4273 4274 if (n_tokens && (strcmp(tokens[0], "time") == 0)) { 4275 uint32_t n; 4276 4277 n = parse_table_action_time(tokens, n_tokens, a); 4278 if (n == 0) { 4279 snprintf(out, out_size, MSG_ARG_INVALID, 4280 "action time"); 4281 return 0; 4282 } 4283 4284 tokens += n; 4285 n_tokens -= n; 4286 } 4287 4288 if (n_tokens && (strcmp(tokens[0], "sym_crypto") == 0)) { 4289 uint32_t n; 4290 4291 n = parse_table_action_sym_crypto(tokens, n_tokens, a); 4292 if (n == 0) { 4293 snprintf(out, out_size, MSG_ARG_INVALID, 4294 "action sym_crypto"); 4295 } 4296 4297 tokens += n; 4298 n_tokens -= n; 4299 } 4300 4301 if (n_tokens && (strcmp(tokens[0], "tag") == 0)) { 4302 uint32_t n; 4303 4304 n = parse_table_action_tag(tokens, n_tokens, a); 4305 if (n == 0) { 4306 snprintf(out, out_size, MSG_ARG_INVALID, 4307 "action tag"); 4308 return 0; 4309 } 4310 4311 tokens += n; 4312 n_tokens -= n; 4313 } 4314 4315 if (n_tokens && (strcmp(tokens[0], "decap") == 0)) { 4316 uint32_t n; 4317 4318 n = parse_table_action_decap(tokens, n_tokens, a); 4319 if (n == 0) { 4320 snprintf(out, out_size, MSG_ARG_INVALID, 4321 "action decap"); 4322 return 0; 4323 } 4324 4325 tokens += n; 4326 n_tokens -= n; 4327 } 4328 4329 if (n_tokens0 - n_tokens == 1) { 4330 snprintf(out, out_size, MSG_ARG_INVALID, "action"); 4331 return 0; 4332 } 4333 4334 return n_tokens0 - n_tokens; 4335 } 4336 4337 4338 static const char cmd_pipeline_table_rule_add_help[] = 4339 "pipeline <pipeline_name> table <table_id> rule add\n" 4340 " match <match>\n" 4341 " action <table_action>\n"; 4342 4343 static void 4344 cmd_pipeline_table_rule_add(char **tokens, 4345 uint32_t n_tokens, 4346 char *out, 4347 size_t out_size) 4348 { 4349 struct table_rule_match m; 4350 struct table_rule_action a; 4351 char *pipeline_name; 4352 uint32_t table_id, t0, n_tokens_parsed; 4353 int status; 4354 4355 if (n_tokens < 8) { 4356 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 4357 return; 4358 } 4359 4360 pipeline_name = tokens[1]; 4361 4362 if (strcmp(tokens[2], "table") != 0) { 4363 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "table"); 4364 return; 4365 } 4366 4367 if (parser_read_uint32(&table_id, tokens[3]) != 0) { 4368 snprintf(out, out_size, MSG_ARG_INVALID, "table_id"); 4369 return; 4370 } 4371 4372 if (strcmp(tokens[4], "rule") != 0) { 4373 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rule"); 4374 return; 4375 } 4376 4377 if (strcmp(tokens[5], "add") != 0) { 4378 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "add"); 4379 return; 4380 } 4381 4382 t0 = 6; 4383 4384 /* match */ 4385 n_tokens_parsed = parse_match(tokens + t0, 4386 n_tokens - t0, 4387 out, 4388 out_size, 4389 &m); 4390 if (n_tokens_parsed == 0) 4391 return; 4392 t0 += n_tokens_parsed; 4393 4394 /* action */ 4395 n_tokens_parsed = parse_table_action(tokens + t0, 4396 n_tokens - t0, 4397 out, 4398 out_size, 4399 &a); 4400 if (n_tokens_parsed == 0) 4401 return; 4402 t0 += n_tokens_parsed; 4403 4404 if (t0 != n_tokens) { 4405 snprintf(out, out_size, MSG_ARG_INVALID, tokens[0]); 4406 return; 4407 } 4408 4409 status = pipeline_table_rule_add(pipeline_name, table_id, &m, &a); 4410 if (status) { 4411 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 4412 return; 4413 } 4414 4415 if (a.action_mask & 1 << RTE_TABLE_ACTION_SYM_CRYPTO) 4416 parse_free_sym_crypto_param_data(&a.sym_crypto); 4417 } 4418 4419 4420 static const char cmd_pipeline_table_rule_add_default_help[] = 4421 "pipeline <pipeline_name> table <table_id> rule add\n" 4422 " match\n" 4423 " default\n" 4424 " action\n" 4425 " fwd\n" 4426 " drop\n" 4427 " | port <port_id>\n" 4428 " | meta\n" 4429 " | table <table_id>\n"; 4430 4431 static void 4432 cmd_pipeline_table_rule_add_default(char **tokens, 4433 uint32_t n_tokens, 4434 char *out, 4435 size_t out_size) 4436 { 4437 struct table_rule_action action; 4438 char *pipeline_name; 4439 uint32_t table_id; 4440 int status; 4441 4442 if ((n_tokens != 11) && (n_tokens != 12)) { 4443 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 4444 return; 4445 } 4446 4447 pipeline_name = tokens[1]; 4448 4449 if (strcmp(tokens[2], "table") != 0) { 4450 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "table"); 4451 return; 4452 } 4453 4454 if (parser_read_uint32(&table_id, tokens[3]) != 0) { 4455 snprintf(out, out_size, MSG_ARG_INVALID, "table_id"); 4456 return; 4457 } 4458 4459 if (strcmp(tokens[4], "rule") != 0) { 4460 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rule"); 4461 return; 4462 } 4463 4464 if (strcmp(tokens[5], "add") != 0) { 4465 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "add"); 4466 return; 4467 } 4468 4469 if (strcmp(tokens[6], "match") != 0) { 4470 snprintf(out, out_size, MSG_ARG_INVALID, "match"); 4471 return; 4472 } 4473 4474 if (strcmp(tokens[7], "default") != 0) { 4475 snprintf(out, out_size, MSG_ARG_INVALID, "default"); 4476 return; 4477 } 4478 4479 if (strcmp(tokens[8], "action") != 0) { 4480 snprintf(out, out_size, MSG_ARG_INVALID, "action"); 4481 return; 4482 } 4483 4484 if (strcmp(tokens[9], "fwd") != 0) { 4485 snprintf(out, out_size, MSG_ARG_INVALID, "fwd"); 4486 return; 4487 } 4488 4489 action.action_mask = 1 << RTE_TABLE_ACTION_FWD; 4490 4491 if (strcmp(tokens[10], "drop") == 0) { 4492 if (n_tokens != 11) { 4493 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 4494 return; 4495 } 4496 4497 action.fwd.action = RTE_PIPELINE_ACTION_DROP; 4498 } else if (strcmp(tokens[10], "port") == 0) { 4499 uint32_t id; 4500 4501 if (n_tokens != 12) { 4502 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 4503 return; 4504 } 4505 4506 if (parser_read_uint32(&id, tokens[11]) != 0) { 4507 snprintf(out, out_size, MSG_ARG_INVALID, "port_id"); 4508 return; 4509 } 4510 4511 action.fwd.action = RTE_PIPELINE_ACTION_PORT; 4512 action.fwd.id = id; 4513 } else if (strcmp(tokens[10], "meta") == 0) { 4514 if (n_tokens != 11) { 4515 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 4516 return; 4517 } 4518 4519 action.fwd.action = RTE_PIPELINE_ACTION_PORT_META; 4520 } else if (strcmp(tokens[10], "table") == 0) { 4521 uint32_t id; 4522 4523 if (n_tokens != 12) { 4524 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 4525 return; 4526 } 4527 4528 if (parser_read_uint32(&id, tokens[11]) != 0) { 4529 snprintf(out, out_size, MSG_ARG_INVALID, "table_id"); 4530 return; 4531 } 4532 4533 action.fwd.action = RTE_PIPELINE_ACTION_TABLE; 4534 action.fwd.id = id; 4535 } else { 4536 snprintf(out, out_size, MSG_ARG_INVALID, 4537 "drop or port or meta or table"); 4538 return; 4539 } 4540 4541 status = pipeline_table_rule_add_default(pipeline_name, 4542 table_id, 4543 &action); 4544 if (status) { 4545 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 4546 return; 4547 } 4548 } 4549 4550 4551 static const char cmd_pipeline_table_rule_add_bulk_help[] = 4552 "pipeline <pipeline_name> table <table_id> rule add bulk <file_name>\n" 4553 "\n" 4554 " File <file_name>:\n" 4555 " - line format: match <match> action <action>\n"; 4556 4557 static int 4558 cli_rule_file_process(const char *file_name, 4559 size_t line_len_max, 4560 struct table_rule_list **rule_list, 4561 uint32_t *n_rules, 4562 uint32_t *line_number, 4563 char *out, 4564 size_t out_size); 4565 4566 static void 4567 cmd_pipeline_table_rule_add_bulk(char **tokens, 4568 uint32_t n_tokens, 4569 char *out, 4570 size_t out_size) 4571 { 4572 struct table_rule_list *list = NULL; 4573 char *pipeline_name, *file_name; 4574 uint32_t table_id, n_rules, n_rules_added, n_rules_not_added, line_number; 4575 int status; 4576 4577 if (n_tokens != 8) { 4578 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 4579 return; 4580 } 4581 4582 pipeline_name = tokens[1]; 4583 4584 if (strcmp(tokens[2], "table") != 0) { 4585 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "table"); 4586 return; 4587 } 4588 4589 if (parser_read_uint32(&table_id, tokens[3]) != 0) { 4590 snprintf(out, out_size, MSG_ARG_INVALID, "table_id"); 4591 return; 4592 } 4593 4594 if (strcmp(tokens[4], "rule") != 0) { 4595 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rule"); 4596 return; 4597 } 4598 4599 if (strcmp(tokens[5], "add") != 0) { 4600 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "add"); 4601 return; 4602 } 4603 4604 if (strcmp(tokens[6], "bulk") != 0) { 4605 snprintf(out, out_size, MSG_ARG_INVALID, "bulk"); 4606 return; 4607 } 4608 4609 file_name = tokens[7]; 4610 4611 /* Load rules from file. */ 4612 status = cli_rule_file_process(file_name, 4613 1024, 4614 &list, 4615 &n_rules, 4616 &line_number, 4617 out, 4618 out_size); 4619 if (status) { 4620 snprintf(out, out_size, MSG_FILE_ERR, file_name, line_number); 4621 return; 4622 } 4623 4624 /* Rule bulk add */ 4625 status = pipeline_table_rule_add_bulk(pipeline_name, 4626 table_id, 4627 list, 4628 &n_rules_added, 4629 &n_rules_not_added); 4630 if (status) { 4631 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 4632 return; 4633 } 4634 4635 snprintf(out, out_size, "Added %u rules out of %u.\n", 4636 n_rules_added, 4637 n_rules); 4638 } 4639 4640 4641 static const char cmd_pipeline_table_rule_delete_help[] = 4642 "pipeline <pipeline_name> table <table_id> rule delete\n" 4643 " match <match>\n"; 4644 4645 static void 4646 cmd_pipeline_table_rule_delete(char **tokens, 4647 uint32_t n_tokens, 4648 char *out, 4649 size_t out_size) 4650 { 4651 struct table_rule_match m; 4652 char *pipeline_name; 4653 uint32_t table_id, n_tokens_parsed, t0; 4654 int status; 4655 4656 if (n_tokens < 8) { 4657 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 4658 return; 4659 } 4660 4661 pipeline_name = tokens[1]; 4662 4663 if (strcmp(tokens[2], "table") != 0) { 4664 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "table"); 4665 return; 4666 } 4667 4668 if (parser_read_uint32(&table_id, tokens[3]) != 0) { 4669 snprintf(out, out_size, MSG_ARG_INVALID, "table_id"); 4670 return; 4671 } 4672 4673 if (strcmp(tokens[4], "rule") != 0) { 4674 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rule"); 4675 return; 4676 } 4677 4678 if (strcmp(tokens[5], "delete") != 0) { 4679 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "delete"); 4680 return; 4681 } 4682 4683 t0 = 6; 4684 4685 /* match */ 4686 n_tokens_parsed = parse_match(tokens + t0, 4687 n_tokens - t0, 4688 out, 4689 out_size, 4690 &m); 4691 if (n_tokens_parsed == 0) 4692 return; 4693 t0 += n_tokens_parsed; 4694 4695 if (n_tokens != t0) { 4696 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 4697 return; 4698 } 4699 4700 status = pipeline_table_rule_delete(pipeline_name, 4701 table_id, 4702 &m); 4703 if (status) { 4704 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 4705 return; 4706 } 4707 } 4708 4709 4710 static const char cmd_pipeline_table_rule_delete_default_help[] = 4711 "pipeline <pipeline_name> table <table_id> rule delete\n" 4712 " match\n" 4713 " default\n"; 4714 4715 static void 4716 cmd_pipeline_table_rule_delete_default(char **tokens, 4717 uint32_t n_tokens, 4718 char *out, 4719 size_t out_size) 4720 { 4721 char *pipeline_name; 4722 uint32_t table_id; 4723 int status; 4724 4725 if (n_tokens != 8) { 4726 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 4727 return; 4728 } 4729 4730 pipeline_name = tokens[1]; 4731 4732 if (strcmp(tokens[2], "table") != 0) { 4733 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "table"); 4734 return; 4735 } 4736 4737 if (parser_read_uint32(&table_id, tokens[3]) != 0) { 4738 snprintf(out, out_size, MSG_ARG_INVALID, "table_id"); 4739 return; 4740 } 4741 4742 if (strcmp(tokens[4], "rule") != 0) { 4743 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rule"); 4744 return; 4745 } 4746 4747 if (strcmp(tokens[5], "delete") != 0) { 4748 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "delete"); 4749 return; 4750 } 4751 4752 if (strcmp(tokens[6], "match") != 0) { 4753 snprintf(out, out_size, MSG_ARG_INVALID, "match"); 4754 return; 4755 } 4756 4757 if (strcmp(tokens[7], "default") != 0) { 4758 snprintf(out, out_size, MSG_ARG_INVALID, "default"); 4759 return; 4760 } 4761 4762 status = pipeline_table_rule_delete_default(pipeline_name, 4763 table_id); 4764 if (status) { 4765 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 4766 return; 4767 } 4768 } 4769 4770 static void 4771 ether_addr_show(FILE *f, struct rte_ether_addr *addr) 4772 { 4773 fprintf(f, RTE_ETHER_ADDR_PRT_FMT, RTE_ETHER_ADDR_BYTES(addr)); 4774 } 4775 4776 static void 4777 ipv4_addr_show(FILE *f, uint32_t addr) 4778 { 4779 fprintf(f, "%u.%u.%u.%u", 4780 addr >> 24, 4781 (addr >> 16) & 0xFF, 4782 (addr >> 8) & 0xFF, 4783 addr & 0xFF); 4784 } 4785 4786 static void 4787 ipv6_addr_show(FILE *f, uint8_t *addr) 4788 { 4789 fprintf(f, "%02x%02x:%02x%02x:%02x%02x:%02x%02x:" 4790 "%02x%02x:%02x%02x:%02x%02x:%02x%02x:", 4791 (uint32_t)addr[0], (uint32_t)addr[1], 4792 (uint32_t)addr[2], (uint32_t)addr[3], 4793 (uint32_t)addr[4], (uint32_t)addr[5], 4794 (uint32_t)addr[6], (uint32_t)addr[7], 4795 (uint32_t)addr[8], (uint32_t)addr[9], 4796 (uint32_t)addr[10], (uint32_t)addr[11], 4797 (uint32_t)addr[12], (uint32_t)addr[13], 4798 (uint32_t)addr[14], (uint32_t)addr[15]); 4799 } 4800 4801 static const char * 4802 policer_action_string(enum rte_table_action_policer action) { 4803 switch (action) { 4804 case RTE_TABLE_ACTION_POLICER_COLOR_GREEN: return "G"; 4805 case RTE_TABLE_ACTION_POLICER_COLOR_YELLOW: return "Y"; 4806 case RTE_TABLE_ACTION_POLICER_COLOR_RED: return "R"; 4807 case RTE_TABLE_ACTION_POLICER_DROP: return "D"; 4808 default: return "?"; 4809 } 4810 } 4811 4812 static int 4813 table_rule_show(const char *pipeline_name, 4814 uint32_t table_id, 4815 const char *file_name) 4816 { 4817 struct pipeline *p; 4818 struct table *table; 4819 struct table_rule *rule; 4820 FILE *f = NULL; 4821 uint32_t i; 4822 4823 /* Check input params. */ 4824 if ((pipeline_name == NULL) || 4825 (file_name == NULL)) 4826 return -1; 4827 4828 p = pipeline_find(pipeline_name); 4829 if ((p == NULL) || 4830 (table_id >= p->n_tables)) 4831 return -1; 4832 4833 table = &p->table[table_id]; 4834 4835 /* Open file. */ 4836 f = fopen(file_name, "w"); 4837 if (f == NULL) 4838 return -1; 4839 4840 /* Write table rules to file. */ 4841 TAILQ_FOREACH(rule, &table->rules, node) { 4842 struct table_rule_match *m = &rule->match; 4843 struct table_rule_action *a = &rule->action; 4844 4845 fprintf(f, "match "); 4846 switch (m->match_type) { 4847 case TABLE_ACL: 4848 fprintf(f, "acl priority %u ", 4849 m->match.acl.priority); 4850 4851 fprintf(f, m->match.acl.ip_version ? "ipv4 " : "ipv6 "); 4852 4853 if (m->match.acl.ip_version) 4854 ipv4_addr_show(f, m->match.acl.ipv4.sa); 4855 else 4856 ipv6_addr_show(f, m->match.acl.ipv6.sa); 4857 4858 fprintf(f, "%u", m->match.acl.sa_depth); 4859 4860 if (m->match.acl.ip_version) 4861 ipv4_addr_show(f, m->match.acl.ipv4.da); 4862 else 4863 ipv6_addr_show(f, m->match.acl.ipv6.da); 4864 4865 fprintf(f, "%u", m->match.acl.da_depth); 4866 4867 fprintf(f, "%u %u %u %u %u ", 4868 (uint32_t)m->match.acl.sp0, 4869 (uint32_t)m->match.acl.sp1, 4870 (uint32_t)m->match.acl.dp0, 4871 (uint32_t)m->match.acl.dp1, 4872 (uint32_t)m->match.acl.proto); 4873 break; 4874 4875 case TABLE_ARRAY: 4876 fprintf(f, "array %u ", 4877 m->match.array.pos); 4878 break; 4879 4880 case TABLE_HASH: 4881 fprintf(f, "hash raw "); 4882 for (i = 0; i < table->params.match.hash.key_size; i++) 4883 fprintf(f, "%02x", m->match.hash.key[i]); 4884 fprintf(f, " "); 4885 break; 4886 4887 case TABLE_LPM: 4888 fprintf(f, "lpm "); 4889 4890 fprintf(f, m->match.lpm.ip_version ? "ipv4 " : "ipv6 "); 4891 4892 if (m->match.acl.ip_version) 4893 ipv4_addr_show(f, m->match.lpm.ipv4); 4894 else 4895 ipv6_addr_show(f, m->match.lpm.ipv6); 4896 4897 fprintf(f, "%u ", 4898 (uint32_t)m->match.lpm.depth); 4899 break; 4900 4901 default: 4902 fprintf(f, "unknown "); 4903 } 4904 4905 fprintf(f, "action "); 4906 if (a->action_mask & (1LLU << RTE_TABLE_ACTION_FWD)) { 4907 fprintf(f, "fwd "); 4908 switch (a->fwd.action) { 4909 case RTE_PIPELINE_ACTION_DROP: 4910 fprintf(f, "drop "); 4911 break; 4912 4913 case RTE_PIPELINE_ACTION_PORT: 4914 fprintf(f, "port %u ", a->fwd.id); 4915 break; 4916 4917 case RTE_PIPELINE_ACTION_PORT_META: 4918 fprintf(f, "meta "); 4919 break; 4920 4921 case RTE_PIPELINE_ACTION_TABLE: 4922 default: 4923 fprintf(f, "table %u ", a->fwd.id); 4924 } 4925 } 4926 4927 if (a->action_mask & (1LLU << RTE_TABLE_ACTION_LB)) { 4928 fprintf(f, "balance "); 4929 for (i = 0; i < RTE_DIM(a->lb.out); i++) 4930 fprintf(f, "%u ", a->lb.out[i]); 4931 } 4932 4933 if (a->action_mask & (1LLU << RTE_TABLE_ACTION_MTR)) { 4934 fprintf(f, "mtr "); 4935 for (i = 0; i < RTE_TABLE_ACTION_TC_MAX; i++) 4936 if (a->mtr.tc_mask & (1 << i)) { 4937 struct rte_table_action_mtr_tc_params *p = 4938 &a->mtr.mtr[i]; 4939 enum rte_table_action_policer ga = 4940 p->policer[RTE_COLOR_GREEN]; 4941 enum rte_table_action_policer ya = 4942 p->policer[RTE_COLOR_YELLOW]; 4943 enum rte_table_action_policer ra = 4944 p->policer[RTE_COLOR_RED]; 4945 4946 fprintf(f, "tc%u meter %u policer g %s y %s r %s ", 4947 i, 4948 a->mtr.mtr[i].meter_profile_id, 4949 policer_action_string(ga), 4950 policer_action_string(ya), 4951 policer_action_string(ra)); 4952 } 4953 } 4954 4955 if (a->action_mask & (1LLU << RTE_TABLE_ACTION_TM)) 4956 fprintf(f, "tm subport %u pipe %u ", 4957 a->tm.subport_id, 4958 a->tm.pipe_id); 4959 4960 if (a->action_mask & (1LLU << RTE_TABLE_ACTION_ENCAP)) { 4961 fprintf(f, "encap "); 4962 switch (a->encap.type) { 4963 case RTE_TABLE_ACTION_ENCAP_ETHER: 4964 fprintf(f, "ether "); 4965 ether_addr_show(f, &a->encap.ether.ether.da); 4966 fprintf(f, " "); 4967 ether_addr_show(f, &a->encap.ether.ether.sa); 4968 fprintf(f, " "); 4969 break; 4970 4971 case RTE_TABLE_ACTION_ENCAP_VLAN: 4972 fprintf(f, "vlan "); 4973 ether_addr_show(f, &a->encap.vlan.ether.da); 4974 fprintf(f, " "); 4975 ether_addr_show(f, &a->encap.vlan.ether.sa); 4976 fprintf(f, " pcp %u dei %u vid %u ", 4977 a->encap.vlan.vlan.pcp, 4978 a->encap.vlan.vlan.dei, 4979 a->encap.vlan.vlan.vid); 4980 break; 4981 4982 case RTE_TABLE_ACTION_ENCAP_QINQ: 4983 fprintf(f, "qinq "); 4984 ether_addr_show(f, &a->encap.qinq.ether.da); 4985 fprintf(f, " "); 4986 ether_addr_show(f, &a->encap.qinq.ether.sa); 4987 fprintf(f, " pcp %u dei %u vid %u pcp %u dei %u vid %u ", 4988 a->encap.qinq.svlan.pcp, 4989 a->encap.qinq.svlan.dei, 4990 a->encap.qinq.svlan.vid, 4991 a->encap.qinq.cvlan.pcp, 4992 a->encap.qinq.cvlan.dei, 4993 a->encap.qinq.cvlan.vid); 4994 break; 4995 4996 case RTE_TABLE_ACTION_ENCAP_MPLS: 4997 fprintf(f, "mpls %s ", (a->encap.mpls.unicast) ? 4998 "unicast " : "multicast "); 4999 ether_addr_show(f, &a->encap.mpls.ether.da); 5000 fprintf(f, " "); 5001 ether_addr_show(f, &a->encap.mpls.ether.sa); 5002 fprintf(f, " "); 5003 for (i = 0; i < a->encap.mpls.mpls_count; i++) { 5004 struct rte_table_action_mpls_hdr *l = 5005 &a->encap.mpls.mpls[i]; 5006 5007 fprintf(f, "label%u %u %u %u ", 5008 i, 5009 l->label, 5010 l->tc, 5011 l->ttl); 5012 } 5013 break; 5014 5015 case RTE_TABLE_ACTION_ENCAP_PPPOE: 5016 fprintf(f, "pppoe "); 5017 ether_addr_show(f, &a->encap.pppoe.ether.da); 5018 fprintf(f, " "); 5019 ether_addr_show(f, &a->encap.pppoe.ether.sa); 5020 fprintf(f, " %u ", a->encap.pppoe.pppoe.session_id); 5021 break; 5022 5023 case RTE_TABLE_ACTION_ENCAP_VXLAN: 5024 fprintf(f, "vxlan ether "); 5025 ether_addr_show(f, &a->encap.vxlan.ether.da); 5026 fprintf(f, " "); 5027 ether_addr_show(f, &a->encap.vxlan.ether.sa); 5028 if (table->ap->params.encap.vxlan.vlan) 5029 fprintf(f, " vlan pcp %u dei %u vid %u ", 5030 a->encap.vxlan.vlan.pcp, 5031 a->encap.vxlan.vlan.dei, 5032 a->encap.vxlan.vlan.vid); 5033 if (table->ap->params.encap.vxlan.ip_version) { 5034 fprintf(f, " ipv4 "); 5035 ipv4_addr_show(f, a->encap.vxlan.ipv4.sa); 5036 fprintf(f, " "); 5037 ipv4_addr_show(f, a->encap.vxlan.ipv4.da); 5038 fprintf(f, " %u %u ", 5039 (uint32_t)a->encap.vxlan.ipv4.dscp, 5040 (uint32_t)a->encap.vxlan.ipv4.ttl); 5041 } else { 5042 fprintf(f, " ipv6 "); 5043 ipv6_addr_show(f, a->encap.vxlan.ipv6.sa); 5044 fprintf(f, " "); 5045 ipv6_addr_show(f, a->encap.vxlan.ipv6.da); 5046 fprintf(f, " %u %u %u ", 5047 a->encap.vxlan.ipv6.flow_label, 5048 (uint32_t)a->encap.vxlan.ipv6.dscp, 5049 (uint32_t)a->encap.vxlan.ipv6.hop_limit); 5050 fprintf(f, " udp %u %u vxlan %u ", 5051 a->encap.vxlan.udp.sp, 5052 a->encap.vxlan.udp.dp, 5053 a->encap.vxlan.vxlan.vni); 5054 } 5055 break; 5056 5057 default: 5058 fprintf(f, "unknown "); 5059 } 5060 } 5061 5062 if (a->action_mask & (1LLU << RTE_TABLE_ACTION_NAT)) { 5063 fprintf(f, "nat %s ", (a->nat.ip_version) ? "ipv4 " : "ipv6 "); 5064 if (a->nat.ip_version) 5065 ipv4_addr_show(f, a->nat.addr.ipv4); 5066 else 5067 ipv6_addr_show(f, a->nat.addr.ipv6); 5068 fprintf(f, " %u ", (uint32_t)(a->nat.port)); 5069 } 5070 5071 if (a->action_mask & (1LLU << RTE_TABLE_ACTION_TTL)) 5072 fprintf(f, "ttl %s ", (a->ttl.decrement) ? "dec" : "keep"); 5073 5074 if (a->action_mask & (1LLU << RTE_TABLE_ACTION_STATS)) 5075 fprintf(f, "stats "); 5076 5077 if (a->action_mask & (1LLU << RTE_TABLE_ACTION_TIME)) 5078 fprintf(f, "time "); 5079 5080 if (a->action_mask & (1LLU << RTE_TABLE_ACTION_SYM_CRYPTO)) 5081 fprintf(f, "sym_crypto "); 5082 5083 if (a->action_mask & (1LLU << RTE_TABLE_ACTION_TAG)) 5084 fprintf(f, "tag %u ", a->tag.tag); 5085 5086 if (a->action_mask & (1LLU << RTE_TABLE_ACTION_DECAP)) 5087 fprintf(f, "decap %u ", a->decap.n); 5088 5089 /* end */ 5090 fprintf(f, "\n"); 5091 } 5092 5093 /* Write table default rule to file. */ 5094 if (table->rule_default) { 5095 struct table_rule_action *a = &table->rule_default->action; 5096 5097 fprintf(f, "# match default action fwd "); 5098 5099 switch (a->fwd.action) { 5100 case RTE_PIPELINE_ACTION_DROP: 5101 fprintf(f, "drop "); 5102 break; 5103 5104 case RTE_PIPELINE_ACTION_PORT: 5105 fprintf(f, "port %u ", a->fwd.id); 5106 break; 5107 5108 case RTE_PIPELINE_ACTION_PORT_META: 5109 fprintf(f, "meta "); 5110 break; 5111 5112 case RTE_PIPELINE_ACTION_TABLE: 5113 default: 5114 fprintf(f, "table %u ", a->fwd.id); 5115 } 5116 } else 5117 fprintf(f, "# match default action fwd drop "); 5118 5119 fprintf(f, "\n"); 5120 5121 /* Close file. */ 5122 fclose(f); 5123 5124 return 0; 5125 } 5126 5127 static const char cmd_pipeline_table_rule_show_help[] = 5128 "pipeline <pipeline_name> table <table_id> rule show\n" 5129 " file <file_name>\n"; 5130 5131 static void 5132 cmd_pipeline_table_rule_show(char **tokens, 5133 uint32_t n_tokens, 5134 char *out, 5135 size_t out_size) 5136 { 5137 char *file_name = NULL, *pipeline_name; 5138 uint32_t table_id; 5139 int status; 5140 5141 if (n_tokens != 8) { 5142 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 5143 return; 5144 } 5145 5146 pipeline_name = tokens[1]; 5147 5148 if (strcmp(tokens[2], "table") != 0) { 5149 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "table"); 5150 return; 5151 } 5152 5153 if (parser_read_uint32(&table_id, tokens[3]) != 0) { 5154 snprintf(out, out_size, MSG_ARG_INVALID, "table_id"); 5155 return; 5156 } 5157 5158 if (strcmp(tokens[4], "rule") != 0) { 5159 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rule"); 5160 return; 5161 } 5162 5163 if (strcmp(tokens[5], "show") != 0) { 5164 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "show"); 5165 return; 5166 } 5167 5168 if (strcmp(tokens[6], "file") != 0) { 5169 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "file"); 5170 return; 5171 } 5172 5173 file_name = tokens[7]; 5174 5175 status = table_rule_show(pipeline_name, table_id, file_name); 5176 if (status) { 5177 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 5178 return; 5179 } 5180 } 5181 5182 static const char cmd_pipeline_table_rule_stats_read_help[] = 5183 "pipeline <pipeline_name> table <table_id> rule read stats [clear]\n" 5184 " match <match>\n"; 5185 5186 static void 5187 cmd_pipeline_table_rule_stats_read(char **tokens, 5188 uint32_t n_tokens, 5189 char *out, 5190 size_t out_size) 5191 { 5192 struct table_rule_match m; 5193 struct rte_table_action_stats_counters stats; 5194 char *pipeline_name; 5195 uint32_t table_id, n_tokens_parsed; 5196 int clear = 0, status; 5197 5198 if (n_tokens < 7) { 5199 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 5200 return; 5201 } 5202 5203 pipeline_name = tokens[1]; 5204 5205 if (strcmp(tokens[2], "table") != 0) { 5206 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "table"); 5207 return; 5208 } 5209 5210 if (parser_read_uint32(&table_id, tokens[3]) != 0) { 5211 snprintf(out, out_size, MSG_ARG_INVALID, "table_id"); 5212 return; 5213 } 5214 5215 if (strcmp(tokens[4], "rule") != 0) { 5216 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rule"); 5217 return; 5218 } 5219 5220 if (strcmp(tokens[5], "read") != 0) { 5221 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "read"); 5222 return; 5223 } 5224 5225 if (strcmp(tokens[6], "stats") != 0) { 5226 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "stats"); 5227 return; 5228 } 5229 5230 n_tokens -= 7; 5231 tokens += 7; 5232 5233 /* clear */ 5234 if (n_tokens && (strcmp(tokens[0], "clear") == 0)) { 5235 clear = 1; 5236 5237 n_tokens--; 5238 tokens++; 5239 } 5240 5241 /* match */ 5242 if ((n_tokens == 0) || strcmp(tokens[0], "match")) { 5243 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "match"); 5244 return; 5245 } 5246 5247 n_tokens_parsed = parse_match(tokens, 5248 n_tokens, 5249 out, 5250 out_size, 5251 &m); 5252 if (n_tokens_parsed == 0) 5253 return; 5254 n_tokens -= n_tokens_parsed; 5255 tokens += n_tokens_parsed; 5256 5257 /* end */ 5258 if (n_tokens) { 5259 snprintf(out, out_size, MSG_ARG_INVALID, tokens[0]); 5260 return; 5261 } 5262 5263 /* Read table rule stats. */ 5264 status = pipeline_table_rule_stats_read(pipeline_name, 5265 table_id, 5266 &m, 5267 &stats, 5268 clear); 5269 if (status) { 5270 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 5271 return; 5272 } 5273 5274 /* Print stats. */ 5275 if (stats.n_packets_valid && stats.n_bytes_valid) 5276 snprintf(out, out_size, "Packets: %" PRIu64 "; Bytes: %" PRIu64 "\n", 5277 stats.n_packets, 5278 stats.n_bytes); 5279 5280 if (stats.n_packets_valid && !stats.n_bytes_valid) 5281 snprintf(out, out_size, "Packets: %" PRIu64 "; Bytes: N/A\n", 5282 stats.n_packets); 5283 5284 if (!stats.n_packets_valid && stats.n_bytes_valid) 5285 snprintf(out, out_size, "Packets: N/A; Bytes: %" PRIu64 "\n", 5286 stats.n_bytes); 5287 5288 if (!stats.n_packets_valid && !stats.n_bytes_valid) 5289 snprintf(out, out_size, "Packets: N/A ; Bytes: N/A\n"); 5290 } 5291 5292 static const char cmd_pipeline_table_meter_profile_add_help[] = 5293 "pipeline <pipeline_name> table <table_id> meter profile <meter_profile_id>\n" 5294 " add srtcm cir <cir> cbs <cbs> ebs <ebs>\n" 5295 " | trtcm cir <cir> pir <pir> cbs <cbs> pbs <pbs>\n"; 5296 5297 static void 5298 cmd_pipeline_table_meter_profile_add(char **tokens, 5299 uint32_t n_tokens, 5300 char *out, 5301 size_t out_size) 5302 { 5303 struct rte_table_action_meter_profile p; 5304 char *pipeline_name; 5305 uint32_t table_id, meter_profile_id; 5306 int status; 5307 5308 if (n_tokens < 9) { 5309 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 5310 return; 5311 } 5312 5313 pipeline_name = tokens[1]; 5314 5315 if (strcmp(tokens[2], "table") != 0) { 5316 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port"); 5317 return; 5318 } 5319 5320 if (parser_read_uint32(&table_id, tokens[3]) != 0) { 5321 snprintf(out, out_size, MSG_ARG_INVALID, "table_id"); 5322 return; 5323 } 5324 5325 if (strcmp(tokens[4], "meter") != 0) { 5326 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "meter"); 5327 return; 5328 } 5329 5330 if (strcmp(tokens[5], "profile") != 0) { 5331 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "profile"); 5332 return; 5333 } 5334 5335 if (parser_read_uint32(&meter_profile_id, tokens[6]) != 0) { 5336 snprintf(out, out_size, MSG_ARG_INVALID, "meter_profile_id"); 5337 return; 5338 } 5339 5340 if (strcmp(tokens[7], "add") != 0) { 5341 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "add"); 5342 return; 5343 } 5344 5345 if (strcmp(tokens[8], "srtcm") == 0) { 5346 if (n_tokens != 15) { 5347 snprintf(out, out_size, MSG_ARG_MISMATCH, 5348 tokens[0]); 5349 return; 5350 } 5351 5352 p.alg = RTE_TABLE_ACTION_METER_SRTCM; 5353 5354 if (strcmp(tokens[9], "cir") != 0) { 5355 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "cir"); 5356 return; 5357 } 5358 5359 if (parser_read_uint64(&p.srtcm.cir, tokens[10]) != 0) { 5360 snprintf(out, out_size, MSG_ARG_INVALID, "cir"); 5361 return; 5362 } 5363 5364 if (strcmp(tokens[11], "cbs") != 0) { 5365 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "cbs"); 5366 return; 5367 } 5368 5369 if (parser_read_uint64(&p.srtcm.cbs, tokens[12]) != 0) { 5370 snprintf(out, out_size, MSG_ARG_INVALID, "cbs"); 5371 return; 5372 } 5373 5374 if (strcmp(tokens[13], "ebs") != 0) { 5375 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "ebs"); 5376 return; 5377 } 5378 5379 if (parser_read_uint64(&p.srtcm.ebs, tokens[14]) != 0) { 5380 snprintf(out, out_size, MSG_ARG_INVALID, "ebs"); 5381 return; 5382 } 5383 } else if (strcmp(tokens[8], "trtcm") == 0) { 5384 if (n_tokens != 17) { 5385 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 5386 return; 5387 } 5388 5389 p.alg = RTE_TABLE_ACTION_METER_TRTCM; 5390 5391 if (strcmp(tokens[9], "cir") != 0) { 5392 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "cir"); 5393 return; 5394 } 5395 5396 if (parser_read_uint64(&p.trtcm.cir, tokens[10]) != 0) { 5397 snprintf(out, out_size, MSG_ARG_INVALID, "cir"); 5398 return; 5399 } 5400 5401 if (strcmp(tokens[11], "pir") != 0) { 5402 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pir"); 5403 return; 5404 } 5405 5406 if (parser_read_uint64(&p.trtcm.pir, tokens[12]) != 0) { 5407 snprintf(out, out_size, MSG_ARG_INVALID, "pir"); 5408 return; 5409 } 5410 if (strcmp(tokens[13], "cbs") != 0) { 5411 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "cbs"); 5412 return; 5413 } 5414 5415 if (parser_read_uint64(&p.trtcm.cbs, tokens[14]) != 0) { 5416 snprintf(out, out_size, MSG_ARG_INVALID, "cbs"); 5417 return; 5418 } 5419 5420 if (strcmp(tokens[15], "pbs") != 0) { 5421 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pbs"); 5422 return; 5423 } 5424 5425 if (parser_read_uint64(&p.trtcm.pbs, tokens[16]) != 0) { 5426 snprintf(out, out_size, MSG_ARG_INVALID, "pbs"); 5427 return; 5428 } 5429 } else { 5430 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 5431 return; 5432 } 5433 5434 status = pipeline_table_mtr_profile_add(pipeline_name, 5435 table_id, 5436 meter_profile_id, 5437 &p); 5438 if (status) { 5439 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 5440 return; 5441 } 5442 } 5443 5444 5445 static const char cmd_pipeline_table_meter_profile_delete_help[] = 5446 "pipeline <pipeline_name> table <table_id>\n" 5447 " meter profile <meter_profile_id> delete\n"; 5448 5449 static void 5450 cmd_pipeline_table_meter_profile_delete(char **tokens, 5451 uint32_t n_tokens, 5452 char *out, 5453 size_t out_size) 5454 { 5455 char *pipeline_name; 5456 uint32_t table_id, meter_profile_id; 5457 int status; 5458 5459 if (n_tokens != 8) { 5460 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 5461 return; 5462 } 5463 5464 pipeline_name = tokens[1]; 5465 5466 if (strcmp(tokens[2], "table") != 0) { 5467 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port"); 5468 return; 5469 } 5470 5471 if (parser_read_uint32(&table_id, tokens[3]) != 0) { 5472 snprintf(out, out_size, MSG_ARG_INVALID, "table_id"); 5473 return; 5474 } 5475 5476 if (strcmp(tokens[4], "meter") != 0) { 5477 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "meter"); 5478 return; 5479 } 5480 5481 if (strcmp(tokens[5], "profile") != 0) { 5482 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "profile"); 5483 return; 5484 } 5485 5486 if (parser_read_uint32(&meter_profile_id, tokens[6]) != 0) { 5487 snprintf(out, out_size, MSG_ARG_INVALID, "meter_profile_id"); 5488 return; 5489 } 5490 5491 if (strcmp(tokens[7], "delete") != 0) { 5492 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "delete"); 5493 return; 5494 } 5495 5496 status = pipeline_table_mtr_profile_delete(pipeline_name, 5497 table_id, 5498 meter_profile_id); 5499 if (status) { 5500 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 5501 return; 5502 } 5503 } 5504 5505 5506 static const char cmd_pipeline_table_rule_meter_read_help[] = 5507 "pipeline <pipeline_name> table <table_id> rule read meter [clear]\n" 5508 " match <match>\n"; 5509 5510 static void 5511 cmd_pipeline_table_rule_meter_read(char **tokens, 5512 uint32_t n_tokens, 5513 char *out, 5514 size_t out_size) 5515 { 5516 struct table_rule_match m; 5517 struct rte_table_action_mtr_counters stats; 5518 char *pipeline_name; 5519 uint32_t table_id, n_tokens_parsed; 5520 int clear = 0, status; 5521 5522 if (n_tokens < 7) { 5523 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 5524 return; 5525 } 5526 5527 pipeline_name = tokens[1]; 5528 5529 if (strcmp(tokens[2], "table") != 0) { 5530 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "table"); 5531 return; 5532 } 5533 5534 if (parser_read_uint32(&table_id, tokens[3]) != 0) { 5535 snprintf(out, out_size, MSG_ARG_INVALID, "table_id"); 5536 return; 5537 } 5538 5539 if (strcmp(tokens[4], "rule") != 0) { 5540 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rule"); 5541 return; 5542 } 5543 5544 if (strcmp(tokens[5], "read") != 0) { 5545 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "read"); 5546 return; 5547 } 5548 5549 if (strcmp(tokens[6], "meter") != 0) { 5550 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "meter"); 5551 return; 5552 } 5553 5554 n_tokens -= 7; 5555 tokens += 7; 5556 5557 /* clear */ 5558 if (n_tokens && (strcmp(tokens[0], "clear") == 0)) { 5559 clear = 1; 5560 5561 n_tokens--; 5562 tokens++; 5563 } 5564 5565 /* match */ 5566 if ((n_tokens == 0) || strcmp(tokens[0], "match")) { 5567 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "match"); 5568 return; 5569 } 5570 5571 n_tokens_parsed = parse_match(tokens, 5572 n_tokens, 5573 out, 5574 out_size, 5575 &m); 5576 if (n_tokens_parsed == 0) 5577 return; 5578 n_tokens -= n_tokens_parsed; 5579 tokens += n_tokens_parsed; 5580 5581 /* end */ 5582 if (n_tokens) { 5583 snprintf(out, out_size, MSG_ARG_INVALID, tokens[0]); 5584 return; 5585 } 5586 5587 /* Read table rule meter stats. */ 5588 status = pipeline_table_rule_mtr_read(pipeline_name, 5589 table_id, 5590 &m, 5591 &stats, 5592 clear); 5593 if (status) { 5594 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 5595 return; 5596 } 5597 5598 /* Print stats. */ 5599 } 5600 5601 5602 static const char cmd_pipeline_table_dscp_help[] = 5603 "pipeline <pipeline_name> table <table_id> dscp <file_name>\n" 5604 "\n" 5605 " File <file_name>:\n" 5606 " - exactly 64 lines\n" 5607 " - line format: <tc_id> <tc_queue_id> <color>, with <color> as: g | y | r\n"; 5608 5609 static int 5610 load_dscp_table(struct rte_table_action_dscp_table *dscp_table, 5611 const char *file_name, 5612 uint32_t *line_number) 5613 { 5614 FILE *f = NULL; 5615 uint32_t dscp, l; 5616 5617 /* Check input arguments */ 5618 if ((dscp_table == NULL) || 5619 (file_name == NULL) || 5620 (line_number == NULL)) { 5621 if (line_number) 5622 *line_number = 0; 5623 return -EINVAL; 5624 } 5625 5626 /* Open input file */ 5627 f = fopen(file_name, "r"); 5628 if (f == NULL) { 5629 *line_number = 0; 5630 return -EINVAL; 5631 } 5632 5633 /* Read file */ 5634 for (dscp = 0, l = 1; ; l++) { 5635 char line[64]; 5636 char *tokens[3]; 5637 enum rte_color color; 5638 uint32_t tc_id, tc_queue_id, n_tokens = RTE_DIM(tokens); 5639 5640 if (fgets(line, sizeof(line), f) == NULL) 5641 break; 5642 5643 if (is_comment(line)) 5644 continue; 5645 5646 if (parse_tokenize_string(line, tokens, &n_tokens)) { 5647 *line_number = l; 5648 fclose(f); 5649 return -EINVAL; 5650 } 5651 5652 if (n_tokens == 0) 5653 continue; 5654 5655 if ((dscp >= RTE_DIM(dscp_table->entry)) || 5656 (n_tokens != RTE_DIM(tokens)) || 5657 parser_read_uint32(&tc_id, tokens[0]) || 5658 (tc_id >= RTE_TABLE_ACTION_TC_MAX) || 5659 parser_read_uint32(&tc_queue_id, tokens[1]) || 5660 (tc_queue_id >= RTE_TABLE_ACTION_TC_QUEUE_MAX) || 5661 (strlen(tokens[2]) != 1)) { 5662 *line_number = l; 5663 fclose(f); 5664 return -EINVAL; 5665 } 5666 5667 switch (tokens[2][0]) { 5668 case 'g': 5669 case 'G': 5670 color = RTE_COLOR_GREEN; 5671 break; 5672 5673 case 'y': 5674 case 'Y': 5675 color = RTE_COLOR_YELLOW; 5676 break; 5677 5678 case 'r': 5679 case 'R': 5680 color = RTE_COLOR_RED; 5681 break; 5682 5683 default: 5684 *line_number = l; 5685 fclose(f); 5686 return -EINVAL; 5687 } 5688 5689 dscp_table->entry[dscp].tc_id = tc_id; 5690 dscp_table->entry[dscp].tc_queue_id = tc_queue_id; 5691 dscp_table->entry[dscp].color = color; 5692 dscp++; 5693 } 5694 5695 /* Close file */ 5696 fclose(f); 5697 return 0; 5698 } 5699 5700 static void 5701 cmd_pipeline_table_dscp(char **tokens, 5702 uint32_t n_tokens, 5703 char *out, 5704 size_t out_size) 5705 { 5706 struct rte_table_action_dscp_table dscp_table; 5707 char *pipeline_name, *file_name; 5708 uint32_t table_id, line_number; 5709 int status; 5710 5711 if (n_tokens != 6) { 5712 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 5713 return; 5714 } 5715 5716 pipeline_name = tokens[1]; 5717 5718 if (strcmp(tokens[2], "table") != 0) { 5719 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port"); 5720 return; 5721 } 5722 5723 if (parser_read_uint32(&table_id, tokens[3]) != 0) { 5724 snprintf(out, out_size, MSG_ARG_INVALID, "table_id"); 5725 return; 5726 } 5727 5728 if (strcmp(tokens[4], "dscp") != 0) { 5729 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "dscp"); 5730 return; 5731 } 5732 5733 file_name = tokens[5]; 5734 5735 status = load_dscp_table(&dscp_table, file_name, &line_number); 5736 if (status) { 5737 snprintf(out, out_size, MSG_FILE_ERR, file_name, line_number); 5738 return; 5739 } 5740 5741 status = pipeline_table_dscp_table_update(pipeline_name, 5742 table_id, 5743 UINT64_MAX, 5744 &dscp_table); 5745 if (status) { 5746 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 5747 return; 5748 } 5749 } 5750 5751 5752 static const char cmd_pipeline_table_rule_ttl_read_help[] = 5753 "pipeline <pipeline_name> table <table_id> rule read ttl [clear]\n" 5754 " match <match>\n"; 5755 5756 static void 5757 cmd_pipeline_table_rule_ttl_read(char **tokens, 5758 uint32_t n_tokens, 5759 char *out, 5760 size_t out_size) 5761 { 5762 struct table_rule_match m; 5763 struct rte_table_action_ttl_counters stats; 5764 char *pipeline_name; 5765 uint32_t table_id, n_tokens_parsed; 5766 int clear = 0, status; 5767 5768 if (n_tokens < 7) { 5769 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 5770 return; 5771 } 5772 5773 pipeline_name = tokens[1]; 5774 5775 if (strcmp(tokens[2], "table") != 0) { 5776 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "table"); 5777 return; 5778 } 5779 5780 if (parser_read_uint32(&table_id, tokens[3]) != 0) { 5781 snprintf(out, out_size, MSG_ARG_INVALID, "table_id"); 5782 return; 5783 } 5784 5785 if (strcmp(tokens[4], "rule") != 0) { 5786 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rule"); 5787 return; 5788 } 5789 5790 if (strcmp(tokens[5], "read") != 0) { 5791 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "read"); 5792 return; 5793 } 5794 5795 if (strcmp(tokens[6], "ttl") != 0) { 5796 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "ttl"); 5797 return; 5798 } 5799 5800 n_tokens -= 7; 5801 tokens += 7; 5802 5803 /* clear */ 5804 if (n_tokens && (strcmp(tokens[0], "clear") == 0)) { 5805 clear = 1; 5806 5807 n_tokens--; 5808 tokens++; 5809 } 5810 5811 /* match */ 5812 if ((n_tokens == 0) || strcmp(tokens[0], "match")) { 5813 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "match"); 5814 return; 5815 } 5816 5817 n_tokens_parsed = parse_match(tokens, 5818 n_tokens, 5819 out, 5820 out_size, 5821 &m); 5822 if (n_tokens_parsed == 0) 5823 return; 5824 n_tokens -= n_tokens_parsed; 5825 tokens += n_tokens_parsed; 5826 5827 /* end */ 5828 if (n_tokens) { 5829 snprintf(out, out_size, MSG_ARG_INVALID, tokens[0]); 5830 return; 5831 } 5832 5833 /* Read table rule TTL stats. */ 5834 status = pipeline_table_rule_ttl_read(pipeline_name, 5835 table_id, 5836 &m, 5837 &stats, 5838 clear); 5839 if (status) { 5840 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 5841 return; 5842 } 5843 5844 /* Print stats. */ 5845 snprintf(out, out_size, "Packets: %" PRIu64 "\n", 5846 stats.n_packets); 5847 } 5848 5849 static const char cmd_pipeline_table_rule_time_read_help[] = 5850 "pipeline <pipeline_name> table <table_id> rule read time\n" 5851 " match <match>\n"; 5852 5853 static void 5854 cmd_pipeline_table_rule_time_read(char **tokens, 5855 uint32_t n_tokens, 5856 char *out, 5857 size_t out_size) 5858 { 5859 struct table_rule_match m; 5860 char *pipeline_name; 5861 uint64_t timestamp; 5862 uint32_t table_id, n_tokens_parsed; 5863 int status; 5864 5865 if (n_tokens < 7) { 5866 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 5867 return; 5868 } 5869 5870 pipeline_name = tokens[1]; 5871 5872 if (strcmp(tokens[2], "table") != 0) { 5873 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "table"); 5874 return; 5875 } 5876 5877 if (parser_read_uint32(&table_id, tokens[3]) != 0) { 5878 snprintf(out, out_size, MSG_ARG_INVALID, "table_id"); 5879 return; 5880 } 5881 5882 if (strcmp(tokens[4], "rule") != 0) { 5883 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rule"); 5884 return; 5885 } 5886 5887 if (strcmp(tokens[5], "read") != 0) { 5888 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "read"); 5889 return; 5890 } 5891 5892 if (strcmp(tokens[6], "time") != 0) { 5893 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "time"); 5894 return; 5895 } 5896 5897 n_tokens -= 7; 5898 tokens += 7; 5899 5900 /* match */ 5901 if ((n_tokens == 0) || strcmp(tokens[0], "match")) { 5902 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "match"); 5903 return; 5904 } 5905 5906 n_tokens_parsed = parse_match(tokens, 5907 n_tokens, 5908 out, 5909 out_size, 5910 &m); 5911 if (n_tokens_parsed == 0) 5912 return; 5913 n_tokens -= n_tokens_parsed; 5914 tokens += n_tokens_parsed; 5915 5916 /* end */ 5917 if (n_tokens) { 5918 snprintf(out, out_size, MSG_ARG_INVALID, tokens[0]); 5919 return; 5920 } 5921 5922 /* Read table rule timestamp. */ 5923 status = pipeline_table_rule_time_read(pipeline_name, 5924 table_id, 5925 &m, 5926 ×tamp); 5927 if (status) { 5928 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 5929 return; 5930 } 5931 5932 /* Print stats. */ 5933 snprintf(out, out_size, "Packets: %" PRIu64 "\n", timestamp); 5934 } 5935 5936 static const char cmd_thread_pipeline_enable_help[] = 5937 "thread <thread_id> pipeline <pipeline_name> enable\n"; 5938 5939 static void 5940 cmd_thread_pipeline_enable(char **tokens, 5941 uint32_t n_tokens, 5942 char *out, 5943 size_t out_size) 5944 { 5945 char *pipeline_name; 5946 uint32_t thread_id; 5947 int status; 5948 5949 if (n_tokens != 5) { 5950 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 5951 return; 5952 } 5953 5954 if (parser_read_uint32(&thread_id, tokens[1]) != 0) { 5955 snprintf(out, out_size, MSG_ARG_INVALID, "thread_id"); 5956 return; 5957 } 5958 5959 if (strcmp(tokens[2], "pipeline") != 0) { 5960 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pipeline"); 5961 return; 5962 } 5963 5964 pipeline_name = tokens[3]; 5965 5966 if (strcmp(tokens[4], "enable") != 0) { 5967 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "enable"); 5968 return; 5969 } 5970 5971 status = thread_pipeline_enable(thread_id, pipeline_name); 5972 if (status) { 5973 snprintf(out, out_size, MSG_CMD_FAIL, "thread pipeline enable"); 5974 return; 5975 } 5976 } 5977 5978 5979 static const char cmd_thread_pipeline_disable_help[] = 5980 "thread <thread_id> pipeline <pipeline_name> disable\n"; 5981 5982 static void 5983 cmd_thread_pipeline_disable(char **tokens, 5984 uint32_t n_tokens, 5985 char *out, 5986 size_t out_size) 5987 { 5988 char *pipeline_name; 5989 uint32_t thread_id; 5990 int status; 5991 5992 if (n_tokens != 5) { 5993 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 5994 return; 5995 } 5996 5997 if (parser_read_uint32(&thread_id, tokens[1]) != 0) { 5998 snprintf(out, out_size, MSG_ARG_INVALID, "thread_id"); 5999 return; 6000 } 6001 6002 if (strcmp(tokens[2], "pipeline") != 0) { 6003 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pipeline"); 6004 return; 6005 } 6006 6007 pipeline_name = tokens[3]; 6008 6009 if (strcmp(tokens[4], "disable") != 0) { 6010 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "disable"); 6011 return; 6012 } 6013 6014 status = thread_pipeline_disable(thread_id, pipeline_name); 6015 if (status) { 6016 snprintf(out, out_size, MSG_CMD_FAIL, 6017 "thread pipeline disable"); 6018 return; 6019 } 6020 } 6021 6022 static void 6023 cmd_help(char **tokens, uint32_t n_tokens, char *out, size_t out_size) 6024 { 6025 tokens++; 6026 n_tokens--; 6027 6028 if (n_tokens == 0) { 6029 snprintf(out, out_size, 6030 "Type 'help <command>' for details on each command.\n\n" 6031 "List of commands:\n" 6032 "\tmempool\n" 6033 "\tlink\n" 6034 "\tswq\n" 6035 "\ttmgr subport profile\n" 6036 "\ttmgr pipe profile\n" 6037 "\ttmgr\n" 6038 "\ttmgr subport\n" 6039 "\ttmgr subport pipe\n" 6040 "\ttap\n" 6041 "\tkni\n" 6042 "\tport in action profile\n" 6043 "\ttable action profile\n" 6044 "\tpipeline\n" 6045 "\tpipeline port in\n" 6046 "\tpipeline port out\n" 6047 "\tpipeline table\n" 6048 "\tpipeline port in table\n" 6049 "\tpipeline port in stats\n" 6050 "\tpipeline port in enable\n" 6051 "\tpipeline port in disable\n" 6052 "\tpipeline port out stats\n" 6053 "\tpipeline table stats\n" 6054 "\tpipeline table rule add\n" 6055 "\tpipeline table rule add default\n" 6056 "\tpipeline table rule add bulk\n" 6057 "\tpipeline table rule delete\n" 6058 "\tpipeline table rule delete default\n" 6059 "\tpipeline table rule show\n" 6060 "\tpipeline table rule stats read\n" 6061 "\tpipeline table meter profile add\n" 6062 "\tpipeline table meter profile delete\n" 6063 "\tpipeline table rule meter read\n" 6064 "\tpipeline table dscp\n" 6065 "\tpipeline table rule ttl read\n" 6066 "\tpipeline table rule time read\n" 6067 "\tthread pipeline enable\n" 6068 "\tthread pipeline disable\n\n"); 6069 return; 6070 } 6071 6072 if (strcmp(tokens[0], "mempool") == 0) { 6073 snprintf(out, out_size, "\n%s\n", cmd_mempool_help); 6074 return; 6075 } 6076 6077 if (strcmp(tokens[0], "link") == 0) { 6078 snprintf(out, out_size, "\n%s\n", cmd_link_help); 6079 return; 6080 } 6081 6082 if (strcmp(tokens[0], "swq") == 0) { 6083 snprintf(out, out_size, "\n%s\n", cmd_swq_help); 6084 return; 6085 } 6086 6087 if (strcmp(tokens[0], "tmgr") == 0) { 6088 if (n_tokens == 1) { 6089 snprintf(out, out_size, "\n%s\n", cmd_tmgr_help); 6090 return; 6091 } 6092 6093 if ((n_tokens == 2) && 6094 (strcmp(tokens[1], "subport")) == 0) { 6095 snprintf(out, out_size, "\n%s\n", cmd_tmgr_subport_help); 6096 return; 6097 } 6098 6099 if ((n_tokens == 3) && 6100 (strcmp(tokens[1], "subport") == 0) && 6101 (strcmp(tokens[2], "profile") == 0)) { 6102 snprintf(out, out_size, "\n%s\n", 6103 cmd_tmgr_subport_profile_help); 6104 return; 6105 } 6106 6107 if ((n_tokens == 3) && 6108 (strcmp(tokens[1], "subport") == 0) && 6109 (strcmp(tokens[2], "pipe") == 0)) { 6110 snprintf(out, out_size, "\n%s\n", cmd_tmgr_subport_pipe_help); 6111 return; 6112 } 6113 6114 if ((n_tokens == 3) && 6115 (strcmp(tokens[1], "pipe") == 0) && 6116 (strcmp(tokens[2], "profile") == 0)) { 6117 snprintf(out, out_size, "\n%s\n", cmd_tmgr_pipe_profile_help); 6118 return; 6119 } 6120 } 6121 6122 if (strcmp(tokens[0], "tap") == 0) { 6123 snprintf(out, out_size, "\n%s\n", cmd_tap_help); 6124 return; 6125 } 6126 6127 if (strcmp(tokens[0], "kni") == 0) { 6128 snprintf(out, out_size, "\n%s\n", cmd_kni_help); 6129 return; 6130 } 6131 6132 if (strcmp(tokens[0], "cryptodev") == 0) { 6133 snprintf(out, out_size, "\n%s\n", cmd_cryptodev_help); 6134 return; 6135 } 6136 6137 if ((n_tokens == 4) && 6138 (strcmp(tokens[0], "port") == 0) && 6139 (strcmp(tokens[1], "in") == 0) && 6140 (strcmp(tokens[2], "action") == 0) && 6141 (strcmp(tokens[3], "profile") == 0)) { 6142 snprintf(out, out_size, "\n%s\n", cmd_port_in_action_profile_help); 6143 return; 6144 } 6145 6146 if ((n_tokens == 3) && 6147 (strcmp(tokens[0], "table") == 0) && 6148 (strcmp(tokens[1], "action") == 0) && 6149 (strcmp(tokens[2], "profile") == 0)) { 6150 snprintf(out, out_size, "\n%s\n", cmd_table_action_profile_help); 6151 return; 6152 } 6153 6154 if ((strcmp(tokens[0], "pipeline") == 0) && (n_tokens == 1)) { 6155 snprintf(out, out_size, "\n%s\n", cmd_pipeline_help); 6156 return; 6157 } 6158 6159 if ((strcmp(tokens[0], "pipeline") == 0) && 6160 (strcmp(tokens[1], "port") == 0)) { 6161 if ((n_tokens == 3) && (strcmp(tokens[2], "in")) == 0) { 6162 snprintf(out, out_size, "\n%s\n", cmd_pipeline_port_in_help); 6163 return; 6164 } 6165 6166 if ((n_tokens == 3) && (strcmp(tokens[2], "out")) == 0) { 6167 snprintf(out, out_size, "\n%s\n", cmd_pipeline_port_out_help); 6168 return; 6169 } 6170 6171 if ((n_tokens == 4) && 6172 (strcmp(tokens[2], "in") == 0) && 6173 (strcmp(tokens[3], "table") == 0)) { 6174 snprintf(out, out_size, "\n%s\n", 6175 cmd_pipeline_port_in_table_help); 6176 return; 6177 } 6178 6179 if ((n_tokens == 4) && 6180 (strcmp(tokens[2], "in") == 0) && 6181 (strcmp(tokens[3], "stats") == 0)) { 6182 snprintf(out, out_size, "\n%s\n", 6183 cmd_pipeline_port_in_stats_help); 6184 return; 6185 } 6186 6187 if ((n_tokens == 4) && 6188 (strcmp(tokens[2], "in") == 0) && 6189 (strcmp(tokens[3], "enable") == 0)) { 6190 snprintf(out, out_size, "\n%s\n", 6191 cmd_pipeline_port_in_enable_help); 6192 return; 6193 } 6194 6195 if ((n_tokens == 4) && 6196 (strcmp(tokens[2], "in") == 0) && 6197 (strcmp(tokens[3], "disable") == 0)) { 6198 snprintf(out, out_size, "\n%s\n", 6199 cmd_pipeline_port_in_disable_help); 6200 return; 6201 } 6202 6203 if ((n_tokens == 4) && 6204 (strcmp(tokens[2], "out") == 0) && 6205 (strcmp(tokens[3], "stats") == 0)) { 6206 snprintf(out, out_size, "\n%s\n", 6207 cmd_pipeline_port_out_stats_help); 6208 return; 6209 } 6210 } 6211 6212 if ((strcmp(tokens[0], "pipeline") == 0) && 6213 (strcmp(tokens[1], "table") == 0)) { 6214 if (n_tokens == 2) { 6215 snprintf(out, out_size, "\n%s\n", cmd_pipeline_table_help); 6216 return; 6217 } 6218 6219 if ((n_tokens == 3) && strcmp(tokens[2], "stats") == 0) { 6220 snprintf(out, out_size, "\n%s\n", 6221 cmd_pipeline_table_stats_help); 6222 return; 6223 } 6224 6225 if ((n_tokens == 3) && strcmp(tokens[2], "dscp") == 0) { 6226 snprintf(out, out_size, "\n%s\n", 6227 cmd_pipeline_table_dscp_help); 6228 return; 6229 } 6230 6231 if ((n_tokens == 4) && 6232 (strcmp(tokens[2], "rule") == 0) && 6233 (strcmp(tokens[3], "add") == 0)) { 6234 snprintf(out, out_size, "\n%s\n", 6235 cmd_pipeline_table_rule_add_help); 6236 return; 6237 } 6238 6239 if ((n_tokens == 5) && 6240 (strcmp(tokens[2], "rule") == 0) && 6241 (strcmp(tokens[3], "add") == 0) && 6242 (strcmp(tokens[4], "default") == 0)) { 6243 snprintf(out, out_size, "\n%s\n", 6244 cmd_pipeline_table_rule_add_default_help); 6245 return; 6246 } 6247 6248 if ((n_tokens == 5) && 6249 (strcmp(tokens[2], "rule") == 0) && 6250 (strcmp(tokens[3], "add") == 0) && 6251 (strcmp(tokens[4], "bulk") == 0)) { 6252 snprintf(out, out_size, "\n%s\n", 6253 cmd_pipeline_table_rule_add_bulk_help); 6254 return; 6255 } 6256 6257 if ((n_tokens == 4) && 6258 (strcmp(tokens[2], "rule") == 0) && 6259 (strcmp(tokens[3], "delete") == 0)) { 6260 snprintf(out, out_size, "\n%s\n", 6261 cmd_pipeline_table_rule_delete_help); 6262 return; 6263 } 6264 6265 if ((n_tokens == 5) && 6266 (strcmp(tokens[2], "rule") == 0) && 6267 (strcmp(tokens[3], "delete") == 0) && 6268 (strcmp(tokens[4], "default") == 0)) { 6269 snprintf(out, out_size, "\n%s\n", 6270 cmd_pipeline_table_rule_delete_default_help); 6271 return; 6272 } 6273 6274 if ((n_tokens == 4) && 6275 (strcmp(tokens[2], "rule") == 0) && 6276 (strcmp(tokens[3], "show") == 0)) { 6277 snprintf(out, out_size, "\n%s\n", 6278 cmd_pipeline_table_rule_show_help); 6279 return; 6280 } 6281 6282 if ((n_tokens == 5) && 6283 (strcmp(tokens[2], "rule") == 0) && 6284 (strcmp(tokens[3], "stats") == 0) && 6285 (strcmp(tokens[4], "read") == 0)) { 6286 snprintf(out, out_size, "\n%s\n", 6287 cmd_pipeline_table_rule_stats_read_help); 6288 return; 6289 } 6290 6291 if ((n_tokens == 5) && 6292 (strcmp(tokens[2], "meter") == 0) && 6293 (strcmp(tokens[3], "profile") == 0) && 6294 (strcmp(tokens[4], "add") == 0)) { 6295 snprintf(out, out_size, "\n%s\n", 6296 cmd_pipeline_table_meter_profile_add_help); 6297 return; 6298 } 6299 6300 if ((n_tokens == 5) && 6301 (strcmp(tokens[2], "meter") == 0) && 6302 (strcmp(tokens[3], "profile") == 0) && 6303 (strcmp(tokens[4], "delete") == 0)) { 6304 snprintf(out, out_size, "\n%s\n", 6305 cmd_pipeline_table_meter_profile_delete_help); 6306 return; 6307 } 6308 6309 if ((n_tokens == 5) && 6310 (strcmp(tokens[2], "rule") == 0) && 6311 (strcmp(tokens[3], "meter") == 0) && 6312 (strcmp(tokens[4], "read") == 0)) { 6313 snprintf(out, out_size, "\n%s\n", 6314 cmd_pipeline_table_rule_meter_read_help); 6315 return; 6316 } 6317 6318 if ((n_tokens == 5) && 6319 (strcmp(tokens[2], "rule") == 0) && 6320 (strcmp(tokens[3], "ttl") == 0) && 6321 (strcmp(tokens[4], "read") == 0)) { 6322 snprintf(out, out_size, "\n%s\n", 6323 cmd_pipeline_table_rule_ttl_read_help); 6324 return; 6325 } 6326 6327 if ((n_tokens == 5) && 6328 (strcmp(tokens[2], "rule") == 0) && 6329 (strcmp(tokens[3], "time") == 0) && 6330 (strcmp(tokens[4], "read") == 0)) { 6331 snprintf(out, out_size, "\n%s\n", 6332 cmd_pipeline_table_rule_time_read_help); 6333 return; 6334 } 6335 } 6336 6337 if ((n_tokens == 3) && 6338 (strcmp(tokens[0], "thread") == 0) && 6339 (strcmp(tokens[1], "pipeline") == 0)) { 6340 if (strcmp(tokens[2], "enable") == 0) { 6341 snprintf(out, out_size, "\n%s\n", 6342 cmd_thread_pipeline_enable_help); 6343 return; 6344 } 6345 6346 if (strcmp(tokens[2], "disable") == 0) { 6347 snprintf(out, out_size, "\n%s\n", 6348 cmd_thread_pipeline_disable_help); 6349 return; 6350 } 6351 } 6352 6353 snprintf(out, out_size, "Invalid command\n"); 6354 } 6355 6356 void 6357 cli_process(char *in, char *out, size_t out_size) 6358 { 6359 char *tokens[CMD_MAX_TOKENS]; 6360 uint32_t n_tokens = RTE_DIM(tokens); 6361 int status; 6362 6363 if (is_comment(in)) 6364 return; 6365 6366 status = parse_tokenize_string(in, tokens, &n_tokens); 6367 if (status) { 6368 snprintf(out, out_size, MSG_ARG_TOO_MANY, ""); 6369 return; 6370 } 6371 6372 if (n_tokens == 0) 6373 return; 6374 6375 if (strcmp(tokens[0], "help") == 0) { 6376 cmd_help(tokens, n_tokens, out, out_size); 6377 return; 6378 } 6379 6380 if (strcmp(tokens[0], "mempool") == 0) { 6381 cmd_mempool(tokens, n_tokens, out, out_size); 6382 return; 6383 } 6384 6385 if (strcmp(tokens[0], "link") == 0) { 6386 if (strcmp(tokens[1], "show") == 0) { 6387 cmd_link_show(tokens, n_tokens, out, out_size); 6388 return; 6389 } 6390 6391 cmd_link(tokens, n_tokens, out, out_size); 6392 return; 6393 } 6394 6395 if (strcmp(tokens[0], "swq") == 0) { 6396 cmd_swq(tokens, n_tokens, out, out_size); 6397 return; 6398 } 6399 6400 if (strcmp(tokens[0], "tmgr") == 0) { 6401 if ((n_tokens >= 3) && 6402 (strcmp(tokens[1], "subport") == 0) && 6403 (strcmp(tokens[2], "profile") == 0)) { 6404 cmd_tmgr_subport_profile(tokens, n_tokens, 6405 out, out_size); 6406 return; 6407 } 6408 6409 if ((n_tokens >= 3) && 6410 (strcmp(tokens[1], "pipe") == 0) && 6411 (strcmp(tokens[2], "profile") == 0)) { 6412 cmd_tmgr_pipe_profile(tokens, n_tokens, out, out_size); 6413 return; 6414 } 6415 6416 if ((n_tokens >= 5) && 6417 (strcmp(tokens[2], "subport") == 0) && 6418 (strcmp(tokens[4], "profile") == 0)) { 6419 cmd_tmgr_subport(tokens, n_tokens, out, out_size); 6420 return; 6421 } 6422 6423 if ((n_tokens >= 5) && 6424 (strcmp(tokens[2], "subport") == 0) && 6425 (strcmp(tokens[4], "pipe") == 0)) { 6426 cmd_tmgr_subport_pipe(tokens, n_tokens, out, out_size); 6427 return; 6428 } 6429 6430 cmd_tmgr(tokens, n_tokens, out, out_size); 6431 return; 6432 } 6433 6434 if (strcmp(tokens[0], "tap") == 0) { 6435 cmd_tap(tokens, n_tokens, out, out_size); 6436 return; 6437 } 6438 6439 if (strcmp(tokens[0], "kni") == 0) { 6440 cmd_kni(tokens, n_tokens, out, out_size); 6441 return; 6442 } 6443 6444 if (strcmp(tokens[0], "cryptodev") == 0) { 6445 cmd_cryptodev(tokens, n_tokens, out, out_size); 6446 return; 6447 } 6448 6449 if (strcmp(tokens[0], "port") == 0) { 6450 cmd_port_in_action_profile(tokens, n_tokens, out, out_size); 6451 return; 6452 } 6453 6454 if (strcmp(tokens[0], "table") == 0) { 6455 cmd_table_action_profile(tokens, n_tokens, out, out_size); 6456 return; 6457 } 6458 6459 if (strcmp(tokens[0], "pipeline") == 0) { 6460 if ((n_tokens >= 3) && 6461 (strcmp(tokens[2], "period") == 0)) { 6462 cmd_pipeline(tokens, n_tokens, out, out_size); 6463 return; 6464 } 6465 6466 if ((n_tokens >= 5) && 6467 (strcmp(tokens[2], "port") == 0) && 6468 (strcmp(tokens[3], "in") == 0) && 6469 (strcmp(tokens[4], "bsz") == 0)) { 6470 cmd_pipeline_port_in(tokens, n_tokens, out, out_size); 6471 return; 6472 } 6473 6474 if ((n_tokens >= 5) && 6475 (strcmp(tokens[2], "port") == 0) && 6476 (strcmp(tokens[3], "out") == 0) && 6477 (strcmp(tokens[4], "bsz") == 0)) { 6478 cmd_pipeline_port_out(tokens, n_tokens, out, out_size); 6479 return; 6480 } 6481 6482 if ((n_tokens >= 4) && 6483 (strcmp(tokens[2], "table") == 0) && 6484 (strcmp(tokens[3], "match") == 0)) { 6485 cmd_pipeline_table(tokens, n_tokens, out, out_size); 6486 return; 6487 } 6488 6489 if ((n_tokens >= 6) && 6490 (strcmp(tokens[2], "port") == 0) && 6491 (strcmp(tokens[3], "in") == 0) && 6492 (strcmp(tokens[5], "table") == 0)) { 6493 cmd_pipeline_port_in_table(tokens, n_tokens, 6494 out, out_size); 6495 return; 6496 } 6497 6498 if ((n_tokens >= 6) && 6499 (strcmp(tokens[2], "port") == 0) && 6500 (strcmp(tokens[3], "in") == 0) && 6501 (strcmp(tokens[5], "stats") == 0)) { 6502 cmd_pipeline_port_in_stats(tokens, n_tokens, 6503 out, out_size); 6504 return; 6505 } 6506 6507 if ((n_tokens >= 6) && 6508 (strcmp(tokens[2], "port") == 0) && 6509 (strcmp(tokens[3], "in") == 0) && 6510 (strcmp(tokens[5], "enable") == 0)) { 6511 cmd_pipeline_port_in_enable(tokens, n_tokens, 6512 out, out_size); 6513 return; 6514 } 6515 6516 if ((n_tokens >= 6) && 6517 (strcmp(tokens[2], "port") == 0) && 6518 (strcmp(tokens[3], "in") == 0) && 6519 (strcmp(tokens[5], "disable") == 0)) { 6520 cmd_pipeline_port_in_disable(tokens, n_tokens, 6521 out, out_size); 6522 return; 6523 } 6524 6525 if ((n_tokens >= 6) && 6526 (strcmp(tokens[2], "port") == 0) && 6527 (strcmp(tokens[3], "out") == 0) && 6528 (strcmp(tokens[5], "stats") == 0)) { 6529 cmd_pipeline_port_out_stats(tokens, n_tokens, 6530 out, out_size); 6531 return; 6532 } 6533 6534 if ((n_tokens >= 5) && 6535 (strcmp(tokens[2], "table") == 0) && 6536 (strcmp(tokens[4], "stats") == 0)) { 6537 cmd_pipeline_table_stats(tokens, n_tokens, 6538 out, out_size); 6539 return; 6540 } 6541 6542 if ((n_tokens >= 7) && 6543 (strcmp(tokens[2], "table") == 0) && 6544 (strcmp(tokens[4], "rule") == 0) && 6545 (strcmp(tokens[5], "add") == 0) && 6546 (strcmp(tokens[6], "match") == 0)) { 6547 if ((n_tokens >= 8) && 6548 (strcmp(tokens[7], "default") == 0)) { 6549 cmd_pipeline_table_rule_add_default(tokens, 6550 n_tokens, out, out_size); 6551 return; 6552 } 6553 6554 cmd_pipeline_table_rule_add(tokens, n_tokens, 6555 out, out_size); 6556 return; 6557 } 6558 6559 if ((n_tokens >= 7) && 6560 (strcmp(tokens[2], "table") == 0) && 6561 (strcmp(tokens[4], "rule") == 0) && 6562 (strcmp(tokens[5], "add") == 0) && 6563 (strcmp(tokens[6], "bulk") == 0)) { 6564 cmd_pipeline_table_rule_add_bulk(tokens, 6565 n_tokens, out, out_size); 6566 return; 6567 } 6568 6569 if ((n_tokens >= 7) && 6570 (strcmp(tokens[2], "table") == 0) && 6571 (strcmp(tokens[4], "rule") == 0) && 6572 (strcmp(tokens[5], "delete") == 0) && 6573 (strcmp(tokens[6], "match") == 0)) { 6574 if ((n_tokens >= 8) && 6575 (strcmp(tokens[7], "default") == 0)) { 6576 cmd_pipeline_table_rule_delete_default(tokens, 6577 n_tokens, out, out_size); 6578 return; 6579 } 6580 6581 cmd_pipeline_table_rule_delete(tokens, n_tokens, 6582 out, out_size); 6583 return; 6584 } 6585 6586 if ((n_tokens >= 6) && 6587 (strcmp(tokens[2], "table") == 0) && 6588 (strcmp(tokens[4], "rule") == 0) && 6589 (strcmp(tokens[5], "show") == 0)) { 6590 cmd_pipeline_table_rule_show(tokens, n_tokens, 6591 out, out_size); 6592 return; 6593 } 6594 6595 if ((n_tokens >= 7) && 6596 (strcmp(tokens[2], "table") == 0) && 6597 (strcmp(tokens[4], "rule") == 0) && 6598 (strcmp(tokens[5], "read") == 0) && 6599 (strcmp(tokens[6], "stats") == 0)) { 6600 cmd_pipeline_table_rule_stats_read(tokens, n_tokens, 6601 out, out_size); 6602 return; 6603 } 6604 6605 if ((n_tokens >= 8) && 6606 (strcmp(tokens[2], "table") == 0) && 6607 (strcmp(tokens[4], "meter") == 0) && 6608 (strcmp(tokens[5], "profile") == 0) && 6609 (strcmp(tokens[7], "add") == 0)) { 6610 cmd_pipeline_table_meter_profile_add(tokens, n_tokens, 6611 out, out_size); 6612 return; 6613 } 6614 6615 if ((n_tokens >= 8) && 6616 (strcmp(tokens[2], "table") == 0) && 6617 (strcmp(tokens[4], "meter") == 0) && 6618 (strcmp(tokens[5], "profile") == 0) && 6619 (strcmp(tokens[7], "delete") == 0)) { 6620 cmd_pipeline_table_meter_profile_delete(tokens, 6621 n_tokens, out, out_size); 6622 return; 6623 } 6624 6625 if ((n_tokens >= 7) && 6626 (strcmp(tokens[2], "table") == 0) && 6627 (strcmp(tokens[4], "rule") == 0) && 6628 (strcmp(tokens[5], "read") == 0) && 6629 (strcmp(tokens[6], "meter") == 0)) { 6630 cmd_pipeline_table_rule_meter_read(tokens, n_tokens, 6631 out, out_size); 6632 return; 6633 } 6634 6635 if ((n_tokens >= 5) && 6636 (strcmp(tokens[2], "table") == 0) && 6637 (strcmp(tokens[4], "dscp") == 0)) { 6638 cmd_pipeline_table_dscp(tokens, n_tokens, 6639 out, out_size); 6640 return; 6641 } 6642 6643 if ((n_tokens >= 7) && 6644 (strcmp(tokens[2], "table") == 0) && 6645 (strcmp(tokens[4], "rule") == 0) && 6646 (strcmp(tokens[5], "read") == 0) && 6647 (strcmp(tokens[6], "ttl") == 0)) { 6648 cmd_pipeline_table_rule_ttl_read(tokens, n_tokens, 6649 out, out_size); 6650 return; 6651 } 6652 6653 if ((n_tokens >= 7) && 6654 (strcmp(tokens[2], "table") == 0) && 6655 (strcmp(tokens[4], "rule") == 0) && 6656 (strcmp(tokens[5], "read") == 0) && 6657 (strcmp(tokens[6], "time") == 0)) { 6658 cmd_pipeline_table_rule_time_read(tokens, n_tokens, 6659 out, out_size); 6660 return; 6661 } 6662 } 6663 6664 if (strcmp(tokens[0], "thread") == 0) { 6665 if ((n_tokens >= 5) && 6666 (strcmp(tokens[4], "enable") == 0)) { 6667 cmd_thread_pipeline_enable(tokens, n_tokens, 6668 out, out_size); 6669 return; 6670 } 6671 6672 if ((n_tokens >= 5) && 6673 (strcmp(tokens[4], "disable") == 0)) { 6674 cmd_thread_pipeline_disable(tokens, n_tokens, 6675 out, out_size); 6676 return; 6677 } 6678 } 6679 6680 snprintf(out, out_size, MSG_CMD_UNKNOWN, tokens[0]); 6681 } 6682 6683 int 6684 cli_script_process(const char *file_name, 6685 size_t msg_in_len_max, 6686 size_t msg_out_len_max) 6687 { 6688 char *msg_in = NULL, *msg_out = NULL; 6689 FILE *f = NULL; 6690 6691 /* Check input arguments */ 6692 if ((file_name == NULL) || 6693 (strlen(file_name) == 0) || 6694 (msg_in_len_max == 0) || 6695 (msg_out_len_max == 0)) 6696 return -EINVAL; 6697 6698 msg_in = malloc(msg_in_len_max + 1); 6699 msg_out = malloc(msg_out_len_max + 1); 6700 if ((msg_in == NULL) || 6701 (msg_out == NULL)) { 6702 free(msg_out); 6703 free(msg_in); 6704 return -ENOMEM; 6705 } 6706 6707 /* Open input file */ 6708 f = fopen(file_name, "r"); 6709 if (f == NULL) { 6710 free(msg_out); 6711 free(msg_in); 6712 return -EIO; 6713 } 6714 6715 /* Read file */ 6716 for ( ; ; ) { 6717 if (fgets(msg_in, msg_in_len_max + 1, f) == NULL) 6718 break; 6719 6720 printf("%s", msg_in); 6721 msg_out[0] = 0; 6722 6723 cli_process(msg_in, 6724 msg_out, 6725 msg_out_len_max); 6726 6727 if (strlen(msg_out)) 6728 printf("%s", msg_out); 6729 } 6730 6731 /* Close file */ 6732 fclose(f); 6733 free(msg_out); 6734 free(msg_in); 6735 return 0; 6736 } 6737 6738 static int 6739 cli_rule_file_process(const char *file_name, 6740 size_t line_len_max, 6741 struct table_rule_list **rule_list, 6742 uint32_t *n_rules, 6743 uint32_t *line_number, 6744 char *out, 6745 size_t out_size) 6746 { 6747 struct table_rule_list *list = NULL; 6748 char *line = NULL; 6749 FILE *f = NULL; 6750 uint32_t rule_id = 0, line_id = 0; 6751 int status = 0; 6752 6753 /* Check input arguments */ 6754 if ((file_name == NULL) || 6755 (strlen(file_name) == 0) || 6756 (line_len_max == 0) || 6757 (rule_list == NULL) || 6758 (n_rules == NULL) || 6759 (line_number == NULL) || 6760 (out == NULL)) { 6761 status = -EINVAL; 6762 goto cli_rule_file_process_free; 6763 } 6764 6765 /* Memory allocation */ 6766 list = malloc(sizeof(struct table_rule_list)); 6767 if (list == NULL) { 6768 status = -ENOMEM; 6769 goto cli_rule_file_process_free; 6770 } 6771 6772 TAILQ_INIT(list); 6773 6774 line = malloc(line_len_max + 1); 6775 if (line == NULL) { 6776 status = -ENOMEM; 6777 goto cli_rule_file_process_free; 6778 } 6779 6780 /* Open file */ 6781 f = fopen(file_name, "r"); 6782 if (f == NULL) { 6783 status = -EIO; 6784 goto cli_rule_file_process_free; 6785 } 6786 6787 /* Read file */ 6788 for (line_id = 1, rule_id = 0; ; line_id++) { 6789 char *tokens[CMD_MAX_TOKENS]; 6790 struct table_rule *rule = NULL; 6791 uint32_t n_tokens, n_tokens_parsed, t0; 6792 6793 /* Read next line from file. */ 6794 if (fgets(line, line_len_max + 1, f) == NULL) 6795 break; 6796 6797 /* Comment. */ 6798 if (is_comment(line)) 6799 continue; 6800 6801 /* Parse line. */ 6802 n_tokens = RTE_DIM(tokens); 6803 status = parse_tokenize_string(line, tokens, &n_tokens); 6804 if (status) { 6805 status = -EINVAL; 6806 goto cli_rule_file_process_free; 6807 } 6808 6809 /* Empty line. */ 6810 if (n_tokens == 0) 6811 continue; 6812 t0 = 0; 6813 6814 /* Rule alloc and insert. */ 6815 rule = calloc(1, sizeof(struct table_rule)); 6816 if (rule == NULL) { 6817 status = -ENOMEM; 6818 goto cli_rule_file_process_free; 6819 } 6820 6821 TAILQ_INSERT_TAIL(list, rule, node); 6822 6823 /* Rule match. */ 6824 n_tokens_parsed = parse_match(tokens + t0, 6825 n_tokens - t0, 6826 out, 6827 out_size, 6828 &rule->match); 6829 if (n_tokens_parsed == 0) { 6830 status = -EINVAL; 6831 goto cli_rule_file_process_free; 6832 } 6833 t0 += n_tokens_parsed; 6834 6835 /* Rule action. */ 6836 n_tokens_parsed = parse_table_action(tokens + t0, 6837 n_tokens - t0, 6838 out, 6839 out_size, 6840 &rule->action); 6841 if (n_tokens_parsed == 0) { 6842 status = -EINVAL; 6843 goto cli_rule_file_process_free; 6844 } 6845 t0 += n_tokens_parsed; 6846 6847 /* Line completed. */ 6848 if (t0 < n_tokens) { 6849 status = -EINVAL; 6850 goto cli_rule_file_process_free; 6851 } 6852 6853 /* Increment rule count */ 6854 rule_id++; 6855 } 6856 6857 /* Close file */ 6858 fclose(f); 6859 6860 /* Memory free */ 6861 free(line); 6862 6863 *rule_list = list; 6864 *n_rules = rule_id; 6865 *line_number = line_id; 6866 return 0; 6867 6868 cli_rule_file_process_free: 6869 if (rule_list != NULL) 6870 *rule_list = NULL; 6871 6872 if (n_rules != NULL) 6873 *n_rules = rule_id; 6874 6875 if (line_number != NULL) 6876 *line_number = line_id; 6877 6878 if (list != NULL) 6879 for ( ; ; ) { 6880 struct table_rule *rule; 6881 6882 rule = TAILQ_FIRST(list); 6883 if (rule == NULL) 6884 break; 6885 6886 TAILQ_REMOVE(list, rule, node); 6887 free(rule); 6888 } 6889 6890 if (f) 6891 fclose(f); 6892 free(line); 6893 free(list); 6894 6895 return status; 6896 } 6897