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