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