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