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