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