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