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