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