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