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 int ret; 3382 int i; 3383 3384 (void)token; 3385 (void)buf; 3386 (void)size; 3387 if (ctx->curr != ACTION_RSS_QUEUE) 3388 return -1; 3389 i = ctx->objdata >> 16; 3390 if (!strcmp_partial("end", str, len)) { 3391 ctx->objdata &= 0xffff; 3392 goto end; 3393 } 3394 if (i >= ACTION_RSS_QUEUE_NUM) 3395 return -1; 3396 if (push_args(ctx, 3397 ARGS_ENTRY_ARB(offsetof(struct action_rss_data, queue) + 3398 i * sizeof(action_rss_data->queue[i]), 3399 sizeof(action_rss_data->queue[i])))) 3400 return -1; 3401 ret = parse_int(ctx, token, str, len, NULL, 0); 3402 if (ret < 0) { 3403 pop_args(ctx); 3404 return -1; 3405 } 3406 ++i; 3407 ctx->objdata = i << 16 | (ctx->objdata & 0xffff); 3408 /* Repeat token. */ 3409 if (ctx->next_num == RTE_DIM(ctx->next)) 3410 return -1; 3411 ctx->next[ctx->next_num++] = next; 3412 end: 3413 if (!ctx->object) 3414 return len; 3415 action_rss_data = ctx->object; 3416 action_rss_data->conf.queue_num = i; 3417 action_rss_data->conf.queue = i ? action_rss_data->queue : NULL; 3418 return len; 3419 } 3420 3421 /** Parse VXLAN encap action. */ 3422 static int 3423 parse_vc_action_vxlan_encap(struct context *ctx, const struct token *token, 3424 const char *str, unsigned int len, 3425 void *buf, unsigned int size) 3426 { 3427 struct buffer *out = buf; 3428 struct rte_flow_action *action; 3429 struct action_vxlan_encap_data *action_vxlan_encap_data; 3430 int ret; 3431 3432 ret = parse_vc(ctx, token, str, len, buf, size); 3433 if (ret < 0) 3434 return ret; 3435 /* Nothing else to do if there is no buffer. */ 3436 if (!out) 3437 return ret; 3438 if (!out->args.vc.actions_n) 3439 return -1; 3440 action = &out->args.vc.actions[out->args.vc.actions_n - 1]; 3441 /* Point to selected object. */ 3442 ctx->object = out->args.vc.data; 3443 ctx->objmask = NULL; 3444 /* Set up default configuration. */ 3445 action_vxlan_encap_data = ctx->object; 3446 *action_vxlan_encap_data = (struct action_vxlan_encap_data){ 3447 .conf = (struct rte_flow_action_vxlan_encap){ 3448 .definition = action_vxlan_encap_data->items, 3449 }, 3450 .items = { 3451 { 3452 .type = RTE_FLOW_ITEM_TYPE_ETH, 3453 .spec = &action_vxlan_encap_data->item_eth, 3454 .mask = &rte_flow_item_eth_mask, 3455 }, 3456 { 3457 .type = RTE_FLOW_ITEM_TYPE_VLAN, 3458 .spec = &action_vxlan_encap_data->item_vlan, 3459 .mask = &rte_flow_item_vlan_mask, 3460 }, 3461 { 3462 .type = RTE_FLOW_ITEM_TYPE_IPV4, 3463 .spec = &action_vxlan_encap_data->item_ipv4, 3464 .mask = &rte_flow_item_ipv4_mask, 3465 }, 3466 { 3467 .type = RTE_FLOW_ITEM_TYPE_UDP, 3468 .spec = &action_vxlan_encap_data->item_udp, 3469 .mask = &rte_flow_item_udp_mask, 3470 }, 3471 { 3472 .type = RTE_FLOW_ITEM_TYPE_VXLAN, 3473 .spec = &action_vxlan_encap_data->item_vxlan, 3474 .mask = &rte_flow_item_vxlan_mask, 3475 }, 3476 { 3477 .type = RTE_FLOW_ITEM_TYPE_END, 3478 }, 3479 }, 3480 .item_eth.type = 0, 3481 .item_vlan = { 3482 .tci = vxlan_encap_conf.vlan_tci, 3483 .inner_type = 0, 3484 }, 3485 .item_ipv4.hdr = { 3486 .src_addr = vxlan_encap_conf.ipv4_src, 3487 .dst_addr = vxlan_encap_conf.ipv4_dst, 3488 }, 3489 .item_udp.hdr = { 3490 .src_port = vxlan_encap_conf.udp_src, 3491 .dst_port = vxlan_encap_conf.udp_dst, 3492 }, 3493 .item_vxlan.flags = 0, 3494 }; 3495 memcpy(action_vxlan_encap_data->item_eth.dst.addr_bytes, 3496 vxlan_encap_conf.eth_dst, ETHER_ADDR_LEN); 3497 memcpy(action_vxlan_encap_data->item_eth.src.addr_bytes, 3498 vxlan_encap_conf.eth_src, ETHER_ADDR_LEN); 3499 if (!vxlan_encap_conf.select_ipv4) { 3500 memcpy(&action_vxlan_encap_data->item_ipv6.hdr.src_addr, 3501 &vxlan_encap_conf.ipv6_src, 3502 sizeof(vxlan_encap_conf.ipv6_src)); 3503 memcpy(&action_vxlan_encap_data->item_ipv6.hdr.dst_addr, 3504 &vxlan_encap_conf.ipv6_dst, 3505 sizeof(vxlan_encap_conf.ipv6_dst)); 3506 action_vxlan_encap_data->items[2] = (struct rte_flow_item){ 3507 .type = RTE_FLOW_ITEM_TYPE_IPV6, 3508 .spec = &action_vxlan_encap_data->item_ipv6, 3509 .mask = &rte_flow_item_ipv6_mask, 3510 }; 3511 } 3512 if (!vxlan_encap_conf.select_vlan) 3513 action_vxlan_encap_data->items[1].type = 3514 RTE_FLOW_ITEM_TYPE_VOID; 3515 memcpy(action_vxlan_encap_data->item_vxlan.vni, vxlan_encap_conf.vni, 3516 RTE_DIM(vxlan_encap_conf.vni)); 3517 action->conf = &action_vxlan_encap_data->conf; 3518 return ret; 3519 } 3520 3521 /** Parse NVGRE encap action. */ 3522 static int 3523 parse_vc_action_nvgre_encap(struct context *ctx, const struct token *token, 3524 const char *str, unsigned int len, 3525 void *buf, unsigned int size) 3526 { 3527 struct buffer *out = buf; 3528 struct rte_flow_action *action; 3529 struct action_nvgre_encap_data *action_nvgre_encap_data; 3530 int ret; 3531 3532 ret = parse_vc(ctx, token, str, len, buf, size); 3533 if (ret < 0) 3534 return ret; 3535 /* Nothing else to do if there is no buffer. */ 3536 if (!out) 3537 return ret; 3538 if (!out->args.vc.actions_n) 3539 return -1; 3540 action = &out->args.vc.actions[out->args.vc.actions_n - 1]; 3541 /* Point to selected object. */ 3542 ctx->object = out->args.vc.data; 3543 ctx->objmask = NULL; 3544 /* Set up default configuration. */ 3545 action_nvgre_encap_data = ctx->object; 3546 *action_nvgre_encap_data = (struct action_nvgre_encap_data){ 3547 .conf = (struct rte_flow_action_nvgre_encap){ 3548 .definition = action_nvgre_encap_data->items, 3549 }, 3550 .items = { 3551 { 3552 .type = RTE_FLOW_ITEM_TYPE_ETH, 3553 .spec = &action_nvgre_encap_data->item_eth, 3554 .mask = &rte_flow_item_eth_mask, 3555 }, 3556 { 3557 .type = RTE_FLOW_ITEM_TYPE_VLAN, 3558 .spec = &action_nvgre_encap_data->item_vlan, 3559 .mask = &rte_flow_item_vlan_mask, 3560 }, 3561 { 3562 .type = RTE_FLOW_ITEM_TYPE_IPV4, 3563 .spec = &action_nvgre_encap_data->item_ipv4, 3564 .mask = &rte_flow_item_ipv4_mask, 3565 }, 3566 { 3567 .type = RTE_FLOW_ITEM_TYPE_NVGRE, 3568 .spec = &action_nvgre_encap_data->item_nvgre, 3569 .mask = &rte_flow_item_nvgre_mask, 3570 }, 3571 { 3572 .type = RTE_FLOW_ITEM_TYPE_END, 3573 }, 3574 }, 3575 .item_eth.type = 0, 3576 .item_vlan = { 3577 .tci = nvgre_encap_conf.vlan_tci, 3578 .inner_type = 0, 3579 }, 3580 .item_ipv4.hdr = { 3581 .src_addr = nvgre_encap_conf.ipv4_src, 3582 .dst_addr = nvgre_encap_conf.ipv4_dst, 3583 }, 3584 .item_nvgre.flow_id = 0, 3585 }; 3586 memcpy(action_nvgre_encap_data->item_eth.dst.addr_bytes, 3587 nvgre_encap_conf.eth_dst, ETHER_ADDR_LEN); 3588 memcpy(action_nvgre_encap_data->item_eth.src.addr_bytes, 3589 nvgre_encap_conf.eth_src, ETHER_ADDR_LEN); 3590 if (!nvgre_encap_conf.select_ipv4) { 3591 memcpy(&action_nvgre_encap_data->item_ipv6.hdr.src_addr, 3592 &nvgre_encap_conf.ipv6_src, 3593 sizeof(nvgre_encap_conf.ipv6_src)); 3594 memcpy(&action_nvgre_encap_data->item_ipv6.hdr.dst_addr, 3595 &nvgre_encap_conf.ipv6_dst, 3596 sizeof(nvgre_encap_conf.ipv6_dst)); 3597 action_nvgre_encap_data->items[2] = (struct rte_flow_item){ 3598 .type = RTE_FLOW_ITEM_TYPE_IPV6, 3599 .spec = &action_nvgre_encap_data->item_ipv6, 3600 .mask = &rte_flow_item_ipv6_mask, 3601 }; 3602 } 3603 if (!nvgre_encap_conf.select_vlan) 3604 action_nvgre_encap_data->items[1].type = 3605 RTE_FLOW_ITEM_TYPE_VOID; 3606 memcpy(action_nvgre_encap_data->item_nvgre.tni, nvgre_encap_conf.tni, 3607 RTE_DIM(nvgre_encap_conf.tni)); 3608 action->conf = &action_nvgre_encap_data->conf; 3609 return ret; 3610 } 3611 3612 /** Parse l2 encap action. */ 3613 static int 3614 parse_vc_action_l2_encap(struct context *ctx, const struct token *token, 3615 const char *str, unsigned int len, 3616 void *buf, unsigned int size) 3617 { 3618 struct buffer *out = buf; 3619 struct rte_flow_action *action; 3620 struct action_raw_encap_data *action_encap_data; 3621 struct rte_flow_item_eth eth = { .type = 0, }; 3622 struct rte_flow_item_vlan vlan = { 3623 .tci = mplsoudp_encap_conf.vlan_tci, 3624 .inner_type = 0, 3625 }; 3626 uint8_t *header; 3627 int ret; 3628 3629 ret = parse_vc(ctx, token, str, len, buf, size); 3630 if (ret < 0) 3631 return ret; 3632 /* Nothing else to do if there is no buffer. */ 3633 if (!out) 3634 return ret; 3635 if (!out->args.vc.actions_n) 3636 return -1; 3637 action = &out->args.vc.actions[out->args.vc.actions_n - 1]; 3638 /* Point to selected object. */ 3639 ctx->object = out->args.vc.data; 3640 ctx->objmask = NULL; 3641 /* Copy the headers to the buffer. */ 3642 action_encap_data = ctx->object; 3643 *action_encap_data = (struct action_raw_encap_data) { 3644 .conf = (struct rte_flow_action_raw_encap){ 3645 .data = action_encap_data->data, 3646 }, 3647 .data = {}, 3648 }; 3649 header = action_encap_data->data; 3650 if (l2_encap_conf.select_vlan) 3651 eth.type = rte_cpu_to_be_16(ETHER_TYPE_VLAN); 3652 else if (l2_encap_conf.select_ipv4) 3653 eth.type = rte_cpu_to_be_16(ETHER_TYPE_IPv4); 3654 else 3655 eth.type = rte_cpu_to_be_16(ETHER_TYPE_IPv6); 3656 memcpy(eth.dst.addr_bytes, 3657 l2_encap_conf.eth_dst, ETHER_ADDR_LEN); 3658 memcpy(eth.src.addr_bytes, 3659 l2_encap_conf.eth_src, ETHER_ADDR_LEN); 3660 memcpy(header, ð, sizeof(eth)); 3661 header += sizeof(eth); 3662 if (l2_encap_conf.select_vlan) { 3663 if (l2_encap_conf.select_ipv4) 3664 vlan.inner_type = rte_cpu_to_be_16(ETHER_TYPE_IPv4); 3665 else 3666 vlan.inner_type = rte_cpu_to_be_16(ETHER_TYPE_IPv6); 3667 memcpy(header, &vlan, sizeof(vlan)); 3668 header += sizeof(vlan); 3669 } 3670 action_encap_data->conf.size = header - 3671 action_encap_data->data; 3672 action->conf = &action_encap_data->conf; 3673 return ret; 3674 } 3675 3676 /** Parse l2 decap action. */ 3677 static int 3678 parse_vc_action_l2_decap(struct context *ctx, const struct token *token, 3679 const char *str, unsigned int len, 3680 void *buf, unsigned int size) 3681 { 3682 struct buffer *out = buf; 3683 struct rte_flow_action *action; 3684 struct action_raw_decap_data *action_decap_data; 3685 struct rte_flow_item_eth eth = { .type = 0, }; 3686 struct rte_flow_item_vlan vlan = { 3687 .tci = mplsoudp_encap_conf.vlan_tci, 3688 .inner_type = 0, 3689 }; 3690 uint8_t *header; 3691 int ret; 3692 3693 ret = parse_vc(ctx, token, str, len, buf, size); 3694 if (ret < 0) 3695 return ret; 3696 /* Nothing else to do if there is no buffer. */ 3697 if (!out) 3698 return ret; 3699 if (!out->args.vc.actions_n) 3700 return -1; 3701 action = &out->args.vc.actions[out->args.vc.actions_n - 1]; 3702 /* Point to selected object. */ 3703 ctx->object = out->args.vc.data; 3704 ctx->objmask = NULL; 3705 /* Copy the headers to the buffer. */ 3706 action_decap_data = ctx->object; 3707 *action_decap_data = (struct action_raw_decap_data) { 3708 .conf = (struct rte_flow_action_raw_decap){ 3709 .data = action_decap_data->data, 3710 }, 3711 .data = {}, 3712 }; 3713 header = action_decap_data->data; 3714 if (l2_decap_conf.select_vlan) 3715 eth.type = rte_cpu_to_be_16(ETHER_TYPE_VLAN); 3716 memcpy(header, ð, sizeof(eth)); 3717 header += sizeof(eth); 3718 if (l2_decap_conf.select_vlan) { 3719 memcpy(header, &vlan, sizeof(vlan)); 3720 header += sizeof(vlan); 3721 } 3722 action_decap_data->conf.size = header - 3723 action_decap_data->data; 3724 action->conf = &action_decap_data->conf; 3725 return ret; 3726 } 3727 3728 #define ETHER_TYPE_MPLS_UNICAST 0x8847 3729 3730 /** Parse MPLSOGRE encap action. */ 3731 static int 3732 parse_vc_action_mplsogre_encap(struct context *ctx, const struct token *token, 3733 const char *str, unsigned int len, 3734 void *buf, unsigned int size) 3735 { 3736 struct buffer *out = buf; 3737 struct rte_flow_action *action; 3738 struct action_raw_encap_data *action_encap_data; 3739 struct rte_flow_item_eth eth = { .type = 0, }; 3740 struct rte_flow_item_vlan vlan = { 3741 .tci = mplsogre_encap_conf.vlan_tci, 3742 .inner_type = 0, 3743 }; 3744 struct rte_flow_item_ipv4 ipv4 = { 3745 .hdr = { 3746 .src_addr = mplsogre_encap_conf.ipv4_src, 3747 .dst_addr = mplsogre_encap_conf.ipv4_dst, 3748 .next_proto_id = IPPROTO_GRE, 3749 }, 3750 }; 3751 struct rte_flow_item_ipv6 ipv6 = { 3752 .hdr = { 3753 .proto = IPPROTO_GRE, 3754 }, 3755 }; 3756 struct rte_flow_item_gre gre = { 3757 .protocol = rte_cpu_to_be_16(ETHER_TYPE_MPLS_UNICAST), 3758 }; 3759 struct rte_flow_item_mpls mpls; 3760 uint8_t *header; 3761 int ret; 3762 3763 ret = parse_vc(ctx, token, str, len, buf, size); 3764 if (ret < 0) 3765 return ret; 3766 /* Nothing else to do if there is no buffer. */ 3767 if (!out) 3768 return ret; 3769 if (!out->args.vc.actions_n) 3770 return -1; 3771 action = &out->args.vc.actions[out->args.vc.actions_n - 1]; 3772 /* Point to selected object. */ 3773 ctx->object = out->args.vc.data; 3774 ctx->objmask = NULL; 3775 /* Copy the headers to the buffer. */ 3776 action_encap_data = ctx->object; 3777 *action_encap_data = (struct action_raw_encap_data) { 3778 .conf = (struct rte_flow_action_raw_encap){ 3779 .data = action_encap_data->data, 3780 }, 3781 .data = {}, 3782 .preserve = {}, 3783 }; 3784 header = action_encap_data->data; 3785 if (mplsogre_encap_conf.select_vlan) 3786 eth.type = rte_cpu_to_be_16(ETHER_TYPE_VLAN); 3787 else if (mplsogre_encap_conf.select_ipv4) 3788 eth.type = rte_cpu_to_be_16(ETHER_TYPE_IPv4); 3789 else 3790 eth.type = rte_cpu_to_be_16(ETHER_TYPE_IPv6); 3791 memcpy(eth.dst.addr_bytes, 3792 mplsogre_encap_conf.eth_dst, ETHER_ADDR_LEN); 3793 memcpy(eth.src.addr_bytes, 3794 mplsogre_encap_conf.eth_src, ETHER_ADDR_LEN); 3795 memcpy(header, ð, sizeof(eth)); 3796 header += sizeof(eth); 3797 if (mplsogre_encap_conf.select_vlan) { 3798 if (mplsogre_encap_conf.select_ipv4) 3799 vlan.inner_type = rte_cpu_to_be_16(ETHER_TYPE_IPv4); 3800 else 3801 vlan.inner_type = rte_cpu_to_be_16(ETHER_TYPE_IPv6); 3802 memcpy(header, &vlan, sizeof(vlan)); 3803 header += sizeof(vlan); 3804 } 3805 if (mplsogre_encap_conf.select_ipv4) { 3806 memcpy(header, &ipv4, sizeof(ipv4)); 3807 header += sizeof(ipv4); 3808 } else { 3809 memcpy(&ipv6.hdr.src_addr, 3810 &mplsogre_encap_conf.ipv6_src, 3811 sizeof(mplsogre_encap_conf.ipv6_src)); 3812 memcpy(&ipv6.hdr.dst_addr, 3813 &mplsogre_encap_conf.ipv6_dst, 3814 sizeof(mplsogre_encap_conf.ipv6_dst)); 3815 memcpy(header, &ipv6, sizeof(ipv6)); 3816 header += sizeof(ipv6); 3817 } 3818 memcpy(header, &gre, sizeof(gre)); 3819 header += sizeof(gre); 3820 memcpy(mpls.label_tc_s, mplsogre_encap_conf.label, 3821 RTE_DIM(mplsogre_encap_conf.label)); 3822 mpls.label_tc_s[2] |= 0x1; 3823 memcpy(header, &mpls, sizeof(mpls)); 3824 header += sizeof(mpls); 3825 action_encap_data->conf.size = header - 3826 action_encap_data->data; 3827 action->conf = &action_encap_data->conf; 3828 return ret; 3829 } 3830 3831 /** Parse MPLSOGRE decap action. */ 3832 static int 3833 parse_vc_action_mplsogre_decap(struct context *ctx, const struct token *token, 3834 const char *str, unsigned int len, 3835 void *buf, unsigned int size) 3836 { 3837 struct buffer *out = buf; 3838 struct rte_flow_action *action; 3839 struct action_raw_decap_data *action_decap_data; 3840 struct rte_flow_item_eth eth = { .type = 0, }; 3841 struct rte_flow_item_vlan vlan = {.tci = 0}; 3842 struct rte_flow_item_ipv4 ipv4 = { 3843 .hdr = { 3844 .next_proto_id = IPPROTO_GRE, 3845 }, 3846 }; 3847 struct rte_flow_item_ipv6 ipv6 = { 3848 .hdr = { 3849 .proto = IPPROTO_GRE, 3850 }, 3851 }; 3852 struct rte_flow_item_gre gre = { 3853 .protocol = rte_cpu_to_be_16(ETHER_TYPE_MPLS_UNICAST), 3854 }; 3855 struct rte_flow_item_mpls mpls; 3856 uint8_t *header; 3857 int ret; 3858 3859 ret = parse_vc(ctx, token, str, len, buf, size); 3860 if (ret < 0) 3861 return ret; 3862 /* Nothing else to do if there is no buffer. */ 3863 if (!out) 3864 return ret; 3865 if (!out->args.vc.actions_n) 3866 return -1; 3867 action = &out->args.vc.actions[out->args.vc.actions_n - 1]; 3868 /* Point to selected object. */ 3869 ctx->object = out->args.vc.data; 3870 ctx->objmask = NULL; 3871 /* Copy the headers to the buffer. */ 3872 action_decap_data = ctx->object; 3873 *action_decap_data = (struct action_raw_decap_data) { 3874 .conf = (struct rte_flow_action_raw_decap){ 3875 .data = action_decap_data->data, 3876 }, 3877 .data = {}, 3878 }; 3879 header = action_decap_data->data; 3880 if (mplsogre_decap_conf.select_vlan) 3881 eth.type = rte_cpu_to_be_16(ETHER_TYPE_VLAN); 3882 else if (mplsogre_encap_conf.select_ipv4) 3883 eth.type = rte_cpu_to_be_16(ETHER_TYPE_IPv4); 3884 else 3885 eth.type = rte_cpu_to_be_16(ETHER_TYPE_IPv6); 3886 memcpy(eth.dst.addr_bytes, 3887 mplsogre_encap_conf.eth_dst, ETHER_ADDR_LEN); 3888 memcpy(eth.src.addr_bytes, 3889 mplsogre_encap_conf.eth_src, ETHER_ADDR_LEN); 3890 memcpy(header, ð, sizeof(eth)); 3891 header += sizeof(eth); 3892 if (mplsogre_encap_conf.select_vlan) { 3893 if (mplsogre_encap_conf.select_ipv4) 3894 vlan.inner_type = rte_cpu_to_be_16(ETHER_TYPE_IPv4); 3895 else 3896 vlan.inner_type = rte_cpu_to_be_16(ETHER_TYPE_IPv6); 3897 memcpy(header, &vlan, sizeof(vlan)); 3898 header += sizeof(vlan); 3899 } 3900 if (mplsogre_encap_conf.select_ipv4) { 3901 memcpy(header, &ipv4, sizeof(ipv4)); 3902 header += sizeof(ipv4); 3903 } else { 3904 memcpy(header, &ipv6, sizeof(ipv6)); 3905 header += sizeof(ipv6); 3906 } 3907 memcpy(header, &gre, sizeof(gre)); 3908 header += sizeof(gre); 3909 memset(&mpls, 0, sizeof(mpls)); 3910 memcpy(header, &mpls, sizeof(mpls)); 3911 header += sizeof(mpls); 3912 action_decap_data->conf.size = header - 3913 action_decap_data->data; 3914 action->conf = &action_decap_data->conf; 3915 return ret; 3916 } 3917 3918 /** Parse MPLSOUDP encap action. */ 3919 static int 3920 parse_vc_action_mplsoudp_encap(struct context *ctx, const struct token *token, 3921 const char *str, unsigned int len, 3922 void *buf, unsigned int size) 3923 { 3924 struct buffer *out = buf; 3925 struct rte_flow_action *action; 3926 struct action_raw_encap_data *action_encap_data; 3927 struct rte_flow_item_eth eth = { .type = 0, }; 3928 struct rte_flow_item_vlan vlan = { 3929 .tci = mplsoudp_encap_conf.vlan_tci, 3930 .inner_type = 0, 3931 }; 3932 struct rte_flow_item_ipv4 ipv4 = { 3933 .hdr = { 3934 .src_addr = mplsoudp_encap_conf.ipv4_src, 3935 .dst_addr = mplsoudp_encap_conf.ipv4_dst, 3936 .next_proto_id = IPPROTO_UDP, 3937 }, 3938 }; 3939 struct rte_flow_item_ipv6 ipv6 = { 3940 .hdr = { 3941 .proto = IPPROTO_UDP, 3942 }, 3943 }; 3944 struct rte_flow_item_udp udp = { 3945 .hdr = { 3946 .src_port = mplsoudp_encap_conf.udp_src, 3947 .dst_port = mplsoudp_encap_conf.udp_dst, 3948 }, 3949 }; 3950 struct rte_flow_item_mpls mpls; 3951 uint8_t *header; 3952 int ret; 3953 3954 ret = parse_vc(ctx, token, str, len, buf, size); 3955 if (ret < 0) 3956 return ret; 3957 /* Nothing else to do if there is no buffer. */ 3958 if (!out) 3959 return ret; 3960 if (!out->args.vc.actions_n) 3961 return -1; 3962 action = &out->args.vc.actions[out->args.vc.actions_n - 1]; 3963 /* Point to selected object. */ 3964 ctx->object = out->args.vc.data; 3965 ctx->objmask = NULL; 3966 /* Copy the headers to the buffer. */ 3967 action_encap_data = ctx->object; 3968 *action_encap_data = (struct action_raw_encap_data) { 3969 .conf = (struct rte_flow_action_raw_encap){ 3970 .data = action_encap_data->data, 3971 }, 3972 .data = {}, 3973 .preserve = {}, 3974 }; 3975 header = action_encap_data->data; 3976 if (mplsoudp_encap_conf.select_vlan) 3977 eth.type = rte_cpu_to_be_16(ETHER_TYPE_VLAN); 3978 else if (mplsoudp_encap_conf.select_ipv4) 3979 eth.type = rte_cpu_to_be_16(ETHER_TYPE_IPv4); 3980 else 3981 eth.type = rte_cpu_to_be_16(ETHER_TYPE_IPv6); 3982 memcpy(eth.dst.addr_bytes, 3983 mplsoudp_encap_conf.eth_dst, ETHER_ADDR_LEN); 3984 memcpy(eth.src.addr_bytes, 3985 mplsoudp_encap_conf.eth_src, ETHER_ADDR_LEN); 3986 memcpy(header, ð, sizeof(eth)); 3987 header += sizeof(eth); 3988 if (mplsoudp_encap_conf.select_vlan) { 3989 if (mplsoudp_encap_conf.select_ipv4) 3990 vlan.inner_type = rte_cpu_to_be_16(ETHER_TYPE_IPv4); 3991 else 3992 vlan.inner_type = rte_cpu_to_be_16(ETHER_TYPE_IPv6); 3993 memcpy(header, &vlan, sizeof(vlan)); 3994 header += sizeof(vlan); 3995 } 3996 if (mplsoudp_encap_conf.select_ipv4) { 3997 memcpy(header, &ipv4, sizeof(ipv4)); 3998 header += sizeof(ipv4); 3999 } else { 4000 memcpy(&ipv6.hdr.src_addr, 4001 &mplsoudp_encap_conf.ipv6_src, 4002 sizeof(mplsoudp_encap_conf.ipv6_src)); 4003 memcpy(&ipv6.hdr.dst_addr, 4004 &mplsoudp_encap_conf.ipv6_dst, 4005 sizeof(mplsoudp_encap_conf.ipv6_dst)); 4006 memcpy(header, &ipv6, sizeof(ipv6)); 4007 header += sizeof(ipv6); 4008 } 4009 memcpy(header, &udp, sizeof(udp)); 4010 header += sizeof(udp); 4011 memcpy(mpls.label_tc_s, mplsoudp_encap_conf.label, 4012 RTE_DIM(mplsoudp_encap_conf.label)); 4013 mpls.label_tc_s[2] |= 0x1; 4014 memcpy(header, &mpls, sizeof(mpls)); 4015 header += sizeof(mpls); 4016 action_encap_data->conf.size = header - 4017 action_encap_data->data; 4018 action->conf = &action_encap_data->conf; 4019 return ret; 4020 } 4021 4022 /** Parse MPLSOUDP decap action. */ 4023 static int 4024 parse_vc_action_mplsoudp_decap(struct context *ctx, const struct token *token, 4025 const char *str, unsigned int len, 4026 void *buf, unsigned int size) 4027 { 4028 struct buffer *out = buf; 4029 struct rte_flow_action *action; 4030 struct action_raw_decap_data *action_decap_data; 4031 struct rte_flow_item_eth eth = { .type = 0, }; 4032 struct rte_flow_item_vlan vlan = {.tci = 0}; 4033 struct rte_flow_item_ipv4 ipv4 = { 4034 .hdr = { 4035 .next_proto_id = IPPROTO_UDP, 4036 }, 4037 }; 4038 struct rte_flow_item_ipv6 ipv6 = { 4039 .hdr = { 4040 .proto = IPPROTO_UDP, 4041 }, 4042 }; 4043 struct rte_flow_item_udp udp = { 4044 .hdr = { 4045 .dst_port = rte_cpu_to_be_16(6635), 4046 }, 4047 }; 4048 struct rte_flow_item_mpls mpls; 4049 uint8_t *header; 4050 int ret; 4051 4052 ret = parse_vc(ctx, token, str, len, buf, size); 4053 if (ret < 0) 4054 return ret; 4055 /* Nothing else to do if there is no buffer. */ 4056 if (!out) 4057 return ret; 4058 if (!out->args.vc.actions_n) 4059 return -1; 4060 action = &out->args.vc.actions[out->args.vc.actions_n - 1]; 4061 /* Point to selected object. */ 4062 ctx->object = out->args.vc.data; 4063 ctx->objmask = NULL; 4064 /* Copy the headers to the buffer. */ 4065 action_decap_data = ctx->object; 4066 *action_decap_data = (struct action_raw_decap_data) { 4067 .conf = (struct rte_flow_action_raw_decap){ 4068 .data = action_decap_data->data, 4069 }, 4070 .data = {}, 4071 }; 4072 header = action_decap_data->data; 4073 if (mplsoudp_decap_conf.select_vlan) 4074 eth.type = rte_cpu_to_be_16(ETHER_TYPE_VLAN); 4075 else if (mplsoudp_encap_conf.select_ipv4) 4076 eth.type = rte_cpu_to_be_16(ETHER_TYPE_IPv4); 4077 else 4078 eth.type = rte_cpu_to_be_16(ETHER_TYPE_IPv6); 4079 memcpy(eth.dst.addr_bytes, 4080 mplsoudp_encap_conf.eth_dst, ETHER_ADDR_LEN); 4081 memcpy(eth.src.addr_bytes, 4082 mplsoudp_encap_conf.eth_src, ETHER_ADDR_LEN); 4083 memcpy(header, ð, sizeof(eth)); 4084 header += sizeof(eth); 4085 if (mplsoudp_encap_conf.select_vlan) { 4086 if (mplsoudp_encap_conf.select_ipv4) 4087 vlan.inner_type = rte_cpu_to_be_16(ETHER_TYPE_IPv4); 4088 else 4089 vlan.inner_type = rte_cpu_to_be_16(ETHER_TYPE_IPv6); 4090 memcpy(header, &vlan, sizeof(vlan)); 4091 header += sizeof(vlan); 4092 } 4093 if (mplsoudp_encap_conf.select_ipv4) { 4094 memcpy(header, &ipv4, sizeof(ipv4)); 4095 header += sizeof(ipv4); 4096 } else { 4097 memcpy(header, &ipv6, sizeof(ipv6)); 4098 header += sizeof(ipv6); 4099 } 4100 memcpy(header, &udp, sizeof(udp)); 4101 header += sizeof(udp); 4102 memset(&mpls, 0, sizeof(mpls)); 4103 memcpy(header, &mpls, sizeof(mpls)); 4104 header += sizeof(mpls); 4105 action_decap_data->conf.size = header - 4106 action_decap_data->data; 4107 action->conf = &action_decap_data->conf; 4108 return ret; 4109 } 4110 4111 /** Parse tokens for destroy command. */ 4112 static int 4113 parse_destroy(struct context *ctx, const struct token *token, 4114 const char *str, unsigned int len, 4115 void *buf, unsigned int size) 4116 { 4117 struct buffer *out = buf; 4118 4119 /* Token name must match. */ 4120 if (parse_default(ctx, token, str, len, NULL, 0) < 0) 4121 return -1; 4122 /* Nothing else to do if there is no buffer. */ 4123 if (!out) 4124 return len; 4125 if (!out->command) { 4126 if (ctx->curr != DESTROY) 4127 return -1; 4128 if (sizeof(*out) > size) 4129 return -1; 4130 out->command = ctx->curr; 4131 ctx->objdata = 0; 4132 ctx->object = out; 4133 ctx->objmask = NULL; 4134 out->args.destroy.rule = 4135 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1), 4136 sizeof(double)); 4137 return len; 4138 } 4139 if (((uint8_t *)(out->args.destroy.rule + out->args.destroy.rule_n) + 4140 sizeof(*out->args.destroy.rule)) > (uint8_t *)out + size) 4141 return -1; 4142 ctx->objdata = 0; 4143 ctx->object = out->args.destroy.rule + out->args.destroy.rule_n++; 4144 ctx->objmask = NULL; 4145 return len; 4146 } 4147 4148 /** Parse tokens for flush command. */ 4149 static int 4150 parse_flush(struct context *ctx, const struct token *token, 4151 const char *str, unsigned int len, 4152 void *buf, unsigned int size) 4153 { 4154 struct buffer *out = buf; 4155 4156 /* Token name must match. */ 4157 if (parse_default(ctx, token, str, len, NULL, 0) < 0) 4158 return -1; 4159 /* Nothing else to do if there is no buffer. */ 4160 if (!out) 4161 return len; 4162 if (!out->command) { 4163 if (ctx->curr != FLUSH) 4164 return -1; 4165 if (sizeof(*out) > size) 4166 return -1; 4167 out->command = ctx->curr; 4168 ctx->objdata = 0; 4169 ctx->object = out; 4170 ctx->objmask = NULL; 4171 } 4172 return len; 4173 } 4174 4175 /** Parse tokens for query command. */ 4176 static int 4177 parse_query(struct context *ctx, const struct token *token, 4178 const char *str, unsigned int len, 4179 void *buf, unsigned int size) 4180 { 4181 struct buffer *out = buf; 4182 4183 /* Token name must match. */ 4184 if (parse_default(ctx, token, str, len, NULL, 0) < 0) 4185 return -1; 4186 /* Nothing else to do if there is no buffer. */ 4187 if (!out) 4188 return len; 4189 if (!out->command) { 4190 if (ctx->curr != QUERY) 4191 return -1; 4192 if (sizeof(*out) > size) 4193 return -1; 4194 out->command = ctx->curr; 4195 ctx->objdata = 0; 4196 ctx->object = out; 4197 ctx->objmask = NULL; 4198 } 4199 return len; 4200 } 4201 4202 /** Parse action names. */ 4203 static int 4204 parse_action(struct context *ctx, const struct token *token, 4205 const char *str, unsigned int len, 4206 void *buf, unsigned int size) 4207 { 4208 struct buffer *out = buf; 4209 const struct arg *arg = pop_args(ctx); 4210 unsigned int i; 4211 4212 (void)size; 4213 /* Argument is expected. */ 4214 if (!arg) 4215 return -1; 4216 /* Parse action name. */ 4217 for (i = 0; next_action[i]; ++i) { 4218 const struct parse_action_priv *priv; 4219 4220 token = &token_list[next_action[i]]; 4221 if (strcmp_partial(token->name, str, len)) 4222 continue; 4223 priv = token->priv; 4224 if (!priv) 4225 goto error; 4226 if (out) 4227 memcpy((uint8_t *)ctx->object + arg->offset, 4228 &priv->type, 4229 arg->size); 4230 return len; 4231 } 4232 error: 4233 push_args(ctx, arg); 4234 return -1; 4235 } 4236 4237 /** Parse tokens for list command. */ 4238 static int 4239 parse_list(struct context *ctx, const struct token *token, 4240 const char *str, unsigned int len, 4241 void *buf, unsigned int size) 4242 { 4243 struct buffer *out = buf; 4244 4245 /* Token name must match. */ 4246 if (parse_default(ctx, token, str, len, NULL, 0) < 0) 4247 return -1; 4248 /* Nothing else to do if there is no buffer. */ 4249 if (!out) 4250 return len; 4251 if (!out->command) { 4252 if (ctx->curr != LIST) 4253 return -1; 4254 if (sizeof(*out) > size) 4255 return -1; 4256 out->command = ctx->curr; 4257 ctx->objdata = 0; 4258 ctx->object = out; 4259 ctx->objmask = NULL; 4260 out->args.list.group = 4261 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1), 4262 sizeof(double)); 4263 return len; 4264 } 4265 if (((uint8_t *)(out->args.list.group + out->args.list.group_n) + 4266 sizeof(*out->args.list.group)) > (uint8_t *)out + size) 4267 return -1; 4268 ctx->objdata = 0; 4269 ctx->object = out->args.list.group + out->args.list.group_n++; 4270 ctx->objmask = NULL; 4271 return len; 4272 } 4273 4274 /** Parse tokens for isolate command. */ 4275 static int 4276 parse_isolate(struct context *ctx, const struct token *token, 4277 const char *str, unsigned int len, 4278 void *buf, unsigned int size) 4279 { 4280 struct buffer *out = buf; 4281 4282 /* Token name must match. */ 4283 if (parse_default(ctx, token, str, len, NULL, 0) < 0) 4284 return -1; 4285 /* Nothing else to do if there is no buffer. */ 4286 if (!out) 4287 return len; 4288 if (!out->command) { 4289 if (ctx->curr != ISOLATE) 4290 return -1; 4291 if (sizeof(*out) > size) 4292 return -1; 4293 out->command = ctx->curr; 4294 ctx->objdata = 0; 4295 ctx->object = out; 4296 ctx->objmask = NULL; 4297 } 4298 return len; 4299 } 4300 4301 /** 4302 * Parse signed/unsigned integers 8 to 64-bit long. 4303 * 4304 * Last argument (ctx->args) is retrieved to determine integer type and 4305 * storage location. 4306 */ 4307 static int 4308 parse_int(struct context *ctx, const struct token *token, 4309 const char *str, unsigned int len, 4310 void *buf, unsigned int size) 4311 { 4312 const struct arg *arg = pop_args(ctx); 4313 uintmax_t u; 4314 char *end; 4315 4316 (void)token; 4317 /* Argument is expected. */ 4318 if (!arg) 4319 return -1; 4320 errno = 0; 4321 u = arg->sign ? 4322 (uintmax_t)strtoimax(str, &end, 0) : 4323 strtoumax(str, &end, 0); 4324 if (errno || (size_t)(end - str) != len) 4325 goto error; 4326 if (arg->bounded && 4327 ((arg->sign && ((intmax_t)u < (intmax_t)arg->min || 4328 (intmax_t)u > (intmax_t)arg->max)) || 4329 (!arg->sign && (u < arg->min || u > arg->max)))) 4330 goto error; 4331 if (!ctx->object) 4332 return len; 4333 if (arg->mask) { 4334 if (!arg_entry_bf_fill(ctx->object, u, arg) || 4335 !arg_entry_bf_fill(ctx->objmask, -1, arg)) 4336 goto error; 4337 return len; 4338 } 4339 buf = (uint8_t *)ctx->object + arg->offset; 4340 size = arg->size; 4341 objmask: 4342 switch (size) { 4343 case sizeof(uint8_t): 4344 *(uint8_t *)buf = u; 4345 break; 4346 case sizeof(uint16_t): 4347 *(uint16_t *)buf = arg->hton ? rte_cpu_to_be_16(u) : u; 4348 break; 4349 case sizeof(uint8_t [3]): 4350 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN 4351 if (!arg->hton) { 4352 ((uint8_t *)buf)[0] = u; 4353 ((uint8_t *)buf)[1] = u >> 8; 4354 ((uint8_t *)buf)[2] = u >> 16; 4355 break; 4356 } 4357 #endif 4358 ((uint8_t *)buf)[0] = u >> 16; 4359 ((uint8_t *)buf)[1] = u >> 8; 4360 ((uint8_t *)buf)[2] = u; 4361 break; 4362 case sizeof(uint32_t): 4363 *(uint32_t *)buf = arg->hton ? rte_cpu_to_be_32(u) : u; 4364 break; 4365 case sizeof(uint64_t): 4366 *(uint64_t *)buf = arg->hton ? rte_cpu_to_be_64(u) : u; 4367 break; 4368 default: 4369 goto error; 4370 } 4371 if (ctx->objmask && buf != (uint8_t *)ctx->objmask + arg->offset) { 4372 u = -1; 4373 buf = (uint8_t *)ctx->objmask + arg->offset; 4374 goto objmask; 4375 } 4376 return len; 4377 error: 4378 push_args(ctx, arg); 4379 return -1; 4380 } 4381 4382 /** 4383 * Parse a string. 4384 * 4385 * Three arguments (ctx->args) are retrieved from the stack to store data, 4386 * its actual length and address (in that order). 4387 */ 4388 static int 4389 parse_string(struct context *ctx, const struct token *token, 4390 const char *str, unsigned int len, 4391 void *buf, unsigned int size) 4392 { 4393 const struct arg *arg_data = pop_args(ctx); 4394 const struct arg *arg_len = pop_args(ctx); 4395 const struct arg *arg_addr = pop_args(ctx); 4396 char tmp[16]; /* Ought to be enough. */ 4397 int ret; 4398 4399 /* Arguments are expected. */ 4400 if (!arg_data) 4401 return -1; 4402 if (!arg_len) { 4403 push_args(ctx, arg_data); 4404 return -1; 4405 } 4406 if (!arg_addr) { 4407 push_args(ctx, arg_len); 4408 push_args(ctx, arg_data); 4409 return -1; 4410 } 4411 size = arg_data->size; 4412 /* Bit-mask fill is not supported. */ 4413 if (arg_data->mask || size < len) 4414 goto error; 4415 if (!ctx->object) 4416 return len; 4417 /* Let parse_int() fill length information first. */ 4418 ret = snprintf(tmp, sizeof(tmp), "%u", len); 4419 if (ret < 0) 4420 goto error; 4421 push_args(ctx, arg_len); 4422 ret = parse_int(ctx, token, tmp, ret, NULL, 0); 4423 if (ret < 0) { 4424 pop_args(ctx); 4425 goto error; 4426 } 4427 buf = (uint8_t *)ctx->object + arg_data->offset; 4428 /* Output buffer is not necessarily NUL-terminated. */ 4429 memcpy(buf, str, len); 4430 memset((uint8_t *)buf + len, 0x00, size - len); 4431 if (ctx->objmask) 4432 memset((uint8_t *)ctx->objmask + arg_data->offset, 0xff, len); 4433 /* Save address if requested. */ 4434 if (arg_addr->size) { 4435 memcpy((uint8_t *)ctx->object + arg_addr->offset, 4436 (void *[]){ 4437 (uint8_t *)ctx->object + arg_data->offset 4438 }, 4439 arg_addr->size); 4440 if (ctx->objmask) 4441 memcpy((uint8_t *)ctx->objmask + arg_addr->offset, 4442 (void *[]){ 4443 (uint8_t *)ctx->objmask + arg_data->offset 4444 }, 4445 arg_addr->size); 4446 } 4447 return len; 4448 error: 4449 push_args(ctx, arg_addr); 4450 push_args(ctx, arg_len); 4451 push_args(ctx, arg_data); 4452 return -1; 4453 } 4454 4455 static int 4456 parse_hex_string(const char *src, uint8_t *dst, uint32_t *size) 4457 { 4458 char *c = NULL; 4459 uint32_t i, len; 4460 char tmp[3]; 4461 4462 /* Check input parameters */ 4463 if ((src == NULL) || 4464 (dst == NULL) || 4465 (size == NULL) || 4466 (*size == 0)) 4467 return -1; 4468 4469 /* Convert chars to bytes */ 4470 for (i = 0, len = 0; i < *size; i += 2) { 4471 snprintf(tmp, 3, "%s", src + i); 4472 dst[len++] = strtoul(tmp, &c, 16); 4473 if (*c != 0) { 4474 len--; 4475 dst[len] = 0; 4476 *size = len; 4477 return -1; 4478 } 4479 } 4480 dst[len] = 0; 4481 *size = len; 4482 4483 return 0; 4484 } 4485 4486 static int 4487 parse_hex(struct context *ctx, const struct token *token, 4488 const char *str, unsigned int len, 4489 void *buf, unsigned int size) 4490 { 4491 const struct arg *arg_data = pop_args(ctx); 4492 const struct arg *arg_len = pop_args(ctx); 4493 const struct arg *arg_addr = pop_args(ctx); 4494 char tmp[16]; /* Ought to be enough. */ 4495 int ret; 4496 unsigned int hexlen = len; 4497 unsigned int length = 256; 4498 uint8_t hex_tmp[length]; 4499 4500 /* Arguments are expected. */ 4501 if (!arg_data) 4502 return -1; 4503 if (!arg_len) { 4504 push_args(ctx, arg_data); 4505 return -1; 4506 } 4507 if (!arg_addr) { 4508 push_args(ctx, arg_len); 4509 push_args(ctx, arg_data); 4510 return -1; 4511 } 4512 size = arg_data->size; 4513 /* Bit-mask fill is not supported. */ 4514 if (arg_data->mask) 4515 goto error; 4516 if (!ctx->object) 4517 return len; 4518 4519 /* translate bytes string to array. */ 4520 if (str[0] == '0' && ((str[1] == 'x') || 4521 (str[1] == 'X'))) { 4522 str += 2; 4523 hexlen -= 2; 4524 } 4525 if (hexlen > length) 4526 return -1; 4527 ret = parse_hex_string(str, hex_tmp, &hexlen); 4528 if (ret < 0) 4529 goto error; 4530 /* Let parse_int() fill length information first. */ 4531 ret = snprintf(tmp, sizeof(tmp), "%u", hexlen); 4532 if (ret < 0) 4533 goto error; 4534 push_args(ctx, arg_len); 4535 ret = parse_int(ctx, token, tmp, ret, NULL, 0); 4536 if (ret < 0) { 4537 pop_args(ctx); 4538 goto error; 4539 } 4540 buf = (uint8_t *)ctx->object + arg_data->offset; 4541 /* Output buffer is not necessarily NUL-terminated. */ 4542 memcpy(buf, hex_tmp, hexlen); 4543 memset((uint8_t *)buf + hexlen, 0x00, size - hexlen); 4544 if (ctx->objmask) 4545 memset((uint8_t *)ctx->objmask + arg_data->offset, 4546 0xff, hexlen); 4547 /* Save address if requested. */ 4548 if (arg_addr->size) { 4549 memcpy((uint8_t *)ctx->object + arg_addr->offset, 4550 (void *[]){ 4551 (uint8_t *)ctx->object + arg_data->offset 4552 }, 4553 arg_addr->size); 4554 if (ctx->objmask) 4555 memcpy((uint8_t *)ctx->objmask + arg_addr->offset, 4556 (void *[]){ 4557 (uint8_t *)ctx->objmask + arg_data->offset 4558 }, 4559 arg_addr->size); 4560 } 4561 return len; 4562 error: 4563 push_args(ctx, arg_addr); 4564 push_args(ctx, arg_len); 4565 push_args(ctx, arg_data); 4566 return -1; 4567 4568 } 4569 4570 /** 4571 * Parse a MAC address. 4572 * 4573 * Last argument (ctx->args) is retrieved to determine storage size and 4574 * location. 4575 */ 4576 static int 4577 parse_mac_addr(struct context *ctx, const struct token *token, 4578 const char *str, unsigned int len, 4579 void *buf, unsigned int size) 4580 { 4581 const struct arg *arg = pop_args(ctx); 4582 struct ether_addr tmp; 4583 int ret; 4584 4585 (void)token; 4586 /* Argument is expected. */ 4587 if (!arg) 4588 return -1; 4589 size = arg->size; 4590 /* Bit-mask fill is not supported. */ 4591 if (arg->mask || size != sizeof(tmp)) 4592 goto error; 4593 /* Only network endian is supported. */ 4594 if (!arg->hton) 4595 goto error; 4596 ret = cmdline_parse_etheraddr(NULL, str, &tmp, size); 4597 if (ret < 0 || (unsigned int)ret != len) 4598 goto error; 4599 if (!ctx->object) 4600 return len; 4601 buf = (uint8_t *)ctx->object + arg->offset; 4602 memcpy(buf, &tmp, size); 4603 if (ctx->objmask) 4604 memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size); 4605 return len; 4606 error: 4607 push_args(ctx, arg); 4608 return -1; 4609 } 4610 4611 /** 4612 * Parse an IPv4 address. 4613 * 4614 * Last argument (ctx->args) is retrieved to determine storage size and 4615 * location. 4616 */ 4617 static int 4618 parse_ipv4_addr(struct context *ctx, const struct token *token, 4619 const char *str, unsigned int len, 4620 void *buf, unsigned int size) 4621 { 4622 const struct arg *arg = pop_args(ctx); 4623 char str2[len + 1]; 4624 struct in_addr tmp; 4625 int ret; 4626 4627 /* Argument is expected. */ 4628 if (!arg) 4629 return -1; 4630 size = arg->size; 4631 /* Bit-mask fill is not supported. */ 4632 if (arg->mask || size != sizeof(tmp)) 4633 goto error; 4634 /* Only network endian is supported. */ 4635 if (!arg->hton) 4636 goto error; 4637 memcpy(str2, str, len); 4638 str2[len] = '\0'; 4639 ret = inet_pton(AF_INET, str2, &tmp); 4640 if (ret != 1) { 4641 /* Attempt integer parsing. */ 4642 push_args(ctx, arg); 4643 return parse_int(ctx, token, str, len, buf, size); 4644 } 4645 if (!ctx->object) 4646 return len; 4647 buf = (uint8_t *)ctx->object + arg->offset; 4648 memcpy(buf, &tmp, size); 4649 if (ctx->objmask) 4650 memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size); 4651 return len; 4652 error: 4653 push_args(ctx, arg); 4654 return -1; 4655 } 4656 4657 /** 4658 * Parse an IPv6 address. 4659 * 4660 * Last argument (ctx->args) is retrieved to determine storage size and 4661 * location. 4662 */ 4663 static int 4664 parse_ipv6_addr(struct context *ctx, const struct token *token, 4665 const char *str, unsigned int len, 4666 void *buf, unsigned int size) 4667 { 4668 const struct arg *arg = pop_args(ctx); 4669 char str2[len + 1]; 4670 struct in6_addr tmp; 4671 int ret; 4672 4673 (void)token; 4674 /* Argument is expected. */ 4675 if (!arg) 4676 return -1; 4677 size = arg->size; 4678 /* Bit-mask fill is not supported. */ 4679 if (arg->mask || size != sizeof(tmp)) 4680 goto error; 4681 /* Only network endian is supported. */ 4682 if (!arg->hton) 4683 goto error; 4684 memcpy(str2, str, len); 4685 str2[len] = '\0'; 4686 ret = inet_pton(AF_INET6, str2, &tmp); 4687 if (ret != 1) 4688 goto error; 4689 if (!ctx->object) 4690 return len; 4691 buf = (uint8_t *)ctx->object + arg->offset; 4692 memcpy(buf, &tmp, size); 4693 if (ctx->objmask) 4694 memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size); 4695 return len; 4696 error: 4697 push_args(ctx, arg); 4698 return -1; 4699 } 4700 4701 /** Boolean values (even indices stand for false). */ 4702 static const char *const boolean_name[] = { 4703 "0", "1", 4704 "false", "true", 4705 "no", "yes", 4706 "N", "Y", 4707 "off", "on", 4708 NULL, 4709 }; 4710 4711 /** 4712 * Parse a boolean value. 4713 * 4714 * Last argument (ctx->args) is retrieved to determine storage size and 4715 * location. 4716 */ 4717 static int 4718 parse_boolean(struct context *ctx, const struct token *token, 4719 const char *str, unsigned int len, 4720 void *buf, unsigned int size) 4721 { 4722 const struct arg *arg = pop_args(ctx); 4723 unsigned int i; 4724 int ret; 4725 4726 /* Argument is expected. */ 4727 if (!arg) 4728 return -1; 4729 for (i = 0; boolean_name[i]; ++i) 4730 if (!strcmp_partial(boolean_name[i], str, len)) 4731 break; 4732 /* Process token as integer. */ 4733 if (boolean_name[i]) 4734 str = i & 1 ? "1" : "0"; 4735 push_args(ctx, arg); 4736 ret = parse_int(ctx, token, str, strlen(str), buf, size); 4737 return ret > 0 ? (int)len : ret; 4738 } 4739 4740 /** Parse port and update context. */ 4741 static int 4742 parse_port(struct context *ctx, const struct token *token, 4743 const char *str, unsigned int len, 4744 void *buf, unsigned int size) 4745 { 4746 struct buffer *out = &(struct buffer){ .port = 0 }; 4747 int ret; 4748 4749 if (buf) 4750 out = buf; 4751 else { 4752 ctx->objdata = 0; 4753 ctx->object = out; 4754 ctx->objmask = NULL; 4755 size = sizeof(*out); 4756 } 4757 ret = parse_int(ctx, token, str, len, out, size); 4758 if (ret >= 0) 4759 ctx->port = out->port; 4760 if (!buf) 4761 ctx->object = NULL; 4762 return ret; 4763 } 4764 4765 /** No completion. */ 4766 static int 4767 comp_none(struct context *ctx, const struct token *token, 4768 unsigned int ent, char *buf, unsigned int size) 4769 { 4770 (void)ctx; 4771 (void)token; 4772 (void)ent; 4773 (void)buf; 4774 (void)size; 4775 return 0; 4776 } 4777 4778 /** Complete boolean values. */ 4779 static int 4780 comp_boolean(struct context *ctx, const struct token *token, 4781 unsigned int ent, char *buf, unsigned int size) 4782 { 4783 unsigned int i; 4784 4785 (void)ctx; 4786 (void)token; 4787 for (i = 0; boolean_name[i]; ++i) 4788 if (buf && i == ent) 4789 return snprintf(buf, size, "%s", boolean_name[i]); 4790 if (buf) 4791 return -1; 4792 return i; 4793 } 4794 4795 /** Complete action names. */ 4796 static int 4797 comp_action(struct context *ctx, const struct token *token, 4798 unsigned int ent, char *buf, unsigned int size) 4799 { 4800 unsigned int i; 4801 4802 (void)ctx; 4803 (void)token; 4804 for (i = 0; next_action[i]; ++i) 4805 if (buf && i == ent) 4806 return snprintf(buf, size, "%s", 4807 token_list[next_action[i]].name); 4808 if (buf) 4809 return -1; 4810 return i; 4811 } 4812 4813 /** Complete available ports. */ 4814 static int 4815 comp_port(struct context *ctx, const struct token *token, 4816 unsigned int ent, char *buf, unsigned int size) 4817 { 4818 unsigned int i = 0; 4819 portid_t p; 4820 4821 (void)ctx; 4822 (void)token; 4823 RTE_ETH_FOREACH_DEV(p) { 4824 if (buf && i == ent) 4825 return snprintf(buf, size, "%u", p); 4826 ++i; 4827 } 4828 if (buf) 4829 return -1; 4830 return i; 4831 } 4832 4833 /** Complete available rule IDs. */ 4834 static int 4835 comp_rule_id(struct context *ctx, const struct token *token, 4836 unsigned int ent, char *buf, unsigned int size) 4837 { 4838 unsigned int i = 0; 4839 struct rte_port *port; 4840 struct port_flow *pf; 4841 4842 (void)token; 4843 if (port_id_is_invalid(ctx->port, DISABLED_WARN) || 4844 ctx->port == (portid_t)RTE_PORT_ALL) 4845 return -1; 4846 port = &ports[ctx->port]; 4847 for (pf = port->flow_list; pf != NULL; pf = pf->next) { 4848 if (buf && i == ent) 4849 return snprintf(buf, size, "%u", pf->id); 4850 ++i; 4851 } 4852 if (buf) 4853 return -1; 4854 return i; 4855 } 4856 4857 /** Complete type field for RSS action. */ 4858 static int 4859 comp_vc_action_rss_type(struct context *ctx, const struct token *token, 4860 unsigned int ent, char *buf, unsigned int size) 4861 { 4862 unsigned int i; 4863 4864 (void)ctx; 4865 (void)token; 4866 for (i = 0; rss_type_table[i].str; ++i) 4867 ; 4868 if (!buf) 4869 return i + 1; 4870 if (ent < i) 4871 return snprintf(buf, size, "%s", rss_type_table[ent].str); 4872 if (ent == i) 4873 return snprintf(buf, size, "end"); 4874 return -1; 4875 } 4876 4877 /** Complete queue field for RSS action. */ 4878 static int 4879 comp_vc_action_rss_queue(struct context *ctx, const struct token *token, 4880 unsigned int ent, char *buf, unsigned int size) 4881 { 4882 (void)ctx; 4883 (void)token; 4884 if (!buf) 4885 return nb_rxq + 1; 4886 if (ent < nb_rxq) 4887 return snprintf(buf, size, "%u", ent); 4888 if (ent == nb_rxq) 4889 return snprintf(buf, size, "end"); 4890 return -1; 4891 } 4892 4893 /** Internal context. */ 4894 static struct context cmd_flow_context; 4895 4896 /** Global parser instance (cmdline API). */ 4897 cmdline_parse_inst_t cmd_flow; 4898 4899 /** Initialize context. */ 4900 static void 4901 cmd_flow_context_init(struct context *ctx) 4902 { 4903 /* A full memset() is not necessary. */ 4904 ctx->curr = ZERO; 4905 ctx->prev = ZERO; 4906 ctx->next_num = 0; 4907 ctx->args_num = 0; 4908 ctx->eol = 0; 4909 ctx->last = 0; 4910 ctx->port = 0; 4911 ctx->objdata = 0; 4912 ctx->object = NULL; 4913 ctx->objmask = NULL; 4914 } 4915 4916 /** Parse a token (cmdline API). */ 4917 static int 4918 cmd_flow_parse(cmdline_parse_token_hdr_t *hdr, const char *src, void *result, 4919 unsigned int size) 4920 { 4921 struct context *ctx = &cmd_flow_context; 4922 const struct token *token; 4923 const enum index *list; 4924 int len; 4925 int i; 4926 4927 (void)hdr; 4928 token = &token_list[ctx->curr]; 4929 /* Check argument length. */ 4930 ctx->eol = 0; 4931 ctx->last = 1; 4932 for (len = 0; src[len]; ++len) 4933 if (src[len] == '#' || isspace(src[len])) 4934 break; 4935 if (!len) 4936 return -1; 4937 /* Last argument and EOL detection. */ 4938 for (i = len; src[i]; ++i) 4939 if (src[i] == '#' || src[i] == '\r' || src[i] == '\n') 4940 break; 4941 else if (!isspace(src[i])) { 4942 ctx->last = 0; 4943 break; 4944 } 4945 for (; src[i]; ++i) 4946 if (src[i] == '\r' || src[i] == '\n') { 4947 ctx->eol = 1; 4948 break; 4949 } 4950 /* Initialize context if necessary. */ 4951 if (!ctx->next_num) { 4952 if (!token->next) 4953 return 0; 4954 ctx->next[ctx->next_num++] = token->next[0]; 4955 } 4956 /* Process argument through candidates. */ 4957 ctx->prev = ctx->curr; 4958 list = ctx->next[ctx->next_num - 1]; 4959 for (i = 0; list[i]; ++i) { 4960 const struct token *next = &token_list[list[i]]; 4961 int tmp; 4962 4963 ctx->curr = list[i]; 4964 if (next->call) 4965 tmp = next->call(ctx, next, src, len, result, size); 4966 else 4967 tmp = parse_default(ctx, next, src, len, result, size); 4968 if (tmp == -1 || tmp != len) 4969 continue; 4970 token = next; 4971 break; 4972 } 4973 if (!list[i]) 4974 return -1; 4975 --ctx->next_num; 4976 /* Push subsequent tokens if any. */ 4977 if (token->next) 4978 for (i = 0; token->next[i]; ++i) { 4979 if (ctx->next_num == RTE_DIM(ctx->next)) 4980 return -1; 4981 ctx->next[ctx->next_num++] = token->next[i]; 4982 } 4983 /* Push arguments if any. */ 4984 if (token->args) 4985 for (i = 0; token->args[i]; ++i) { 4986 if (ctx->args_num == RTE_DIM(ctx->args)) 4987 return -1; 4988 ctx->args[ctx->args_num++] = token->args[i]; 4989 } 4990 return len; 4991 } 4992 4993 /** Return number of completion entries (cmdline API). */ 4994 static int 4995 cmd_flow_complete_get_nb(cmdline_parse_token_hdr_t *hdr) 4996 { 4997 struct context *ctx = &cmd_flow_context; 4998 const struct token *token = &token_list[ctx->curr]; 4999 const enum index *list; 5000 int i; 5001 5002 (void)hdr; 5003 /* Count number of tokens in current list. */ 5004 if (ctx->next_num) 5005 list = ctx->next[ctx->next_num - 1]; 5006 else 5007 list = token->next[0]; 5008 for (i = 0; list[i]; ++i) 5009 ; 5010 if (!i) 5011 return 0; 5012 /* 5013 * If there is a single token, use its completion callback, otherwise 5014 * return the number of entries. 5015 */ 5016 token = &token_list[list[0]]; 5017 if (i == 1 && token->comp) { 5018 /* Save index for cmd_flow_get_help(). */ 5019 ctx->prev = list[0]; 5020 return token->comp(ctx, token, 0, NULL, 0); 5021 } 5022 return i; 5023 } 5024 5025 /** Return a completion entry (cmdline API). */ 5026 static int 5027 cmd_flow_complete_get_elt(cmdline_parse_token_hdr_t *hdr, int index, 5028 char *dst, unsigned int size) 5029 { 5030 struct context *ctx = &cmd_flow_context; 5031 const struct token *token = &token_list[ctx->curr]; 5032 const enum index *list; 5033 int i; 5034 5035 (void)hdr; 5036 /* Count number of tokens in current list. */ 5037 if (ctx->next_num) 5038 list = ctx->next[ctx->next_num - 1]; 5039 else 5040 list = token->next[0]; 5041 for (i = 0; list[i]; ++i) 5042 ; 5043 if (!i) 5044 return -1; 5045 /* If there is a single token, use its completion callback. */ 5046 token = &token_list[list[0]]; 5047 if (i == 1 && token->comp) { 5048 /* Save index for cmd_flow_get_help(). */ 5049 ctx->prev = list[0]; 5050 return token->comp(ctx, token, index, dst, size) < 0 ? -1 : 0; 5051 } 5052 /* Otherwise make sure the index is valid and use defaults. */ 5053 if (index >= i) 5054 return -1; 5055 token = &token_list[list[index]]; 5056 snprintf(dst, size, "%s", token->name); 5057 /* Save index for cmd_flow_get_help(). */ 5058 ctx->prev = list[index]; 5059 return 0; 5060 } 5061 5062 /** Populate help strings for current token (cmdline API). */ 5063 static int 5064 cmd_flow_get_help(cmdline_parse_token_hdr_t *hdr, char *dst, unsigned int size) 5065 { 5066 struct context *ctx = &cmd_flow_context; 5067 const struct token *token = &token_list[ctx->prev]; 5068 5069 (void)hdr; 5070 if (!size) 5071 return -1; 5072 /* Set token type and update global help with details. */ 5073 snprintf(dst, size, "%s", (token->type ? token->type : "TOKEN")); 5074 if (token->help) 5075 cmd_flow.help_str = token->help; 5076 else 5077 cmd_flow.help_str = token->name; 5078 return 0; 5079 } 5080 5081 /** Token definition template (cmdline API). */ 5082 static struct cmdline_token_hdr cmd_flow_token_hdr = { 5083 .ops = &(struct cmdline_token_ops){ 5084 .parse = cmd_flow_parse, 5085 .complete_get_nb = cmd_flow_complete_get_nb, 5086 .complete_get_elt = cmd_flow_complete_get_elt, 5087 .get_help = cmd_flow_get_help, 5088 }, 5089 .offset = 0, 5090 }; 5091 5092 /** Populate the next dynamic token. */ 5093 static void 5094 cmd_flow_tok(cmdline_parse_token_hdr_t **hdr, 5095 cmdline_parse_token_hdr_t **hdr_inst) 5096 { 5097 struct context *ctx = &cmd_flow_context; 5098 5099 /* Always reinitialize context before requesting the first token. */ 5100 if (!(hdr_inst - cmd_flow.tokens)) 5101 cmd_flow_context_init(ctx); 5102 /* Return NULL when no more tokens are expected. */ 5103 if (!ctx->next_num && ctx->curr) { 5104 *hdr = NULL; 5105 return; 5106 } 5107 /* Determine if command should end here. */ 5108 if (ctx->eol && ctx->last && ctx->next_num) { 5109 const enum index *list = ctx->next[ctx->next_num - 1]; 5110 int i; 5111 5112 for (i = 0; list[i]; ++i) { 5113 if (list[i] != END) 5114 continue; 5115 *hdr = NULL; 5116 return; 5117 } 5118 } 5119 *hdr = &cmd_flow_token_hdr; 5120 } 5121 5122 /** Dispatch parsed buffer to function calls. */ 5123 static void 5124 cmd_flow_parsed(const struct buffer *in) 5125 { 5126 switch (in->command) { 5127 case VALIDATE: 5128 port_flow_validate(in->port, &in->args.vc.attr, 5129 in->args.vc.pattern, in->args.vc.actions); 5130 break; 5131 case CREATE: 5132 port_flow_create(in->port, &in->args.vc.attr, 5133 in->args.vc.pattern, in->args.vc.actions); 5134 break; 5135 case DESTROY: 5136 port_flow_destroy(in->port, in->args.destroy.rule_n, 5137 in->args.destroy.rule); 5138 break; 5139 case FLUSH: 5140 port_flow_flush(in->port); 5141 break; 5142 case QUERY: 5143 port_flow_query(in->port, in->args.query.rule, 5144 &in->args.query.action); 5145 break; 5146 case LIST: 5147 port_flow_list(in->port, in->args.list.group_n, 5148 in->args.list.group); 5149 break; 5150 case ISOLATE: 5151 port_flow_isolate(in->port, in->args.isolate.set); 5152 break; 5153 default: 5154 break; 5155 } 5156 } 5157 5158 /** Token generator and output processing callback (cmdline API). */ 5159 static void 5160 cmd_flow_cb(void *arg0, struct cmdline *cl, void *arg2) 5161 { 5162 if (cl == NULL) 5163 cmd_flow_tok(arg0, arg2); 5164 else 5165 cmd_flow_parsed(arg0); 5166 } 5167 5168 /** Global parser instance (cmdline API). */ 5169 cmdline_parse_inst_t cmd_flow = { 5170 .f = cmd_flow_cb, 5171 .data = NULL, /**< Unused. */ 5172 .help_str = NULL, /**< Updated by cmd_flow_get_help(). */ 5173 .tokens = { 5174 NULL, 5175 }, /**< Tokens are returned by cmd_flow_tok(). */ 5176 }; 5177