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