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