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