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