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