1 /*- 2 * BSD LICENSE 3 * 4 * Copyright 2016 6WIND S.A. 5 * Copyright 2016 Mellanox. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * * Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * * Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in 15 * the documentation and/or other materials provided with the 16 * distribution. 17 * * Neither the name of 6WIND S.A. nor the names of its 18 * contributors may be used to endorse or promote products derived 19 * from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 #include <stddef.h> 35 #include <stdint.h> 36 #include <stdio.h> 37 #include <inttypes.h> 38 #include <errno.h> 39 #include <ctype.h> 40 #include <string.h> 41 #include <arpa/inet.h> 42 #include <sys/socket.h> 43 44 #include <rte_common.h> 45 #include <rte_ethdev.h> 46 #include <rte_byteorder.h> 47 #include <cmdline_parse.h> 48 #include <cmdline_parse_etheraddr.h> 49 #include <rte_flow.h> 50 51 #include "testpmd.h" 52 53 /** Parser token indices. */ 54 enum index { 55 /* Special tokens. */ 56 ZERO = 0, 57 END, 58 59 /* Common tokens. */ 60 INTEGER, 61 UNSIGNED, 62 PREFIX, 63 BOOLEAN, 64 STRING, 65 MAC_ADDR, 66 IPV4_ADDR, 67 IPV6_ADDR, 68 RULE_ID, 69 PORT_ID, 70 GROUP_ID, 71 PRIORITY_LEVEL, 72 73 /* Top-level command. */ 74 FLOW, 75 76 /* Sub-level commands. */ 77 VALIDATE, 78 CREATE, 79 DESTROY, 80 FLUSH, 81 QUERY, 82 LIST, 83 84 /* Destroy arguments. */ 85 DESTROY_RULE, 86 87 /* Query arguments. */ 88 QUERY_ACTION, 89 90 /* List arguments. */ 91 LIST_GROUP, 92 93 /* Validate/create arguments. */ 94 GROUP, 95 PRIORITY, 96 INGRESS, 97 EGRESS, 98 99 /* Validate/create pattern. */ 100 PATTERN, 101 ITEM_PARAM_IS, 102 ITEM_PARAM_SPEC, 103 ITEM_PARAM_LAST, 104 ITEM_PARAM_MASK, 105 ITEM_PARAM_PREFIX, 106 ITEM_NEXT, 107 ITEM_END, 108 ITEM_VOID, 109 ITEM_INVERT, 110 ITEM_ANY, 111 ITEM_ANY_NUM, 112 ITEM_PF, 113 ITEM_VF, 114 ITEM_VF_ID, 115 ITEM_PORT, 116 ITEM_PORT_INDEX, 117 ITEM_RAW, 118 ITEM_RAW_RELATIVE, 119 ITEM_RAW_SEARCH, 120 ITEM_RAW_OFFSET, 121 ITEM_RAW_LIMIT, 122 ITEM_RAW_PATTERN, 123 ITEM_ETH, 124 ITEM_ETH_DST, 125 ITEM_ETH_SRC, 126 ITEM_ETH_TYPE, 127 ITEM_VLAN, 128 ITEM_VLAN_TPID, 129 ITEM_VLAN_TCI, 130 ITEM_VLAN_PCP, 131 ITEM_VLAN_DEI, 132 ITEM_VLAN_VID, 133 ITEM_IPV4, 134 ITEM_IPV4_TOS, 135 ITEM_IPV4_TTL, 136 ITEM_IPV4_PROTO, 137 ITEM_IPV4_SRC, 138 ITEM_IPV4_DST, 139 ITEM_IPV6, 140 ITEM_IPV6_TC, 141 ITEM_IPV6_FLOW, 142 ITEM_IPV6_PROTO, 143 ITEM_IPV6_HOP, 144 ITEM_IPV6_SRC, 145 ITEM_IPV6_DST, 146 ITEM_ICMP, 147 ITEM_ICMP_TYPE, 148 ITEM_ICMP_CODE, 149 ITEM_UDP, 150 ITEM_UDP_SRC, 151 ITEM_UDP_DST, 152 ITEM_TCP, 153 ITEM_TCP_SRC, 154 ITEM_TCP_DST, 155 ITEM_SCTP, 156 ITEM_SCTP_SRC, 157 ITEM_SCTP_DST, 158 ITEM_SCTP_TAG, 159 ITEM_SCTP_CKSUM, 160 ITEM_VXLAN, 161 ITEM_VXLAN_VNI, 162 ITEM_MPLS, 163 ITEM_MPLS_LABEL, 164 ITEM_GRE, 165 ITEM_GRE_PROTO, 166 167 /* Validate/create actions. */ 168 ACTIONS, 169 ACTION_NEXT, 170 ACTION_END, 171 ACTION_VOID, 172 ACTION_PASSTHRU, 173 ACTION_MARK, 174 ACTION_MARK_ID, 175 ACTION_FLAG, 176 ACTION_QUEUE, 177 ACTION_QUEUE_INDEX, 178 ACTION_DROP, 179 ACTION_COUNT, 180 ACTION_DUP, 181 ACTION_DUP_INDEX, 182 ACTION_RSS, 183 ACTION_RSS_QUEUES, 184 ACTION_RSS_QUEUE, 185 ACTION_PF, 186 ACTION_VF, 187 ACTION_VF_ORIGINAL, 188 ACTION_VF_ID, 189 }; 190 191 /** Size of pattern[] field in struct rte_flow_item_raw. */ 192 #define ITEM_RAW_PATTERN_SIZE 36 193 194 /** Storage size for struct rte_flow_item_raw including pattern. */ 195 #define ITEM_RAW_SIZE \ 196 (offsetof(struct rte_flow_item_raw, pattern) + ITEM_RAW_PATTERN_SIZE) 197 198 /** Number of queue[] entries in struct rte_flow_action_rss. */ 199 #define ACTION_RSS_NUM 32 200 201 /** Storage size for struct rte_flow_action_rss including queues. */ 202 #define ACTION_RSS_SIZE \ 203 (offsetof(struct rte_flow_action_rss, queue) + \ 204 sizeof(*((struct rte_flow_action_rss *)0)->queue) * ACTION_RSS_NUM) 205 206 /** Maximum number of subsequent tokens and arguments on the stack. */ 207 #define CTX_STACK_SIZE 16 208 209 /** Parser context. */ 210 struct context { 211 /** Stack of subsequent token lists to process. */ 212 const enum index *next[CTX_STACK_SIZE]; 213 /** Arguments for stacked tokens. */ 214 const void *args[CTX_STACK_SIZE]; 215 enum index curr; /**< Current token index. */ 216 enum index prev; /**< Index of the last token seen. */ 217 int next_num; /**< Number of entries in next[]. */ 218 int args_num; /**< Number of entries in args[]. */ 219 uint32_t reparse:1; /**< Start over from the beginning. */ 220 uint32_t eol:1; /**< EOL has been detected. */ 221 uint32_t last:1; /**< No more arguments. */ 222 uint16_t port; /**< Current port ID (for completions). */ 223 uint32_t objdata; /**< Object-specific data. */ 224 void *object; /**< Address of current object for relative offsets. */ 225 void *objmask; /**< Object a full mask must be written to. */ 226 }; 227 228 /** Token argument. */ 229 struct arg { 230 uint32_t hton:1; /**< Use network byte ordering. */ 231 uint32_t sign:1; /**< Value is signed. */ 232 uint32_t offset; /**< Relative offset from ctx->object. */ 233 uint32_t size; /**< Field size. */ 234 const uint8_t *mask; /**< Bit-mask to use instead of offset/size. */ 235 }; 236 237 /** Parser token definition. */ 238 struct token { 239 /** Type displayed during completion (defaults to "TOKEN"). */ 240 const char *type; 241 /** Help displayed during completion (defaults to token name). */ 242 const char *help; 243 /** Private data used by parser functions. */ 244 const void *priv; 245 /** 246 * Lists of subsequent tokens to push on the stack. Each call to the 247 * parser consumes the last entry of that stack. 248 */ 249 const enum index *const *next; 250 /** Arguments stack for subsequent tokens that need them. */ 251 const struct arg *const *args; 252 /** 253 * Token-processing callback, returns -1 in case of error, the 254 * length of the matched string otherwise. If NULL, attempts to 255 * match the token name. 256 * 257 * If buf is not NULL, the result should be stored in it according 258 * to context. An error is returned if not large enough. 259 */ 260 int (*call)(struct context *ctx, const struct token *token, 261 const char *str, unsigned int len, 262 void *buf, unsigned int size); 263 /** 264 * Callback that provides possible values for this token, used for 265 * completion. Returns -1 in case of error, the number of possible 266 * values otherwise. If NULL, the token name is used. 267 * 268 * If buf is not NULL, entry index ent is written to buf and the 269 * full length of the entry is returned (same behavior as 270 * snprintf()). 271 */ 272 int (*comp)(struct context *ctx, const struct token *token, 273 unsigned int ent, char *buf, unsigned int size); 274 /** Mandatory token name, no default value. */ 275 const char *name; 276 }; 277 278 /** Static initializer for the next field. */ 279 #define NEXT(...) (const enum index *const []){ __VA_ARGS__, NULL, } 280 281 /** Static initializer for a NEXT() entry. */ 282 #define NEXT_ENTRY(...) (const enum index []){ __VA_ARGS__, ZERO, } 283 284 /** Static initializer for the args field. */ 285 #define ARGS(...) (const struct arg *const []){ __VA_ARGS__, NULL, } 286 287 /** Static initializer for ARGS() to target a field. */ 288 #define ARGS_ENTRY(s, f) \ 289 (&(const struct arg){ \ 290 .offset = offsetof(s, f), \ 291 .size = sizeof(((s *)0)->f), \ 292 }) 293 294 /** Static initializer for ARGS() to target a bit-field. */ 295 #define ARGS_ENTRY_BF(s, f, b) \ 296 (&(const struct arg){ \ 297 .size = sizeof(s), \ 298 .mask = (const void *)&(const s){ .f = (1 << (b)) - 1 }, \ 299 }) 300 301 /** Static initializer for ARGS() to target an arbitrary bit-mask. */ 302 #define ARGS_ENTRY_MASK(s, f, m) \ 303 (&(const struct arg){ \ 304 .offset = offsetof(s, f), \ 305 .size = sizeof(((s *)0)->f), \ 306 .mask = (const void *)(m), \ 307 }) 308 309 /** Same as ARGS_ENTRY_MASK() using network byte ordering for the value. */ 310 #define ARGS_ENTRY_MASK_HTON(s, f, m) \ 311 (&(const struct arg){ \ 312 .hton = 1, \ 313 .offset = offsetof(s, f), \ 314 .size = sizeof(((s *)0)->f), \ 315 .mask = (const void *)(m), \ 316 }) 317 318 /** Static initializer for ARGS() to target a pointer. */ 319 #define ARGS_ENTRY_PTR(s, f) \ 320 (&(const struct arg){ \ 321 .size = sizeof(*((s *)0)->f), \ 322 }) 323 324 /** Static initializer for ARGS() with arbitrary size. */ 325 #define ARGS_ENTRY_USZ(s, f, sz) \ 326 (&(const struct arg){ \ 327 .offset = offsetof(s, f), \ 328 .size = (sz), \ 329 }) 330 331 /** Same as ARGS_ENTRY() using network byte ordering. */ 332 #define ARGS_ENTRY_HTON(s, f) \ 333 (&(const struct arg){ \ 334 .hton = 1, \ 335 .offset = offsetof(s, f), \ 336 .size = sizeof(((s *)0)->f), \ 337 }) 338 339 /** Parser output buffer layout expected by cmd_flow_parsed(). */ 340 struct buffer { 341 enum index command; /**< Flow command. */ 342 uint16_t port; /**< Affected port ID. */ 343 union { 344 struct { 345 struct rte_flow_attr attr; 346 struct rte_flow_item *pattern; 347 struct rte_flow_action *actions; 348 uint32_t pattern_n; 349 uint32_t actions_n; 350 uint8_t *data; 351 } vc; /**< Validate/create arguments. */ 352 struct { 353 uint32_t *rule; 354 uint32_t rule_n; 355 } destroy; /**< Destroy arguments. */ 356 struct { 357 uint32_t rule; 358 enum rte_flow_action_type action; 359 } query; /**< Query arguments. */ 360 struct { 361 uint32_t *group; 362 uint32_t group_n; 363 } list; /**< List arguments. */ 364 } args; /**< Command arguments. */ 365 }; 366 367 /** Private data for pattern items. */ 368 struct parse_item_priv { 369 enum rte_flow_item_type type; /**< Item type. */ 370 uint32_t size; /**< Size of item specification structure. */ 371 }; 372 373 #define PRIV_ITEM(t, s) \ 374 (&(const struct parse_item_priv){ \ 375 .type = RTE_FLOW_ITEM_TYPE_ ## t, \ 376 .size = s, \ 377 }) 378 379 /** Private data for actions. */ 380 struct parse_action_priv { 381 enum rte_flow_action_type type; /**< Action type. */ 382 uint32_t size; /**< Size of action configuration structure. */ 383 }; 384 385 #define PRIV_ACTION(t, s) \ 386 (&(const struct parse_action_priv){ \ 387 .type = RTE_FLOW_ACTION_TYPE_ ## t, \ 388 .size = s, \ 389 }) 390 391 static const enum index next_vc_attr[] = { 392 GROUP, 393 PRIORITY, 394 INGRESS, 395 EGRESS, 396 PATTERN, 397 ZERO, 398 }; 399 400 static const enum index next_destroy_attr[] = { 401 DESTROY_RULE, 402 END, 403 ZERO, 404 }; 405 406 static const enum index next_list_attr[] = { 407 LIST_GROUP, 408 END, 409 ZERO, 410 }; 411 412 static const enum index item_param[] = { 413 ITEM_PARAM_IS, 414 ITEM_PARAM_SPEC, 415 ITEM_PARAM_LAST, 416 ITEM_PARAM_MASK, 417 ITEM_PARAM_PREFIX, 418 ZERO, 419 }; 420 421 static const enum index next_item[] = { 422 ITEM_END, 423 ITEM_VOID, 424 ITEM_INVERT, 425 ITEM_ANY, 426 ITEM_PF, 427 ITEM_VF, 428 ITEM_PORT, 429 ITEM_RAW, 430 ITEM_ETH, 431 ITEM_VLAN, 432 ITEM_IPV4, 433 ITEM_IPV6, 434 ITEM_ICMP, 435 ITEM_UDP, 436 ITEM_TCP, 437 ITEM_SCTP, 438 ITEM_VXLAN, 439 ITEM_MPLS, 440 ITEM_GRE, 441 ZERO, 442 }; 443 444 static const enum index item_any[] = { 445 ITEM_ANY_NUM, 446 ITEM_NEXT, 447 ZERO, 448 }; 449 450 static const enum index item_vf[] = { 451 ITEM_VF_ID, 452 ITEM_NEXT, 453 ZERO, 454 }; 455 456 static const enum index item_port[] = { 457 ITEM_PORT_INDEX, 458 ITEM_NEXT, 459 ZERO, 460 }; 461 462 static const enum index item_raw[] = { 463 ITEM_RAW_RELATIVE, 464 ITEM_RAW_SEARCH, 465 ITEM_RAW_OFFSET, 466 ITEM_RAW_LIMIT, 467 ITEM_RAW_PATTERN, 468 ITEM_NEXT, 469 ZERO, 470 }; 471 472 static const enum index item_eth[] = { 473 ITEM_ETH_DST, 474 ITEM_ETH_SRC, 475 ITEM_ETH_TYPE, 476 ITEM_NEXT, 477 ZERO, 478 }; 479 480 static const enum index item_vlan[] = { 481 ITEM_VLAN_TPID, 482 ITEM_VLAN_TCI, 483 ITEM_VLAN_PCP, 484 ITEM_VLAN_DEI, 485 ITEM_VLAN_VID, 486 ITEM_NEXT, 487 ZERO, 488 }; 489 490 static const enum index item_ipv4[] = { 491 ITEM_IPV4_TOS, 492 ITEM_IPV4_TTL, 493 ITEM_IPV4_PROTO, 494 ITEM_IPV4_SRC, 495 ITEM_IPV4_DST, 496 ITEM_NEXT, 497 ZERO, 498 }; 499 500 static const enum index item_ipv6[] = { 501 ITEM_IPV6_TC, 502 ITEM_IPV6_FLOW, 503 ITEM_IPV6_PROTO, 504 ITEM_IPV6_HOP, 505 ITEM_IPV6_SRC, 506 ITEM_IPV6_DST, 507 ITEM_NEXT, 508 ZERO, 509 }; 510 511 static const enum index item_icmp[] = { 512 ITEM_ICMP_TYPE, 513 ITEM_ICMP_CODE, 514 ITEM_NEXT, 515 ZERO, 516 }; 517 518 static const enum index item_udp[] = { 519 ITEM_UDP_SRC, 520 ITEM_UDP_DST, 521 ITEM_NEXT, 522 ZERO, 523 }; 524 525 static const enum index item_tcp[] = { 526 ITEM_TCP_SRC, 527 ITEM_TCP_DST, 528 ITEM_NEXT, 529 ZERO, 530 }; 531 532 static const enum index item_sctp[] = { 533 ITEM_SCTP_SRC, 534 ITEM_SCTP_DST, 535 ITEM_SCTP_TAG, 536 ITEM_SCTP_CKSUM, 537 ITEM_NEXT, 538 ZERO, 539 }; 540 541 static const enum index item_vxlan[] = { 542 ITEM_VXLAN_VNI, 543 ITEM_NEXT, 544 ZERO, 545 }; 546 547 static const enum index item_mpls[] = { 548 ITEM_MPLS_LABEL, 549 ITEM_NEXT, 550 ZERO, 551 }; 552 553 static const enum index item_gre[] = { 554 ITEM_GRE_PROTO, 555 ITEM_NEXT, 556 ZERO, 557 }; 558 559 static const enum index next_action[] = { 560 ACTION_END, 561 ACTION_VOID, 562 ACTION_PASSTHRU, 563 ACTION_MARK, 564 ACTION_FLAG, 565 ACTION_QUEUE, 566 ACTION_DROP, 567 ACTION_COUNT, 568 ACTION_DUP, 569 ACTION_RSS, 570 ACTION_PF, 571 ACTION_VF, 572 ZERO, 573 }; 574 575 static const enum index action_mark[] = { 576 ACTION_MARK_ID, 577 ACTION_NEXT, 578 ZERO, 579 }; 580 581 static const enum index action_queue[] = { 582 ACTION_QUEUE_INDEX, 583 ACTION_NEXT, 584 ZERO, 585 }; 586 587 static const enum index action_dup[] = { 588 ACTION_DUP_INDEX, 589 ACTION_NEXT, 590 ZERO, 591 }; 592 593 static const enum index action_rss[] = { 594 ACTION_RSS_QUEUES, 595 ACTION_NEXT, 596 ZERO, 597 }; 598 599 static const enum index action_vf[] = { 600 ACTION_VF_ORIGINAL, 601 ACTION_VF_ID, 602 ACTION_NEXT, 603 ZERO, 604 }; 605 606 static int parse_init(struct context *, const struct token *, 607 const char *, unsigned int, 608 void *, unsigned int); 609 static int parse_vc(struct context *, const struct token *, 610 const char *, unsigned int, 611 void *, unsigned int); 612 static int parse_vc_spec(struct context *, const struct token *, 613 const char *, unsigned int, void *, unsigned int); 614 static int parse_vc_conf(struct context *, const struct token *, 615 const char *, unsigned int, void *, unsigned int); 616 static int parse_vc_action_rss_queue(struct context *, const struct token *, 617 const char *, unsigned int, void *, 618 unsigned int); 619 static int parse_destroy(struct context *, const struct token *, 620 const char *, unsigned int, 621 void *, unsigned int); 622 static int parse_flush(struct context *, const struct token *, 623 const char *, unsigned int, 624 void *, unsigned int); 625 static int parse_query(struct context *, const struct token *, 626 const char *, unsigned int, 627 void *, unsigned int); 628 static int parse_action(struct context *, const struct token *, 629 const char *, unsigned int, 630 void *, unsigned int); 631 static int parse_list(struct context *, const struct token *, 632 const char *, unsigned int, 633 void *, unsigned int); 634 static int parse_int(struct context *, const struct token *, 635 const char *, unsigned int, 636 void *, unsigned int); 637 static int parse_prefix(struct context *, const struct token *, 638 const char *, unsigned int, 639 void *, unsigned int); 640 static int parse_boolean(struct context *, const struct token *, 641 const char *, unsigned int, 642 void *, unsigned int); 643 static int parse_string(struct context *, const struct token *, 644 const char *, unsigned int, 645 void *, unsigned int); 646 static int parse_mac_addr(struct context *, const struct token *, 647 const char *, unsigned int, 648 void *, unsigned int); 649 static int parse_ipv4_addr(struct context *, const struct token *, 650 const char *, unsigned int, 651 void *, unsigned int); 652 static int parse_ipv6_addr(struct context *, const struct token *, 653 const char *, unsigned int, 654 void *, unsigned int); 655 static int parse_port(struct context *, const struct token *, 656 const char *, unsigned int, 657 void *, unsigned int); 658 static int comp_none(struct context *, const struct token *, 659 unsigned int, char *, unsigned int); 660 static int comp_boolean(struct context *, const struct token *, 661 unsigned int, char *, unsigned int); 662 static int comp_action(struct context *, const struct token *, 663 unsigned int, char *, unsigned int); 664 static int comp_port(struct context *, const struct token *, 665 unsigned int, char *, unsigned int); 666 static int comp_rule_id(struct context *, const struct token *, 667 unsigned int, char *, unsigned int); 668 static int comp_vc_action_rss_queue(struct context *, const struct token *, 669 unsigned int, char *, unsigned int); 670 671 /** Token definitions. */ 672 static const struct token token_list[] = { 673 /* Special tokens. */ 674 [ZERO] = { 675 .name = "ZERO", 676 .help = "null entry, abused as the entry point", 677 .next = NEXT(NEXT_ENTRY(FLOW)), 678 }, 679 [END] = { 680 .name = "", 681 .type = "RETURN", 682 .help = "command may end here", 683 }, 684 /* Common tokens. */ 685 [INTEGER] = { 686 .name = "{int}", 687 .type = "INTEGER", 688 .help = "integer value", 689 .call = parse_int, 690 .comp = comp_none, 691 }, 692 [UNSIGNED] = { 693 .name = "{unsigned}", 694 .type = "UNSIGNED", 695 .help = "unsigned integer value", 696 .call = parse_int, 697 .comp = comp_none, 698 }, 699 [PREFIX] = { 700 .name = "{prefix}", 701 .type = "PREFIX", 702 .help = "prefix length for bit-mask", 703 .call = parse_prefix, 704 .comp = comp_none, 705 }, 706 [BOOLEAN] = { 707 .name = "{boolean}", 708 .type = "BOOLEAN", 709 .help = "any boolean value", 710 .call = parse_boolean, 711 .comp = comp_boolean, 712 }, 713 [STRING] = { 714 .name = "{string}", 715 .type = "STRING", 716 .help = "fixed string", 717 .call = parse_string, 718 .comp = comp_none, 719 }, 720 [MAC_ADDR] = { 721 .name = "{MAC address}", 722 .type = "MAC-48", 723 .help = "standard MAC address notation", 724 .call = parse_mac_addr, 725 .comp = comp_none, 726 }, 727 [IPV4_ADDR] = { 728 .name = "{IPv4 address}", 729 .type = "IPV4 ADDRESS", 730 .help = "standard IPv4 address notation", 731 .call = parse_ipv4_addr, 732 .comp = comp_none, 733 }, 734 [IPV6_ADDR] = { 735 .name = "{IPv6 address}", 736 .type = "IPV6 ADDRESS", 737 .help = "standard IPv6 address notation", 738 .call = parse_ipv6_addr, 739 .comp = comp_none, 740 }, 741 [RULE_ID] = { 742 .name = "{rule id}", 743 .type = "RULE ID", 744 .help = "rule identifier", 745 .call = parse_int, 746 .comp = comp_rule_id, 747 }, 748 [PORT_ID] = { 749 .name = "{port_id}", 750 .type = "PORT ID", 751 .help = "port identifier", 752 .call = parse_port, 753 .comp = comp_port, 754 }, 755 [GROUP_ID] = { 756 .name = "{group_id}", 757 .type = "GROUP ID", 758 .help = "group identifier", 759 .call = parse_int, 760 .comp = comp_none, 761 }, 762 [PRIORITY_LEVEL] = { 763 .name = "{level}", 764 .type = "PRIORITY", 765 .help = "priority level", 766 .call = parse_int, 767 .comp = comp_none, 768 }, 769 /* Top-level command. */ 770 [FLOW] = { 771 .name = "flow", 772 .type = "{command} {port_id} [{arg} [...]]", 773 .help = "manage ingress/egress flow rules", 774 .next = NEXT(NEXT_ENTRY 775 (VALIDATE, 776 CREATE, 777 DESTROY, 778 FLUSH, 779 LIST, 780 QUERY)), 781 .call = parse_init, 782 }, 783 /* Sub-level commands. */ 784 [VALIDATE] = { 785 .name = "validate", 786 .help = "check whether a flow rule can be created", 787 .next = NEXT(next_vc_attr, NEXT_ENTRY(PORT_ID)), 788 .args = ARGS(ARGS_ENTRY(struct buffer, port)), 789 .call = parse_vc, 790 }, 791 [CREATE] = { 792 .name = "create", 793 .help = "create a flow rule", 794 .next = NEXT(next_vc_attr, NEXT_ENTRY(PORT_ID)), 795 .args = ARGS(ARGS_ENTRY(struct buffer, port)), 796 .call = parse_vc, 797 }, 798 [DESTROY] = { 799 .name = "destroy", 800 .help = "destroy specific flow rules", 801 .next = NEXT(NEXT_ENTRY(DESTROY_RULE), NEXT_ENTRY(PORT_ID)), 802 .args = ARGS(ARGS_ENTRY(struct buffer, port)), 803 .call = parse_destroy, 804 }, 805 [FLUSH] = { 806 .name = "flush", 807 .help = "destroy all flow rules", 808 .next = NEXT(NEXT_ENTRY(PORT_ID)), 809 .args = ARGS(ARGS_ENTRY(struct buffer, port)), 810 .call = parse_flush, 811 }, 812 [QUERY] = { 813 .name = "query", 814 .help = "query an existing flow rule", 815 .next = NEXT(NEXT_ENTRY(QUERY_ACTION), 816 NEXT_ENTRY(RULE_ID), 817 NEXT_ENTRY(PORT_ID)), 818 .args = ARGS(ARGS_ENTRY(struct buffer, args.query.action), 819 ARGS_ENTRY(struct buffer, args.query.rule), 820 ARGS_ENTRY(struct buffer, port)), 821 .call = parse_query, 822 }, 823 [LIST] = { 824 .name = "list", 825 .help = "list existing flow rules", 826 .next = NEXT(next_list_attr, NEXT_ENTRY(PORT_ID)), 827 .args = ARGS(ARGS_ENTRY(struct buffer, port)), 828 .call = parse_list, 829 }, 830 /* Destroy arguments. */ 831 [DESTROY_RULE] = { 832 .name = "rule", 833 .help = "specify a rule identifier", 834 .next = NEXT(next_destroy_attr, NEXT_ENTRY(RULE_ID)), 835 .args = ARGS(ARGS_ENTRY_PTR(struct buffer, args.destroy.rule)), 836 .call = parse_destroy, 837 }, 838 /* Query arguments. */ 839 [QUERY_ACTION] = { 840 .name = "{action}", 841 .type = "ACTION", 842 .help = "action to query, must be part of the rule", 843 .call = parse_action, 844 .comp = comp_action, 845 }, 846 /* List arguments. */ 847 [LIST_GROUP] = { 848 .name = "group", 849 .help = "specify a group", 850 .next = NEXT(next_list_attr, NEXT_ENTRY(GROUP_ID)), 851 .args = ARGS(ARGS_ENTRY_PTR(struct buffer, args.list.group)), 852 .call = parse_list, 853 }, 854 /* Validate/create attributes. */ 855 [GROUP] = { 856 .name = "group", 857 .help = "specify a group", 858 .next = NEXT(next_vc_attr, NEXT_ENTRY(GROUP_ID)), 859 .args = ARGS(ARGS_ENTRY(struct rte_flow_attr, group)), 860 .call = parse_vc, 861 }, 862 [PRIORITY] = { 863 .name = "priority", 864 .help = "specify a priority level", 865 .next = NEXT(next_vc_attr, NEXT_ENTRY(PRIORITY_LEVEL)), 866 .args = ARGS(ARGS_ENTRY(struct rte_flow_attr, priority)), 867 .call = parse_vc, 868 }, 869 [INGRESS] = { 870 .name = "ingress", 871 .help = "affect rule to ingress", 872 .next = NEXT(next_vc_attr), 873 .call = parse_vc, 874 }, 875 [EGRESS] = { 876 .name = "egress", 877 .help = "affect rule to egress", 878 .next = NEXT(next_vc_attr), 879 .call = parse_vc, 880 }, 881 /* Validate/create pattern. */ 882 [PATTERN] = { 883 .name = "pattern", 884 .help = "submit a list of pattern items", 885 .next = NEXT(next_item), 886 .call = parse_vc, 887 }, 888 [ITEM_PARAM_IS] = { 889 .name = "is", 890 .help = "match value perfectly (with full bit-mask)", 891 .call = parse_vc_spec, 892 }, 893 [ITEM_PARAM_SPEC] = { 894 .name = "spec", 895 .help = "match value according to configured bit-mask", 896 .call = parse_vc_spec, 897 }, 898 [ITEM_PARAM_LAST] = { 899 .name = "last", 900 .help = "specify upper bound to establish a range", 901 .call = parse_vc_spec, 902 }, 903 [ITEM_PARAM_MASK] = { 904 .name = "mask", 905 .help = "specify bit-mask with relevant bits set to one", 906 .call = parse_vc_spec, 907 }, 908 [ITEM_PARAM_PREFIX] = { 909 .name = "prefix", 910 .help = "generate bit-mask from a prefix length", 911 .call = parse_vc_spec, 912 }, 913 [ITEM_NEXT] = { 914 .name = "/", 915 .help = "specify next pattern item", 916 .next = NEXT(next_item), 917 }, 918 [ITEM_END] = { 919 .name = "end", 920 .help = "end list of pattern items", 921 .priv = PRIV_ITEM(END, 0), 922 .next = NEXT(NEXT_ENTRY(ACTIONS)), 923 .call = parse_vc, 924 }, 925 [ITEM_VOID] = { 926 .name = "void", 927 .help = "no-op pattern item", 928 .priv = PRIV_ITEM(VOID, 0), 929 .next = NEXT(NEXT_ENTRY(ITEM_NEXT)), 930 .call = parse_vc, 931 }, 932 [ITEM_INVERT] = { 933 .name = "invert", 934 .help = "perform actions when pattern does not match", 935 .priv = PRIV_ITEM(INVERT, 0), 936 .next = NEXT(NEXT_ENTRY(ITEM_NEXT)), 937 .call = parse_vc, 938 }, 939 [ITEM_ANY] = { 940 .name = "any", 941 .help = "match any protocol for the current layer", 942 .priv = PRIV_ITEM(ANY, sizeof(struct rte_flow_item_any)), 943 .next = NEXT(item_any), 944 .call = parse_vc, 945 }, 946 [ITEM_ANY_NUM] = { 947 .name = "num", 948 .help = "number of layers covered", 949 .next = NEXT(item_any, NEXT_ENTRY(UNSIGNED), item_param), 950 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_any, num)), 951 }, 952 [ITEM_PF] = { 953 .name = "pf", 954 .help = "match packets addressed to the physical function", 955 .priv = PRIV_ITEM(PF, 0), 956 .next = NEXT(NEXT_ENTRY(ITEM_NEXT)), 957 .call = parse_vc, 958 }, 959 [ITEM_VF] = { 960 .name = "vf", 961 .help = "match packets addressed to a virtual function ID", 962 .priv = PRIV_ITEM(VF, sizeof(struct rte_flow_item_vf)), 963 .next = NEXT(item_vf), 964 .call = parse_vc, 965 }, 966 [ITEM_VF_ID] = { 967 .name = "id", 968 .help = "destination VF ID", 969 .next = NEXT(item_vf, NEXT_ENTRY(UNSIGNED), item_param), 970 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_vf, id)), 971 }, 972 [ITEM_PORT] = { 973 .name = "port", 974 .help = "device-specific physical port index to use", 975 .priv = PRIV_ITEM(PORT, sizeof(struct rte_flow_item_port)), 976 .next = NEXT(item_port), 977 .call = parse_vc, 978 }, 979 [ITEM_PORT_INDEX] = { 980 .name = "index", 981 .help = "physical port index", 982 .next = NEXT(item_port, NEXT_ENTRY(UNSIGNED), item_param), 983 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_port, index)), 984 }, 985 [ITEM_RAW] = { 986 .name = "raw", 987 .help = "match an arbitrary byte string", 988 .priv = PRIV_ITEM(RAW, ITEM_RAW_SIZE), 989 .next = NEXT(item_raw), 990 .call = parse_vc, 991 }, 992 [ITEM_RAW_RELATIVE] = { 993 .name = "relative", 994 .help = "look for pattern after the previous item", 995 .next = NEXT(item_raw, NEXT_ENTRY(BOOLEAN), item_param), 996 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_raw, 997 relative, 1)), 998 }, 999 [ITEM_RAW_SEARCH] = { 1000 .name = "search", 1001 .help = "search pattern from offset (see also limit)", 1002 .next = NEXT(item_raw, NEXT_ENTRY(BOOLEAN), item_param), 1003 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_raw, 1004 search, 1)), 1005 }, 1006 [ITEM_RAW_OFFSET] = { 1007 .name = "offset", 1008 .help = "absolute or relative offset for pattern", 1009 .next = NEXT(item_raw, NEXT_ENTRY(INTEGER), item_param), 1010 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, offset)), 1011 }, 1012 [ITEM_RAW_LIMIT] = { 1013 .name = "limit", 1014 .help = "search area limit for start of pattern", 1015 .next = NEXT(item_raw, NEXT_ENTRY(UNSIGNED), item_param), 1016 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, limit)), 1017 }, 1018 [ITEM_RAW_PATTERN] = { 1019 .name = "pattern", 1020 .help = "byte string to look for", 1021 .next = NEXT(item_raw, 1022 NEXT_ENTRY(STRING), 1023 NEXT_ENTRY(ITEM_PARAM_IS, 1024 ITEM_PARAM_SPEC, 1025 ITEM_PARAM_MASK)), 1026 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, length), 1027 ARGS_ENTRY_USZ(struct rte_flow_item_raw, 1028 pattern, 1029 ITEM_RAW_PATTERN_SIZE)), 1030 }, 1031 [ITEM_ETH] = { 1032 .name = "eth", 1033 .help = "match Ethernet header", 1034 .priv = PRIV_ITEM(ETH, sizeof(struct rte_flow_item_eth)), 1035 .next = NEXT(item_eth), 1036 .call = parse_vc, 1037 }, 1038 [ITEM_ETH_DST] = { 1039 .name = "dst", 1040 .help = "destination MAC", 1041 .next = NEXT(item_eth, NEXT_ENTRY(MAC_ADDR), item_param), 1042 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_eth, dst)), 1043 }, 1044 [ITEM_ETH_SRC] = { 1045 .name = "src", 1046 .help = "source MAC", 1047 .next = NEXT(item_eth, NEXT_ENTRY(MAC_ADDR), item_param), 1048 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_eth, src)), 1049 }, 1050 [ITEM_ETH_TYPE] = { 1051 .name = "type", 1052 .help = "EtherType", 1053 .next = NEXT(item_eth, NEXT_ENTRY(UNSIGNED), item_param), 1054 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_eth, type)), 1055 }, 1056 [ITEM_VLAN] = { 1057 .name = "vlan", 1058 .help = "match 802.1Q/ad VLAN tag", 1059 .priv = PRIV_ITEM(VLAN, sizeof(struct rte_flow_item_vlan)), 1060 .next = NEXT(item_vlan), 1061 .call = parse_vc, 1062 }, 1063 [ITEM_VLAN_TPID] = { 1064 .name = "tpid", 1065 .help = "tag protocol identifier", 1066 .next = NEXT(item_vlan, NEXT_ENTRY(UNSIGNED), item_param), 1067 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vlan, tpid)), 1068 }, 1069 [ITEM_VLAN_TCI] = { 1070 .name = "tci", 1071 .help = "tag control information", 1072 .next = NEXT(item_vlan, NEXT_ENTRY(UNSIGNED), item_param), 1073 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vlan, tci)), 1074 }, 1075 [ITEM_VLAN_PCP] = { 1076 .name = "pcp", 1077 .help = "priority code point", 1078 .next = NEXT(item_vlan, NEXT_ENTRY(UNSIGNED), item_param), 1079 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_vlan, 1080 tci, "\xe0\x00")), 1081 }, 1082 [ITEM_VLAN_DEI] = { 1083 .name = "dei", 1084 .help = "drop eligible indicator", 1085 .next = NEXT(item_vlan, NEXT_ENTRY(UNSIGNED), item_param), 1086 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_vlan, 1087 tci, "\x10\x00")), 1088 }, 1089 [ITEM_VLAN_VID] = { 1090 .name = "vid", 1091 .help = "VLAN identifier", 1092 .next = NEXT(item_vlan, NEXT_ENTRY(UNSIGNED), item_param), 1093 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_vlan, 1094 tci, "\x0f\xff")), 1095 }, 1096 [ITEM_IPV4] = { 1097 .name = "ipv4", 1098 .help = "match IPv4 header", 1099 .priv = PRIV_ITEM(IPV4, sizeof(struct rte_flow_item_ipv4)), 1100 .next = NEXT(item_ipv4), 1101 .call = parse_vc, 1102 }, 1103 [ITEM_IPV4_TOS] = { 1104 .name = "tos", 1105 .help = "type of service", 1106 .next = NEXT(item_ipv4, NEXT_ENTRY(UNSIGNED), item_param), 1107 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4, 1108 hdr.type_of_service)), 1109 }, 1110 [ITEM_IPV4_TTL] = { 1111 .name = "ttl", 1112 .help = "time to live", 1113 .next = NEXT(item_ipv4, NEXT_ENTRY(UNSIGNED), item_param), 1114 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4, 1115 hdr.time_to_live)), 1116 }, 1117 [ITEM_IPV4_PROTO] = { 1118 .name = "proto", 1119 .help = "next protocol ID", 1120 .next = NEXT(item_ipv4, NEXT_ENTRY(UNSIGNED), item_param), 1121 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4, 1122 hdr.next_proto_id)), 1123 }, 1124 [ITEM_IPV4_SRC] = { 1125 .name = "src", 1126 .help = "source address", 1127 .next = NEXT(item_ipv4, NEXT_ENTRY(IPV4_ADDR), item_param), 1128 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4, 1129 hdr.src_addr)), 1130 }, 1131 [ITEM_IPV4_DST] = { 1132 .name = "dst", 1133 .help = "destination address", 1134 .next = NEXT(item_ipv4, NEXT_ENTRY(IPV4_ADDR), item_param), 1135 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4, 1136 hdr.dst_addr)), 1137 }, 1138 [ITEM_IPV6] = { 1139 .name = "ipv6", 1140 .help = "match IPv6 header", 1141 .priv = PRIV_ITEM(IPV6, sizeof(struct rte_flow_item_ipv6)), 1142 .next = NEXT(item_ipv6), 1143 .call = parse_vc, 1144 }, 1145 [ITEM_IPV6_TC] = { 1146 .name = "tc", 1147 .help = "traffic class", 1148 .next = NEXT(item_ipv6, NEXT_ENTRY(UNSIGNED), item_param), 1149 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_ipv6, 1150 hdr.vtc_flow, 1151 "\x0f\xf0\x00\x00")), 1152 }, 1153 [ITEM_IPV6_FLOW] = { 1154 .name = "flow", 1155 .help = "flow label", 1156 .next = NEXT(item_ipv6, NEXT_ENTRY(UNSIGNED), item_param), 1157 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_ipv6, 1158 hdr.vtc_flow, 1159 "\x00\x0f\xff\xff")), 1160 }, 1161 [ITEM_IPV6_PROTO] = { 1162 .name = "proto", 1163 .help = "protocol (next header)", 1164 .next = NEXT(item_ipv6, NEXT_ENTRY(UNSIGNED), item_param), 1165 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6, 1166 hdr.proto)), 1167 }, 1168 [ITEM_IPV6_HOP] = { 1169 .name = "hop", 1170 .help = "hop limit", 1171 .next = NEXT(item_ipv6, NEXT_ENTRY(UNSIGNED), item_param), 1172 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6, 1173 hdr.hop_limits)), 1174 }, 1175 [ITEM_IPV6_SRC] = { 1176 .name = "src", 1177 .help = "source address", 1178 .next = NEXT(item_ipv6, NEXT_ENTRY(IPV6_ADDR), item_param), 1179 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6, 1180 hdr.src_addr)), 1181 }, 1182 [ITEM_IPV6_DST] = { 1183 .name = "dst", 1184 .help = "destination address", 1185 .next = NEXT(item_ipv6, NEXT_ENTRY(IPV6_ADDR), item_param), 1186 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6, 1187 hdr.dst_addr)), 1188 }, 1189 [ITEM_ICMP] = { 1190 .name = "icmp", 1191 .help = "match ICMP header", 1192 .priv = PRIV_ITEM(ICMP, sizeof(struct rte_flow_item_icmp)), 1193 .next = NEXT(item_icmp), 1194 .call = parse_vc, 1195 }, 1196 [ITEM_ICMP_TYPE] = { 1197 .name = "type", 1198 .help = "ICMP packet type", 1199 .next = NEXT(item_icmp, NEXT_ENTRY(UNSIGNED), item_param), 1200 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp, 1201 hdr.icmp_type)), 1202 }, 1203 [ITEM_ICMP_CODE] = { 1204 .name = "code", 1205 .help = "ICMP packet code", 1206 .next = NEXT(item_icmp, NEXT_ENTRY(UNSIGNED), item_param), 1207 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp, 1208 hdr.icmp_code)), 1209 }, 1210 [ITEM_UDP] = { 1211 .name = "udp", 1212 .help = "match UDP header", 1213 .priv = PRIV_ITEM(UDP, sizeof(struct rte_flow_item_udp)), 1214 .next = NEXT(item_udp), 1215 .call = parse_vc, 1216 }, 1217 [ITEM_UDP_SRC] = { 1218 .name = "src", 1219 .help = "UDP source port", 1220 .next = NEXT(item_udp, NEXT_ENTRY(UNSIGNED), item_param), 1221 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_udp, 1222 hdr.src_port)), 1223 }, 1224 [ITEM_UDP_DST] = { 1225 .name = "dst", 1226 .help = "UDP destination port", 1227 .next = NEXT(item_udp, NEXT_ENTRY(UNSIGNED), item_param), 1228 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_udp, 1229 hdr.dst_port)), 1230 }, 1231 [ITEM_TCP] = { 1232 .name = "tcp", 1233 .help = "match TCP header", 1234 .priv = PRIV_ITEM(TCP, sizeof(struct rte_flow_item_tcp)), 1235 .next = NEXT(item_tcp), 1236 .call = parse_vc, 1237 }, 1238 [ITEM_TCP_SRC] = { 1239 .name = "src", 1240 .help = "TCP source port", 1241 .next = NEXT(item_tcp, NEXT_ENTRY(UNSIGNED), item_param), 1242 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_tcp, 1243 hdr.src_port)), 1244 }, 1245 [ITEM_TCP_DST] = { 1246 .name = "dst", 1247 .help = "TCP destination port", 1248 .next = NEXT(item_tcp, NEXT_ENTRY(UNSIGNED), item_param), 1249 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_tcp, 1250 hdr.dst_port)), 1251 }, 1252 [ITEM_SCTP] = { 1253 .name = "sctp", 1254 .help = "match SCTP header", 1255 .priv = PRIV_ITEM(SCTP, sizeof(struct rte_flow_item_sctp)), 1256 .next = NEXT(item_sctp), 1257 .call = parse_vc, 1258 }, 1259 [ITEM_SCTP_SRC] = { 1260 .name = "src", 1261 .help = "SCTP source port", 1262 .next = NEXT(item_sctp, NEXT_ENTRY(UNSIGNED), item_param), 1263 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp, 1264 hdr.src_port)), 1265 }, 1266 [ITEM_SCTP_DST] = { 1267 .name = "dst", 1268 .help = "SCTP destination port", 1269 .next = NEXT(item_sctp, NEXT_ENTRY(UNSIGNED), item_param), 1270 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp, 1271 hdr.dst_port)), 1272 }, 1273 [ITEM_SCTP_TAG] = { 1274 .name = "tag", 1275 .help = "validation tag", 1276 .next = NEXT(item_sctp, NEXT_ENTRY(UNSIGNED), item_param), 1277 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp, 1278 hdr.tag)), 1279 }, 1280 [ITEM_SCTP_CKSUM] = { 1281 .name = "cksum", 1282 .help = "checksum", 1283 .next = NEXT(item_sctp, NEXT_ENTRY(UNSIGNED), item_param), 1284 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp, 1285 hdr.cksum)), 1286 }, 1287 [ITEM_VXLAN] = { 1288 .name = "vxlan", 1289 .help = "match VXLAN header", 1290 .priv = PRIV_ITEM(VXLAN, sizeof(struct rte_flow_item_vxlan)), 1291 .next = NEXT(item_vxlan), 1292 .call = parse_vc, 1293 }, 1294 [ITEM_VXLAN_VNI] = { 1295 .name = "vni", 1296 .help = "VXLAN identifier", 1297 .next = NEXT(item_vxlan, NEXT_ENTRY(UNSIGNED), item_param), 1298 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan, vni)), 1299 }, 1300 [ITEM_MPLS] = { 1301 .name = "mpls", 1302 .help = "match MPLS header", 1303 .priv = PRIV_ITEM(MPLS, sizeof(struct rte_flow_item_mpls)), 1304 .next = NEXT(item_mpls), 1305 .call = parse_vc, 1306 }, 1307 [ITEM_MPLS_LABEL] = { 1308 .name = "label", 1309 .help = "MPLS label", 1310 .next = NEXT(item_mpls, NEXT_ENTRY(UNSIGNED), item_param), 1311 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_mpls, 1312 label_tc_s, 1313 "\xff\xff\xf0")), 1314 }, 1315 [ITEM_GRE] = { 1316 .name = "gre", 1317 .help = "match GRE header", 1318 .priv = PRIV_ITEM(GRE, sizeof(struct rte_flow_item_gre)), 1319 .next = NEXT(item_gre), 1320 .call = parse_vc, 1321 }, 1322 [ITEM_GRE_PROTO] = { 1323 .name = "protocol", 1324 .help = "GRE protocol type", 1325 .next = NEXT(item_gre, NEXT_ENTRY(UNSIGNED), item_param), 1326 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre, 1327 protocol)), 1328 }, 1329 /* Validate/create actions. */ 1330 [ACTIONS] = { 1331 .name = "actions", 1332 .help = "submit a list of associated actions", 1333 .next = NEXT(next_action), 1334 .call = parse_vc, 1335 }, 1336 [ACTION_NEXT] = { 1337 .name = "/", 1338 .help = "specify next action", 1339 .next = NEXT(next_action), 1340 }, 1341 [ACTION_END] = { 1342 .name = "end", 1343 .help = "end list of actions", 1344 .priv = PRIV_ACTION(END, 0), 1345 .call = parse_vc, 1346 }, 1347 [ACTION_VOID] = { 1348 .name = "void", 1349 .help = "no-op action", 1350 .priv = PRIV_ACTION(VOID, 0), 1351 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)), 1352 .call = parse_vc, 1353 }, 1354 [ACTION_PASSTHRU] = { 1355 .name = "passthru", 1356 .help = "let subsequent rule process matched packets", 1357 .priv = PRIV_ACTION(PASSTHRU, 0), 1358 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)), 1359 .call = parse_vc, 1360 }, 1361 [ACTION_MARK] = { 1362 .name = "mark", 1363 .help = "attach 32 bit value to packets", 1364 .priv = PRIV_ACTION(MARK, sizeof(struct rte_flow_action_mark)), 1365 .next = NEXT(action_mark), 1366 .call = parse_vc, 1367 }, 1368 [ACTION_MARK_ID] = { 1369 .name = "id", 1370 .help = "32 bit value to return with packets", 1371 .next = NEXT(action_mark, NEXT_ENTRY(UNSIGNED)), 1372 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_mark, id)), 1373 .call = parse_vc_conf, 1374 }, 1375 [ACTION_FLAG] = { 1376 .name = "flag", 1377 .help = "flag packets", 1378 .priv = PRIV_ACTION(FLAG, 0), 1379 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)), 1380 .call = parse_vc, 1381 }, 1382 [ACTION_QUEUE] = { 1383 .name = "queue", 1384 .help = "assign packets to a given queue index", 1385 .priv = PRIV_ACTION(QUEUE, 1386 sizeof(struct rte_flow_action_queue)), 1387 .next = NEXT(action_queue), 1388 .call = parse_vc, 1389 }, 1390 [ACTION_QUEUE_INDEX] = { 1391 .name = "index", 1392 .help = "queue index to use", 1393 .next = NEXT(action_queue, NEXT_ENTRY(UNSIGNED)), 1394 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_queue, index)), 1395 .call = parse_vc_conf, 1396 }, 1397 [ACTION_DROP] = { 1398 .name = "drop", 1399 .help = "drop packets (note: passthru has priority)", 1400 .priv = PRIV_ACTION(DROP, 0), 1401 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)), 1402 .call = parse_vc, 1403 }, 1404 [ACTION_COUNT] = { 1405 .name = "count", 1406 .help = "enable counters for this rule", 1407 .priv = PRIV_ACTION(COUNT, 0), 1408 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)), 1409 .call = parse_vc, 1410 }, 1411 [ACTION_DUP] = { 1412 .name = "dup", 1413 .help = "duplicate packets to a given queue index", 1414 .priv = PRIV_ACTION(DUP, sizeof(struct rte_flow_action_dup)), 1415 .next = NEXT(action_dup), 1416 .call = parse_vc, 1417 }, 1418 [ACTION_DUP_INDEX] = { 1419 .name = "index", 1420 .help = "queue index to duplicate packets to", 1421 .next = NEXT(action_dup, NEXT_ENTRY(UNSIGNED)), 1422 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_dup, index)), 1423 .call = parse_vc_conf, 1424 }, 1425 [ACTION_RSS] = { 1426 .name = "rss", 1427 .help = "spread packets among several queues", 1428 .priv = PRIV_ACTION(RSS, ACTION_RSS_SIZE), 1429 .next = NEXT(action_rss), 1430 .call = parse_vc, 1431 }, 1432 [ACTION_RSS_QUEUES] = { 1433 .name = "queues", 1434 .help = "queue indices to use", 1435 .next = NEXT(action_rss, NEXT_ENTRY(ACTION_RSS_QUEUE)), 1436 .call = parse_vc_conf, 1437 }, 1438 [ACTION_RSS_QUEUE] = { 1439 .name = "{queue}", 1440 .help = "queue index", 1441 .call = parse_vc_action_rss_queue, 1442 .comp = comp_vc_action_rss_queue, 1443 }, 1444 [ACTION_PF] = { 1445 .name = "pf", 1446 .help = "redirect packets to physical device function", 1447 .priv = PRIV_ACTION(PF, 0), 1448 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)), 1449 .call = parse_vc, 1450 }, 1451 [ACTION_VF] = { 1452 .name = "vf", 1453 .help = "redirect packets to virtual device function", 1454 .priv = PRIV_ACTION(VF, sizeof(struct rte_flow_action_vf)), 1455 .next = NEXT(action_vf), 1456 .call = parse_vc, 1457 }, 1458 [ACTION_VF_ORIGINAL] = { 1459 .name = "original", 1460 .help = "use original VF ID if possible", 1461 .next = NEXT(action_vf, NEXT_ENTRY(BOOLEAN)), 1462 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_vf, 1463 original, 1)), 1464 .call = parse_vc_conf, 1465 }, 1466 [ACTION_VF_ID] = { 1467 .name = "id", 1468 .help = "VF ID to redirect packets to", 1469 .next = NEXT(action_vf, NEXT_ENTRY(UNSIGNED)), 1470 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_vf, id)), 1471 .call = parse_vc_conf, 1472 }, 1473 }; 1474 1475 /** Remove and return last entry from argument stack. */ 1476 static const struct arg * 1477 pop_args(struct context *ctx) 1478 { 1479 return ctx->args_num ? ctx->args[--ctx->args_num] : NULL; 1480 } 1481 1482 /** Add entry on top of the argument stack. */ 1483 static int 1484 push_args(struct context *ctx, const struct arg *arg) 1485 { 1486 if (ctx->args_num == CTX_STACK_SIZE) 1487 return -1; 1488 ctx->args[ctx->args_num++] = arg; 1489 return 0; 1490 } 1491 1492 /** Spread value into buffer according to bit-mask. */ 1493 static size_t 1494 arg_entry_bf_fill(void *dst, uintmax_t val, const struct arg *arg) 1495 { 1496 uint32_t i = arg->size; 1497 uint32_t end = 0; 1498 int sub = 1; 1499 int add = 0; 1500 size_t len = 0; 1501 1502 if (!arg->mask) 1503 return 0; 1504 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN 1505 if (!arg->hton) { 1506 i = 0; 1507 end = arg->size; 1508 sub = 0; 1509 add = 1; 1510 } 1511 #endif 1512 while (i != end) { 1513 unsigned int shift = 0; 1514 uint8_t *buf = (uint8_t *)dst + arg->offset + (i -= sub); 1515 1516 for (shift = 0; arg->mask[i] >> shift; ++shift) { 1517 if (!(arg->mask[i] & (1 << shift))) 1518 continue; 1519 ++len; 1520 if (!dst) 1521 continue; 1522 *buf &= ~(1 << shift); 1523 *buf |= (val & 1) << shift; 1524 val >>= 1; 1525 } 1526 i += add; 1527 } 1528 return len; 1529 } 1530 1531 /** 1532 * Parse a prefix length and generate a bit-mask. 1533 * 1534 * Last argument (ctx->args) is retrieved to determine mask size, storage 1535 * location and whether the result must use network byte ordering. 1536 */ 1537 static int 1538 parse_prefix(struct context *ctx, const struct token *token, 1539 const char *str, unsigned int len, 1540 void *buf, unsigned int size) 1541 { 1542 const struct arg *arg = pop_args(ctx); 1543 static const uint8_t conv[] = "\x00\x80\xc0\xe0\xf0\xf8\xfc\xfe\xff"; 1544 char *end; 1545 uintmax_t u; 1546 unsigned int bytes; 1547 unsigned int extra; 1548 1549 (void)token; 1550 /* Argument is expected. */ 1551 if (!arg) 1552 return -1; 1553 errno = 0; 1554 u = strtoumax(str, &end, 0); 1555 if (errno || (size_t)(end - str) != len) 1556 goto error; 1557 if (arg->mask) { 1558 uintmax_t v = 0; 1559 1560 extra = arg_entry_bf_fill(NULL, 0, arg); 1561 if (u > extra) 1562 goto error; 1563 if (!ctx->object) 1564 return len; 1565 extra -= u; 1566 while (u--) 1567 (v <<= 1, v |= 1); 1568 v <<= extra; 1569 if (!arg_entry_bf_fill(ctx->object, v, arg) || 1570 !arg_entry_bf_fill(ctx->objmask, -1, arg)) 1571 goto error; 1572 return len; 1573 } 1574 bytes = u / 8; 1575 extra = u % 8; 1576 size = arg->size; 1577 if (bytes > size || bytes + !!extra > size) 1578 goto error; 1579 if (!ctx->object) 1580 return len; 1581 buf = (uint8_t *)ctx->object + arg->offset; 1582 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN 1583 if (!arg->hton) { 1584 memset((uint8_t *)buf + size - bytes, 0xff, bytes); 1585 memset(buf, 0x00, size - bytes); 1586 if (extra) 1587 ((uint8_t *)buf)[size - bytes - 1] = conv[extra]; 1588 } else 1589 #endif 1590 { 1591 memset(buf, 0xff, bytes); 1592 memset((uint8_t *)buf + bytes, 0x00, size - bytes); 1593 if (extra) 1594 ((uint8_t *)buf)[bytes] = conv[extra]; 1595 } 1596 if (ctx->objmask) 1597 memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size); 1598 return len; 1599 error: 1600 push_args(ctx, arg); 1601 return -1; 1602 } 1603 1604 /** Default parsing function for token name matching. */ 1605 static int 1606 parse_default(struct context *ctx, const struct token *token, 1607 const char *str, unsigned int len, 1608 void *buf, unsigned int size) 1609 { 1610 (void)ctx; 1611 (void)buf; 1612 (void)size; 1613 if (strncmp(str, token->name, len)) 1614 return -1; 1615 return len; 1616 } 1617 1618 /** Parse flow command, initialize output buffer for subsequent tokens. */ 1619 static int 1620 parse_init(struct context *ctx, const struct token *token, 1621 const char *str, unsigned int len, 1622 void *buf, unsigned int size) 1623 { 1624 struct buffer *out = buf; 1625 1626 /* Token name must match. */ 1627 if (parse_default(ctx, token, str, len, NULL, 0) < 0) 1628 return -1; 1629 /* Nothing else to do if there is no buffer. */ 1630 if (!out) 1631 return len; 1632 /* Make sure buffer is large enough. */ 1633 if (size < sizeof(*out)) 1634 return -1; 1635 /* Initialize buffer. */ 1636 memset(out, 0x00, sizeof(*out)); 1637 memset((uint8_t *)out + sizeof(*out), 0x22, size - sizeof(*out)); 1638 ctx->objdata = 0; 1639 ctx->object = out; 1640 ctx->objmask = NULL; 1641 return len; 1642 } 1643 1644 /** Parse tokens for validate/create commands. */ 1645 static int 1646 parse_vc(struct context *ctx, const struct token *token, 1647 const char *str, unsigned int len, 1648 void *buf, unsigned int size) 1649 { 1650 struct buffer *out = buf; 1651 uint8_t *data; 1652 uint32_t data_size; 1653 1654 /* Token name must match. */ 1655 if (parse_default(ctx, token, str, len, NULL, 0) < 0) 1656 return -1; 1657 /* Nothing else to do if there is no buffer. */ 1658 if (!out) 1659 return len; 1660 if (!out->command) { 1661 if (ctx->curr != VALIDATE && ctx->curr != CREATE) 1662 return -1; 1663 if (sizeof(*out) > size) 1664 return -1; 1665 out->command = ctx->curr; 1666 ctx->objdata = 0; 1667 ctx->object = out; 1668 ctx->objmask = NULL; 1669 out->args.vc.data = (uint8_t *)out + size; 1670 return len; 1671 } 1672 ctx->objdata = 0; 1673 ctx->object = &out->args.vc.attr; 1674 ctx->objmask = NULL; 1675 switch (ctx->curr) { 1676 case GROUP: 1677 case PRIORITY: 1678 return len; 1679 case INGRESS: 1680 out->args.vc.attr.ingress = 1; 1681 return len; 1682 case EGRESS: 1683 out->args.vc.attr.egress = 1; 1684 return len; 1685 case PATTERN: 1686 out->args.vc.pattern = 1687 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1), 1688 sizeof(double)); 1689 ctx->object = out->args.vc.pattern; 1690 ctx->objmask = NULL; 1691 return len; 1692 case ACTIONS: 1693 out->args.vc.actions = 1694 (void *)RTE_ALIGN_CEIL((uintptr_t) 1695 (out->args.vc.pattern + 1696 out->args.vc.pattern_n), 1697 sizeof(double)); 1698 ctx->object = out->args.vc.actions; 1699 ctx->objmask = NULL; 1700 return len; 1701 default: 1702 if (!token->priv) 1703 return -1; 1704 break; 1705 } 1706 if (!out->args.vc.actions) { 1707 const struct parse_item_priv *priv = token->priv; 1708 struct rte_flow_item *item = 1709 out->args.vc.pattern + out->args.vc.pattern_n; 1710 1711 data_size = priv->size * 3; /* spec, last, mask */ 1712 data = (void *)RTE_ALIGN_FLOOR((uintptr_t) 1713 (out->args.vc.data - data_size), 1714 sizeof(double)); 1715 if ((uint8_t *)item + sizeof(*item) > data) 1716 return -1; 1717 *item = (struct rte_flow_item){ 1718 .type = priv->type, 1719 }; 1720 ++out->args.vc.pattern_n; 1721 ctx->object = item; 1722 ctx->objmask = NULL; 1723 } else { 1724 const struct parse_action_priv *priv = token->priv; 1725 struct rte_flow_action *action = 1726 out->args.vc.actions + out->args.vc.actions_n; 1727 1728 data_size = priv->size; /* configuration */ 1729 data = (void *)RTE_ALIGN_FLOOR((uintptr_t) 1730 (out->args.vc.data - data_size), 1731 sizeof(double)); 1732 if ((uint8_t *)action + sizeof(*action) > data) 1733 return -1; 1734 *action = (struct rte_flow_action){ 1735 .type = priv->type, 1736 }; 1737 ++out->args.vc.actions_n; 1738 ctx->object = action; 1739 ctx->objmask = NULL; 1740 } 1741 memset(data, 0, data_size); 1742 out->args.vc.data = data; 1743 ctx->objdata = data_size; 1744 return len; 1745 } 1746 1747 /** Parse pattern item parameter type. */ 1748 static int 1749 parse_vc_spec(struct context *ctx, const struct token *token, 1750 const char *str, unsigned int len, 1751 void *buf, unsigned int size) 1752 { 1753 struct buffer *out = buf; 1754 struct rte_flow_item *item; 1755 uint32_t data_size; 1756 int index; 1757 int objmask = 0; 1758 1759 (void)size; 1760 /* Token name must match. */ 1761 if (parse_default(ctx, token, str, len, NULL, 0) < 0) 1762 return -1; 1763 /* Parse parameter types. */ 1764 switch (ctx->curr) { 1765 case ITEM_PARAM_IS: 1766 index = 0; 1767 objmask = 1; 1768 break; 1769 case ITEM_PARAM_SPEC: 1770 index = 0; 1771 break; 1772 case ITEM_PARAM_LAST: 1773 index = 1; 1774 break; 1775 case ITEM_PARAM_PREFIX: 1776 /* Modify next token to expect a prefix. */ 1777 if (ctx->next_num < 2) 1778 return -1; 1779 ctx->next[ctx->next_num - 2] = NEXT_ENTRY(PREFIX); 1780 /* Fall through. */ 1781 case ITEM_PARAM_MASK: 1782 index = 2; 1783 break; 1784 default: 1785 return -1; 1786 } 1787 /* Nothing else to do if there is no buffer. */ 1788 if (!out) 1789 return len; 1790 if (!out->args.vc.pattern_n) 1791 return -1; 1792 item = &out->args.vc.pattern[out->args.vc.pattern_n - 1]; 1793 data_size = ctx->objdata / 3; /* spec, last, mask */ 1794 /* Point to selected object. */ 1795 ctx->object = out->args.vc.data + (data_size * index); 1796 if (objmask) { 1797 ctx->objmask = out->args.vc.data + (data_size * 2); /* mask */ 1798 item->mask = ctx->objmask; 1799 } else 1800 ctx->objmask = NULL; 1801 /* Update relevant item pointer. */ 1802 *((const void **[]){ &item->spec, &item->last, &item->mask })[index] = 1803 ctx->object; 1804 return len; 1805 } 1806 1807 /** Parse action configuration field. */ 1808 static int 1809 parse_vc_conf(struct context *ctx, const struct token *token, 1810 const char *str, unsigned int len, 1811 void *buf, unsigned int size) 1812 { 1813 struct buffer *out = buf; 1814 struct rte_flow_action *action; 1815 1816 (void)size; 1817 /* Token name must match. */ 1818 if (parse_default(ctx, token, str, len, NULL, 0) < 0) 1819 return -1; 1820 /* Nothing else to do if there is no buffer. */ 1821 if (!out) 1822 return len; 1823 if (!out->args.vc.actions_n) 1824 return -1; 1825 action = &out->args.vc.actions[out->args.vc.actions_n - 1]; 1826 /* Point to selected object. */ 1827 ctx->object = out->args.vc.data; 1828 ctx->objmask = NULL; 1829 /* Update configuration pointer. */ 1830 action->conf = ctx->object; 1831 return len; 1832 } 1833 1834 /** 1835 * Parse queue field for RSS action. 1836 * 1837 * Valid tokens are queue indices and the "end" token. 1838 */ 1839 static int 1840 parse_vc_action_rss_queue(struct context *ctx, const struct token *token, 1841 const char *str, unsigned int len, 1842 void *buf, unsigned int size) 1843 { 1844 static const enum index next[] = NEXT_ENTRY(ACTION_RSS_QUEUE); 1845 int ret; 1846 int i; 1847 1848 (void)token; 1849 (void)buf; 1850 (void)size; 1851 if (ctx->curr != ACTION_RSS_QUEUE) 1852 return -1; 1853 i = ctx->objdata >> 16; 1854 if (!strncmp(str, "end", len)) { 1855 ctx->objdata &= 0xffff; 1856 return len; 1857 } 1858 if (i >= ACTION_RSS_NUM) 1859 return -1; 1860 if (push_args(ctx, ARGS_ENTRY(struct rte_flow_action_rss, queue[i]))) 1861 return -1; 1862 ret = parse_int(ctx, token, str, len, NULL, 0); 1863 if (ret < 0) { 1864 pop_args(ctx); 1865 return -1; 1866 } 1867 ++i; 1868 ctx->objdata = i << 16 | (ctx->objdata & 0xffff); 1869 /* Repeat token. */ 1870 if (ctx->next_num == RTE_DIM(ctx->next)) 1871 return -1; 1872 ctx->next[ctx->next_num++] = next; 1873 if (!ctx->object) 1874 return len; 1875 ((struct rte_flow_action_rss *)ctx->object)->num = i; 1876 return len; 1877 } 1878 1879 /** Parse tokens for destroy command. */ 1880 static int 1881 parse_destroy(struct context *ctx, const struct token *token, 1882 const char *str, unsigned int len, 1883 void *buf, unsigned int size) 1884 { 1885 struct buffer *out = buf; 1886 1887 /* Token name must match. */ 1888 if (parse_default(ctx, token, str, len, NULL, 0) < 0) 1889 return -1; 1890 /* Nothing else to do if there is no buffer. */ 1891 if (!out) 1892 return len; 1893 if (!out->command) { 1894 if (ctx->curr != DESTROY) 1895 return -1; 1896 if (sizeof(*out) > size) 1897 return -1; 1898 out->command = ctx->curr; 1899 ctx->objdata = 0; 1900 ctx->object = out; 1901 ctx->objmask = NULL; 1902 out->args.destroy.rule = 1903 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1), 1904 sizeof(double)); 1905 return len; 1906 } 1907 if (((uint8_t *)(out->args.destroy.rule + out->args.destroy.rule_n) + 1908 sizeof(*out->args.destroy.rule)) > (uint8_t *)out + size) 1909 return -1; 1910 ctx->objdata = 0; 1911 ctx->object = out->args.destroy.rule + out->args.destroy.rule_n++; 1912 ctx->objmask = NULL; 1913 return len; 1914 } 1915 1916 /** Parse tokens for flush command. */ 1917 static int 1918 parse_flush(struct context *ctx, const struct token *token, 1919 const char *str, unsigned int len, 1920 void *buf, unsigned int size) 1921 { 1922 struct buffer *out = buf; 1923 1924 /* Token name must match. */ 1925 if (parse_default(ctx, token, str, len, NULL, 0) < 0) 1926 return -1; 1927 /* Nothing else to do if there is no buffer. */ 1928 if (!out) 1929 return len; 1930 if (!out->command) { 1931 if (ctx->curr != FLUSH) 1932 return -1; 1933 if (sizeof(*out) > size) 1934 return -1; 1935 out->command = ctx->curr; 1936 ctx->objdata = 0; 1937 ctx->object = out; 1938 ctx->objmask = NULL; 1939 } 1940 return len; 1941 } 1942 1943 /** Parse tokens for query command. */ 1944 static int 1945 parse_query(struct context *ctx, const struct token *token, 1946 const char *str, unsigned int len, 1947 void *buf, unsigned int size) 1948 { 1949 struct buffer *out = buf; 1950 1951 /* Token name must match. */ 1952 if (parse_default(ctx, token, str, len, NULL, 0) < 0) 1953 return -1; 1954 /* Nothing else to do if there is no buffer. */ 1955 if (!out) 1956 return len; 1957 if (!out->command) { 1958 if (ctx->curr != QUERY) 1959 return -1; 1960 if (sizeof(*out) > size) 1961 return -1; 1962 out->command = ctx->curr; 1963 ctx->objdata = 0; 1964 ctx->object = out; 1965 ctx->objmask = NULL; 1966 } 1967 return len; 1968 } 1969 1970 /** Parse action names. */ 1971 static int 1972 parse_action(struct context *ctx, const struct token *token, 1973 const char *str, unsigned int len, 1974 void *buf, unsigned int size) 1975 { 1976 struct buffer *out = buf; 1977 const struct arg *arg = pop_args(ctx); 1978 unsigned int i; 1979 1980 (void)size; 1981 /* Argument is expected. */ 1982 if (!arg) 1983 return -1; 1984 /* Parse action name. */ 1985 for (i = 0; next_action[i]; ++i) { 1986 const struct parse_action_priv *priv; 1987 1988 token = &token_list[next_action[i]]; 1989 if (strncmp(token->name, str, len)) 1990 continue; 1991 priv = token->priv; 1992 if (!priv) 1993 goto error; 1994 if (out) 1995 memcpy((uint8_t *)ctx->object + arg->offset, 1996 &priv->type, 1997 arg->size); 1998 return len; 1999 } 2000 error: 2001 push_args(ctx, arg); 2002 return -1; 2003 } 2004 2005 /** Parse tokens for list command. */ 2006 static int 2007 parse_list(struct context *ctx, const struct token *token, 2008 const char *str, unsigned int len, 2009 void *buf, unsigned int size) 2010 { 2011 struct buffer *out = buf; 2012 2013 /* Token name must match. */ 2014 if (parse_default(ctx, token, str, len, NULL, 0) < 0) 2015 return -1; 2016 /* Nothing else to do if there is no buffer. */ 2017 if (!out) 2018 return len; 2019 if (!out->command) { 2020 if (ctx->curr != LIST) 2021 return -1; 2022 if (sizeof(*out) > size) 2023 return -1; 2024 out->command = ctx->curr; 2025 ctx->objdata = 0; 2026 ctx->object = out; 2027 ctx->objmask = NULL; 2028 out->args.list.group = 2029 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1), 2030 sizeof(double)); 2031 return len; 2032 } 2033 if (((uint8_t *)(out->args.list.group + out->args.list.group_n) + 2034 sizeof(*out->args.list.group)) > (uint8_t *)out + size) 2035 return -1; 2036 ctx->objdata = 0; 2037 ctx->object = out->args.list.group + out->args.list.group_n++; 2038 ctx->objmask = NULL; 2039 return len; 2040 } 2041 2042 /** 2043 * Parse signed/unsigned integers 8 to 64-bit long. 2044 * 2045 * Last argument (ctx->args) is retrieved to determine integer type and 2046 * storage location. 2047 */ 2048 static int 2049 parse_int(struct context *ctx, const struct token *token, 2050 const char *str, unsigned int len, 2051 void *buf, unsigned int size) 2052 { 2053 const struct arg *arg = pop_args(ctx); 2054 uintmax_t u; 2055 char *end; 2056 2057 (void)token; 2058 /* Argument is expected. */ 2059 if (!arg) 2060 return -1; 2061 errno = 0; 2062 u = arg->sign ? 2063 (uintmax_t)strtoimax(str, &end, 0) : 2064 strtoumax(str, &end, 0); 2065 if (errno || (size_t)(end - str) != len) 2066 goto error; 2067 if (!ctx->object) 2068 return len; 2069 if (arg->mask) { 2070 if (!arg_entry_bf_fill(ctx->object, u, arg) || 2071 !arg_entry_bf_fill(ctx->objmask, -1, arg)) 2072 goto error; 2073 return len; 2074 } 2075 buf = (uint8_t *)ctx->object + arg->offset; 2076 size = arg->size; 2077 objmask: 2078 switch (size) { 2079 case sizeof(uint8_t): 2080 *(uint8_t *)buf = u; 2081 break; 2082 case sizeof(uint16_t): 2083 *(uint16_t *)buf = arg->hton ? rte_cpu_to_be_16(u) : u; 2084 break; 2085 case sizeof(uint8_t [3]): 2086 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN 2087 if (!arg->hton) { 2088 ((uint8_t *)buf)[0] = u; 2089 ((uint8_t *)buf)[1] = u >> 8; 2090 ((uint8_t *)buf)[2] = u >> 16; 2091 break; 2092 } 2093 #endif 2094 ((uint8_t *)buf)[0] = u >> 16; 2095 ((uint8_t *)buf)[1] = u >> 8; 2096 ((uint8_t *)buf)[2] = u; 2097 break; 2098 case sizeof(uint32_t): 2099 *(uint32_t *)buf = arg->hton ? rte_cpu_to_be_32(u) : u; 2100 break; 2101 case sizeof(uint64_t): 2102 *(uint64_t *)buf = arg->hton ? rte_cpu_to_be_64(u) : u; 2103 break; 2104 default: 2105 goto error; 2106 } 2107 if (ctx->objmask && buf != (uint8_t *)ctx->objmask + arg->offset) { 2108 u = -1; 2109 buf = (uint8_t *)ctx->objmask + arg->offset; 2110 goto objmask; 2111 } 2112 return len; 2113 error: 2114 push_args(ctx, arg); 2115 return -1; 2116 } 2117 2118 /** 2119 * Parse a string. 2120 * 2121 * Two arguments (ctx->args) are retrieved from the stack to store data and 2122 * its length (in that order). 2123 */ 2124 static int 2125 parse_string(struct context *ctx, const struct token *token, 2126 const char *str, unsigned int len, 2127 void *buf, unsigned int size) 2128 { 2129 const struct arg *arg_data = pop_args(ctx); 2130 const struct arg *arg_len = pop_args(ctx); 2131 char tmp[16]; /* Ought to be enough. */ 2132 int ret; 2133 2134 /* Arguments are expected. */ 2135 if (!arg_data) 2136 return -1; 2137 if (!arg_len) { 2138 push_args(ctx, arg_data); 2139 return -1; 2140 } 2141 size = arg_data->size; 2142 /* Bit-mask fill is not supported. */ 2143 if (arg_data->mask || size < len) 2144 goto error; 2145 if (!ctx->object) 2146 return len; 2147 /* Let parse_int() fill length information first. */ 2148 ret = snprintf(tmp, sizeof(tmp), "%u", len); 2149 if (ret < 0) 2150 goto error; 2151 push_args(ctx, arg_len); 2152 ret = parse_int(ctx, token, tmp, ret, NULL, 0); 2153 if (ret < 0) { 2154 pop_args(ctx); 2155 goto error; 2156 } 2157 buf = (uint8_t *)ctx->object + arg_data->offset; 2158 /* Output buffer is not necessarily NUL-terminated. */ 2159 memcpy(buf, str, len); 2160 memset((uint8_t *)buf + len, 0x55, size - len); 2161 if (ctx->objmask) 2162 memset((uint8_t *)ctx->objmask + arg_data->offset, 0xff, len); 2163 return len; 2164 error: 2165 push_args(ctx, arg_len); 2166 push_args(ctx, arg_data); 2167 return -1; 2168 } 2169 2170 /** 2171 * Parse a MAC address. 2172 * 2173 * Last argument (ctx->args) is retrieved to determine storage size and 2174 * location. 2175 */ 2176 static int 2177 parse_mac_addr(struct context *ctx, const struct token *token, 2178 const char *str, unsigned int len, 2179 void *buf, unsigned int size) 2180 { 2181 const struct arg *arg = pop_args(ctx); 2182 struct ether_addr tmp; 2183 int ret; 2184 2185 (void)token; 2186 /* Argument is expected. */ 2187 if (!arg) 2188 return -1; 2189 size = arg->size; 2190 /* Bit-mask fill is not supported. */ 2191 if (arg->mask || size != sizeof(tmp)) 2192 goto error; 2193 ret = cmdline_parse_etheraddr(NULL, str, &tmp, size); 2194 if (ret < 0 || (unsigned int)ret != len) 2195 goto error; 2196 if (!ctx->object) 2197 return len; 2198 buf = (uint8_t *)ctx->object + arg->offset; 2199 memcpy(buf, &tmp, size); 2200 if (ctx->objmask) 2201 memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size); 2202 return len; 2203 error: 2204 push_args(ctx, arg); 2205 return -1; 2206 } 2207 2208 /** 2209 * Parse an IPv4 address. 2210 * 2211 * Last argument (ctx->args) is retrieved to determine storage size and 2212 * location. 2213 */ 2214 static int 2215 parse_ipv4_addr(struct context *ctx, const struct token *token, 2216 const char *str, unsigned int len, 2217 void *buf, unsigned int size) 2218 { 2219 const struct arg *arg = pop_args(ctx); 2220 char str2[len + 1]; 2221 struct in_addr tmp; 2222 int ret; 2223 2224 /* Argument is expected. */ 2225 if (!arg) 2226 return -1; 2227 size = arg->size; 2228 /* Bit-mask fill is not supported. */ 2229 if (arg->mask || size != sizeof(tmp)) 2230 goto error; 2231 /* Only network endian is supported. */ 2232 if (!arg->hton) 2233 goto error; 2234 memcpy(str2, str, len); 2235 str2[len] = '\0'; 2236 ret = inet_pton(AF_INET, str2, &tmp); 2237 if (ret != 1) { 2238 /* Attempt integer parsing. */ 2239 push_args(ctx, arg); 2240 return parse_int(ctx, token, str, len, buf, size); 2241 } 2242 if (!ctx->object) 2243 return len; 2244 buf = (uint8_t *)ctx->object + arg->offset; 2245 memcpy(buf, &tmp, size); 2246 if (ctx->objmask) 2247 memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size); 2248 return len; 2249 error: 2250 push_args(ctx, arg); 2251 return -1; 2252 } 2253 2254 /** 2255 * Parse an IPv6 address. 2256 * 2257 * Last argument (ctx->args) is retrieved to determine storage size and 2258 * location. 2259 */ 2260 static int 2261 parse_ipv6_addr(struct context *ctx, const struct token *token, 2262 const char *str, unsigned int len, 2263 void *buf, unsigned int size) 2264 { 2265 const struct arg *arg = pop_args(ctx); 2266 char str2[len + 1]; 2267 struct in6_addr tmp; 2268 int ret; 2269 2270 (void)token; 2271 /* Argument is expected. */ 2272 if (!arg) 2273 return -1; 2274 size = arg->size; 2275 /* Bit-mask fill is not supported. */ 2276 if (arg->mask || size != sizeof(tmp)) 2277 goto error; 2278 /* Only network endian is supported. */ 2279 if (!arg->hton) 2280 goto error; 2281 memcpy(str2, str, len); 2282 str2[len] = '\0'; 2283 ret = inet_pton(AF_INET6, str2, &tmp); 2284 if (ret != 1) 2285 goto error; 2286 if (!ctx->object) 2287 return len; 2288 buf = (uint8_t *)ctx->object + arg->offset; 2289 memcpy(buf, &tmp, size); 2290 if (ctx->objmask) 2291 memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size); 2292 return len; 2293 error: 2294 push_args(ctx, arg); 2295 return -1; 2296 } 2297 2298 /** Boolean values (even indices stand for false). */ 2299 static const char *const boolean_name[] = { 2300 "0", "1", 2301 "false", "true", 2302 "no", "yes", 2303 "N", "Y", 2304 NULL, 2305 }; 2306 2307 /** 2308 * Parse a boolean value. 2309 * 2310 * Last argument (ctx->args) is retrieved to determine storage size and 2311 * location. 2312 */ 2313 static int 2314 parse_boolean(struct context *ctx, const struct token *token, 2315 const char *str, unsigned int len, 2316 void *buf, unsigned int size) 2317 { 2318 const struct arg *arg = pop_args(ctx); 2319 unsigned int i; 2320 int ret; 2321 2322 /* Argument is expected. */ 2323 if (!arg) 2324 return -1; 2325 for (i = 0; boolean_name[i]; ++i) 2326 if (!strncmp(str, boolean_name[i], len)) 2327 break; 2328 /* Process token as integer. */ 2329 if (boolean_name[i]) 2330 str = i & 1 ? "1" : "0"; 2331 push_args(ctx, arg); 2332 ret = parse_int(ctx, token, str, strlen(str), buf, size); 2333 return ret > 0 ? (int)len : ret; 2334 } 2335 2336 /** Parse port and update context. */ 2337 static int 2338 parse_port(struct context *ctx, const struct token *token, 2339 const char *str, unsigned int len, 2340 void *buf, unsigned int size) 2341 { 2342 struct buffer *out = &(struct buffer){ .port = 0 }; 2343 int ret; 2344 2345 if (buf) 2346 out = buf; 2347 else { 2348 ctx->objdata = 0; 2349 ctx->object = out; 2350 ctx->objmask = NULL; 2351 size = sizeof(*out); 2352 } 2353 ret = parse_int(ctx, token, str, len, out, size); 2354 if (ret >= 0) 2355 ctx->port = out->port; 2356 if (!buf) 2357 ctx->object = NULL; 2358 return ret; 2359 } 2360 2361 /** No completion. */ 2362 static int 2363 comp_none(struct context *ctx, const struct token *token, 2364 unsigned int ent, char *buf, unsigned int size) 2365 { 2366 (void)ctx; 2367 (void)token; 2368 (void)ent; 2369 (void)buf; 2370 (void)size; 2371 return 0; 2372 } 2373 2374 /** Complete boolean values. */ 2375 static int 2376 comp_boolean(struct context *ctx, const struct token *token, 2377 unsigned int ent, char *buf, unsigned int size) 2378 { 2379 unsigned int i; 2380 2381 (void)ctx; 2382 (void)token; 2383 for (i = 0; boolean_name[i]; ++i) 2384 if (buf && i == ent) 2385 return snprintf(buf, size, "%s", boolean_name[i]); 2386 if (buf) 2387 return -1; 2388 return i; 2389 } 2390 2391 /** Complete action names. */ 2392 static int 2393 comp_action(struct context *ctx, const struct token *token, 2394 unsigned int ent, char *buf, unsigned int size) 2395 { 2396 unsigned int i; 2397 2398 (void)ctx; 2399 (void)token; 2400 for (i = 0; next_action[i]; ++i) 2401 if (buf && i == ent) 2402 return snprintf(buf, size, "%s", 2403 token_list[next_action[i]].name); 2404 if (buf) 2405 return -1; 2406 return i; 2407 } 2408 2409 /** Complete available ports. */ 2410 static int 2411 comp_port(struct context *ctx, const struct token *token, 2412 unsigned int ent, char *buf, unsigned int size) 2413 { 2414 unsigned int i = 0; 2415 portid_t p; 2416 2417 (void)ctx; 2418 (void)token; 2419 FOREACH_PORT(p, ports) { 2420 if (buf && i == ent) 2421 return snprintf(buf, size, "%u", p); 2422 ++i; 2423 } 2424 if (buf) 2425 return -1; 2426 return i; 2427 } 2428 2429 /** Complete available rule IDs. */ 2430 static int 2431 comp_rule_id(struct context *ctx, const struct token *token, 2432 unsigned int ent, char *buf, unsigned int size) 2433 { 2434 unsigned int i = 0; 2435 struct rte_port *port; 2436 struct port_flow *pf; 2437 2438 (void)token; 2439 if (port_id_is_invalid(ctx->port, DISABLED_WARN) || 2440 ctx->port == (uint16_t)RTE_PORT_ALL) 2441 return -1; 2442 port = &ports[ctx->port]; 2443 for (pf = port->flow_list; pf != NULL; pf = pf->next) { 2444 if (buf && i == ent) 2445 return snprintf(buf, size, "%u", pf->id); 2446 ++i; 2447 } 2448 if (buf) 2449 return -1; 2450 return i; 2451 } 2452 2453 /** Complete queue field for RSS action. */ 2454 static int 2455 comp_vc_action_rss_queue(struct context *ctx, const struct token *token, 2456 unsigned int ent, char *buf, unsigned int size) 2457 { 2458 static const char *const str[] = { "", "end", NULL }; 2459 unsigned int i; 2460 2461 (void)ctx; 2462 (void)token; 2463 for (i = 0; str[i] != NULL; ++i) 2464 if (buf && i == ent) 2465 return snprintf(buf, size, "%s", str[i]); 2466 if (buf) 2467 return -1; 2468 return i; 2469 } 2470 2471 /** Internal context. */ 2472 static struct context cmd_flow_context; 2473 2474 /** Global parser instance (cmdline API). */ 2475 cmdline_parse_inst_t cmd_flow; 2476 2477 /** Initialize context. */ 2478 static void 2479 cmd_flow_context_init(struct context *ctx) 2480 { 2481 /* A full memset() is not necessary. */ 2482 ctx->curr = ZERO; 2483 ctx->prev = ZERO; 2484 ctx->next_num = 0; 2485 ctx->args_num = 0; 2486 ctx->reparse = 0; 2487 ctx->eol = 0; 2488 ctx->last = 0; 2489 ctx->port = 0; 2490 ctx->objdata = 0; 2491 ctx->object = NULL; 2492 ctx->objmask = NULL; 2493 } 2494 2495 /** Parse a token (cmdline API). */ 2496 static int 2497 cmd_flow_parse(cmdline_parse_token_hdr_t *hdr, const char *src, void *result, 2498 unsigned int size) 2499 { 2500 struct context *ctx = &cmd_flow_context; 2501 const struct token *token; 2502 const enum index *list; 2503 int len; 2504 int i; 2505 2506 (void)hdr; 2507 /* Restart as requested. */ 2508 if (ctx->reparse) 2509 cmd_flow_context_init(ctx); 2510 token = &token_list[ctx->curr]; 2511 /* Check argument length. */ 2512 ctx->eol = 0; 2513 ctx->last = 1; 2514 for (len = 0; src[len]; ++len) 2515 if (src[len] == '#' || isspace(src[len])) 2516 break; 2517 if (!len) 2518 return -1; 2519 /* Last argument and EOL detection. */ 2520 for (i = len; src[i]; ++i) 2521 if (src[i] == '#' || src[i] == '\r' || src[i] == '\n') 2522 break; 2523 else if (!isspace(src[i])) { 2524 ctx->last = 0; 2525 break; 2526 } 2527 for (; src[i]; ++i) 2528 if (src[i] == '\r' || src[i] == '\n') { 2529 ctx->eol = 1; 2530 break; 2531 } 2532 /* Initialize context if necessary. */ 2533 if (!ctx->next_num) { 2534 if (!token->next) 2535 return 0; 2536 ctx->next[ctx->next_num++] = token->next[0]; 2537 } 2538 /* Process argument through candidates. */ 2539 ctx->prev = ctx->curr; 2540 list = ctx->next[ctx->next_num - 1]; 2541 for (i = 0; list[i]; ++i) { 2542 const struct token *next = &token_list[list[i]]; 2543 int tmp; 2544 2545 ctx->curr = list[i]; 2546 if (next->call) 2547 tmp = next->call(ctx, next, src, len, result, size); 2548 else 2549 tmp = parse_default(ctx, next, src, len, result, size); 2550 if (tmp == -1 || tmp != len) 2551 continue; 2552 token = next; 2553 break; 2554 } 2555 if (!list[i]) 2556 return -1; 2557 --ctx->next_num; 2558 /* Push subsequent tokens if any. */ 2559 if (token->next) 2560 for (i = 0; token->next[i]; ++i) { 2561 if (ctx->next_num == RTE_DIM(ctx->next)) 2562 return -1; 2563 ctx->next[ctx->next_num++] = token->next[i]; 2564 } 2565 /* Push arguments if any. */ 2566 if (token->args) 2567 for (i = 0; token->args[i]; ++i) { 2568 if (ctx->args_num == RTE_DIM(ctx->args)) 2569 return -1; 2570 ctx->args[ctx->args_num++] = token->args[i]; 2571 } 2572 return len; 2573 } 2574 2575 /** Return number of completion entries (cmdline API). */ 2576 static int 2577 cmd_flow_complete_get_nb(cmdline_parse_token_hdr_t *hdr) 2578 { 2579 struct context *ctx = &cmd_flow_context; 2580 const struct token *token = &token_list[ctx->curr]; 2581 const enum index *list; 2582 int i; 2583 2584 (void)hdr; 2585 /* Tell cmd_flow_parse() that context must be reinitialized. */ 2586 ctx->reparse = 1; 2587 /* Count number of tokens in current list. */ 2588 if (ctx->next_num) 2589 list = ctx->next[ctx->next_num - 1]; 2590 else 2591 list = token->next[0]; 2592 for (i = 0; list[i]; ++i) 2593 ; 2594 if (!i) 2595 return 0; 2596 /* 2597 * If there is a single token, use its completion callback, otherwise 2598 * return the number of entries. 2599 */ 2600 token = &token_list[list[0]]; 2601 if (i == 1 && token->comp) { 2602 /* Save index for cmd_flow_get_help(). */ 2603 ctx->prev = list[0]; 2604 return token->comp(ctx, token, 0, NULL, 0); 2605 } 2606 return i; 2607 } 2608 2609 /** Return a completion entry (cmdline API). */ 2610 static int 2611 cmd_flow_complete_get_elt(cmdline_parse_token_hdr_t *hdr, int index, 2612 char *dst, unsigned int size) 2613 { 2614 struct context *ctx = &cmd_flow_context; 2615 const struct token *token = &token_list[ctx->curr]; 2616 const enum index *list; 2617 int i; 2618 2619 (void)hdr; 2620 /* Tell cmd_flow_parse() that context must be reinitialized. */ 2621 ctx->reparse = 1; 2622 /* Count number of tokens in current list. */ 2623 if (ctx->next_num) 2624 list = ctx->next[ctx->next_num - 1]; 2625 else 2626 list = token->next[0]; 2627 for (i = 0; list[i]; ++i) 2628 ; 2629 if (!i) 2630 return -1; 2631 /* If there is a single token, use its completion callback. */ 2632 token = &token_list[list[0]]; 2633 if (i == 1 && token->comp) { 2634 /* Save index for cmd_flow_get_help(). */ 2635 ctx->prev = list[0]; 2636 return token->comp(ctx, token, index, dst, size) < 0 ? -1 : 0; 2637 } 2638 /* Otherwise make sure the index is valid and use defaults. */ 2639 if (index >= i) 2640 return -1; 2641 token = &token_list[list[index]]; 2642 snprintf(dst, size, "%s", token->name); 2643 /* Save index for cmd_flow_get_help(). */ 2644 ctx->prev = list[index]; 2645 return 0; 2646 } 2647 2648 /** Populate help strings for current token (cmdline API). */ 2649 static int 2650 cmd_flow_get_help(cmdline_parse_token_hdr_t *hdr, char *dst, unsigned int size) 2651 { 2652 struct context *ctx = &cmd_flow_context; 2653 const struct token *token = &token_list[ctx->prev]; 2654 2655 (void)hdr; 2656 /* Tell cmd_flow_parse() that context must be reinitialized. */ 2657 ctx->reparse = 1; 2658 if (!size) 2659 return -1; 2660 /* Set token type and update global help with details. */ 2661 snprintf(dst, size, "%s", (token->type ? token->type : "TOKEN")); 2662 if (token->help) 2663 cmd_flow.help_str = token->help; 2664 else 2665 cmd_flow.help_str = token->name; 2666 return 0; 2667 } 2668 2669 /** Token definition template (cmdline API). */ 2670 static struct cmdline_token_hdr cmd_flow_token_hdr = { 2671 .ops = &(struct cmdline_token_ops){ 2672 .parse = cmd_flow_parse, 2673 .complete_get_nb = cmd_flow_complete_get_nb, 2674 .complete_get_elt = cmd_flow_complete_get_elt, 2675 .get_help = cmd_flow_get_help, 2676 }, 2677 .offset = 0, 2678 }; 2679 2680 /** Populate the next dynamic token. */ 2681 static void 2682 cmd_flow_tok(cmdline_parse_token_hdr_t **hdr, 2683 cmdline_parse_token_hdr_t *(*hdrs)[]) 2684 { 2685 struct context *ctx = &cmd_flow_context; 2686 2687 /* Always reinitialize context before requesting the first token. */ 2688 if (!(hdr - *hdrs)) 2689 cmd_flow_context_init(ctx); 2690 /* Return NULL when no more tokens are expected. */ 2691 if (!ctx->next_num && ctx->curr) { 2692 *hdr = NULL; 2693 return; 2694 } 2695 /* Determine if command should end here. */ 2696 if (ctx->eol && ctx->last && ctx->next_num) { 2697 const enum index *list = ctx->next[ctx->next_num - 1]; 2698 int i; 2699 2700 for (i = 0; list[i]; ++i) { 2701 if (list[i] != END) 2702 continue; 2703 *hdr = NULL; 2704 return; 2705 } 2706 } 2707 *hdr = &cmd_flow_token_hdr; 2708 } 2709 2710 /** Dispatch parsed buffer to function calls. */ 2711 static void 2712 cmd_flow_parsed(const struct buffer *in) 2713 { 2714 switch (in->command) { 2715 case VALIDATE: 2716 port_flow_validate(in->port, &in->args.vc.attr, 2717 in->args.vc.pattern, in->args.vc.actions); 2718 break; 2719 case CREATE: 2720 port_flow_create(in->port, &in->args.vc.attr, 2721 in->args.vc.pattern, in->args.vc.actions); 2722 break; 2723 case DESTROY: 2724 port_flow_destroy(in->port, in->args.destroy.rule_n, 2725 in->args.destroy.rule); 2726 break; 2727 case FLUSH: 2728 port_flow_flush(in->port); 2729 break; 2730 case QUERY: 2731 port_flow_query(in->port, in->args.query.rule, 2732 in->args.query.action); 2733 break; 2734 case LIST: 2735 port_flow_list(in->port, in->args.list.group_n, 2736 in->args.list.group); 2737 break; 2738 default: 2739 break; 2740 } 2741 } 2742 2743 /** Token generator and output processing callback (cmdline API). */ 2744 static void 2745 cmd_flow_cb(void *arg0, struct cmdline *cl, void *arg2) 2746 { 2747 if (cl == NULL) 2748 cmd_flow_tok(arg0, arg2); 2749 else 2750 cmd_flow_parsed(arg0); 2751 } 2752 2753 /** Global parser instance (cmdline API). */ 2754 cmdline_parse_inst_t cmd_flow = { 2755 .f = cmd_flow_cb, 2756 .data = NULL, /**< Unused. */ 2757 .help_str = NULL, /**< Updated by cmd_flow_get_help(). */ 2758 .tokens = { 2759 NULL, 2760 }, /**< Tokens are returned by cmd_flow_tok(). */ 2761 }; 2762