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 3553 rte_eth_dev_info_get(ctx->port, &info); 3554 action_rss_data->conf.key_len = 3555 RTE_MIN(sizeof(action_rss_data->key), 3556 info.hash_key_size); 3557 } 3558 action->conf = &action_rss_data->conf; 3559 return ret; 3560 } 3561 3562 /** 3563 * Parse func field for RSS action. 3564 * 3565 * The RTE_ETH_HASH_FUNCTION_* value to assign is derived from the 3566 * ACTION_RSS_FUNC_* index that called this function. 3567 */ 3568 static int 3569 parse_vc_action_rss_func(struct context *ctx, const struct token *token, 3570 const char *str, unsigned int len, 3571 void *buf, unsigned int size) 3572 { 3573 struct action_rss_data *action_rss_data; 3574 enum rte_eth_hash_function func; 3575 3576 (void)buf; 3577 (void)size; 3578 /* Token name must match. */ 3579 if (parse_default(ctx, token, str, len, NULL, 0) < 0) 3580 return -1; 3581 switch (ctx->curr) { 3582 case ACTION_RSS_FUNC_DEFAULT: 3583 func = RTE_ETH_HASH_FUNCTION_DEFAULT; 3584 break; 3585 case ACTION_RSS_FUNC_TOEPLITZ: 3586 func = RTE_ETH_HASH_FUNCTION_TOEPLITZ; 3587 break; 3588 case ACTION_RSS_FUNC_SIMPLE_XOR: 3589 func = RTE_ETH_HASH_FUNCTION_SIMPLE_XOR; 3590 break; 3591 default: 3592 return -1; 3593 } 3594 if (!ctx->object) 3595 return len; 3596 action_rss_data = ctx->object; 3597 action_rss_data->conf.func = func; 3598 return len; 3599 } 3600 3601 /** 3602 * Parse type field for RSS action. 3603 * 3604 * Valid tokens are type field names and the "end" token. 3605 */ 3606 static int 3607 parse_vc_action_rss_type(struct context *ctx, const struct token *token, 3608 const char *str, unsigned int len, 3609 void *buf, unsigned int size) 3610 { 3611 static const enum index next[] = NEXT_ENTRY(ACTION_RSS_TYPE); 3612 struct action_rss_data *action_rss_data; 3613 unsigned int i; 3614 3615 (void)token; 3616 (void)buf; 3617 (void)size; 3618 if (ctx->curr != ACTION_RSS_TYPE) 3619 return -1; 3620 if (!(ctx->objdata >> 16) && ctx->object) { 3621 action_rss_data = ctx->object; 3622 action_rss_data->conf.types = 0; 3623 } 3624 if (!strcmp_partial("end", str, len)) { 3625 ctx->objdata &= 0xffff; 3626 return len; 3627 } 3628 for (i = 0; rss_type_table[i].str; ++i) 3629 if (!strcmp_partial(rss_type_table[i].str, str, len)) 3630 break; 3631 if (!rss_type_table[i].str) 3632 return -1; 3633 ctx->objdata = 1 << 16 | (ctx->objdata & 0xffff); 3634 /* Repeat token. */ 3635 if (ctx->next_num == RTE_DIM(ctx->next)) 3636 return -1; 3637 ctx->next[ctx->next_num++] = next; 3638 if (!ctx->object) 3639 return len; 3640 action_rss_data = ctx->object; 3641 action_rss_data->conf.types |= rss_type_table[i].rss_type; 3642 return len; 3643 } 3644 3645 /** 3646 * Parse queue field for RSS action. 3647 * 3648 * Valid tokens are queue indices and the "end" token. 3649 */ 3650 static int 3651 parse_vc_action_rss_queue(struct context *ctx, const struct token *token, 3652 const char *str, unsigned int len, 3653 void *buf, unsigned int size) 3654 { 3655 static const enum index next[] = NEXT_ENTRY(ACTION_RSS_QUEUE); 3656 struct action_rss_data *action_rss_data; 3657 const struct arg *arg; 3658 int ret; 3659 int i; 3660 3661 (void)token; 3662 (void)buf; 3663 (void)size; 3664 if (ctx->curr != ACTION_RSS_QUEUE) 3665 return -1; 3666 i = ctx->objdata >> 16; 3667 if (!strcmp_partial("end", str, len)) { 3668 ctx->objdata &= 0xffff; 3669 goto end; 3670 } 3671 if (i >= ACTION_RSS_QUEUE_NUM) 3672 return -1; 3673 arg = ARGS_ENTRY_ARB(offsetof(struct action_rss_data, queue) + 3674 i * sizeof(action_rss_data->queue[i]), 3675 sizeof(action_rss_data->queue[i])); 3676 if (push_args(ctx, arg)) 3677 return -1; 3678 ret = parse_int(ctx, token, str, len, NULL, 0); 3679 if (ret < 0) { 3680 pop_args(ctx); 3681 return -1; 3682 } 3683 ++i; 3684 ctx->objdata = i << 16 | (ctx->objdata & 0xffff); 3685 /* Repeat token. */ 3686 if (ctx->next_num == RTE_DIM(ctx->next)) 3687 return -1; 3688 ctx->next[ctx->next_num++] = next; 3689 end: 3690 if (!ctx->object) 3691 return len; 3692 action_rss_data = ctx->object; 3693 action_rss_data->conf.queue_num = i; 3694 action_rss_data->conf.queue = i ? action_rss_data->queue : NULL; 3695 return len; 3696 } 3697 3698 /** Parse VXLAN encap action. */ 3699 static int 3700 parse_vc_action_vxlan_encap(struct context *ctx, const struct token *token, 3701 const char *str, unsigned int len, 3702 void *buf, unsigned int size) 3703 { 3704 struct buffer *out = buf; 3705 struct rte_flow_action *action; 3706 struct action_vxlan_encap_data *action_vxlan_encap_data; 3707 int ret; 3708 3709 ret = parse_vc(ctx, token, str, len, buf, size); 3710 if (ret < 0) 3711 return ret; 3712 /* Nothing else to do if there is no buffer. */ 3713 if (!out) 3714 return ret; 3715 if (!out->args.vc.actions_n) 3716 return -1; 3717 action = &out->args.vc.actions[out->args.vc.actions_n - 1]; 3718 /* Point to selected object. */ 3719 ctx->object = out->args.vc.data; 3720 ctx->objmask = NULL; 3721 /* Set up default configuration. */ 3722 action_vxlan_encap_data = ctx->object; 3723 *action_vxlan_encap_data = (struct action_vxlan_encap_data){ 3724 .conf = (struct rte_flow_action_vxlan_encap){ 3725 .definition = action_vxlan_encap_data->items, 3726 }, 3727 .items = { 3728 { 3729 .type = RTE_FLOW_ITEM_TYPE_ETH, 3730 .spec = &action_vxlan_encap_data->item_eth, 3731 .mask = &rte_flow_item_eth_mask, 3732 }, 3733 { 3734 .type = RTE_FLOW_ITEM_TYPE_VLAN, 3735 .spec = &action_vxlan_encap_data->item_vlan, 3736 .mask = &rte_flow_item_vlan_mask, 3737 }, 3738 { 3739 .type = RTE_FLOW_ITEM_TYPE_IPV4, 3740 .spec = &action_vxlan_encap_data->item_ipv4, 3741 .mask = &rte_flow_item_ipv4_mask, 3742 }, 3743 { 3744 .type = RTE_FLOW_ITEM_TYPE_UDP, 3745 .spec = &action_vxlan_encap_data->item_udp, 3746 .mask = &rte_flow_item_udp_mask, 3747 }, 3748 { 3749 .type = RTE_FLOW_ITEM_TYPE_VXLAN, 3750 .spec = &action_vxlan_encap_data->item_vxlan, 3751 .mask = &rte_flow_item_vxlan_mask, 3752 }, 3753 { 3754 .type = RTE_FLOW_ITEM_TYPE_END, 3755 }, 3756 }, 3757 .item_eth.type = 0, 3758 .item_vlan = { 3759 .tci = vxlan_encap_conf.vlan_tci, 3760 .inner_type = 0, 3761 }, 3762 .item_ipv4.hdr = { 3763 .src_addr = vxlan_encap_conf.ipv4_src, 3764 .dst_addr = vxlan_encap_conf.ipv4_dst, 3765 }, 3766 .item_udp.hdr = { 3767 .src_port = vxlan_encap_conf.udp_src, 3768 .dst_port = vxlan_encap_conf.udp_dst, 3769 }, 3770 .item_vxlan.flags = 0, 3771 }; 3772 memcpy(action_vxlan_encap_data->item_eth.dst.addr_bytes, 3773 vxlan_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN); 3774 memcpy(action_vxlan_encap_data->item_eth.src.addr_bytes, 3775 vxlan_encap_conf.eth_src, RTE_ETHER_ADDR_LEN); 3776 if (!vxlan_encap_conf.select_ipv4) { 3777 memcpy(&action_vxlan_encap_data->item_ipv6.hdr.src_addr, 3778 &vxlan_encap_conf.ipv6_src, 3779 sizeof(vxlan_encap_conf.ipv6_src)); 3780 memcpy(&action_vxlan_encap_data->item_ipv6.hdr.dst_addr, 3781 &vxlan_encap_conf.ipv6_dst, 3782 sizeof(vxlan_encap_conf.ipv6_dst)); 3783 action_vxlan_encap_data->items[2] = (struct rte_flow_item){ 3784 .type = RTE_FLOW_ITEM_TYPE_IPV6, 3785 .spec = &action_vxlan_encap_data->item_ipv6, 3786 .mask = &rte_flow_item_ipv6_mask, 3787 }; 3788 } 3789 if (!vxlan_encap_conf.select_vlan) 3790 action_vxlan_encap_data->items[1].type = 3791 RTE_FLOW_ITEM_TYPE_VOID; 3792 if (vxlan_encap_conf.select_tos_ttl) { 3793 if (vxlan_encap_conf.select_ipv4) { 3794 static struct rte_flow_item_ipv4 ipv4_mask_tos; 3795 3796 memcpy(&ipv4_mask_tos, &rte_flow_item_ipv4_mask, 3797 sizeof(ipv4_mask_tos)); 3798 ipv4_mask_tos.hdr.type_of_service = 0xff; 3799 ipv4_mask_tos.hdr.time_to_live = 0xff; 3800 action_vxlan_encap_data->item_ipv4.hdr.type_of_service = 3801 vxlan_encap_conf.ip_tos; 3802 action_vxlan_encap_data->item_ipv4.hdr.time_to_live = 3803 vxlan_encap_conf.ip_ttl; 3804 action_vxlan_encap_data->items[2].mask = 3805 &ipv4_mask_tos; 3806 } else { 3807 static struct rte_flow_item_ipv6 ipv6_mask_tos; 3808 3809 memcpy(&ipv6_mask_tos, &rte_flow_item_ipv6_mask, 3810 sizeof(ipv6_mask_tos)); 3811 ipv6_mask_tos.hdr.vtc_flow |= 3812 RTE_BE32(0xfful << RTE_IPV6_HDR_TC_SHIFT); 3813 ipv6_mask_tos.hdr.hop_limits = 0xff; 3814 action_vxlan_encap_data->item_ipv6.hdr.vtc_flow |= 3815 rte_cpu_to_be_32 3816 ((uint32_t)vxlan_encap_conf.ip_tos << 3817 RTE_IPV6_HDR_TC_SHIFT); 3818 action_vxlan_encap_data->item_ipv6.hdr.hop_limits = 3819 vxlan_encap_conf.ip_ttl; 3820 action_vxlan_encap_data->items[2].mask = 3821 &ipv6_mask_tos; 3822 } 3823 } 3824 memcpy(action_vxlan_encap_data->item_vxlan.vni, vxlan_encap_conf.vni, 3825 RTE_DIM(vxlan_encap_conf.vni)); 3826 action->conf = &action_vxlan_encap_data->conf; 3827 return ret; 3828 } 3829 3830 /** Parse NVGRE encap action. */ 3831 static int 3832 parse_vc_action_nvgre_encap(struct context *ctx, const struct token *token, 3833 const char *str, unsigned int len, 3834 void *buf, unsigned int size) 3835 { 3836 struct buffer *out = buf; 3837 struct rte_flow_action *action; 3838 struct action_nvgre_encap_data *action_nvgre_encap_data; 3839 int ret; 3840 3841 ret = parse_vc(ctx, token, str, len, buf, size); 3842 if (ret < 0) 3843 return ret; 3844 /* Nothing else to do if there is no buffer. */ 3845 if (!out) 3846 return ret; 3847 if (!out->args.vc.actions_n) 3848 return -1; 3849 action = &out->args.vc.actions[out->args.vc.actions_n - 1]; 3850 /* Point to selected object. */ 3851 ctx->object = out->args.vc.data; 3852 ctx->objmask = NULL; 3853 /* Set up default configuration. */ 3854 action_nvgre_encap_data = ctx->object; 3855 *action_nvgre_encap_data = (struct action_nvgre_encap_data){ 3856 .conf = (struct rte_flow_action_nvgre_encap){ 3857 .definition = action_nvgre_encap_data->items, 3858 }, 3859 .items = { 3860 { 3861 .type = RTE_FLOW_ITEM_TYPE_ETH, 3862 .spec = &action_nvgre_encap_data->item_eth, 3863 .mask = &rte_flow_item_eth_mask, 3864 }, 3865 { 3866 .type = RTE_FLOW_ITEM_TYPE_VLAN, 3867 .spec = &action_nvgre_encap_data->item_vlan, 3868 .mask = &rte_flow_item_vlan_mask, 3869 }, 3870 { 3871 .type = RTE_FLOW_ITEM_TYPE_IPV4, 3872 .spec = &action_nvgre_encap_data->item_ipv4, 3873 .mask = &rte_flow_item_ipv4_mask, 3874 }, 3875 { 3876 .type = RTE_FLOW_ITEM_TYPE_NVGRE, 3877 .spec = &action_nvgre_encap_data->item_nvgre, 3878 .mask = &rte_flow_item_nvgre_mask, 3879 }, 3880 { 3881 .type = RTE_FLOW_ITEM_TYPE_END, 3882 }, 3883 }, 3884 .item_eth.type = 0, 3885 .item_vlan = { 3886 .tci = nvgre_encap_conf.vlan_tci, 3887 .inner_type = 0, 3888 }, 3889 .item_ipv4.hdr = { 3890 .src_addr = nvgre_encap_conf.ipv4_src, 3891 .dst_addr = nvgre_encap_conf.ipv4_dst, 3892 }, 3893 .item_nvgre.flow_id = 0, 3894 }; 3895 memcpy(action_nvgre_encap_data->item_eth.dst.addr_bytes, 3896 nvgre_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN); 3897 memcpy(action_nvgre_encap_data->item_eth.src.addr_bytes, 3898 nvgre_encap_conf.eth_src, RTE_ETHER_ADDR_LEN); 3899 if (!nvgre_encap_conf.select_ipv4) { 3900 memcpy(&action_nvgre_encap_data->item_ipv6.hdr.src_addr, 3901 &nvgre_encap_conf.ipv6_src, 3902 sizeof(nvgre_encap_conf.ipv6_src)); 3903 memcpy(&action_nvgre_encap_data->item_ipv6.hdr.dst_addr, 3904 &nvgre_encap_conf.ipv6_dst, 3905 sizeof(nvgre_encap_conf.ipv6_dst)); 3906 action_nvgre_encap_data->items[2] = (struct rte_flow_item){ 3907 .type = RTE_FLOW_ITEM_TYPE_IPV6, 3908 .spec = &action_nvgre_encap_data->item_ipv6, 3909 .mask = &rte_flow_item_ipv6_mask, 3910 }; 3911 } 3912 if (!nvgre_encap_conf.select_vlan) 3913 action_nvgre_encap_data->items[1].type = 3914 RTE_FLOW_ITEM_TYPE_VOID; 3915 memcpy(action_nvgre_encap_data->item_nvgre.tni, nvgre_encap_conf.tni, 3916 RTE_DIM(nvgre_encap_conf.tni)); 3917 action->conf = &action_nvgre_encap_data->conf; 3918 return ret; 3919 } 3920 3921 /** Parse l2 encap action. */ 3922 static int 3923 parse_vc_action_l2_encap(struct context *ctx, const struct token *token, 3924 const char *str, unsigned int len, 3925 void *buf, unsigned int size) 3926 { 3927 struct buffer *out = buf; 3928 struct rte_flow_action *action; 3929 struct action_raw_encap_data *action_encap_data; 3930 struct rte_flow_item_eth eth = { .type = 0, }; 3931 struct rte_flow_item_vlan vlan = { 3932 .tci = mplsoudp_encap_conf.vlan_tci, 3933 .inner_type = 0, 3934 }; 3935 uint8_t *header; 3936 int ret; 3937 3938 ret = parse_vc(ctx, token, str, len, buf, size); 3939 if (ret < 0) 3940 return ret; 3941 /* Nothing else to do if there is no buffer. */ 3942 if (!out) 3943 return ret; 3944 if (!out->args.vc.actions_n) 3945 return -1; 3946 action = &out->args.vc.actions[out->args.vc.actions_n - 1]; 3947 /* Point to selected object. */ 3948 ctx->object = out->args.vc.data; 3949 ctx->objmask = NULL; 3950 /* Copy the headers to the buffer. */ 3951 action_encap_data = ctx->object; 3952 *action_encap_data = (struct action_raw_encap_data) { 3953 .conf = (struct rte_flow_action_raw_encap){ 3954 .data = action_encap_data->data, 3955 }, 3956 .data = {}, 3957 }; 3958 header = action_encap_data->data; 3959 if (l2_encap_conf.select_vlan) 3960 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN); 3961 else if (l2_encap_conf.select_ipv4) 3962 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4); 3963 else 3964 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6); 3965 memcpy(eth.dst.addr_bytes, 3966 l2_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN); 3967 memcpy(eth.src.addr_bytes, 3968 l2_encap_conf.eth_src, RTE_ETHER_ADDR_LEN); 3969 memcpy(header, ð, sizeof(eth)); 3970 header += sizeof(eth); 3971 if (l2_encap_conf.select_vlan) { 3972 if (l2_encap_conf.select_ipv4) 3973 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4); 3974 else 3975 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6); 3976 memcpy(header, &vlan, sizeof(vlan)); 3977 header += sizeof(vlan); 3978 } 3979 action_encap_data->conf.size = header - 3980 action_encap_data->data; 3981 action->conf = &action_encap_data->conf; 3982 return ret; 3983 } 3984 3985 /** Parse l2 decap action. */ 3986 static int 3987 parse_vc_action_l2_decap(struct context *ctx, const struct token *token, 3988 const char *str, unsigned int len, 3989 void *buf, unsigned int size) 3990 { 3991 struct buffer *out = buf; 3992 struct rte_flow_action *action; 3993 struct action_raw_decap_data *action_decap_data; 3994 struct rte_flow_item_eth eth = { .type = 0, }; 3995 struct rte_flow_item_vlan vlan = { 3996 .tci = mplsoudp_encap_conf.vlan_tci, 3997 .inner_type = 0, 3998 }; 3999 uint8_t *header; 4000 int ret; 4001 4002 ret = parse_vc(ctx, token, str, len, buf, size); 4003 if (ret < 0) 4004 return ret; 4005 /* Nothing else to do if there is no buffer. */ 4006 if (!out) 4007 return ret; 4008 if (!out->args.vc.actions_n) 4009 return -1; 4010 action = &out->args.vc.actions[out->args.vc.actions_n - 1]; 4011 /* Point to selected object. */ 4012 ctx->object = out->args.vc.data; 4013 ctx->objmask = NULL; 4014 /* Copy the headers to the buffer. */ 4015 action_decap_data = ctx->object; 4016 *action_decap_data = (struct action_raw_decap_data) { 4017 .conf = (struct rte_flow_action_raw_decap){ 4018 .data = action_decap_data->data, 4019 }, 4020 .data = {}, 4021 }; 4022 header = action_decap_data->data; 4023 if (l2_decap_conf.select_vlan) 4024 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN); 4025 memcpy(header, ð, sizeof(eth)); 4026 header += sizeof(eth); 4027 if (l2_decap_conf.select_vlan) { 4028 memcpy(header, &vlan, sizeof(vlan)); 4029 header += sizeof(vlan); 4030 } 4031 action_decap_data->conf.size = header - 4032 action_decap_data->data; 4033 action->conf = &action_decap_data->conf; 4034 return ret; 4035 } 4036 4037 #define ETHER_TYPE_MPLS_UNICAST 0x8847 4038 4039 /** Parse MPLSOGRE encap action. */ 4040 static int 4041 parse_vc_action_mplsogre_encap(struct context *ctx, const struct token *token, 4042 const char *str, unsigned int len, 4043 void *buf, unsigned int size) 4044 { 4045 struct buffer *out = buf; 4046 struct rte_flow_action *action; 4047 struct action_raw_encap_data *action_encap_data; 4048 struct rte_flow_item_eth eth = { .type = 0, }; 4049 struct rte_flow_item_vlan vlan = { 4050 .tci = mplsogre_encap_conf.vlan_tci, 4051 .inner_type = 0, 4052 }; 4053 struct rte_flow_item_ipv4 ipv4 = { 4054 .hdr = { 4055 .src_addr = mplsogre_encap_conf.ipv4_src, 4056 .dst_addr = mplsogre_encap_conf.ipv4_dst, 4057 .next_proto_id = IPPROTO_GRE, 4058 .version_ihl = RTE_IPV4_VHL_DEF, 4059 .time_to_live = IPDEFTTL, 4060 }, 4061 }; 4062 struct rte_flow_item_ipv6 ipv6 = { 4063 .hdr = { 4064 .proto = IPPROTO_GRE, 4065 .hop_limits = IPDEFTTL, 4066 }, 4067 }; 4068 struct rte_flow_item_gre gre = { 4069 .protocol = rte_cpu_to_be_16(ETHER_TYPE_MPLS_UNICAST), 4070 }; 4071 struct rte_flow_item_mpls mpls; 4072 uint8_t *header; 4073 int ret; 4074 4075 ret = parse_vc(ctx, token, str, len, buf, size); 4076 if (ret < 0) 4077 return ret; 4078 /* Nothing else to do if there is no buffer. */ 4079 if (!out) 4080 return ret; 4081 if (!out->args.vc.actions_n) 4082 return -1; 4083 action = &out->args.vc.actions[out->args.vc.actions_n - 1]; 4084 /* Point to selected object. */ 4085 ctx->object = out->args.vc.data; 4086 ctx->objmask = NULL; 4087 /* Copy the headers to the buffer. */ 4088 action_encap_data = ctx->object; 4089 *action_encap_data = (struct action_raw_encap_data) { 4090 .conf = (struct rte_flow_action_raw_encap){ 4091 .data = action_encap_data->data, 4092 }, 4093 .data = {}, 4094 .preserve = {}, 4095 }; 4096 header = action_encap_data->data; 4097 if (mplsogre_encap_conf.select_vlan) 4098 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN); 4099 else if (mplsogre_encap_conf.select_ipv4) 4100 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4); 4101 else 4102 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6); 4103 memcpy(eth.dst.addr_bytes, 4104 mplsogre_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN); 4105 memcpy(eth.src.addr_bytes, 4106 mplsogre_encap_conf.eth_src, RTE_ETHER_ADDR_LEN); 4107 memcpy(header, ð, sizeof(eth)); 4108 header += sizeof(eth); 4109 if (mplsogre_encap_conf.select_vlan) { 4110 if (mplsogre_encap_conf.select_ipv4) 4111 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4); 4112 else 4113 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6); 4114 memcpy(header, &vlan, sizeof(vlan)); 4115 header += sizeof(vlan); 4116 } 4117 if (mplsogre_encap_conf.select_ipv4) { 4118 memcpy(header, &ipv4, sizeof(ipv4)); 4119 header += sizeof(ipv4); 4120 } else { 4121 memcpy(&ipv6.hdr.src_addr, 4122 &mplsogre_encap_conf.ipv6_src, 4123 sizeof(mplsogre_encap_conf.ipv6_src)); 4124 memcpy(&ipv6.hdr.dst_addr, 4125 &mplsogre_encap_conf.ipv6_dst, 4126 sizeof(mplsogre_encap_conf.ipv6_dst)); 4127 memcpy(header, &ipv6, sizeof(ipv6)); 4128 header += sizeof(ipv6); 4129 } 4130 memcpy(header, &gre, sizeof(gre)); 4131 header += sizeof(gre); 4132 memcpy(mpls.label_tc_s, mplsogre_encap_conf.label, 4133 RTE_DIM(mplsogre_encap_conf.label)); 4134 mpls.label_tc_s[2] |= 0x1; 4135 memcpy(header, &mpls, sizeof(mpls)); 4136 header += sizeof(mpls); 4137 action_encap_data->conf.size = header - 4138 action_encap_data->data; 4139 action->conf = &action_encap_data->conf; 4140 return ret; 4141 } 4142 4143 /** Parse MPLSOGRE decap action. */ 4144 static int 4145 parse_vc_action_mplsogre_decap(struct context *ctx, const struct token *token, 4146 const char *str, unsigned int len, 4147 void *buf, unsigned int size) 4148 { 4149 struct buffer *out = buf; 4150 struct rte_flow_action *action; 4151 struct action_raw_decap_data *action_decap_data; 4152 struct rte_flow_item_eth eth = { .type = 0, }; 4153 struct rte_flow_item_vlan vlan = {.tci = 0}; 4154 struct rte_flow_item_ipv4 ipv4 = { 4155 .hdr = { 4156 .next_proto_id = IPPROTO_GRE, 4157 }, 4158 }; 4159 struct rte_flow_item_ipv6 ipv6 = { 4160 .hdr = { 4161 .proto = IPPROTO_GRE, 4162 }, 4163 }; 4164 struct rte_flow_item_gre gre = { 4165 .protocol = rte_cpu_to_be_16(ETHER_TYPE_MPLS_UNICAST), 4166 }; 4167 struct rte_flow_item_mpls mpls; 4168 uint8_t *header; 4169 int ret; 4170 4171 ret = parse_vc(ctx, token, str, len, buf, size); 4172 if (ret < 0) 4173 return ret; 4174 /* Nothing else to do if there is no buffer. */ 4175 if (!out) 4176 return ret; 4177 if (!out->args.vc.actions_n) 4178 return -1; 4179 action = &out->args.vc.actions[out->args.vc.actions_n - 1]; 4180 /* Point to selected object. */ 4181 ctx->object = out->args.vc.data; 4182 ctx->objmask = NULL; 4183 /* Copy the headers to the buffer. */ 4184 action_decap_data = ctx->object; 4185 *action_decap_data = (struct action_raw_decap_data) { 4186 .conf = (struct rte_flow_action_raw_decap){ 4187 .data = action_decap_data->data, 4188 }, 4189 .data = {}, 4190 }; 4191 header = action_decap_data->data; 4192 if (mplsogre_decap_conf.select_vlan) 4193 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN); 4194 else if (mplsogre_encap_conf.select_ipv4) 4195 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4); 4196 else 4197 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6); 4198 memcpy(eth.dst.addr_bytes, 4199 mplsogre_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN); 4200 memcpy(eth.src.addr_bytes, 4201 mplsogre_encap_conf.eth_src, RTE_ETHER_ADDR_LEN); 4202 memcpy(header, ð, sizeof(eth)); 4203 header += sizeof(eth); 4204 if (mplsogre_encap_conf.select_vlan) { 4205 if (mplsogre_encap_conf.select_ipv4) 4206 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4); 4207 else 4208 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6); 4209 memcpy(header, &vlan, sizeof(vlan)); 4210 header += sizeof(vlan); 4211 } 4212 if (mplsogre_encap_conf.select_ipv4) { 4213 memcpy(header, &ipv4, sizeof(ipv4)); 4214 header += sizeof(ipv4); 4215 } else { 4216 memcpy(header, &ipv6, sizeof(ipv6)); 4217 header += sizeof(ipv6); 4218 } 4219 memcpy(header, &gre, sizeof(gre)); 4220 header += sizeof(gre); 4221 memset(&mpls, 0, sizeof(mpls)); 4222 memcpy(header, &mpls, sizeof(mpls)); 4223 header += sizeof(mpls); 4224 action_decap_data->conf.size = header - 4225 action_decap_data->data; 4226 action->conf = &action_decap_data->conf; 4227 return ret; 4228 } 4229 4230 /** Parse MPLSOUDP encap action. */ 4231 static int 4232 parse_vc_action_mplsoudp_encap(struct context *ctx, const struct token *token, 4233 const char *str, unsigned int len, 4234 void *buf, unsigned int size) 4235 { 4236 struct buffer *out = buf; 4237 struct rte_flow_action *action; 4238 struct action_raw_encap_data *action_encap_data; 4239 struct rte_flow_item_eth eth = { .type = 0, }; 4240 struct rte_flow_item_vlan vlan = { 4241 .tci = mplsoudp_encap_conf.vlan_tci, 4242 .inner_type = 0, 4243 }; 4244 struct rte_flow_item_ipv4 ipv4 = { 4245 .hdr = { 4246 .src_addr = mplsoudp_encap_conf.ipv4_src, 4247 .dst_addr = mplsoudp_encap_conf.ipv4_dst, 4248 .next_proto_id = IPPROTO_UDP, 4249 .version_ihl = RTE_IPV4_VHL_DEF, 4250 .time_to_live = IPDEFTTL, 4251 }, 4252 }; 4253 struct rte_flow_item_ipv6 ipv6 = { 4254 .hdr = { 4255 .proto = IPPROTO_UDP, 4256 .hop_limits = IPDEFTTL, 4257 }, 4258 }; 4259 struct rte_flow_item_udp udp = { 4260 .hdr = { 4261 .src_port = mplsoudp_encap_conf.udp_src, 4262 .dst_port = mplsoudp_encap_conf.udp_dst, 4263 }, 4264 }; 4265 struct rte_flow_item_mpls mpls; 4266 uint8_t *header; 4267 int ret; 4268 4269 ret = parse_vc(ctx, token, str, len, buf, size); 4270 if (ret < 0) 4271 return ret; 4272 /* Nothing else to do if there is no buffer. */ 4273 if (!out) 4274 return ret; 4275 if (!out->args.vc.actions_n) 4276 return -1; 4277 action = &out->args.vc.actions[out->args.vc.actions_n - 1]; 4278 /* Point to selected object. */ 4279 ctx->object = out->args.vc.data; 4280 ctx->objmask = NULL; 4281 /* Copy the headers to the buffer. */ 4282 action_encap_data = ctx->object; 4283 *action_encap_data = (struct action_raw_encap_data) { 4284 .conf = (struct rte_flow_action_raw_encap){ 4285 .data = action_encap_data->data, 4286 }, 4287 .data = {}, 4288 .preserve = {}, 4289 }; 4290 header = action_encap_data->data; 4291 if (mplsoudp_encap_conf.select_vlan) 4292 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN); 4293 else if (mplsoudp_encap_conf.select_ipv4) 4294 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4); 4295 else 4296 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6); 4297 memcpy(eth.dst.addr_bytes, 4298 mplsoudp_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN); 4299 memcpy(eth.src.addr_bytes, 4300 mplsoudp_encap_conf.eth_src, RTE_ETHER_ADDR_LEN); 4301 memcpy(header, ð, sizeof(eth)); 4302 header += sizeof(eth); 4303 if (mplsoudp_encap_conf.select_vlan) { 4304 if (mplsoudp_encap_conf.select_ipv4) 4305 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4); 4306 else 4307 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6); 4308 memcpy(header, &vlan, sizeof(vlan)); 4309 header += sizeof(vlan); 4310 } 4311 if (mplsoudp_encap_conf.select_ipv4) { 4312 memcpy(header, &ipv4, sizeof(ipv4)); 4313 header += sizeof(ipv4); 4314 } else { 4315 memcpy(&ipv6.hdr.src_addr, 4316 &mplsoudp_encap_conf.ipv6_src, 4317 sizeof(mplsoudp_encap_conf.ipv6_src)); 4318 memcpy(&ipv6.hdr.dst_addr, 4319 &mplsoudp_encap_conf.ipv6_dst, 4320 sizeof(mplsoudp_encap_conf.ipv6_dst)); 4321 memcpy(header, &ipv6, sizeof(ipv6)); 4322 header += sizeof(ipv6); 4323 } 4324 memcpy(header, &udp, sizeof(udp)); 4325 header += sizeof(udp); 4326 memcpy(mpls.label_tc_s, mplsoudp_encap_conf.label, 4327 RTE_DIM(mplsoudp_encap_conf.label)); 4328 mpls.label_tc_s[2] |= 0x1; 4329 memcpy(header, &mpls, sizeof(mpls)); 4330 header += sizeof(mpls); 4331 action_encap_data->conf.size = header - 4332 action_encap_data->data; 4333 action->conf = &action_encap_data->conf; 4334 return ret; 4335 } 4336 4337 /** Parse MPLSOUDP decap action. */ 4338 static int 4339 parse_vc_action_mplsoudp_decap(struct context *ctx, const struct token *token, 4340 const char *str, unsigned int len, 4341 void *buf, unsigned int size) 4342 { 4343 struct buffer *out = buf; 4344 struct rte_flow_action *action; 4345 struct action_raw_decap_data *action_decap_data; 4346 struct rte_flow_item_eth eth = { .type = 0, }; 4347 struct rte_flow_item_vlan vlan = {.tci = 0}; 4348 struct rte_flow_item_ipv4 ipv4 = { 4349 .hdr = { 4350 .next_proto_id = IPPROTO_UDP, 4351 }, 4352 }; 4353 struct rte_flow_item_ipv6 ipv6 = { 4354 .hdr = { 4355 .proto = IPPROTO_UDP, 4356 }, 4357 }; 4358 struct rte_flow_item_udp udp = { 4359 .hdr = { 4360 .dst_port = rte_cpu_to_be_16(6635), 4361 }, 4362 }; 4363 struct rte_flow_item_mpls mpls; 4364 uint8_t *header; 4365 int ret; 4366 4367 ret = parse_vc(ctx, token, str, len, buf, size); 4368 if (ret < 0) 4369 return ret; 4370 /* Nothing else to do if there is no buffer. */ 4371 if (!out) 4372 return ret; 4373 if (!out->args.vc.actions_n) 4374 return -1; 4375 action = &out->args.vc.actions[out->args.vc.actions_n - 1]; 4376 /* Point to selected object. */ 4377 ctx->object = out->args.vc.data; 4378 ctx->objmask = NULL; 4379 /* Copy the headers to the buffer. */ 4380 action_decap_data = ctx->object; 4381 *action_decap_data = (struct action_raw_decap_data) { 4382 .conf = (struct rte_flow_action_raw_decap){ 4383 .data = action_decap_data->data, 4384 }, 4385 .data = {}, 4386 }; 4387 header = action_decap_data->data; 4388 if (mplsoudp_decap_conf.select_vlan) 4389 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN); 4390 else if (mplsoudp_encap_conf.select_ipv4) 4391 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4); 4392 else 4393 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6); 4394 memcpy(eth.dst.addr_bytes, 4395 mplsoudp_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN); 4396 memcpy(eth.src.addr_bytes, 4397 mplsoudp_encap_conf.eth_src, RTE_ETHER_ADDR_LEN); 4398 memcpy(header, ð, sizeof(eth)); 4399 header += sizeof(eth); 4400 if (mplsoudp_encap_conf.select_vlan) { 4401 if (mplsoudp_encap_conf.select_ipv4) 4402 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4); 4403 else 4404 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6); 4405 memcpy(header, &vlan, sizeof(vlan)); 4406 header += sizeof(vlan); 4407 } 4408 if (mplsoudp_encap_conf.select_ipv4) { 4409 memcpy(header, &ipv4, sizeof(ipv4)); 4410 header += sizeof(ipv4); 4411 } else { 4412 memcpy(header, &ipv6, sizeof(ipv6)); 4413 header += sizeof(ipv6); 4414 } 4415 memcpy(header, &udp, sizeof(udp)); 4416 header += sizeof(udp); 4417 memset(&mpls, 0, sizeof(mpls)); 4418 memcpy(header, &mpls, sizeof(mpls)); 4419 header += sizeof(mpls); 4420 action_decap_data->conf.size = header - 4421 action_decap_data->data; 4422 action->conf = &action_decap_data->conf; 4423 return ret; 4424 } 4425 4426 static int 4427 parse_vc_action_raw_encap(struct context *ctx, const struct token *token, 4428 const char *str, unsigned int len, void *buf, 4429 unsigned int size) 4430 { 4431 struct buffer *out = buf; 4432 struct rte_flow_action *action; 4433 struct rte_flow_action_raw_encap *action_raw_encap_conf = NULL; 4434 uint8_t *data = NULL; 4435 int ret; 4436 4437 ret = parse_vc(ctx, token, str, len, buf, size); 4438 if (ret < 0) 4439 return ret; 4440 /* Nothing else to do if there is no buffer. */ 4441 if (!out) 4442 return ret; 4443 if (!out->args.vc.actions_n) 4444 return -1; 4445 action = &out->args.vc.actions[out->args.vc.actions_n - 1]; 4446 /* Point to selected object. */ 4447 ctx->object = out->args.vc.data; 4448 ctx->objmask = NULL; 4449 /* Copy the headers to the buffer. */ 4450 action_raw_encap_conf = ctx->object; 4451 /* data stored from tail of data buffer */ 4452 data = (uint8_t *)&(raw_encap_conf.data) + 4453 ACTION_RAW_ENCAP_MAX_DATA - raw_encap_conf.size; 4454 action_raw_encap_conf->data = data; 4455 action_raw_encap_conf->preserve = NULL; 4456 action_raw_encap_conf->size = raw_encap_conf.size; 4457 action->conf = action_raw_encap_conf; 4458 return ret; 4459 } 4460 4461 static int 4462 parse_vc_action_raw_decap(struct context *ctx, const struct token *token, 4463 const char *str, unsigned int len, void *buf, 4464 unsigned int size) 4465 { 4466 struct buffer *out = buf; 4467 struct rte_flow_action *action; 4468 struct rte_flow_action_raw_decap *action_raw_decap_conf = NULL; 4469 uint8_t *data = NULL; 4470 int ret; 4471 4472 ret = parse_vc(ctx, token, str, len, buf, size); 4473 if (ret < 0) 4474 return ret; 4475 /* Nothing else to do if there is no buffer. */ 4476 if (!out) 4477 return ret; 4478 if (!out->args.vc.actions_n) 4479 return -1; 4480 action = &out->args.vc.actions[out->args.vc.actions_n - 1]; 4481 /* Point to selected object. */ 4482 ctx->object = out->args.vc.data; 4483 ctx->objmask = NULL; 4484 /* Copy the headers to the buffer. */ 4485 action_raw_decap_conf = ctx->object; 4486 /* data stored from tail of data buffer */ 4487 data = (uint8_t *)&(raw_decap_conf.data) + 4488 ACTION_RAW_ENCAP_MAX_DATA - raw_decap_conf.size; 4489 action_raw_decap_conf->data = data; 4490 action_raw_decap_conf->size = raw_decap_conf.size; 4491 action->conf = action_raw_decap_conf; 4492 return ret; 4493 } 4494 4495 /** Parse tokens for destroy command. */ 4496 static int 4497 parse_destroy(struct context *ctx, const struct token *token, 4498 const char *str, unsigned int len, 4499 void *buf, unsigned int size) 4500 { 4501 struct buffer *out = buf; 4502 4503 /* Token name must match. */ 4504 if (parse_default(ctx, token, str, len, NULL, 0) < 0) 4505 return -1; 4506 /* Nothing else to do if there is no buffer. */ 4507 if (!out) 4508 return len; 4509 if (!out->command) { 4510 if (ctx->curr != DESTROY) 4511 return -1; 4512 if (sizeof(*out) > size) 4513 return -1; 4514 out->command = ctx->curr; 4515 ctx->objdata = 0; 4516 ctx->object = out; 4517 ctx->objmask = NULL; 4518 out->args.destroy.rule = 4519 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1), 4520 sizeof(double)); 4521 return len; 4522 } 4523 if (((uint8_t *)(out->args.destroy.rule + out->args.destroy.rule_n) + 4524 sizeof(*out->args.destroy.rule)) > (uint8_t *)out + size) 4525 return -1; 4526 ctx->objdata = 0; 4527 ctx->object = out->args.destroy.rule + out->args.destroy.rule_n++; 4528 ctx->objmask = NULL; 4529 return len; 4530 } 4531 4532 /** Parse tokens for flush command. */ 4533 static int 4534 parse_flush(struct context *ctx, const struct token *token, 4535 const char *str, unsigned int len, 4536 void *buf, unsigned int size) 4537 { 4538 struct buffer *out = buf; 4539 4540 /* Token name must match. */ 4541 if (parse_default(ctx, token, str, len, NULL, 0) < 0) 4542 return -1; 4543 /* Nothing else to do if there is no buffer. */ 4544 if (!out) 4545 return len; 4546 if (!out->command) { 4547 if (ctx->curr != FLUSH) 4548 return -1; 4549 if (sizeof(*out) > size) 4550 return -1; 4551 out->command = ctx->curr; 4552 ctx->objdata = 0; 4553 ctx->object = out; 4554 ctx->objmask = NULL; 4555 } 4556 return len; 4557 } 4558 4559 /** Parse tokens for query command. */ 4560 static int 4561 parse_query(struct context *ctx, const struct token *token, 4562 const char *str, unsigned int len, 4563 void *buf, unsigned int size) 4564 { 4565 struct buffer *out = buf; 4566 4567 /* Token name must match. */ 4568 if (parse_default(ctx, token, str, len, NULL, 0) < 0) 4569 return -1; 4570 /* Nothing else to do if there is no buffer. */ 4571 if (!out) 4572 return len; 4573 if (!out->command) { 4574 if (ctx->curr != QUERY) 4575 return -1; 4576 if (sizeof(*out) > size) 4577 return -1; 4578 out->command = ctx->curr; 4579 ctx->objdata = 0; 4580 ctx->object = out; 4581 ctx->objmask = NULL; 4582 } 4583 return len; 4584 } 4585 4586 /** Parse action names. */ 4587 static int 4588 parse_action(struct context *ctx, const struct token *token, 4589 const char *str, unsigned int len, 4590 void *buf, unsigned int size) 4591 { 4592 struct buffer *out = buf; 4593 const struct arg *arg = pop_args(ctx); 4594 unsigned int i; 4595 4596 (void)size; 4597 /* Argument is expected. */ 4598 if (!arg) 4599 return -1; 4600 /* Parse action name. */ 4601 for (i = 0; next_action[i]; ++i) { 4602 const struct parse_action_priv *priv; 4603 4604 token = &token_list[next_action[i]]; 4605 if (strcmp_partial(token->name, str, len)) 4606 continue; 4607 priv = token->priv; 4608 if (!priv) 4609 goto error; 4610 if (out) 4611 memcpy((uint8_t *)ctx->object + arg->offset, 4612 &priv->type, 4613 arg->size); 4614 return len; 4615 } 4616 error: 4617 push_args(ctx, arg); 4618 return -1; 4619 } 4620 4621 /** Parse tokens for list command. */ 4622 static int 4623 parse_list(struct context *ctx, const struct token *token, 4624 const char *str, unsigned int len, 4625 void *buf, unsigned int size) 4626 { 4627 struct buffer *out = buf; 4628 4629 /* Token name must match. */ 4630 if (parse_default(ctx, token, str, len, NULL, 0) < 0) 4631 return -1; 4632 /* Nothing else to do if there is no buffer. */ 4633 if (!out) 4634 return len; 4635 if (!out->command) { 4636 if (ctx->curr != LIST) 4637 return -1; 4638 if (sizeof(*out) > size) 4639 return -1; 4640 out->command = ctx->curr; 4641 ctx->objdata = 0; 4642 ctx->object = out; 4643 ctx->objmask = NULL; 4644 out->args.list.group = 4645 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1), 4646 sizeof(double)); 4647 return len; 4648 } 4649 if (((uint8_t *)(out->args.list.group + out->args.list.group_n) + 4650 sizeof(*out->args.list.group)) > (uint8_t *)out + size) 4651 return -1; 4652 ctx->objdata = 0; 4653 ctx->object = out->args.list.group + out->args.list.group_n++; 4654 ctx->objmask = NULL; 4655 return len; 4656 } 4657 4658 /** Parse tokens for isolate command. */ 4659 static int 4660 parse_isolate(struct context *ctx, const struct token *token, 4661 const char *str, unsigned int len, 4662 void *buf, unsigned int size) 4663 { 4664 struct buffer *out = buf; 4665 4666 /* Token name must match. */ 4667 if (parse_default(ctx, token, str, len, NULL, 0) < 0) 4668 return -1; 4669 /* Nothing else to do if there is no buffer. */ 4670 if (!out) 4671 return len; 4672 if (!out->command) { 4673 if (ctx->curr != ISOLATE) 4674 return -1; 4675 if (sizeof(*out) > size) 4676 return -1; 4677 out->command = ctx->curr; 4678 ctx->objdata = 0; 4679 ctx->object = out; 4680 ctx->objmask = NULL; 4681 } 4682 return len; 4683 } 4684 4685 /** 4686 * Parse signed/unsigned integers 8 to 64-bit long. 4687 * 4688 * Last argument (ctx->args) is retrieved to determine integer type and 4689 * storage location. 4690 */ 4691 static int 4692 parse_int(struct context *ctx, const struct token *token, 4693 const char *str, unsigned int len, 4694 void *buf, unsigned int size) 4695 { 4696 const struct arg *arg = pop_args(ctx); 4697 uintmax_t u; 4698 char *end; 4699 4700 (void)token; 4701 /* Argument is expected. */ 4702 if (!arg) 4703 return -1; 4704 errno = 0; 4705 u = arg->sign ? 4706 (uintmax_t)strtoimax(str, &end, 0) : 4707 strtoumax(str, &end, 0); 4708 if (errno || (size_t)(end - str) != len) 4709 goto error; 4710 if (arg->bounded && 4711 ((arg->sign && ((intmax_t)u < (intmax_t)arg->min || 4712 (intmax_t)u > (intmax_t)arg->max)) || 4713 (!arg->sign && (u < arg->min || u > arg->max)))) 4714 goto error; 4715 if (!ctx->object) 4716 return len; 4717 if (arg->mask) { 4718 if (!arg_entry_bf_fill(ctx->object, u, arg) || 4719 !arg_entry_bf_fill(ctx->objmask, -1, arg)) 4720 goto error; 4721 return len; 4722 } 4723 buf = (uint8_t *)ctx->object + arg->offset; 4724 size = arg->size; 4725 if (u > RTE_LEN2MASK(size * CHAR_BIT, uint64_t)) 4726 return -1; 4727 objmask: 4728 switch (size) { 4729 case sizeof(uint8_t): 4730 *(uint8_t *)buf = u; 4731 break; 4732 case sizeof(uint16_t): 4733 *(uint16_t *)buf = arg->hton ? rte_cpu_to_be_16(u) : u; 4734 break; 4735 case sizeof(uint8_t [3]): 4736 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN 4737 if (!arg->hton) { 4738 ((uint8_t *)buf)[0] = u; 4739 ((uint8_t *)buf)[1] = u >> 8; 4740 ((uint8_t *)buf)[2] = u >> 16; 4741 break; 4742 } 4743 #endif 4744 ((uint8_t *)buf)[0] = u >> 16; 4745 ((uint8_t *)buf)[1] = u >> 8; 4746 ((uint8_t *)buf)[2] = u; 4747 break; 4748 case sizeof(uint32_t): 4749 *(uint32_t *)buf = arg->hton ? rte_cpu_to_be_32(u) : u; 4750 break; 4751 case sizeof(uint64_t): 4752 *(uint64_t *)buf = arg->hton ? rte_cpu_to_be_64(u) : u; 4753 break; 4754 default: 4755 goto error; 4756 } 4757 if (ctx->objmask && buf != (uint8_t *)ctx->objmask + arg->offset) { 4758 u = -1; 4759 buf = (uint8_t *)ctx->objmask + arg->offset; 4760 goto objmask; 4761 } 4762 return len; 4763 error: 4764 push_args(ctx, arg); 4765 return -1; 4766 } 4767 4768 /** 4769 * Parse a string. 4770 * 4771 * Three arguments (ctx->args) are retrieved from the stack to store data, 4772 * its actual length and address (in that order). 4773 */ 4774 static int 4775 parse_string(struct context *ctx, const struct token *token, 4776 const char *str, unsigned int len, 4777 void *buf, unsigned int size) 4778 { 4779 const struct arg *arg_data = pop_args(ctx); 4780 const struct arg *arg_len = pop_args(ctx); 4781 const struct arg *arg_addr = pop_args(ctx); 4782 char tmp[16]; /* Ought to be enough. */ 4783 int ret; 4784 4785 /* Arguments are expected. */ 4786 if (!arg_data) 4787 return -1; 4788 if (!arg_len) { 4789 push_args(ctx, arg_data); 4790 return -1; 4791 } 4792 if (!arg_addr) { 4793 push_args(ctx, arg_len); 4794 push_args(ctx, arg_data); 4795 return -1; 4796 } 4797 size = arg_data->size; 4798 /* Bit-mask fill is not supported. */ 4799 if (arg_data->mask || size < len) 4800 goto error; 4801 if (!ctx->object) 4802 return len; 4803 /* Let parse_int() fill length information first. */ 4804 ret = snprintf(tmp, sizeof(tmp), "%u", len); 4805 if (ret < 0) 4806 goto error; 4807 push_args(ctx, arg_len); 4808 ret = parse_int(ctx, token, tmp, ret, NULL, 0); 4809 if (ret < 0) { 4810 pop_args(ctx); 4811 goto error; 4812 } 4813 buf = (uint8_t *)ctx->object + arg_data->offset; 4814 /* Output buffer is not necessarily NUL-terminated. */ 4815 memcpy(buf, str, len); 4816 memset((uint8_t *)buf + len, 0x00, size - len); 4817 if (ctx->objmask) 4818 memset((uint8_t *)ctx->objmask + arg_data->offset, 0xff, len); 4819 /* Save address if requested. */ 4820 if (arg_addr->size) { 4821 memcpy((uint8_t *)ctx->object + arg_addr->offset, 4822 (void *[]){ 4823 (uint8_t *)ctx->object + arg_data->offset 4824 }, 4825 arg_addr->size); 4826 if (ctx->objmask) 4827 memcpy((uint8_t *)ctx->objmask + arg_addr->offset, 4828 (void *[]){ 4829 (uint8_t *)ctx->objmask + arg_data->offset 4830 }, 4831 arg_addr->size); 4832 } 4833 return len; 4834 error: 4835 push_args(ctx, arg_addr); 4836 push_args(ctx, arg_len); 4837 push_args(ctx, arg_data); 4838 return -1; 4839 } 4840 4841 static int 4842 parse_hex_string(const char *src, uint8_t *dst, uint32_t *size) 4843 { 4844 char *c = NULL; 4845 uint32_t i, len; 4846 char tmp[3]; 4847 4848 /* Check input parameters */ 4849 if ((src == NULL) || 4850 (dst == NULL) || 4851 (size == NULL) || 4852 (*size == 0)) 4853 return -1; 4854 4855 /* Convert chars to bytes */ 4856 for (i = 0, len = 0; i < *size; i += 2) { 4857 snprintf(tmp, 3, "%s", src + i); 4858 dst[len++] = strtoul(tmp, &c, 16); 4859 if (*c != 0) { 4860 len--; 4861 dst[len] = 0; 4862 *size = len; 4863 return -1; 4864 } 4865 } 4866 dst[len] = 0; 4867 *size = len; 4868 4869 return 0; 4870 } 4871 4872 static int 4873 parse_hex(struct context *ctx, const struct token *token, 4874 const char *str, unsigned int len, 4875 void *buf, unsigned int size) 4876 { 4877 const struct arg *arg_data = pop_args(ctx); 4878 const struct arg *arg_len = pop_args(ctx); 4879 const struct arg *arg_addr = pop_args(ctx); 4880 char tmp[16]; /* Ought to be enough. */ 4881 int ret; 4882 unsigned int hexlen = len; 4883 unsigned int length = 256; 4884 uint8_t hex_tmp[length]; 4885 4886 /* Arguments are expected. */ 4887 if (!arg_data) 4888 return -1; 4889 if (!arg_len) { 4890 push_args(ctx, arg_data); 4891 return -1; 4892 } 4893 if (!arg_addr) { 4894 push_args(ctx, arg_len); 4895 push_args(ctx, arg_data); 4896 return -1; 4897 } 4898 size = arg_data->size; 4899 /* Bit-mask fill is not supported. */ 4900 if (arg_data->mask) 4901 goto error; 4902 if (!ctx->object) 4903 return len; 4904 4905 /* translate bytes string to array. */ 4906 if (str[0] == '0' && ((str[1] == 'x') || 4907 (str[1] == 'X'))) { 4908 str += 2; 4909 hexlen -= 2; 4910 } 4911 if (hexlen > length) 4912 return -1; 4913 ret = parse_hex_string(str, hex_tmp, &hexlen); 4914 if (ret < 0) 4915 goto error; 4916 /* Let parse_int() fill length information first. */ 4917 ret = snprintf(tmp, sizeof(tmp), "%u", hexlen); 4918 if (ret < 0) 4919 goto error; 4920 push_args(ctx, arg_len); 4921 ret = parse_int(ctx, token, tmp, ret, NULL, 0); 4922 if (ret < 0) { 4923 pop_args(ctx); 4924 goto error; 4925 } 4926 buf = (uint8_t *)ctx->object + arg_data->offset; 4927 /* Output buffer is not necessarily NUL-terminated. */ 4928 memcpy(buf, hex_tmp, hexlen); 4929 memset((uint8_t *)buf + hexlen, 0x00, size - hexlen); 4930 if (ctx->objmask) 4931 memset((uint8_t *)ctx->objmask + arg_data->offset, 4932 0xff, hexlen); 4933 /* Save address if requested. */ 4934 if (arg_addr->size) { 4935 memcpy((uint8_t *)ctx->object + arg_addr->offset, 4936 (void *[]){ 4937 (uint8_t *)ctx->object + arg_data->offset 4938 }, 4939 arg_addr->size); 4940 if (ctx->objmask) 4941 memcpy((uint8_t *)ctx->objmask + arg_addr->offset, 4942 (void *[]){ 4943 (uint8_t *)ctx->objmask + arg_data->offset 4944 }, 4945 arg_addr->size); 4946 } 4947 return len; 4948 error: 4949 push_args(ctx, arg_addr); 4950 push_args(ctx, arg_len); 4951 push_args(ctx, arg_data); 4952 return -1; 4953 4954 } 4955 4956 /** 4957 * Parse a MAC address. 4958 * 4959 * Last argument (ctx->args) is retrieved to determine storage size and 4960 * location. 4961 */ 4962 static int 4963 parse_mac_addr(struct context *ctx, const struct token *token, 4964 const char *str, unsigned int len, 4965 void *buf, unsigned int size) 4966 { 4967 const struct arg *arg = pop_args(ctx); 4968 struct rte_ether_addr tmp; 4969 int ret; 4970 4971 (void)token; 4972 /* Argument is expected. */ 4973 if (!arg) 4974 return -1; 4975 size = arg->size; 4976 /* Bit-mask fill is not supported. */ 4977 if (arg->mask || size != sizeof(tmp)) 4978 goto error; 4979 /* Only network endian is supported. */ 4980 if (!arg->hton) 4981 goto error; 4982 ret = cmdline_parse_etheraddr(NULL, str, &tmp, size); 4983 if (ret < 0 || (unsigned int)ret != len) 4984 goto error; 4985 if (!ctx->object) 4986 return len; 4987 buf = (uint8_t *)ctx->object + arg->offset; 4988 memcpy(buf, &tmp, size); 4989 if (ctx->objmask) 4990 memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size); 4991 return len; 4992 error: 4993 push_args(ctx, arg); 4994 return -1; 4995 } 4996 4997 /** 4998 * Parse an IPv4 address. 4999 * 5000 * Last argument (ctx->args) is retrieved to determine storage size and 5001 * location. 5002 */ 5003 static int 5004 parse_ipv4_addr(struct context *ctx, const struct token *token, 5005 const char *str, unsigned int len, 5006 void *buf, unsigned int size) 5007 { 5008 const struct arg *arg = pop_args(ctx); 5009 char str2[len + 1]; 5010 struct in_addr tmp; 5011 int ret; 5012 5013 /* Argument is expected. */ 5014 if (!arg) 5015 return -1; 5016 size = arg->size; 5017 /* Bit-mask fill is not supported. */ 5018 if (arg->mask || size != sizeof(tmp)) 5019 goto error; 5020 /* Only network endian is supported. */ 5021 if (!arg->hton) 5022 goto error; 5023 memcpy(str2, str, len); 5024 str2[len] = '\0'; 5025 ret = inet_pton(AF_INET, str2, &tmp); 5026 if (ret != 1) { 5027 /* Attempt integer parsing. */ 5028 push_args(ctx, arg); 5029 return parse_int(ctx, token, str, len, buf, size); 5030 } 5031 if (!ctx->object) 5032 return len; 5033 buf = (uint8_t *)ctx->object + arg->offset; 5034 memcpy(buf, &tmp, size); 5035 if (ctx->objmask) 5036 memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size); 5037 return len; 5038 error: 5039 push_args(ctx, arg); 5040 return -1; 5041 } 5042 5043 /** 5044 * Parse an IPv6 address. 5045 * 5046 * Last argument (ctx->args) is retrieved to determine storage size and 5047 * location. 5048 */ 5049 static int 5050 parse_ipv6_addr(struct context *ctx, const struct token *token, 5051 const char *str, unsigned int len, 5052 void *buf, unsigned int size) 5053 { 5054 const struct arg *arg = pop_args(ctx); 5055 char str2[len + 1]; 5056 struct in6_addr tmp; 5057 int ret; 5058 5059 (void)token; 5060 /* Argument is expected. */ 5061 if (!arg) 5062 return -1; 5063 size = arg->size; 5064 /* Bit-mask fill is not supported. */ 5065 if (arg->mask || size != sizeof(tmp)) 5066 goto error; 5067 /* Only network endian is supported. */ 5068 if (!arg->hton) 5069 goto error; 5070 memcpy(str2, str, len); 5071 str2[len] = '\0'; 5072 ret = inet_pton(AF_INET6, str2, &tmp); 5073 if (ret != 1) 5074 goto error; 5075 if (!ctx->object) 5076 return len; 5077 buf = (uint8_t *)ctx->object + arg->offset; 5078 memcpy(buf, &tmp, size); 5079 if (ctx->objmask) 5080 memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size); 5081 return len; 5082 error: 5083 push_args(ctx, arg); 5084 return -1; 5085 } 5086 5087 /** Boolean values (even indices stand for false). */ 5088 static const char *const boolean_name[] = { 5089 "0", "1", 5090 "false", "true", 5091 "no", "yes", 5092 "N", "Y", 5093 "off", "on", 5094 NULL, 5095 }; 5096 5097 /** 5098 * Parse a boolean value. 5099 * 5100 * Last argument (ctx->args) is retrieved to determine storage size and 5101 * location. 5102 */ 5103 static int 5104 parse_boolean(struct context *ctx, const struct token *token, 5105 const char *str, unsigned int len, 5106 void *buf, unsigned int size) 5107 { 5108 const struct arg *arg = pop_args(ctx); 5109 unsigned int i; 5110 int ret; 5111 5112 /* Argument is expected. */ 5113 if (!arg) 5114 return -1; 5115 for (i = 0; boolean_name[i]; ++i) 5116 if (!strcmp_partial(boolean_name[i], str, len)) 5117 break; 5118 /* Process token as integer. */ 5119 if (boolean_name[i]) 5120 str = i & 1 ? "1" : "0"; 5121 push_args(ctx, arg); 5122 ret = parse_int(ctx, token, str, strlen(str), buf, size); 5123 return ret > 0 ? (int)len : ret; 5124 } 5125 5126 /** Parse port and update context. */ 5127 static int 5128 parse_port(struct context *ctx, const struct token *token, 5129 const char *str, unsigned int len, 5130 void *buf, unsigned int size) 5131 { 5132 struct buffer *out = &(struct buffer){ .port = 0 }; 5133 int ret; 5134 5135 if (buf) 5136 out = buf; 5137 else { 5138 ctx->objdata = 0; 5139 ctx->object = out; 5140 ctx->objmask = NULL; 5141 size = sizeof(*out); 5142 } 5143 ret = parse_int(ctx, token, str, len, out, size); 5144 if (ret >= 0) 5145 ctx->port = out->port; 5146 if (!buf) 5147 ctx->object = NULL; 5148 return ret; 5149 } 5150 5151 /** Parse set command, initialize output buffer for subsequent tokens. */ 5152 static int 5153 parse_set_raw_encap_decap(struct context *ctx, const struct token *token, 5154 const char *str, unsigned int len, 5155 void *buf, unsigned int size) 5156 { 5157 struct buffer *out = buf; 5158 5159 /* Token name must match. */ 5160 if (parse_default(ctx, token, str, len, NULL, 0) < 0) 5161 return -1; 5162 /* Nothing else to do if there is no buffer. */ 5163 if (!out) 5164 return len; 5165 /* Make sure buffer is large enough. */ 5166 if (size < sizeof(*out)) 5167 return -1; 5168 ctx->objdata = 0; 5169 ctx->objmask = NULL; 5170 if (!out->command) 5171 return -1; 5172 out->command = ctx->curr; 5173 return len; 5174 } 5175 5176 /** 5177 * Parse set raw_encap/raw_decap command, 5178 * initialize output buffer for subsequent tokens. 5179 */ 5180 static int 5181 parse_set_init(struct context *ctx, const struct token *token, 5182 const char *str, unsigned int len, 5183 void *buf, unsigned int size) 5184 { 5185 struct buffer *out = buf; 5186 5187 /* Token name must match. */ 5188 if (parse_default(ctx, token, str, len, NULL, 0) < 0) 5189 return -1; 5190 /* Nothing else to do if there is no buffer. */ 5191 if (!out) 5192 return len; 5193 /* Make sure buffer is large enough. */ 5194 if (size < sizeof(*out)) 5195 return -1; 5196 /* Initialize buffer. */ 5197 memset(out, 0x00, sizeof(*out)); 5198 memset((uint8_t *)out + sizeof(*out), 0x22, size - sizeof(*out)); 5199 ctx->objdata = 0; 5200 ctx->object = out; 5201 ctx->objmask = NULL; 5202 if (!out->command) { 5203 if (ctx->curr != SET) 5204 return -1; 5205 if (sizeof(*out) > size) 5206 return -1; 5207 out->command = ctx->curr; 5208 out->args.vc.data = (uint8_t *)out + size; 5209 /* All we need is pattern */ 5210 out->args.vc.pattern = 5211 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1), 5212 sizeof(double)); 5213 ctx->object = out->args.vc.pattern; 5214 } 5215 return len; 5216 } 5217 5218 /** No completion. */ 5219 static int 5220 comp_none(struct context *ctx, const struct token *token, 5221 unsigned int ent, char *buf, unsigned int size) 5222 { 5223 (void)ctx; 5224 (void)token; 5225 (void)ent; 5226 (void)buf; 5227 (void)size; 5228 return 0; 5229 } 5230 5231 /** Complete boolean values. */ 5232 static int 5233 comp_boolean(struct context *ctx, const struct token *token, 5234 unsigned int ent, char *buf, unsigned int size) 5235 { 5236 unsigned int i; 5237 5238 (void)ctx; 5239 (void)token; 5240 for (i = 0; boolean_name[i]; ++i) 5241 if (buf && i == ent) 5242 return strlcpy(buf, boolean_name[i], size); 5243 if (buf) 5244 return -1; 5245 return i; 5246 } 5247 5248 /** Complete action names. */ 5249 static int 5250 comp_action(struct context *ctx, const struct token *token, 5251 unsigned int ent, char *buf, unsigned int size) 5252 { 5253 unsigned int i; 5254 5255 (void)ctx; 5256 (void)token; 5257 for (i = 0; next_action[i]; ++i) 5258 if (buf && i == ent) 5259 return strlcpy(buf, token_list[next_action[i]].name, 5260 size); 5261 if (buf) 5262 return -1; 5263 return i; 5264 } 5265 5266 /** Complete available ports. */ 5267 static int 5268 comp_port(struct context *ctx, const struct token *token, 5269 unsigned int ent, char *buf, unsigned int size) 5270 { 5271 unsigned int i = 0; 5272 portid_t p; 5273 5274 (void)ctx; 5275 (void)token; 5276 RTE_ETH_FOREACH_DEV(p) { 5277 if (buf && i == ent) 5278 return snprintf(buf, size, "%u", p); 5279 ++i; 5280 } 5281 if (buf) 5282 return -1; 5283 return i; 5284 } 5285 5286 /** Complete available rule IDs. */ 5287 static int 5288 comp_rule_id(struct context *ctx, const struct token *token, 5289 unsigned int ent, char *buf, unsigned int size) 5290 { 5291 unsigned int i = 0; 5292 struct rte_port *port; 5293 struct port_flow *pf; 5294 5295 (void)token; 5296 if (port_id_is_invalid(ctx->port, DISABLED_WARN) || 5297 ctx->port == (portid_t)RTE_PORT_ALL) 5298 return -1; 5299 port = &ports[ctx->port]; 5300 for (pf = port->flow_list; pf != NULL; pf = pf->next) { 5301 if (buf && i == ent) 5302 return snprintf(buf, size, "%u", pf->id); 5303 ++i; 5304 } 5305 if (buf) 5306 return -1; 5307 return i; 5308 } 5309 5310 /** Complete type field for RSS action. */ 5311 static int 5312 comp_vc_action_rss_type(struct context *ctx, const struct token *token, 5313 unsigned int ent, char *buf, unsigned int size) 5314 { 5315 unsigned int i; 5316 5317 (void)ctx; 5318 (void)token; 5319 for (i = 0; rss_type_table[i].str; ++i) 5320 ; 5321 if (!buf) 5322 return i + 1; 5323 if (ent < i) 5324 return strlcpy(buf, rss_type_table[ent].str, size); 5325 if (ent == i) 5326 return snprintf(buf, size, "end"); 5327 return -1; 5328 } 5329 5330 /** Complete queue field for RSS action. */ 5331 static int 5332 comp_vc_action_rss_queue(struct context *ctx, const struct token *token, 5333 unsigned int ent, char *buf, unsigned int size) 5334 { 5335 (void)ctx; 5336 (void)token; 5337 if (!buf) 5338 return nb_rxq + 1; 5339 if (ent < nb_rxq) 5340 return snprintf(buf, size, "%u", ent); 5341 if (ent == nb_rxq) 5342 return snprintf(buf, size, "end"); 5343 return -1; 5344 } 5345 5346 /** Internal context. */ 5347 static struct context cmd_flow_context; 5348 5349 /** Global parser instance (cmdline API). */ 5350 cmdline_parse_inst_t cmd_flow; 5351 cmdline_parse_inst_t cmd_set_raw; 5352 5353 /** Initialize context. */ 5354 static void 5355 cmd_flow_context_init(struct context *ctx) 5356 { 5357 /* A full memset() is not necessary. */ 5358 ctx->curr = ZERO; 5359 ctx->prev = ZERO; 5360 ctx->next_num = 0; 5361 ctx->args_num = 0; 5362 ctx->eol = 0; 5363 ctx->last = 0; 5364 ctx->port = 0; 5365 ctx->objdata = 0; 5366 ctx->object = NULL; 5367 ctx->objmask = NULL; 5368 } 5369 5370 /** Parse a token (cmdline API). */ 5371 static int 5372 cmd_flow_parse(cmdline_parse_token_hdr_t *hdr, const char *src, void *result, 5373 unsigned int size) 5374 { 5375 struct context *ctx = &cmd_flow_context; 5376 const struct token *token; 5377 const enum index *list; 5378 int len; 5379 int i; 5380 5381 (void)hdr; 5382 token = &token_list[ctx->curr]; 5383 /* Check argument length. */ 5384 ctx->eol = 0; 5385 ctx->last = 1; 5386 for (len = 0; src[len]; ++len) 5387 if (src[len] == '#' || isspace(src[len])) 5388 break; 5389 if (!len) 5390 return -1; 5391 /* Last argument and EOL detection. */ 5392 for (i = len; src[i]; ++i) 5393 if (src[i] == '#' || src[i] == '\r' || src[i] == '\n') 5394 break; 5395 else if (!isspace(src[i])) { 5396 ctx->last = 0; 5397 break; 5398 } 5399 for (; src[i]; ++i) 5400 if (src[i] == '\r' || src[i] == '\n') { 5401 ctx->eol = 1; 5402 break; 5403 } 5404 /* Initialize context if necessary. */ 5405 if (!ctx->next_num) { 5406 if (!token->next) 5407 return 0; 5408 ctx->next[ctx->next_num++] = token->next[0]; 5409 } 5410 /* Process argument through candidates. */ 5411 ctx->prev = ctx->curr; 5412 list = ctx->next[ctx->next_num - 1]; 5413 for (i = 0; list[i]; ++i) { 5414 const struct token *next = &token_list[list[i]]; 5415 int tmp; 5416 5417 ctx->curr = list[i]; 5418 if (next->call) 5419 tmp = next->call(ctx, next, src, len, result, size); 5420 else 5421 tmp = parse_default(ctx, next, src, len, result, size); 5422 if (tmp == -1 || tmp != len) 5423 continue; 5424 token = next; 5425 break; 5426 } 5427 if (!list[i]) 5428 return -1; 5429 --ctx->next_num; 5430 /* Push subsequent tokens if any. */ 5431 if (token->next) 5432 for (i = 0; token->next[i]; ++i) { 5433 if (ctx->next_num == RTE_DIM(ctx->next)) 5434 return -1; 5435 ctx->next[ctx->next_num++] = token->next[i]; 5436 } 5437 /* Push arguments if any. */ 5438 if (token->args) 5439 for (i = 0; token->args[i]; ++i) { 5440 if (ctx->args_num == RTE_DIM(ctx->args)) 5441 return -1; 5442 ctx->args[ctx->args_num++] = token->args[i]; 5443 } 5444 return len; 5445 } 5446 5447 /** Return number of completion entries (cmdline API). */ 5448 static int 5449 cmd_flow_complete_get_nb(cmdline_parse_token_hdr_t *hdr) 5450 { 5451 struct context *ctx = &cmd_flow_context; 5452 const struct token *token = &token_list[ctx->curr]; 5453 const enum index *list; 5454 int i; 5455 5456 (void)hdr; 5457 /* Count number of tokens in current list. */ 5458 if (ctx->next_num) 5459 list = ctx->next[ctx->next_num - 1]; 5460 else 5461 list = token->next[0]; 5462 for (i = 0; list[i]; ++i) 5463 ; 5464 if (!i) 5465 return 0; 5466 /* 5467 * If there is a single token, use its completion callback, otherwise 5468 * return the number of entries. 5469 */ 5470 token = &token_list[list[0]]; 5471 if (i == 1 && token->comp) { 5472 /* Save index for cmd_flow_get_help(). */ 5473 ctx->prev = list[0]; 5474 return token->comp(ctx, token, 0, NULL, 0); 5475 } 5476 return i; 5477 } 5478 5479 /** Return a completion entry (cmdline API). */ 5480 static int 5481 cmd_flow_complete_get_elt(cmdline_parse_token_hdr_t *hdr, int index, 5482 char *dst, unsigned int size) 5483 { 5484 struct context *ctx = &cmd_flow_context; 5485 const struct token *token = &token_list[ctx->curr]; 5486 const enum index *list; 5487 int i; 5488 5489 (void)hdr; 5490 /* Count number of tokens in current list. */ 5491 if (ctx->next_num) 5492 list = ctx->next[ctx->next_num - 1]; 5493 else 5494 list = token->next[0]; 5495 for (i = 0; list[i]; ++i) 5496 ; 5497 if (!i) 5498 return -1; 5499 /* If there is a single token, use its completion callback. */ 5500 token = &token_list[list[0]]; 5501 if (i == 1 && token->comp) { 5502 /* Save index for cmd_flow_get_help(). */ 5503 ctx->prev = list[0]; 5504 return token->comp(ctx, token, index, dst, size) < 0 ? -1 : 0; 5505 } 5506 /* Otherwise make sure the index is valid and use defaults. */ 5507 if (index >= i) 5508 return -1; 5509 token = &token_list[list[index]]; 5510 strlcpy(dst, token->name, size); 5511 /* Save index for cmd_flow_get_help(). */ 5512 ctx->prev = list[index]; 5513 return 0; 5514 } 5515 5516 /** Populate help strings for current token (cmdline API). */ 5517 static int 5518 cmd_flow_get_help(cmdline_parse_token_hdr_t *hdr, char *dst, unsigned int size) 5519 { 5520 struct context *ctx = &cmd_flow_context; 5521 const struct token *token = &token_list[ctx->prev]; 5522 5523 (void)hdr; 5524 if (!size) 5525 return -1; 5526 /* Set token type and update global help with details. */ 5527 strlcpy(dst, (token->type ? token->type : "TOKEN"), size); 5528 if (token->help) 5529 cmd_flow.help_str = token->help; 5530 else 5531 cmd_flow.help_str = token->name; 5532 return 0; 5533 } 5534 5535 /** Token definition template (cmdline API). */ 5536 static struct cmdline_token_hdr cmd_flow_token_hdr = { 5537 .ops = &(struct cmdline_token_ops){ 5538 .parse = cmd_flow_parse, 5539 .complete_get_nb = cmd_flow_complete_get_nb, 5540 .complete_get_elt = cmd_flow_complete_get_elt, 5541 .get_help = cmd_flow_get_help, 5542 }, 5543 .offset = 0, 5544 }; 5545 5546 /** Populate the next dynamic token. */ 5547 static void 5548 cmd_flow_tok(cmdline_parse_token_hdr_t **hdr, 5549 cmdline_parse_token_hdr_t **hdr_inst) 5550 { 5551 struct context *ctx = &cmd_flow_context; 5552 5553 /* Always reinitialize context before requesting the first token. */ 5554 if (!(hdr_inst - cmd_flow.tokens)) 5555 cmd_flow_context_init(ctx); 5556 /* Return NULL when no more tokens are expected. */ 5557 if (!ctx->next_num && ctx->curr) { 5558 *hdr = NULL; 5559 return; 5560 } 5561 /* Determine if command should end here. */ 5562 if (ctx->eol && ctx->last && ctx->next_num) { 5563 const enum index *list = ctx->next[ctx->next_num - 1]; 5564 int i; 5565 5566 for (i = 0; list[i]; ++i) { 5567 if (list[i] != END) 5568 continue; 5569 *hdr = NULL; 5570 return; 5571 } 5572 } 5573 *hdr = &cmd_flow_token_hdr; 5574 } 5575 5576 /** Dispatch parsed buffer to function calls. */ 5577 static void 5578 cmd_flow_parsed(const struct buffer *in) 5579 { 5580 switch (in->command) { 5581 case VALIDATE: 5582 port_flow_validate(in->port, &in->args.vc.attr, 5583 in->args.vc.pattern, in->args.vc.actions); 5584 break; 5585 case CREATE: 5586 port_flow_create(in->port, &in->args.vc.attr, 5587 in->args.vc.pattern, in->args.vc.actions); 5588 break; 5589 case DESTROY: 5590 port_flow_destroy(in->port, in->args.destroy.rule_n, 5591 in->args.destroy.rule); 5592 break; 5593 case FLUSH: 5594 port_flow_flush(in->port); 5595 break; 5596 case QUERY: 5597 port_flow_query(in->port, in->args.query.rule, 5598 &in->args.query.action); 5599 break; 5600 case LIST: 5601 port_flow_list(in->port, in->args.list.group_n, 5602 in->args.list.group); 5603 break; 5604 case ISOLATE: 5605 port_flow_isolate(in->port, in->args.isolate.set); 5606 break; 5607 default: 5608 break; 5609 } 5610 } 5611 5612 /** Token generator and output processing callback (cmdline API). */ 5613 static void 5614 cmd_flow_cb(void *arg0, struct cmdline *cl, void *arg2) 5615 { 5616 if (cl == NULL) 5617 cmd_flow_tok(arg0, arg2); 5618 else 5619 cmd_flow_parsed(arg0); 5620 } 5621 5622 /** Global parser instance (cmdline API). */ 5623 cmdline_parse_inst_t cmd_flow = { 5624 .f = cmd_flow_cb, 5625 .data = NULL, /**< Unused. */ 5626 .help_str = NULL, /**< Updated by cmd_flow_get_help(). */ 5627 .tokens = { 5628 NULL, 5629 }, /**< Tokens are returned by cmd_flow_tok(). */ 5630 }; 5631 5632 /** set cmd facility. Reuse cmd flow's infrastructure as much as possible. */ 5633 5634 static void 5635 update_fields(uint8_t *buf, struct rte_flow_item *item, uint16_t next_proto) 5636 { 5637 struct rte_flow_item_ipv4 *ipv4; 5638 struct rte_flow_item_eth *eth; 5639 struct rte_flow_item_ipv6 *ipv6; 5640 struct rte_flow_item_vxlan *vxlan; 5641 struct rte_flow_item_vxlan_gpe *gpe; 5642 struct rte_flow_item_nvgre *nvgre; 5643 uint32_t ipv6_vtc_flow; 5644 5645 switch (item->type) { 5646 case RTE_FLOW_ITEM_TYPE_ETH: 5647 eth = (struct rte_flow_item_eth *)buf; 5648 if (next_proto) 5649 eth->type = rte_cpu_to_be_16(next_proto); 5650 break; 5651 case RTE_FLOW_ITEM_TYPE_IPV4: 5652 ipv4 = (struct rte_flow_item_ipv4 *)buf; 5653 ipv4->hdr.version_ihl = 0x45; 5654 ipv4->hdr.next_proto_id = (uint8_t)next_proto; 5655 break; 5656 case RTE_FLOW_ITEM_TYPE_IPV6: 5657 ipv6 = (struct rte_flow_item_ipv6 *)buf; 5658 ipv6->hdr.proto = (uint8_t)next_proto; 5659 ipv6_vtc_flow = rte_be_to_cpu_32(ipv6->hdr.vtc_flow); 5660 ipv6_vtc_flow &= 0x0FFFFFFF; /*< reset version bits. */ 5661 ipv6_vtc_flow |= 0x60000000; /*< set ipv6 version. */ 5662 ipv6->hdr.vtc_flow = rte_cpu_to_be_32(ipv6_vtc_flow); 5663 break; 5664 case RTE_FLOW_ITEM_TYPE_VXLAN: 5665 vxlan = (struct rte_flow_item_vxlan *)buf; 5666 vxlan->flags = 0x08; 5667 break; 5668 case RTE_FLOW_ITEM_TYPE_VXLAN_GPE: 5669 gpe = (struct rte_flow_item_vxlan_gpe *)buf; 5670 gpe->flags = 0x0C; 5671 break; 5672 case RTE_FLOW_ITEM_TYPE_NVGRE: 5673 nvgre = (struct rte_flow_item_nvgre *)buf; 5674 nvgre->protocol = rte_cpu_to_be_16(0x6558); 5675 nvgre->c_k_s_rsvd0_ver = rte_cpu_to_be_16(0x2000); 5676 break; 5677 default: 5678 break; 5679 } 5680 } 5681 5682 /** Helper of get item's default mask. */ 5683 static const void * 5684 flow_item_default_mask(const struct rte_flow_item *item) 5685 { 5686 const void *mask = NULL; 5687 static rte_be32_t gre_key_default_mask = RTE_BE32(UINT32_MAX); 5688 5689 switch (item->type) { 5690 case RTE_FLOW_ITEM_TYPE_ANY: 5691 mask = &rte_flow_item_any_mask; 5692 break; 5693 case RTE_FLOW_ITEM_TYPE_VF: 5694 mask = &rte_flow_item_vf_mask; 5695 break; 5696 case RTE_FLOW_ITEM_TYPE_PORT_ID: 5697 mask = &rte_flow_item_port_id_mask; 5698 break; 5699 case RTE_FLOW_ITEM_TYPE_RAW: 5700 mask = &rte_flow_item_raw_mask; 5701 break; 5702 case RTE_FLOW_ITEM_TYPE_ETH: 5703 mask = &rte_flow_item_eth_mask; 5704 break; 5705 case RTE_FLOW_ITEM_TYPE_VLAN: 5706 mask = &rte_flow_item_vlan_mask; 5707 break; 5708 case RTE_FLOW_ITEM_TYPE_IPV4: 5709 mask = &rte_flow_item_ipv4_mask; 5710 break; 5711 case RTE_FLOW_ITEM_TYPE_IPV6: 5712 mask = &rte_flow_item_ipv6_mask; 5713 break; 5714 case RTE_FLOW_ITEM_TYPE_ICMP: 5715 mask = &rte_flow_item_icmp_mask; 5716 break; 5717 case RTE_FLOW_ITEM_TYPE_UDP: 5718 mask = &rte_flow_item_udp_mask; 5719 break; 5720 case RTE_FLOW_ITEM_TYPE_TCP: 5721 mask = &rte_flow_item_tcp_mask; 5722 break; 5723 case RTE_FLOW_ITEM_TYPE_SCTP: 5724 mask = &rte_flow_item_sctp_mask; 5725 break; 5726 case RTE_FLOW_ITEM_TYPE_VXLAN: 5727 mask = &rte_flow_item_vxlan_mask; 5728 break; 5729 case RTE_FLOW_ITEM_TYPE_VXLAN_GPE: 5730 mask = &rte_flow_item_vxlan_gpe_mask; 5731 break; 5732 case RTE_FLOW_ITEM_TYPE_E_TAG: 5733 mask = &rte_flow_item_e_tag_mask; 5734 break; 5735 case RTE_FLOW_ITEM_TYPE_NVGRE: 5736 mask = &rte_flow_item_nvgre_mask; 5737 break; 5738 case RTE_FLOW_ITEM_TYPE_MPLS: 5739 mask = &rte_flow_item_mpls_mask; 5740 break; 5741 case RTE_FLOW_ITEM_TYPE_GRE: 5742 mask = &rte_flow_item_gre_mask; 5743 break; 5744 case RTE_FLOW_ITEM_TYPE_GRE_KEY: 5745 mask = &gre_key_default_mask; 5746 break; 5747 case RTE_FLOW_ITEM_TYPE_META: 5748 mask = &rte_flow_item_meta_mask; 5749 break; 5750 case RTE_FLOW_ITEM_TYPE_FUZZY: 5751 mask = &rte_flow_item_fuzzy_mask; 5752 break; 5753 case RTE_FLOW_ITEM_TYPE_GTP: 5754 mask = &rte_flow_item_gtp_mask; 5755 break; 5756 case RTE_FLOW_ITEM_TYPE_ESP: 5757 mask = &rte_flow_item_esp_mask; 5758 break; 5759 default: 5760 break; 5761 } 5762 return mask; 5763 } 5764 5765 5766 5767 /** Dispatch parsed buffer to function calls. */ 5768 static void 5769 cmd_set_raw_parsed(const struct buffer *in) 5770 { 5771 uint32_t n = in->args.vc.pattern_n; 5772 int i = 0; 5773 struct rte_flow_item *item = NULL; 5774 size_t size = 0; 5775 uint8_t *data = NULL; 5776 uint8_t *data_tail = NULL; 5777 size_t *total_size = NULL; 5778 uint16_t upper_layer = 0; 5779 uint16_t proto = 0; 5780 5781 RTE_ASSERT(in->command == SET_RAW_ENCAP || 5782 in->command == SET_RAW_DECAP); 5783 if (in->command == SET_RAW_ENCAP) { 5784 total_size = &raw_encap_conf.size; 5785 data = (uint8_t *)&raw_encap_conf.data; 5786 } else { 5787 total_size = &raw_decap_conf.size; 5788 data = (uint8_t *)&raw_decap_conf.data; 5789 } 5790 *total_size = 0; 5791 memset(data, 0x00, ACTION_RAW_ENCAP_MAX_DATA); 5792 /* process hdr from upper layer to low layer (L3/L4 -> L2). */ 5793 data_tail = data + ACTION_RAW_ENCAP_MAX_DATA; 5794 for (i = n - 1 ; i >= 0; --i) { 5795 item = in->args.vc.pattern + i; 5796 if (item->spec == NULL) 5797 item->spec = flow_item_default_mask(item); 5798 switch (item->type) { 5799 case RTE_FLOW_ITEM_TYPE_ETH: 5800 size = sizeof(struct rte_flow_item_eth); 5801 break; 5802 case RTE_FLOW_ITEM_TYPE_VLAN: 5803 size = sizeof(struct rte_flow_item_vlan); 5804 proto = RTE_ETHER_TYPE_VLAN; 5805 break; 5806 case RTE_FLOW_ITEM_TYPE_IPV4: 5807 size = sizeof(struct rte_flow_item_ipv4); 5808 proto = RTE_ETHER_TYPE_IPV4; 5809 break; 5810 case RTE_FLOW_ITEM_TYPE_IPV6: 5811 size = sizeof(struct rte_flow_item_ipv6); 5812 proto = RTE_ETHER_TYPE_IPV6; 5813 break; 5814 case RTE_FLOW_ITEM_TYPE_UDP: 5815 size = sizeof(struct rte_flow_item_udp); 5816 proto = 0x11; 5817 break; 5818 case RTE_FLOW_ITEM_TYPE_TCP: 5819 size = sizeof(struct rte_flow_item_tcp); 5820 proto = 0x06; 5821 break; 5822 case RTE_FLOW_ITEM_TYPE_VXLAN: 5823 size = sizeof(struct rte_flow_item_vxlan); 5824 break; 5825 case RTE_FLOW_ITEM_TYPE_VXLAN_GPE: 5826 size = sizeof(struct rte_flow_item_vxlan_gpe); 5827 break; 5828 case RTE_FLOW_ITEM_TYPE_GRE: 5829 size = sizeof(struct rte_flow_item_gre); 5830 proto = 0x2F; 5831 break; 5832 case RTE_FLOW_ITEM_TYPE_GRE_KEY: 5833 size = sizeof(rte_be32_t); 5834 break; 5835 case RTE_FLOW_ITEM_TYPE_MPLS: 5836 size = sizeof(struct rte_flow_item_mpls); 5837 break; 5838 case RTE_FLOW_ITEM_TYPE_NVGRE: 5839 size = sizeof(struct rte_flow_item_nvgre); 5840 proto = 0x2F; 5841 break; 5842 default: 5843 printf("Error - Not supported item\n"); 5844 *total_size = 0; 5845 memset(data, 0x00, ACTION_RAW_ENCAP_MAX_DATA); 5846 return; 5847 } 5848 *total_size += size; 5849 rte_memcpy(data_tail - (*total_size), item->spec, size); 5850 /* update some fields which cannot be set by cmdline */ 5851 update_fields((data_tail - (*total_size)), item, 5852 upper_layer); 5853 upper_layer = proto; 5854 } 5855 if (verbose_level & 0x1) 5856 printf("total data size is %zu\n", (*total_size)); 5857 RTE_ASSERT((*total_size) <= ACTION_RAW_ENCAP_MAX_DATA); 5858 } 5859 5860 /** Populate help strings for current token (cmdline API). */ 5861 static int 5862 cmd_set_raw_get_help(cmdline_parse_token_hdr_t *hdr, char *dst, 5863 unsigned int size) 5864 { 5865 struct context *ctx = &cmd_flow_context; 5866 const struct token *token = &token_list[ctx->prev]; 5867 5868 (void)hdr; 5869 if (!size) 5870 return -1; 5871 /* Set token type and update global help with details. */ 5872 snprintf(dst, size, "%s", (token->type ? token->type : "TOKEN")); 5873 if (token->help) 5874 cmd_set_raw.help_str = token->help; 5875 else 5876 cmd_set_raw.help_str = token->name; 5877 return 0; 5878 } 5879 5880 /** Token definition template (cmdline API). */ 5881 static struct cmdline_token_hdr cmd_set_raw_token_hdr = { 5882 .ops = &(struct cmdline_token_ops){ 5883 .parse = cmd_flow_parse, 5884 .complete_get_nb = cmd_flow_complete_get_nb, 5885 .complete_get_elt = cmd_flow_complete_get_elt, 5886 .get_help = cmd_set_raw_get_help, 5887 }, 5888 .offset = 0, 5889 }; 5890 5891 /** Populate the next dynamic token. */ 5892 static void 5893 cmd_set_raw_tok(cmdline_parse_token_hdr_t **hdr, 5894 cmdline_parse_token_hdr_t **hdr_inst) 5895 { 5896 struct context *ctx = &cmd_flow_context; 5897 5898 /* Always reinitialize context before requesting the first token. */ 5899 if (!(hdr_inst - cmd_set_raw.tokens)) { 5900 cmd_flow_context_init(ctx); 5901 ctx->curr = START_SET; 5902 } 5903 /* Return NULL when no more tokens are expected. */ 5904 if (!ctx->next_num && (ctx->curr != START_SET)) { 5905 *hdr = NULL; 5906 return; 5907 } 5908 /* Determine if command should end here. */ 5909 if (ctx->eol && ctx->last && ctx->next_num) { 5910 const enum index *list = ctx->next[ctx->next_num - 1]; 5911 int i; 5912 5913 for (i = 0; list[i]; ++i) { 5914 if (list[i] != END) 5915 continue; 5916 *hdr = NULL; 5917 return; 5918 } 5919 } 5920 *hdr = &cmd_set_raw_token_hdr; 5921 } 5922 5923 /** Token generator and output processing callback (cmdline API). */ 5924 static void 5925 cmd_set_raw_cb(void *arg0, struct cmdline *cl, void *arg2) 5926 { 5927 if (cl == NULL) 5928 cmd_set_raw_tok(arg0, arg2); 5929 else 5930 cmd_set_raw_parsed(arg0); 5931 } 5932 5933 /** Global parser instance (cmdline API). */ 5934 cmdline_parse_inst_t cmd_set_raw = { 5935 .f = cmd_set_raw_cb, 5936 .data = NULL, /**< Unused. */ 5937 .help_str = NULL, /**< Updated by cmd_flow_get_help(). */ 5938 .tokens = { 5939 NULL, 5940 }, /**< Tokens are returned by cmd_flow_tok(). */ 5941 }; 5942