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