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