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