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