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