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