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