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