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