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