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