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