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