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