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