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