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