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