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