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