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