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