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