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