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