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