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 #include "kni.h" 16 #include "link.h" 17 #include "mempool.h" 18 #include "parser.h" 19 #include "pipeline.h" 20 #include "swq.h" 21 #include "tap.h" 22 #include "thread.h" 23 #include "tmgr.h" 24 25 #ifndef CMD_MAX_TOKENS 26 #define CMD_MAX_TOKENS 256 27 #endif 28 29 #define MSG_OUT_OF_MEMORY "Not enough memory.\n" 30 #define MSG_CMD_UNKNOWN "Unknown command \"%s\".\n" 31 #define MSG_CMD_UNIMPLEM "Command \"%s\" not implemented.\n" 32 #define MSG_ARG_NOT_ENOUGH "Not enough arguments for command \"%s\".\n" 33 #define MSG_ARG_TOO_MANY "Too many arguments for command \"%s\".\n" 34 #define MSG_ARG_MISMATCH "Wrong number of arguments for command \"%s\".\n" 35 #define MSG_ARG_NOT_FOUND "Argument \"%s\" not found.\n" 36 #define MSG_ARG_INVALID "Invalid value for argument \"%s\".\n" 37 #define MSG_FILE_ERR "Error in file \"%s\" at line %u.\n" 38 #define MSG_FILE_NOT_ENOUGH "Not enough rules in file \"%s\".\n" 39 #define MSG_CMD_FAIL "Command \"%s\" failed.\n" 40 41 static int 42 is_comment(char *in) 43 { 44 if ((strlen(in) && index("!#%;", in[0])) || 45 (strncmp(in, "//", 2) == 0) || 46 (strncmp(in, "--", 2) == 0)) 47 return 1; 48 49 return 0; 50 } 51 52 static const char cmd_mempool_help[] = 53 "mempool <mempool_name>\n" 54 " buffer <buffer_size>\n" 55 " pool <pool_size>\n" 56 " cache <cache_size>\n" 57 " cpu <cpu_id>\n"; 58 59 static void 60 cmd_mempool(char **tokens, 61 uint32_t n_tokens, 62 char *out, 63 size_t out_size) 64 { 65 struct mempool_params p; 66 char *name; 67 struct mempool *mempool; 68 69 if (n_tokens != 10) { 70 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 71 return; 72 } 73 74 name = tokens[1]; 75 76 if (strcmp(tokens[2], "buffer") != 0) { 77 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "buffer"); 78 return; 79 } 80 81 if (parser_read_uint32(&p.buffer_size, tokens[3]) != 0) { 82 snprintf(out, out_size, MSG_ARG_INVALID, "buffer_size"); 83 return; 84 } 85 86 if (strcmp(tokens[4], "pool") != 0) { 87 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pool"); 88 return; 89 } 90 91 if (parser_read_uint32(&p.pool_size, tokens[5]) != 0) { 92 snprintf(out, out_size, MSG_ARG_INVALID, "pool_size"); 93 return; 94 } 95 96 if (strcmp(tokens[6], "cache") != 0) { 97 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "cache"); 98 return; 99 } 100 101 if (parser_read_uint32(&p.cache_size, tokens[7]) != 0) { 102 snprintf(out, out_size, MSG_ARG_INVALID, "cache_size"); 103 return; 104 } 105 106 if (strcmp(tokens[8], "cpu") != 0) { 107 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "cpu"); 108 return; 109 } 110 111 if (parser_read_uint32(&p.cpu_id, tokens[9]) != 0) { 112 snprintf(out, out_size, MSG_ARG_INVALID, "cpu_id"); 113 return; 114 } 115 116 mempool = mempool_create(name, &p); 117 if (mempool == NULL) { 118 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 119 return; 120 } 121 } 122 123 static const char cmd_link_help[] = 124 "link <link_name>\n" 125 " dev <device_name> | port <port_id>\n" 126 " rxq <n_queues> <queue_size> <mempool_name>\n" 127 " txq <n_queues> <queue_size>\n" 128 " promiscuous on | off\n" 129 " [rss <qid_0> ... <qid_n>]\n"; 130 131 static void 132 cmd_link(char **tokens, 133 uint32_t n_tokens, 134 char *out, 135 size_t out_size) 136 { 137 struct link_params p; 138 struct link_params_rss rss; 139 struct link *link; 140 char *name; 141 142 memset(&p, 0, sizeof(p)); 143 144 if ((n_tokens < 13) || (n_tokens > 14 + LINK_RXQ_RSS_MAX)) { 145 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 146 return; 147 } 148 name = tokens[1]; 149 150 if (strcmp(tokens[2], "dev") == 0) 151 p.dev_name = tokens[3]; 152 else if (strcmp(tokens[2], "port") == 0) { 153 p.dev_name = NULL; 154 155 if (parser_read_uint16(&p.port_id, tokens[3]) != 0) { 156 snprintf(out, out_size, MSG_ARG_INVALID, "port_id"); 157 return; 158 } 159 } else { 160 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "dev or port"); 161 return; 162 } 163 164 if (strcmp(tokens[4], "rxq") != 0) { 165 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rxq"); 166 return; 167 } 168 169 if (parser_read_uint32(&p.rx.n_queues, tokens[5]) != 0) { 170 snprintf(out, out_size, MSG_ARG_INVALID, "n_queues"); 171 return; 172 } 173 if (parser_read_uint32(&p.rx.queue_size, tokens[6]) != 0) { 174 snprintf(out, out_size, MSG_ARG_INVALID, "queue_size"); 175 return; 176 } 177 178 p.rx.mempool_name = tokens[7]; 179 180 if (strcmp(tokens[8], "txq") != 0) { 181 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "txq"); 182 return; 183 } 184 185 if (parser_read_uint32(&p.tx.n_queues, tokens[9]) != 0) { 186 snprintf(out, out_size, MSG_ARG_INVALID, "n_queues"); 187 return; 188 } 189 190 if (parser_read_uint32(&p.tx.queue_size, tokens[10]) != 0) { 191 snprintf(out, out_size, MSG_ARG_INVALID, "queue_size"); 192 return; 193 } 194 195 if (strcmp(tokens[11], "promiscuous") != 0) { 196 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "promiscuous"); 197 return; 198 } 199 200 if (strcmp(tokens[12], "on") == 0) 201 p.promiscuous = 1; 202 else if (strcmp(tokens[12], "off") == 0) 203 p.promiscuous = 0; 204 else { 205 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "on or off"); 206 return; 207 } 208 209 /* RSS */ 210 p.rx.rss = NULL; 211 if (n_tokens > 13) { 212 uint32_t queue_id, i; 213 214 if (strcmp(tokens[13], "rss") != 0) { 215 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rss"); 216 return; 217 } 218 219 p.rx.rss = &rss; 220 221 rss.n_queues = 0; 222 for (i = 14; i < n_tokens; i++) { 223 if (parser_read_uint32(&queue_id, tokens[i]) != 0) { 224 snprintf(out, out_size, MSG_ARG_INVALID, 225 "queue_id"); 226 return; 227 } 228 229 rss.queue_id[rss.n_queues] = queue_id; 230 rss.n_queues++; 231 } 232 } 233 234 link = link_create(name, &p); 235 if (link == NULL) { 236 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 237 return; 238 } 239 } 240 241 /* Print the link stats and info */ 242 static void 243 print_link_info(struct link *link, char *out, size_t out_size) 244 { 245 struct rte_eth_stats stats; 246 struct ether_addr mac_addr; 247 struct rte_eth_link eth_link; 248 uint16_t mtu; 249 250 memset(&stats, 0, sizeof(stats)); 251 rte_eth_stats_get(link->port_id, &stats); 252 253 rte_eth_macaddr_get(link->port_id, &mac_addr); 254 rte_eth_link_get(link->port_id, ð_link); 255 rte_eth_dev_get_mtu(link->port_id, &mtu); 256 257 snprintf(out, out_size, 258 "\n" 259 "%s: flags=<%s> mtu %u\n" 260 "\tether %02X:%02X:%02X:%02X:%02X:%02X rxqueues %u txqueues %u\n" 261 "\tport# %u speed %u Mbps\n" 262 "\tRX packets %" PRIu64" bytes %" PRIu64"\n" 263 "\tRX errors %" PRIu64" missed %" PRIu64" no-mbuf %" PRIu64"\n" 264 "\tTX packets %" PRIu64" bytes %" PRIu64"\n" 265 "\tTX errors %" PRIu64"\n", 266 link->name, 267 eth_link.link_status == 0 ? "DOWN" : "UP", 268 mtu, 269 mac_addr.addr_bytes[0], mac_addr.addr_bytes[1], 270 mac_addr.addr_bytes[2], mac_addr.addr_bytes[3], 271 mac_addr.addr_bytes[4], mac_addr.addr_bytes[5], 272 link->n_rxq, 273 link->n_txq, 274 link->port_id, 275 eth_link.link_speed, 276 stats.ipackets, 277 stats.ibytes, 278 stats.ierrors, 279 stats.imissed, 280 stats.rx_nombuf, 281 stats.opackets, 282 stats.obytes, 283 stats.oerrors); 284 } 285 286 /* 287 * link show [<link_name>] 288 */ 289 static void 290 cmd_link_show(char **tokens, uint32_t n_tokens, char *out, size_t out_size) 291 { 292 struct link *link; 293 char *link_name; 294 295 if (n_tokens != 2 && n_tokens != 3) { 296 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 297 return; 298 } 299 300 if (n_tokens == 2) { 301 link = link_next(NULL); 302 303 while (link != NULL) { 304 out_size = out_size - strlen(out); 305 out = &out[strlen(out)]; 306 307 print_link_info(link, out, out_size); 308 link = link_next(link); 309 } 310 } else { 311 out_size = out_size - strlen(out); 312 out = &out[strlen(out)]; 313 314 link_name = tokens[2]; 315 link = link_find(link_name); 316 317 if (link == NULL) { 318 snprintf(out, out_size, MSG_ARG_INVALID, 319 "Link does not exist"); 320 return; 321 } 322 print_link_info(link, out, out_size); 323 } 324 } 325 326 static const char cmd_swq_help[] = 327 "swq <swq_name>\n" 328 " size <size>\n" 329 " cpu <cpu_id>\n"; 330 331 static void 332 cmd_swq(char **tokens, 333 uint32_t n_tokens, 334 char *out, 335 size_t out_size) 336 { 337 struct swq_params p; 338 char *name; 339 struct swq *swq; 340 341 if (n_tokens != 6) { 342 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 343 return; 344 } 345 346 name = tokens[1]; 347 348 if (strcmp(tokens[2], "size") != 0) { 349 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "size"); 350 return; 351 } 352 353 if (parser_read_uint32(&p.size, tokens[3]) != 0) { 354 snprintf(out, out_size, MSG_ARG_INVALID, "size"); 355 return; 356 } 357 358 if (strcmp(tokens[4], "cpu") != 0) { 359 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "cpu"); 360 return; 361 } 362 363 if (parser_read_uint32(&p.cpu_id, tokens[5]) != 0) { 364 snprintf(out, out_size, MSG_ARG_INVALID, "cpu_id"); 365 return; 366 } 367 368 swq = swq_create(name, &p); 369 if (swq == NULL) { 370 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 371 return; 372 } 373 } 374 375 static const char cmd_tmgr_subport_profile_help[] = 376 "tmgr subport profile\n" 377 " <tb_rate> <tb_size>\n" 378 " <tc0_rate> <tc1_rate> <tc2_rate> <tc3_rate>\n" 379 " <tc_period>\n"; 380 381 static void 382 cmd_tmgr_subport_profile(char **tokens, 383 uint32_t n_tokens, 384 char *out, 385 size_t out_size) 386 { 387 struct rte_sched_subport_params p; 388 int status, i; 389 390 if (n_tokens != 10) { 391 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 392 return; 393 } 394 395 if (parser_read_uint32(&p.tb_rate, tokens[3]) != 0) { 396 snprintf(out, out_size, MSG_ARG_INVALID, "tb_rate"); 397 return; 398 } 399 400 if (parser_read_uint32(&p.tb_size, tokens[4]) != 0) { 401 snprintf(out, out_size, MSG_ARG_INVALID, "tb_size"); 402 return; 403 } 404 405 for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) 406 if (parser_read_uint32(&p.tc_rate[i], tokens[5 + i]) != 0) { 407 snprintf(out, out_size, MSG_ARG_INVALID, "tc_rate"); 408 return; 409 } 410 411 if (parser_read_uint32(&p.tc_period, tokens[9]) != 0) { 412 snprintf(out, out_size, MSG_ARG_INVALID, "tc_period"); 413 return; 414 } 415 416 status = tmgr_subport_profile_add(&p); 417 if (status != 0) { 418 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 419 return; 420 } 421 } 422 423 static const char cmd_tmgr_pipe_profile_help[] = 424 "tmgr pipe profile\n" 425 " <tb_rate> <tb_size>\n" 426 " <tc0_rate> <tc1_rate> <tc2_rate> <tc3_rate>\n" 427 " <tc_period>\n" 428 " <tc_ov_weight>\n" 429 " <wrr_weight0..15>\n"; 430 431 static void 432 cmd_tmgr_pipe_profile(char **tokens, 433 uint32_t n_tokens, 434 char *out, 435 size_t out_size) 436 { 437 struct rte_sched_pipe_params p; 438 int status, i; 439 440 if (n_tokens != 27) { 441 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 442 return; 443 } 444 445 if (parser_read_uint32(&p.tb_rate, tokens[3]) != 0) { 446 snprintf(out, out_size, MSG_ARG_INVALID, "tb_rate"); 447 return; 448 } 449 450 if (parser_read_uint32(&p.tb_size, tokens[4]) != 0) { 451 snprintf(out, out_size, MSG_ARG_INVALID, "tb_size"); 452 return; 453 } 454 455 for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) 456 if (parser_read_uint32(&p.tc_rate[i], tokens[5 + i]) != 0) { 457 snprintf(out, out_size, MSG_ARG_INVALID, "tc_rate"); 458 return; 459 } 460 461 if (parser_read_uint32(&p.tc_period, tokens[9]) != 0) { 462 snprintf(out, out_size, MSG_ARG_INVALID, "tc_period"); 463 return; 464 } 465 466 #ifdef RTE_SCHED_SUBPORT_TC_OV 467 if (parser_read_uint8(&p.tc_ov_weight, tokens[10]) != 0) { 468 snprintf(out, out_size, MSG_ARG_INVALID, "tc_ov_weight"); 469 return; 470 } 471 #endif 472 473 for (i = 0; i < RTE_SCHED_QUEUES_PER_PIPE; i++) 474 if (parser_read_uint8(&p.wrr_weights[i], tokens[11 + i]) != 0) { 475 snprintf(out, out_size, MSG_ARG_INVALID, "wrr_weights"); 476 return; 477 } 478 479 status = tmgr_pipe_profile_add(&p); 480 if (status != 0) { 481 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 482 return; 483 } 484 } 485 486 static const char cmd_tmgr_help[] = 487 "tmgr <tmgr_name>\n" 488 " rate <rate>\n" 489 " spp <n_subports_per_port>\n" 490 " pps <n_pipes_per_subport>\n" 491 " qsize <qsize_tc0> <qsize_tc1> <qsize_tc2> <qsize_tc3>\n" 492 " fo <frame_overhead>\n" 493 " mtu <mtu>\n" 494 " cpu <cpu_id>\n"; 495 496 static void 497 cmd_tmgr(char **tokens, 498 uint32_t n_tokens, 499 char *out, 500 size_t out_size) 501 { 502 struct tmgr_port_params p; 503 char *name; 504 struct tmgr_port *tmgr_port; 505 int i; 506 507 if (n_tokens != 19) { 508 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 509 return; 510 } 511 512 name = tokens[1]; 513 514 if (strcmp(tokens[2], "rate") != 0) { 515 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rate"); 516 return; 517 } 518 519 if (parser_read_uint32(&p.rate, tokens[3]) != 0) { 520 snprintf(out, out_size, MSG_ARG_INVALID, "rate"); 521 return; 522 } 523 524 if (strcmp(tokens[4], "spp") != 0) { 525 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "spp"); 526 return; 527 } 528 529 if (parser_read_uint32(&p.n_subports_per_port, tokens[5]) != 0) { 530 snprintf(out, out_size, MSG_ARG_INVALID, "n_subports_per_port"); 531 return; 532 } 533 534 if (strcmp(tokens[6], "pps") != 0) { 535 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pps"); 536 return; 537 } 538 539 if (parser_read_uint32(&p.n_pipes_per_subport, tokens[7]) != 0) { 540 snprintf(out, out_size, MSG_ARG_INVALID, "n_pipes_per_subport"); 541 return; 542 } 543 544 if (strcmp(tokens[8], "qsize") != 0) { 545 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "qsize"); 546 return; 547 } 548 549 for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) 550 if (parser_read_uint16(&p.qsize[i], tokens[9 + i]) != 0) { 551 snprintf(out, out_size, MSG_ARG_INVALID, "qsize"); 552 return; 553 } 554 555 if (strcmp(tokens[13], "fo") != 0) { 556 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "fo"); 557 return; 558 } 559 560 if (parser_read_uint32(&p.frame_overhead, tokens[14]) != 0) { 561 snprintf(out, out_size, MSG_ARG_INVALID, "frame_overhead"); 562 return; 563 } 564 565 if (strcmp(tokens[15], "mtu") != 0) { 566 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "mtu"); 567 return; 568 } 569 570 if (parser_read_uint32(&p.mtu, tokens[16]) != 0) { 571 snprintf(out, out_size, MSG_ARG_INVALID, "mtu"); 572 return; 573 } 574 575 if (strcmp(tokens[17], "cpu") != 0) { 576 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "cpu"); 577 return; 578 } 579 580 if (parser_read_uint32(&p.cpu_id, tokens[18]) != 0) { 581 snprintf(out, out_size, MSG_ARG_INVALID, "cpu_id"); 582 return; 583 } 584 585 tmgr_port = tmgr_port_create(name, &p); 586 if (tmgr_port == NULL) { 587 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 588 return; 589 } 590 } 591 592 static const char cmd_tmgr_subport_help[] = 593 "tmgr <tmgr_name> subport <subport_id>\n" 594 " profile <subport_profile_id>\n"; 595 596 static void 597 cmd_tmgr_subport(char **tokens, 598 uint32_t n_tokens, 599 char *out, 600 size_t out_size) 601 { 602 uint32_t subport_id, subport_profile_id; 603 int status; 604 char *name; 605 606 if (n_tokens != 6) { 607 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 608 return; 609 } 610 611 name = tokens[1]; 612 613 if (parser_read_uint32(&subport_id, tokens[3]) != 0) { 614 snprintf(out, out_size, MSG_ARG_INVALID, "subport_id"); 615 return; 616 } 617 618 if (parser_read_uint32(&subport_profile_id, tokens[5]) != 0) { 619 snprintf(out, out_size, MSG_ARG_INVALID, "subport_profile_id"); 620 return; 621 } 622 623 status = tmgr_subport_config(name, subport_id, subport_profile_id); 624 if (status) { 625 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 626 return; 627 } 628 } 629 630 631 static const char cmd_tmgr_subport_pipe_help[] = 632 "tmgr <tmgr_name> subport <subport_id> pipe\n" 633 " from <pipe_id_first> to <pipe_id_last>\n" 634 " profile <pipe_profile_id>\n"; 635 636 static void 637 cmd_tmgr_subport_pipe(char **tokens, 638 uint32_t n_tokens, 639 char *out, 640 size_t out_size) 641 { 642 uint32_t subport_id, pipe_id_first, pipe_id_last, pipe_profile_id; 643 int status; 644 char *name; 645 646 if (n_tokens != 11) { 647 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 648 return; 649 } 650 651 name = tokens[1]; 652 653 if (parser_read_uint32(&subport_id, tokens[3]) != 0) { 654 snprintf(out, out_size, MSG_ARG_INVALID, "subport_id"); 655 return; 656 } 657 658 if (strcmp(tokens[4], "pipe") != 0) { 659 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pipe"); 660 return; 661 } 662 663 if (strcmp(tokens[5], "from") != 0) { 664 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "from"); 665 return; 666 } 667 668 if (parser_read_uint32(&pipe_id_first, tokens[6]) != 0) { 669 snprintf(out, out_size, MSG_ARG_INVALID, "pipe_id_first"); 670 return; 671 } 672 673 if (strcmp(tokens[7], "to") != 0) { 674 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "to"); 675 return; 676 } 677 678 if (parser_read_uint32(&pipe_id_last, tokens[8]) != 0) { 679 snprintf(out, out_size, MSG_ARG_INVALID, "pipe_id_last"); 680 return; 681 } 682 683 if (strcmp(tokens[9], "profile") != 0) { 684 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "profile"); 685 return; 686 } 687 688 if (parser_read_uint32(&pipe_profile_id, tokens[10]) != 0) { 689 snprintf(out, out_size, MSG_ARG_INVALID, "pipe_profile_id"); 690 return; 691 } 692 693 status = tmgr_pipe_config(name, subport_id, pipe_id_first, 694 pipe_id_last, pipe_profile_id); 695 if (status) { 696 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 697 return; 698 } 699 } 700 701 702 static const char cmd_tap_help[] = 703 "tap <tap_name>\n"; 704 705 static void 706 cmd_tap(char **tokens, 707 uint32_t n_tokens, 708 char *out, 709 size_t out_size) 710 { 711 char *name; 712 struct tap *tap; 713 714 if (n_tokens != 2) { 715 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 716 return; 717 } 718 719 name = tokens[1]; 720 721 tap = tap_create(name); 722 if (tap == NULL) { 723 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 724 return; 725 } 726 } 727 728 static const char cmd_kni_help[] = 729 "kni <kni_name>\n" 730 " link <link_name>\n" 731 " mempool <mempool_name>\n" 732 " [thread <thread_id>]\n"; 733 734 static void 735 cmd_kni(char **tokens, 736 uint32_t n_tokens, 737 char *out, 738 size_t out_size) 739 { 740 struct kni_params p; 741 char *name; 742 struct kni *kni; 743 744 memset(&p, 0, sizeof(p)); 745 if ((n_tokens != 6) && (n_tokens != 8)) { 746 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 747 return; 748 } 749 750 name = tokens[1]; 751 752 if (strcmp(tokens[2], "link") != 0) { 753 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "link"); 754 return; 755 } 756 757 p.link_name = tokens[3]; 758 759 if (strcmp(tokens[4], "mempool") != 0) { 760 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "mempool"); 761 return; 762 } 763 764 p.mempool_name = tokens[5]; 765 766 if (n_tokens == 8) { 767 if (strcmp(tokens[6], "thread") != 0) { 768 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "thread"); 769 return; 770 } 771 772 if (parser_read_uint32(&p.thread_id, tokens[7]) != 0) { 773 snprintf(out, out_size, MSG_ARG_INVALID, "thread_id"); 774 return; 775 } 776 777 p.force_bind = 1; 778 } else 779 p.force_bind = 0; 780 781 kni = kni_create(name, &p); 782 if (kni == NULL) { 783 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 784 return; 785 } 786 } 787 788 789 static const char cmd_port_in_action_profile_help[] = 790 "port in action profile <profile_name>\n" 791 " [filter match | mismatch offset <key_offset> mask <key_mask> key <key_value> port <port_id>]\n" 792 " [balance offset <key_offset> mask <key_mask> port <port_id0> ... <port_id15>]\n"; 793 794 static void 795 cmd_port_in_action_profile(char **tokens, 796 uint32_t n_tokens, 797 char *out, 798 size_t out_size) 799 { 800 struct port_in_action_profile_params p; 801 struct port_in_action_profile *ap; 802 char *name; 803 uint32_t t0; 804 805 memset(&p, 0, sizeof(p)); 806 807 if (n_tokens < 5) { 808 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 809 return; 810 } 811 812 if (strcmp(tokens[1], "in") != 0) { 813 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "in"); 814 return; 815 } 816 817 if (strcmp(tokens[2], "action") != 0) { 818 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "action"); 819 return; 820 } 821 822 if (strcmp(tokens[3], "profile") != 0) { 823 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "profile"); 824 return; 825 } 826 827 name = tokens[4]; 828 829 t0 = 5; 830 831 if ((t0 < n_tokens) && (strcmp(tokens[t0], "filter") == 0)) { 832 uint32_t size; 833 834 if (n_tokens < t0 + 10) { 835 snprintf(out, out_size, MSG_ARG_MISMATCH, "port in action profile filter"); 836 return; 837 } 838 839 if (strcmp(tokens[t0 + 1], "match") == 0) 840 p.fltr.filter_on_match = 1; 841 else if (strcmp(tokens[t0 + 1], "mismatch") == 0) 842 p.fltr.filter_on_match = 0; 843 else { 844 snprintf(out, out_size, MSG_ARG_INVALID, "match or mismatch"); 845 return; 846 } 847 848 if (strcmp(tokens[t0 + 2], "offset") != 0) { 849 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset"); 850 return; 851 } 852 853 if (parser_read_uint32(&p.fltr.key_offset, tokens[t0 + 3]) != 0) { 854 snprintf(out, out_size, MSG_ARG_INVALID, "key_offset"); 855 return; 856 } 857 858 if (strcmp(tokens[t0 + 4], "mask") != 0) { 859 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "mask"); 860 return; 861 } 862 863 size = RTE_PORT_IN_ACTION_FLTR_KEY_SIZE; 864 if ((parse_hex_string(tokens[t0 + 5], p.fltr.key_mask, &size) != 0) || 865 (size != RTE_PORT_IN_ACTION_FLTR_KEY_SIZE)) { 866 snprintf(out, out_size, MSG_ARG_INVALID, "key_mask"); 867 return; 868 } 869 870 if (strcmp(tokens[t0 + 6], "key") != 0) { 871 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "key"); 872 return; 873 } 874 875 size = RTE_PORT_IN_ACTION_FLTR_KEY_SIZE; 876 if ((parse_hex_string(tokens[t0 + 7], p.fltr.key, &size) != 0) || 877 (size != RTE_PORT_IN_ACTION_FLTR_KEY_SIZE)) { 878 snprintf(out, out_size, MSG_ARG_INVALID, "key_value"); 879 return; 880 } 881 882 if (strcmp(tokens[t0 + 8], "port") != 0) { 883 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port"); 884 return; 885 } 886 887 if (parser_read_uint32(&p.fltr.port_id, tokens[t0 + 9]) != 0) { 888 snprintf(out, out_size, MSG_ARG_INVALID, "port_id"); 889 return; 890 } 891 892 p.action_mask |= 1LLU << RTE_PORT_IN_ACTION_FLTR; 893 t0 += 10; 894 } /* filter */ 895 896 if ((t0 < n_tokens) && (strcmp(tokens[t0], "balance") == 0)) { 897 uint32_t i; 898 899 if (n_tokens < t0 + 22) { 900 snprintf(out, out_size, MSG_ARG_MISMATCH, 901 "port in action profile balance"); 902 return; 903 } 904 905 if (strcmp(tokens[t0 + 1], "offset") != 0) { 906 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset"); 907 return; 908 } 909 910 if (parser_read_uint32(&p.lb.key_offset, tokens[t0 + 2]) != 0) { 911 snprintf(out, out_size, MSG_ARG_INVALID, "key_offset"); 912 return; 913 } 914 915 if (strcmp(tokens[t0 + 3], "mask") != 0) { 916 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "mask"); 917 return; 918 } 919 920 p.lb.key_size = RTE_PORT_IN_ACTION_LB_KEY_SIZE_MAX; 921 if (parse_hex_string(tokens[t0 + 4], p.lb.key_mask, &p.lb.key_size) != 0) { 922 snprintf(out, out_size, MSG_ARG_INVALID, "key_mask"); 923 return; 924 } 925 926 if (strcmp(tokens[t0 + 5], "port") != 0) { 927 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port"); 928 return; 929 } 930 931 for (i = 0; i < 16; i++) 932 if (parser_read_uint32(&p.lb.port_id[i], tokens[t0 + 6 + i]) != 0) { 933 snprintf(out, out_size, MSG_ARG_INVALID, "port_id"); 934 return; 935 } 936 937 p.action_mask |= 1LLU << RTE_PORT_IN_ACTION_LB; 938 t0 += 22; 939 } /* balance */ 940 941 if (t0 < n_tokens) { 942 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 943 return; 944 } 945 946 ap = port_in_action_profile_create(name, &p); 947 if (ap == NULL) { 948 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 949 return; 950 } 951 } 952 953 954 static const char cmd_table_action_profile_help[] = 955 "table action profile <profile_name>\n" 956 " ipv4 | ipv6\n" 957 " offset <ip_offset>\n" 958 " fwd\n" 959 " [balance offset <key_offset> mask <key_mask> outoffset <out_offset>]\n" 960 " [meter srtcm | trtcm\n" 961 " tc <n_tc>\n" 962 " stats none | pkts | bytes | both]\n" 963 " [tm spp <n_subports_per_port> pps <n_pipes_per_subport>]\n" 964 " [encap ether | vlan | qinq | mpls | pppoe]\n" 965 " [nat src | dst\n" 966 " proto udp | tcp]\n" 967 " [ttl drop | fwd\n" 968 " stats none | pkts]\n" 969 " [stats pkts | bytes | both]\n" 970 " [time]\n"; 971 972 static void 973 cmd_table_action_profile(char **tokens, 974 uint32_t n_tokens, 975 char *out, 976 size_t out_size) 977 { 978 struct table_action_profile_params p; 979 struct table_action_profile *ap; 980 char *name; 981 uint32_t t0; 982 983 memset(&p, 0, sizeof(p)); 984 985 if (n_tokens < 8) { 986 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 987 return; 988 } 989 990 if (strcmp(tokens[1], "action") != 0) { 991 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "action"); 992 return; 993 } 994 995 if (strcmp(tokens[2], "profile") != 0) { 996 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "profile"); 997 return; 998 } 999 1000 name = tokens[3]; 1001 1002 if (strcmp(tokens[4], "ipv4") == 0) 1003 p.common.ip_version = 1; 1004 else if (strcmp(tokens[4], "ipv6") == 0) 1005 p.common.ip_version = 0; 1006 else { 1007 snprintf(out, out_size, MSG_ARG_INVALID, "ipv4 or ipv6"); 1008 return; 1009 } 1010 1011 if (strcmp(tokens[5], "offset") != 0) { 1012 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset"); 1013 return; 1014 } 1015 1016 if (parser_read_uint32(&p.common.ip_offset, tokens[6]) != 0) { 1017 snprintf(out, out_size, MSG_ARG_INVALID, "ip_offset"); 1018 return; 1019 } 1020 1021 if (strcmp(tokens[7], "fwd") != 0) { 1022 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "fwd"); 1023 return; 1024 } 1025 1026 p.action_mask |= 1LLU << RTE_TABLE_ACTION_FWD; 1027 1028 t0 = 8; 1029 if ((t0 < n_tokens) && (strcmp(tokens[t0], "balance") == 0)) { 1030 if (n_tokens < t0 + 7) { 1031 snprintf(out, out_size, MSG_ARG_MISMATCH, "table action profile balance"); 1032 return; 1033 } 1034 1035 if (strcmp(tokens[t0 + 1], "offset") != 0) { 1036 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset"); 1037 return; 1038 } 1039 1040 if (parser_read_uint32(&p.lb.key_offset, tokens[t0 + 2]) != 0) { 1041 snprintf(out, out_size, MSG_ARG_INVALID, "key_offset"); 1042 return; 1043 } 1044 1045 if (strcmp(tokens[t0 + 3], "mask") != 0) { 1046 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "mask"); 1047 return; 1048 } 1049 1050 p.lb.key_size = RTE_PORT_IN_ACTION_LB_KEY_SIZE_MAX; 1051 if (parse_hex_string(tokens[t0 + 4], p.lb.key_mask, &p.lb.key_size) != 0) { 1052 snprintf(out, out_size, MSG_ARG_INVALID, "key_mask"); 1053 return; 1054 } 1055 1056 if (strcmp(tokens[t0 + 5], "outoffset") != 0) { 1057 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "outoffset"); 1058 return; 1059 } 1060 1061 if (parser_read_uint32(&p.lb.out_offset, tokens[t0 + 6]) != 0) { 1062 snprintf(out, out_size, MSG_ARG_INVALID, "out_offset"); 1063 return; 1064 } 1065 1066 p.action_mask |= 1LLU << RTE_TABLE_ACTION_LB; 1067 t0 += 7; 1068 } /* balance */ 1069 1070 if ((t0 < n_tokens) && (strcmp(tokens[t0], "meter") == 0)) { 1071 if (n_tokens < t0 + 6) { 1072 snprintf(out, out_size, MSG_ARG_MISMATCH, 1073 "table action profile meter"); 1074 return; 1075 } 1076 1077 if (strcmp(tokens[t0 + 1], "srtcm") == 0) 1078 p.mtr.alg = RTE_TABLE_ACTION_METER_SRTCM; 1079 else if (strcmp(tokens[t0 + 1], "trtcm") == 0) 1080 p.mtr.alg = RTE_TABLE_ACTION_METER_TRTCM; 1081 else { 1082 snprintf(out, out_size, MSG_ARG_NOT_FOUND, 1083 "srtcm or trtcm"); 1084 return; 1085 } 1086 1087 if (strcmp(tokens[t0 + 2], "tc") != 0) { 1088 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc"); 1089 return; 1090 } 1091 1092 if (parser_read_uint32(&p.mtr.n_tc, tokens[t0 + 3]) != 0) { 1093 snprintf(out, out_size, MSG_ARG_INVALID, "n_tc"); 1094 return; 1095 } 1096 1097 if (strcmp(tokens[t0 + 4], "stats") != 0) { 1098 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "stats"); 1099 return; 1100 } 1101 1102 if (strcmp(tokens[t0 + 5], "none") == 0) { 1103 p.mtr.n_packets_enabled = 0; 1104 p.mtr.n_bytes_enabled = 0; 1105 } else if (strcmp(tokens[t0 + 5], "pkts") == 0) { 1106 p.mtr.n_packets_enabled = 1; 1107 p.mtr.n_bytes_enabled = 0; 1108 } else if (strcmp(tokens[t0 + 5], "bytes") == 0) { 1109 p.mtr.n_packets_enabled = 0; 1110 p.mtr.n_bytes_enabled = 1; 1111 } else if (strcmp(tokens[t0 + 5], "both") == 0) { 1112 p.mtr.n_packets_enabled = 1; 1113 p.mtr.n_bytes_enabled = 1; 1114 } else { 1115 snprintf(out, out_size, MSG_ARG_NOT_FOUND, 1116 "none or pkts or bytes or both"); 1117 return; 1118 } 1119 1120 p.action_mask |= 1LLU << RTE_TABLE_ACTION_MTR; 1121 t0 += 6; 1122 } /* meter */ 1123 1124 if ((t0 < n_tokens) && (strcmp(tokens[t0], "tm") == 0)) { 1125 if (n_tokens < t0 + 5) { 1126 snprintf(out, out_size, MSG_ARG_MISMATCH, 1127 "table action profile tm"); 1128 return; 1129 } 1130 1131 if (strcmp(tokens[t0 + 1], "spp") != 0) { 1132 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "spp"); 1133 return; 1134 } 1135 1136 if (parser_read_uint32(&p.tm.n_subports_per_port, 1137 tokens[t0 + 2]) != 0) { 1138 snprintf(out, out_size, MSG_ARG_INVALID, 1139 "n_subports_per_port"); 1140 return; 1141 } 1142 1143 if (strcmp(tokens[t0 + 3], "pps") != 0) { 1144 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pps"); 1145 return; 1146 } 1147 1148 if (parser_read_uint32(&p.tm.n_pipes_per_subport, 1149 tokens[t0 + 4]) != 0) { 1150 snprintf(out, out_size, MSG_ARG_INVALID, 1151 "n_pipes_per_subport"); 1152 return; 1153 } 1154 1155 p.action_mask |= 1LLU << RTE_TABLE_ACTION_TM; 1156 t0 += 5; 1157 } /* tm */ 1158 1159 if ((t0 < n_tokens) && (strcmp(tokens[t0], "encap") == 0)) { 1160 if (n_tokens < t0 + 2) { 1161 snprintf(out, out_size, MSG_ARG_MISMATCH, 1162 "action profile encap"); 1163 return; 1164 } 1165 1166 if (strcmp(tokens[t0 + 1], "ether") == 0) 1167 p.encap.encap_mask = 1LLU << RTE_TABLE_ACTION_ENCAP_ETHER; 1168 else if (strcmp(tokens[t0 + 1], "vlan") == 0) 1169 p.encap.encap_mask = 1LLU << RTE_TABLE_ACTION_ENCAP_VLAN; 1170 else if (strcmp(tokens[t0 + 1], "qinq") == 0) 1171 p.encap.encap_mask = 1LLU << RTE_TABLE_ACTION_ENCAP_QINQ; 1172 else if (strcmp(tokens[t0 + 1], "mpls") == 0) 1173 p.encap.encap_mask = 1LLU << RTE_TABLE_ACTION_ENCAP_MPLS; 1174 else if (strcmp(tokens[t0 + 1], "pppoe") == 0) 1175 p.encap.encap_mask = 1LLU << RTE_TABLE_ACTION_ENCAP_PPPOE; 1176 else { 1177 snprintf(out, out_size, MSG_ARG_MISMATCH, "encap"); 1178 return; 1179 } 1180 1181 p.action_mask |= 1LLU << RTE_TABLE_ACTION_ENCAP; 1182 t0 += 2; 1183 } /* encap */ 1184 1185 if ((t0 < n_tokens) && (strcmp(tokens[t0], "nat") == 0)) { 1186 if (n_tokens < t0 + 4) { 1187 snprintf(out, out_size, MSG_ARG_MISMATCH, 1188 "table action profile nat"); 1189 return; 1190 } 1191 1192 if (strcmp(tokens[t0 + 1], "src") == 0) 1193 p.nat.source_nat = 1; 1194 else if (strcmp(tokens[t0 + 1], "dst") == 0) 1195 p.nat.source_nat = 0; 1196 else { 1197 snprintf(out, out_size, MSG_ARG_NOT_FOUND, 1198 "src or dst"); 1199 return; 1200 } 1201 1202 if (strcmp(tokens[t0 + 2], "proto") != 0) { 1203 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "proto"); 1204 return; 1205 } 1206 1207 if (strcmp(tokens[t0 + 3], "tcp") == 0) 1208 p.nat.proto = 0x06; 1209 else if (strcmp(tokens[t0 + 3], "udp") == 0) 1210 p.nat.proto = 0x11; 1211 else { 1212 snprintf(out, out_size, MSG_ARG_NOT_FOUND, 1213 "tcp or udp"); 1214 return; 1215 } 1216 1217 p.action_mask |= 1LLU << RTE_TABLE_ACTION_NAT; 1218 t0 += 4; 1219 } /* nat */ 1220 1221 if ((t0 < n_tokens) && (strcmp(tokens[t0], "ttl") == 0)) { 1222 if (n_tokens < t0 + 4) { 1223 snprintf(out, out_size, MSG_ARG_MISMATCH, 1224 "table action profile ttl"); 1225 return; 1226 } 1227 1228 if (strcmp(tokens[t0 + 1], "drop") == 0) 1229 p.ttl.drop = 1; 1230 else if (strcmp(tokens[t0 + 1], "fwd") == 0) 1231 p.ttl.drop = 0; 1232 else { 1233 snprintf(out, out_size, MSG_ARG_NOT_FOUND, 1234 "drop or fwd"); 1235 return; 1236 } 1237 1238 if (strcmp(tokens[t0 + 2], "stats") != 0) { 1239 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "stats"); 1240 return; 1241 } 1242 1243 if (strcmp(tokens[t0 + 3], "none") == 0) 1244 p.ttl.n_packets_enabled = 0; 1245 else if (strcmp(tokens[t0 + 3], "pkts") == 0) 1246 p.ttl.n_packets_enabled = 1; 1247 else { 1248 snprintf(out, out_size, MSG_ARG_NOT_FOUND, 1249 "none or pkts"); 1250 return; 1251 } 1252 1253 p.action_mask |= 1LLU << RTE_TABLE_ACTION_TTL; 1254 t0 += 4; 1255 } /* ttl */ 1256 1257 if ((t0 < n_tokens) && (strcmp(tokens[t0], "stats") == 0)) { 1258 if (n_tokens < t0 + 2) { 1259 snprintf(out, out_size, MSG_ARG_MISMATCH, 1260 "table action profile stats"); 1261 return; 1262 } 1263 1264 if (strcmp(tokens[t0 + 1], "pkts") == 0) { 1265 p.stats.n_packets_enabled = 1; 1266 p.stats.n_bytes_enabled = 0; 1267 } else if (strcmp(tokens[t0 + 1], "bytes") == 0) { 1268 p.stats.n_packets_enabled = 0; 1269 p.stats.n_bytes_enabled = 1; 1270 } else if (strcmp(tokens[t0 + 1], "both") == 0) { 1271 p.stats.n_packets_enabled = 1; 1272 p.stats.n_bytes_enabled = 1; 1273 } else { 1274 snprintf(out, out_size, MSG_ARG_NOT_FOUND, 1275 "pkts or bytes or both"); 1276 return; 1277 } 1278 1279 p.action_mask |= 1LLU << RTE_TABLE_ACTION_STATS; 1280 t0 += 2; 1281 } /* stats */ 1282 1283 if ((t0 < n_tokens) && (strcmp(tokens[t0], "time") == 0)) { 1284 p.action_mask |= 1LLU << RTE_TABLE_ACTION_TIME; 1285 t0 += 1; 1286 } /* time */ 1287 1288 if (t0 < n_tokens) { 1289 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 1290 return; 1291 } 1292 1293 ap = table_action_profile_create(name, &p); 1294 if (ap == NULL) { 1295 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 1296 return; 1297 } 1298 } 1299 1300 static const char cmd_pipeline_help[] = 1301 "pipeline <pipeline_name>\n" 1302 " period <timer_period_ms>\n" 1303 " offset_port_id <offset_port_id>\n" 1304 " cpu <cpu_id>\n"; 1305 1306 static void 1307 cmd_pipeline(char **tokens, 1308 uint32_t n_tokens, 1309 char *out, 1310 size_t out_size) 1311 { 1312 struct pipeline_params p; 1313 char *name; 1314 struct pipeline *pipeline; 1315 1316 if (n_tokens != 8) { 1317 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 1318 return; 1319 } 1320 1321 name = tokens[1]; 1322 1323 if (strcmp(tokens[2], "period") != 0) { 1324 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "period"); 1325 return; 1326 } 1327 1328 if (parser_read_uint32(&p.timer_period_ms, tokens[3]) != 0) { 1329 snprintf(out, out_size, MSG_ARG_INVALID, "timer_period_ms"); 1330 return; 1331 } 1332 1333 if (strcmp(tokens[4], "offset_port_id") != 0) { 1334 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset_port_id"); 1335 return; 1336 } 1337 1338 if (parser_read_uint32(&p.offset_port_id, tokens[5]) != 0) { 1339 snprintf(out, out_size, MSG_ARG_INVALID, "offset_port_id"); 1340 return; 1341 } 1342 1343 if (strcmp(tokens[6], "cpu") != 0) { 1344 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "cpu"); 1345 return; 1346 } 1347 1348 if (parser_read_uint32(&p.cpu_id, tokens[7]) != 0) { 1349 snprintf(out, out_size, MSG_ARG_INVALID, "cpu_id"); 1350 return; 1351 } 1352 1353 pipeline = pipeline_create(name, &p); 1354 if (pipeline == NULL) { 1355 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 1356 return; 1357 } 1358 } 1359 1360 static const char cmd_pipeline_port_in_help[] = 1361 "pipeline <pipeline_name> port in\n" 1362 " bsz <burst_size>\n" 1363 " link <link_name> rxq <queue_id>\n" 1364 " | swq <swq_name>\n" 1365 " | tmgr <tmgr_name>\n" 1366 " | tap <tap_name> mempool <mempool_name> mtu <mtu>\n" 1367 " | kni <kni_name>\n" 1368 " | source mempool <mempool_name> file <file_name> bpp <n_bytes_per_pkt>\n" 1369 " [action <port_in_action_profile_name>]\n" 1370 " [disabled]\n"; 1371 1372 static void 1373 cmd_pipeline_port_in(char **tokens, 1374 uint32_t n_tokens, 1375 char *out, 1376 size_t out_size) 1377 { 1378 struct port_in_params p; 1379 char *pipeline_name; 1380 uint32_t t0; 1381 int enabled, status; 1382 1383 if (n_tokens < 7) { 1384 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 1385 return; 1386 } 1387 1388 pipeline_name = tokens[1]; 1389 1390 if (strcmp(tokens[2], "port") != 0) { 1391 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port"); 1392 return; 1393 } 1394 1395 if (strcmp(tokens[3], "in") != 0) { 1396 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "in"); 1397 return; 1398 } 1399 1400 if (strcmp(tokens[4], "bsz") != 0) { 1401 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "bsz"); 1402 return; 1403 } 1404 1405 if (parser_read_uint32(&p.burst_size, tokens[5]) != 0) { 1406 snprintf(out, out_size, MSG_ARG_INVALID, "burst_size"); 1407 return; 1408 } 1409 1410 t0 = 6; 1411 1412 if (strcmp(tokens[t0], "link") == 0) { 1413 if (n_tokens < t0 + 4) { 1414 snprintf(out, out_size, MSG_ARG_MISMATCH, 1415 "pipeline port in link"); 1416 return; 1417 } 1418 1419 p.type = PORT_IN_RXQ; 1420 1421 p.dev_name = tokens[t0 + 1]; 1422 1423 if (strcmp(tokens[t0 + 2], "rxq") != 0) { 1424 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rxq"); 1425 return; 1426 } 1427 1428 if (parser_read_uint16(&p.rxq.queue_id, tokens[t0 + 3]) != 0) { 1429 snprintf(out, out_size, MSG_ARG_INVALID, 1430 "queue_id"); 1431 return; 1432 } 1433 t0 += 4; 1434 } else if (strcmp(tokens[t0], "swq") == 0) { 1435 if (n_tokens < t0 + 2) { 1436 snprintf(out, out_size, MSG_ARG_MISMATCH, 1437 "pipeline port in swq"); 1438 return; 1439 } 1440 1441 p.type = PORT_IN_SWQ; 1442 1443 p.dev_name = tokens[t0 + 1]; 1444 1445 t0 += 2; 1446 } else if (strcmp(tokens[t0], "tmgr") == 0) { 1447 if (n_tokens < t0 + 2) { 1448 snprintf(out, out_size, MSG_ARG_MISMATCH, 1449 "pipeline port in tmgr"); 1450 return; 1451 } 1452 1453 p.type = PORT_IN_TMGR; 1454 1455 p.dev_name = tokens[t0 + 1]; 1456 1457 t0 += 2; 1458 } else if (strcmp(tokens[t0], "tap") == 0) { 1459 if (n_tokens < t0 + 6) { 1460 snprintf(out, out_size, MSG_ARG_MISMATCH, 1461 "pipeline port in tap"); 1462 return; 1463 } 1464 1465 p.type = PORT_IN_TAP; 1466 1467 p.dev_name = tokens[t0 + 1]; 1468 1469 if (strcmp(tokens[t0 + 2], "mempool") != 0) { 1470 snprintf(out, out_size, MSG_ARG_NOT_FOUND, 1471 "mempool"); 1472 return; 1473 } 1474 1475 p.tap.mempool_name = tokens[t0 + 3]; 1476 1477 if (strcmp(tokens[t0 + 4], "mtu") != 0) { 1478 snprintf(out, out_size, MSG_ARG_NOT_FOUND, 1479 "mtu"); 1480 return; 1481 } 1482 1483 if (parser_read_uint32(&p.tap.mtu, tokens[t0 + 5]) != 0) { 1484 snprintf(out, out_size, MSG_ARG_INVALID, "mtu"); 1485 return; 1486 } 1487 1488 t0 += 6; 1489 } else if (strcmp(tokens[t0], "kni") == 0) { 1490 if (n_tokens < t0 + 2) { 1491 snprintf(out, out_size, MSG_ARG_MISMATCH, 1492 "pipeline port in kni"); 1493 return; 1494 } 1495 1496 p.type = PORT_IN_KNI; 1497 1498 p.dev_name = tokens[t0 + 1]; 1499 1500 t0 += 2; 1501 } else if (strcmp(tokens[t0], "source") == 0) { 1502 if (n_tokens < t0 + 6) { 1503 snprintf(out, out_size, MSG_ARG_MISMATCH, 1504 "pipeline port in source"); 1505 return; 1506 } 1507 1508 p.type = PORT_IN_SOURCE; 1509 1510 p.dev_name = NULL; 1511 1512 if (strcmp(tokens[t0 + 1], "mempool") != 0) { 1513 snprintf(out, out_size, MSG_ARG_NOT_FOUND, 1514 "mempool"); 1515 return; 1516 } 1517 1518 p.source.mempool_name = tokens[t0 + 2]; 1519 1520 if (strcmp(tokens[t0 + 3], "file") != 0) { 1521 snprintf(out, out_size, MSG_ARG_NOT_FOUND, 1522 "file"); 1523 return; 1524 } 1525 1526 p.source.file_name = tokens[t0 + 4]; 1527 1528 if (strcmp(tokens[t0 + 5], "bpp") != 0) { 1529 snprintf(out, out_size, MSG_ARG_NOT_FOUND, 1530 "bpp"); 1531 return; 1532 } 1533 1534 if (parser_read_uint32(&p.source.n_bytes_per_pkt, tokens[t0 + 6]) != 0) { 1535 snprintf(out, out_size, MSG_ARG_INVALID, 1536 "n_bytes_per_pkt"); 1537 return; 1538 } 1539 1540 t0 += 7; 1541 } else { 1542 snprintf(out, out_size, MSG_ARG_INVALID, tokens[0]); 1543 return; 1544 } 1545 1546 p.action_profile_name = NULL; 1547 if ((n_tokens > t0) && (strcmp(tokens[t0], "action") == 0)) { 1548 if (n_tokens < t0 + 2) { 1549 snprintf(out, out_size, MSG_ARG_MISMATCH, "action"); 1550 return; 1551 } 1552 1553 p.action_profile_name = tokens[t0 + 1]; 1554 1555 t0 += 2; 1556 } 1557 1558 enabled = 1; 1559 if ((n_tokens > t0) && 1560 (strcmp(tokens[t0], "disabled") == 0)) { 1561 enabled = 0; 1562 1563 t0 += 1; 1564 } 1565 1566 if (n_tokens != t0) { 1567 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 1568 return; 1569 } 1570 1571 status = pipeline_port_in_create(pipeline_name, 1572 &p, enabled); 1573 if (status) { 1574 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 1575 return; 1576 } 1577 } 1578 1579 static const char cmd_pipeline_port_out_help[] = 1580 "pipeline <pipeline_name> port out\n" 1581 " bsz <burst_size>\n" 1582 " link <link_name> txq <txq_id>\n" 1583 " | swq <swq_name>\n" 1584 " | tmgr <tmgr_name>\n" 1585 " | tap <tap_name>\n" 1586 " | kni <kni_name>\n" 1587 " | sink [file <file_name> pkts <max_n_pkts>]\n"; 1588 1589 static void 1590 cmd_pipeline_port_out(char **tokens, 1591 uint32_t n_tokens, 1592 char *out, 1593 size_t out_size) 1594 { 1595 struct port_out_params p; 1596 char *pipeline_name; 1597 int status; 1598 1599 memset(&p, 0, sizeof(p)); 1600 1601 if (n_tokens < 7) { 1602 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 1603 return; 1604 } 1605 1606 pipeline_name = tokens[1]; 1607 1608 if (strcmp(tokens[2], "port") != 0) { 1609 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port"); 1610 return; 1611 } 1612 1613 if (strcmp(tokens[3], "out") != 0) { 1614 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "out"); 1615 return; 1616 } 1617 1618 if (strcmp(tokens[4], "bsz") != 0) { 1619 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "bsz"); 1620 return; 1621 } 1622 1623 if (parser_read_uint32(&p.burst_size, tokens[5]) != 0) { 1624 snprintf(out, out_size, MSG_ARG_INVALID, "burst_size"); 1625 return; 1626 } 1627 1628 if (strcmp(tokens[6], "link") == 0) { 1629 if (n_tokens != 10) { 1630 snprintf(out, out_size, MSG_ARG_MISMATCH, 1631 "pipeline port out link"); 1632 return; 1633 } 1634 1635 p.type = PORT_OUT_TXQ; 1636 1637 p.dev_name = tokens[7]; 1638 1639 if (strcmp(tokens[8], "txq") != 0) { 1640 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "txq"); 1641 return; 1642 } 1643 1644 if (parser_read_uint16(&p.txq.queue_id, tokens[9]) != 0) { 1645 snprintf(out, out_size, MSG_ARG_INVALID, "queue_id"); 1646 return; 1647 } 1648 } else if (strcmp(tokens[6], "swq") == 0) { 1649 if (n_tokens != 8) { 1650 snprintf(out, out_size, MSG_ARG_MISMATCH, 1651 "pipeline port out swq"); 1652 return; 1653 } 1654 1655 p.type = PORT_OUT_SWQ; 1656 1657 p.dev_name = tokens[7]; 1658 } else if (strcmp(tokens[6], "tmgr") == 0) { 1659 if (n_tokens != 8) { 1660 snprintf(out, out_size, MSG_ARG_MISMATCH, 1661 "pipeline port out tmgr"); 1662 return; 1663 } 1664 1665 p.type = PORT_OUT_TMGR; 1666 1667 p.dev_name = tokens[7]; 1668 } else if (strcmp(tokens[6], "tap") == 0) { 1669 if (n_tokens != 8) { 1670 snprintf(out, out_size, MSG_ARG_MISMATCH, 1671 "pipeline port out tap"); 1672 return; 1673 } 1674 1675 p.type = PORT_OUT_TAP; 1676 1677 p.dev_name = tokens[7]; 1678 } else if (strcmp(tokens[6], "kni") == 0) { 1679 if (n_tokens != 8) { 1680 snprintf(out, out_size, MSG_ARG_MISMATCH, 1681 "pipeline port out kni"); 1682 return; 1683 } 1684 1685 p.type = PORT_OUT_KNI; 1686 1687 p.dev_name = tokens[7]; 1688 } else if (strcmp(tokens[6], "sink") == 0) { 1689 if ((n_tokens != 7) && (n_tokens != 11)) { 1690 snprintf(out, out_size, MSG_ARG_MISMATCH, 1691 "pipeline port out sink"); 1692 return; 1693 } 1694 1695 p.type = PORT_OUT_SINK; 1696 1697 p.dev_name = NULL; 1698 1699 if (n_tokens == 7) { 1700 p.sink.file_name = NULL; 1701 p.sink.max_n_pkts = 0; 1702 } else { 1703 if (strcmp(tokens[7], "file") != 0) { 1704 snprintf(out, out_size, MSG_ARG_NOT_FOUND, 1705 "file"); 1706 return; 1707 } 1708 1709 p.sink.file_name = tokens[8]; 1710 1711 if (strcmp(tokens[9], "pkts") != 0) { 1712 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pkts"); 1713 return; 1714 } 1715 1716 if (parser_read_uint32(&p.sink.max_n_pkts, tokens[10]) != 0) { 1717 snprintf(out, out_size, MSG_ARG_INVALID, "max_n_pkts"); 1718 return; 1719 } 1720 } 1721 } else { 1722 snprintf(out, out_size, MSG_ARG_INVALID, tokens[0]); 1723 return; 1724 } 1725 1726 status = pipeline_port_out_create(pipeline_name, &p); 1727 if (status) { 1728 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 1729 return; 1730 } 1731 } 1732 1733 static const char cmd_pipeline_table_help[] = 1734 "pipeline <pipeline_name> table\n" 1735 " match\n" 1736 " acl\n" 1737 " ipv4 | ipv6\n" 1738 " offset <ip_header_offset>\n" 1739 " size <n_rules>\n" 1740 " | array\n" 1741 " offset <key_offset>\n" 1742 " size <n_keys>\n" 1743 " | hash\n" 1744 " ext | lru\n" 1745 " key <key_size>\n" 1746 " mask <key_mask>\n" 1747 " offset <key_offset>\n" 1748 " buckets <n_buckets>\n" 1749 " size <n_keys>\n" 1750 " | lpm\n" 1751 " ipv4 | ipv6\n" 1752 " offset <ip_header_offset>\n" 1753 " size <n_rules>\n" 1754 " | stub\n" 1755 " [action <table_action_profile_name>]\n"; 1756 1757 static void 1758 cmd_pipeline_table(char **tokens, 1759 uint32_t n_tokens, 1760 char *out, 1761 size_t out_size) 1762 { 1763 uint8_t key_mask[TABLE_RULE_MATCH_SIZE_MAX]; 1764 struct table_params p; 1765 char *pipeline_name; 1766 uint32_t t0; 1767 int status; 1768 1769 if (n_tokens < 5) { 1770 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 1771 return; 1772 } 1773 1774 pipeline_name = tokens[1]; 1775 1776 if (strcmp(tokens[2], "table") != 0) { 1777 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "table"); 1778 return; 1779 } 1780 1781 if (strcmp(tokens[3], "match") != 0) { 1782 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "match"); 1783 return; 1784 } 1785 1786 t0 = 4; 1787 if (strcmp(tokens[t0], "acl") == 0) { 1788 if (n_tokens < t0 + 6) { 1789 snprintf(out, out_size, MSG_ARG_MISMATCH, 1790 "pipeline table acl"); 1791 return; 1792 } 1793 1794 p.match_type = TABLE_ACL; 1795 1796 if (strcmp(tokens[t0 + 1], "ipv4") == 0) 1797 p.match.acl.ip_version = 1; 1798 else if (strcmp(tokens[t0 + 1], "ipv6") == 0) 1799 p.match.acl.ip_version = 0; 1800 else { 1801 snprintf(out, out_size, MSG_ARG_NOT_FOUND, 1802 "ipv4 or ipv6"); 1803 return; 1804 } 1805 1806 if (strcmp(tokens[t0 + 2], "offset") != 0) { 1807 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset"); 1808 return; 1809 } 1810 1811 if (parser_read_uint32(&p.match.acl.ip_header_offset, 1812 tokens[t0 + 3]) != 0) { 1813 snprintf(out, out_size, MSG_ARG_INVALID, 1814 "ip_header_offset"); 1815 return; 1816 } 1817 1818 if (strcmp(tokens[t0 + 4], "size") != 0) { 1819 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "size"); 1820 return; 1821 } 1822 1823 if (parser_read_uint32(&p.match.acl.n_rules, 1824 tokens[t0 + 5]) != 0) { 1825 snprintf(out, out_size, MSG_ARG_INVALID, "n_rules"); 1826 return; 1827 } 1828 1829 t0 += 6; 1830 } else if (strcmp(tokens[t0], "array") == 0) { 1831 if (n_tokens < t0 + 5) { 1832 snprintf(out, out_size, MSG_ARG_MISMATCH, 1833 "pipeline table array"); 1834 return; 1835 } 1836 1837 p.match_type = TABLE_ARRAY; 1838 1839 if (strcmp(tokens[t0 + 1], "offset") != 0) { 1840 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset"); 1841 return; 1842 } 1843 1844 if (parser_read_uint32(&p.match.array.key_offset, 1845 tokens[t0 + 2]) != 0) { 1846 snprintf(out, out_size, MSG_ARG_INVALID, "key_offset"); 1847 return; 1848 } 1849 1850 if (strcmp(tokens[t0 + 3], "size") != 0) { 1851 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "size"); 1852 return; 1853 } 1854 1855 if (parser_read_uint32(&p.match.array.n_keys, 1856 tokens[t0 + 4]) != 0) { 1857 snprintf(out, out_size, MSG_ARG_INVALID, "n_keys"); 1858 return; 1859 } 1860 1861 t0 += 5; 1862 } else if (strcmp(tokens[t0], "hash") == 0) { 1863 uint32_t key_mask_size = TABLE_RULE_MATCH_SIZE_MAX; 1864 1865 if (n_tokens < t0 + 12) { 1866 snprintf(out, out_size, MSG_ARG_MISMATCH, 1867 "pipeline table hash"); 1868 return; 1869 } 1870 1871 p.match_type = TABLE_HASH; 1872 1873 if (strcmp(tokens[t0 + 1], "ext") == 0) 1874 p.match.hash.extendable_bucket = 1; 1875 else if (strcmp(tokens[t0 + 1], "lru") == 0) 1876 p.match.hash.extendable_bucket = 0; 1877 else { 1878 snprintf(out, out_size, MSG_ARG_NOT_FOUND, 1879 "ext or lru"); 1880 return; 1881 } 1882 1883 if (strcmp(tokens[t0 + 2], "key") != 0) { 1884 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "key"); 1885 return; 1886 } 1887 1888 if ((parser_read_uint32(&p.match.hash.key_size, 1889 tokens[t0 + 3]) != 0) || 1890 (p.match.hash.key_size == 0) || 1891 (p.match.hash.key_size > TABLE_RULE_MATCH_SIZE_MAX)) { 1892 snprintf(out, out_size, MSG_ARG_INVALID, "key_size"); 1893 return; 1894 } 1895 1896 if (strcmp(tokens[t0 + 4], "mask") != 0) { 1897 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "mask"); 1898 return; 1899 } 1900 1901 if ((parse_hex_string(tokens[t0 + 5], 1902 key_mask, &key_mask_size) != 0) || 1903 (key_mask_size != p.match.hash.key_size)) { 1904 snprintf(out, out_size, MSG_ARG_INVALID, "key_mask"); 1905 return; 1906 } 1907 p.match.hash.key_mask = key_mask; 1908 1909 if (strcmp(tokens[t0 + 6], "offset") != 0) { 1910 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset"); 1911 return; 1912 } 1913 1914 if (parser_read_uint32(&p.match.hash.key_offset, 1915 tokens[t0 + 7]) != 0) { 1916 snprintf(out, out_size, MSG_ARG_INVALID, "key_offset"); 1917 return; 1918 } 1919 1920 if (strcmp(tokens[t0 + 8], "buckets") != 0) { 1921 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "buckets"); 1922 return; 1923 } 1924 1925 if (parser_read_uint32(&p.match.hash.n_buckets, 1926 tokens[t0 + 9]) != 0) { 1927 snprintf(out, out_size, MSG_ARG_INVALID, "n_buckets"); 1928 return; 1929 } 1930 1931 if (strcmp(tokens[t0 + 10], "size") != 0) { 1932 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "size"); 1933 return; 1934 } 1935 1936 if (parser_read_uint32(&p.match.hash.n_keys, 1937 tokens[t0 + 11]) != 0) { 1938 snprintf(out, out_size, MSG_ARG_INVALID, "n_keys"); 1939 return; 1940 } 1941 1942 t0 += 12; 1943 } else if (strcmp(tokens[t0], "lpm") == 0) { 1944 if (n_tokens < t0 + 6) { 1945 snprintf(out, out_size, MSG_ARG_MISMATCH, 1946 "pipeline table lpm"); 1947 return; 1948 } 1949 1950 p.match_type = TABLE_LPM; 1951 1952 if (strcmp(tokens[t0 + 1], "ipv4") == 0) 1953 p.match.lpm.key_size = 4; 1954 else if (strcmp(tokens[t0 + 1], "ipv6") == 0) 1955 p.match.lpm.key_size = 16; 1956 else { 1957 snprintf(out, out_size, MSG_ARG_NOT_FOUND, 1958 "ipv4 or ipv6"); 1959 return; 1960 } 1961 1962 if (strcmp(tokens[t0 + 2], "offset") != 0) { 1963 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset"); 1964 return; 1965 } 1966 1967 if (parser_read_uint32(&p.match.lpm.key_offset, 1968 tokens[t0 + 3]) != 0) { 1969 snprintf(out, out_size, MSG_ARG_INVALID, "key_offset"); 1970 return; 1971 } 1972 1973 if (strcmp(tokens[t0 + 4], "size") != 0) { 1974 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "size"); 1975 return; 1976 } 1977 1978 if (parser_read_uint32(&p.match.lpm.n_rules, 1979 tokens[t0 + 5]) != 0) { 1980 snprintf(out, out_size, MSG_ARG_INVALID, "n_rules"); 1981 return; 1982 } 1983 1984 t0 += 6; 1985 } else if (strcmp(tokens[t0], "stub") == 0) { 1986 p.match_type = TABLE_STUB; 1987 1988 t0 += 1; 1989 } else { 1990 snprintf(out, out_size, MSG_ARG_INVALID, tokens[0]); 1991 return; 1992 } 1993 1994 p.action_profile_name = NULL; 1995 if ((n_tokens > t0) && (strcmp(tokens[t0], "action") == 0)) { 1996 if (n_tokens < t0 + 2) { 1997 snprintf(out, out_size, MSG_ARG_MISMATCH, "action"); 1998 return; 1999 } 2000 2001 p.action_profile_name = tokens[t0 + 1]; 2002 2003 t0 += 2; 2004 } 2005 2006 if (n_tokens > t0) { 2007 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 2008 return; 2009 } 2010 2011 status = pipeline_table_create(pipeline_name, &p); 2012 if (status) { 2013 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 2014 return; 2015 } 2016 } 2017 2018 static const char cmd_pipeline_port_in_table_help[] = 2019 "pipeline <pipeline_name> port in <port_id> table <table_id>\n"; 2020 2021 static void 2022 cmd_pipeline_port_in_table(char **tokens, 2023 uint32_t n_tokens, 2024 char *out, 2025 size_t out_size) 2026 { 2027 char *pipeline_name; 2028 uint32_t port_id, table_id; 2029 int status; 2030 2031 if (n_tokens != 7) { 2032 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 2033 return; 2034 } 2035 2036 pipeline_name = tokens[1]; 2037 2038 if (strcmp(tokens[2], "port") != 0) { 2039 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port"); 2040 return; 2041 } 2042 2043 if (strcmp(tokens[3], "in") != 0) { 2044 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "in"); 2045 return; 2046 } 2047 2048 if (parser_read_uint32(&port_id, tokens[4]) != 0) { 2049 snprintf(out, out_size, MSG_ARG_INVALID, "port_id"); 2050 return; 2051 } 2052 2053 if (strcmp(tokens[5], "table") != 0) { 2054 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "table"); 2055 return; 2056 } 2057 2058 if (parser_read_uint32(&table_id, tokens[6]) != 0) { 2059 snprintf(out, out_size, MSG_ARG_INVALID, "table_id"); 2060 return; 2061 } 2062 2063 status = pipeline_port_in_connect_to_table(pipeline_name, 2064 port_id, 2065 table_id); 2066 if (status) { 2067 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 2068 return; 2069 } 2070 } 2071 2072 2073 static const char cmd_pipeline_port_in_stats_help[] = 2074 "pipeline <pipeline_name> port in <port_id> stats read [clear]\n"; 2075 2076 #define MSG_PIPELINE_PORT_IN_STATS \ 2077 "Pkts in: %" PRIu64 "\n" \ 2078 "Pkts dropped by AH: %" PRIu64 "\n" \ 2079 "Pkts dropped by other: %" PRIu64 "\n" 2080 2081 static void 2082 cmd_pipeline_port_in_stats(char **tokens, 2083 uint32_t n_tokens, 2084 char *out, 2085 size_t out_size) 2086 { 2087 struct rte_pipeline_port_in_stats stats; 2088 char *pipeline_name; 2089 uint32_t port_id; 2090 int clear, status; 2091 2092 if ((n_tokens != 7) && (n_tokens != 8)) { 2093 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 2094 return; 2095 } 2096 2097 pipeline_name = tokens[1]; 2098 2099 if (strcmp(tokens[2], "port") != 0) { 2100 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port"); 2101 return; 2102 } 2103 2104 if (strcmp(tokens[3], "in") != 0) { 2105 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "in"); 2106 return; 2107 } 2108 2109 if (parser_read_uint32(&port_id, tokens[4]) != 0) { 2110 snprintf(out, out_size, MSG_ARG_INVALID, "port_id"); 2111 return; 2112 } 2113 2114 if (strcmp(tokens[5], "stats") != 0) { 2115 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "stats"); 2116 return; 2117 } 2118 2119 if (strcmp(tokens[6], "read") != 0) { 2120 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "read"); 2121 return; 2122 } 2123 2124 clear = 0; 2125 if (n_tokens == 8) { 2126 if (strcmp(tokens[7], "clear") != 0) { 2127 snprintf(out, out_size, MSG_ARG_INVALID, "clear"); 2128 return; 2129 } 2130 2131 clear = 1; 2132 } 2133 2134 status = pipeline_port_in_stats_read(pipeline_name, 2135 port_id, 2136 &stats, 2137 clear); 2138 if (status) { 2139 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 2140 return; 2141 } 2142 2143 snprintf(out, out_size, MSG_PIPELINE_PORT_IN_STATS, 2144 stats.stats.n_pkts_in, 2145 stats.n_pkts_dropped_by_ah, 2146 stats.stats.n_pkts_drop); 2147 } 2148 2149 2150 static const char cmd_pipeline_port_in_enable_help[] = 2151 "pipeline <pipeline_name> port in <port_id> enable\n"; 2152 2153 static void 2154 cmd_pipeline_port_in_enable(char **tokens, 2155 uint32_t n_tokens, 2156 char *out, 2157 size_t out_size) 2158 { 2159 char *pipeline_name; 2160 uint32_t port_id; 2161 int status; 2162 2163 if (n_tokens != 6) { 2164 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 2165 return; 2166 } 2167 2168 pipeline_name = tokens[1]; 2169 2170 if (strcmp(tokens[2], "port") != 0) { 2171 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port"); 2172 return; 2173 } 2174 2175 if (strcmp(tokens[3], "in") != 0) { 2176 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "in"); 2177 return; 2178 } 2179 2180 if (parser_read_uint32(&port_id, tokens[4]) != 0) { 2181 snprintf(out, out_size, MSG_ARG_INVALID, "port_id"); 2182 return; 2183 } 2184 2185 if (strcmp(tokens[5], "enable") != 0) { 2186 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "enable"); 2187 return; 2188 } 2189 2190 status = pipeline_port_in_enable(pipeline_name, port_id); 2191 if (status) { 2192 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 2193 return; 2194 } 2195 } 2196 2197 2198 static const char cmd_pipeline_port_in_disable_help[] = 2199 "pipeline <pipeline_name> port in <port_id> disable\n"; 2200 2201 static void 2202 cmd_pipeline_port_in_disable(char **tokens, 2203 uint32_t n_tokens, 2204 char *out, 2205 size_t out_size) 2206 { 2207 char *pipeline_name; 2208 uint32_t port_id; 2209 int status; 2210 2211 if (n_tokens != 6) { 2212 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 2213 return; 2214 } 2215 2216 pipeline_name = tokens[1]; 2217 2218 if (strcmp(tokens[2], "port") != 0) { 2219 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port"); 2220 return; 2221 } 2222 2223 if (strcmp(tokens[3], "in") != 0) { 2224 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "in"); 2225 return; 2226 } 2227 2228 if (parser_read_uint32(&port_id, tokens[4]) != 0) { 2229 snprintf(out, out_size, MSG_ARG_INVALID, "port_id"); 2230 return; 2231 } 2232 2233 if (strcmp(tokens[5], "disable") != 0) { 2234 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "disable"); 2235 return; 2236 } 2237 2238 status = pipeline_port_in_disable(pipeline_name, port_id); 2239 if (status) { 2240 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 2241 return; 2242 } 2243 } 2244 2245 2246 static const char cmd_pipeline_port_out_stats_help[] = 2247 "pipeline <pipeline_name> port out <port_id> stats read [clear]\n"; 2248 2249 #define MSG_PIPELINE_PORT_OUT_STATS \ 2250 "Pkts in: %" PRIu64 "\n" \ 2251 "Pkts dropped by AH: %" PRIu64 "\n" \ 2252 "Pkts dropped by other: %" PRIu64 "\n" 2253 2254 static void 2255 cmd_pipeline_port_out_stats(char **tokens, 2256 uint32_t n_tokens, 2257 char *out, 2258 size_t out_size) 2259 { 2260 struct rte_pipeline_port_out_stats stats; 2261 char *pipeline_name; 2262 uint32_t port_id; 2263 int clear, status; 2264 2265 if ((n_tokens != 7) && (n_tokens != 8)) { 2266 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 2267 return; 2268 } 2269 2270 pipeline_name = tokens[1]; 2271 2272 if (strcmp(tokens[2], "port") != 0) { 2273 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port"); 2274 return; 2275 } 2276 2277 if (strcmp(tokens[3], "out") != 0) { 2278 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "out"); 2279 return; 2280 } 2281 2282 if (parser_read_uint32(&port_id, tokens[4]) != 0) { 2283 snprintf(out, out_size, MSG_ARG_INVALID, "port_id"); 2284 return; 2285 } 2286 2287 if (strcmp(tokens[5], "stats") != 0) { 2288 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "stats"); 2289 return; 2290 } 2291 2292 if (strcmp(tokens[6], "read") != 0) { 2293 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "read"); 2294 return; 2295 } 2296 2297 clear = 0; 2298 if (n_tokens == 8) { 2299 if (strcmp(tokens[7], "clear") != 0) { 2300 snprintf(out, out_size, MSG_ARG_INVALID, "clear"); 2301 return; 2302 } 2303 2304 clear = 1; 2305 } 2306 2307 status = pipeline_port_out_stats_read(pipeline_name, 2308 port_id, 2309 &stats, 2310 clear); 2311 if (status) { 2312 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 2313 return; 2314 } 2315 2316 snprintf(out, out_size, MSG_PIPELINE_PORT_OUT_STATS, 2317 stats.stats.n_pkts_in, 2318 stats.n_pkts_dropped_by_ah, 2319 stats.stats.n_pkts_drop); 2320 } 2321 2322 2323 static const char cmd_pipeline_table_stats_help[] = 2324 "pipeline <pipeline_name> table <table_id> stats read [clear]\n"; 2325 2326 #define MSG_PIPELINE_TABLE_STATS \ 2327 "Pkts in: %" PRIu64 "\n" \ 2328 "Pkts in with lookup miss: %" PRIu64 "\n" \ 2329 "Pkts in with lookup hit dropped by AH: %" PRIu64 "\n" \ 2330 "Pkts in with lookup hit dropped by others: %" PRIu64 "\n" \ 2331 "Pkts in with lookup miss dropped by AH: %" PRIu64 "\n" \ 2332 "Pkts in with lookup miss dropped by others: %" PRIu64 "\n" 2333 2334 static void 2335 cmd_pipeline_table_stats(char **tokens, 2336 uint32_t n_tokens, 2337 char *out, 2338 size_t out_size) 2339 { 2340 struct rte_pipeline_table_stats stats; 2341 char *pipeline_name; 2342 uint32_t table_id; 2343 int clear, status; 2344 2345 if ((n_tokens != 6) && (n_tokens != 7)) { 2346 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 2347 return; 2348 } 2349 2350 pipeline_name = tokens[1]; 2351 2352 if (strcmp(tokens[2], "table") != 0) { 2353 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port"); 2354 return; 2355 } 2356 2357 if (parser_read_uint32(&table_id, tokens[3]) != 0) { 2358 snprintf(out, out_size, MSG_ARG_INVALID, "table_id"); 2359 return; 2360 } 2361 2362 if (strcmp(tokens[4], "stats") != 0) { 2363 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "stats"); 2364 return; 2365 } 2366 2367 if (strcmp(tokens[5], "read") != 0) { 2368 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "read"); 2369 return; 2370 } 2371 2372 clear = 0; 2373 if (n_tokens == 7) { 2374 if (strcmp(tokens[6], "clear") != 0) { 2375 snprintf(out, out_size, MSG_ARG_INVALID, "clear"); 2376 return; 2377 } 2378 2379 clear = 1; 2380 } 2381 2382 status = pipeline_table_stats_read(pipeline_name, 2383 table_id, 2384 &stats, 2385 clear); 2386 if (status) { 2387 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 2388 return; 2389 } 2390 2391 snprintf(out, out_size, MSG_PIPELINE_TABLE_STATS, 2392 stats.stats.n_pkts_in, 2393 stats.stats.n_pkts_lookup_miss, 2394 stats.n_pkts_dropped_by_lkp_hit_ah, 2395 stats.n_pkts_dropped_lkp_hit, 2396 stats.n_pkts_dropped_by_lkp_miss_ah, 2397 stats.n_pkts_dropped_lkp_miss); 2398 } 2399 2400 /** 2401 * <match> ::= 2402 * 2403 * match 2404 * acl 2405 * priority <priority> 2406 * ipv4 | ipv6 <sa> <sa_depth> <da> <da_depth> 2407 * <sp0> <sp1> <dp0> <dp1> <proto> 2408 * | array <pos> 2409 * | hash 2410 * raw <key> 2411 * | ipv4_5tuple <sa> <da> <sp> <dp> <proto> 2412 * | ipv6_5tuple <sa> <da> <sp> <dp> <proto> 2413 * | ipv4_addr <addr> 2414 * | ipv6_addr <addr> 2415 * | qinq <svlan> <cvlan> 2416 * | lpm 2417 * ipv4 | ipv6 <addr> <depth> 2418 */ 2419 struct pkt_key_qinq { 2420 uint16_t ethertype_svlan; 2421 uint16_t svlan; 2422 uint16_t ethertype_cvlan; 2423 uint16_t cvlan; 2424 } __attribute__((__packed__)); 2425 2426 struct pkt_key_ipv4_5tuple { 2427 uint8_t time_to_live; 2428 uint8_t proto; 2429 uint16_t hdr_checksum; 2430 uint32_t sa; 2431 uint32_t da; 2432 uint16_t sp; 2433 uint16_t dp; 2434 } __attribute__((__packed__)); 2435 2436 struct pkt_key_ipv6_5tuple { 2437 uint16_t payload_length; 2438 uint8_t proto; 2439 uint8_t hop_limit; 2440 uint8_t sa[16]; 2441 uint8_t da[16]; 2442 uint16_t sp; 2443 uint16_t dp; 2444 } __attribute__((__packed__)); 2445 2446 struct pkt_key_ipv4_addr { 2447 uint32_t addr; 2448 } __attribute__((__packed__)); 2449 2450 struct pkt_key_ipv6_addr { 2451 uint8_t addr[16]; 2452 } __attribute__((__packed__)); 2453 2454 static uint32_t 2455 parse_match(char **tokens, 2456 uint32_t n_tokens, 2457 char *out, 2458 size_t out_size, 2459 struct table_rule_match *m) 2460 { 2461 memset(m, 0, sizeof(*m)); 2462 2463 if (n_tokens < 2) 2464 return 0; 2465 2466 if (strcmp(tokens[0], "match") != 0) { 2467 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "match"); 2468 return 0; 2469 } 2470 2471 if (strcmp(tokens[1], "acl") == 0) { 2472 if (n_tokens < 14) { 2473 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 2474 return 0; 2475 } 2476 2477 m->match_type = TABLE_ACL; 2478 2479 if (strcmp(tokens[2], "priority") != 0) { 2480 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "priority"); 2481 return 0; 2482 } 2483 2484 if (parser_read_uint32(&m->match.acl.priority, 2485 tokens[3]) != 0) { 2486 snprintf(out, out_size, MSG_ARG_INVALID, "priority"); 2487 return 0; 2488 } 2489 2490 if (strcmp(tokens[4], "ipv4") == 0) { 2491 struct in_addr saddr, daddr; 2492 2493 m->match.acl.ip_version = 1; 2494 2495 if (parse_ipv4_addr(tokens[5], &saddr) != 0) { 2496 snprintf(out, out_size, MSG_ARG_INVALID, "sa"); 2497 return 0; 2498 } 2499 m->match.acl.ipv4.sa = rte_be_to_cpu_32(saddr.s_addr); 2500 2501 if (parse_ipv4_addr(tokens[7], &daddr) != 0) { 2502 snprintf(out, out_size, MSG_ARG_INVALID, "da"); 2503 return 0; 2504 } 2505 m->match.acl.ipv4.da = rte_be_to_cpu_32(daddr.s_addr); 2506 } else if (strcmp(tokens[4], "ipv6") == 0) { 2507 struct in6_addr saddr, daddr; 2508 2509 m->match.acl.ip_version = 0; 2510 2511 if (parse_ipv6_addr(tokens[5], &saddr) != 0) { 2512 snprintf(out, out_size, MSG_ARG_INVALID, "sa"); 2513 return 0; 2514 } 2515 memcpy(m->match.acl.ipv6.sa, saddr.s6_addr, 16); 2516 2517 if (parse_ipv6_addr(tokens[7], &daddr) != 0) { 2518 snprintf(out, out_size, MSG_ARG_INVALID, "da"); 2519 return 0; 2520 } 2521 memcpy(m->match.acl.ipv6.da, daddr.s6_addr, 16); 2522 } else { 2523 snprintf(out, out_size, MSG_ARG_NOT_FOUND, 2524 "ipv4 or ipv6"); 2525 return 0; 2526 } 2527 2528 if (parser_read_uint32(&m->match.acl.sa_depth, 2529 tokens[6]) != 0) { 2530 snprintf(out, out_size, MSG_ARG_INVALID, "sa_depth"); 2531 return 0; 2532 } 2533 2534 if (parser_read_uint32(&m->match.acl.da_depth, 2535 tokens[8]) != 0) { 2536 snprintf(out, out_size, MSG_ARG_INVALID, "da_depth"); 2537 return 0; 2538 } 2539 2540 if (parser_read_uint16(&m->match.acl.sp0, tokens[9]) != 0) { 2541 snprintf(out, out_size, MSG_ARG_INVALID, "sp0"); 2542 return 0; 2543 } 2544 2545 if (parser_read_uint16(&m->match.acl.sp1, tokens[10]) != 0) { 2546 snprintf(out, out_size, MSG_ARG_INVALID, "sp1"); 2547 return 0; 2548 } 2549 2550 if (parser_read_uint16(&m->match.acl.dp0, tokens[11]) != 0) { 2551 snprintf(out, out_size, MSG_ARG_INVALID, "dp0"); 2552 return 0; 2553 } 2554 2555 if (parser_read_uint16(&m->match.acl.dp1, tokens[12]) != 0) { 2556 snprintf(out, out_size, MSG_ARG_INVALID, "dp1"); 2557 return 0; 2558 } 2559 2560 if (parser_read_uint8(&m->match.acl.proto, tokens[13]) != 0) { 2561 snprintf(out, out_size, MSG_ARG_INVALID, "proto"); 2562 return 0; 2563 } 2564 2565 m->match.acl.proto_mask = 0xff; 2566 2567 return 14; 2568 } /* acl */ 2569 2570 if (strcmp(tokens[1], "array") == 0) { 2571 if (n_tokens < 3) { 2572 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 2573 return 0; 2574 } 2575 2576 m->match_type = TABLE_ARRAY; 2577 2578 if (parser_read_uint32(&m->match.array.pos, tokens[2]) != 0) { 2579 snprintf(out, out_size, MSG_ARG_INVALID, "pos"); 2580 return 0; 2581 } 2582 2583 return 3; 2584 } /* array */ 2585 2586 if (strcmp(tokens[1], "hash") == 0) { 2587 if (n_tokens < 3) { 2588 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 2589 return 0; 2590 } 2591 2592 m->match_type = TABLE_HASH; 2593 2594 if (strcmp(tokens[2], "raw") == 0) { 2595 uint32_t key_size = TABLE_RULE_MATCH_SIZE_MAX; 2596 2597 if (n_tokens < 4) { 2598 snprintf(out, out_size, MSG_ARG_MISMATCH, 2599 tokens[0]); 2600 return 0; 2601 } 2602 2603 if (parse_hex_string(tokens[3], 2604 m->match.hash.key, &key_size) != 0) { 2605 snprintf(out, out_size, MSG_ARG_INVALID, "key"); 2606 return 0; 2607 } 2608 2609 return 4; 2610 } /* hash raw */ 2611 2612 if (strcmp(tokens[2], "ipv4_5tuple") == 0) { 2613 struct pkt_key_ipv4_5tuple *ipv4 = 2614 (struct pkt_key_ipv4_5tuple *) m->match.hash.key; 2615 struct in_addr saddr, daddr; 2616 uint16_t sp, dp; 2617 uint8_t proto; 2618 2619 if (n_tokens < 8) { 2620 snprintf(out, out_size, MSG_ARG_MISMATCH, 2621 tokens[0]); 2622 return 0; 2623 } 2624 2625 if (parse_ipv4_addr(tokens[3], &saddr) != 0) { 2626 snprintf(out, out_size, MSG_ARG_INVALID, "sa"); 2627 return 0; 2628 } 2629 2630 if (parse_ipv4_addr(tokens[4], &daddr) != 0) { 2631 snprintf(out, out_size, MSG_ARG_INVALID, "da"); 2632 return 0; 2633 } 2634 2635 if (parser_read_uint16(&sp, tokens[5]) != 0) { 2636 snprintf(out, out_size, MSG_ARG_INVALID, "sp"); 2637 return 0; 2638 } 2639 2640 if (parser_read_uint16(&dp, tokens[6]) != 0) { 2641 snprintf(out, out_size, MSG_ARG_INVALID, "dp"); 2642 return 0; 2643 } 2644 2645 if (parser_read_uint8(&proto, tokens[7]) != 0) { 2646 snprintf(out, out_size, MSG_ARG_INVALID, 2647 "proto"); 2648 return 0; 2649 } 2650 2651 ipv4->sa = saddr.s_addr; 2652 ipv4->da = daddr.s_addr; 2653 ipv4->sp = rte_cpu_to_be_16(sp); 2654 ipv4->dp = rte_cpu_to_be_16(dp); 2655 ipv4->proto = proto; 2656 2657 return 8; 2658 } /* hash ipv4_5tuple */ 2659 2660 if (strcmp(tokens[2], "ipv6_5tuple") == 0) { 2661 struct pkt_key_ipv6_5tuple *ipv6 = 2662 (struct pkt_key_ipv6_5tuple *) m->match.hash.key; 2663 struct in6_addr saddr, daddr; 2664 uint16_t sp, dp; 2665 uint8_t proto; 2666 2667 if (n_tokens < 8) { 2668 snprintf(out, out_size, MSG_ARG_MISMATCH, 2669 tokens[0]); 2670 return 0; 2671 } 2672 2673 if (parse_ipv6_addr(tokens[3], &saddr) != 0) { 2674 snprintf(out, out_size, MSG_ARG_INVALID, "sa"); 2675 return 0; 2676 } 2677 2678 if (parse_ipv6_addr(tokens[4], &daddr) != 0) { 2679 snprintf(out, out_size, MSG_ARG_INVALID, "da"); 2680 return 0; 2681 } 2682 2683 if (parser_read_uint16(&sp, tokens[5]) != 0) { 2684 snprintf(out, out_size, MSG_ARG_INVALID, "sp"); 2685 return 0; 2686 } 2687 2688 if (parser_read_uint16(&dp, tokens[6]) != 0) { 2689 snprintf(out, out_size, MSG_ARG_INVALID, "dp"); 2690 return 0; 2691 } 2692 2693 if (parser_read_uint8(&proto, tokens[7]) != 0) { 2694 snprintf(out, out_size, MSG_ARG_INVALID, 2695 "proto"); 2696 return 0; 2697 } 2698 2699 memcpy(ipv6->sa, saddr.s6_addr, 16); 2700 memcpy(ipv6->da, daddr.s6_addr, 16); 2701 ipv6->sp = rte_cpu_to_be_16(sp); 2702 ipv6->dp = rte_cpu_to_be_16(dp); 2703 ipv6->proto = proto; 2704 2705 return 8; 2706 } /* hash ipv6_5tuple */ 2707 2708 if (strcmp(tokens[2], "ipv4_addr") == 0) { 2709 struct pkt_key_ipv4_addr *ipv4_addr = 2710 (struct pkt_key_ipv4_addr *) m->match.hash.key; 2711 struct in_addr addr; 2712 2713 if (n_tokens < 4) { 2714 snprintf(out, out_size, MSG_ARG_MISMATCH, 2715 tokens[0]); 2716 return 0; 2717 } 2718 2719 if (parse_ipv4_addr(tokens[3], &addr) != 0) { 2720 snprintf(out, out_size, MSG_ARG_INVALID, 2721 "addr"); 2722 return 0; 2723 } 2724 2725 ipv4_addr->addr = addr.s_addr; 2726 2727 return 4; 2728 } /* hash ipv4_addr */ 2729 2730 if (strcmp(tokens[2], "ipv6_addr") == 0) { 2731 struct pkt_key_ipv6_addr *ipv6_addr = 2732 (struct pkt_key_ipv6_addr *) m->match.hash.key; 2733 struct in6_addr addr; 2734 2735 if (n_tokens < 4) { 2736 snprintf(out, out_size, MSG_ARG_MISMATCH, 2737 tokens[0]); 2738 return 0; 2739 } 2740 2741 if (parse_ipv6_addr(tokens[3], &addr) != 0) { 2742 snprintf(out, out_size, MSG_ARG_INVALID, 2743 "addr"); 2744 return 0; 2745 } 2746 2747 memcpy(ipv6_addr->addr, addr.s6_addr, 16); 2748 2749 return 4; 2750 } /* hash ipv6_5tuple */ 2751 2752 if (strcmp(tokens[2], "qinq") == 0) { 2753 struct pkt_key_qinq *qinq = 2754 (struct pkt_key_qinq *) m->match.hash.key; 2755 uint16_t svlan, cvlan; 2756 2757 if (n_tokens < 5) { 2758 snprintf(out, out_size, MSG_ARG_MISMATCH, 2759 tokens[0]); 2760 return 0; 2761 } 2762 2763 if ((parser_read_uint16(&svlan, tokens[3]) != 0) || 2764 (svlan > 0xFFF)) { 2765 snprintf(out, out_size, MSG_ARG_INVALID, 2766 "svlan"); 2767 return 0; 2768 } 2769 2770 if ((parser_read_uint16(&cvlan, tokens[4]) != 0) || 2771 (cvlan > 0xFFF)) { 2772 snprintf(out, out_size, MSG_ARG_INVALID, 2773 "cvlan"); 2774 return 0; 2775 } 2776 2777 qinq->svlan = rte_cpu_to_be_16(svlan); 2778 qinq->cvlan = rte_cpu_to_be_16(cvlan); 2779 2780 return 5; 2781 } /* hash qinq */ 2782 2783 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 2784 return 0; 2785 } /* hash */ 2786 2787 if (strcmp(tokens[1], "lpm") == 0) { 2788 if (n_tokens < 5) { 2789 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 2790 return 0; 2791 } 2792 2793 m->match_type = TABLE_LPM; 2794 2795 if (strcmp(tokens[2], "ipv4") == 0) { 2796 struct in_addr addr; 2797 2798 m->match.lpm.ip_version = 1; 2799 2800 if (parse_ipv4_addr(tokens[3], &addr) != 0) { 2801 snprintf(out, out_size, MSG_ARG_INVALID, 2802 "addr"); 2803 return 0; 2804 } 2805 2806 m->match.lpm.ipv4 = rte_be_to_cpu_32(addr.s_addr); 2807 } else if (strcmp(tokens[2], "ipv6") == 0) { 2808 struct in6_addr addr; 2809 2810 m->match.lpm.ip_version = 0; 2811 2812 if (parse_ipv6_addr(tokens[3], &addr) != 0) { 2813 snprintf(out, out_size, MSG_ARG_INVALID, 2814 "addr"); 2815 return 0; 2816 } 2817 2818 memcpy(m->match.lpm.ipv6, addr.s6_addr, 16); 2819 } else { 2820 snprintf(out, out_size, MSG_ARG_MISMATCH, 2821 "ipv4 or ipv6"); 2822 return 0; 2823 } 2824 2825 if (parser_read_uint8(&m->match.lpm.depth, tokens[4]) != 0) { 2826 snprintf(out, out_size, MSG_ARG_INVALID, "depth"); 2827 return 0; 2828 } 2829 2830 return 5; 2831 } /* lpm */ 2832 2833 snprintf(out, out_size, MSG_ARG_MISMATCH, 2834 "acl or array or hash or lpm"); 2835 return 0; 2836 } 2837 2838 /** 2839 * table_action ::= 2840 * 2841 * action 2842 * fwd 2843 * drop 2844 * | port <port_id> 2845 * | meta 2846 * | table <table_id> 2847 * [balance <out0> ... <out7>] 2848 * [meter 2849 * tc0 meter <meter_profile_id> policer g <pa> y <pa> r <pa> 2850 * [tc1 meter <meter_profile_id> policer g <pa> y <pa> r <pa> 2851 * tc2 meter <meter_profile_id> policer g <pa> y <pa> r <pa> 2852 * tc3 meter <meter_profile_id> policer g <pa> y <pa> r <pa>]] 2853 * [tm subport <subport_id> pipe <pipe_id>] 2854 * [encap 2855 * ether <da> <sa> 2856 * | vlan <da> <sa> <pcp> <dei> <vid> 2857 * | qinq <da> <sa> <pcp> <dei> <vid> <pcp> <dei> <vid> 2858 * | mpls unicast | multicast 2859 * <da> <sa> 2860 * label0 <label> <tc> <ttl> 2861 * [label1 <label> <tc> <ttl> 2862 * [label2 <label> <tc> <ttl> 2863 * [label3 <label> <tc> <ttl>]]] 2864 * | pppoe <da> <sa> <session_id>] 2865 * [nat ipv4 | ipv6 <addr> <port>] 2866 * [ttl dec | keep] 2867 * [stats] 2868 * [time] 2869 * 2870 * where: 2871 * <pa> ::= g | y | r | drop 2872 */ 2873 static uint32_t 2874 parse_table_action_fwd(char **tokens, 2875 uint32_t n_tokens, 2876 struct table_rule_action *a) 2877 { 2878 if ((n_tokens == 0) || (strcmp(tokens[0], "fwd") != 0)) 2879 return 0; 2880 2881 tokens++; 2882 n_tokens--; 2883 2884 if (n_tokens && (strcmp(tokens[0], "drop") == 0)) { 2885 a->fwd.action = RTE_PIPELINE_ACTION_DROP; 2886 a->action_mask |= 1 << RTE_TABLE_ACTION_FWD; 2887 return 1 + 1; 2888 } 2889 2890 if (n_tokens && (strcmp(tokens[0], "port") == 0)) { 2891 uint32_t id; 2892 2893 if ((n_tokens < 2) || 2894 parser_read_uint32(&id, tokens[1])) 2895 return 0; 2896 2897 a->fwd.action = RTE_PIPELINE_ACTION_PORT; 2898 a->fwd.id = id; 2899 a->action_mask |= 1 << RTE_TABLE_ACTION_FWD; 2900 return 1 + 2; 2901 } 2902 2903 if (n_tokens && (strcmp(tokens[0], "meta") == 0)) { 2904 a->fwd.action = RTE_PIPELINE_ACTION_PORT_META; 2905 a->action_mask |= 1 << RTE_TABLE_ACTION_FWD; 2906 return 1 + 1; 2907 } 2908 2909 if (n_tokens && (strcmp(tokens[0], "table") == 0)) { 2910 uint32_t id; 2911 2912 if ((n_tokens < 2) || 2913 parser_read_uint32(&id, tokens[1])) 2914 return 0; 2915 2916 a->fwd.action = RTE_PIPELINE_ACTION_TABLE; 2917 a->fwd.id = id; 2918 a->action_mask |= 1 << RTE_TABLE_ACTION_FWD; 2919 return 1 + 2; 2920 } 2921 2922 return 0; 2923 } 2924 2925 static uint32_t 2926 parse_table_action_balance(char **tokens, 2927 uint32_t n_tokens, 2928 struct table_rule_action *a) 2929 { 2930 uint32_t i; 2931 2932 if ((n_tokens == 0) || (strcmp(tokens[0], "balance") != 0)) 2933 return 0; 2934 2935 tokens++; 2936 n_tokens--; 2937 2938 if (n_tokens < RTE_TABLE_ACTION_LB_TABLE_SIZE) 2939 return 0; 2940 2941 for (i = 0; i < RTE_TABLE_ACTION_LB_TABLE_SIZE; i++) 2942 if (parser_read_uint32(&a->lb.out[i], tokens[i]) != 0) 2943 return 0; 2944 2945 a->action_mask |= 1 << RTE_TABLE_ACTION_LB; 2946 return 1 + RTE_TABLE_ACTION_LB_TABLE_SIZE; 2947 2948 } 2949 2950 static int 2951 parse_policer_action(char *token, enum rte_table_action_policer *a) 2952 { 2953 if (strcmp(token, "g") == 0) { 2954 *a = RTE_TABLE_ACTION_POLICER_COLOR_GREEN; 2955 return 0; 2956 } 2957 2958 if (strcmp(token, "y") == 0) { 2959 *a = RTE_TABLE_ACTION_POLICER_COLOR_YELLOW; 2960 return 0; 2961 } 2962 2963 if (strcmp(token, "r") == 0) { 2964 *a = RTE_TABLE_ACTION_POLICER_COLOR_RED; 2965 return 0; 2966 } 2967 2968 if (strcmp(token, "drop") == 0) { 2969 *a = RTE_TABLE_ACTION_POLICER_DROP; 2970 return 0; 2971 } 2972 2973 return -1; 2974 } 2975 2976 static uint32_t 2977 parse_table_action_meter_tc(char **tokens, 2978 uint32_t n_tokens, 2979 struct rte_table_action_mtr_tc_params *mtr) 2980 { 2981 if ((n_tokens < 9) || 2982 strcmp(tokens[0], "meter") || 2983 parser_read_uint32(&mtr->meter_profile_id, tokens[1]) || 2984 strcmp(tokens[2], "policer") || 2985 strcmp(tokens[3], "g") || 2986 parse_policer_action(tokens[4], &mtr->policer[e_RTE_METER_GREEN]) || 2987 strcmp(tokens[5], "y") || 2988 parse_policer_action(tokens[6], &mtr->policer[e_RTE_METER_YELLOW]) || 2989 strcmp(tokens[7], "r") || 2990 parse_policer_action(tokens[8], &mtr->policer[e_RTE_METER_RED])) 2991 return 0; 2992 2993 return 9; 2994 } 2995 2996 static uint32_t 2997 parse_table_action_meter(char **tokens, 2998 uint32_t n_tokens, 2999 struct table_rule_action *a) 3000 { 3001 if ((n_tokens == 0) || strcmp(tokens[0], "meter")) 3002 return 0; 3003 3004 tokens++; 3005 n_tokens--; 3006 3007 if ((n_tokens < 10) || 3008 strcmp(tokens[0], "tc0") || 3009 (parse_table_action_meter_tc(tokens + 1, 3010 n_tokens - 1, 3011 &a->mtr.mtr[0]) == 0)) 3012 return 0; 3013 3014 tokens += 10; 3015 n_tokens -= 10; 3016 3017 if ((n_tokens == 0) || strcmp(tokens[0], "tc1")) { 3018 a->mtr.tc_mask = 1; 3019 a->action_mask |= 1 << RTE_TABLE_ACTION_MTR; 3020 return 1 + 10; 3021 } 3022 3023 if ((n_tokens < 30) || 3024 (parse_table_action_meter_tc(tokens + 1, 3025 n_tokens - 1, &a->mtr.mtr[1]) == 0) || 3026 strcmp(tokens[10], "tc2") || 3027 (parse_table_action_meter_tc(tokens + 11, 3028 n_tokens - 11, &a->mtr.mtr[2]) == 0) || 3029 strcmp(tokens[20], "tc3") || 3030 (parse_table_action_meter_tc(tokens + 21, 3031 n_tokens - 21, &a->mtr.mtr[3]) == 0)) 3032 return 0; 3033 3034 a->mtr.tc_mask = 0xF; 3035 a->action_mask |= 1 << RTE_TABLE_ACTION_MTR; 3036 return 1 + 10 + 3 * 10; 3037 } 3038 3039 static uint32_t 3040 parse_table_action_tm(char **tokens, 3041 uint32_t n_tokens, 3042 struct table_rule_action *a) 3043 { 3044 uint32_t subport_id, pipe_id; 3045 3046 if ((n_tokens < 5) || 3047 strcmp(tokens[0], "tm") || 3048 strcmp(tokens[1], "subport") || 3049 parser_read_uint32(&subport_id, tokens[2]) || 3050 strcmp(tokens[3], "pipe") || 3051 parser_read_uint32(&pipe_id, tokens[4])) 3052 return 0; 3053 3054 a->tm.subport_id = subport_id; 3055 a->tm.pipe_id = pipe_id; 3056 a->action_mask |= 1 << RTE_TABLE_ACTION_TM; 3057 return 5; 3058 } 3059 3060 static uint32_t 3061 parse_table_action_encap(char **tokens, 3062 uint32_t n_tokens, 3063 struct table_rule_action *a) 3064 { 3065 if ((n_tokens == 0) || strcmp(tokens[0], "encap")) 3066 return 0; 3067 3068 tokens++; 3069 n_tokens--; 3070 3071 /* ether */ 3072 if (n_tokens && (strcmp(tokens[0], "ether") == 0)) { 3073 if ((n_tokens < 3) || 3074 parse_mac_addr(tokens[1], &a->encap.ether.ether.da) || 3075 parse_mac_addr(tokens[2], &a->encap.ether.ether.sa)) 3076 return 0; 3077 3078 a->encap.type = RTE_TABLE_ACTION_ENCAP_ETHER; 3079 a->action_mask |= 1 << RTE_TABLE_ACTION_ENCAP; 3080 return 1 + 3; 3081 } 3082 3083 /* vlan */ 3084 if (n_tokens && (strcmp(tokens[0], "vlan") == 0)) { 3085 uint32_t pcp, dei, vid; 3086 3087 if ((n_tokens < 6) || 3088 parse_mac_addr(tokens[1], &a->encap.vlan.ether.da) || 3089 parse_mac_addr(tokens[2], &a->encap.vlan.ether.sa) || 3090 parser_read_uint32(&pcp, tokens[3]) || 3091 (pcp > 0x7) || 3092 parser_read_uint32(&dei, tokens[4]) || 3093 (dei > 0x1) || 3094 parser_read_uint32(&vid, tokens[5]) || 3095 (vid > 0xFFF)) 3096 return 0; 3097 3098 a->encap.vlan.vlan.pcp = pcp & 0x7; 3099 a->encap.vlan.vlan.dei = dei & 0x1; 3100 a->encap.vlan.vlan.vid = vid & 0xFFF; 3101 a->encap.type = RTE_TABLE_ACTION_ENCAP_VLAN; 3102 a->action_mask |= 1 << RTE_TABLE_ACTION_ENCAP; 3103 return 1 + 6; 3104 } 3105 3106 /* qinq */ 3107 if (n_tokens && (strcmp(tokens[0], "qinq") == 0)) { 3108 uint32_t svlan_pcp, svlan_dei, svlan_vid; 3109 uint32_t cvlan_pcp, cvlan_dei, cvlan_vid; 3110 3111 if ((n_tokens < 9) || 3112 parse_mac_addr(tokens[1], &a->encap.qinq.ether.da) || 3113 parse_mac_addr(tokens[2], &a->encap.qinq.ether.sa) || 3114 parser_read_uint32(&svlan_pcp, tokens[3]) || 3115 (svlan_pcp > 0x7) || 3116 parser_read_uint32(&svlan_dei, tokens[4]) || 3117 (svlan_dei > 0x1) || 3118 parser_read_uint32(&svlan_vid, tokens[5]) || 3119 (svlan_vid > 0xFFF) || 3120 parser_read_uint32(&cvlan_pcp, tokens[6]) || 3121 (cvlan_pcp > 0x7) || 3122 parser_read_uint32(&cvlan_dei, tokens[7]) || 3123 (cvlan_dei > 0x1) || 3124 parser_read_uint32(&cvlan_vid, tokens[8]) || 3125 (cvlan_vid > 0xFFF)) 3126 return 0; 3127 3128 a->encap.qinq.svlan.pcp = svlan_pcp & 0x7; 3129 a->encap.qinq.svlan.dei = svlan_dei & 0x1; 3130 a->encap.qinq.svlan.vid = svlan_vid & 0xFFF; 3131 a->encap.qinq.cvlan.pcp = cvlan_pcp & 0x7; 3132 a->encap.qinq.cvlan.dei = cvlan_dei & 0x1; 3133 a->encap.qinq.cvlan.vid = cvlan_vid & 0xFFF; 3134 a->encap.type = RTE_TABLE_ACTION_ENCAP_QINQ; 3135 a->action_mask |= 1 << RTE_TABLE_ACTION_ENCAP; 3136 return 1 + 9; 3137 } 3138 3139 /* mpls */ 3140 if (n_tokens && (strcmp(tokens[0], "mpls") == 0)) { 3141 uint32_t label, tc, ttl; 3142 3143 if (n_tokens < 8) 3144 return 0; 3145 3146 if (strcmp(tokens[1], "unicast") == 0) 3147 a->encap.mpls.unicast = 1; 3148 else if (strcmp(tokens[1], "multicast") == 0) 3149 a->encap.mpls.unicast = 0; 3150 else 3151 return 0; 3152 3153 if (parse_mac_addr(tokens[2], &a->encap.mpls.ether.da) || 3154 parse_mac_addr(tokens[3], &a->encap.mpls.ether.sa) || 3155 strcmp(tokens[4], "label0") || 3156 parser_read_uint32(&label, tokens[5]) || 3157 (label > 0xFFFFF) || 3158 parser_read_uint32(&tc, tokens[6]) || 3159 (tc > 0x7) || 3160 parser_read_uint32(&ttl, tokens[7]) || 3161 (ttl > 0x3F)) 3162 return 0; 3163 3164 a->encap.mpls.mpls[0].label = label; 3165 a->encap.mpls.mpls[0].tc = tc; 3166 a->encap.mpls.mpls[0].ttl = ttl; 3167 3168 tokens += 8; 3169 n_tokens -= 8; 3170 3171 if ((n_tokens == 0) || strcmp(tokens[0], "label1")) { 3172 a->encap.mpls.mpls_count = 1; 3173 a->encap.type = RTE_TABLE_ACTION_ENCAP_MPLS; 3174 a->action_mask |= 1 << RTE_TABLE_ACTION_ENCAP; 3175 return 1 + 8; 3176 } 3177 3178 if ((n_tokens < 4) || 3179 parser_read_uint32(&label, tokens[1]) || 3180 (label > 0xFFFFF) || 3181 parser_read_uint32(&tc, tokens[2]) || 3182 (tc > 0x7) || 3183 parser_read_uint32(&ttl, tokens[3]) || 3184 (ttl > 0x3F)) 3185 return 0; 3186 3187 a->encap.mpls.mpls[1].label = label; 3188 a->encap.mpls.mpls[1].tc = tc; 3189 a->encap.mpls.mpls[1].ttl = ttl; 3190 3191 tokens += 4; 3192 n_tokens -= 4; 3193 3194 if ((n_tokens == 0) || strcmp(tokens[0], "label2")) { 3195 a->encap.mpls.mpls_count = 2; 3196 a->encap.type = RTE_TABLE_ACTION_ENCAP_MPLS; 3197 a->action_mask |= 1 << RTE_TABLE_ACTION_ENCAP; 3198 return 1 + 8 + 4; 3199 } 3200 3201 if ((n_tokens < 4) || 3202 parser_read_uint32(&label, tokens[1]) || 3203 (label > 0xFFFFF) || 3204 parser_read_uint32(&tc, tokens[2]) || 3205 (tc > 0x7) || 3206 parser_read_uint32(&ttl, tokens[3]) || 3207 (ttl > 0x3F)) 3208 return 0; 3209 3210 a->encap.mpls.mpls[2].label = label; 3211 a->encap.mpls.mpls[2].tc = tc; 3212 a->encap.mpls.mpls[2].ttl = ttl; 3213 3214 tokens += 4; 3215 n_tokens -= 4; 3216 3217 if ((n_tokens == 0) || strcmp(tokens[0], "label3")) { 3218 a->encap.mpls.mpls_count = 3; 3219 a->encap.type = RTE_TABLE_ACTION_ENCAP_MPLS; 3220 a->action_mask |= 1 << RTE_TABLE_ACTION_ENCAP; 3221 return 1 + 8 + 4 + 4; 3222 } 3223 3224 if ((n_tokens < 4) || 3225 parser_read_uint32(&label, tokens[1]) || 3226 (label > 0xFFFFF) || 3227 parser_read_uint32(&tc, tokens[2]) || 3228 (tc > 0x7) || 3229 parser_read_uint32(&ttl, tokens[3]) || 3230 (ttl > 0x3F)) 3231 return 0; 3232 3233 a->encap.mpls.mpls[3].label = label; 3234 a->encap.mpls.mpls[3].tc = tc; 3235 a->encap.mpls.mpls[3].ttl = ttl; 3236 3237 a->encap.mpls.mpls_count = 4; 3238 a->encap.type = RTE_TABLE_ACTION_ENCAP_MPLS; 3239 a->action_mask |= 1 << RTE_TABLE_ACTION_ENCAP; 3240 return 1 + 8 + 4 + 4 + 4; 3241 } 3242 3243 /* pppoe */ 3244 if (n_tokens && (strcmp(tokens[0], "pppoe") == 0)) { 3245 if ((n_tokens < 4) || 3246 parse_mac_addr(tokens[1], &a->encap.pppoe.ether.da) || 3247 parse_mac_addr(tokens[2], &a->encap.pppoe.ether.sa) || 3248 parser_read_uint16(&a->encap.pppoe.pppoe.session_id, 3249 tokens[3])) 3250 return 0; 3251 3252 a->encap.type = RTE_TABLE_ACTION_ENCAP_PPPOE; 3253 a->action_mask |= 1 << RTE_TABLE_ACTION_ENCAP; 3254 return 1 + 4; 3255 } 3256 3257 return 0; 3258 } 3259 3260 static uint32_t 3261 parse_table_action_nat(char **tokens, 3262 uint32_t n_tokens, 3263 struct table_rule_action *a) 3264 { 3265 if ((n_tokens < 4) || 3266 strcmp(tokens[0], "nat")) 3267 return 0; 3268 3269 if (strcmp(tokens[1], "ipv4") == 0) { 3270 struct in_addr addr; 3271 uint16_t port; 3272 3273 if (parse_ipv4_addr(tokens[2], &addr) || 3274 parser_read_uint16(&port, tokens[3])) 3275 return 0; 3276 3277 a->nat.ip_version = 1; 3278 a->nat.addr.ipv4 = rte_be_to_cpu_32(addr.s_addr); 3279 a->nat.port = port; 3280 a->action_mask |= 1 << RTE_TABLE_ACTION_NAT; 3281 return 4; 3282 } 3283 3284 if (strcmp(tokens[1], "ipv6") == 0) { 3285 struct in6_addr addr; 3286 uint16_t port; 3287 3288 if (parse_ipv6_addr(tokens[2], &addr) || 3289 parser_read_uint16(&port, tokens[3])) 3290 return 0; 3291 3292 a->nat.ip_version = 0; 3293 memcpy(a->nat.addr.ipv6, addr.s6_addr, 16); 3294 a->nat.port = port; 3295 a->action_mask |= 1 << RTE_TABLE_ACTION_NAT; 3296 return 4; 3297 } 3298 3299 return 0; 3300 } 3301 3302 static uint32_t 3303 parse_table_action_ttl(char **tokens, 3304 uint32_t n_tokens, 3305 struct table_rule_action *a) 3306 { 3307 if ((n_tokens < 2) || 3308 strcmp(tokens[0], "ttl")) 3309 return 0; 3310 3311 if (strcmp(tokens[1], "dec") == 0) 3312 a->ttl.decrement = 1; 3313 else if (strcmp(tokens[1], "keep") == 0) 3314 a->ttl.decrement = 0; 3315 else 3316 return 0; 3317 3318 a->action_mask |= 1 << RTE_TABLE_ACTION_TTL; 3319 return 2; 3320 } 3321 3322 static uint32_t 3323 parse_table_action_stats(char **tokens, 3324 uint32_t n_tokens, 3325 struct table_rule_action *a) 3326 { 3327 if ((n_tokens < 1) || 3328 strcmp(tokens[0], "stats")) 3329 return 0; 3330 3331 a->stats.n_packets = 0; 3332 a->stats.n_bytes = 0; 3333 a->action_mask |= 1 << RTE_TABLE_ACTION_STATS; 3334 return 1; 3335 } 3336 3337 static uint32_t 3338 parse_table_action_time(char **tokens, 3339 uint32_t n_tokens, 3340 struct table_rule_action *a) 3341 { 3342 if ((n_tokens < 1) || 3343 strcmp(tokens[0], "time")) 3344 return 0; 3345 3346 a->time.time = rte_rdtsc(); 3347 a->action_mask |= 1 << RTE_TABLE_ACTION_TIME; 3348 return 1; 3349 } 3350 3351 static uint32_t 3352 parse_table_action(char **tokens, 3353 uint32_t n_tokens, 3354 char *out, 3355 size_t out_size, 3356 struct table_rule_action *a) 3357 { 3358 uint32_t n_tokens0 = n_tokens; 3359 3360 memset(a, 0, sizeof(*a)); 3361 3362 if ((n_tokens < 2) || 3363 strcmp(tokens[0], "action")) 3364 return 0; 3365 3366 tokens++; 3367 n_tokens--; 3368 3369 if (n_tokens && (strcmp(tokens[0], "fwd") == 0)) { 3370 uint32_t n; 3371 3372 n = parse_table_action_fwd(tokens, n_tokens, a); 3373 if (n == 0) { 3374 snprintf(out, out_size, MSG_ARG_INVALID, 3375 "action fwd"); 3376 return 0; 3377 } 3378 3379 tokens += n; 3380 n_tokens -= n; 3381 } 3382 3383 if (n_tokens && (strcmp(tokens[0], "balance") == 0)) { 3384 uint32_t n; 3385 3386 n = parse_table_action_balance(tokens, n_tokens, a); 3387 if (n == 0) { 3388 snprintf(out, out_size, MSG_ARG_INVALID, 3389 "action balance"); 3390 return 0; 3391 } 3392 3393 tokens += n; 3394 n_tokens -= n; 3395 } 3396 3397 if (n_tokens && (strcmp(tokens[0], "meter") == 0)) { 3398 uint32_t n; 3399 3400 n = parse_table_action_meter(tokens, n_tokens, a); 3401 if (n == 0) { 3402 snprintf(out, out_size, MSG_ARG_INVALID, 3403 "action meter"); 3404 return 0; 3405 } 3406 3407 tokens += n; 3408 n_tokens -= n; 3409 } 3410 3411 if (n_tokens && (strcmp(tokens[0], "tm") == 0)) { 3412 uint32_t n; 3413 3414 n = parse_table_action_tm(tokens, n_tokens, a); 3415 if (n == 0) { 3416 snprintf(out, out_size, MSG_ARG_INVALID, 3417 "action tm"); 3418 return 0; 3419 } 3420 3421 tokens += n; 3422 n_tokens -= n; 3423 } 3424 3425 if (n_tokens && (strcmp(tokens[0], "encap") == 0)) { 3426 uint32_t n; 3427 3428 n = parse_table_action_encap(tokens, n_tokens, a); 3429 if (n == 0) { 3430 snprintf(out, out_size, MSG_ARG_INVALID, 3431 "action encap"); 3432 return 0; 3433 } 3434 3435 tokens += n; 3436 n_tokens -= n; 3437 } 3438 3439 if (n_tokens && (strcmp(tokens[0], "nat") == 0)) { 3440 uint32_t n; 3441 3442 n = parse_table_action_nat(tokens, n_tokens, a); 3443 if (n == 0) { 3444 snprintf(out, out_size, MSG_ARG_INVALID, 3445 "action nat"); 3446 return 0; 3447 } 3448 3449 tokens += n; 3450 n_tokens -= n; 3451 } 3452 3453 if (n_tokens && (strcmp(tokens[0], "ttl") == 0)) { 3454 uint32_t n; 3455 3456 n = parse_table_action_ttl(tokens, n_tokens, a); 3457 if (n == 0) { 3458 snprintf(out, out_size, MSG_ARG_INVALID, 3459 "action ttl"); 3460 return 0; 3461 } 3462 3463 tokens += n; 3464 n_tokens -= n; 3465 } 3466 3467 if (n_tokens && (strcmp(tokens[0], "stats") == 0)) { 3468 uint32_t n; 3469 3470 n = parse_table_action_stats(tokens, n_tokens, a); 3471 if (n == 0) { 3472 snprintf(out, out_size, MSG_ARG_INVALID, 3473 "action stats"); 3474 return 0; 3475 } 3476 3477 tokens += n; 3478 n_tokens -= n; 3479 } 3480 3481 if (n_tokens && (strcmp(tokens[0], "time") == 0)) { 3482 uint32_t n; 3483 3484 n = parse_table_action_time(tokens, n_tokens, a); 3485 if (n == 0) { 3486 snprintf(out, out_size, MSG_ARG_INVALID, 3487 "action time"); 3488 return 0; 3489 } 3490 3491 tokens += n; 3492 n_tokens -= n; 3493 } 3494 3495 if (n_tokens0 - n_tokens == 1) { 3496 snprintf(out, out_size, MSG_ARG_INVALID, "action"); 3497 return 0; 3498 } 3499 3500 return n_tokens0 - n_tokens; 3501 } 3502 3503 3504 static const char cmd_pipeline_table_rule_add_help[] = 3505 "pipeline <pipeline_name> table <table_id> rule add\n" 3506 " match <match>\n" 3507 " action <table_action>\n"; 3508 3509 static void 3510 cmd_pipeline_table_rule_add(char **tokens, 3511 uint32_t n_tokens, 3512 char *out, 3513 size_t out_size) 3514 { 3515 struct table_rule_match m; 3516 struct table_rule_action a; 3517 char *pipeline_name; 3518 void *data; 3519 uint32_t table_id, t0, n_tokens_parsed; 3520 int status; 3521 3522 if (n_tokens < 8) { 3523 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 3524 return; 3525 } 3526 3527 pipeline_name = tokens[1]; 3528 3529 if (strcmp(tokens[2], "table") != 0) { 3530 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "table"); 3531 return; 3532 } 3533 3534 if (parser_read_uint32(&table_id, tokens[3]) != 0) { 3535 snprintf(out, out_size, MSG_ARG_INVALID, "table_id"); 3536 return; 3537 } 3538 3539 if (strcmp(tokens[4], "rule") != 0) { 3540 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rule"); 3541 return; 3542 } 3543 3544 if (strcmp(tokens[5], "add") != 0) { 3545 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "add"); 3546 return; 3547 } 3548 3549 t0 = 6; 3550 3551 /* match */ 3552 n_tokens_parsed = parse_match(tokens + t0, 3553 n_tokens - t0, 3554 out, 3555 out_size, 3556 &m); 3557 if (n_tokens_parsed == 0) 3558 return; 3559 t0 += n_tokens_parsed; 3560 3561 /* action */ 3562 n_tokens_parsed = parse_table_action(tokens + t0, 3563 n_tokens - t0, 3564 out, 3565 out_size, 3566 &a); 3567 if (n_tokens_parsed == 0) 3568 return; 3569 t0 += n_tokens_parsed; 3570 3571 if (t0 != n_tokens) { 3572 snprintf(out, out_size, MSG_ARG_INVALID, tokens[0]); 3573 return; 3574 } 3575 3576 status = pipeline_table_rule_add(pipeline_name, table_id, 3577 &m, &a, &data); 3578 if (status) { 3579 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 3580 return; 3581 } 3582 } 3583 3584 3585 static const char cmd_pipeline_table_rule_add_default_help[] = 3586 "pipeline <pipeline_name> table <table_id> rule add\n" 3587 " match\n" 3588 " default\n" 3589 " action\n" 3590 " fwd\n" 3591 " drop\n" 3592 " | port <port_id>\n" 3593 " | meta\n" 3594 " | table <table_id>\n"; 3595 3596 static void 3597 cmd_pipeline_table_rule_add_default(char **tokens, 3598 uint32_t n_tokens, 3599 char *out, 3600 size_t out_size) 3601 { 3602 struct table_rule_action action; 3603 void *data; 3604 char *pipeline_name; 3605 uint32_t table_id; 3606 int status; 3607 3608 if ((n_tokens != 11) && (n_tokens != 12)) { 3609 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 3610 return; 3611 } 3612 3613 pipeline_name = tokens[1]; 3614 3615 if (strcmp(tokens[2], "table") != 0) { 3616 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "table"); 3617 return; 3618 } 3619 3620 if (parser_read_uint32(&table_id, tokens[3]) != 0) { 3621 snprintf(out, out_size, MSG_ARG_INVALID, "table_id"); 3622 return; 3623 } 3624 3625 if (strcmp(tokens[4], "rule") != 0) { 3626 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rule"); 3627 return; 3628 } 3629 3630 if (strcmp(tokens[5], "add") != 0) { 3631 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "add"); 3632 return; 3633 } 3634 3635 if (strcmp(tokens[6], "match") != 0) { 3636 snprintf(out, out_size, MSG_ARG_INVALID, "match"); 3637 return; 3638 } 3639 3640 if (strcmp(tokens[7], "default") != 0) { 3641 snprintf(out, out_size, MSG_ARG_INVALID, "default"); 3642 return; 3643 } 3644 3645 if (strcmp(tokens[8], "action") != 0) { 3646 snprintf(out, out_size, MSG_ARG_INVALID, "action"); 3647 return; 3648 } 3649 3650 if (strcmp(tokens[9], "fwd") != 0) { 3651 snprintf(out, out_size, MSG_ARG_INVALID, "fwd"); 3652 return; 3653 } 3654 3655 action.action_mask = 1 << RTE_TABLE_ACTION_FWD; 3656 3657 if (strcmp(tokens[10], "drop") == 0) { 3658 if (n_tokens != 11) { 3659 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 3660 return; 3661 } 3662 3663 action.fwd.action = RTE_PIPELINE_ACTION_DROP; 3664 } else if (strcmp(tokens[10], "port") == 0) { 3665 uint32_t id; 3666 3667 if (n_tokens != 12) { 3668 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 3669 return; 3670 } 3671 3672 if (parser_read_uint32(&id, tokens[11]) != 0) { 3673 snprintf(out, out_size, MSG_ARG_INVALID, "port_id"); 3674 return; 3675 } 3676 3677 action.fwd.action = RTE_PIPELINE_ACTION_PORT; 3678 action.fwd.id = id; 3679 } else if (strcmp(tokens[10], "meta") == 0) { 3680 if (n_tokens != 11) { 3681 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 3682 return; 3683 } 3684 3685 action.fwd.action = RTE_PIPELINE_ACTION_PORT_META; 3686 } else if (strcmp(tokens[10], "table") == 0) { 3687 uint32_t id; 3688 3689 if (n_tokens != 12) { 3690 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 3691 return; 3692 } 3693 3694 if (parser_read_uint32(&id, tokens[11]) != 0) { 3695 snprintf(out, out_size, MSG_ARG_INVALID, "table_id"); 3696 return; 3697 } 3698 3699 action.fwd.action = RTE_PIPELINE_ACTION_TABLE; 3700 action.fwd.id = id; 3701 } else { 3702 snprintf(out, out_size, MSG_ARG_INVALID, 3703 "drop or port or meta or table"); 3704 return; 3705 } 3706 3707 status = pipeline_table_rule_add_default(pipeline_name, 3708 table_id, 3709 &action, 3710 &data); 3711 if (status) { 3712 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 3713 return; 3714 } 3715 } 3716 3717 3718 static const char cmd_pipeline_table_rule_add_bulk_help[] = 3719 "pipeline <pipeline_name> table <table_id> rule add bulk <file_name> <n_rules>\n" 3720 "\n" 3721 " File <file_name>:\n" 3722 " - line format: match <match> action <action>\n"; 3723 3724 static int 3725 cli_rule_file_process(const char *file_name, 3726 size_t line_len_max, 3727 struct table_rule_match *m, 3728 struct table_rule_action *a, 3729 uint32_t *n_rules, 3730 uint32_t *line_number, 3731 char *out, 3732 size_t out_size); 3733 3734 static void 3735 cmd_pipeline_table_rule_add_bulk(char **tokens, 3736 uint32_t n_tokens, 3737 char *out, 3738 size_t out_size) 3739 { 3740 struct table_rule_match *match; 3741 struct table_rule_action *action; 3742 void **data; 3743 char *pipeline_name, *file_name; 3744 uint32_t table_id, n_rules, n_rules_parsed, line_number; 3745 int status; 3746 3747 if (n_tokens != 9) { 3748 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 3749 return; 3750 } 3751 3752 pipeline_name = tokens[1]; 3753 3754 if (strcmp(tokens[2], "table") != 0) { 3755 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "table"); 3756 return; 3757 } 3758 3759 if (parser_read_uint32(&table_id, tokens[3]) != 0) { 3760 snprintf(out, out_size, MSG_ARG_INVALID, "table_id"); 3761 return; 3762 } 3763 3764 if (strcmp(tokens[4], "rule") != 0) { 3765 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rule"); 3766 return; 3767 } 3768 3769 if (strcmp(tokens[5], "add") != 0) { 3770 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "add"); 3771 return; 3772 } 3773 3774 if (strcmp(tokens[6], "bulk") != 0) { 3775 snprintf(out, out_size, MSG_ARG_INVALID, "bulk"); 3776 return; 3777 } 3778 3779 file_name = tokens[7]; 3780 3781 if ((parser_read_uint32(&n_rules, tokens[8]) != 0) || 3782 (n_rules == 0)) { 3783 snprintf(out, out_size, MSG_ARG_INVALID, "n_rules"); 3784 return; 3785 } 3786 3787 /* Memory allocation. */ 3788 match = calloc(n_rules, sizeof(struct table_rule_match)); 3789 action = calloc(n_rules, sizeof(struct table_rule_action)); 3790 data = calloc(n_rules, sizeof(void *)); 3791 if ((match == NULL) || (action == NULL) || (data == NULL)) { 3792 snprintf(out, out_size, MSG_OUT_OF_MEMORY); 3793 free(data); 3794 free(action); 3795 free(match); 3796 return; 3797 } 3798 3799 /* Load rule file */ 3800 n_rules_parsed = n_rules; 3801 status = cli_rule_file_process(file_name, 3802 1024, 3803 match, 3804 action, 3805 &n_rules_parsed, 3806 &line_number, 3807 out, 3808 out_size); 3809 if (status) { 3810 snprintf(out, out_size, MSG_FILE_ERR, file_name, line_number); 3811 free(data); 3812 free(action); 3813 free(match); 3814 return; 3815 } 3816 if (n_rules_parsed != n_rules) { 3817 snprintf(out, out_size, MSG_FILE_NOT_ENOUGH, file_name); 3818 free(data); 3819 free(action); 3820 free(match); 3821 return; 3822 } 3823 3824 /* Rule bulk add */ 3825 status = pipeline_table_rule_add_bulk(pipeline_name, 3826 table_id, 3827 match, 3828 action, 3829 data, 3830 &n_rules); 3831 if (status) { 3832 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 3833 free(data); 3834 free(action); 3835 free(match); 3836 return; 3837 } 3838 3839 /* Memory free */ 3840 free(data); 3841 free(action); 3842 free(match); 3843 } 3844 3845 3846 static const char cmd_pipeline_table_rule_delete_help[] = 3847 "pipeline <pipeline_name> table <table_id> rule delete\n" 3848 " match <match>\n"; 3849 3850 static void 3851 cmd_pipeline_table_rule_delete(char **tokens, 3852 uint32_t n_tokens, 3853 char *out, 3854 size_t out_size) 3855 { 3856 struct table_rule_match m; 3857 char *pipeline_name; 3858 uint32_t table_id, n_tokens_parsed, t0; 3859 int status; 3860 3861 if (n_tokens < 8) { 3862 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 3863 return; 3864 } 3865 3866 pipeline_name = tokens[1]; 3867 3868 if (strcmp(tokens[2], "table") != 0) { 3869 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "table"); 3870 return; 3871 } 3872 3873 if (parser_read_uint32(&table_id, tokens[3]) != 0) { 3874 snprintf(out, out_size, MSG_ARG_INVALID, "table_id"); 3875 return; 3876 } 3877 3878 if (strcmp(tokens[4], "rule") != 0) { 3879 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rule"); 3880 return; 3881 } 3882 3883 if (strcmp(tokens[5], "delete") != 0) { 3884 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "delete"); 3885 return; 3886 } 3887 3888 t0 = 6; 3889 3890 /* match */ 3891 n_tokens_parsed = parse_match(tokens + t0, 3892 n_tokens - t0, 3893 out, 3894 out_size, 3895 &m); 3896 if (n_tokens_parsed == 0) 3897 return; 3898 t0 += n_tokens_parsed; 3899 3900 if (n_tokens != t0) { 3901 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 3902 return; 3903 } 3904 3905 status = pipeline_table_rule_delete(pipeline_name, 3906 table_id, 3907 &m); 3908 if (status) { 3909 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 3910 return; 3911 } 3912 } 3913 3914 3915 static const char cmd_pipeline_table_rule_delete_default_help[] = 3916 "pipeline <pipeline_name> table <table_id> rule delete\n" 3917 " match\n" 3918 " default\n"; 3919 3920 static void 3921 cmd_pipeline_table_rule_delete_default(char **tokens, 3922 uint32_t n_tokens, 3923 char *out, 3924 size_t out_size) 3925 { 3926 char *pipeline_name; 3927 uint32_t table_id; 3928 int status; 3929 3930 if (n_tokens != 8) { 3931 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 3932 return; 3933 } 3934 3935 pipeline_name = tokens[1]; 3936 3937 if (strcmp(tokens[2], "table") != 0) { 3938 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "table"); 3939 return; 3940 } 3941 3942 if (parser_read_uint32(&table_id, tokens[3]) != 0) { 3943 snprintf(out, out_size, MSG_ARG_INVALID, "table_id"); 3944 return; 3945 } 3946 3947 if (strcmp(tokens[4], "rule") != 0) { 3948 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rule"); 3949 return; 3950 } 3951 3952 if (strcmp(tokens[5], "delete") != 0) { 3953 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "delete"); 3954 return; 3955 } 3956 3957 if (strcmp(tokens[6], "match") != 0) { 3958 snprintf(out, out_size, MSG_ARG_INVALID, "match"); 3959 return; 3960 } 3961 3962 if (strcmp(tokens[7], "default") != 0) { 3963 snprintf(out, out_size, MSG_ARG_INVALID, "default"); 3964 return; 3965 } 3966 3967 status = pipeline_table_rule_delete_default(pipeline_name, 3968 table_id); 3969 if (status) { 3970 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 3971 return; 3972 } 3973 } 3974 3975 3976 static const char cmd_pipeline_table_rule_stats_read_help[] = 3977 "pipeline <pipeline_name> table <table_id> rule read stats [clear]\n"; 3978 3979 static void 3980 cmd_pipeline_table_rule_stats_read(char **tokens, 3981 uint32_t n_tokens __rte_unused, 3982 char *out, 3983 size_t out_size) 3984 { 3985 snprintf(out, out_size, MSG_CMD_UNIMPLEM, tokens[0]); 3986 } 3987 3988 3989 static const char cmd_pipeline_table_meter_profile_add_help[] = 3990 "pipeline <pipeline_name> table <table_id> meter profile <meter_profile_id>\n" 3991 " add srtcm cir <cir> cbs <cbs> ebs <ebs>\n" 3992 " | trtcm cir <cir> pir <pir> cbs <cbs> pbs <pbs>\n"; 3993 3994 static void 3995 cmd_pipeline_table_meter_profile_add(char **tokens, 3996 uint32_t n_tokens, 3997 char *out, 3998 size_t out_size) 3999 { 4000 struct rte_table_action_meter_profile p; 4001 char *pipeline_name; 4002 uint32_t table_id, meter_profile_id; 4003 int status; 4004 4005 if (n_tokens < 9) { 4006 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 4007 return; 4008 } 4009 4010 pipeline_name = tokens[1]; 4011 4012 if (strcmp(tokens[2], "table") != 0) { 4013 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port"); 4014 return; 4015 } 4016 4017 if (parser_read_uint32(&table_id, tokens[3]) != 0) { 4018 snprintf(out, out_size, MSG_ARG_INVALID, "table_id"); 4019 return; 4020 } 4021 4022 if (strcmp(tokens[4], "meter") != 0) { 4023 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "meter"); 4024 return; 4025 } 4026 4027 if (strcmp(tokens[5], "profile") != 0) { 4028 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "profile"); 4029 return; 4030 } 4031 4032 if (parser_read_uint32(&meter_profile_id, tokens[6]) != 0) { 4033 snprintf(out, out_size, MSG_ARG_INVALID, "meter_profile_id"); 4034 return; 4035 } 4036 4037 if (strcmp(tokens[7], "add") != 0) { 4038 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "add"); 4039 return; 4040 } 4041 4042 if (strcmp(tokens[8], "srtcm") == 0) { 4043 if (n_tokens != 15) { 4044 snprintf(out, out_size, MSG_ARG_MISMATCH, 4045 tokens[0]); 4046 return; 4047 } 4048 4049 p.alg = RTE_TABLE_ACTION_METER_SRTCM; 4050 4051 if (strcmp(tokens[9], "cir") != 0) { 4052 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "cir"); 4053 return; 4054 } 4055 4056 if (parser_read_uint64(&p.srtcm.cir, tokens[10]) != 0) { 4057 snprintf(out, out_size, MSG_ARG_INVALID, "cir"); 4058 return; 4059 } 4060 4061 if (strcmp(tokens[11], "cbs") != 0) { 4062 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "cbs"); 4063 return; 4064 } 4065 4066 if (parser_read_uint64(&p.srtcm.cbs, tokens[12]) != 0) { 4067 snprintf(out, out_size, MSG_ARG_INVALID, "cbs"); 4068 return; 4069 } 4070 4071 if (strcmp(tokens[13], "ebs") != 0) { 4072 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "ebs"); 4073 return; 4074 } 4075 4076 if (parser_read_uint64(&p.srtcm.ebs, tokens[14]) != 0) { 4077 snprintf(out, out_size, MSG_ARG_INVALID, "ebs"); 4078 return; 4079 } 4080 } else if (strcmp(tokens[8], "trtcm") == 0) { 4081 if (n_tokens != 17) { 4082 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 4083 return; 4084 } 4085 4086 p.alg = RTE_TABLE_ACTION_METER_TRTCM; 4087 4088 if (strcmp(tokens[9], "cir") != 0) { 4089 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "cir"); 4090 return; 4091 } 4092 4093 if (parser_read_uint64(&p.trtcm.cir, tokens[10]) != 0) { 4094 snprintf(out, out_size, MSG_ARG_INVALID, "cir"); 4095 return; 4096 } 4097 4098 if (strcmp(tokens[11], "pir") != 0) { 4099 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pir"); 4100 return; 4101 } 4102 4103 if (parser_read_uint64(&p.trtcm.pir, tokens[12]) != 0) { 4104 snprintf(out, out_size, MSG_ARG_INVALID, "pir"); 4105 return; 4106 } 4107 if (strcmp(tokens[13], "cbs") != 0) { 4108 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "cbs"); 4109 return; 4110 } 4111 4112 if (parser_read_uint64(&p.trtcm.cbs, tokens[14]) != 0) { 4113 snprintf(out, out_size, MSG_ARG_INVALID, "cbs"); 4114 return; 4115 } 4116 4117 if (strcmp(tokens[15], "pbs") != 0) { 4118 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pbs"); 4119 return; 4120 } 4121 4122 if (parser_read_uint64(&p.trtcm.pbs, tokens[16]) != 0) { 4123 snprintf(out, out_size, MSG_ARG_INVALID, "pbs"); 4124 return; 4125 } 4126 } else { 4127 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 4128 return; 4129 } 4130 4131 status = pipeline_table_mtr_profile_add(pipeline_name, 4132 table_id, 4133 meter_profile_id, 4134 &p); 4135 if (status) { 4136 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 4137 return; 4138 } 4139 } 4140 4141 4142 static const char cmd_pipeline_table_meter_profile_delete_help[] = 4143 "pipeline <pipeline_name> table <table_id>\n" 4144 " meter profile <meter_profile_id> delete\n"; 4145 4146 static void 4147 cmd_pipeline_table_meter_profile_delete(char **tokens, 4148 uint32_t n_tokens, 4149 char *out, 4150 size_t out_size) 4151 { 4152 char *pipeline_name; 4153 uint32_t table_id, meter_profile_id; 4154 int status; 4155 4156 if (n_tokens != 8) { 4157 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 4158 return; 4159 } 4160 4161 pipeline_name = tokens[1]; 4162 4163 if (strcmp(tokens[2], "table") != 0) { 4164 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port"); 4165 return; 4166 } 4167 4168 if (parser_read_uint32(&table_id, tokens[3]) != 0) { 4169 snprintf(out, out_size, MSG_ARG_INVALID, "table_id"); 4170 return; 4171 } 4172 4173 if (strcmp(tokens[4], "meter") != 0) { 4174 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "meter"); 4175 return; 4176 } 4177 4178 if (strcmp(tokens[5], "profile") != 0) { 4179 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "profile"); 4180 return; 4181 } 4182 4183 if (parser_read_uint32(&meter_profile_id, tokens[6]) != 0) { 4184 snprintf(out, out_size, MSG_ARG_INVALID, "meter_profile_id"); 4185 return; 4186 } 4187 4188 if (strcmp(tokens[7], "delete") != 0) { 4189 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "delete"); 4190 return; 4191 } 4192 4193 status = pipeline_table_mtr_profile_delete(pipeline_name, 4194 table_id, 4195 meter_profile_id); 4196 if (status) { 4197 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 4198 return; 4199 } 4200 } 4201 4202 4203 static const char cmd_pipeline_table_rule_meter_read_help[] = 4204 "pipeline <pipeline_name> table <table_id> rule read meter [clear]\n"; 4205 4206 static void 4207 cmd_pipeline_table_rule_meter_read(char **tokens, 4208 uint32_t n_tokens __rte_unused, 4209 char *out, 4210 size_t out_size) 4211 { 4212 snprintf(out, out_size, MSG_CMD_UNIMPLEM, tokens[0]); 4213 } 4214 4215 4216 static const char cmd_pipeline_table_dscp_help[] = 4217 "pipeline <pipeline_name> table <table_id> dscp <file_name>\n" 4218 "\n" 4219 " File <file_name>:\n" 4220 " - exactly 64 lines\n" 4221 " - line format: <tc_id> <tc_queue_id> <color>, with <color> as: g | y | r\n"; 4222 4223 static int 4224 load_dscp_table(struct rte_table_action_dscp_table *dscp_table, 4225 const char *file_name, 4226 uint32_t *line_number) 4227 { 4228 FILE *f = NULL; 4229 uint32_t dscp, l; 4230 4231 /* Check input arguments */ 4232 if ((dscp_table == NULL) || 4233 (file_name == NULL) || 4234 (line_number == NULL)) { 4235 if (line_number) 4236 *line_number = 0; 4237 return -EINVAL; 4238 } 4239 4240 /* Open input file */ 4241 f = fopen(file_name, "r"); 4242 if (f == NULL) { 4243 *line_number = 0; 4244 return -EINVAL; 4245 } 4246 4247 /* Read file */ 4248 for (dscp = 0, l = 1; ; l++) { 4249 char line[64]; 4250 char *tokens[3]; 4251 enum rte_meter_color color; 4252 uint32_t tc_id, tc_queue_id, n_tokens = RTE_DIM(tokens); 4253 4254 if (fgets(line, sizeof(line), f) == NULL) 4255 break; 4256 4257 if (is_comment(line)) 4258 continue; 4259 4260 if (parse_tokenize_string(line, tokens, &n_tokens)) { 4261 *line_number = l; 4262 fclose(f); 4263 return -EINVAL; 4264 } 4265 4266 if (n_tokens == 0) 4267 continue; 4268 4269 if ((dscp >= RTE_DIM(dscp_table->entry)) || 4270 (n_tokens != RTE_DIM(tokens)) || 4271 parser_read_uint32(&tc_id, tokens[0]) || 4272 (tc_id >= RTE_TABLE_ACTION_TC_MAX) || 4273 parser_read_uint32(&tc_queue_id, tokens[1]) || 4274 (tc_queue_id >= RTE_TABLE_ACTION_TC_QUEUE_MAX) || 4275 (strlen(tokens[2]) != 1)) { 4276 *line_number = l; 4277 fclose(f); 4278 return -EINVAL; 4279 } 4280 4281 switch (tokens[2][0]) { 4282 case 'g': 4283 case 'G': 4284 color = e_RTE_METER_GREEN; 4285 break; 4286 4287 case 'y': 4288 case 'Y': 4289 color = e_RTE_METER_YELLOW; 4290 break; 4291 4292 case 'r': 4293 case 'R': 4294 color = e_RTE_METER_RED; 4295 break; 4296 4297 default: 4298 *line_number = l; 4299 fclose(f); 4300 return -EINVAL; 4301 } 4302 4303 dscp_table->entry[dscp].tc_id = tc_id; 4304 dscp_table->entry[dscp].tc_queue_id = tc_queue_id; 4305 dscp_table->entry[dscp].color = color; 4306 dscp++; 4307 } 4308 4309 /* Close file */ 4310 fclose(f); 4311 return 0; 4312 } 4313 4314 static void 4315 cmd_pipeline_table_dscp(char **tokens, 4316 uint32_t n_tokens, 4317 char *out, 4318 size_t out_size) 4319 { 4320 struct rte_table_action_dscp_table dscp_table; 4321 char *pipeline_name, *file_name; 4322 uint32_t table_id, line_number; 4323 int status; 4324 4325 if (n_tokens != 6) { 4326 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 4327 return; 4328 } 4329 4330 pipeline_name = tokens[1]; 4331 4332 if (strcmp(tokens[2], "table") != 0) { 4333 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port"); 4334 return; 4335 } 4336 4337 if (parser_read_uint32(&table_id, tokens[3]) != 0) { 4338 snprintf(out, out_size, MSG_ARG_INVALID, "table_id"); 4339 return; 4340 } 4341 4342 if (strcmp(tokens[4], "dscp") != 0) { 4343 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "dscp"); 4344 return; 4345 } 4346 4347 file_name = tokens[5]; 4348 4349 status = load_dscp_table(&dscp_table, file_name, &line_number); 4350 if (status) { 4351 snprintf(out, out_size, MSG_FILE_ERR, file_name, line_number); 4352 return; 4353 } 4354 4355 status = pipeline_table_dscp_table_update(pipeline_name, 4356 table_id, 4357 UINT64_MAX, 4358 &dscp_table); 4359 if (status) { 4360 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 4361 return; 4362 } 4363 } 4364 4365 4366 static const char cmd_pipeline_table_rule_ttl_read_help[] = 4367 "pipeline <pipeline_name> table <table_id> rule read ttl [clear]\n"; 4368 4369 static void 4370 cmd_pipeline_table_rule_ttl_read(char **tokens, 4371 uint32_t n_tokens __rte_unused, 4372 char *out, 4373 size_t out_size) 4374 { 4375 snprintf(out, out_size, MSG_CMD_UNIMPLEM, tokens[0]); 4376 } 4377 4378 4379 static const char cmd_thread_pipeline_enable_help[] = 4380 "thread <thread_id> pipeline <pipeline_name> enable\n"; 4381 4382 static void 4383 cmd_thread_pipeline_enable(char **tokens, 4384 uint32_t n_tokens, 4385 char *out, 4386 size_t out_size) 4387 { 4388 char *pipeline_name; 4389 uint32_t thread_id; 4390 int status; 4391 4392 if (n_tokens != 5) { 4393 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 4394 return; 4395 } 4396 4397 if (parser_read_uint32(&thread_id, tokens[1]) != 0) { 4398 snprintf(out, out_size, MSG_ARG_INVALID, "thread_id"); 4399 return; 4400 } 4401 4402 if (strcmp(tokens[2], "pipeline") != 0) { 4403 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pipeline"); 4404 return; 4405 } 4406 4407 pipeline_name = tokens[3]; 4408 4409 if (strcmp(tokens[4], "enable") != 0) { 4410 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "enable"); 4411 return; 4412 } 4413 4414 status = thread_pipeline_enable(thread_id, pipeline_name); 4415 if (status) { 4416 snprintf(out, out_size, MSG_CMD_FAIL, "thread pipeline enable"); 4417 return; 4418 } 4419 } 4420 4421 4422 static const char cmd_thread_pipeline_disable_help[] = 4423 "thread <thread_id> pipeline <pipeline_name> disable\n"; 4424 4425 static void 4426 cmd_thread_pipeline_disable(char **tokens, 4427 uint32_t n_tokens, 4428 char *out, 4429 size_t out_size) 4430 { 4431 char *pipeline_name; 4432 uint32_t thread_id; 4433 int status; 4434 4435 if (n_tokens != 5) { 4436 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 4437 return; 4438 } 4439 4440 if (parser_read_uint32(&thread_id, tokens[1]) != 0) { 4441 snprintf(out, out_size, MSG_ARG_INVALID, "thread_id"); 4442 return; 4443 } 4444 4445 if (strcmp(tokens[2], "pipeline") != 0) { 4446 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pipeline"); 4447 return; 4448 } 4449 4450 pipeline_name = tokens[3]; 4451 4452 if (strcmp(tokens[4], "disable") != 0) { 4453 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "disable"); 4454 return; 4455 } 4456 4457 status = thread_pipeline_disable(thread_id, pipeline_name); 4458 if (status) { 4459 snprintf(out, out_size, MSG_CMD_FAIL, 4460 "thread pipeline disable"); 4461 return; 4462 } 4463 } 4464 4465 static void 4466 cmd_help(char **tokens, uint32_t n_tokens, char *out, size_t out_size) 4467 { 4468 tokens++; 4469 n_tokens--; 4470 4471 if (n_tokens == 0) { 4472 snprintf(out, out_size, 4473 "Type 'help <command>' for details on each command.\n\n" 4474 "List of commands:\n" 4475 "\tmempool\n" 4476 "\tlink\n" 4477 "\tswq\n" 4478 "\ttmgr subport profile\n" 4479 "\ttmgr pipe profile\n" 4480 "\ttmgr\n" 4481 "\ttmgr subport\n" 4482 "\ttmgr subport pipe\n" 4483 "\ttap\n" 4484 "\tkni\n" 4485 "\tport in action profile\n" 4486 "\ttable action profile\n" 4487 "\tpipeline\n" 4488 "\tpipeline port in\n" 4489 "\tpipeline port out\n" 4490 "\tpipeline table\n" 4491 "\tpipeline port in table\n" 4492 "\tpipeline port in stats\n" 4493 "\tpipeline port in enable\n" 4494 "\tpipeline port in disable\n" 4495 "\tpipeline port out stats\n" 4496 "\tpipeline table stats\n" 4497 "\tpipeline table rule add\n" 4498 "\tpipeline table rule add default\n" 4499 "\tpipeline table rule add bulk\n" 4500 "\tpipeline table rule delete\n" 4501 "\tpipeline table rule delete default\n" 4502 "\tpipeline table rule stats read\n" 4503 "\tpipeline table meter profile add\n" 4504 "\tpipeline table meter profile delete\n" 4505 "\tpipeline table rule meter read\n" 4506 "\tpipeline table dscp\n" 4507 "\tpipeline table rule ttl read\n" 4508 "\tthread pipeline enable\n" 4509 "\tthread pipeline disable\n\n"); 4510 return; 4511 } 4512 4513 if (strcmp(tokens[0], "mempool") == 0) { 4514 snprintf(out, out_size, "\n%s\n", cmd_mempool_help); 4515 return; 4516 } 4517 4518 if (strcmp(tokens[0], "link") == 0) { 4519 snprintf(out, out_size, "\n%s\n", cmd_link_help); 4520 return; 4521 } 4522 4523 if (strcmp(tokens[0], "swq") == 0) { 4524 snprintf(out, out_size, "\n%s\n", cmd_swq_help); 4525 return; 4526 } 4527 4528 if (strcmp(tokens[0], "tmgr") == 0) { 4529 if (n_tokens == 1) { 4530 snprintf(out, out_size, "\n%s\n", cmd_tmgr_help); 4531 return; 4532 } 4533 4534 if ((n_tokens == 2) && 4535 (strcmp(tokens[1], "subport")) == 0) { 4536 snprintf(out, out_size, "\n%s\n", cmd_tmgr_subport_help); 4537 return; 4538 } 4539 4540 if ((n_tokens == 3) && 4541 (strcmp(tokens[1], "subport") == 0) && 4542 (strcmp(tokens[2], "profile") == 0)) { 4543 snprintf(out, out_size, "\n%s\n", 4544 cmd_tmgr_subport_profile_help); 4545 return; 4546 } 4547 4548 if ((n_tokens == 3) && 4549 (strcmp(tokens[1], "subport") == 0) && 4550 (strcmp(tokens[2], "pipe") == 0)) { 4551 snprintf(out, out_size, "\n%s\n", cmd_tmgr_subport_pipe_help); 4552 return; 4553 } 4554 4555 if ((n_tokens == 3) && 4556 (strcmp(tokens[1], "pipe") == 0) && 4557 (strcmp(tokens[2], "profile") == 0)) { 4558 snprintf(out, out_size, "\n%s\n", cmd_tmgr_pipe_profile_help); 4559 return; 4560 } 4561 } 4562 4563 if (strcmp(tokens[0], "tap") == 0) { 4564 snprintf(out, out_size, "\n%s\n", cmd_tap_help); 4565 return; 4566 } 4567 4568 if (strcmp(tokens[0], "kni") == 0) { 4569 snprintf(out, out_size, "\n%s\n", cmd_kni_help); 4570 return; 4571 } 4572 4573 if ((n_tokens == 4) && 4574 (strcmp(tokens[0], "port") == 0) && 4575 (strcmp(tokens[1], "in") == 0) && 4576 (strcmp(tokens[2], "action") == 0) && 4577 (strcmp(tokens[3], "profile") == 0)) { 4578 snprintf(out, out_size, "\n%s\n", cmd_port_in_action_profile_help); 4579 return; 4580 } 4581 4582 if ((n_tokens == 3) && 4583 (strcmp(tokens[0], "table") == 0) && 4584 (strcmp(tokens[1], "action") == 0) && 4585 (strcmp(tokens[2], "profile") == 0)) { 4586 snprintf(out, out_size, "\n%s\n", cmd_table_action_profile_help); 4587 return; 4588 } 4589 4590 if ((strcmp(tokens[0], "pipeline") == 0) && (n_tokens == 1)) { 4591 snprintf(out, out_size, "\n%s\n", cmd_pipeline_help); 4592 return; 4593 } 4594 4595 if ((strcmp(tokens[0], "pipeline") == 0) && 4596 (strcmp(tokens[1], "port") == 0)) { 4597 if ((n_tokens == 3) && (strcmp(tokens[2], "in")) == 0) { 4598 snprintf(out, out_size, "\n%s\n", cmd_pipeline_port_in_help); 4599 return; 4600 } 4601 4602 if ((n_tokens == 3) && (strcmp(tokens[2], "out")) == 0) { 4603 snprintf(out, out_size, "\n%s\n", cmd_pipeline_port_out_help); 4604 return; 4605 } 4606 4607 if ((n_tokens == 4) && 4608 (strcmp(tokens[2], "in") == 0) && 4609 (strcmp(tokens[3], "table") == 0)) { 4610 snprintf(out, out_size, "\n%s\n", 4611 cmd_pipeline_port_in_table_help); 4612 return; 4613 } 4614 4615 if ((n_tokens == 4) && 4616 (strcmp(tokens[2], "in") == 0) && 4617 (strcmp(tokens[3], "stats") == 0)) { 4618 snprintf(out, out_size, "\n%s\n", 4619 cmd_pipeline_port_in_stats_help); 4620 return; 4621 } 4622 4623 if ((n_tokens == 4) && 4624 (strcmp(tokens[2], "in") == 0) && 4625 (strcmp(tokens[3], "enable") == 0)) { 4626 snprintf(out, out_size, "\n%s\n", 4627 cmd_pipeline_port_in_enable_help); 4628 return; 4629 } 4630 4631 if ((n_tokens == 4) && 4632 (strcmp(tokens[2], "in") == 0) && 4633 (strcmp(tokens[3], "disable") == 0)) { 4634 snprintf(out, out_size, "\n%s\n", 4635 cmd_pipeline_port_in_disable_help); 4636 return; 4637 } 4638 4639 if ((n_tokens == 4) && 4640 (strcmp(tokens[2], "out") == 0) && 4641 (strcmp(tokens[3], "stats") == 0)) { 4642 snprintf(out, out_size, "\n%s\n", 4643 cmd_pipeline_port_out_stats_help); 4644 return; 4645 } 4646 } 4647 4648 if ((strcmp(tokens[0], "pipeline") == 0) && 4649 (strcmp(tokens[1], "table") == 0)) { 4650 if (n_tokens == 2) { 4651 snprintf(out, out_size, "\n%s\n", cmd_pipeline_table_help); 4652 return; 4653 } 4654 4655 if ((n_tokens == 3) && strcmp(tokens[2], "stats") == 0) { 4656 snprintf(out, out_size, "\n%s\n", 4657 cmd_pipeline_table_stats_help); 4658 return; 4659 } 4660 4661 if ((n_tokens == 3) && strcmp(tokens[2], "dscp") == 0) { 4662 snprintf(out, out_size, "\n%s\n", 4663 cmd_pipeline_table_dscp_help); 4664 return; 4665 } 4666 4667 if ((n_tokens == 4) && 4668 (strcmp(tokens[2], "rule") == 0) && 4669 (strcmp(tokens[3], "add") == 0)) { 4670 snprintf(out, out_size, "\n%s\n", 4671 cmd_pipeline_table_rule_add_help); 4672 return; 4673 } 4674 4675 if ((n_tokens == 5) && 4676 (strcmp(tokens[2], "rule") == 0) && 4677 (strcmp(tokens[3], "add") == 0) && 4678 (strcmp(tokens[4], "default") == 0)) { 4679 snprintf(out, out_size, "\n%s\n", 4680 cmd_pipeline_table_rule_add_default_help); 4681 return; 4682 } 4683 4684 if ((n_tokens == 5) && 4685 (strcmp(tokens[2], "rule") == 0) && 4686 (strcmp(tokens[3], "add") == 0) && 4687 (strcmp(tokens[4], "bulk") == 0)) { 4688 snprintf(out, out_size, "\n%s\n", 4689 cmd_pipeline_table_rule_add_bulk_help); 4690 return; 4691 } 4692 4693 if ((n_tokens == 4) && 4694 (strcmp(tokens[2], "rule") == 0) && 4695 (strcmp(tokens[3], "delete") == 0)) { 4696 snprintf(out, out_size, "\n%s\n", 4697 cmd_pipeline_table_rule_delete_help); 4698 return; 4699 } 4700 4701 if ((n_tokens == 5) && 4702 (strcmp(tokens[2], "rule") == 0) && 4703 (strcmp(tokens[3], "delete") == 0) && 4704 (strcmp(tokens[4], "default") == 0)) { 4705 snprintf(out, out_size, "\n%s\n", 4706 cmd_pipeline_table_rule_delete_default_help); 4707 return; 4708 } 4709 4710 if ((n_tokens == 5) && 4711 (strcmp(tokens[2], "rule") == 0) && 4712 (strcmp(tokens[3], "stats") == 0) && 4713 (strcmp(tokens[4], "read") == 0)) { 4714 snprintf(out, out_size, "\n%s\n", 4715 cmd_pipeline_table_rule_stats_read_help); 4716 return; 4717 } 4718 4719 if ((n_tokens == 5) && 4720 (strcmp(tokens[2], "meter") == 0) && 4721 (strcmp(tokens[3], "profile") == 0) && 4722 (strcmp(tokens[4], "add") == 0)) { 4723 snprintf(out, out_size, "\n%s\n", 4724 cmd_pipeline_table_meter_profile_add_help); 4725 return; 4726 } 4727 4728 if ((n_tokens == 5) && 4729 (strcmp(tokens[2], "meter") == 0) && 4730 (strcmp(tokens[3], "profile") == 0) && 4731 (strcmp(tokens[4], "delete") == 0)) { 4732 snprintf(out, out_size, "\n%s\n", 4733 cmd_pipeline_table_meter_profile_delete_help); 4734 return; 4735 } 4736 4737 if ((n_tokens == 5) && 4738 (strcmp(tokens[2], "rule") == 0) && 4739 (strcmp(tokens[3], "meter") == 0) && 4740 (strcmp(tokens[4], "read") == 0)) { 4741 snprintf(out, out_size, "\n%s\n", 4742 cmd_pipeline_table_rule_meter_read_help); 4743 return; 4744 } 4745 4746 if ((n_tokens == 5) && 4747 (strcmp(tokens[2], "rule") == 0) && 4748 (strcmp(tokens[3], "ttl") == 0) && 4749 (strcmp(tokens[4], "read") == 0)) { 4750 snprintf(out, out_size, "\n%s\n", 4751 cmd_pipeline_table_rule_ttl_read_help); 4752 return; 4753 } 4754 } 4755 4756 if ((n_tokens == 3) && 4757 (strcmp(tokens[0], "thread") == 0) && 4758 (strcmp(tokens[1], "pipeline") == 0)) { 4759 if (strcmp(tokens[2], "enable") == 0) { 4760 snprintf(out, out_size, "\n%s\n", 4761 cmd_thread_pipeline_enable_help); 4762 return; 4763 } 4764 4765 if (strcmp(tokens[2], "disable") == 0) { 4766 snprintf(out, out_size, "\n%s\n", 4767 cmd_thread_pipeline_disable_help); 4768 return; 4769 } 4770 } 4771 4772 snprintf(out, out_size, "Invalid command\n"); 4773 } 4774 4775 void 4776 cli_process(char *in, char *out, size_t out_size) 4777 { 4778 char *tokens[CMD_MAX_TOKENS]; 4779 uint32_t n_tokens = RTE_DIM(tokens); 4780 int status; 4781 4782 if (is_comment(in)) 4783 return; 4784 4785 status = parse_tokenize_string(in, tokens, &n_tokens); 4786 if (status) { 4787 snprintf(out, out_size, MSG_ARG_TOO_MANY, ""); 4788 return; 4789 } 4790 4791 if (n_tokens == 0) 4792 return; 4793 4794 if (strcmp(tokens[0], "help") == 0) { 4795 cmd_help(tokens, n_tokens, out, out_size); 4796 return; 4797 } 4798 4799 if (strcmp(tokens[0], "mempool") == 0) { 4800 cmd_mempool(tokens, n_tokens, out, out_size); 4801 return; 4802 } 4803 4804 if (strcmp(tokens[0], "link") == 0) { 4805 if (strcmp(tokens[1], "show") == 0) { 4806 cmd_link_show(tokens, n_tokens, out, out_size); 4807 return; 4808 } 4809 4810 cmd_link(tokens, n_tokens, out, out_size); 4811 return; 4812 } 4813 4814 if (strcmp(tokens[0], "swq") == 0) { 4815 cmd_swq(tokens, n_tokens, out, out_size); 4816 return; 4817 } 4818 4819 if (strcmp(tokens[0], "tmgr") == 0) { 4820 if ((n_tokens >= 3) && 4821 (strcmp(tokens[1], "subport") == 0) && 4822 (strcmp(tokens[2], "profile") == 0)) { 4823 cmd_tmgr_subport_profile(tokens, n_tokens, 4824 out, out_size); 4825 return; 4826 } 4827 4828 if ((n_tokens >= 3) && 4829 (strcmp(tokens[1], "pipe") == 0) && 4830 (strcmp(tokens[2], "profile") == 0)) { 4831 cmd_tmgr_pipe_profile(tokens, n_tokens, out, out_size); 4832 return; 4833 } 4834 4835 if ((n_tokens >= 5) && 4836 (strcmp(tokens[2], "subport") == 0) && 4837 (strcmp(tokens[4], "profile") == 0)) { 4838 cmd_tmgr_subport(tokens, n_tokens, out, out_size); 4839 return; 4840 } 4841 4842 if ((n_tokens >= 5) && 4843 (strcmp(tokens[2], "subport") == 0) && 4844 (strcmp(tokens[4], "pipe") == 0)) { 4845 cmd_tmgr_subport_pipe(tokens, n_tokens, out, out_size); 4846 return; 4847 } 4848 4849 cmd_tmgr(tokens, n_tokens, out, out_size); 4850 return; 4851 } 4852 4853 if (strcmp(tokens[0], "tap") == 0) { 4854 cmd_tap(tokens, n_tokens, out, out_size); 4855 return; 4856 } 4857 4858 if (strcmp(tokens[0], "kni") == 0) { 4859 cmd_kni(tokens, n_tokens, out, out_size); 4860 return; 4861 } 4862 4863 if (strcmp(tokens[0], "port") == 0) { 4864 cmd_port_in_action_profile(tokens, n_tokens, out, out_size); 4865 return; 4866 } 4867 4868 if (strcmp(tokens[0], "table") == 0) { 4869 cmd_table_action_profile(tokens, n_tokens, out, out_size); 4870 return; 4871 } 4872 4873 if (strcmp(tokens[0], "pipeline") == 0) { 4874 if ((n_tokens >= 3) && 4875 (strcmp(tokens[2], "period") == 0)) { 4876 cmd_pipeline(tokens, n_tokens, out, out_size); 4877 return; 4878 } 4879 4880 if ((n_tokens >= 5) && 4881 (strcmp(tokens[2], "port") == 0) && 4882 (strcmp(tokens[3], "in") == 0) && 4883 (strcmp(tokens[4], "bsz") == 0)) { 4884 cmd_pipeline_port_in(tokens, n_tokens, out, out_size); 4885 return; 4886 } 4887 4888 if ((n_tokens >= 5) && 4889 (strcmp(tokens[2], "port") == 0) && 4890 (strcmp(tokens[3], "out") == 0) && 4891 (strcmp(tokens[4], "bsz") == 0)) { 4892 cmd_pipeline_port_out(tokens, n_tokens, out, out_size); 4893 return; 4894 } 4895 4896 if ((n_tokens >= 4) && 4897 (strcmp(tokens[2], "table") == 0) && 4898 (strcmp(tokens[3], "match") == 0)) { 4899 cmd_pipeline_table(tokens, n_tokens, out, out_size); 4900 return; 4901 } 4902 4903 if ((n_tokens >= 6) && 4904 (strcmp(tokens[2], "port") == 0) && 4905 (strcmp(tokens[3], "in") == 0) && 4906 (strcmp(tokens[5], "table") == 0)) { 4907 cmd_pipeline_port_in_table(tokens, n_tokens, 4908 out, out_size); 4909 return; 4910 } 4911 4912 if ((n_tokens >= 6) && 4913 (strcmp(tokens[2], "port") == 0) && 4914 (strcmp(tokens[3], "in") == 0) && 4915 (strcmp(tokens[5], "stats") == 0)) { 4916 cmd_pipeline_port_in_stats(tokens, n_tokens, 4917 out, out_size); 4918 return; 4919 } 4920 4921 if ((n_tokens >= 6) && 4922 (strcmp(tokens[2], "port") == 0) && 4923 (strcmp(tokens[3], "in") == 0) && 4924 (strcmp(tokens[5], "enable") == 0)) { 4925 cmd_pipeline_port_in_enable(tokens, n_tokens, 4926 out, out_size); 4927 return; 4928 } 4929 4930 if ((n_tokens >= 6) && 4931 (strcmp(tokens[2], "port") == 0) && 4932 (strcmp(tokens[3], "in") == 0) && 4933 (strcmp(tokens[5], "disable") == 0)) { 4934 cmd_pipeline_port_in_disable(tokens, n_tokens, 4935 out, out_size); 4936 return; 4937 } 4938 4939 if ((n_tokens >= 6) && 4940 (strcmp(tokens[2], "port") == 0) && 4941 (strcmp(tokens[3], "out") == 0) && 4942 (strcmp(tokens[5], "stats") == 0)) { 4943 cmd_pipeline_port_out_stats(tokens, n_tokens, 4944 out, out_size); 4945 return; 4946 } 4947 4948 if ((n_tokens >= 5) && 4949 (strcmp(tokens[2], "table") == 0) && 4950 (strcmp(tokens[4], "stats") == 0)) { 4951 cmd_pipeline_table_stats(tokens, n_tokens, 4952 out, out_size); 4953 return; 4954 } 4955 4956 if ((n_tokens >= 7) && 4957 (strcmp(tokens[2], "table") == 0) && 4958 (strcmp(tokens[4], "rule") == 0) && 4959 (strcmp(tokens[5], "add") == 0) && 4960 (strcmp(tokens[6], "match") == 0)) { 4961 if ((n_tokens >= 8) && 4962 (strcmp(tokens[7], "default") == 0)) { 4963 cmd_pipeline_table_rule_add_default(tokens, 4964 n_tokens, out, out_size); 4965 return; 4966 } 4967 4968 cmd_pipeline_table_rule_add(tokens, n_tokens, 4969 out, out_size); 4970 return; 4971 } 4972 4973 if ((n_tokens >= 7) && 4974 (strcmp(tokens[2], "table") == 0) && 4975 (strcmp(tokens[4], "rule") == 0) && 4976 (strcmp(tokens[5], "add") == 0) && 4977 (strcmp(tokens[6], "bulk") == 0)) { 4978 cmd_pipeline_table_rule_add_bulk(tokens, 4979 n_tokens, out, out_size); 4980 return; 4981 } 4982 4983 if ((n_tokens >= 7) && 4984 (strcmp(tokens[2], "table") == 0) && 4985 (strcmp(tokens[4], "rule") == 0) && 4986 (strcmp(tokens[5], "delete") == 0) && 4987 (strcmp(tokens[6], "match") == 0)) { 4988 if ((n_tokens >= 8) && 4989 (strcmp(tokens[7], "default") == 0)) { 4990 cmd_pipeline_table_rule_delete_default(tokens, 4991 n_tokens, out, out_size); 4992 return; 4993 } 4994 4995 cmd_pipeline_table_rule_delete(tokens, n_tokens, 4996 out, out_size); 4997 return; 4998 } 4999 5000 if ((n_tokens >= 7) && 5001 (strcmp(tokens[2], "table") == 0) && 5002 (strcmp(tokens[4], "rule") == 0) && 5003 (strcmp(tokens[5], "read") == 0) && 5004 (strcmp(tokens[6], "stats") == 0)) { 5005 cmd_pipeline_table_rule_stats_read(tokens, n_tokens, 5006 out, out_size); 5007 return; 5008 } 5009 5010 if ((n_tokens >= 8) && 5011 (strcmp(tokens[2], "table") == 0) && 5012 (strcmp(tokens[4], "meter") == 0) && 5013 (strcmp(tokens[5], "profile") == 0) && 5014 (strcmp(tokens[7], "add") == 0)) { 5015 cmd_pipeline_table_meter_profile_add(tokens, n_tokens, 5016 out, out_size); 5017 return; 5018 } 5019 5020 if ((n_tokens >= 8) && 5021 (strcmp(tokens[2], "table") == 0) && 5022 (strcmp(tokens[4], "meter") == 0) && 5023 (strcmp(tokens[5], "profile") == 0) && 5024 (strcmp(tokens[7], "delete") == 0)) { 5025 cmd_pipeline_table_meter_profile_delete(tokens, 5026 n_tokens, out, out_size); 5027 return; 5028 } 5029 5030 if ((n_tokens >= 7) && 5031 (strcmp(tokens[2], "table") == 0) && 5032 (strcmp(tokens[4], "rule") == 0) && 5033 (strcmp(tokens[5], "read") == 0) && 5034 (strcmp(tokens[6], "meter") == 0)) { 5035 cmd_pipeline_table_rule_meter_read(tokens, n_tokens, 5036 out, out_size); 5037 return; 5038 } 5039 5040 if ((n_tokens >= 5) && 5041 (strcmp(tokens[2], "table") == 0) && 5042 (strcmp(tokens[4], "dscp") == 0)) { 5043 cmd_pipeline_table_dscp(tokens, n_tokens, 5044 out, out_size); 5045 return; 5046 } 5047 5048 if ((n_tokens >= 7) && 5049 (strcmp(tokens[2], "table") == 0) && 5050 (strcmp(tokens[4], "rule") == 0) && 5051 (strcmp(tokens[5], "read") == 0) && 5052 (strcmp(tokens[6], "ttl") == 0)) { 5053 cmd_pipeline_table_rule_ttl_read(tokens, n_tokens, 5054 out, out_size); 5055 return; 5056 } 5057 } 5058 5059 if (strcmp(tokens[0], "thread") == 0) { 5060 if ((n_tokens >= 5) && 5061 (strcmp(tokens[4], "enable") == 0)) { 5062 cmd_thread_pipeline_enable(tokens, n_tokens, 5063 out, out_size); 5064 return; 5065 } 5066 5067 if ((n_tokens >= 5) && 5068 (strcmp(tokens[4], "disable") == 0)) { 5069 cmd_thread_pipeline_disable(tokens, n_tokens, 5070 out, out_size); 5071 return; 5072 } 5073 } 5074 5075 snprintf(out, out_size, MSG_CMD_UNKNOWN, tokens[0]); 5076 } 5077 5078 int 5079 cli_script_process(const char *file_name, 5080 size_t msg_in_len_max, 5081 size_t msg_out_len_max) 5082 { 5083 char *msg_in = NULL, *msg_out = NULL; 5084 FILE *f = NULL; 5085 5086 /* Check input arguments */ 5087 if ((file_name == NULL) || 5088 (strlen(file_name) == 0) || 5089 (msg_in_len_max == 0) || 5090 (msg_out_len_max == 0)) 5091 return -EINVAL; 5092 5093 msg_in = malloc(msg_in_len_max + 1); 5094 msg_out = malloc(msg_out_len_max + 1); 5095 if ((msg_in == NULL) || 5096 (msg_out == NULL)) { 5097 free(msg_out); 5098 free(msg_in); 5099 return -ENOMEM; 5100 } 5101 5102 /* Open input file */ 5103 f = fopen(file_name, "r"); 5104 if (f == NULL) { 5105 free(msg_out); 5106 free(msg_in); 5107 return -EIO; 5108 } 5109 5110 /* Read file */ 5111 for ( ; ; ) { 5112 if (fgets(msg_in, msg_in_len_max + 1, f) == NULL) 5113 break; 5114 5115 printf("%s", msg_in); 5116 msg_out[0] = 0; 5117 5118 cli_process(msg_in, 5119 msg_out, 5120 msg_out_len_max); 5121 5122 if (strlen(msg_out)) 5123 printf("%s", msg_out); 5124 } 5125 5126 /* Close file */ 5127 fclose(f); 5128 free(msg_out); 5129 free(msg_in); 5130 return 0; 5131 } 5132 5133 static int 5134 cli_rule_file_process(const char *file_name, 5135 size_t line_len_max, 5136 struct table_rule_match *m, 5137 struct table_rule_action *a, 5138 uint32_t *n_rules, 5139 uint32_t *line_number, 5140 char *out, 5141 size_t out_size) 5142 { 5143 FILE *f = NULL; 5144 char *line = NULL; 5145 uint32_t rule_id, line_id; 5146 int status = 0; 5147 5148 /* Check input arguments */ 5149 if ((file_name == NULL) || 5150 (strlen(file_name) == 0) || 5151 (line_len_max == 0)) { 5152 *line_number = 0; 5153 return -EINVAL; 5154 } 5155 5156 /* Memory allocation */ 5157 line = malloc(line_len_max + 1); 5158 if (line == NULL) { 5159 *line_number = 0; 5160 return -ENOMEM; 5161 } 5162 5163 /* Open file */ 5164 f = fopen(file_name, "r"); 5165 if (f == NULL) { 5166 *line_number = 0; 5167 free(line); 5168 return -EIO; 5169 } 5170 5171 /* Read file */ 5172 for (line_id = 1, rule_id = 0; rule_id < *n_rules; line_id++) { 5173 char *tokens[CMD_MAX_TOKENS]; 5174 uint32_t n_tokens, n_tokens_parsed, t0; 5175 5176 /* Read next line from file. */ 5177 if (fgets(line, line_len_max + 1, f) == NULL) 5178 break; 5179 5180 /* Comment. */ 5181 if (is_comment(line)) 5182 continue; 5183 5184 /* Parse line. */ 5185 n_tokens = RTE_DIM(tokens); 5186 status = parse_tokenize_string(line, tokens, &n_tokens); 5187 if (status) { 5188 status = -EINVAL; 5189 break; 5190 } 5191 5192 /* Empty line. */ 5193 if (n_tokens == 0) 5194 continue; 5195 t0 = 0; 5196 5197 /* Rule match. */ 5198 n_tokens_parsed = parse_match(tokens + t0, 5199 n_tokens - t0, 5200 out, 5201 out_size, 5202 &m[rule_id]); 5203 if (n_tokens_parsed == 0) { 5204 status = -EINVAL; 5205 break; 5206 } 5207 t0 += n_tokens_parsed; 5208 5209 /* Rule action. */ 5210 n_tokens_parsed = parse_table_action(tokens + t0, 5211 n_tokens - t0, 5212 out, 5213 out_size, 5214 &a[rule_id]); 5215 if (n_tokens_parsed == 0) { 5216 status = -EINVAL; 5217 break; 5218 } 5219 t0 += n_tokens_parsed; 5220 5221 /* Line completed. */ 5222 if (t0 < n_tokens) { 5223 status = -EINVAL; 5224 break; 5225 } 5226 5227 /* Increment rule count */ 5228 rule_id++; 5229 } 5230 5231 /* Close file */ 5232 fclose(f); 5233 5234 /* Memory free */ 5235 free(line); 5236 5237 *n_rules = rule_id; 5238 *line_number = line_id; 5239 return status; 5240 } 5241