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