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