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