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