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_ethdev.h> 19 #include <rte_byteorder.h> 20 #include <cmdline_parse.h> 21 #include <cmdline_parse_etheraddr.h> 22 #include <cmdline_parse_string.h> 23 #include <cmdline_parse_num.h> 24 #include <rte_flow.h> 25 #include <rte_hexdump.h> 26 27 #include "testpmd.h" 28 29 /** Parser token indices. */ 30 enum index { 31 /* Special tokens. */ 32 ZERO = 0, 33 END, 34 START_SET, 35 END_SET, 36 37 /* Common tokens. */ 38 INTEGER, 39 UNSIGNED, 40 PREFIX, 41 BOOLEAN, 42 STRING, 43 HEX, 44 MAC_ADDR, 45 IPV4_ADDR, 46 IPV6_ADDR, 47 RULE_ID, 48 PORT_ID, 49 GROUP_ID, 50 PRIORITY_LEVEL, 51 52 /* Top-level command. */ 53 SET, 54 /* Sub-leve commands. */ 55 SET_RAW_ENCAP, 56 SET_RAW_DECAP, 57 SET_RAW_INDEX, 58 59 /* Top-level command. */ 60 FLOW, 61 /* Sub-level commands. */ 62 VALIDATE, 63 CREATE, 64 DESTROY, 65 FLUSH, 66 QUERY, 67 LIST, 68 ISOLATE, 69 70 /* Destroy arguments. */ 71 DESTROY_RULE, 72 73 /* Query arguments. */ 74 QUERY_ACTION, 75 76 /* List arguments. */ 77 LIST_GROUP, 78 79 /* Validate/create arguments. */ 80 GROUP, 81 PRIORITY, 82 INGRESS, 83 EGRESS, 84 TRANSFER, 85 86 /* Validate/create pattern. */ 87 PATTERN, 88 ITEM_PARAM_IS, 89 ITEM_PARAM_SPEC, 90 ITEM_PARAM_LAST, 91 ITEM_PARAM_MASK, 92 ITEM_PARAM_PREFIX, 93 ITEM_NEXT, 94 ITEM_END, 95 ITEM_VOID, 96 ITEM_INVERT, 97 ITEM_ANY, 98 ITEM_ANY_NUM, 99 ITEM_PF, 100 ITEM_VF, 101 ITEM_VF_ID, 102 ITEM_PHY_PORT, 103 ITEM_PHY_PORT_INDEX, 104 ITEM_PORT_ID, 105 ITEM_PORT_ID_ID, 106 ITEM_MARK, 107 ITEM_MARK_ID, 108 ITEM_RAW, 109 ITEM_RAW_RELATIVE, 110 ITEM_RAW_SEARCH, 111 ITEM_RAW_OFFSET, 112 ITEM_RAW_LIMIT, 113 ITEM_RAW_PATTERN, 114 ITEM_ETH, 115 ITEM_ETH_DST, 116 ITEM_ETH_SRC, 117 ITEM_ETH_TYPE, 118 ITEM_VLAN, 119 ITEM_VLAN_TCI, 120 ITEM_VLAN_PCP, 121 ITEM_VLAN_DEI, 122 ITEM_VLAN_VID, 123 ITEM_VLAN_INNER_TYPE, 124 ITEM_IPV4, 125 ITEM_IPV4_TOS, 126 ITEM_IPV4_TTL, 127 ITEM_IPV4_PROTO, 128 ITEM_IPV4_SRC, 129 ITEM_IPV4_DST, 130 ITEM_IPV6, 131 ITEM_IPV6_TC, 132 ITEM_IPV6_FLOW, 133 ITEM_IPV6_PROTO, 134 ITEM_IPV6_HOP, 135 ITEM_IPV6_SRC, 136 ITEM_IPV6_DST, 137 ITEM_ICMP, 138 ITEM_ICMP_TYPE, 139 ITEM_ICMP_CODE, 140 ITEM_UDP, 141 ITEM_UDP_SRC, 142 ITEM_UDP_DST, 143 ITEM_TCP, 144 ITEM_TCP_SRC, 145 ITEM_TCP_DST, 146 ITEM_TCP_FLAGS, 147 ITEM_SCTP, 148 ITEM_SCTP_SRC, 149 ITEM_SCTP_DST, 150 ITEM_SCTP_TAG, 151 ITEM_SCTP_CKSUM, 152 ITEM_VXLAN, 153 ITEM_VXLAN_VNI, 154 ITEM_E_TAG, 155 ITEM_E_TAG_GRP_ECID_B, 156 ITEM_NVGRE, 157 ITEM_NVGRE_TNI, 158 ITEM_MPLS, 159 ITEM_MPLS_LABEL, 160 ITEM_MPLS_TC, 161 ITEM_MPLS_S, 162 ITEM_GRE, 163 ITEM_GRE_PROTO, 164 ITEM_GRE_C_RSVD0_VER, 165 ITEM_GRE_C_BIT, 166 ITEM_GRE_K_BIT, 167 ITEM_GRE_S_BIT, 168 ITEM_FUZZY, 169 ITEM_FUZZY_THRESH, 170 ITEM_GTP, 171 ITEM_GTP_TEID, 172 ITEM_GTPC, 173 ITEM_GTPU, 174 ITEM_GENEVE, 175 ITEM_GENEVE_VNI, 176 ITEM_GENEVE_PROTO, 177 ITEM_VXLAN_GPE, 178 ITEM_VXLAN_GPE_VNI, 179 ITEM_ARP_ETH_IPV4, 180 ITEM_ARP_ETH_IPV4_SHA, 181 ITEM_ARP_ETH_IPV4_SPA, 182 ITEM_ARP_ETH_IPV4_THA, 183 ITEM_ARP_ETH_IPV4_TPA, 184 ITEM_IPV6_EXT, 185 ITEM_IPV6_EXT_NEXT_HDR, 186 ITEM_ICMP6, 187 ITEM_ICMP6_TYPE, 188 ITEM_ICMP6_CODE, 189 ITEM_ICMP6_ND_NS, 190 ITEM_ICMP6_ND_NS_TARGET_ADDR, 191 ITEM_ICMP6_ND_NA, 192 ITEM_ICMP6_ND_NA_TARGET_ADDR, 193 ITEM_ICMP6_ND_OPT, 194 ITEM_ICMP6_ND_OPT_TYPE, 195 ITEM_ICMP6_ND_OPT_SLA_ETH, 196 ITEM_ICMP6_ND_OPT_SLA_ETH_SLA, 197 ITEM_ICMP6_ND_OPT_TLA_ETH, 198 ITEM_ICMP6_ND_OPT_TLA_ETH_TLA, 199 ITEM_META, 200 ITEM_META_DATA, 201 ITEM_GRE_KEY, 202 ITEM_GRE_KEY_VALUE, 203 ITEM_GTP_PSC, 204 ITEM_GTP_PSC_QFI, 205 ITEM_GTP_PSC_PDU_T, 206 ITEM_PPPOES, 207 ITEM_PPPOED, 208 ITEM_PPPOE_SEID, 209 ITEM_PPPOE_PROTO_ID, 210 ITEM_HIGIG2, 211 ITEM_HIGIG2_CLASSIFICATION, 212 ITEM_HIGIG2_VID, 213 ITEM_TAG, 214 ITEM_TAG_DATA, 215 ITEM_TAG_INDEX, 216 217 /* Validate/create actions. */ 218 ACTIONS, 219 ACTION_NEXT, 220 ACTION_END, 221 ACTION_VOID, 222 ACTION_PASSTHRU, 223 ACTION_JUMP, 224 ACTION_JUMP_GROUP, 225 ACTION_MARK, 226 ACTION_MARK_ID, 227 ACTION_FLAG, 228 ACTION_QUEUE, 229 ACTION_QUEUE_INDEX, 230 ACTION_DROP, 231 ACTION_COUNT, 232 ACTION_COUNT_SHARED, 233 ACTION_COUNT_ID, 234 ACTION_RSS, 235 ACTION_RSS_FUNC, 236 ACTION_RSS_LEVEL, 237 ACTION_RSS_FUNC_DEFAULT, 238 ACTION_RSS_FUNC_TOEPLITZ, 239 ACTION_RSS_FUNC_SIMPLE_XOR, 240 ACTION_RSS_FUNC_SYMMETRIC_TOEPLITZ, 241 ACTION_RSS_TYPES, 242 ACTION_RSS_TYPE, 243 ACTION_RSS_KEY, 244 ACTION_RSS_KEY_LEN, 245 ACTION_RSS_QUEUES, 246 ACTION_RSS_QUEUE, 247 ACTION_PF, 248 ACTION_VF, 249 ACTION_VF_ORIGINAL, 250 ACTION_VF_ID, 251 ACTION_PHY_PORT, 252 ACTION_PHY_PORT_ORIGINAL, 253 ACTION_PHY_PORT_INDEX, 254 ACTION_PORT_ID, 255 ACTION_PORT_ID_ORIGINAL, 256 ACTION_PORT_ID_ID, 257 ACTION_METER, 258 ACTION_METER_ID, 259 ACTION_OF_SET_MPLS_TTL, 260 ACTION_OF_SET_MPLS_TTL_MPLS_TTL, 261 ACTION_OF_DEC_MPLS_TTL, 262 ACTION_OF_SET_NW_TTL, 263 ACTION_OF_SET_NW_TTL_NW_TTL, 264 ACTION_OF_DEC_NW_TTL, 265 ACTION_OF_COPY_TTL_OUT, 266 ACTION_OF_COPY_TTL_IN, 267 ACTION_OF_POP_VLAN, 268 ACTION_OF_PUSH_VLAN, 269 ACTION_OF_PUSH_VLAN_ETHERTYPE, 270 ACTION_OF_SET_VLAN_VID, 271 ACTION_OF_SET_VLAN_VID_VLAN_VID, 272 ACTION_OF_SET_VLAN_PCP, 273 ACTION_OF_SET_VLAN_PCP_VLAN_PCP, 274 ACTION_OF_POP_MPLS, 275 ACTION_OF_POP_MPLS_ETHERTYPE, 276 ACTION_OF_PUSH_MPLS, 277 ACTION_OF_PUSH_MPLS_ETHERTYPE, 278 ACTION_VXLAN_ENCAP, 279 ACTION_VXLAN_DECAP, 280 ACTION_NVGRE_ENCAP, 281 ACTION_NVGRE_DECAP, 282 ACTION_L2_ENCAP, 283 ACTION_L2_DECAP, 284 ACTION_MPLSOGRE_ENCAP, 285 ACTION_MPLSOGRE_DECAP, 286 ACTION_MPLSOUDP_ENCAP, 287 ACTION_MPLSOUDP_DECAP, 288 ACTION_SET_IPV4_SRC, 289 ACTION_SET_IPV4_SRC_IPV4_SRC, 290 ACTION_SET_IPV4_DST, 291 ACTION_SET_IPV4_DST_IPV4_DST, 292 ACTION_SET_IPV6_SRC, 293 ACTION_SET_IPV6_SRC_IPV6_SRC, 294 ACTION_SET_IPV6_DST, 295 ACTION_SET_IPV6_DST_IPV6_DST, 296 ACTION_SET_TP_SRC, 297 ACTION_SET_TP_SRC_TP_SRC, 298 ACTION_SET_TP_DST, 299 ACTION_SET_TP_DST_TP_DST, 300 ACTION_MAC_SWAP, 301 ACTION_DEC_TTL, 302 ACTION_SET_TTL, 303 ACTION_SET_TTL_TTL, 304 ACTION_SET_MAC_SRC, 305 ACTION_SET_MAC_SRC_MAC_SRC, 306 ACTION_SET_MAC_DST, 307 ACTION_SET_MAC_DST_MAC_DST, 308 ACTION_INC_TCP_SEQ, 309 ACTION_INC_TCP_SEQ_VALUE, 310 ACTION_DEC_TCP_SEQ, 311 ACTION_DEC_TCP_SEQ_VALUE, 312 ACTION_INC_TCP_ACK, 313 ACTION_INC_TCP_ACK_VALUE, 314 ACTION_DEC_TCP_ACK, 315 ACTION_DEC_TCP_ACK_VALUE, 316 ACTION_RAW_ENCAP, 317 ACTION_RAW_DECAP, 318 ACTION_RAW_ENCAP_INDEX, 319 ACTION_RAW_ENCAP_INDEX_VALUE, 320 ACTION_RAW_DECAP_INDEX, 321 ACTION_RAW_DECAP_INDEX_VALUE, 322 ACTION_SET_TAG, 323 ACTION_SET_TAG_DATA, 324 ACTION_SET_TAG_INDEX, 325 ACTION_SET_TAG_MASK, 326 ACTION_SET_META, 327 ACTION_SET_META_DATA, 328 ACTION_SET_META_MASK, 329 }; 330 331 /** Maximum size for pattern in struct rte_flow_item_raw. */ 332 #define ITEM_RAW_PATTERN_SIZE 40 333 334 /** Storage size for struct rte_flow_item_raw including pattern. */ 335 #define ITEM_RAW_SIZE \ 336 (sizeof(struct rte_flow_item_raw) + ITEM_RAW_PATTERN_SIZE) 337 338 /** Maximum number of queue indices in struct rte_flow_action_rss. */ 339 #define ACTION_RSS_QUEUE_NUM 128 340 341 /** Storage for struct rte_flow_action_rss including external data. */ 342 struct action_rss_data { 343 struct rte_flow_action_rss conf; 344 uint8_t key[RSS_HASH_KEY_LENGTH]; 345 uint16_t queue[ACTION_RSS_QUEUE_NUM]; 346 }; 347 348 /** Maximum data size in struct rte_flow_action_raw_encap. */ 349 #define ACTION_RAW_ENCAP_MAX_DATA 128 350 #define RAW_ENCAP_CONFS_MAX_NUM 8 351 352 /** Storage for struct rte_flow_action_raw_encap. */ 353 struct raw_encap_conf { 354 uint8_t data[ACTION_RAW_ENCAP_MAX_DATA]; 355 uint8_t preserve[ACTION_RAW_ENCAP_MAX_DATA]; 356 size_t size; 357 }; 358 359 struct raw_encap_conf raw_encap_confs[RAW_ENCAP_CONFS_MAX_NUM]; 360 361 /** Storage for struct rte_flow_action_raw_encap including external data. */ 362 struct action_raw_encap_data { 363 struct rte_flow_action_raw_encap conf; 364 uint8_t data[ACTION_RAW_ENCAP_MAX_DATA]; 365 uint8_t preserve[ACTION_RAW_ENCAP_MAX_DATA]; 366 uint16_t idx; 367 }; 368 369 /** Storage for struct rte_flow_action_raw_decap. */ 370 struct raw_decap_conf { 371 uint8_t data[ACTION_RAW_ENCAP_MAX_DATA]; 372 size_t size; 373 }; 374 375 struct raw_decap_conf raw_decap_confs[RAW_ENCAP_CONFS_MAX_NUM]; 376 377 /** Storage for struct rte_flow_action_raw_decap including external data. */ 378 struct action_raw_decap_data { 379 struct rte_flow_action_raw_decap conf; 380 uint8_t data[ACTION_RAW_ENCAP_MAX_DATA]; 381 uint16_t idx; 382 }; 383 384 struct vxlan_encap_conf vxlan_encap_conf = { 385 .select_ipv4 = 1, 386 .select_vlan = 0, 387 .select_tos_ttl = 0, 388 .vni = "\x00\x00\x00", 389 .udp_src = 0, 390 .udp_dst = RTE_BE16(4789), 391 .ipv4_src = RTE_IPV4(127, 0, 0, 1), 392 .ipv4_dst = RTE_IPV4(255, 255, 255, 255), 393 .ipv6_src = "\x00\x00\x00\x00\x00\x00\x00\x00" 394 "\x00\x00\x00\x00\x00\x00\x00\x01", 395 .ipv6_dst = "\x00\x00\x00\x00\x00\x00\x00\x00" 396 "\x00\x00\x00\x00\x00\x00\x11\x11", 397 .vlan_tci = 0, 398 .ip_tos = 0, 399 .ip_ttl = 255, 400 .eth_src = "\x00\x00\x00\x00\x00\x00", 401 .eth_dst = "\xff\xff\xff\xff\xff\xff", 402 }; 403 404 /** Maximum number of items in struct rte_flow_action_vxlan_encap. */ 405 #define ACTION_VXLAN_ENCAP_ITEMS_NUM 6 406 407 /** Storage for struct rte_flow_action_vxlan_encap including external data. */ 408 struct action_vxlan_encap_data { 409 struct rte_flow_action_vxlan_encap conf; 410 struct rte_flow_item items[ACTION_VXLAN_ENCAP_ITEMS_NUM]; 411 struct rte_flow_item_eth item_eth; 412 struct rte_flow_item_vlan item_vlan; 413 union { 414 struct rte_flow_item_ipv4 item_ipv4; 415 struct rte_flow_item_ipv6 item_ipv6; 416 }; 417 struct rte_flow_item_udp item_udp; 418 struct rte_flow_item_vxlan item_vxlan; 419 }; 420 421 struct nvgre_encap_conf nvgre_encap_conf = { 422 .select_ipv4 = 1, 423 .select_vlan = 0, 424 .tni = "\x00\x00\x00", 425 .ipv4_src = RTE_IPV4(127, 0, 0, 1), 426 .ipv4_dst = RTE_IPV4(255, 255, 255, 255), 427 .ipv6_src = "\x00\x00\x00\x00\x00\x00\x00\x00" 428 "\x00\x00\x00\x00\x00\x00\x00\x01", 429 .ipv6_dst = "\x00\x00\x00\x00\x00\x00\x00\x00" 430 "\x00\x00\x00\x00\x00\x00\x11\x11", 431 .vlan_tci = 0, 432 .eth_src = "\x00\x00\x00\x00\x00\x00", 433 .eth_dst = "\xff\xff\xff\xff\xff\xff", 434 }; 435 436 /** Maximum number of items in struct rte_flow_action_nvgre_encap. */ 437 #define ACTION_NVGRE_ENCAP_ITEMS_NUM 5 438 439 /** Storage for struct rte_flow_action_nvgre_encap including external data. */ 440 struct action_nvgre_encap_data { 441 struct rte_flow_action_nvgre_encap conf; 442 struct rte_flow_item items[ACTION_NVGRE_ENCAP_ITEMS_NUM]; 443 struct rte_flow_item_eth item_eth; 444 struct rte_flow_item_vlan item_vlan; 445 union { 446 struct rte_flow_item_ipv4 item_ipv4; 447 struct rte_flow_item_ipv6 item_ipv6; 448 }; 449 struct rte_flow_item_nvgre item_nvgre; 450 }; 451 452 struct l2_encap_conf l2_encap_conf; 453 454 struct l2_decap_conf l2_decap_conf; 455 456 struct mplsogre_encap_conf mplsogre_encap_conf; 457 458 struct mplsogre_decap_conf mplsogre_decap_conf; 459 460 struct mplsoudp_encap_conf mplsoudp_encap_conf; 461 462 struct mplsoudp_decap_conf mplsoudp_decap_conf; 463 464 /** Maximum number of subsequent tokens and arguments on the stack. */ 465 #define CTX_STACK_SIZE 16 466 467 /** Parser context. */ 468 struct context { 469 /** Stack of subsequent token lists to process. */ 470 const enum index *next[CTX_STACK_SIZE]; 471 /** Arguments for stacked tokens. */ 472 const void *args[CTX_STACK_SIZE]; 473 enum index curr; /**< Current token index. */ 474 enum index prev; /**< Index of the last token seen. */ 475 int next_num; /**< Number of entries in next[]. */ 476 int args_num; /**< Number of entries in args[]. */ 477 uint32_t eol:1; /**< EOL has been detected. */ 478 uint32_t last:1; /**< No more arguments. */ 479 portid_t port; /**< Current port ID (for completions). */ 480 uint32_t objdata; /**< Object-specific data. */ 481 void *object; /**< Address of current object for relative offsets. */ 482 void *objmask; /**< Object a full mask must be written to. */ 483 }; 484 485 /** Token argument. */ 486 struct arg { 487 uint32_t hton:1; /**< Use network byte ordering. */ 488 uint32_t sign:1; /**< Value is signed. */ 489 uint32_t bounded:1; /**< Value is bounded. */ 490 uintmax_t min; /**< Minimum value if bounded. */ 491 uintmax_t max; /**< Maximum value if bounded. */ 492 uint32_t offset; /**< Relative offset from ctx->object. */ 493 uint32_t size; /**< Field size. */ 494 const uint8_t *mask; /**< Bit-mask to use instead of offset/size. */ 495 }; 496 497 /** Parser token definition. */ 498 struct token { 499 /** Type displayed during completion (defaults to "TOKEN"). */ 500 const char *type; 501 /** Help displayed during completion (defaults to token name). */ 502 const char *help; 503 /** Private data used by parser functions. */ 504 const void *priv; 505 /** 506 * Lists of subsequent tokens to push on the stack. Each call to the 507 * parser consumes the last entry of that stack. 508 */ 509 const enum index *const *next; 510 /** Arguments stack for subsequent tokens that need them. */ 511 const struct arg *const *args; 512 /** 513 * Token-processing callback, returns -1 in case of error, the 514 * length of the matched string otherwise. If NULL, attempts to 515 * match the token name. 516 * 517 * If buf is not NULL, the result should be stored in it according 518 * to context. An error is returned if not large enough. 519 */ 520 int (*call)(struct context *ctx, const struct token *token, 521 const char *str, unsigned int len, 522 void *buf, unsigned int size); 523 /** 524 * Callback that provides possible values for this token, used for 525 * completion. Returns -1 in case of error, the number of possible 526 * values otherwise. If NULL, the token name is used. 527 * 528 * If buf is not NULL, entry index ent is written to buf and the 529 * full length of the entry is returned (same behavior as 530 * snprintf()). 531 */ 532 int (*comp)(struct context *ctx, const struct token *token, 533 unsigned int ent, char *buf, unsigned int size); 534 /** Mandatory token name, no default value. */ 535 const char *name; 536 }; 537 538 /** Static initializer for the next field. */ 539 #define NEXT(...) (const enum index *const []){ __VA_ARGS__, NULL, } 540 541 /** Static initializer for a NEXT() entry. */ 542 #define NEXT_ENTRY(...) (const enum index []){ __VA_ARGS__, ZERO, } 543 544 /** Static initializer for the args field. */ 545 #define ARGS(...) (const struct arg *const []){ __VA_ARGS__, NULL, } 546 547 /** Static initializer for ARGS() to target a field. */ 548 #define ARGS_ENTRY(s, f) \ 549 (&(const struct arg){ \ 550 .offset = offsetof(s, f), \ 551 .size = sizeof(((s *)0)->f), \ 552 }) 553 554 /** Static initializer for ARGS() to target a bit-field. */ 555 #define ARGS_ENTRY_BF(s, f, b) \ 556 (&(const struct arg){ \ 557 .size = sizeof(s), \ 558 .mask = (const void *)&(const s){ .f = (1 << (b)) - 1 }, \ 559 }) 560 561 /** Static initializer for ARGS() to target an arbitrary bit-mask. */ 562 #define ARGS_ENTRY_MASK(s, f, m) \ 563 (&(const struct arg){ \ 564 .offset = offsetof(s, f), \ 565 .size = sizeof(((s *)0)->f), \ 566 .mask = (const void *)(m), \ 567 }) 568 569 /** Same as ARGS_ENTRY_MASK() using network byte ordering for the value. */ 570 #define ARGS_ENTRY_MASK_HTON(s, f, m) \ 571 (&(const struct arg){ \ 572 .hton = 1, \ 573 .offset = offsetof(s, f), \ 574 .size = sizeof(((s *)0)->f), \ 575 .mask = (const void *)(m), \ 576 }) 577 578 /** Static initializer for ARGS() to target a pointer. */ 579 #define ARGS_ENTRY_PTR(s, f) \ 580 (&(const struct arg){ \ 581 .size = sizeof(*((s *)0)->f), \ 582 }) 583 584 /** Static initializer for ARGS() with arbitrary offset and size. */ 585 #define ARGS_ENTRY_ARB(o, s) \ 586 (&(const struct arg){ \ 587 .offset = (o), \ 588 .size = (s), \ 589 }) 590 591 /** Same as ARGS_ENTRY_ARB() with bounded values. */ 592 #define ARGS_ENTRY_ARB_BOUNDED(o, s, i, a) \ 593 (&(const struct arg){ \ 594 .bounded = 1, \ 595 .min = (i), \ 596 .max = (a), \ 597 .offset = (o), \ 598 .size = (s), \ 599 }) 600 601 /** Same as ARGS_ENTRY() using network byte ordering. */ 602 #define ARGS_ENTRY_HTON(s, f) \ 603 (&(const struct arg){ \ 604 .hton = 1, \ 605 .offset = offsetof(s, f), \ 606 .size = sizeof(((s *)0)->f), \ 607 }) 608 609 /** Same as ARGS_ENTRY_HTON() for a single argument, without structure. */ 610 #define ARG_ENTRY_HTON(s) \ 611 (&(const struct arg){ \ 612 .hton = 1, \ 613 .offset = 0, \ 614 .size = sizeof(s), \ 615 }) 616 617 /** Parser output buffer layout expected by cmd_flow_parsed(). */ 618 struct buffer { 619 enum index command; /**< Flow command. */ 620 portid_t port; /**< Affected port ID. */ 621 union { 622 struct { 623 struct rte_flow_attr attr; 624 struct rte_flow_item *pattern; 625 struct rte_flow_action *actions; 626 uint32_t pattern_n; 627 uint32_t actions_n; 628 uint8_t *data; 629 } vc; /**< Validate/create arguments. */ 630 struct { 631 uint32_t *rule; 632 uint32_t rule_n; 633 } destroy; /**< Destroy arguments. */ 634 struct { 635 uint32_t rule; 636 struct rte_flow_action action; 637 } query; /**< Query arguments. */ 638 struct { 639 uint32_t *group; 640 uint32_t group_n; 641 } list; /**< List arguments. */ 642 struct { 643 int set; 644 } isolate; /**< Isolated mode arguments. */ 645 } args; /**< Command arguments. */ 646 }; 647 648 /** Private data for pattern items. */ 649 struct parse_item_priv { 650 enum rte_flow_item_type type; /**< Item type. */ 651 uint32_t size; /**< Size of item specification structure. */ 652 }; 653 654 #define PRIV_ITEM(t, s) \ 655 (&(const struct parse_item_priv){ \ 656 .type = RTE_FLOW_ITEM_TYPE_ ## t, \ 657 .size = s, \ 658 }) 659 660 /** Private data for actions. */ 661 struct parse_action_priv { 662 enum rte_flow_action_type type; /**< Action type. */ 663 uint32_t size; /**< Size of action configuration structure. */ 664 }; 665 666 #define PRIV_ACTION(t, s) \ 667 (&(const struct parse_action_priv){ \ 668 .type = RTE_FLOW_ACTION_TYPE_ ## t, \ 669 .size = s, \ 670 }) 671 672 static const enum index next_vc_attr[] = { 673 GROUP, 674 PRIORITY, 675 INGRESS, 676 EGRESS, 677 TRANSFER, 678 PATTERN, 679 ZERO, 680 }; 681 682 static const enum index next_destroy_attr[] = { 683 DESTROY_RULE, 684 END, 685 ZERO, 686 }; 687 688 static const enum index next_list_attr[] = { 689 LIST_GROUP, 690 END, 691 ZERO, 692 }; 693 694 static const enum index item_param[] = { 695 ITEM_PARAM_IS, 696 ITEM_PARAM_SPEC, 697 ITEM_PARAM_LAST, 698 ITEM_PARAM_MASK, 699 ITEM_PARAM_PREFIX, 700 ZERO, 701 }; 702 703 static const enum index next_item[] = { 704 ITEM_END, 705 ITEM_VOID, 706 ITEM_INVERT, 707 ITEM_ANY, 708 ITEM_PF, 709 ITEM_VF, 710 ITEM_PHY_PORT, 711 ITEM_PORT_ID, 712 ITEM_MARK, 713 ITEM_RAW, 714 ITEM_ETH, 715 ITEM_VLAN, 716 ITEM_IPV4, 717 ITEM_IPV6, 718 ITEM_ICMP, 719 ITEM_UDP, 720 ITEM_TCP, 721 ITEM_SCTP, 722 ITEM_VXLAN, 723 ITEM_E_TAG, 724 ITEM_NVGRE, 725 ITEM_MPLS, 726 ITEM_GRE, 727 ITEM_FUZZY, 728 ITEM_GTP, 729 ITEM_GTPC, 730 ITEM_GTPU, 731 ITEM_GENEVE, 732 ITEM_VXLAN_GPE, 733 ITEM_ARP_ETH_IPV4, 734 ITEM_IPV6_EXT, 735 ITEM_ICMP6, 736 ITEM_ICMP6_ND_NS, 737 ITEM_ICMP6_ND_NA, 738 ITEM_ICMP6_ND_OPT, 739 ITEM_ICMP6_ND_OPT_SLA_ETH, 740 ITEM_ICMP6_ND_OPT_TLA_ETH, 741 ITEM_META, 742 ITEM_GRE_KEY, 743 ITEM_GTP_PSC, 744 ITEM_PPPOES, 745 ITEM_PPPOED, 746 ITEM_PPPOE_PROTO_ID, 747 ITEM_HIGIG2, 748 ITEM_TAG, 749 END_SET, 750 ZERO, 751 }; 752 753 static const enum index item_fuzzy[] = { 754 ITEM_FUZZY_THRESH, 755 ITEM_NEXT, 756 ZERO, 757 }; 758 759 static const enum index item_any[] = { 760 ITEM_ANY_NUM, 761 ITEM_NEXT, 762 ZERO, 763 }; 764 765 static const enum index item_vf[] = { 766 ITEM_VF_ID, 767 ITEM_NEXT, 768 ZERO, 769 }; 770 771 static const enum index item_phy_port[] = { 772 ITEM_PHY_PORT_INDEX, 773 ITEM_NEXT, 774 ZERO, 775 }; 776 777 static const enum index item_port_id[] = { 778 ITEM_PORT_ID_ID, 779 ITEM_NEXT, 780 ZERO, 781 }; 782 783 static const enum index item_mark[] = { 784 ITEM_MARK_ID, 785 ITEM_NEXT, 786 ZERO, 787 }; 788 789 static const enum index item_raw[] = { 790 ITEM_RAW_RELATIVE, 791 ITEM_RAW_SEARCH, 792 ITEM_RAW_OFFSET, 793 ITEM_RAW_LIMIT, 794 ITEM_RAW_PATTERN, 795 ITEM_NEXT, 796 ZERO, 797 }; 798 799 static const enum index item_eth[] = { 800 ITEM_ETH_DST, 801 ITEM_ETH_SRC, 802 ITEM_ETH_TYPE, 803 ITEM_NEXT, 804 ZERO, 805 }; 806 807 static const enum index item_vlan[] = { 808 ITEM_VLAN_TCI, 809 ITEM_VLAN_PCP, 810 ITEM_VLAN_DEI, 811 ITEM_VLAN_VID, 812 ITEM_VLAN_INNER_TYPE, 813 ITEM_NEXT, 814 ZERO, 815 }; 816 817 static const enum index item_ipv4[] = { 818 ITEM_IPV4_TOS, 819 ITEM_IPV4_TTL, 820 ITEM_IPV4_PROTO, 821 ITEM_IPV4_SRC, 822 ITEM_IPV4_DST, 823 ITEM_NEXT, 824 ZERO, 825 }; 826 827 static const enum index item_ipv6[] = { 828 ITEM_IPV6_TC, 829 ITEM_IPV6_FLOW, 830 ITEM_IPV6_PROTO, 831 ITEM_IPV6_HOP, 832 ITEM_IPV6_SRC, 833 ITEM_IPV6_DST, 834 ITEM_NEXT, 835 ZERO, 836 }; 837 838 static const enum index item_icmp[] = { 839 ITEM_ICMP_TYPE, 840 ITEM_ICMP_CODE, 841 ITEM_NEXT, 842 ZERO, 843 }; 844 845 static const enum index item_udp[] = { 846 ITEM_UDP_SRC, 847 ITEM_UDP_DST, 848 ITEM_NEXT, 849 ZERO, 850 }; 851 852 static const enum index item_tcp[] = { 853 ITEM_TCP_SRC, 854 ITEM_TCP_DST, 855 ITEM_TCP_FLAGS, 856 ITEM_NEXT, 857 ZERO, 858 }; 859 860 static const enum index item_sctp[] = { 861 ITEM_SCTP_SRC, 862 ITEM_SCTP_DST, 863 ITEM_SCTP_TAG, 864 ITEM_SCTP_CKSUM, 865 ITEM_NEXT, 866 ZERO, 867 }; 868 869 static const enum index item_vxlan[] = { 870 ITEM_VXLAN_VNI, 871 ITEM_NEXT, 872 ZERO, 873 }; 874 875 static const enum index item_e_tag[] = { 876 ITEM_E_TAG_GRP_ECID_B, 877 ITEM_NEXT, 878 ZERO, 879 }; 880 881 static const enum index item_nvgre[] = { 882 ITEM_NVGRE_TNI, 883 ITEM_NEXT, 884 ZERO, 885 }; 886 887 static const enum index item_mpls[] = { 888 ITEM_MPLS_LABEL, 889 ITEM_MPLS_TC, 890 ITEM_MPLS_S, 891 ITEM_NEXT, 892 ZERO, 893 }; 894 895 static const enum index item_gre[] = { 896 ITEM_GRE_PROTO, 897 ITEM_GRE_C_RSVD0_VER, 898 ITEM_GRE_C_BIT, 899 ITEM_GRE_K_BIT, 900 ITEM_GRE_S_BIT, 901 ITEM_NEXT, 902 ZERO, 903 }; 904 905 static const enum index item_gre_key[] = { 906 ITEM_GRE_KEY_VALUE, 907 ITEM_NEXT, 908 ZERO, 909 }; 910 911 static const enum index item_gtp[] = { 912 ITEM_GTP_TEID, 913 ITEM_NEXT, 914 ZERO, 915 }; 916 917 static const enum index item_geneve[] = { 918 ITEM_GENEVE_VNI, 919 ITEM_GENEVE_PROTO, 920 ITEM_NEXT, 921 ZERO, 922 }; 923 924 static const enum index item_vxlan_gpe[] = { 925 ITEM_VXLAN_GPE_VNI, 926 ITEM_NEXT, 927 ZERO, 928 }; 929 930 static const enum index item_arp_eth_ipv4[] = { 931 ITEM_ARP_ETH_IPV4_SHA, 932 ITEM_ARP_ETH_IPV4_SPA, 933 ITEM_ARP_ETH_IPV4_THA, 934 ITEM_ARP_ETH_IPV4_TPA, 935 ITEM_NEXT, 936 ZERO, 937 }; 938 939 static const enum index item_ipv6_ext[] = { 940 ITEM_IPV6_EXT_NEXT_HDR, 941 ITEM_NEXT, 942 ZERO, 943 }; 944 945 static const enum index item_icmp6[] = { 946 ITEM_ICMP6_TYPE, 947 ITEM_ICMP6_CODE, 948 ITEM_NEXT, 949 ZERO, 950 }; 951 952 static const enum index item_icmp6_nd_ns[] = { 953 ITEM_ICMP6_ND_NS_TARGET_ADDR, 954 ITEM_NEXT, 955 ZERO, 956 }; 957 958 static const enum index item_icmp6_nd_na[] = { 959 ITEM_ICMP6_ND_NA_TARGET_ADDR, 960 ITEM_NEXT, 961 ZERO, 962 }; 963 964 static const enum index item_icmp6_nd_opt[] = { 965 ITEM_ICMP6_ND_OPT_TYPE, 966 ITEM_NEXT, 967 ZERO, 968 }; 969 970 static const enum index item_icmp6_nd_opt_sla_eth[] = { 971 ITEM_ICMP6_ND_OPT_SLA_ETH_SLA, 972 ITEM_NEXT, 973 ZERO, 974 }; 975 976 static const enum index item_icmp6_nd_opt_tla_eth[] = { 977 ITEM_ICMP6_ND_OPT_TLA_ETH_TLA, 978 ITEM_NEXT, 979 ZERO, 980 }; 981 982 static const enum index item_meta[] = { 983 ITEM_META_DATA, 984 ITEM_NEXT, 985 ZERO, 986 }; 987 988 static const enum index item_gtp_psc[] = { 989 ITEM_GTP_PSC_QFI, 990 ITEM_GTP_PSC_PDU_T, 991 ITEM_NEXT, 992 ZERO, 993 }; 994 995 static const enum index item_pppoed[] = { 996 ITEM_PPPOE_SEID, 997 ITEM_NEXT, 998 ZERO, 999 }; 1000 1001 static const enum index item_pppoes[] = { 1002 ITEM_PPPOE_SEID, 1003 ITEM_NEXT, 1004 ZERO, 1005 }; 1006 1007 static const enum index item_pppoe_proto_id[] = { 1008 ITEM_PPPOE_PROTO_ID, 1009 ITEM_NEXT, 1010 ZERO, 1011 }; 1012 1013 static const enum index item_higig2[] = { 1014 ITEM_HIGIG2_CLASSIFICATION, 1015 ITEM_HIGIG2_VID, 1016 ITEM_NEXT, 1017 ZERO, 1018 }; 1019 1020 static const enum index next_set_raw[] = { 1021 SET_RAW_INDEX, 1022 ITEM_ETH, 1023 ZERO, 1024 }; 1025 1026 static const enum index item_tag[] = { 1027 ITEM_TAG_DATA, 1028 ITEM_TAG_INDEX, 1029 ITEM_NEXT, 1030 ZERO, 1031 }; 1032 1033 static const enum index next_action[] = { 1034 ACTION_END, 1035 ACTION_VOID, 1036 ACTION_PASSTHRU, 1037 ACTION_JUMP, 1038 ACTION_MARK, 1039 ACTION_FLAG, 1040 ACTION_QUEUE, 1041 ACTION_DROP, 1042 ACTION_COUNT, 1043 ACTION_RSS, 1044 ACTION_PF, 1045 ACTION_VF, 1046 ACTION_PHY_PORT, 1047 ACTION_PORT_ID, 1048 ACTION_METER, 1049 ACTION_OF_SET_MPLS_TTL, 1050 ACTION_OF_DEC_MPLS_TTL, 1051 ACTION_OF_SET_NW_TTL, 1052 ACTION_OF_DEC_NW_TTL, 1053 ACTION_OF_COPY_TTL_OUT, 1054 ACTION_OF_COPY_TTL_IN, 1055 ACTION_OF_POP_VLAN, 1056 ACTION_OF_PUSH_VLAN, 1057 ACTION_OF_SET_VLAN_VID, 1058 ACTION_OF_SET_VLAN_PCP, 1059 ACTION_OF_POP_MPLS, 1060 ACTION_OF_PUSH_MPLS, 1061 ACTION_VXLAN_ENCAP, 1062 ACTION_VXLAN_DECAP, 1063 ACTION_NVGRE_ENCAP, 1064 ACTION_NVGRE_DECAP, 1065 ACTION_L2_ENCAP, 1066 ACTION_L2_DECAP, 1067 ACTION_MPLSOGRE_ENCAP, 1068 ACTION_MPLSOGRE_DECAP, 1069 ACTION_MPLSOUDP_ENCAP, 1070 ACTION_MPLSOUDP_DECAP, 1071 ACTION_SET_IPV4_SRC, 1072 ACTION_SET_IPV4_DST, 1073 ACTION_SET_IPV6_SRC, 1074 ACTION_SET_IPV6_DST, 1075 ACTION_SET_TP_SRC, 1076 ACTION_SET_TP_DST, 1077 ACTION_MAC_SWAP, 1078 ACTION_DEC_TTL, 1079 ACTION_SET_TTL, 1080 ACTION_SET_MAC_SRC, 1081 ACTION_SET_MAC_DST, 1082 ACTION_INC_TCP_SEQ, 1083 ACTION_DEC_TCP_SEQ, 1084 ACTION_INC_TCP_ACK, 1085 ACTION_DEC_TCP_ACK, 1086 ACTION_RAW_ENCAP, 1087 ACTION_RAW_DECAP, 1088 ACTION_SET_TAG, 1089 ACTION_SET_META, 1090 ZERO, 1091 }; 1092 1093 static const enum index action_mark[] = { 1094 ACTION_MARK_ID, 1095 ACTION_NEXT, 1096 ZERO, 1097 }; 1098 1099 static const enum index action_queue[] = { 1100 ACTION_QUEUE_INDEX, 1101 ACTION_NEXT, 1102 ZERO, 1103 }; 1104 1105 static const enum index action_count[] = { 1106 ACTION_COUNT_ID, 1107 ACTION_COUNT_SHARED, 1108 ACTION_NEXT, 1109 ZERO, 1110 }; 1111 1112 static const enum index action_rss[] = { 1113 ACTION_RSS_FUNC, 1114 ACTION_RSS_LEVEL, 1115 ACTION_RSS_TYPES, 1116 ACTION_RSS_KEY, 1117 ACTION_RSS_KEY_LEN, 1118 ACTION_RSS_QUEUES, 1119 ACTION_NEXT, 1120 ZERO, 1121 }; 1122 1123 static const enum index action_vf[] = { 1124 ACTION_VF_ORIGINAL, 1125 ACTION_VF_ID, 1126 ACTION_NEXT, 1127 ZERO, 1128 }; 1129 1130 static const enum index action_phy_port[] = { 1131 ACTION_PHY_PORT_ORIGINAL, 1132 ACTION_PHY_PORT_INDEX, 1133 ACTION_NEXT, 1134 ZERO, 1135 }; 1136 1137 static const enum index action_port_id[] = { 1138 ACTION_PORT_ID_ORIGINAL, 1139 ACTION_PORT_ID_ID, 1140 ACTION_NEXT, 1141 ZERO, 1142 }; 1143 1144 static const enum index action_meter[] = { 1145 ACTION_METER_ID, 1146 ACTION_NEXT, 1147 ZERO, 1148 }; 1149 1150 static const enum index action_of_set_mpls_ttl[] = { 1151 ACTION_OF_SET_MPLS_TTL_MPLS_TTL, 1152 ACTION_NEXT, 1153 ZERO, 1154 }; 1155 1156 static const enum index action_of_set_nw_ttl[] = { 1157 ACTION_OF_SET_NW_TTL_NW_TTL, 1158 ACTION_NEXT, 1159 ZERO, 1160 }; 1161 1162 static const enum index action_of_push_vlan[] = { 1163 ACTION_OF_PUSH_VLAN_ETHERTYPE, 1164 ACTION_NEXT, 1165 ZERO, 1166 }; 1167 1168 static const enum index action_of_set_vlan_vid[] = { 1169 ACTION_OF_SET_VLAN_VID_VLAN_VID, 1170 ACTION_NEXT, 1171 ZERO, 1172 }; 1173 1174 static const enum index action_of_set_vlan_pcp[] = { 1175 ACTION_OF_SET_VLAN_PCP_VLAN_PCP, 1176 ACTION_NEXT, 1177 ZERO, 1178 }; 1179 1180 static const enum index action_of_pop_mpls[] = { 1181 ACTION_OF_POP_MPLS_ETHERTYPE, 1182 ACTION_NEXT, 1183 ZERO, 1184 }; 1185 1186 static const enum index action_of_push_mpls[] = { 1187 ACTION_OF_PUSH_MPLS_ETHERTYPE, 1188 ACTION_NEXT, 1189 ZERO, 1190 }; 1191 1192 static const enum index action_set_ipv4_src[] = { 1193 ACTION_SET_IPV4_SRC_IPV4_SRC, 1194 ACTION_NEXT, 1195 ZERO, 1196 }; 1197 1198 static const enum index action_set_mac_src[] = { 1199 ACTION_SET_MAC_SRC_MAC_SRC, 1200 ACTION_NEXT, 1201 ZERO, 1202 }; 1203 1204 static const enum index action_set_ipv4_dst[] = { 1205 ACTION_SET_IPV4_DST_IPV4_DST, 1206 ACTION_NEXT, 1207 ZERO, 1208 }; 1209 1210 static const enum index action_set_ipv6_src[] = { 1211 ACTION_SET_IPV6_SRC_IPV6_SRC, 1212 ACTION_NEXT, 1213 ZERO, 1214 }; 1215 1216 static const enum index action_set_ipv6_dst[] = { 1217 ACTION_SET_IPV6_DST_IPV6_DST, 1218 ACTION_NEXT, 1219 ZERO, 1220 }; 1221 1222 static const enum index action_set_tp_src[] = { 1223 ACTION_SET_TP_SRC_TP_SRC, 1224 ACTION_NEXT, 1225 ZERO, 1226 }; 1227 1228 static const enum index action_set_tp_dst[] = { 1229 ACTION_SET_TP_DST_TP_DST, 1230 ACTION_NEXT, 1231 ZERO, 1232 }; 1233 1234 static const enum index action_set_ttl[] = { 1235 ACTION_SET_TTL_TTL, 1236 ACTION_NEXT, 1237 ZERO, 1238 }; 1239 1240 static const enum index action_jump[] = { 1241 ACTION_JUMP_GROUP, 1242 ACTION_NEXT, 1243 ZERO, 1244 }; 1245 1246 static const enum index action_set_mac_dst[] = { 1247 ACTION_SET_MAC_DST_MAC_DST, 1248 ACTION_NEXT, 1249 ZERO, 1250 }; 1251 1252 static const enum index action_inc_tcp_seq[] = { 1253 ACTION_INC_TCP_SEQ_VALUE, 1254 ACTION_NEXT, 1255 ZERO, 1256 }; 1257 1258 static const enum index action_dec_tcp_seq[] = { 1259 ACTION_DEC_TCP_SEQ_VALUE, 1260 ACTION_NEXT, 1261 ZERO, 1262 }; 1263 1264 static const enum index action_inc_tcp_ack[] = { 1265 ACTION_INC_TCP_ACK_VALUE, 1266 ACTION_NEXT, 1267 ZERO, 1268 }; 1269 1270 static const enum index action_dec_tcp_ack[] = { 1271 ACTION_DEC_TCP_ACK_VALUE, 1272 ACTION_NEXT, 1273 ZERO, 1274 }; 1275 1276 static const enum index action_raw_encap[] = { 1277 ACTION_RAW_ENCAP_INDEX, 1278 ACTION_NEXT, 1279 ZERO, 1280 }; 1281 1282 static const enum index action_raw_decap[] = { 1283 ACTION_RAW_DECAP_INDEX, 1284 ACTION_NEXT, 1285 ZERO, 1286 }; 1287 1288 static const enum index action_set_tag[] = { 1289 ACTION_SET_TAG_DATA, 1290 ACTION_SET_TAG_INDEX, 1291 ACTION_SET_TAG_MASK, 1292 ACTION_NEXT, 1293 ZERO, 1294 }; 1295 1296 static const enum index action_set_meta[] = { 1297 ACTION_SET_META_DATA, 1298 ACTION_SET_META_MASK, 1299 ACTION_NEXT, 1300 ZERO, 1301 }; 1302 1303 static int parse_set_raw_encap_decap(struct context *, const struct token *, 1304 const char *, unsigned int, 1305 void *, unsigned int); 1306 static int parse_set_init(struct context *, const struct token *, 1307 const char *, unsigned int, 1308 void *, unsigned int); 1309 static int parse_init(struct context *, const struct token *, 1310 const char *, unsigned int, 1311 void *, unsigned int); 1312 static int parse_vc(struct context *, const struct token *, 1313 const char *, unsigned int, 1314 void *, unsigned int); 1315 static int parse_vc_spec(struct context *, const struct token *, 1316 const char *, unsigned int, void *, unsigned int); 1317 static int parse_vc_conf(struct context *, const struct token *, 1318 const char *, unsigned int, void *, unsigned int); 1319 static int parse_vc_action_rss(struct context *, const struct token *, 1320 const char *, unsigned int, void *, 1321 unsigned int); 1322 static int parse_vc_action_rss_func(struct context *, const struct token *, 1323 const char *, unsigned int, void *, 1324 unsigned int); 1325 static int parse_vc_action_rss_type(struct context *, const struct token *, 1326 const char *, unsigned int, void *, 1327 unsigned int); 1328 static int parse_vc_action_rss_queue(struct context *, const struct token *, 1329 const char *, unsigned int, void *, 1330 unsigned int); 1331 static int parse_vc_action_vxlan_encap(struct context *, const struct token *, 1332 const char *, unsigned int, void *, 1333 unsigned int); 1334 static int parse_vc_action_nvgre_encap(struct context *, const struct token *, 1335 const char *, unsigned int, void *, 1336 unsigned int); 1337 static int parse_vc_action_l2_encap(struct context *, const struct token *, 1338 const char *, unsigned int, void *, 1339 unsigned int); 1340 static int parse_vc_action_l2_decap(struct context *, const struct token *, 1341 const char *, unsigned int, void *, 1342 unsigned int); 1343 static int parse_vc_action_mplsogre_encap(struct context *, 1344 const struct token *, const char *, 1345 unsigned int, void *, unsigned int); 1346 static int parse_vc_action_mplsogre_decap(struct context *, 1347 const struct token *, const char *, 1348 unsigned int, void *, unsigned int); 1349 static int parse_vc_action_mplsoudp_encap(struct context *, 1350 const struct token *, const char *, 1351 unsigned int, void *, unsigned int); 1352 static int parse_vc_action_mplsoudp_decap(struct context *, 1353 const struct token *, const char *, 1354 unsigned int, void *, unsigned int); 1355 static int parse_vc_action_raw_encap(struct context *, 1356 const struct token *, const char *, 1357 unsigned int, void *, unsigned int); 1358 static int parse_vc_action_raw_decap(struct context *, 1359 const struct token *, const char *, 1360 unsigned int, void *, unsigned int); 1361 static int parse_vc_action_raw_encap_index(struct context *, 1362 const struct token *, const char *, 1363 unsigned int, void *, unsigned int); 1364 static int parse_vc_action_raw_decap_index(struct context *, 1365 const struct token *, const char *, 1366 unsigned int, void *, unsigned int); 1367 static int parse_vc_action_set_meta(struct context *ctx, 1368 const struct token *token, const char *str, 1369 unsigned int len, void *buf, 1370 unsigned int size); 1371 static int parse_destroy(struct context *, const struct token *, 1372 const char *, unsigned int, 1373 void *, unsigned int); 1374 static int parse_flush(struct context *, const struct token *, 1375 const char *, unsigned int, 1376 void *, unsigned int); 1377 static int parse_query(struct context *, const struct token *, 1378 const char *, unsigned int, 1379 void *, unsigned int); 1380 static int parse_action(struct context *, const struct token *, 1381 const char *, unsigned int, 1382 void *, unsigned int); 1383 static int parse_list(struct context *, const struct token *, 1384 const char *, unsigned int, 1385 void *, unsigned int); 1386 static int parse_isolate(struct context *, const struct token *, 1387 const char *, unsigned int, 1388 void *, unsigned int); 1389 static int parse_int(struct context *, const struct token *, 1390 const char *, unsigned int, 1391 void *, unsigned int); 1392 static int parse_prefix(struct context *, const struct token *, 1393 const char *, unsigned int, 1394 void *, unsigned int); 1395 static int parse_boolean(struct context *, const struct token *, 1396 const char *, unsigned int, 1397 void *, unsigned int); 1398 static int parse_string(struct context *, const struct token *, 1399 const char *, unsigned int, 1400 void *, unsigned int); 1401 static int parse_hex(struct context *ctx, const struct token *token, 1402 const char *str, unsigned int len, 1403 void *buf, unsigned int size); 1404 static int parse_mac_addr(struct context *, const struct token *, 1405 const char *, unsigned int, 1406 void *, unsigned int); 1407 static int parse_ipv4_addr(struct context *, const struct token *, 1408 const char *, unsigned int, 1409 void *, unsigned int); 1410 static int parse_ipv6_addr(struct context *, const struct token *, 1411 const char *, unsigned int, 1412 void *, unsigned int); 1413 static int parse_port(struct context *, const struct token *, 1414 const char *, unsigned int, 1415 void *, unsigned int); 1416 static int comp_none(struct context *, const struct token *, 1417 unsigned int, char *, unsigned int); 1418 static int comp_boolean(struct context *, const struct token *, 1419 unsigned int, char *, unsigned int); 1420 static int comp_action(struct context *, const struct token *, 1421 unsigned int, char *, unsigned int); 1422 static int comp_port(struct context *, const struct token *, 1423 unsigned int, char *, unsigned int); 1424 static int comp_rule_id(struct context *, const struct token *, 1425 unsigned int, char *, unsigned int); 1426 static int comp_vc_action_rss_type(struct context *, const struct token *, 1427 unsigned int, char *, unsigned int); 1428 static int comp_vc_action_rss_queue(struct context *, const struct token *, 1429 unsigned int, char *, unsigned int); 1430 static int comp_set_raw_index(struct context *, const struct token *, 1431 unsigned int, char *, unsigned int); 1432 1433 /** Token definitions. */ 1434 static const struct token token_list[] = { 1435 /* Special tokens. */ 1436 [ZERO] = { 1437 .name = "ZERO", 1438 .help = "null entry, abused as the entry point", 1439 .next = NEXT(NEXT_ENTRY(FLOW)), 1440 }, 1441 [END] = { 1442 .name = "", 1443 .type = "RETURN", 1444 .help = "command may end here", 1445 }, 1446 [START_SET] = { 1447 .name = "START_SET", 1448 .help = "null entry, abused as the entry point for set", 1449 .next = NEXT(NEXT_ENTRY(SET)), 1450 }, 1451 [END_SET] = { 1452 .name = "end_set", 1453 .type = "RETURN", 1454 .help = "set command may end here", 1455 }, 1456 /* Common tokens. */ 1457 [INTEGER] = { 1458 .name = "{int}", 1459 .type = "INTEGER", 1460 .help = "integer value", 1461 .call = parse_int, 1462 .comp = comp_none, 1463 }, 1464 [UNSIGNED] = { 1465 .name = "{unsigned}", 1466 .type = "UNSIGNED", 1467 .help = "unsigned integer value", 1468 .call = parse_int, 1469 .comp = comp_none, 1470 }, 1471 [PREFIX] = { 1472 .name = "{prefix}", 1473 .type = "PREFIX", 1474 .help = "prefix length for bit-mask", 1475 .call = parse_prefix, 1476 .comp = comp_none, 1477 }, 1478 [BOOLEAN] = { 1479 .name = "{boolean}", 1480 .type = "BOOLEAN", 1481 .help = "any boolean value", 1482 .call = parse_boolean, 1483 .comp = comp_boolean, 1484 }, 1485 [STRING] = { 1486 .name = "{string}", 1487 .type = "STRING", 1488 .help = "fixed string", 1489 .call = parse_string, 1490 .comp = comp_none, 1491 }, 1492 [HEX] = { 1493 .name = "{hex}", 1494 .type = "HEX", 1495 .help = "fixed string", 1496 .call = parse_hex, 1497 .comp = comp_none, 1498 }, 1499 [MAC_ADDR] = { 1500 .name = "{MAC address}", 1501 .type = "MAC-48", 1502 .help = "standard MAC address notation", 1503 .call = parse_mac_addr, 1504 .comp = comp_none, 1505 }, 1506 [IPV4_ADDR] = { 1507 .name = "{IPv4 address}", 1508 .type = "IPV4 ADDRESS", 1509 .help = "standard IPv4 address notation", 1510 .call = parse_ipv4_addr, 1511 .comp = comp_none, 1512 }, 1513 [IPV6_ADDR] = { 1514 .name = "{IPv6 address}", 1515 .type = "IPV6 ADDRESS", 1516 .help = "standard IPv6 address notation", 1517 .call = parse_ipv6_addr, 1518 .comp = comp_none, 1519 }, 1520 [RULE_ID] = { 1521 .name = "{rule id}", 1522 .type = "RULE ID", 1523 .help = "rule identifier", 1524 .call = parse_int, 1525 .comp = comp_rule_id, 1526 }, 1527 [PORT_ID] = { 1528 .name = "{port_id}", 1529 .type = "PORT ID", 1530 .help = "port identifier", 1531 .call = parse_port, 1532 .comp = comp_port, 1533 }, 1534 [GROUP_ID] = { 1535 .name = "{group_id}", 1536 .type = "GROUP ID", 1537 .help = "group identifier", 1538 .call = parse_int, 1539 .comp = comp_none, 1540 }, 1541 [PRIORITY_LEVEL] = { 1542 .name = "{level}", 1543 .type = "PRIORITY", 1544 .help = "priority level", 1545 .call = parse_int, 1546 .comp = comp_none, 1547 }, 1548 /* Top-level command. */ 1549 [FLOW] = { 1550 .name = "flow", 1551 .type = "{command} {port_id} [{arg} [...]]", 1552 .help = "manage ingress/egress flow rules", 1553 .next = NEXT(NEXT_ENTRY 1554 (VALIDATE, 1555 CREATE, 1556 DESTROY, 1557 FLUSH, 1558 LIST, 1559 QUERY, 1560 ISOLATE)), 1561 .call = parse_init, 1562 }, 1563 /* Sub-level commands. */ 1564 [VALIDATE] = { 1565 .name = "validate", 1566 .help = "check whether a flow rule can be created", 1567 .next = NEXT(next_vc_attr, NEXT_ENTRY(PORT_ID)), 1568 .args = ARGS(ARGS_ENTRY(struct buffer, port)), 1569 .call = parse_vc, 1570 }, 1571 [CREATE] = { 1572 .name = "create", 1573 .help = "create a flow rule", 1574 .next = NEXT(next_vc_attr, NEXT_ENTRY(PORT_ID)), 1575 .args = ARGS(ARGS_ENTRY(struct buffer, port)), 1576 .call = parse_vc, 1577 }, 1578 [DESTROY] = { 1579 .name = "destroy", 1580 .help = "destroy specific flow rules", 1581 .next = NEXT(NEXT_ENTRY(DESTROY_RULE), NEXT_ENTRY(PORT_ID)), 1582 .args = ARGS(ARGS_ENTRY(struct buffer, port)), 1583 .call = parse_destroy, 1584 }, 1585 [FLUSH] = { 1586 .name = "flush", 1587 .help = "destroy all flow rules", 1588 .next = NEXT(NEXT_ENTRY(PORT_ID)), 1589 .args = ARGS(ARGS_ENTRY(struct buffer, port)), 1590 .call = parse_flush, 1591 }, 1592 [QUERY] = { 1593 .name = "query", 1594 .help = "query an existing flow rule", 1595 .next = NEXT(NEXT_ENTRY(QUERY_ACTION), 1596 NEXT_ENTRY(RULE_ID), 1597 NEXT_ENTRY(PORT_ID)), 1598 .args = ARGS(ARGS_ENTRY(struct buffer, args.query.action.type), 1599 ARGS_ENTRY(struct buffer, args.query.rule), 1600 ARGS_ENTRY(struct buffer, port)), 1601 .call = parse_query, 1602 }, 1603 [LIST] = { 1604 .name = "list", 1605 .help = "list existing flow rules", 1606 .next = NEXT(next_list_attr, NEXT_ENTRY(PORT_ID)), 1607 .args = ARGS(ARGS_ENTRY(struct buffer, port)), 1608 .call = parse_list, 1609 }, 1610 [ISOLATE] = { 1611 .name = "isolate", 1612 .help = "restrict ingress traffic to the defined flow rules", 1613 .next = NEXT(NEXT_ENTRY(BOOLEAN), 1614 NEXT_ENTRY(PORT_ID)), 1615 .args = ARGS(ARGS_ENTRY(struct buffer, args.isolate.set), 1616 ARGS_ENTRY(struct buffer, port)), 1617 .call = parse_isolate, 1618 }, 1619 /* Destroy arguments. */ 1620 [DESTROY_RULE] = { 1621 .name = "rule", 1622 .help = "specify a rule identifier", 1623 .next = NEXT(next_destroy_attr, NEXT_ENTRY(RULE_ID)), 1624 .args = ARGS(ARGS_ENTRY_PTR(struct buffer, args.destroy.rule)), 1625 .call = parse_destroy, 1626 }, 1627 /* Query arguments. */ 1628 [QUERY_ACTION] = { 1629 .name = "{action}", 1630 .type = "ACTION", 1631 .help = "action to query, must be part of the rule", 1632 .call = parse_action, 1633 .comp = comp_action, 1634 }, 1635 /* List arguments. */ 1636 [LIST_GROUP] = { 1637 .name = "group", 1638 .help = "specify a group", 1639 .next = NEXT(next_list_attr, NEXT_ENTRY(GROUP_ID)), 1640 .args = ARGS(ARGS_ENTRY_PTR(struct buffer, args.list.group)), 1641 .call = parse_list, 1642 }, 1643 /* Validate/create attributes. */ 1644 [GROUP] = { 1645 .name = "group", 1646 .help = "specify a group", 1647 .next = NEXT(next_vc_attr, NEXT_ENTRY(GROUP_ID)), 1648 .args = ARGS(ARGS_ENTRY(struct rte_flow_attr, group)), 1649 .call = parse_vc, 1650 }, 1651 [PRIORITY] = { 1652 .name = "priority", 1653 .help = "specify a priority level", 1654 .next = NEXT(next_vc_attr, NEXT_ENTRY(PRIORITY_LEVEL)), 1655 .args = ARGS(ARGS_ENTRY(struct rte_flow_attr, priority)), 1656 .call = parse_vc, 1657 }, 1658 [INGRESS] = { 1659 .name = "ingress", 1660 .help = "affect rule to ingress", 1661 .next = NEXT(next_vc_attr), 1662 .call = parse_vc, 1663 }, 1664 [EGRESS] = { 1665 .name = "egress", 1666 .help = "affect rule to egress", 1667 .next = NEXT(next_vc_attr), 1668 .call = parse_vc, 1669 }, 1670 [TRANSFER] = { 1671 .name = "transfer", 1672 .help = "apply rule directly to endpoints found in pattern", 1673 .next = NEXT(next_vc_attr), 1674 .call = parse_vc, 1675 }, 1676 /* Validate/create pattern. */ 1677 [PATTERN] = { 1678 .name = "pattern", 1679 .help = "submit a list of pattern items", 1680 .next = NEXT(next_item), 1681 .call = parse_vc, 1682 }, 1683 [ITEM_PARAM_IS] = { 1684 .name = "is", 1685 .help = "match value perfectly (with full bit-mask)", 1686 .call = parse_vc_spec, 1687 }, 1688 [ITEM_PARAM_SPEC] = { 1689 .name = "spec", 1690 .help = "match value according to configured bit-mask", 1691 .call = parse_vc_spec, 1692 }, 1693 [ITEM_PARAM_LAST] = { 1694 .name = "last", 1695 .help = "specify upper bound to establish a range", 1696 .call = parse_vc_spec, 1697 }, 1698 [ITEM_PARAM_MASK] = { 1699 .name = "mask", 1700 .help = "specify bit-mask with relevant bits set to one", 1701 .call = parse_vc_spec, 1702 }, 1703 [ITEM_PARAM_PREFIX] = { 1704 .name = "prefix", 1705 .help = "generate bit-mask from a prefix length", 1706 .call = parse_vc_spec, 1707 }, 1708 [ITEM_NEXT] = { 1709 .name = "/", 1710 .help = "specify next pattern item", 1711 .next = NEXT(next_item), 1712 }, 1713 [ITEM_END] = { 1714 .name = "end", 1715 .help = "end list of pattern items", 1716 .priv = PRIV_ITEM(END, 0), 1717 .next = NEXT(NEXT_ENTRY(ACTIONS)), 1718 .call = parse_vc, 1719 }, 1720 [ITEM_VOID] = { 1721 .name = "void", 1722 .help = "no-op pattern item", 1723 .priv = PRIV_ITEM(VOID, 0), 1724 .next = NEXT(NEXT_ENTRY(ITEM_NEXT)), 1725 .call = parse_vc, 1726 }, 1727 [ITEM_INVERT] = { 1728 .name = "invert", 1729 .help = "perform actions when pattern does not match", 1730 .priv = PRIV_ITEM(INVERT, 0), 1731 .next = NEXT(NEXT_ENTRY(ITEM_NEXT)), 1732 .call = parse_vc, 1733 }, 1734 [ITEM_ANY] = { 1735 .name = "any", 1736 .help = "match any protocol for the current layer", 1737 .priv = PRIV_ITEM(ANY, sizeof(struct rte_flow_item_any)), 1738 .next = NEXT(item_any), 1739 .call = parse_vc, 1740 }, 1741 [ITEM_ANY_NUM] = { 1742 .name = "num", 1743 .help = "number of layers covered", 1744 .next = NEXT(item_any, NEXT_ENTRY(UNSIGNED), item_param), 1745 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_any, num)), 1746 }, 1747 [ITEM_PF] = { 1748 .name = "pf", 1749 .help = "match traffic from/to the physical function", 1750 .priv = PRIV_ITEM(PF, 0), 1751 .next = NEXT(NEXT_ENTRY(ITEM_NEXT)), 1752 .call = parse_vc, 1753 }, 1754 [ITEM_VF] = { 1755 .name = "vf", 1756 .help = "match traffic from/to a virtual function ID", 1757 .priv = PRIV_ITEM(VF, sizeof(struct rte_flow_item_vf)), 1758 .next = NEXT(item_vf), 1759 .call = parse_vc, 1760 }, 1761 [ITEM_VF_ID] = { 1762 .name = "id", 1763 .help = "VF ID", 1764 .next = NEXT(item_vf, NEXT_ENTRY(UNSIGNED), item_param), 1765 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_vf, id)), 1766 }, 1767 [ITEM_PHY_PORT] = { 1768 .name = "phy_port", 1769 .help = "match traffic from/to a specific physical port", 1770 .priv = PRIV_ITEM(PHY_PORT, 1771 sizeof(struct rte_flow_item_phy_port)), 1772 .next = NEXT(item_phy_port), 1773 .call = parse_vc, 1774 }, 1775 [ITEM_PHY_PORT_INDEX] = { 1776 .name = "index", 1777 .help = "physical port index", 1778 .next = NEXT(item_phy_port, NEXT_ENTRY(UNSIGNED), item_param), 1779 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_phy_port, index)), 1780 }, 1781 [ITEM_PORT_ID] = { 1782 .name = "port_id", 1783 .help = "match traffic from/to a given DPDK port ID", 1784 .priv = PRIV_ITEM(PORT_ID, 1785 sizeof(struct rte_flow_item_port_id)), 1786 .next = NEXT(item_port_id), 1787 .call = parse_vc, 1788 }, 1789 [ITEM_PORT_ID_ID] = { 1790 .name = "id", 1791 .help = "DPDK port ID", 1792 .next = NEXT(item_port_id, NEXT_ENTRY(UNSIGNED), item_param), 1793 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_port_id, id)), 1794 }, 1795 [ITEM_MARK] = { 1796 .name = "mark", 1797 .help = "match traffic against value set in previously matched rule", 1798 .priv = PRIV_ITEM(MARK, sizeof(struct rte_flow_item_mark)), 1799 .next = NEXT(item_mark), 1800 .call = parse_vc, 1801 }, 1802 [ITEM_MARK_ID] = { 1803 .name = "id", 1804 .help = "Integer value to match against", 1805 .next = NEXT(item_mark, NEXT_ENTRY(UNSIGNED), item_param), 1806 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_mark, id)), 1807 }, 1808 [ITEM_RAW] = { 1809 .name = "raw", 1810 .help = "match an arbitrary byte string", 1811 .priv = PRIV_ITEM(RAW, ITEM_RAW_SIZE), 1812 .next = NEXT(item_raw), 1813 .call = parse_vc, 1814 }, 1815 [ITEM_RAW_RELATIVE] = { 1816 .name = "relative", 1817 .help = "look for pattern after the previous item", 1818 .next = NEXT(item_raw, NEXT_ENTRY(BOOLEAN), item_param), 1819 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_raw, 1820 relative, 1)), 1821 }, 1822 [ITEM_RAW_SEARCH] = { 1823 .name = "search", 1824 .help = "search pattern from offset (see also limit)", 1825 .next = NEXT(item_raw, NEXT_ENTRY(BOOLEAN), item_param), 1826 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_raw, 1827 search, 1)), 1828 }, 1829 [ITEM_RAW_OFFSET] = { 1830 .name = "offset", 1831 .help = "absolute or relative offset for pattern", 1832 .next = NEXT(item_raw, NEXT_ENTRY(INTEGER), item_param), 1833 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, offset)), 1834 }, 1835 [ITEM_RAW_LIMIT] = { 1836 .name = "limit", 1837 .help = "search area limit for start of pattern", 1838 .next = NEXT(item_raw, NEXT_ENTRY(UNSIGNED), item_param), 1839 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, limit)), 1840 }, 1841 [ITEM_RAW_PATTERN] = { 1842 .name = "pattern", 1843 .help = "byte string to look for", 1844 .next = NEXT(item_raw, 1845 NEXT_ENTRY(STRING), 1846 NEXT_ENTRY(ITEM_PARAM_IS, 1847 ITEM_PARAM_SPEC, 1848 ITEM_PARAM_MASK)), 1849 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, pattern), 1850 ARGS_ENTRY(struct rte_flow_item_raw, length), 1851 ARGS_ENTRY_ARB(sizeof(struct rte_flow_item_raw), 1852 ITEM_RAW_PATTERN_SIZE)), 1853 }, 1854 [ITEM_ETH] = { 1855 .name = "eth", 1856 .help = "match Ethernet header", 1857 .priv = PRIV_ITEM(ETH, sizeof(struct rte_flow_item_eth)), 1858 .next = NEXT(item_eth), 1859 .call = parse_vc, 1860 }, 1861 [ITEM_ETH_DST] = { 1862 .name = "dst", 1863 .help = "destination MAC", 1864 .next = NEXT(item_eth, NEXT_ENTRY(MAC_ADDR), item_param), 1865 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_eth, dst)), 1866 }, 1867 [ITEM_ETH_SRC] = { 1868 .name = "src", 1869 .help = "source MAC", 1870 .next = NEXT(item_eth, NEXT_ENTRY(MAC_ADDR), item_param), 1871 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_eth, src)), 1872 }, 1873 [ITEM_ETH_TYPE] = { 1874 .name = "type", 1875 .help = "EtherType", 1876 .next = NEXT(item_eth, NEXT_ENTRY(UNSIGNED), item_param), 1877 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_eth, type)), 1878 }, 1879 [ITEM_VLAN] = { 1880 .name = "vlan", 1881 .help = "match 802.1Q/ad VLAN tag", 1882 .priv = PRIV_ITEM(VLAN, sizeof(struct rte_flow_item_vlan)), 1883 .next = NEXT(item_vlan), 1884 .call = parse_vc, 1885 }, 1886 [ITEM_VLAN_TCI] = { 1887 .name = "tci", 1888 .help = "tag control information", 1889 .next = NEXT(item_vlan, NEXT_ENTRY(UNSIGNED), item_param), 1890 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vlan, tci)), 1891 }, 1892 [ITEM_VLAN_PCP] = { 1893 .name = "pcp", 1894 .help = "priority code point", 1895 .next = NEXT(item_vlan, NEXT_ENTRY(UNSIGNED), item_param), 1896 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_vlan, 1897 tci, "\xe0\x00")), 1898 }, 1899 [ITEM_VLAN_DEI] = { 1900 .name = "dei", 1901 .help = "drop eligible indicator", 1902 .next = NEXT(item_vlan, NEXT_ENTRY(UNSIGNED), item_param), 1903 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_vlan, 1904 tci, "\x10\x00")), 1905 }, 1906 [ITEM_VLAN_VID] = { 1907 .name = "vid", 1908 .help = "VLAN identifier", 1909 .next = NEXT(item_vlan, NEXT_ENTRY(UNSIGNED), item_param), 1910 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_vlan, 1911 tci, "\x0f\xff")), 1912 }, 1913 [ITEM_VLAN_INNER_TYPE] = { 1914 .name = "inner_type", 1915 .help = "inner EtherType", 1916 .next = NEXT(item_vlan, NEXT_ENTRY(UNSIGNED), item_param), 1917 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vlan, 1918 inner_type)), 1919 }, 1920 [ITEM_IPV4] = { 1921 .name = "ipv4", 1922 .help = "match IPv4 header", 1923 .priv = PRIV_ITEM(IPV4, sizeof(struct rte_flow_item_ipv4)), 1924 .next = NEXT(item_ipv4), 1925 .call = parse_vc, 1926 }, 1927 [ITEM_IPV4_TOS] = { 1928 .name = "tos", 1929 .help = "type of service", 1930 .next = NEXT(item_ipv4, NEXT_ENTRY(UNSIGNED), item_param), 1931 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4, 1932 hdr.type_of_service)), 1933 }, 1934 [ITEM_IPV4_TTL] = { 1935 .name = "ttl", 1936 .help = "time to live", 1937 .next = NEXT(item_ipv4, NEXT_ENTRY(UNSIGNED), item_param), 1938 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4, 1939 hdr.time_to_live)), 1940 }, 1941 [ITEM_IPV4_PROTO] = { 1942 .name = "proto", 1943 .help = "next protocol ID", 1944 .next = NEXT(item_ipv4, NEXT_ENTRY(UNSIGNED), item_param), 1945 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4, 1946 hdr.next_proto_id)), 1947 }, 1948 [ITEM_IPV4_SRC] = { 1949 .name = "src", 1950 .help = "source address", 1951 .next = NEXT(item_ipv4, NEXT_ENTRY(IPV4_ADDR), item_param), 1952 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4, 1953 hdr.src_addr)), 1954 }, 1955 [ITEM_IPV4_DST] = { 1956 .name = "dst", 1957 .help = "destination address", 1958 .next = NEXT(item_ipv4, NEXT_ENTRY(IPV4_ADDR), item_param), 1959 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4, 1960 hdr.dst_addr)), 1961 }, 1962 [ITEM_IPV6] = { 1963 .name = "ipv6", 1964 .help = "match IPv6 header", 1965 .priv = PRIV_ITEM(IPV6, sizeof(struct rte_flow_item_ipv6)), 1966 .next = NEXT(item_ipv6), 1967 .call = parse_vc, 1968 }, 1969 [ITEM_IPV6_TC] = { 1970 .name = "tc", 1971 .help = "traffic class", 1972 .next = NEXT(item_ipv6, NEXT_ENTRY(UNSIGNED), item_param), 1973 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_ipv6, 1974 hdr.vtc_flow, 1975 "\x0f\xf0\x00\x00")), 1976 }, 1977 [ITEM_IPV6_FLOW] = { 1978 .name = "flow", 1979 .help = "flow label", 1980 .next = NEXT(item_ipv6, NEXT_ENTRY(UNSIGNED), item_param), 1981 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_ipv6, 1982 hdr.vtc_flow, 1983 "\x00\x0f\xff\xff")), 1984 }, 1985 [ITEM_IPV6_PROTO] = { 1986 .name = "proto", 1987 .help = "protocol (next header)", 1988 .next = NEXT(item_ipv6, NEXT_ENTRY(UNSIGNED), item_param), 1989 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6, 1990 hdr.proto)), 1991 }, 1992 [ITEM_IPV6_HOP] = { 1993 .name = "hop", 1994 .help = "hop limit", 1995 .next = NEXT(item_ipv6, NEXT_ENTRY(UNSIGNED), item_param), 1996 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6, 1997 hdr.hop_limits)), 1998 }, 1999 [ITEM_IPV6_SRC] = { 2000 .name = "src", 2001 .help = "source address", 2002 .next = NEXT(item_ipv6, NEXT_ENTRY(IPV6_ADDR), item_param), 2003 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6, 2004 hdr.src_addr)), 2005 }, 2006 [ITEM_IPV6_DST] = { 2007 .name = "dst", 2008 .help = "destination address", 2009 .next = NEXT(item_ipv6, NEXT_ENTRY(IPV6_ADDR), item_param), 2010 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6, 2011 hdr.dst_addr)), 2012 }, 2013 [ITEM_ICMP] = { 2014 .name = "icmp", 2015 .help = "match ICMP header", 2016 .priv = PRIV_ITEM(ICMP, sizeof(struct rte_flow_item_icmp)), 2017 .next = NEXT(item_icmp), 2018 .call = parse_vc, 2019 }, 2020 [ITEM_ICMP_TYPE] = { 2021 .name = "type", 2022 .help = "ICMP packet type", 2023 .next = NEXT(item_icmp, NEXT_ENTRY(UNSIGNED), item_param), 2024 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp, 2025 hdr.icmp_type)), 2026 }, 2027 [ITEM_ICMP_CODE] = { 2028 .name = "code", 2029 .help = "ICMP packet code", 2030 .next = NEXT(item_icmp, NEXT_ENTRY(UNSIGNED), item_param), 2031 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp, 2032 hdr.icmp_code)), 2033 }, 2034 [ITEM_UDP] = { 2035 .name = "udp", 2036 .help = "match UDP header", 2037 .priv = PRIV_ITEM(UDP, sizeof(struct rte_flow_item_udp)), 2038 .next = NEXT(item_udp), 2039 .call = parse_vc, 2040 }, 2041 [ITEM_UDP_SRC] = { 2042 .name = "src", 2043 .help = "UDP source port", 2044 .next = NEXT(item_udp, NEXT_ENTRY(UNSIGNED), item_param), 2045 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_udp, 2046 hdr.src_port)), 2047 }, 2048 [ITEM_UDP_DST] = { 2049 .name = "dst", 2050 .help = "UDP destination port", 2051 .next = NEXT(item_udp, NEXT_ENTRY(UNSIGNED), item_param), 2052 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_udp, 2053 hdr.dst_port)), 2054 }, 2055 [ITEM_TCP] = { 2056 .name = "tcp", 2057 .help = "match TCP header", 2058 .priv = PRIV_ITEM(TCP, sizeof(struct rte_flow_item_tcp)), 2059 .next = NEXT(item_tcp), 2060 .call = parse_vc, 2061 }, 2062 [ITEM_TCP_SRC] = { 2063 .name = "src", 2064 .help = "TCP source port", 2065 .next = NEXT(item_tcp, NEXT_ENTRY(UNSIGNED), item_param), 2066 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_tcp, 2067 hdr.src_port)), 2068 }, 2069 [ITEM_TCP_DST] = { 2070 .name = "dst", 2071 .help = "TCP destination port", 2072 .next = NEXT(item_tcp, NEXT_ENTRY(UNSIGNED), item_param), 2073 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_tcp, 2074 hdr.dst_port)), 2075 }, 2076 [ITEM_TCP_FLAGS] = { 2077 .name = "flags", 2078 .help = "TCP flags", 2079 .next = NEXT(item_tcp, NEXT_ENTRY(UNSIGNED), item_param), 2080 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_tcp, 2081 hdr.tcp_flags)), 2082 }, 2083 [ITEM_SCTP] = { 2084 .name = "sctp", 2085 .help = "match SCTP header", 2086 .priv = PRIV_ITEM(SCTP, sizeof(struct rte_flow_item_sctp)), 2087 .next = NEXT(item_sctp), 2088 .call = parse_vc, 2089 }, 2090 [ITEM_SCTP_SRC] = { 2091 .name = "src", 2092 .help = "SCTP source port", 2093 .next = NEXT(item_sctp, NEXT_ENTRY(UNSIGNED), item_param), 2094 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp, 2095 hdr.src_port)), 2096 }, 2097 [ITEM_SCTP_DST] = { 2098 .name = "dst", 2099 .help = "SCTP destination port", 2100 .next = NEXT(item_sctp, NEXT_ENTRY(UNSIGNED), item_param), 2101 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp, 2102 hdr.dst_port)), 2103 }, 2104 [ITEM_SCTP_TAG] = { 2105 .name = "tag", 2106 .help = "validation tag", 2107 .next = NEXT(item_sctp, NEXT_ENTRY(UNSIGNED), item_param), 2108 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp, 2109 hdr.tag)), 2110 }, 2111 [ITEM_SCTP_CKSUM] = { 2112 .name = "cksum", 2113 .help = "checksum", 2114 .next = NEXT(item_sctp, NEXT_ENTRY(UNSIGNED), item_param), 2115 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp, 2116 hdr.cksum)), 2117 }, 2118 [ITEM_VXLAN] = { 2119 .name = "vxlan", 2120 .help = "match VXLAN header", 2121 .priv = PRIV_ITEM(VXLAN, sizeof(struct rte_flow_item_vxlan)), 2122 .next = NEXT(item_vxlan), 2123 .call = parse_vc, 2124 }, 2125 [ITEM_VXLAN_VNI] = { 2126 .name = "vni", 2127 .help = "VXLAN identifier", 2128 .next = NEXT(item_vxlan, NEXT_ENTRY(UNSIGNED), item_param), 2129 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan, vni)), 2130 }, 2131 [ITEM_E_TAG] = { 2132 .name = "e_tag", 2133 .help = "match E-Tag header", 2134 .priv = PRIV_ITEM(E_TAG, sizeof(struct rte_flow_item_e_tag)), 2135 .next = NEXT(item_e_tag), 2136 .call = parse_vc, 2137 }, 2138 [ITEM_E_TAG_GRP_ECID_B] = { 2139 .name = "grp_ecid_b", 2140 .help = "GRP and E-CID base", 2141 .next = NEXT(item_e_tag, NEXT_ENTRY(UNSIGNED), item_param), 2142 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_e_tag, 2143 rsvd_grp_ecid_b, 2144 "\x3f\xff")), 2145 }, 2146 [ITEM_NVGRE] = { 2147 .name = "nvgre", 2148 .help = "match NVGRE header", 2149 .priv = PRIV_ITEM(NVGRE, sizeof(struct rte_flow_item_nvgre)), 2150 .next = NEXT(item_nvgre), 2151 .call = parse_vc, 2152 }, 2153 [ITEM_NVGRE_TNI] = { 2154 .name = "tni", 2155 .help = "virtual subnet ID", 2156 .next = NEXT(item_nvgre, NEXT_ENTRY(UNSIGNED), item_param), 2157 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_nvgre, tni)), 2158 }, 2159 [ITEM_MPLS] = { 2160 .name = "mpls", 2161 .help = "match MPLS header", 2162 .priv = PRIV_ITEM(MPLS, sizeof(struct rte_flow_item_mpls)), 2163 .next = NEXT(item_mpls), 2164 .call = parse_vc, 2165 }, 2166 [ITEM_MPLS_LABEL] = { 2167 .name = "label", 2168 .help = "MPLS label", 2169 .next = NEXT(item_mpls, NEXT_ENTRY(UNSIGNED), item_param), 2170 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_mpls, 2171 label_tc_s, 2172 "\xff\xff\xf0")), 2173 }, 2174 [ITEM_MPLS_TC] = { 2175 .name = "tc", 2176 .help = "MPLS Traffic Class", 2177 .next = NEXT(item_mpls, NEXT_ENTRY(UNSIGNED), item_param), 2178 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_mpls, 2179 label_tc_s, 2180 "\x00\x00\x0e")), 2181 }, 2182 [ITEM_MPLS_S] = { 2183 .name = "s", 2184 .help = "MPLS Bottom-of-Stack", 2185 .next = NEXT(item_mpls, NEXT_ENTRY(UNSIGNED), item_param), 2186 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_mpls, 2187 label_tc_s, 2188 "\x00\x00\x01")), 2189 }, 2190 [ITEM_GRE] = { 2191 .name = "gre", 2192 .help = "match GRE header", 2193 .priv = PRIV_ITEM(GRE, sizeof(struct rte_flow_item_gre)), 2194 .next = NEXT(item_gre), 2195 .call = parse_vc, 2196 }, 2197 [ITEM_GRE_PROTO] = { 2198 .name = "protocol", 2199 .help = "GRE protocol type", 2200 .next = NEXT(item_gre, NEXT_ENTRY(UNSIGNED), item_param), 2201 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre, 2202 protocol)), 2203 }, 2204 [ITEM_GRE_C_RSVD0_VER] = { 2205 .name = "c_rsvd0_ver", 2206 .help = 2207 "checksum (1b), undefined (1b), key bit (1b)," 2208 " sequence number (1b), reserved 0 (9b)," 2209 " version (3b)", 2210 .next = NEXT(item_gre, NEXT_ENTRY(UNSIGNED), item_param), 2211 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre, 2212 c_rsvd0_ver)), 2213 }, 2214 [ITEM_GRE_C_BIT] = { 2215 .name = "c_bit", 2216 .help = "checksum bit (C)", 2217 .next = NEXT(item_gre, NEXT_ENTRY(BOOLEAN), item_param), 2218 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_gre, 2219 c_rsvd0_ver, 2220 "\x80\x00\x00\x00")), 2221 }, 2222 [ITEM_GRE_S_BIT] = { 2223 .name = "s_bit", 2224 .help = "sequence number bit (S)", 2225 .next = NEXT(item_gre, NEXT_ENTRY(BOOLEAN), item_param), 2226 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_gre, 2227 c_rsvd0_ver, 2228 "\x10\x00\x00\x00")), 2229 }, 2230 [ITEM_GRE_K_BIT] = { 2231 .name = "k_bit", 2232 .help = "key bit (K)", 2233 .next = NEXT(item_gre, NEXT_ENTRY(BOOLEAN), item_param), 2234 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_gre, 2235 c_rsvd0_ver, 2236 "\x20\x00\x00\x00")), 2237 }, 2238 [ITEM_FUZZY] = { 2239 .name = "fuzzy", 2240 .help = "fuzzy pattern match, expect faster than default", 2241 .priv = PRIV_ITEM(FUZZY, 2242 sizeof(struct rte_flow_item_fuzzy)), 2243 .next = NEXT(item_fuzzy), 2244 .call = parse_vc, 2245 }, 2246 [ITEM_FUZZY_THRESH] = { 2247 .name = "thresh", 2248 .help = "match accuracy threshold", 2249 .next = NEXT(item_fuzzy, NEXT_ENTRY(UNSIGNED), item_param), 2250 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_fuzzy, 2251 thresh)), 2252 }, 2253 [ITEM_GTP] = { 2254 .name = "gtp", 2255 .help = "match GTP header", 2256 .priv = PRIV_ITEM(GTP, sizeof(struct rte_flow_item_gtp)), 2257 .next = NEXT(item_gtp), 2258 .call = parse_vc, 2259 }, 2260 [ITEM_GTP_TEID] = { 2261 .name = "teid", 2262 .help = "tunnel endpoint identifier", 2263 .next = NEXT(item_gtp, NEXT_ENTRY(UNSIGNED), item_param), 2264 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gtp, teid)), 2265 }, 2266 [ITEM_GTPC] = { 2267 .name = "gtpc", 2268 .help = "match GTP header", 2269 .priv = PRIV_ITEM(GTPC, sizeof(struct rte_flow_item_gtp)), 2270 .next = NEXT(item_gtp), 2271 .call = parse_vc, 2272 }, 2273 [ITEM_GTPU] = { 2274 .name = "gtpu", 2275 .help = "match GTP header", 2276 .priv = PRIV_ITEM(GTPU, sizeof(struct rte_flow_item_gtp)), 2277 .next = NEXT(item_gtp), 2278 .call = parse_vc, 2279 }, 2280 [ITEM_GENEVE] = { 2281 .name = "geneve", 2282 .help = "match GENEVE header", 2283 .priv = PRIV_ITEM(GENEVE, sizeof(struct rte_flow_item_geneve)), 2284 .next = NEXT(item_geneve), 2285 .call = parse_vc, 2286 }, 2287 [ITEM_GENEVE_VNI] = { 2288 .name = "vni", 2289 .help = "virtual network identifier", 2290 .next = NEXT(item_geneve, NEXT_ENTRY(UNSIGNED), item_param), 2291 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_geneve, vni)), 2292 }, 2293 [ITEM_GENEVE_PROTO] = { 2294 .name = "protocol", 2295 .help = "GENEVE protocol type", 2296 .next = NEXT(item_geneve, NEXT_ENTRY(UNSIGNED), item_param), 2297 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_geneve, 2298 protocol)), 2299 }, 2300 [ITEM_VXLAN_GPE] = { 2301 .name = "vxlan-gpe", 2302 .help = "match VXLAN-GPE header", 2303 .priv = PRIV_ITEM(VXLAN_GPE, 2304 sizeof(struct rte_flow_item_vxlan_gpe)), 2305 .next = NEXT(item_vxlan_gpe), 2306 .call = parse_vc, 2307 }, 2308 [ITEM_VXLAN_GPE_VNI] = { 2309 .name = "vni", 2310 .help = "VXLAN-GPE identifier", 2311 .next = NEXT(item_vxlan_gpe, NEXT_ENTRY(UNSIGNED), item_param), 2312 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan_gpe, 2313 vni)), 2314 }, 2315 [ITEM_ARP_ETH_IPV4] = { 2316 .name = "arp_eth_ipv4", 2317 .help = "match ARP header for Ethernet/IPv4", 2318 .priv = PRIV_ITEM(ARP_ETH_IPV4, 2319 sizeof(struct rte_flow_item_arp_eth_ipv4)), 2320 .next = NEXT(item_arp_eth_ipv4), 2321 .call = parse_vc, 2322 }, 2323 [ITEM_ARP_ETH_IPV4_SHA] = { 2324 .name = "sha", 2325 .help = "sender hardware address", 2326 .next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(MAC_ADDR), 2327 item_param), 2328 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4, 2329 sha)), 2330 }, 2331 [ITEM_ARP_ETH_IPV4_SPA] = { 2332 .name = "spa", 2333 .help = "sender IPv4 address", 2334 .next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(IPV4_ADDR), 2335 item_param), 2336 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4, 2337 spa)), 2338 }, 2339 [ITEM_ARP_ETH_IPV4_THA] = { 2340 .name = "tha", 2341 .help = "target hardware address", 2342 .next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(MAC_ADDR), 2343 item_param), 2344 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4, 2345 tha)), 2346 }, 2347 [ITEM_ARP_ETH_IPV4_TPA] = { 2348 .name = "tpa", 2349 .help = "target IPv4 address", 2350 .next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(IPV4_ADDR), 2351 item_param), 2352 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4, 2353 tpa)), 2354 }, 2355 [ITEM_IPV6_EXT] = { 2356 .name = "ipv6_ext", 2357 .help = "match presence of any IPv6 extension header", 2358 .priv = PRIV_ITEM(IPV6_EXT, 2359 sizeof(struct rte_flow_item_ipv6_ext)), 2360 .next = NEXT(item_ipv6_ext), 2361 .call = parse_vc, 2362 }, 2363 [ITEM_IPV6_EXT_NEXT_HDR] = { 2364 .name = "next_hdr", 2365 .help = "next header", 2366 .next = NEXT(item_ipv6_ext, NEXT_ENTRY(UNSIGNED), item_param), 2367 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_ext, 2368 next_hdr)), 2369 }, 2370 [ITEM_ICMP6] = { 2371 .name = "icmp6", 2372 .help = "match any ICMPv6 header", 2373 .priv = PRIV_ITEM(ICMP6, sizeof(struct rte_flow_item_icmp6)), 2374 .next = NEXT(item_icmp6), 2375 .call = parse_vc, 2376 }, 2377 [ITEM_ICMP6_TYPE] = { 2378 .name = "type", 2379 .help = "ICMPv6 type", 2380 .next = NEXT(item_icmp6, NEXT_ENTRY(UNSIGNED), item_param), 2381 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6, 2382 type)), 2383 }, 2384 [ITEM_ICMP6_CODE] = { 2385 .name = "code", 2386 .help = "ICMPv6 code", 2387 .next = NEXT(item_icmp6, NEXT_ENTRY(UNSIGNED), item_param), 2388 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6, 2389 code)), 2390 }, 2391 [ITEM_ICMP6_ND_NS] = { 2392 .name = "icmp6_nd_ns", 2393 .help = "match ICMPv6 neighbor discovery solicitation", 2394 .priv = PRIV_ITEM(ICMP6_ND_NS, 2395 sizeof(struct rte_flow_item_icmp6_nd_ns)), 2396 .next = NEXT(item_icmp6_nd_ns), 2397 .call = parse_vc, 2398 }, 2399 [ITEM_ICMP6_ND_NS_TARGET_ADDR] = { 2400 .name = "target_addr", 2401 .help = "target address", 2402 .next = NEXT(item_icmp6_nd_ns, NEXT_ENTRY(IPV6_ADDR), 2403 item_param), 2404 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_nd_ns, 2405 target_addr)), 2406 }, 2407 [ITEM_ICMP6_ND_NA] = { 2408 .name = "icmp6_nd_na", 2409 .help = "match ICMPv6 neighbor discovery advertisement", 2410 .priv = PRIV_ITEM(ICMP6_ND_NA, 2411 sizeof(struct rte_flow_item_icmp6_nd_na)), 2412 .next = NEXT(item_icmp6_nd_na), 2413 .call = parse_vc, 2414 }, 2415 [ITEM_ICMP6_ND_NA_TARGET_ADDR] = { 2416 .name = "target_addr", 2417 .help = "target address", 2418 .next = NEXT(item_icmp6_nd_na, NEXT_ENTRY(IPV6_ADDR), 2419 item_param), 2420 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_nd_na, 2421 target_addr)), 2422 }, 2423 [ITEM_ICMP6_ND_OPT] = { 2424 .name = "icmp6_nd_opt", 2425 .help = "match presence of any ICMPv6 neighbor discovery" 2426 " option", 2427 .priv = PRIV_ITEM(ICMP6_ND_OPT, 2428 sizeof(struct rte_flow_item_icmp6_nd_opt)), 2429 .next = NEXT(item_icmp6_nd_opt), 2430 .call = parse_vc, 2431 }, 2432 [ITEM_ICMP6_ND_OPT_TYPE] = { 2433 .name = "type", 2434 .help = "ND option type", 2435 .next = NEXT(item_icmp6_nd_opt, NEXT_ENTRY(UNSIGNED), 2436 item_param), 2437 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_nd_opt, 2438 type)), 2439 }, 2440 [ITEM_ICMP6_ND_OPT_SLA_ETH] = { 2441 .name = "icmp6_nd_opt_sla_eth", 2442 .help = "match ICMPv6 neighbor discovery source Ethernet" 2443 " link-layer address option", 2444 .priv = PRIV_ITEM 2445 (ICMP6_ND_OPT_SLA_ETH, 2446 sizeof(struct rte_flow_item_icmp6_nd_opt_sla_eth)), 2447 .next = NEXT(item_icmp6_nd_opt_sla_eth), 2448 .call = parse_vc, 2449 }, 2450 [ITEM_ICMP6_ND_OPT_SLA_ETH_SLA] = { 2451 .name = "sla", 2452 .help = "source Ethernet LLA", 2453 .next = NEXT(item_icmp6_nd_opt_sla_eth, NEXT_ENTRY(MAC_ADDR), 2454 item_param), 2455 .args = ARGS(ARGS_ENTRY_HTON 2456 (struct rte_flow_item_icmp6_nd_opt_sla_eth, sla)), 2457 }, 2458 [ITEM_ICMP6_ND_OPT_TLA_ETH] = { 2459 .name = "icmp6_nd_opt_tla_eth", 2460 .help = "match ICMPv6 neighbor discovery target Ethernet" 2461 " link-layer address option", 2462 .priv = PRIV_ITEM 2463 (ICMP6_ND_OPT_TLA_ETH, 2464 sizeof(struct rte_flow_item_icmp6_nd_opt_tla_eth)), 2465 .next = NEXT(item_icmp6_nd_opt_tla_eth), 2466 .call = parse_vc, 2467 }, 2468 [ITEM_ICMP6_ND_OPT_TLA_ETH_TLA] = { 2469 .name = "tla", 2470 .help = "target Ethernet LLA", 2471 .next = NEXT(item_icmp6_nd_opt_tla_eth, NEXT_ENTRY(MAC_ADDR), 2472 item_param), 2473 .args = ARGS(ARGS_ENTRY_HTON 2474 (struct rte_flow_item_icmp6_nd_opt_tla_eth, tla)), 2475 }, 2476 [ITEM_META] = { 2477 .name = "meta", 2478 .help = "match metadata header", 2479 .priv = PRIV_ITEM(META, sizeof(struct rte_flow_item_meta)), 2480 .next = NEXT(item_meta), 2481 .call = parse_vc, 2482 }, 2483 [ITEM_META_DATA] = { 2484 .name = "data", 2485 .help = "metadata value", 2486 .next = NEXT(item_meta, NEXT_ENTRY(UNSIGNED), item_param), 2487 .args = ARGS(ARGS_ENTRY_MASK(struct rte_flow_item_meta, 2488 data, "\xff\xff\xff\xff")), 2489 }, 2490 [ITEM_GRE_KEY] = { 2491 .name = "gre_key", 2492 .help = "match GRE key", 2493 .priv = PRIV_ITEM(GRE_KEY, sizeof(rte_be32_t)), 2494 .next = NEXT(item_gre_key), 2495 .call = parse_vc, 2496 }, 2497 [ITEM_GRE_KEY_VALUE] = { 2498 .name = "value", 2499 .help = "key value", 2500 .next = NEXT(item_gre_key, NEXT_ENTRY(UNSIGNED), item_param), 2501 .args = ARGS(ARG_ENTRY_HTON(rte_be32_t)), 2502 }, 2503 [ITEM_GTP_PSC] = { 2504 .name = "gtp_psc", 2505 .help = "match GTP extension header with type 0x85", 2506 .priv = PRIV_ITEM(GTP_PSC, 2507 sizeof(struct rte_flow_item_gtp_psc)), 2508 .next = NEXT(item_gtp_psc), 2509 .call = parse_vc, 2510 }, 2511 [ITEM_GTP_PSC_QFI] = { 2512 .name = "qfi", 2513 .help = "QoS flow identifier", 2514 .next = NEXT(item_gtp_psc, NEXT_ENTRY(UNSIGNED), item_param), 2515 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gtp_psc, 2516 qfi)), 2517 }, 2518 [ITEM_GTP_PSC_PDU_T] = { 2519 .name = "pdu_t", 2520 .help = "PDU type", 2521 .next = NEXT(item_gtp_psc, NEXT_ENTRY(UNSIGNED), item_param), 2522 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gtp_psc, 2523 pdu_type)), 2524 }, 2525 [ITEM_PPPOES] = { 2526 .name = "pppoes", 2527 .help = "match PPPoE session header", 2528 .priv = PRIV_ITEM(PPPOES, sizeof(struct rte_flow_item_pppoe)), 2529 .next = NEXT(item_pppoes), 2530 .call = parse_vc, 2531 }, 2532 [ITEM_PPPOED] = { 2533 .name = "pppoed", 2534 .help = "match PPPoE discovery header", 2535 .priv = PRIV_ITEM(PPPOED, sizeof(struct rte_flow_item_pppoe)), 2536 .next = NEXT(item_pppoed), 2537 .call = parse_vc, 2538 }, 2539 [ITEM_PPPOE_SEID] = { 2540 .name = "seid", 2541 .help = "session identifier", 2542 .next = NEXT(item_pppoes, NEXT_ENTRY(UNSIGNED), item_param), 2543 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_pppoe, 2544 session_id)), 2545 }, 2546 [ITEM_PPPOE_PROTO_ID] = { 2547 .name = "proto_id", 2548 .help = "match PPPoE session protocol identifier", 2549 .priv = PRIV_ITEM(PPPOE_PROTO_ID, 2550 sizeof(struct rte_flow_item_pppoe_proto_id)), 2551 .next = NEXT(item_pppoe_proto_id), 2552 .call = parse_vc, 2553 }, 2554 [ITEM_HIGIG2] = { 2555 .name = "higig2", 2556 .help = "matches higig2 header", 2557 .priv = PRIV_ITEM(HIGIG2, 2558 sizeof(struct rte_flow_item_higig2_hdr)), 2559 .next = NEXT(item_higig2), 2560 .call = parse_vc, 2561 }, 2562 [ITEM_HIGIG2_CLASSIFICATION] = { 2563 .name = "classification", 2564 .help = "matches classification of higig2 header", 2565 .next = NEXT(item_higig2, NEXT_ENTRY(UNSIGNED), item_param), 2566 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_higig2_hdr, 2567 hdr.ppt1.classification)), 2568 }, 2569 [ITEM_HIGIG2_VID] = { 2570 .name = "vid", 2571 .help = "matches vid of higig2 header", 2572 .next = NEXT(item_higig2, NEXT_ENTRY(UNSIGNED), item_param), 2573 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_higig2_hdr, 2574 hdr.ppt1.vid)), 2575 }, 2576 [ITEM_TAG] = { 2577 .name = "tag", 2578 .help = "match tag value", 2579 .priv = PRIV_ITEM(TAG, sizeof(struct rte_flow_item_tag)), 2580 .next = NEXT(item_tag), 2581 .call = parse_vc, 2582 }, 2583 [ITEM_TAG_DATA] = { 2584 .name = "data", 2585 .help = "tag value to match", 2586 .next = NEXT(item_tag, NEXT_ENTRY(UNSIGNED), item_param), 2587 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_tag, data)), 2588 }, 2589 [ITEM_TAG_INDEX] = { 2590 .name = "index", 2591 .help = "index of tag array to match", 2592 .next = NEXT(item_tag, NEXT_ENTRY(UNSIGNED), 2593 NEXT_ENTRY(ITEM_PARAM_IS)), 2594 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_tag, index)), 2595 }, 2596 /* Validate/create actions. */ 2597 [ACTIONS] = { 2598 .name = "actions", 2599 .help = "submit a list of associated actions", 2600 .next = NEXT(next_action), 2601 .call = parse_vc, 2602 }, 2603 [ACTION_NEXT] = { 2604 .name = "/", 2605 .help = "specify next action", 2606 .next = NEXT(next_action), 2607 }, 2608 [ACTION_END] = { 2609 .name = "end", 2610 .help = "end list of actions", 2611 .priv = PRIV_ACTION(END, 0), 2612 .call = parse_vc, 2613 }, 2614 [ACTION_VOID] = { 2615 .name = "void", 2616 .help = "no-op action", 2617 .priv = PRIV_ACTION(VOID, 0), 2618 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)), 2619 .call = parse_vc, 2620 }, 2621 [ACTION_PASSTHRU] = { 2622 .name = "passthru", 2623 .help = "let subsequent rule process matched packets", 2624 .priv = PRIV_ACTION(PASSTHRU, 0), 2625 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)), 2626 .call = parse_vc, 2627 }, 2628 [ACTION_JUMP] = { 2629 .name = "jump", 2630 .help = "redirect traffic to a given group", 2631 .priv = PRIV_ACTION(JUMP, sizeof(struct rte_flow_action_jump)), 2632 .next = NEXT(action_jump), 2633 .call = parse_vc, 2634 }, 2635 [ACTION_JUMP_GROUP] = { 2636 .name = "group", 2637 .help = "group to redirect traffic to", 2638 .next = NEXT(action_jump, NEXT_ENTRY(UNSIGNED)), 2639 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_jump, group)), 2640 .call = parse_vc_conf, 2641 }, 2642 [ACTION_MARK] = { 2643 .name = "mark", 2644 .help = "attach 32 bit value to packets", 2645 .priv = PRIV_ACTION(MARK, sizeof(struct rte_flow_action_mark)), 2646 .next = NEXT(action_mark), 2647 .call = parse_vc, 2648 }, 2649 [ACTION_MARK_ID] = { 2650 .name = "id", 2651 .help = "32 bit value to return with packets", 2652 .next = NEXT(action_mark, NEXT_ENTRY(UNSIGNED)), 2653 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_mark, id)), 2654 .call = parse_vc_conf, 2655 }, 2656 [ACTION_FLAG] = { 2657 .name = "flag", 2658 .help = "flag packets", 2659 .priv = PRIV_ACTION(FLAG, 0), 2660 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)), 2661 .call = parse_vc, 2662 }, 2663 [ACTION_QUEUE] = { 2664 .name = "queue", 2665 .help = "assign packets to a given queue index", 2666 .priv = PRIV_ACTION(QUEUE, 2667 sizeof(struct rte_flow_action_queue)), 2668 .next = NEXT(action_queue), 2669 .call = parse_vc, 2670 }, 2671 [ACTION_QUEUE_INDEX] = { 2672 .name = "index", 2673 .help = "queue index to use", 2674 .next = NEXT(action_queue, NEXT_ENTRY(UNSIGNED)), 2675 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_queue, index)), 2676 .call = parse_vc_conf, 2677 }, 2678 [ACTION_DROP] = { 2679 .name = "drop", 2680 .help = "drop packets (note: passthru has priority)", 2681 .priv = PRIV_ACTION(DROP, 0), 2682 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)), 2683 .call = parse_vc, 2684 }, 2685 [ACTION_COUNT] = { 2686 .name = "count", 2687 .help = "enable counters for this rule", 2688 .priv = PRIV_ACTION(COUNT, 2689 sizeof(struct rte_flow_action_count)), 2690 .next = NEXT(action_count), 2691 .call = parse_vc, 2692 }, 2693 [ACTION_COUNT_ID] = { 2694 .name = "identifier", 2695 .help = "counter identifier to use", 2696 .next = NEXT(action_count, NEXT_ENTRY(UNSIGNED)), 2697 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_count, id)), 2698 .call = parse_vc_conf, 2699 }, 2700 [ACTION_COUNT_SHARED] = { 2701 .name = "shared", 2702 .help = "shared counter", 2703 .next = NEXT(action_count, NEXT_ENTRY(BOOLEAN)), 2704 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_count, 2705 shared, 1)), 2706 .call = parse_vc_conf, 2707 }, 2708 [ACTION_RSS] = { 2709 .name = "rss", 2710 .help = "spread packets among several queues", 2711 .priv = PRIV_ACTION(RSS, sizeof(struct action_rss_data)), 2712 .next = NEXT(action_rss), 2713 .call = parse_vc_action_rss, 2714 }, 2715 [ACTION_RSS_FUNC] = { 2716 .name = "func", 2717 .help = "RSS hash function to apply", 2718 .next = NEXT(action_rss, 2719 NEXT_ENTRY(ACTION_RSS_FUNC_DEFAULT, 2720 ACTION_RSS_FUNC_TOEPLITZ, 2721 ACTION_RSS_FUNC_SIMPLE_XOR, 2722 ACTION_RSS_FUNC_SYMMETRIC_TOEPLITZ)), 2723 }, 2724 [ACTION_RSS_FUNC_DEFAULT] = { 2725 .name = "default", 2726 .help = "default hash function", 2727 .call = parse_vc_action_rss_func, 2728 }, 2729 [ACTION_RSS_FUNC_TOEPLITZ] = { 2730 .name = "toeplitz", 2731 .help = "Toeplitz hash function", 2732 .call = parse_vc_action_rss_func, 2733 }, 2734 [ACTION_RSS_FUNC_SIMPLE_XOR] = { 2735 .name = "simple_xor", 2736 .help = "simple XOR hash function", 2737 .call = parse_vc_action_rss_func, 2738 }, 2739 [ACTION_RSS_FUNC_SYMMETRIC_TOEPLITZ] = { 2740 .name = "symmetric_toeplitz", 2741 .help = "Symmetric Toeplitz hash function", 2742 .call = parse_vc_action_rss_func, 2743 }, 2744 [ACTION_RSS_LEVEL] = { 2745 .name = "level", 2746 .help = "encapsulation level for \"types\"", 2747 .next = NEXT(action_rss, NEXT_ENTRY(UNSIGNED)), 2748 .args = ARGS(ARGS_ENTRY_ARB 2749 (offsetof(struct action_rss_data, conf) + 2750 offsetof(struct rte_flow_action_rss, level), 2751 sizeof(((struct rte_flow_action_rss *)0)-> 2752 level))), 2753 }, 2754 [ACTION_RSS_TYPES] = { 2755 .name = "types", 2756 .help = "specific RSS hash types", 2757 .next = NEXT(action_rss, NEXT_ENTRY(ACTION_RSS_TYPE)), 2758 }, 2759 [ACTION_RSS_TYPE] = { 2760 .name = "{type}", 2761 .help = "RSS hash type", 2762 .call = parse_vc_action_rss_type, 2763 .comp = comp_vc_action_rss_type, 2764 }, 2765 [ACTION_RSS_KEY] = { 2766 .name = "key", 2767 .help = "RSS hash key", 2768 .next = NEXT(action_rss, NEXT_ENTRY(HEX)), 2769 .args = ARGS(ARGS_ENTRY_ARB(0, 0), 2770 ARGS_ENTRY_ARB 2771 (offsetof(struct action_rss_data, conf) + 2772 offsetof(struct rte_flow_action_rss, key_len), 2773 sizeof(((struct rte_flow_action_rss *)0)-> 2774 key_len)), 2775 ARGS_ENTRY(struct action_rss_data, key)), 2776 }, 2777 [ACTION_RSS_KEY_LEN] = { 2778 .name = "key_len", 2779 .help = "RSS hash key length in bytes", 2780 .next = NEXT(action_rss, NEXT_ENTRY(UNSIGNED)), 2781 .args = ARGS(ARGS_ENTRY_ARB_BOUNDED 2782 (offsetof(struct action_rss_data, conf) + 2783 offsetof(struct rte_flow_action_rss, key_len), 2784 sizeof(((struct rte_flow_action_rss *)0)-> 2785 key_len), 2786 0, 2787 RSS_HASH_KEY_LENGTH)), 2788 }, 2789 [ACTION_RSS_QUEUES] = { 2790 .name = "queues", 2791 .help = "queue indices to use", 2792 .next = NEXT(action_rss, NEXT_ENTRY(ACTION_RSS_QUEUE)), 2793 .call = parse_vc_conf, 2794 }, 2795 [ACTION_RSS_QUEUE] = { 2796 .name = "{queue}", 2797 .help = "queue index", 2798 .call = parse_vc_action_rss_queue, 2799 .comp = comp_vc_action_rss_queue, 2800 }, 2801 [ACTION_PF] = { 2802 .name = "pf", 2803 .help = "direct traffic to physical function", 2804 .priv = PRIV_ACTION(PF, 0), 2805 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)), 2806 .call = parse_vc, 2807 }, 2808 [ACTION_VF] = { 2809 .name = "vf", 2810 .help = "direct traffic to a virtual function ID", 2811 .priv = PRIV_ACTION(VF, sizeof(struct rte_flow_action_vf)), 2812 .next = NEXT(action_vf), 2813 .call = parse_vc, 2814 }, 2815 [ACTION_VF_ORIGINAL] = { 2816 .name = "original", 2817 .help = "use original VF ID if possible", 2818 .next = NEXT(action_vf, NEXT_ENTRY(BOOLEAN)), 2819 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_vf, 2820 original, 1)), 2821 .call = parse_vc_conf, 2822 }, 2823 [ACTION_VF_ID] = { 2824 .name = "id", 2825 .help = "VF ID", 2826 .next = NEXT(action_vf, NEXT_ENTRY(UNSIGNED)), 2827 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_vf, id)), 2828 .call = parse_vc_conf, 2829 }, 2830 [ACTION_PHY_PORT] = { 2831 .name = "phy_port", 2832 .help = "direct packets to physical port index", 2833 .priv = PRIV_ACTION(PHY_PORT, 2834 sizeof(struct rte_flow_action_phy_port)), 2835 .next = NEXT(action_phy_port), 2836 .call = parse_vc, 2837 }, 2838 [ACTION_PHY_PORT_ORIGINAL] = { 2839 .name = "original", 2840 .help = "use original port index if possible", 2841 .next = NEXT(action_phy_port, NEXT_ENTRY(BOOLEAN)), 2842 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_phy_port, 2843 original, 1)), 2844 .call = parse_vc_conf, 2845 }, 2846 [ACTION_PHY_PORT_INDEX] = { 2847 .name = "index", 2848 .help = "physical port index", 2849 .next = NEXT(action_phy_port, NEXT_ENTRY(UNSIGNED)), 2850 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_phy_port, 2851 index)), 2852 .call = parse_vc_conf, 2853 }, 2854 [ACTION_PORT_ID] = { 2855 .name = "port_id", 2856 .help = "direct matching traffic to a given DPDK port ID", 2857 .priv = PRIV_ACTION(PORT_ID, 2858 sizeof(struct rte_flow_action_port_id)), 2859 .next = NEXT(action_port_id), 2860 .call = parse_vc, 2861 }, 2862 [ACTION_PORT_ID_ORIGINAL] = { 2863 .name = "original", 2864 .help = "use original DPDK port ID if possible", 2865 .next = NEXT(action_port_id, NEXT_ENTRY(BOOLEAN)), 2866 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_port_id, 2867 original, 1)), 2868 .call = parse_vc_conf, 2869 }, 2870 [ACTION_PORT_ID_ID] = { 2871 .name = "id", 2872 .help = "DPDK port ID", 2873 .next = NEXT(action_port_id, NEXT_ENTRY(UNSIGNED)), 2874 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_port_id, id)), 2875 .call = parse_vc_conf, 2876 }, 2877 [ACTION_METER] = { 2878 .name = "meter", 2879 .help = "meter the directed packets at given id", 2880 .priv = PRIV_ACTION(METER, 2881 sizeof(struct rte_flow_action_meter)), 2882 .next = NEXT(action_meter), 2883 .call = parse_vc, 2884 }, 2885 [ACTION_METER_ID] = { 2886 .name = "mtr_id", 2887 .help = "meter id to use", 2888 .next = NEXT(action_meter, NEXT_ENTRY(UNSIGNED)), 2889 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_meter, mtr_id)), 2890 .call = parse_vc_conf, 2891 }, 2892 [ACTION_OF_SET_MPLS_TTL] = { 2893 .name = "of_set_mpls_ttl", 2894 .help = "OpenFlow's OFPAT_SET_MPLS_TTL", 2895 .priv = PRIV_ACTION 2896 (OF_SET_MPLS_TTL, 2897 sizeof(struct rte_flow_action_of_set_mpls_ttl)), 2898 .next = NEXT(action_of_set_mpls_ttl), 2899 .call = parse_vc, 2900 }, 2901 [ACTION_OF_SET_MPLS_TTL_MPLS_TTL] = { 2902 .name = "mpls_ttl", 2903 .help = "MPLS TTL", 2904 .next = NEXT(action_of_set_mpls_ttl, NEXT_ENTRY(UNSIGNED)), 2905 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_of_set_mpls_ttl, 2906 mpls_ttl)), 2907 .call = parse_vc_conf, 2908 }, 2909 [ACTION_OF_DEC_MPLS_TTL] = { 2910 .name = "of_dec_mpls_ttl", 2911 .help = "OpenFlow's OFPAT_DEC_MPLS_TTL", 2912 .priv = PRIV_ACTION(OF_DEC_MPLS_TTL, 0), 2913 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)), 2914 .call = parse_vc, 2915 }, 2916 [ACTION_OF_SET_NW_TTL] = { 2917 .name = "of_set_nw_ttl", 2918 .help = "OpenFlow's OFPAT_SET_NW_TTL", 2919 .priv = PRIV_ACTION 2920 (OF_SET_NW_TTL, 2921 sizeof(struct rte_flow_action_of_set_nw_ttl)), 2922 .next = NEXT(action_of_set_nw_ttl), 2923 .call = parse_vc, 2924 }, 2925 [ACTION_OF_SET_NW_TTL_NW_TTL] = { 2926 .name = "nw_ttl", 2927 .help = "IP TTL", 2928 .next = NEXT(action_of_set_nw_ttl, NEXT_ENTRY(UNSIGNED)), 2929 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_of_set_nw_ttl, 2930 nw_ttl)), 2931 .call = parse_vc_conf, 2932 }, 2933 [ACTION_OF_DEC_NW_TTL] = { 2934 .name = "of_dec_nw_ttl", 2935 .help = "OpenFlow's OFPAT_DEC_NW_TTL", 2936 .priv = PRIV_ACTION(OF_DEC_NW_TTL, 0), 2937 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)), 2938 .call = parse_vc, 2939 }, 2940 [ACTION_OF_COPY_TTL_OUT] = { 2941 .name = "of_copy_ttl_out", 2942 .help = "OpenFlow's OFPAT_COPY_TTL_OUT", 2943 .priv = PRIV_ACTION(OF_COPY_TTL_OUT, 0), 2944 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)), 2945 .call = parse_vc, 2946 }, 2947 [ACTION_OF_COPY_TTL_IN] = { 2948 .name = "of_copy_ttl_in", 2949 .help = "OpenFlow's OFPAT_COPY_TTL_IN", 2950 .priv = PRIV_ACTION(OF_COPY_TTL_IN, 0), 2951 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)), 2952 .call = parse_vc, 2953 }, 2954 [ACTION_OF_POP_VLAN] = { 2955 .name = "of_pop_vlan", 2956 .help = "OpenFlow's OFPAT_POP_VLAN", 2957 .priv = PRIV_ACTION(OF_POP_VLAN, 0), 2958 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)), 2959 .call = parse_vc, 2960 }, 2961 [ACTION_OF_PUSH_VLAN] = { 2962 .name = "of_push_vlan", 2963 .help = "OpenFlow's OFPAT_PUSH_VLAN", 2964 .priv = PRIV_ACTION 2965 (OF_PUSH_VLAN, 2966 sizeof(struct rte_flow_action_of_push_vlan)), 2967 .next = NEXT(action_of_push_vlan), 2968 .call = parse_vc, 2969 }, 2970 [ACTION_OF_PUSH_VLAN_ETHERTYPE] = { 2971 .name = "ethertype", 2972 .help = "EtherType", 2973 .next = NEXT(action_of_push_vlan, NEXT_ENTRY(UNSIGNED)), 2974 .args = ARGS(ARGS_ENTRY_HTON 2975 (struct rte_flow_action_of_push_vlan, 2976 ethertype)), 2977 .call = parse_vc_conf, 2978 }, 2979 [ACTION_OF_SET_VLAN_VID] = { 2980 .name = "of_set_vlan_vid", 2981 .help = "OpenFlow's OFPAT_SET_VLAN_VID", 2982 .priv = PRIV_ACTION 2983 (OF_SET_VLAN_VID, 2984 sizeof(struct rte_flow_action_of_set_vlan_vid)), 2985 .next = NEXT(action_of_set_vlan_vid), 2986 .call = parse_vc, 2987 }, 2988 [ACTION_OF_SET_VLAN_VID_VLAN_VID] = { 2989 .name = "vlan_vid", 2990 .help = "VLAN id", 2991 .next = NEXT(action_of_set_vlan_vid, NEXT_ENTRY(UNSIGNED)), 2992 .args = ARGS(ARGS_ENTRY_HTON 2993 (struct rte_flow_action_of_set_vlan_vid, 2994 vlan_vid)), 2995 .call = parse_vc_conf, 2996 }, 2997 [ACTION_OF_SET_VLAN_PCP] = { 2998 .name = "of_set_vlan_pcp", 2999 .help = "OpenFlow's OFPAT_SET_VLAN_PCP", 3000 .priv = PRIV_ACTION 3001 (OF_SET_VLAN_PCP, 3002 sizeof(struct rte_flow_action_of_set_vlan_pcp)), 3003 .next = NEXT(action_of_set_vlan_pcp), 3004 .call = parse_vc, 3005 }, 3006 [ACTION_OF_SET_VLAN_PCP_VLAN_PCP] = { 3007 .name = "vlan_pcp", 3008 .help = "VLAN priority", 3009 .next = NEXT(action_of_set_vlan_pcp, NEXT_ENTRY(UNSIGNED)), 3010 .args = ARGS(ARGS_ENTRY_HTON 3011 (struct rte_flow_action_of_set_vlan_pcp, 3012 vlan_pcp)), 3013 .call = parse_vc_conf, 3014 }, 3015 [ACTION_OF_POP_MPLS] = { 3016 .name = "of_pop_mpls", 3017 .help = "OpenFlow's OFPAT_POP_MPLS", 3018 .priv = PRIV_ACTION(OF_POP_MPLS, 3019 sizeof(struct rte_flow_action_of_pop_mpls)), 3020 .next = NEXT(action_of_pop_mpls), 3021 .call = parse_vc, 3022 }, 3023 [ACTION_OF_POP_MPLS_ETHERTYPE] = { 3024 .name = "ethertype", 3025 .help = "EtherType", 3026 .next = NEXT(action_of_pop_mpls, NEXT_ENTRY(UNSIGNED)), 3027 .args = ARGS(ARGS_ENTRY_HTON 3028 (struct rte_flow_action_of_pop_mpls, 3029 ethertype)), 3030 .call = parse_vc_conf, 3031 }, 3032 [ACTION_OF_PUSH_MPLS] = { 3033 .name = "of_push_mpls", 3034 .help = "OpenFlow's OFPAT_PUSH_MPLS", 3035 .priv = PRIV_ACTION 3036 (OF_PUSH_MPLS, 3037 sizeof(struct rte_flow_action_of_push_mpls)), 3038 .next = NEXT(action_of_push_mpls), 3039 .call = parse_vc, 3040 }, 3041 [ACTION_OF_PUSH_MPLS_ETHERTYPE] = { 3042 .name = "ethertype", 3043 .help = "EtherType", 3044 .next = NEXT(action_of_push_mpls, NEXT_ENTRY(UNSIGNED)), 3045 .args = ARGS(ARGS_ENTRY_HTON 3046 (struct rte_flow_action_of_push_mpls, 3047 ethertype)), 3048 .call = parse_vc_conf, 3049 }, 3050 [ACTION_VXLAN_ENCAP] = { 3051 .name = "vxlan_encap", 3052 .help = "VXLAN encapsulation, uses configuration set by \"set" 3053 " vxlan\"", 3054 .priv = PRIV_ACTION(VXLAN_ENCAP, 3055 sizeof(struct action_vxlan_encap_data)), 3056 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)), 3057 .call = parse_vc_action_vxlan_encap, 3058 }, 3059 [ACTION_VXLAN_DECAP] = { 3060 .name = "vxlan_decap", 3061 .help = "Performs a decapsulation action by stripping all" 3062 " headers of the VXLAN tunnel network overlay from the" 3063 " matched flow.", 3064 .priv = PRIV_ACTION(VXLAN_DECAP, 0), 3065 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)), 3066 .call = parse_vc, 3067 }, 3068 [ACTION_NVGRE_ENCAP] = { 3069 .name = "nvgre_encap", 3070 .help = "NVGRE encapsulation, uses configuration set by \"set" 3071 " nvgre\"", 3072 .priv = PRIV_ACTION(NVGRE_ENCAP, 3073 sizeof(struct action_nvgre_encap_data)), 3074 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)), 3075 .call = parse_vc_action_nvgre_encap, 3076 }, 3077 [ACTION_NVGRE_DECAP] = { 3078 .name = "nvgre_decap", 3079 .help = "Performs a decapsulation action by stripping all" 3080 " headers of the NVGRE tunnel network overlay from the" 3081 " matched flow.", 3082 .priv = PRIV_ACTION(NVGRE_DECAP, 0), 3083 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)), 3084 .call = parse_vc, 3085 }, 3086 [ACTION_L2_ENCAP] = { 3087 .name = "l2_encap", 3088 .help = "l2 encap, uses configuration set by" 3089 " \"set l2_encap\"", 3090 .priv = PRIV_ACTION(RAW_ENCAP, 3091 sizeof(struct action_raw_encap_data)), 3092 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)), 3093 .call = parse_vc_action_l2_encap, 3094 }, 3095 [ACTION_L2_DECAP] = { 3096 .name = "l2_decap", 3097 .help = "l2 decap, uses configuration set by" 3098 " \"set l2_decap\"", 3099 .priv = PRIV_ACTION(RAW_DECAP, 3100 sizeof(struct action_raw_decap_data)), 3101 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)), 3102 .call = parse_vc_action_l2_decap, 3103 }, 3104 [ACTION_MPLSOGRE_ENCAP] = { 3105 .name = "mplsogre_encap", 3106 .help = "mplsogre encapsulation, uses configuration set by" 3107 " \"set mplsogre_encap\"", 3108 .priv = PRIV_ACTION(RAW_ENCAP, 3109 sizeof(struct action_raw_encap_data)), 3110 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)), 3111 .call = parse_vc_action_mplsogre_encap, 3112 }, 3113 [ACTION_MPLSOGRE_DECAP] = { 3114 .name = "mplsogre_decap", 3115 .help = "mplsogre decapsulation, uses configuration set by" 3116 " \"set mplsogre_decap\"", 3117 .priv = PRIV_ACTION(RAW_DECAP, 3118 sizeof(struct action_raw_decap_data)), 3119 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)), 3120 .call = parse_vc_action_mplsogre_decap, 3121 }, 3122 [ACTION_MPLSOUDP_ENCAP] = { 3123 .name = "mplsoudp_encap", 3124 .help = "mplsoudp encapsulation, uses configuration set by" 3125 " \"set mplsoudp_encap\"", 3126 .priv = PRIV_ACTION(RAW_ENCAP, 3127 sizeof(struct action_raw_encap_data)), 3128 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)), 3129 .call = parse_vc_action_mplsoudp_encap, 3130 }, 3131 [ACTION_MPLSOUDP_DECAP] = { 3132 .name = "mplsoudp_decap", 3133 .help = "mplsoudp decapsulation, uses configuration set by" 3134 " \"set mplsoudp_decap\"", 3135 .priv = PRIV_ACTION(RAW_DECAP, 3136 sizeof(struct action_raw_decap_data)), 3137 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)), 3138 .call = parse_vc_action_mplsoudp_decap, 3139 }, 3140 [ACTION_SET_IPV4_SRC] = { 3141 .name = "set_ipv4_src", 3142 .help = "Set a new IPv4 source address in the outermost" 3143 " IPv4 header", 3144 .priv = PRIV_ACTION(SET_IPV4_SRC, 3145 sizeof(struct rte_flow_action_set_ipv4)), 3146 .next = NEXT(action_set_ipv4_src), 3147 .call = parse_vc, 3148 }, 3149 [ACTION_SET_IPV4_SRC_IPV4_SRC] = { 3150 .name = "ipv4_addr", 3151 .help = "new IPv4 source address to set", 3152 .next = NEXT(action_set_ipv4_src, NEXT_ENTRY(IPV4_ADDR)), 3153 .args = ARGS(ARGS_ENTRY_HTON 3154 (struct rte_flow_action_set_ipv4, ipv4_addr)), 3155 .call = parse_vc_conf, 3156 }, 3157 [ACTION_SET_IPV4_DST] = { 3158 .name = "set_ipv4_dst", 3159 .help = "Set a new IPv4 destination address in the outermost" 3160 " IPv4 header", 3161 .priv = PRIV_ACTION(SET_IPV4_DST, 3162 sizeof(struct rte_flow_action_set_ipv4)), 3163 .next = NEXT(action_set_ipv4_dst), 3164 .call = parse_vc, 3165 }, 3166 [ACTION_SET_IPV4_DST_IPV4_DST] = { 3167 .name = "ipv4_addr", 3168 .help = "new IPv4 destination address to set", 3169 .next = NEXT(action_set_ipv4_dst, NEXT_ENTRY(IPV4_ADDR)), 3170 .args = ARGS(ARGS_ENTRY_HTON 3171 (struct rte_flow_action_set_ipv4, ipv4_addr)), 3172 .call = parse_vc_conf, 3173 }, 3174 [ACTION_SET_IPV6_SRC] = { 3175 .name = "set_ipv6_src", 3176 .help = "Set a new IPv6 source address in the outermost" 3177 " IPv6 header", 3178 .priv = PRIV_ACTION(SET_IPV6_SRC, 3179 sizeof(struct rte_flow_action_set_ipv6)), 3180 .next = NEXT(action_set_ipv6_src), 3181 .call = parse_vc, 3182 }, 3183 [ACTION_SET_IPV6_SRC_IPV6_SRC] = { 3184 .name = "ipv6_addr", 3185 .help = "new IPv6 source address to set", 3186 .next = NEXT(action_set_ipv6_src, NEXT_ENTRY(IPV6_ADDR)), 3187 .args = ARGS(ARGS_ENTRY_HTON 3188 (struct rte_flow_action_set_ipv6, ipv6_addr)), 3189 .call = parse_vc_conf, 3190 }, 3191 [ACTION_SET_IPV6_DST] = { 3192 .name = "set_ipv6_dst", 3193 .help = "Set a new IPv6 destination address in the outermost" 3194 " IPv6 header", 3195 .priv = PRIV_ACTION(SET_IPV6_DST, 3196 sizeof(struct rte_flow_action_set_ipv6)), 3197 .next = NEXT(action_set_ipv6_dst), 3198 .call = parse_vc, 3199 }, 3200 [ACTION_SET_IPV6_DST_IPV6_DST] = { 3201 .name = "ipv6_addr", 3202 .help = "new IPv6 destination address to set", 3203 .next = NEXT(action_set_ipv6_dst, NEXT_ENTRY(IPV6_ADDR)), 3204 .args = ARGS(ARGS_ENTRY_HTON 3205 (struct rte_flow_action_set_ipv6, ipv6_addr)), 3206 .call = parse_vc_conf, 3207 }, 3208 [ACTION_SET_TP_SRC] = { 3209 .name = "set_tp_src", 3210 .help = "set a new source port number in the outermost" 3211 " TCP/UDP header", 3212 .priv = PRIV_ACTION(SET_TP_SRC, 3213 sizeof(struct rte_flow_action_set_tp)), 3214 .next = NEXT(action_set_tp_src), 3215 .call = parse_vc, 3216 }, 3217 [ACTION_SET_TP_SRC_TP_SRC] = { 3218 .name = "port", 3219 .help = "new source port number to set", 3220 .next = NEXT(action_set_tp_src, NEXT_ENTRY(UNSIGNED)), 3221 .args = ARGS(ARGS_ENTRY_HTON 3222 (struct rte_flow_action_set_tp, port)), 3223 .call = parse_vc_conf, 3224 }, 3225 [ACTION_SET_TP_DST] = { 3226 .name = "set_tp_dst", 3227 .help = "set a new destination port number in the outermost" 3228 " TCP/UDP header", 3229 .priv = PRIV_ACTION(SET_TP_DST, 3230 sizeof(struct rte_flow_action_set_tp)), 3231 .next = NEXT(action_set_tp_dst), 3232 .call = parse_vc, 3233 }, 3234 [ACTION_SET_TP_DST_TP_DST] = { 3235 .name = "port", 3236 .help = "new destination port number to set", 3237 .next = NEXT(action_set_tp_dst, NEXT_ENTRY(UNSIGNED)), 3238 .args = ARGS(ARGS_ENTRY_HTON 3239 (struct rte_flow_action_set_tp, port)), 3240 .call = parse_vc_conf, 3241 }, 3242 [ACTION_MAC_SWAP] = { 3243 .name = "mac_swap", 3244 .help = "Swap the source and destination MAC addresses" 3245 " in the outermost Ethernet header", 3246 .priv = PRIV_ACTION(MAC_SWAP, 0), 3247 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)), 3248 .call = parse_vc, 3249 }, 3250 [ACTION_DEC_TTL] = { 3251 .name = "dec_ttl", 3252 .help = "decrease network TTL if available", 3253 .priv = PRIV_ACTION(DEC_TTL, 0), 3254 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)), 3255 .call = parse_vc, 3256 }, 3257 [ACTION_SET_TTL] = { 3258 .name = "set_ttl", 3259 .help = "set ttl value", 3260 .priv = PRIV_ACTION(SET_TTL, 3261 sizeof(struct rte_flow_action_set_ttl)), 3262 .next = NEXT(action_set_ttl), 3263 .call = parse_vc, 3264 }, 3265 [ACTION_SET_TTL_TTL] = { 3266 .name = "ttl_value", 3267 .help = "new ttl value to set", 3268 .next = NEXT(action_set_ttl, NEXT_ENTRY(UNSIGNED)), 3269 .args = ARGS(ARGS_ENTRY_HTON 3270 (struct rte_flow_action_set_ttl, ttl_value)), 3271 .call = parse_vc_conf, 3272 }, 3273 [ACTION_SET_MAC_SRC] = { 3274 .name = "set_mac_src", 3275 .help = "set source mac address", 3276 .priv = PRIV_ACTION(SET_MAC_SRC, 3277 sizeof(struct rte_flow_action_set_mac)), 3278 .next = NEXT(action_set_mac_src), 3279 .call = parse_vc, 3280 }, 3281 [ACTION_SET_MAC_SRC_MAC_SRC] = { 3282 .name = "mac_addr", 3283 .help = "new source mac address", 3284 .next = NEXT(action_set_mac_src, NEXT_ENTRY(MAC_ADDR)), 3285 .args = ARGS(ARGS_ENTRY_HTON 3286 (struct rte_flow_action_set_mac, mac_addr)), 3287 .call = parse_vc_conf, 3288 }, 3289 [ACTION_SET_MAC_DST] = { 3290 .name = "set_mac_dst", 3291 .help = "set destination mac address", 3292 .priv = PRIV_ACTION(SET_MAC_DST, 3293 sizeof(struct rte_flow_action_set_mac)), 3294 .next = NEXT(action_set_mac_dst), 3295 .call = parse_vc, 3296 }, 3297 [ACTION_SET_MAC_DST_MAC_DST] = { 3298 .name = "mac_addr", 3299 .help = "new destination mac address to set", 3300 .next = NEXT(action_set_mac_dst, NEXT_ENTRY(MAC_ADDR)), 3301 .args = ARGS(ARGS_ENTRY_HTON 3302 (struct rte_flow_action_set_mac, mac_addr)), 3303 .call = parse_vc_conf, 3304 }, 3305 [ACTION_INC_TCP_SEQ] = { 3306 .name = "inc_tcp_seq", 3307 .help = "increase TCP sequence number", 3308 .priv = PRIV_ACTION(INC_TCP_SEQ, sizeof(rte_be32_t)), 3309 .next = NEXT(action_inc_tcp_seq), 3310 .call = parse_vc, 3311 }, 3312 [ACTION_INC_TCP_SEQ_VALUE] = { 3313 .name = "value", 3314 .help = "the value to increase TCP sequence number by", 3315 .next = NEXT(action_inc_tcp_seq, NEXT_ENTRY(UNSIGNED)), 3316 .args = ARGS(ARG_ENTRY_HTON(rte_be32_t)), 3317 .call = parse_vc_conf, 3318 }, 3319 [ACTION_DEC_TCP_SEQ] = { 3320 .name = "dec_tcp_seq", 3321 .help = "decrease TCP sequence number", 3322 .priv = PRIV_ACTION(DEC_TCP_SEQ, sizeof(rte_be32_t)), 3323 .next = NEXT(action_dec_tcp_seq), 3324 .call = parse_vc, 3325 }, 3326 [ACTION_DEC_TCP_SEQ_VALUE] = { 3327 .name = "value", 3328 .help = "the value to decrease TCP sequence number by", 3329 .next = NEXT(action_dec_tcp_seq, NEXT_ENTRY(UNSIGNED)), 3330 .args = ARGS(ARG_ENTRY_HTON(rte_be32_t)), 3331 .call = parse_vc_conf, 3332 }, 3333 [ACTION_INC_TCP_ACK] = { 3334 .name = "inc_tcp_ack", 3335 .help = "increase TCP acknowledgment number", 3336 .priv = PRIV_ACTION(INC_TCP_ACK, sizeof(rte_be32_t)), 3337 .next = NEXT(action_inc_tcp_ack), 3338 .call = parse_vc, 3339 }, 3340 [ACTION_INC_TCP_ACK_VALUE] = { 3341 .name = "value", 3342 .help = "the value to increase TCP acknowledgment number by", 3343 .next = NEXT(action_inc_tcp_ack, NEXT_ENTRY(UNSIGNED)), 3344 .args = ARGS(ARG_ENTRY_HTON(rte_be32_t)), 3345 .call = parse_vc_conf, 3346 }, 3347 [ACTION_DEC_TCP_ACK] = { 3348 .name = "dec_tcp_ack", 3349 .help = "decrease TCP acknowledgment number", 3350 .priv = PRIV_ACTION(DEC_TCP_ACK, sizeof(rte_be32_t)), 3351 .next = NEXT(action_dec_tcp_ack), 3352 .call = parse_vc, 3353 }, 3354 [ACTION_DEC_TCP_ACK_VALUE] = { 3355 .name = "value", 3356 .help = "the value to decrease TCP acknowledgment number by", 3357 .next = NEXT(action_dec_tcp_ack, NEXT_ENTRY(UNSIGNED)), 3358 .args = ARGS(ARG_ENTRY_HTON(rte_be32_t)), 3359 .call = parse_vc_conf, 3360 }, 3361 [ACTION_RAW_ENCAP] = { 3362 .name = "raw_encap", 3363 .help = "encapsulation data, defined by set raw_encap", 3364 .priv = PRIV_ACTION(RAW_ENCAP, 3365 sizeof(struct action_raw_encap_data)), 3366 .next = NEXT(action_raw_encap), 3367 .call = parse_vc_action_raw_encap, 3368 }, 3369 [ACTION_RAW_ENCAP_INDEX] = { 3370 .name = "index", 3371 .help = "the index of raw_encap_confs", 3372 .next = NEXT(NEXT_ENTRY(ACTION_RAW_ENCAP_INDEX_VALUE)), 3373 }, 3374 [ACTION_RAW_ENCAP_INDEX_VALUE] = { 3375 .name = "{index}", 3376 .type = "UNSIGNED", 3377 .help = "unsigned integer value", 3378 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)), 3379 .call = parse_vc_action_raw_encap_index, 3380 .comp = comp_set_raw_index, 3381 }, 3382 [ACTION_RAW_DECAP] = { 3383 .name = "raw_decap", 3384 .help = "decapsulation data, defined by set raw_encap", 3385 .priv = PRIV_ACTION(RAW_DECAP, 3386 sizeof(struct action_raw_decap_data)), 3387 .next = NEXT(action_raw_decap), 3388 .call = parse_vc_action_raw_decap, 3389 }, 3390 [ACTION_RAW_DECAP_INDEX] = { 3391 .name = "index", 3392 .help = "the index of raw_encap_confs", 3393 .next = NEXT(NEXT_ENTRY(ACTION_RAW_DECAP_INDEX_VALUE)), 3394 }, 3395 [ACTION_RAW_DECAP_INDEX_VALUE] = { 3396 .name = "{index}", 3397 .type = "UNSIGNED", 3398 .help = "unsigned integer value", 3399 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)), 3400 .call = parse_vc_action_raw_decap_index, 3401 .comp = comp_set_raw_index, 3402 }, 3403 /* Top level command. */ 3404 [SET] = { 3405 .name = "set", 3406 .help = "set raw encap/decap data", 3407 .type = "set raw_encap|raw_decap <index> <pattern>", 3408 .next = NEXT(NEXT_ENTRY 3409 (SET_RAW_ENCAP, 3410 SET_RAW_DECAP)), 3411 .call = parse_set_init, 3412 }, 3413 /* Sub-level commands. */ 3414 [SET_RAW_ENCAP] = { 3415 .name = "raw_encap", 3416 .help = "set raw encap data", 3417 .next = NEXT(next_set_raw), 3418 .args = ARGS(ARGS_ENTRY_ARB_BOUNDED 3419 (offsetof(struct buffer, port), 3420 sizeof(((struct buffer *)0)->port), 3421 0, RAW_ENCAP_CONFS_MAX_NUM - 1)), 3422 .call = parse_set_raw_encap_decap, 3423 }, 3424 [SET_RAW_DECAP] = { 3425 .name = "raw_decap", 3426 .help = "set raw decap data", 3427 .next = NEXT(next_set_raw), 3428 .args = ARGS(ARGS_ENTRY_ARB_BOUNDED 3429 (offsetof(struct buffer, port), 3430 sizeof(((struct buffer *)0)->port), 3431 0, RAW_ENCAP_CONFS_MAX_NUM - 1)), 3432 .call = parse_set_raw_encap_decap, 3433 }, 3434 [SET_RAW_INDEX] = { 3435 .name = "{index}", 3436 .type = "UNSIGNED", 3437 .help = "index of raw_encap/raw_decap data", 3438 .next = NEXT(next_item), 3439 .call = parse_port, 3440 }, 3441 [ACTION_SET_TAG] = { 3442 .name = "set_tag", 3443 .help = "set tag", 3444 .priv = PRIV_ACTION(SET_TAG, 3445 sizeof(struct rte_flow_action_set_tag)), 3446 .next = NEXT(action_set_tag), 3447 .call = parse_vc, 3448 }, 3449 [ACTION_SET_TAG_INDEX] = { 3450 .name = "index", 3451 .help = "index of tag array", 3452 .next = NEXT(action_set_tag, NEXT_ENTRY(UNSIGNED)), 3453 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_set_tag, index)), 3454 .call = parse_vc_conf, 3455 }, 3456 [ACTION_SET_TAG_DATA] = { 3457 .name = "data", 3458 .help = "tag value", 3459 .next = NEXT(action_set_tag, NEXT_ENTRY(UNSIGNED)), 3460 .args = ARGS(ARGS_ENTRY 3461 (struct rte_flow_action_set_tag, data)), 3462 .call = parse_vc_conf, 3463 }, 3464 [ACTION_SET_TAG_MASK] = { 3465 .name = "mask", 3466 .help = "mask for tag value", 3467 .next = NEXT(action_set_tag, NEXT_ENTRY(UNSIGNED)), 3468 .args = ARGS(ARGS_ENTRY 3469 (struct rte_flow_action_set_tag, mask)), 3470 .call = parse_vc_conf, 3471 }, 3472 [ACTION_SET_META] = { 3473 .name = "set_meta", 3474 .help = "set metadata", 3475 .priv = PRIV_ACTION(SET_META, 3476 sizeof(struct rte_flow_action_set_meta)), 3477 .next = NEXT(action_set_meta), 3478 .call = parse_vc_action_set_meta, 3479 }, 3480 [ACTION_SET_META_DATA] = { 3481 .name = "data", 3482 .help = "metadata value", 3483 .next = NEXT(action_set_meta, NEXT_ENTRY(UNSIGNED)), 3484 .args = ARGS(ARGS_ENTRY 3485 (struct rte_flow_action_set_meta, data)), 3486 .call = parse_vc_conf, 3487 }, 3488 [ACTION_SET_META_MASK] = { 3489 .name = "mask", 3490 .help = "mask for metadata value", 3491 .next = NEXT(action_set_meta, NEXT_ENTRY(UNSIGNED)), 3492 .args = ARGS(ARGS_ENTRY 3493 (struct rte_flow_action_set_meta, mask)), 3494 .call = parse_vc_conf, 3495 }, 3496 }; 3497 3498 /** Remove and return last entry from argument stack. */ 3499 static const struct arg * 3500 pop_args(struct context *ctx) 3501 { 3502 return ctx->args_num ? ctx->args[--ctx->args_num] : NULL; 3503 } 3504 3505 /** Add entry on top of the argument stack. */ 3506 static int 3507 push_args(struct context *ctx, const struct arg *arg) 3508 { 3509 if (ctx->args_num == CTX_STACK_SIZE) 3510 return -1; 3511 ctx->args[ctx->args_num++] = arg; 3512 return 0; 3513 } 3514 3515 /** Spread value into buffer according to bit-mask. */ 3516 static size_t 3517 arg_entry_bf_fill(void *dst, uintmax_t val, const struct arg *arg) 3518 { 3519 uint32_t i = arg->size; 3520 uint32_t end = 0; 3521 int sub = 1; 3522 int add = 0; 3523 size_t len = 0; 3524 3525 if (!arg->mask) 3526 return 0; 3527 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN 3528 if (!arg->hton) { 3529 i = 0; 3530 end = arg->size; 3531 sub = 0; 3532 add = 1; 3533 } 3534 #endif 3535 while (i != end) { 3536 unsigned int shift = 0; 3537 uint8_t *buf = (uint8_t *)dst + arg->offset + (i -= sub); 3538 3539 for (shift = 0; arg->mask[i] >> shift; ++shift) { 3540 if (!(arg->mask[i] & (1 << shift))) 3541 continue; 3542 ++len; 3543 if (!dst) 3544 continue; 3545 *buf &= ~(1 << shift); 3546 *buf |= (val & 1) << shift; 3547 val >>= 1; 3548 } 3549 i += add; 3550 } 3551 return len; 3552 } 3553 3554 /** Compare a string with a partial one of a given length. */ 3555 static int 3556 strcmp_partial(const char *full, const char *partial, size_t partial_len) 3557 { 3558 int r = strncmp(full, partial, partial_len); 3559 3560 if (r) 3561 return r; 3562 if (strlen(full) <= partial_len) 3563 return 0; 3564 return full[partial_len]; 3565 } 3566 3567 /** 3568 * Parse a prefix length and generate a bit-mask. 3569 * 3570 * Last argument (ctx->args) is retrieved to determine mask size, storage 3571 * location and whether the result must use network byte ordering. 3572 */ 3573 static int 3574 parse_prefix(struct context *ctx, const struct token *token, 3575 const char *str, unsigned int len, 3576 void *buf, unsigned int size) 3577 { 3578 const struct arg *arg = pop_args(ctx); 3579 static const uint8_t conv[] = "\x00\x80\xc0\xe0\xf0\xf8\xfc\xfe\xff"; 3580 char *end; 3581 uintmax_t u; 3582 unsigned int bytes; 3583 unsigned int extra; 3584 3585 (void)token; 3586 /* Argument is expected. */ 3587 if (!arg) 3588 return -1; 3589 errno = 0; 3590 u = strtoumax(str, &end, 0); 3591 if (errno || (size_t)(end - str) != len) 3592 goto error; 3593 if (arg->mask) { 3594 uintmax_t v = 0; 3595 3596 extra = arg_entry_bf_fill(NULL, 0, arg); 3597 if (u > extra) 3598 goto error; 3599 if (!ctx->object) 3600 return len; 3601 extra -= u; 3602 while (u--) 3603 (v <<= 1, v |= 1); 3604 v <<= extra; 3605 if (!arg_entry_bf_fill(ctx->object, v, arg) || 3606 !arg_entry_bf_fill(ctx->objmask, -1, arg)) 3607 goto error; 3608 return len; 3609 } 3610 bytes = u / 8; 3611 extra = u % 8; 3612 size = arg->size; 3613 if (bytes > size || bytes + !!extra > size) 3614 goto error; 3615 if (!ctx->object) 3616 return len; 3617 buf = (uint8_t *)ctx->object + arg->offset; 3618 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN 3619 if (!arg->hton) { 3620 memset((uint8_t *)buf + size - bytes, 0xff, bytes); 3621 memset(buf, 0x00, size - bytes); 3622 if (extra) 3623 ((uint8_t *)buf)[size - bytes - 1] = conv[extra]; 3624 } else 3625 #endif 3626 { 3627 memset(buf, 0xff, bytes); 3628 memset((uint8_t *)buf + bytes, 0x00, size - bytes); 3629 if (extra) 3630 ((uint8_t *)buf)[bytes] = conv[extra]; 3631 } 3632 if (ctx->objmask) 3633 memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size); 3634 return len; 3635 error: 3636 push_args(ctx, arg); 3637 return -1; 3638 } 3639 3640 /** Default parsing function for token name matching. */ 3641 static int 3642 parse_default(struct context *ctx, const struct token *token, 3643 const char *str, unsigned int len, 3644 void *buf, unsigned int size) 3645 { 3646 (void)ctx; 3647 (void)buf; 3648 (void)size; 3649 if (strcmp_partial(token->name, str, len)) 3650 return -1; 3651 return len; 3652 } 3653 3654 /** Parse flow command, initialize output buffer for subsequent tokens. */ 3655 static int 3656 parse_init(struct context *ctx, const struct token *token, 3657 const char *str, unsigned int len, 3658 void *buf, unsigned int size) 3659 { 3660 struct buffer *out = buf; 3661 3662 /* Token name must match. */ 3663 if (parse_default(ctx, token, str, len, NULL, 0) < 0) 3664 return -1; 3665 /* Nothing else to do if there is no buffer. */ 3666 if (!out) 3667 return len; 3668 /* Make sure buffer is large enough. */ 3669 if (size < sizeof(*out)) 3670 return -1; 3671 /* Initialize buffer. */ 3672 memset(out, 0x00, sizeof(*out)); 3673 memset((uint8_t *)out + sizeof(*out), 0x22, size - sizeof(*out)); 3674 ctx->objdata = 0; 3675 ctx->object = out; 3676 ctx->objmask = NULL; 3677 return len; 3678 } 3679 3680 /** Parse tokens for validate/create commands. */ 3681 static int 3682 parse_vc(struct context *ctx, const struct token *token, 3683 const char *str, unsigned int len, 3684 void *buf, unsigned int size) 3685 { 3686 struct buffer *out = buf; 3687 uint8_t *data; 3688 uint32_t data_size; 3689 3690 /* Token name must match. */ 3691 if (parse_default(ctx, token, str, len, NULL, 0) < 0) 3692 return -1; 3693 /* Nothing else to do if there is no buffer. */ 3694 if (!out) 3695 return len; 3696 if (!out->command) { 3697 if (ctx->curr != VALIDATE && ctx->curr != CREATE) 3698 return -1; 3699 if (sizeof(*out) > size) 3700 return -1; 3701 out->command = ctx->curr; 3702 ctx->objdata = 0; 3703 ctx->object = out; 3704 ctx->objmask = NULL; 3705 out->args.vc.data = (uint8_t *)out + size; 3706 return len; 3707 } 3708 ctx->objdata = 0; 3709 ctx->object = &out->args.vc.attr; 3710 ctx->objmask = NULL; 3711 switch (ctx->curr) { 3712 case GROUP: 3713 case PRIORITY: 3714 return len; 3715 case INGRESS: 3716 out->args.vc.attr.ingress = 1; 3717 return len; 3718 case EGRESS: 3719 out->args.vc.attr.egress = 1; 3720 return len; 3721 case TRANSFER: 3722 out->args.vc.attr.transfer = 1; 3723 return len; 3724 case PATTERN: 3725 out->args.vc.pattern = 3726 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1), 3727 sizeof(double)); 3728 ctx->object = out->args.vc.pattern; 3729 ctx->objmask = NULL; 3730 return len; 3731 case ACTIONS: 3732 out->args.vc.actions = 3733 (void *)RTE_ALIGN_CEIL((uintptr_t) 3734 (out->args.vc.pattern + 3735 out->args.vc.pattern_n), 3736 sizeof(double)); 3737 ctx->object = out->args.vc.actions; 3738 ctx->objmask = NULL; 3739 return len; 3740 default: 3741 if (!token->priv) 3742 return -1; 3743 break; 3744 } 3745 if (!out->args.vc.actions) { 3746 const struct parse_item_priv *priv = token->priv; 3747 struct rte_flow_item *item = 3748 out->args.vc.pattern + out->args.vc.pattern_n; 3749 3750 data_size = priv->size * 3; /* spec, last, mask */ 3751 data = (void *)RTE_ALIGN_FLOOR((uintptr_t) 3752 (out->args.vc.data - data_size), 3753 sizeof(double)); 3754 if ((uint8_t *)item + sizeof(*item) > data) 3755 return -1; 3756 *item = (struct rte_flow_item){ 3757 .type = priv->type, 3758 }; 3759 ++out->args.vc.pattern_n; 3760 ctx->object = item; 3761 ctx->objmask = NULL; 3762 } else { 3763 const struct parse_action_priv *priv = token->priv; 3764 struct rte_flow_action *action = 3765 out->args.vc.actions + out->args.vc.actions_n; 3766 3767 data_size = priv->size; /* configuration */ 3768 data = (void *)RTE_ALIGN_FLOOR((uintptr_t) 3769 (out->args.vc.data - data_size), 3770 sizeof(double)); 3771 if ((uint8_t *)action + sizeof(*action) > data) 3772 return -1; 3773 *action = (struct rte_flow_action){ 3774 .type = priv->type, 3775 .conf = data_size ? data : NULL, 3776 }; 3777 ++out->args.vc.actions_n; 3778 ctx->object = action; 3779 ctx->objmask = NULL; 3780 } 3781 memset(data, 0, data_size); 3782 out->args.vc.data = data; 3783 ctx->objdata = data_size; 3784 return len; 3785 } 3786 3787 /** Parse pattern item parameter type. */ 3788 static int 3789 parse_vc_spec(struct context *ctx, const struct token *token, 3790 const char *str, unsigned int len, 3791 void *buf, unsigned int size) 3792 { 3793 struct buffer *out = buf; 3794 struct rte_flow_item *item; 3795 uint32_t data_size; 3796 int index; 3797 int objmask = 0; 3798 3799 (void)size; 3800 /* Token name must match. */ 3801 if (parse_default(ctx, token, str, len, NULL, 0) < 0) 3802 return -1; 3803 /* Parse parameter types. */ 3804 switch (ctx->curr) { 3805 static const enum index prefix[] = NEXT_ENTRY(PREFIX); 3806 3807 case ITEM_PARAM_IS: 3808 index = 0; 3809 objmask = 1; 3810 break; 3811 case ITEM_PARAM_SPEC: 3812 index = 0; 3813 break; 3814 case ITEM_PARAM_LAST: 3815 index = 1; 3816 break; 3817 case ITEM_PARAM_PREFIX: 3818 /* Modify next token to expect a prefix. */ 3819 if (ctx->next_num < 2) 3820 return -1; 3821 ctx->next[ctx->next_num - 2] = prefix; 3822 /* Fall through. */ 3823 case ITEM_PARAM_MASK: 3824 index = 2; 3825 break; 3826 default: 3827 return -1; 3828 } 3829 /* Nothing else to do if there is no buffer. */ 3830 if (!out) 3831 return len; 3832 if (!out->args.vc.pattern_n) 3833 return -1; 3834 item = &out->args.vc.pattern[out->args.vc.pattern_n - 1]; 3835 data_size = ctx->objdata / 3; /* spec, last, mask */ 3836 /* Point to selected object. */ 3837 ctx->object = out->args.vc.data + (data_size * index); 3838 if (objmask) { 3839 ctx->objmask = out->args.vc.data + (data_size * 2); /* mask */ 3840 item->mask = ctx->objmask; 3841 } else 3842 ctx->objmask = NULL; 3843 /* Update relevant item pointer. */ 3844 *((const void **[]){ &item->spec, &item->last, &item->mask })[index] = 3845 ctx->object; 3846 return len; 3847 } 3848 3849 /** Parse action configuration field. */ 3850 static int 3851 parse_vc_conf(struct context *ctx, const struct token *token, 3852 const char *str, unsigned int len, 3853 void *buf, unsigned int size) 3854 { 3855 struct buffer *out = buf; 3856 3857 (void)size; 3858 /* Token name must match. */ 3859 if (parse_default(ctx, token, str, len, NULL, 0) < 0) 3860 return -1; 3861 /* Nothing else to do if there is no buffer. */ 3862 if (!out) 3863 return len; 3864 /* Point to selected object. */ 3865 ctx->object = out->args.vc.data; 3866 ctx->objmask = NULL; 3867 return len; 3868 } 3869 3870 /** Parse RSS action. */ 3871 static int 3872 parse_vc_action_rss(struct context *ctx, const struct token *token, 3873 const char *str, unsigned int len, 3874 void *buf, unsigned int size) 3875 { 3876 struct buffer *out = buf; 3877 struct rte_flow_action *action; 3878 struct action_rss_data *action_rss_data; 3879 unsigned int i; 3880 int ret; 3881 3882 ret = parse_vc(ctx, token, str, len, buf, size); 3883 if (ret < 0) 3884 return ret; 3885 /* Nothing else to do if there is no buffer. */ 3886 if (!out) 3887 return ret; 3888 if (!out->args.vc.actions_n) 3889 return -1; 3890 action = &out->args.vc.actions[out->args.vc.actions_n - 1]; 3891 /* Point to selected object. */ 3892 ctx->object = out->args.vc.data; 3893 ctx->objmask = NULL; 3894 /* Set up default configuration. */ 3895 action_rss_data = ctx->object; 3896 *action_rss_data = (struct action_rss_data){ 3897 .conf = (struct rte_flow_action_rss){ 3898 .func = RTE_ETH_HASH_FUNCTION_DEFAULT, 3899 .level = 0, 3900 .types = rss_hf, 3901 .key_len = sizeof(action_rss_data->key), 3902 .queue_num = RTE_MIN(nb_rxq, ACTION_RSS_QUEUE_NUM), 3903 .key = action_rss_data->key, 3904 .queue = action_rss_data->queue, 3905 }, 3906 .key = "testpmd's default RSS hash key, " 3907 "override it for better balancing", 3908 .queue = { 0 }, 3909 }; 3910 for (i = 0; i < action_rss_data->conf.queue_num; ++i) 3911 action_rss_data->queue[i] = i; 3912 if (!port_id_is_invalid(ctx->port, DISABLED_WARN) && 3913 ctx->port != (portid_t)RTE_PORT_ALL) { 3914 struct rte_eth_dev_info info; 3915 int ret2; 3916 3917 ret2 = rte_eth_dev_info_get(ctx->port, &info); 3918 if (ret2 != 0) 3919 return ret2; 3920 3921 action_rss_data->conf.key_len = 3922 RTE_MIN(sizeof(action_rss_data->key), 3923 info.hash_key_size); 3924 } 3925 action->conf = &action_rss_data->conf; 3926 return ret; 3927 } 3928 3929 /** 3930 * Parse func field for RSS action. 3931 * 3932 * The RTE_ETH_HASH_FUNCTION_* value to assign is derived from the 3933 * ACTION_RSS_FUNC_* index that called this function. 3934 */ 3935 static int 3936 parse_vc_action_rss_func(struct context *ctx, const struct token *token, 3937 const char *str, unsigned int len, 3938 void *buf, unsigned int size) 3939 { 3940 struct action_rss_data *action_rss_data; 3941 enum rte_eth_hash_function func; 3942 3943 (void)buf; 3944 (void)size; 3945 /* Token name must match. */ 3946 if (parse_default(ctx, token, str, len, NULL, 0) < 0) 3947 return -1; 3948 switch (ctx->curr) { 3949 case ACTION_RSS_FUNC_DEFAULT: 3950 func = RTE_ETH_HASH_FUNCTION_DEFAULT; 3951 break; 3952 case ACTION_RSS_FUNC_TOEPLITZ: 3953 func = RTE_ETH_HASH_FUNCTION_TOEPLITZ; 3954 break; 3955 case ACTION_RSS_FUNC_SIMPLE_XOR: 3956 func = RTE_ETH_HASH_FUNCTION_SIMPLE_XOR; 3957 break; 3958 case ACTION_RSS_FUNC_SYMMETRIC_TOEPLITZ: 3959 func = RTE_ETH_HASH_FUNCTION_SYMMETRIC_TOEPLITZ; 3960 break; 3961 default: 3962 return -1; 3963 } 3964 if (!ctx->object) 3965 return len; 3966 action_rss_data = ctx->object; 3967 action_rss_data->conf.func = func; 3968 return len; 3969 } 3970 3971 /** 3972 * Parse type field for RSS action. 3973 * 3974 * Valid tokens are type field names and the "end" token. 3975 */ 3976 static int 3977 parse_vc_action_rss_type(struct context *ctx, const struct token *token, 3978 const char *str, unsigned int len, 3979 void *buf, unsigned int size) 3980 { 3981 static const enum index next[] = NEXT_ENTRY(ACTION_RSS_TYPE); 3982 struct action_rss_data *action_rss_data; 3983 unsigned int i; 3984 3985 (void)token; 3986 (void)buf; 3987 (void)size; 3988 if (ctx->curr != ACTION_RSS_TYPE) 3989 return -1; 3990 if (!(ctx->objdata >> 16) && ctx->object) { 3991 action_rss_data = ctx->object; 3992 action_rss_data->conf.types = 0; 3993 } 3994 if (!strcmp_partial("end", str, len)) { 3995 ctx->objdata &= 0xffff; 3996 return len; 3997 } 3998 for (i = 0; rss_type_table[i].str; ++i) 3999 if (!strcmp_partial(rss_type_table[i].str, str, len)) 4000 break; 4001 if (!rss_type_table[i].str) 4002 return -1; 4003 ctx->objdata = 1 << 16 | (ctx->objdata & 0xffff); 4004 /* Repeat token. */ 4005 if (ctx->next_num == RTE_DIM(ctx->next)) 4006 return -1; 4007 ctx->next[ctx->next_num++] = next; 4008 if (!ctx->object) 4009 return len; 4010 action_rss_data = ctx->object; 4011 action_rss_data->conf.types |= rss_type_table[i].rss_type; 4012 return len; 4013 } 4014 4015 /** 4016 * Parse queue field for RSS action. 4017 * 4018 * Valid tokens are queue indices and the "end" token. 4019 */ 4020 static int 4021 parse_vc_action_rss_queue(struct context *ctx, const struct token *token, 4022 const char *str, unsigned int len, 4023 void *buf, unsigned int size) 4024 { 4025 static const enum index next[] = NEXT_ENTRY(ACTION_RSS_QUEUE); 4026 struct action_rss_data *action_rss_data; 4027 const struct arg *arg; 4028 int ret; 4029 int i; 4030 4031 (void)token; 4032 (void)buf; 4033 (void)size; 4034 if (ctx->curr != ACTION_RSS_QUEUE) 4035 return -1; 4036 i = ctx->objdata >> 16; 4037 if (!strcmp_partial("end", str, len)) { 4038 ctx->objdata &= 0xffff; 4039 goto end; 4040 } 4041 if (i >= ACTION_RSS_QUEUE_NUM) 4042 return -1; 4043 arg = ARGS_ENTRY_ARB(offsetof(struct action_rss_data, queue) + 4044 i * sizeof(action_rss_data->queue[i]), 4045 sizeof(action_rss_data->queue[i])); 4046 if (push_args(ctx, arg)) 4047 return -1; 4048 ret = parse_int(ctx, token, str, len, NULL, 0); 4049 if (ret < 0) { 4050 pop_args(ctx); 4051 return -1; 4052 } 4053 ++i; 4054 ctx->objdata = i << 16 | (ctx->objdata & 0xffff); 4055 /* Repeat token. */ 4056 if (ctx->next_num == RTE_DIM(ctx->next)) 4057 return -1; 4058 ctx->next[ctx->next_num++] = next; 4059 end: 4060 if (!ctx->object) 4061 return len; 4062 action_rss_data = ctx->object; 4063 action_rss_data->conf.queue_num = i; 4064 action_rss_data->conf.queue = i ? action_rss_data->queue : NULL; 4065 return len; 4066 } 4067 4068 /** Parse VXLAN encap action. */ 4069 static int 4070 parse_vc_action_vxlan_encap(struct context *ctx, const struct token *token, 4071 const char *str, unsigned int len, 4072 void *buf, unsigned int size) 4073 { 4074 struct buffer *out = buf; 4075 struct rte_flow_action *action; 4076 struct action_vxlan_encap_data *action_vxlan_encap_data; 4077 int ret; 4078 4079 ret = parse_vc(ctx, token, str, len, buf, size); 4080 if (ret < 0) 4081 return ret; 4082 /* Nothing else to do if there is no buffer. */ 4083 if (!out) 4084 return ret; 4085 if (!out->args.vc.actions_n) 4086 return -1; 4087 action = &out->args.vc.actions[out->args.vc.actions_n - 1]; 4088 /* Point to selected object. */ 4089 ctx->object = out->args.vc.data; 4090 ctx->objmask = NULL; 4091 /* Set up default configuration. */ 4092 action_vxlan_encap_data = ctx->object; 4093 *action_vxlan_encap_data = (struct action_vxlan_encap_data){ 4094 .conf = (struct rte_flow_action_vxlan_encap){ 4095 .definition = action_vxlan_encap_data->items, 4096 }, 4097 .items = { 4098 { 4099 .type = RTE_FLOW_ITEM_TYPE_ETH, 4100 .spec = &action_vxlan_encap_data->item_eth, 4101 .mask = &rte_flow_item_eth_mask, 4102 }, 4103 { 4104 .type = RTE_FLOW_ITEM_TYPE_VLAN, 4105 .spec = &action_vxlan_encap_data->item_vlan, 4106 .mask = &rte_flow_item_vlan_mask, 4107 }, 4108 { 4109 .type = RTE_FLOW_ITEM_TYPE_IPV4, 4110 .spec = &action_vxlan_encap_data->item_ipv4, 4111 .mask = &rte_flow_item_ipv4_mask, 4112 }, 4113 { 4114 .type = RTE_FLOW_ITEM_TYPE_UDP, 4115 .spec = &action_vxlan_encap_data->item_udp, 4116 .mask = &rte_flow_item_udp_mask, 4117 }, 4118 { 4119 .type = RTE_FLOW_ITEM_TYPE_VXLAN, 4120 .spec = &action_vxlan_encap_data->item_vxlan, 4121 .mask = &rte_flow_item_vxlan_mask, 4122 }, 4123 { 4124 .type = RTE_FLOW_ITEM_TYPE_END, 4125 }, 4126 }, 4127 .item_eth.type = 0, 4128 .item_vlan = { 4129 .tci = vxlan_encap_conf.vlan_tci, 4130 .inner_type = 0, 4131 }, 4132 .item_ipv4.hdr = { 4133 .src_addr = vxlan_encap_conf.ipv4_src, 4134 .dst_addr = vxlan_encap_conf.ipv4_dst, 4135 }, 4136 .item_udp.hdr = { 4137 .src_port = vxlan_encap_conf.udp_src, 4138 .dst_port = vxlan_encap_conf.udp_dst, 4139 }, 4140 .item_vxlan.flags = 0, 4141 }; 4142 memcpy(action_vxlan_encap_data->item_eth.dst.addr_bytes, 4143 vxlan_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN); 4144 memcpy(action_vxlan_encap_data->item_eth.src.addr_bytes, 4145 vxlan_encap_conf.eth_src, RTE_ETHER_ADDR_LEN); 4146 if (!vxlan_encap_conf.select_ipv4) { 4147 memcpy(&action_vxlan_encap_data->item_ipv6.hdr.src_addr, 4148 &vxlan_encap_conf.ipv6_src, 4149 sizeof(vxlan_encap_conf.ipv6_src)); 4150 memcpy(&action_vxlan_encap_data->item_ipv6.hdr.dst_addr, 4151 &vxlan_encap_conf.ipv6_dst, 4152 sizeof(vxlan_encap_conf.ipv6_dst)); 4153 action_vxlan_encap_data->items[2] = (struct rte_flow_item){ 4154 .type = RTE_FLOW_ITEM_TYPE_IPV6, 4155 .spec = &action_vxlan_encap_data->item_ipv6, 4156 .mask = &rte_flow_item_ipv6_mask, 4157 }; 4158 } 4159 if (!vxlan_encap_conf.select_vlan) 4160 action_vxlan_encap_data->items[1].type = 4161 RTE_FLOW_ITEM_TYPE_VOID; 4162 if (vxlan_encap_conf.select_tos_ttl) { 4163 if (vxlan_encap_conf.select_ipv4) { 4164 static struct rte_flow_item_ipv4 ipv4_mask_tos; 4165 4166 memcpy(&ipv4_mask_tos, &rte_flow_item_ipv4_mask, 4167 sizeof(ipv4_mask_tos)); 4168 ipv4_mask_tos.hdr.type_of_service = 0xff; 4169 ipv4_mask_tos.hdr.time_to_live = 0xff; 4170 action_vxlan_encap_data->item_ipv4.hdr.type_of_service = 4171 vxlan_encap_conf.ip_tos; 4172 action_vxlan_encap_data->item_ipv4.hdr.time_to_live = 4173 vxlan_encap_conf.ip_ttl; 4174 action_vxlan_encap_data->items[2].mask = 4175 &ipv4_mask_tos; 4176 } else { 4177 static struct rte_flow_item_ipv6 ipv6_mask_tos; 4178 4179 memcpy(&ipv6_mask_tos, &rte_flow_item_ipv6_mask, 4180 sizeof(ipv6_mask_tos)); 4181 ipv6_mask_tos.hdr.vtc_flow |= 4182 RTE_BE32(0xfful << RTE_IPV6_HDR_TC_SHIFT); 4183 ipv6_mask_tos.hdr.hop_limits = 0xff; 4184 action_vxlan_encap_data->item_ipv6.hdr.vtc_flow |= 4185 rte_cpu_to_be_32 4186 ((uint32_t)vxlan_encap_conf.ip_tos << 4187 RTE_IPV6_HDR_TC_SHIFT); 4188 action_vxlan_encap_data->item_ipv6.hdr.hop_limits = 4189 vxlan_encap_conf.ip_ttl; 4190 action_vxlan_encap_data->items[2].mask = 4191 &ipv6_mask_tos; 4192 } 4193 } 4194 memcpy(action_vxlan_encap_data->item_vxlan.vni, vxlan_encap_conf.vni, 4195 RTE_DIM(vxlan_encap_conf.vni)); 4196 action->conf = &action_vxlan_encap_data->conf; 4197 return ret; 4198 } 4199 4200 /** Parse NVGRE encap action. */ 4201 static int 4202 parse_vc_action_nvgre_encap(struct context *ctx, const struct token *token, 4203 const char *str, unsigned int len, 4204 void *buf, unsigned int size) 4205 { 4206 struct buffer *out = buf; 4207 struct rte_flow_action *action; 4208 struct action_nvgre_encap_data *action_nvgre_encap_data; 4209 int ret; 4210 4211 ret = parse_vc(ctx, token, str, len, buf, size); 4212 if (ret < 0) 4213 return ret; 4214 /* Nothing else to do if there is no buffer. */ 4215 if (!out) 4216 return ret; 4217 if (!out->args.vc.actions_n) 4218 return -1; 4219 action = &out->args.vc.actions[out->args.vc.actions_n - 1]; 4220 /* Point to selected object. */ 4221 ctx->object = out->args.vc.data; 4222 ctx->objmask = NULL; 4223 /* Set up default configuration. */ 4224 action_nvgre_encap_data = ctx->object; 4225 *action_nvgre_encap_data = (struct action_nvgre_encap_data){ 4226 .conf = (struct rte_flow_action_nvgre_encap){ 4227 .definition = action_nvgre_encap_data->items, 4228 }, 4229 .items = { 4230 { 4231 .type = RTE_FLOW_ITEM_TYPE_ETH, 4232 .spec = &action_nvgre_encap_data->item_eth, 4233 .mask = &rte_flow_item_eth_mask, 4234 }, 4235 { 4236 .type = RTE_FLOW_ITEM_TYPE_VLAN, 4237 .spec = &action_nvgre_encap_data->item_vlan, 4238 .mask = &rte_flow_item_vlan_mask, 4239 }, 4240 { 4241 .type = RTE_FLOW_ITEM_TYPE_IPV4, 4242 .spec = &action_nvgre_encap_data->item_ipv4, 4243 .mask = &rte_flow_item_ipv4_mask, 4244 }, 4245 { 4246 .type = RTE_FLOW_ITEM_TYPE_NVGRE, 4247 .spec = &action_nvgre_encap_data->item_nvgre, 4248 .mask = &rte_flow_item_nvgre_mask, 4249 }, 4250 { 4251 .type = RTE_FLOW_ITEM_TYPE_END, 4252 }, 4253 }, 4254 .item_eth.type = 0, 4255 .item_vlan = { 4256 .tci = nvgre_encap_conf.vlan_tci, 4257 .inner_type = 0, 4258 }, 4259 .item_ipv4.hdr = { 4260 .src_addr = nvgre_encap_conf.ipv4_src, 4261 .dst_addr = nvgre_encap_conf.ipv4_dst, 4262 }, 4263 .item_nvgre.flow_id = 0, 4264 }; 4265 memcpy(action_nvgre_encap_data->item_eth.dst.addr_bytes, 4266 nvgre_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN); 4267 memcpy(action_nvgre_encap_data->item_eth.src.addr_bytes, 4268 nvgre_encap_conf.eth_src, RTE_ETHER_ADDR_LEN); 4269 if (!nvgre_encap_conf.select_ipv4) { 4270 memcpy(&action_nvgre_encap_data->item_ipv6.hdr.src_addr, 4271 &nvgre_encap_conf.ipv6_src, 4272 sizeof(nvgre_encap_conf.ipv6_src)); 4273 memcpy(&action_nvgre_encap_data->item_ipv6.hdr.dst_addr, 4274 &nvgre_encap_conf.ipv6_dst, 4275 sizeof(nvgre_encap_conf.ipv6_dst)); 4276 action_nvgre_encap_data->items[2] = (struct rte_flow_item){ 4277 .type = RTE_FLOW_ITEM_TYPE_IPV6, 4278 .spec = &action_nvgre_encap_data->item_ipv6, 4279 .mask = &rte_flow_item_ipv6_mask, 4280 }; 4281 } 4282 if (!nvgre_encap_conf.select_vlan) 4283 action_nvgre_encap_data->items[1].type = 4284 RTE_FLOW_ITEM_TYPE_VOID; 4285 memcpy(action_nvgre_encap_data->item_nvgre.tni, nvgre_encap_conf.tni, 4286 RTE_DIM(nvgre_encap_conf.tni)); 4287 action->conf = &action_nvgre_encap_data->conf; 4288 return ret; 4289 } 4290 4291 /** Parse l2 encap action. */ 4292 static int 4293 parse_vc_action_l2_encap(struct context *ctx, const struct token *token, 4294 const char *str, unsigned int len, 4295 void *buf, unsigned int size) 4296 { 4297 struct buffer *out = buf; 4298 struct rte_flow_action *action; 4299 struct action_raw_encap_data *action_encap_data; 4300 struct rte_flow_item_eth eth = { .type = 0, }; 4301 struct rte_flow_item_vlan vlan = { 4302 .tci = mplsoudp_encap_conf.vlan_tci, 4303 .inner_type = 0, 4304 }; 4305 uint8_t *header; 4306 int ret; 4307 4308 ret = parse_vc(ctx, token, str, len, buf, size); 4309 if (ret < 0) 4310 return ret; 4311 /* Nothing else to do if there is no buffer. */ 4312 if (!out) 4313 return ret; 4314 if (!out->args.vc.actions_n) 4315 return -1; 4316 action = &out->args.vc.actions[out->args.vc.actions_n - 1]; 4317 /* Point to selected object. */ 4318 ctx->object = out->args.vc.data; 4319 ctx->objmask = NULL; 4320 /* Copy the headers to the buffer. */ 4321 action_encap_data = ctx->object; 4322 *action_encap_data = (struct action_raw_encap_data) { 4323 .conf = (struct rte_flow_action_raw_encap){ 4324 .data = action_encap_data->data, 4325 }, 4326 .data = {}, 4327 }; 4328 header = action_encap_data->data; 4329 if (l2_encap_conf.select_vlan) 4330 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN); 4331 else if (l2_encap_conf.select_ipv4) 4332 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4); 4333 else 4334 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6); 4335 memcpy(eth.dst.addr_bytes, 4336 l2_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN); 4337 memcpy(eth.src.addr_bytes, 4338 l2_encap_conf.eth_src, RTE_ETHER_ADDR_LEN); 4339 memcpy(header, ð, sizeof(eth)); 4340 header += sizeof(eth); 4341 if (l2_encap_conf.select_vlan) { 4342 if (l2_encap_conf.select_ipv4) 4343 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4); 4344 else 4345 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6); 4346 memcpy(header, &vlan, sizeof(vlan)); 4347 header += sizeof(vlan); 4348 } 4349 action_encap_data->conf.size = header - 4350 action_encap_data->data; 4351 action->conf = &action_encap_data->conf; 4352 return ret; 4353 } 4354 4355 /** Parse l2 decap action. */ 4356 static int 4357 parse_vc_action_l2_decap(struct context *ctx, const struct token *token, 4358 const char *str, unsigned int len, 4359 void *buf, unsigned int size) 4360 { 4361 struct buffer *out = buf; 4362 struct rte_flow_action *action; 4363 struct action_raw_decap_data *action_decap_data; 4364 struct rte_flow_item_eth eth = { .type = 0, }; 4365 struct rte_flow_item_vlan vlan = { 4366 .tci = mplsoudp_encap_conf.vlan_tci, 4367 .inner_type = 0, 4368 }; 4369 uint8_t *header; 4370 int ret; 4371 4372 ret = parse_vc(ctx, token, str, len, buf, size); 4373 if (ret < 0) 4374 return ret; 4375 /* Nothing else to do if there is no buffer. */ 4376 if (!out) 4377 return ret; 4378 if (!out->args.vc.actions_n) 4379 return -1; 4380 action = &out->args.vc.actions[out->args.vc.actions_n - 1]; 4381 /* Point to selected object. */ 4382 ctx->object = out->args.vc.data; 4383 ctx->objmask = NULL; 4384 /* Copy the headers to the buffer. */ 4385 action_decap_data = ctx->object; 4386 *action_decap_data = (struct action_raw_decap_data) { 4387 .conf = (struct rte_flow_action_raw_decap){ 4388 .data = action_decap_data->data, 4389 }, 4390 .data = {}, 4391 }; 4392 header = action_decap_data->data; 4393 if (l2_decap_conf.select_vlan) 4394 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN); 4395 memcpy(header, ð, sizeof(eth)); 4396 header += sizeof(eth); 4397 if (l2_decap_conf.select_vlan) { 4398 memcpy(header, &vlan, sizeof(vlan)); 4399 header += sizeof(vlan); 4400 } 4401 action_decap_data->conf.size = header - 4402 action_decap_data->data; 4403 action->conf = &action_decap_data->conf; 4404 return ret; 4405 } 4406 4407 #define ETHER_TYPE_MPLS_UNICAST 0x8847 4408 4409 /** Parse MPLSOGRE encap action. */ 4410 static int 4411 parse_vc_action_mplsogre_encap(struct context *ctx, const struct token *token, 4412 const char *str, unsigned int len, 4413 void *buf, unsigned int size) 4414 { 4415 struct buffer *out = buf; 4416 struct rte_flow_action *action; 4417 struct action_raw_encap_data *action_encap_data; 4418 struct rte_flow_item_eth eth = { .type = 0, }; 4419 struct rte_flow_item_vlan vlan = { 4420 .tci = mplsogre_encap_conf.vlan_tci, 4421 .inner_type = 0, 4422 }; 4423 struct rte_flow_item_ipv4 ipv4 = { 4424 .hdr = { 4425 .src_addr = mplsogre_encap_conf.ipv4_src, 4426 .dst_addr = mplsogre_encap_conf.ipv4_dst, 4427 .next_proto_id = IPPROTO_GRE, 4428 .version_ihl = RTE_IPV4_VHL_DEF, 4429 .time_to_live = IPDEFTTL, 4430 }, 4431 }; 4432 struct rte_flow_item_ipv6 ipv6 = { 4433 .hdr = { 4434 .proto = IPPROTO_GRE, 4435 .hop_limits = IPDEFTTL, 4436 }, 4437 }; 4438 struct rte_flow_item_gre gre = { 4439 .protocol = rte_cpu_to_be_16(ETHER_TYPE_MPLS_UNICAST), 4440 }; 4441 struct rte_flow_item_mpls mpls; 4442 uint8_t *header; 4443 int ret; 4444 4445 ret = parse_vc(ctx, token, str, len, buf, size); 4446 if (ret < 0) 4447 return ret; 4448 /* Nothing else to do if there is no buffer. */ 4449 if (!out) 4450 return ret; 4451 if (!out->args.vc.actions_n) 4452 return -1; 4453 action = &out->args.vc.actions[out->args.vc.actions_n - 1]; 4454 /* Point to selected object. */ 4455 ctx->object = out->args.vc.data; 4456 ctx->objmask = NULL; 4457 /* Copy the headers to the buffer. */ 4458 action_encap_data = ctx->object; 4459 *action_encap_data = (struct action_raw_encap_data) { 4460 .conf = (struct rte_flow_action_raw_encap){ 4461 .data = action_encap_data->data, 4462 }, 4463 .data = {}, 4464 .preserve = {}, 4465 }; 4466 header = action_encap_data->data; 4467 if (mplsogre_encap_conf.select_vlan) 4468 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN); 4469 else if (mplsogre_encap_conf.select_ipv4) 4470 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4); 4471 else 4472 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6); 4473 memcpy(eth.dst.addr_bytes, 4474 mplsogre_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN); 4475 memcpy(eth.src.addr_bytes, 4476 mplsogre_encap_conf.eth_src, RTE_ETHER_ADDR_LEN); 4477 memcpy(header, ð, sizeof(eth)); 4478 header += sizeof(eth); 4479 if (mplsogre_encap_conf.select_vlan) { 4480 if (mplsogre_encap_conf.select_ipv4) 4481 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4); 4482 else 4483 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6); 4484 memcpy(header, &vlan, sizeof(vlan)); 4485 header += sizeof(vlan); 4486 } 4487 if (mplsogre_encap_conf.select_ipv4) { 4488 memcpy(header, &ipv4, sizeof(ipv4)); 4489 header += sizeof(ipv4); 4490 } else { 4491 memcpy(&ipv6.hdr.src_addr, 4492 &mplsogre_encap_conf.ipv6_src, 4493 sizeof(mplsogre_encap_conf.ipv6_src)); 4494 memcpy(&ipv6.hdr.dst_addr, 4495 &mplsogre_encap_conf.ipv6_dst, 4496 sizeof(mplsogre_encap_conf.ipv6_dst)); 4497 memcpy(header, &ipv6, sizeof(ipv6)); 4498 header += sizeof(ipv6); 4499 } 4500 memcpy(header, &gre, sizeof(gre)); 4501 header += sizeof(gre); 4502 memcpy(mpls.label_tc_s, mplsogre_encap_conf.label, 4503 RTE_DIM(mplsogre_encap_conf.label)); 4504 mpls.label_tc_s[2] |= 0x1; 4505 memcpy(header, &mpls, sizeof(mpls)); 4506 header += sizeof(mpls); 4507 action_encap_data->conf.size = header - 4508 action_encap_data->data; 4509 action->conf = &action_encap_data->conf; 4510 return ret; 4511 } 4512 4513 /** Parse MPLSOGRE decap action. */ 4514 static int 4515 parse_vc_action_mplsogre_decap(struct context *ctx, const struct token *token, 4516 const char *str, unsigned int len, 4517 void *buf, unsigned int size) 4518 { 4519 struct buffer *out = buf; 4520 struct rte_flow_action *action; 4521 struct action_raw_decap_data *action_decap_data; 4522 struct rte_flow_item_eth eth = { .type = 0, }; 4523 struct rte_flow_item_vlan vlan = {.tci = 0}; 4524 struct rte_flow_item_ipv4 ipv4 = { 4525 .hdr = { 4526 .next_proto_id = IPPROTO_GRE, 4527 }, 4528 }; 4529 struct rte_flow_item_ipv6 ipv6 = { 4530 .hdr = { 4531 .proto = IPPROTO_GRE, 4532 }, 4533 }; 4534 struct rte_flow_item_gre gre = { 4535 .protocol = rte_cpu_to_be_16(ETHER_TYPE_MPLS_UNICAST), 4536 }; 4537 struct rte_flow_item_mpls mpls; 4538 uint8_t *header; 4539 int ret; 4540 4541 ret = parse_vc(ctx, token, str, len, buf, size); 4542 if (ret < 0) 4543 return ret; 4544 /* Nothing else to do if there is no buffer. */ 4545 if (!out) 4546 return ret; 4547 if (!out->args.vc.actions_n) 4548 return -1; 4549 action = &out->args.vc.actions[out->args.vc.actions_n - 1]; 4550 /* Point to selected object. */ 4551 ctx->object = out->args.vc.data; 4552 ctx->objmask = NULL; 4553 /* Copy the headers to the buffer. */ 4554 action_decap_data = ctx->object; 4555 *action_decap_data = (struct action_raw_decap_data) { 4556 .conf = (struct rte_flow_action_raw_decap){ 4557 .data = action_decap_data->data, 4558 }, 4559 .data = {}, 4560 }; 4561 header = action_decap_data->data; 4562 if (mplsogre_decap_conf.select_vlan) 4563 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN); 4564 else if (mplsogre_encap_conf.select_ipv4) 4565 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4); 4566 else 4567 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6); 4568 memcpy(eth.dst.addr_bytes, 4569 mplsogre_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN); 4570 memcpy(eth.src.addr_bytes, 4571 mplsogre_encap_conf.eth_src, RTE_ETHER_ADDR_LEN); 4572 memcpy(header, ð, sizeof(eth)); 4573 header += sizeof(eth); 4574 if (mplsogre_encap_conf.select_vlan) { 4575 if (mplsogre_encap_conf.select_ipv4) 4576 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4); 4577 else 4578 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6); 4579 memcpy(header, &vlan, sizeof(vlan)); 4580 header += sizeof(vlan); 4581 } 4582 if (mplsogre_encap_conf.select_ipv4) { 4583 memcpy(header, &ipv4, sizeof(ipv4)); 4584 header += sizeof(ipv4); 4585 } else { 4586 memcpy(header, &ipv6, sizeof(ipv6)); 4587 header += sizeof(ipv6); 4588 } 4589 memcpy(header, &gre, sizeof(gre)); 4590 header += sizeof(gre); 4591 memset(&mpls, 0, sizeof(mpls)); 4592 memcpy(header, &mpls, sizeof(mpls)); 4593 header += sizeof(mpls); 4594 action_decap_data->conf.size = header - 4595 action_decap_data->data; 4596 action->conf = &action_decap_data->conf; 4597 return ret; 4598 } 4599 4600 /** Parse MPLSOUDP encap action. */ 4601 static int 4602 parse_vc_action_mplsoudp_encap(struct context *ctx, const struct token *token, 4603 const char *str, unsigned int len, 4604 void *buf, unsigned int size) 4605 { 4606 struct buffer *out = buf; 4607 struct rte_flow_action *action; 4608 struct action_raw_encap_data *action_encap_data; 4609 struct rte_flow_item_eth eth = { .type = 0, }; 4610 struct rte_flow_item_vlan vlan = { 4611 .tci = mplsoudp_encap_conf.vlan_tci, 4612 .inner_type = 0, 4613 }; 4614 struct rte_flow_item_ipv4 ipv4 = { 4615 .hdr = { 4616 .src_addr = mplsoudp_encap_conf.ipv4_src, 4617 .dst_addr = mplsoudp_encap_conf.ipv4_dst, 4618 .next_proto_id = IPPROTO_UDP, 4619 .version_ihl = RTE_IPV4_VHL_DEF, 4620 .time_to_live = IPDEFTTL, 4621 }, 4622 }; 4623 struct rte_flow_item_ipv6 ipv6 = { 4624 .hdr = { 4625 .proto = IPPROTO_UDP, 4626 .hop_limits = IPDEFTTL, 4627 }, 4628 }; 4629 struct rte_flow_item_udp udp = { 4630 .hdr = { 4631 .src_port = mplsoudp_encap_conf.udp_src, 4632 .dst_port = mplsoudp_encap_conf.udp_dst, 4633 }, 4634 }; 4635 struct rte_flow_item_mpls mpls; 4636 uint8_t *header; 4637 int ret; 4638 4639 ret = parse_vc(ctx, token, str, len, buf, size); 4640 if (ret < 0) 4641 return ret; 4642 /* Nothing else to do if there is no buffer. */ 4643 if (!out) 4644 return ret; 4645 if (!out->args.vc.actions_n) 4646 return -1; 4647 action = &out->args.vc.actions[out->args.vc.actions_n - 1]; 4648 /* Point to selected object. */ 4649 ctx->object = out->args.vc.data; 4650 ctx->objmask = NULL; 4651 /* Copy the headers to the buffer. */ 4652 action_encap_data = ctx->object; 4653 *action_encap_data = (struct action_raw_encap_data) { 4654 .conf = (struct rte_flow_action_raw_encap){ 4655 .data = action_encap_data->data, 4656 }, 4657 .data = {}, 4658 .preserve = {}, 4659 }; 4660 header = action_encap_data->data; 4661 if (mplsoudp_encap_conf.select_vlan) 4662 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN); 4663 else if (mplsoudp_encap_conf.select_ipv4) 4664 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4); 4665 else 4666 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6); 4667 memcpy(eth.dst.addr_bytes, 4668 mplsoudp_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN); 4669 memcpy(eth.src.addr_bytes, 4670 mplsoudp_encap_conf.eth_src, RTE_ETHER_ADDR_LEN); 4671 memcpy(header, ð, sizeof(eth)); 4672 header += sizeof(eth); 4673 if (mplsoudp_encap_conf.select_vlan) { 4674 if (mplsoudp_encap_conf.select_ipv4) 4675 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4); 4676 else 4677 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6); 4678 memcpy(header, &vlan, sizeof(vlan)); 4679 header += sizeof(vlan); 4680 } 4681 if (mplsoudp_encap_conf.select_ipv4) { 4682 memcpy(header, &ipv4, sizeof(ipv4)); 4683 header += sizeof(ipv4); 4684 } else { 4685 memcpy(&ipv6.hdr.src_addr, 4686 &mplsoudp_encap_conf.ipv6_src, 4687 sizeof(mplsoudp_encap_conf.ipv6_src)); 4688 memcpy(&ipv6.hdr.dst_addr, 4689 &mplsoudp_encap_conf.ipv6_dst, 4690 sizeof(mplsoudp_encap_conf.ipv6_dst)); 4691 memcpy(header, &ipv6, sizeof(ipv6)); 4692 header += sizeof(ipv6); 4693 } 4694 memcpy(header, &udp, sizeof(udp)); 4695 header += sizeof(udp); 4696 memcpy(mpls.label_tc_s, mplsoudp_encap_conf.label, 4697 RTE_DIM(mplsoudp_encap_conf.label)); 4698 mpls.label_tc_s[2] |= 0x1; 4699 memcpy(header, &mpls, sizeof(mpls)); 4700 header += sizeof(mpls); 4701 action_encap_data->conf.size = header - 4702 action_encap_data->data; 4703 action->conf = &action_encap_data->conf; 4704 return ret; 4705 } 4706 4707 /** Parse MPLSOUDP decap action. */ 4708 static int 4709 parse_vc_action_mplsoudp_decap(struct context *ctx, const struct token *token, 4710 const char *str, unsigned int len, 4711 void *buf, unsigned int size) 4712 { 4713 struct buffer *out = buf; 4714 struct rte_flow_action *action; 4715 struct action_raw_decap_data *action_decap_data; 4716 struct rte_flow_item_eth eth = { .type = 0, }; 4717 struct rte_flow_item_vlan vlan = {.tci = 0}; 4718 struct rte_flow_item_ipv4 ipv4 = { 4719 .hdr = { 4720 .next_proto_id = IPPROTO_UDP, 4721 }, 4722 }; 4723 struct rte_flow_item_ipv6 ipv6 = { 4724 .hdr = { 4725 .proto = IPPROTO_UDP, 4726 }, 4727 }; 4728 struct rte_flow_item_udp udp = { 4729 .hdr = { 4730 .dst_port = rte_cpu_to_be_16(6635), 4731 }, 4732 }; 4733 struct rte_flow_item_mpls mpls; 4734 uint8_t *header; 4735 int ret; 4736 4737 ret = parse_vc(ctx, token, str, len, buf, size); 4738 if (ret < 0) 4739 return ret; 4740 /* Nothing else to do if there is no buffer. */ 4741 if (!out) 4742 return ret; 4743 if (!out->args.vc.actions_n) 4744 return -1; 4745 action = &out->args.vc.actions[out->args.vc.actions_n - 1]; 4746 /* Point to selected object. */ 4747 ctx->object = out->args.vc.data; 4748 ctx->objmask = NULL; 4749 /* Copy the headers to the buffer. */ 4750 action_decap_data = ctx->object; 4751 *action_decap_data = (struct action_raw_decap_data) { 4752 .conf = (struct rte_flow_action_raw_decap){ 4753 .data = action_decap_data->data, 4754 }, 4755 .data = {}, 4756 }; 4757 header = action_decap_data->data; 4758 if (mplsoudp_decap_conf.select_vlan) 4759 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN); 4760 else if (mplsoudp_encap_conf.select_ipv4) 4761 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4); 4762 else 4763 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6); 4764 memcpy(eth.dst.addr_bytes, 4765 mplsoudp_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN); 4766 memcpy(eth.src.addr_bytes, 4767 mplsoudp_encap_conf.eth_src, RTE_ETHER_ADDR_LEN); 4768 memcpy(header, ð, sizeof(eth)); 4769 header += sizeof(eth); 4770 if (mplsoudp_encap_conf.select_vlan) { 4771 if (mplsoudp_encap_conf.select_ipv4) 4772 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4); 4773 else 4774 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6); 4775 memcpy(header, &vlan, sizeof(vlan)); 4776 header += sizeof(vlan); 4777 } 4778 if (mplsoudp_encap_conf.select_ipv4) { 4779 memcpy(header, &ipv4, sizeof(ipv4)); 4780 header += sizeof(ipv4); 4781 } else { 4782 memcpy(header, &ipv6, sizeof(ipv6)); 4783 header += sizeof(ipv6); 4784 } 4785 memcpy(header, &udp, sizeof(udp)); 4786 header += sizeof(udp); 4787 memset(&mpls, 0, sizeof(mpls)); 4788 memcpy(header, &mpls, sizeof(mpls)); 4789 header += sizeof(mpls); 4790 action_decap_data->conf.size = header - 4791 action_decap_data->data; 4792 action->conf = &action_decap_data->conf; 4793 return ret; 4794 } 4795 4796 static int 4797 parse_vc_action_raw_decap_index(struct context *ctx, const struct token *token, 4798 const char *str, unsigned int len, void *buf, 4799 unsigned int size) 4800 { 4801 struct action_raw_decap_data *action_raw_decap_data; 4802 struct rte_flow_action *action; 4803 const struct arg *arg; 4804 struct buffer *out = buf; 4805 int ret; 4806 uint16_t idx; 4807 4808 RTE_SET_USED(token); 4809 RTE_SET_USED(buf); 4810 RTE_SET_USED(size); 4811 arg = ARGS_ENTRY_ARB_BOUNDED 4812 (offsetof(struct action_raw_decap_data, idx), 4813 sizeof(((struct action_raw_decap_data *)0)->idx), 4814 0, RAW_ENCAP_CONFS_MAX_NUM - 1); 4815 if (push_args(ctx, arg)) 4816 return -1; 4817 ret = parse_int(ctx, token, str, len, NULL, 0); 4818 if (ret < 0) { 4819 pop_args(ctx); 4820 return -1; 4821 } 4822 if (!ctx->object) 4823 return len; 4824 action = &out->args.vc.actions[out->args.vc.actions_n - 1]; 4825 action_raw_decap_data = ctx->object; 4826 idx = action_raw_decap_data->idx; 4827 action_raw_decap_data->conf.data = raw_decap_confs[idx].data; 4828 action_raw_decap_data->conf.size = raw_decap_confs[idx].size; 4829 action->conf = &action_raw_decap_data->conf; 4830 return len; 4831 } 4832 4833 4834 static int 4835 parse_vc_action_raw_encap_index(struct context *ctx, const struct token *token, 4836 const char *str, unsigned int len, void *buf, 4837 unsigned int size) 4838 { 4839 struct action_raw_encap_data *action_raw_encap_data; 4840 struct rte_flow_action *action; 4841 const struct arg *arg; 4842 struct buffer *out = buf; 4843 int ret; 4844 uint16_t idx; 4845 4846 RTE_SET_USED(token); 4847 RTE_SET_USED(buf); 4848 RTE_SET_USED(size); 4849 if (ctx->curr != ACTION_RAW_ENCAP_INDEX_VALUE) 4850 return -1; 4851 arg = ARGS_ENTRY_ARB_BOUNDED 4852 (offsetof(struct action_raw_encap_data, idx), 4853 sizeof(((struct action_raw_encap_data *)0)->idx), 4854 0, RAW_ENCAP_CONFS_MAX_NUM - 1); 4855 if (push_args(ctx, arg)) 4856 return -1; 4857 ret = parse_int(ctx, token, str, len, NULL, 0); 4858 if (ret < 0) { 4859 pop_args(ctx); 4860 return -1; 4861 } 4862 if (!ctx->object) 4863 return len; 4864 action = &out->args.vc.actions[out->args.vc.actions_n - 1]; 4865 action_raw_encap_data = ctx->object; 4866 idx = action_raw_encap_data->idx; 4867 action_raw_encap_data->conf.data = raw_encap_confs[idx].data; 4868 action_raw_encap_data->conf.size = raw_encap_confs[idx].size; 4869 action_raw_encap_data->conf.preserve = NULL; 4870 action->conf = &action_raw_encap_data->conf; 4871 return len; 4872 } 4873 4874 static int 4875 parse_vc_action_raw_encap(struct context *ctx, const struct token *token, 4876 const char *str, unsigned int len, void *buf, 4877 unsigned int size) 4878 { 4879 struct buffer *out = buf; 4880 struct rte_flow_action *action; 4881 struct action_raw_encap_data *action_raw_encap_data = NULL; 4882 int ret; 4883 4884 ret = parse_vc(ctx, token, str, len, buf, size); 4885 if (ret < 0) 4886 return ret; 4887 /* Nothing else to do if there is no buffer. */ 4888 if (!out) 4889 return ret; 4890 if (!out->args.vc.actions_n) 4891 return -1; 4892 action = &out->args.vc.actions[out->args.vc.actions_n - 1]; 4893 /* Point to selected object. */ 4894 ctx->object = out->args.vc.data; 4895 ctx->objmask = NULL; 4896 /* Copy the headers to the buffer. */ 4897 action_raw_encap_data = ctx->object; 4898 action_raw_encap_data->conf.data = raw_encap_confs[0].data; 4899 action_raw_encap_data->conf.preserve = NULL; 4900 action_raw_encap_data->conf.size = raw_encap_confs[0].size; 4901 action->conf = &action_raw_encap_data->conf; 4902 return ret; 4903 } 4904 4905 static int 4906 parse_vc_action_raw_decap(struct context *ctx, const struct token *token, 4907 const char *str, unsigned int len, void *buf, 4908 unsigned int size) 4909 { 4910 struct buffer *out = buf; 4911 struct rte_flow_action *action; 4912 struct action_raw_decap_data *action_raw_decap_data = NULL; 4913 int ret; 4914 4915 ret = parse_vc(ctx, token, str, len, buf, size); 4916 if (ret < 0) 4917 return ret; 4918 /* Nothing else to do if there is no buffer. */ 4919 if (!out) 4920 return ret; 4921 if (!out->args.vc.actions_n) 4922 return -1; 4923 action = &out->args.vc.actions[out->args.vc.actions_n - 1]; 4924 /* Point to selected object. */ 4925 ctx->object = out->args.vc.data; 4926 ctx->objmask = NULL; 4927 /* Copy the headers to the buffer. */ 4928 action_raw_decap_data = ctx->object; 4929 action_raw_decap_data->conf.data = raw_decap_confs[0].data; 4930 action_raw_decap_data->conf.size = raw_decap_confs[0].size; 4931 action->conf = &action_raw_decap_data->conf; 4932 return ret; 4933 } 4934 4935 static int 4936 parse_vc_action_set_meta(struct context *ctx, const struct token *token, 4937 const char *str, unsigned int len, void *buf, 4938 unsigned int size) 4939 { 4940 int ret; 4941 4942 ret = parse_vc(ctx, token, str, len, buf, size); 4943 if (ret < 0) 4944 return ret; 4945 ret = rte_flow_dynf_metadata_register(); 4946 if (ret < 0) 4947 return -1; 4948 return len; 4949 } 4950 4951 /** Parse tokens for destroy command. */ 4952 static int 4953 parse_destroy(struct context *ctx, const struct token *token, 4954 const char *str, unsigned int len, 4955 void *buf, unsigned int size) 4956 { 4957 struct buffer *out = buf; 4958 4959 /* Token name must match. */ 4960 if (parse_default(ctx, token, str, len, NULL, 0) < 0) 4961 return -1; 4962 /* Nothing else to do if there is no buffer. */ 4963 if (!out) 4964 return len; 4965 if (!out->command) { 4966 if (ctx->curr != DESTROY) 4967 return -1; 4968 if (sizeof(*out) > size) 4969 return -1; 4970 out->command = ctx->curr; 4971 ctx->objdata = 0; 4972 ctx->object = out; 4973 ctx->objmask = NULL; 4974 out->args.destroy.rule = 4975 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1), 4976 sizeof(double)); 4977 return len; 4978 } 4979 if (((uint8_t *)(out->args.destroy.rule + out->args.destroy.rule_n) + 4980 sizeof(*out->args.destroy.rule)) > (uint8_t *)out + size) 4981 return -1; 4982 ctx->objdata = 0; 4983 ctx->object = out->args.destroy.rule + out->args.destroy.rule_n++; 4984 ctx->objmask = NULL; 4985 return len; 4986 } 4987 4988 /** Parse tokens for flush command. */ 4989 static int 4990 parse_flush(struct context *ctx, const struct token *token, 4991 const char *str, unsigned int len, 4992 void *buf, unsigned int size) 4993 { 4994 struct buffer *out = buf; 4995 4996 /* Token name must match. */ 4997 if (parse_default(ctx, token, str, len, NULL, 0) < 0) 4998 return -1; 4999 /* Nothing else to do if there is no buffer. */ 5000 if (!out) 5001 return len; 5002 if (!out->command) { 5003 if (ctx->curr != FLUSH) 5004 return -1; 5005 if (sizeof(*out) > size) 5006 return -1; 5007 out->command = ctx->curr; 5008 ctx->objdata = 0; 5009 ctx->object = out; 5010 ctx->objmask = NULL; 5011 } 5012 return len; 5013 } 5014 5015 /** Parse tokens for query command. */ 5016 static int 5017 parse_query(struct context *ctx, const struct token *token, 5018 const char *str, unsigned int len, 5019 void *buf, unsigned int size) 5020 { 5021 struct buffer *out = buf; 5022 5023 /* Token name must match. */ 5024 if (parse_default(ctx, token, str, len, NULL, 0) < 0) 5025 return -1; 5026 /* Nothing else to do if there is no buffer. */ 5027 if (!out) 5028 return len; 5029 if (!out->command) { 5030 if (ctx->curr != QUERY) 5031 return -1; 5032 if (sizeof(*out) > size) 5033 return -1; 5034 out->command = ctx->curr; 5035 ctx->objdata = 0; 5036 ctx->object = out; 5037 ctx->objmask = NULL; 5038 } 5039 return len; 5040 } 5041 5042 /** Parse action names. */ 5043 static int 5044 parse_action(struct context *ctx, const struct token *token, 5045 const char *str, unsigned int len, 5046 void *buf, unsigned int size) 5047 { 5048 struct buffer *out = buf; 5049 const struct arg *arg = pop_args(ctx); 5050 unsigned int i; 5051 5052 (void)size; 5053 /* Argument is expected. */ 5054 if (!arg) 5055 return -1; 5056 /* Parse action name. */ 5057 for (i = 0; next_action[i]; ++i) { 5058 const struct parse_action_priv *priv; 5059 5060 token = &token_list[next_action[i]]; 5061 if (strcmp_partial(token->name, str, len)) 5062 continue; 5063 priv = token->priv; 5064 if (!priv) 5065 goto error; 5066 if (out) 5067 memcpy((uint8_t *)ctx->object + arg->offset, 5068 &priv->type, 5069 arg->size); 5070 return len; 5071 } 5072 error: 5073 push_args(ctx, arg); 5074 return -1; 5075 } 5076 5077 /** Parse tokens for list command. */ 5078 static int 5079 parse_list(struct context *ctx, const struct token *token, 5080 const char *str, unsigned int len, 5081 void *buf, unsigned int size) 5082 { 5083 struct buffer *out = buf; 5084 5085 /* Token name must match. */ 5086 if (parse_default(ctx, token, str, len, NULL, 0) < 0) 5087 return -1; 5088 /* Nothing else to do if there is no buffer. */ 5089 if (!out) 5090 return len; 5091 if (!out->command) { 5092 if (ctx->curr != LIST) 5093 return -1; 5094 if (sizeof(*out) > size) 5095 return -1; 5096 out->command = ctx->curr; 5097 ctx->objdata = 0; 5098 ctx->object = out; 5099 ctx->objmask = NULL; 5100 out->args.list.group = 5101 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1), 5102 sizeof(double)); 5103 return len; 5104 } 5105 if (((uint8_t *)(out->args.list.group + out->args.list.group_n) + 5106 sizeof(*out->args.list.group)) > (uint8_t *)out + size) 5107 return -1; 5108 ctx->objdata = 0; 5109 ctx->object = out->args.list.group + out->args.list.group_n++; 5110 ctx->objmask = NULL; 5111 return len; 5112 } 5113 5114 /** Parse tokens for isolate command. */ 5115 static int 5116 parse_isolate(struct context *ctx, const struct token *token, 5117 const char *str, unsigned int len, 5118 void *buf, unsigned int size) 5119 { 5120 struct buffer *out = buf; 5121 5122 /* Token name must match. */ 5123 if (parse_default(ctx, token, str, len, NULL, 0) < 0) 5124 return -1; 5125 /* Nothing else to do if there is no buffer. */ 5126 if (!out) 5127 return len; 5128 if (!out->command) { 5129 if (ctx->curr != ISOLATE) 5130 return -1; 5131 if (sizeof(*out) > size) 5132 return -1; 5133 out->command = ctx->curr; 5134 ctx->objdata = 0; 5135 ctx->object = out; 5136 ctx->objmask = NULL; 5137 } 5138 return len; 5139 } 5140 5141 /** 5142 * Parse signed/unsigned integers 8 to 64-bit long. 5143 * 5144 * Last argument (ctx->args) is retrieved to determine integer type and 5145 * storage location. 5146 */ 5147 static int 5148 parse_int(struct context *ctx, const struct token *token, 5149 const char *str, unsigned int len, 5150 void *buf, unsigned int size) 5151 { 5152 const struct arg *arg = pop_args(ctx); 5153 uintmax_t u; 5154 char *end; 5155 5156 (void)token; 5157 /* Argument is expected. */ 5158 if (!arg) 5159 return -1; 5160 errno = 0; 5161 u = arg->sign ? 5162 (uintmax_t)strtoimax(str, &end, 0) : 5163 strtoumax(str, &end, 0); 5164 if (errno || (size_t)(end - str) != len) 5165 goto error; 5166 if (arg->bounded && 5167 ((arg->sign && ((intmax_t)u < (intmax_t)arg->min || 5168 (intmax_t)u > (intmax_t)arg->max)) || 5169 (!arg->sign && (u < arg->min || u > arg->max)))) 5170 goto error; 5171 if (!ctx->object) 5172 return len; 5173 if (arg->mask) { 5174 if (!arg_entry_bf_fill(ctx->object, u, arg) || 5175 !arg_entry_bf_fill(ctx->objmask, -1, arg)) 5176 goto error; 5177 return len; 5178 } 5179 buf = (uint8_t *)ctx->object + arg->offset; 5180 size = arg->size; 5181 if (u > RTE_LEN2MASK(size * CHAR_BIT, uint64_t)) 5182 return -1; 5183 objmask: 5184 switch (size) { 5185 case sizeof(uint8_t): 5186 *(uint8_t *)buf = u; 5187 break; 5188 case sizeof(uint16_t): 5189 *(uint16_t *)buf = arg->hton ? rte_cpu_to_be_16(u) : u; 5190 break; 5191 case sizeof(uint8_t [3]): 5192 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN 5193 if (!arg->hton) { 5194 ((uint8_t *)buf)[0] = u; 5195 ((uint8_t *)buf)[1] = u >> 8; 5196 ((uint8_t *)buf)[2] = u >> 16; 5197 break; 5198 } 5199 #endif 5200 ((uint8_t *)buf)[0] = u >> 16; 5201 ((uint8_t *)buf)[1] = u >> 8; 5202 ((uint8_t *)buf)[2] = u; 5203 break; 5204 case sizeof(uint32_t): 5205 *(uint32_t *)buf = arg->hton ? rte_cpu_to_be_32(u) : u; 5206 break; 5207 case sizeof(uint64_t): 5208 *(uint64_t *)buf = arg->hton ? rte_cpu_to_be_64(u) : u; 5209 break; 5210 default: 5211 goto error; 5212 } 5213 if (ctx->objmask && buf != (uint8_t *)ctx->objmask + arg->offset) { 5214 u = -1; 5215 buf = (uint8_t *)ctx->objmask + arg->offset; 5216 goto objmask; 5217 } 5218 return len; 5219 error: 5220 push_args(ctx, arg); 5221 return -1; 5222 } 5223 5224 /** 5225 * Parse a string. 5226 * 5227 * Three arguments (ctx->args) are retrieved from the stack to store data, 5228 * its actual length and address (in that order). 5229 */ 5230 static int 5231 parse_string(struct context *ctx, const struct token *token, 5232 const char *str, unsigned int len, 5233 void *buf, unsigned int size) 5234 { 5235 const struct arg *arg_data = pop_args(ctx); 5236 const struct arg *arg_len = pop_args(ctx); 5237 const struct arg *arg_addr = pop_args(ctx); 5238 char tmp[16]; /* Ought to be enough. */ 5239 int ret; 5240 5241 /* Arguments are expected. */ 5242 if (!arg_data) 5243 return -1; 5244 if (!arg_len) { 5245 push_args(ctx, arg_data); 5246 return -1; 5247 } 5248 if (!arg_addr) { 5249 push_args(ctx, arg_len); 5250 push_args(ctx, arg_data); 5251 return -1; 5252 } 5253 size = arg_data->size; 5254 /* Bit-mask fill is not supported. */ 5255 if (arg_data->mask || size < len) 5256 goto error; 5257 if (!ctx->object) 5258 return len; 5259 /* Let parse_int() fill length information first. */ 5260 ret = snprintf(tmp, sizeof(tmp), "%u", len); 5261 if (ret < 0) 5262 goto error; 5263 push_args(ctx, arg_len); 5264 ret = parse_int(ctx, token, tmp, ret, NULL, 0); 5265 if (ret < 0) { 5266 pop_args(ctx); 5267 goto error; 5268 } 5269 buf = (uint8_t *)ctx->object + arg_data->offset; 5270 /* Output buffer is not necessarily NUL-terminated. */ 5271 memcpy(buf, str, len); 5272 memset((uint8_t *)buf + len, 0x00, size - len); 5273 if (ctx->objmask) 5274 memset((uint8_t *)ctx->objmask + arg_data->offset, 0xff, len); 5275 /* Save address if requested. */ 5276 if (arg_addr->size) { 5277 memcpy((uint8_t *)ctx->object + arg_addr->offset, 5278 (void *[]){ 5279 (uint8_t *)ctx->object + arg_data->offset 5280 }, 5281 arg_addr->size); 5282 if (ctx->objmask) 5283 memcpy((uint8_t *)ctx->objmask + arg_addr->offset, 5284 (void *[]){ 5285 (uint8_t *)ctx->objmask + arg_data->offset 5286 }, 5287 arg_addr->size); 5288 } 5289 return len; 5290 error: 5291 push_args(ctx, arg_addr); 5292 push_args(ctx, arg_len); 5293 push_args(ctx, arg_data); 5294 return -1; 5295 } 5296 5297 static int 5298 parse_hex_string(const char *src, uint8_t *dst, uint32_t *size) 5299 { 5300 char *c = NULL; 5301 uint32_t i, len; 5302 char tmp[3]; 5303 5304 /* Check input parameters */ 5305 if ((src == NULL) || 5306 (dst == NULL) || 5307 (size == NULL) || 5308 (*size == 0)) 5309 return -1; 5310 5311 /* Convert chars to bytes */ 5312 for (i = 0, len = 0; i < *size; i += 2) { 5313 snprintf(tmp, 3, "%s", src + i); 5314 dst[len++] = strtoul(tmp, &c, 16); 5315 if (*c != 0) { 5316 len--; 5317 dst[len] = 0; 5318 *size = len; 5319 return -1; 5320 } 5321 } 5322 dst[len] = 0; 5323 *size = len; 5324 5325 return 0; 5326 } 5327 5328 static int 5329 parse_hex(struct context *ctx, const struct token *token, 5330 const char *str, unsigned int len, 5331 void *buf, unsigned int size) 5332 { 5333 const struct arg *arg_data = pop_args(ctx); 5334 const struct arg *arg_len = pop_args(ctx); 5335 const struct arg *arg_addr = pop_args(ctx); 5336 char tmp[16]; /* Ought to be enough. */ 5337 int ret; 5338 unsigned int hexlen = len; 5339 unsigned int length = 256; 5340 uint8_t hex_tmp[length]; 5341 5342 /* Arguments are expected. */ 5343 if (!arg_data) 5344 return -1; 5345 if (!arg_len) { 5346 push_args(ctx, arg_data); 5347 return -1; 5348 } 5349 if (!arg_addr) { 5350 push_args(ctx, arg_len); 5351 push_args(ctx, arg_data); 5352 return -1; 5353 } 5354 size = arg_data->size; 5355 /* Bit-mask fill is not supported. */ 5356 if (arg_data->mask) 5357 goto error; 5358 if (!ctx->object) 5359 return len; 5360 5361 /* translate bytes string to array. */ 5362 if (str[0] == '0' && ((str[1] == 'x') || 5363 (str[1] == 'X'))) { 5364 str += 2; 5365 hexlen -= 2; 5366 } 5367 if (hexlen > length) 5368 return -1; 5369 ret = parse_hex_string(str, hex_tmp, &hexlen); 5370 if (ret < 0) 5371 goto error; 5372 /* Let parse_int() fill length information first. */ 5373 ret = snprintf(tmp, sizeof(tmp), "%u", hexlen); 5374 if (ret < 0) 5375 goto error; 5376 push_args(ctx, arg_len); 5377 ret = parse_int(ctx, token, tmp, ret, NULL, 0); 5378 if (ret < 0) { 5379 pop_args(ctx); 5380 goto error; 5381 } 5382 buf = (uint8_t *)ctx->object + arg_data->offset; 5383 /* Output buffer is not necessarily NUL-terminated. */ 5384 memcpy(buf, hex_tmp, hexlen); 5385 memset((uint8_t *)buf + hexlen, 0x00, size - hexlen); 5386 if (ctx->objmask) 5387 memset((uint8_t *)ctx->objmask + arg_data->offset, 5388 0xff, hexlen); 5389 /* Save address if requested. */ 5390 if (arg_addr->size) { 5391 memcpy((uint8_t *)ctx->object + arg_addr->offset, 5392 (void *[]){ 5393 (uint8_t *)ctx->object + arg_data->offset 5394 }, 5395 arg_addr->size); 5396 if (ctx->objmask) 5397 memcpy((uint8_t *)ctx->objmask + arg_addr->offset, 5398 (void *[]){ 5399 (uint8_t *)ctx->objmask + arg_data->offset 5400 }, 5401 arg_addr->size); 5402 } 5403 return len; 5404 error: 5405 push_args(ctx, arg_addr); 5406 push_args(ctx, arg_len); 5407 push_args(ctx, arg_data); 5408 return -1; 5409 5410 } 5411 5412 /** 5413 * Parse a MAC address. 5414 * 5415 * Last argument (ctx->args) is retrieved to determine storage size and 5416 * location. 5417 */ 5418 static int 5419 parse_mac_addr(struct context *ctx, const struct token *token, 5420 const char *str, unsigned int len, 5421 void *buf, unsigned int size) 5422 { 5423 const struct arg *arg = pop_args(ctx); 5424 struct rte_ether_addr tmp; 5425 int ret; 5426 5427 (void)token; 5428 /* Argument is expected. */ 5429 if (!arg) 5430 return -1; 5431 size = arg->size; 5432 /* Bit-mask fill is not supported. */ 5433 if (arg->mask || size != sizeof(tmp)) 5434 goto error; 5435 /* Only network endian is supported. */ 5436 if (!arg->hton) 5437 goto error; 5438 ret = cmdline_parse_etheraddr(NULL, str, &tmp, size); 5439 if (ret < 0 || (unsigned int)ret != len) 5440 goto error; 5441 if (!ctx->object) 5442 return len; 5443 buf = (uint8_t *)ctx->object + arg->offset; 5444 memcpy(buf, &tmp, size); 5445 if (ctx->objmask) 5446 memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size); 5447 return len; 5448 error: 5449 push_args(ctx, arg); 5450 return -1; 5451 } 5452 5453 /** 5454 * Parse an IPv4 address. 5455 * 5456 * Last argument (ctx->args) is retrieved to determine storage size and 5457 * location. 5458 */ 5459 static int 5460 parse_ipv4_addr(struct context *ctx, const struct token *token, 5461 const char *str, unsigned int len, 5462 void *buf, unsigned int size) 5463 { 5464 const struct arg *arg = pop_args(ctx); 5465 char str2[len + 1]; 5466 struct in_addr tmp; 5467 int ret; 5468 5469 /* Argument is expected. */ 5470 if (!arg) 5471 return -1; 5472 size = arg->size; 5473 /* Bit-mask fill is not supported. */ 5474 if (arg->mask || size != sizeof(tmp)) 5475 goto error; 5476 /* Only network endian is supported. */ 5477 if (!arg->hton) 5478 goto error; 5479 memcpy(str2, str, len); 5480 str2[len] = '\0'; 5481 ret = inet_pton(AF_INET, str2, &tmp); 5482 if (ret != 1) { 5483 /* Attempt integer parsing. */ 5484 push_args(ctx, arg); 5485 return parse_int(ctx, token, str, len, buf, size); 5486 } 5487 if (!ctx->object) 5488 return len; 5489 buf = (uint8_t *)ctx->object + arg->offset; 5490 memcpy(buf, &tmp, size); 5491 if (ctx->objmask) 5492 memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size); 5493 return len; 5494 error: 5495 push_args(ctx, arg); 5496 return -1; 5497 } 5498 5499 /** 5500 * Parse an IPv6 address. 5501 * 5502 * Last argument (ctx->args) is retrieved to determine storage size and 5503 * location. 5504 */ 5505 static int 5506 parse_ipv6_addr(struct context *ctx, const struct token *token, 5507 const char *str, unsigned int len, 5508 void *buf, unsigned int size) 5509 { 5510 const struct arg *arg = pop_args(ctx); 5511 char str2[len + 1]; 5512 struct in6_addr tmp; 5513 int ret; 5514 5515 (void)token; 5516 /* Argument is expected. */ 5517 if (!arg) 5518 return -1; 5519 size = arg->size; 5520 /* Bit-mask fill is not supported. */ 5521 if (arg->mask || size != sizeof(tmp)) 5522 goto error; 5523 /* Only network endian is supported. */ 5524 if (!arg->hton) 5525 goto error; 5526 memcpy(str2, str, len); 5527 str2[len] = '\0'; 5528 ret = inet_pton(AF_INET6, str2, &tmp); 5529 if (ret != 1) 5530 goto error; 5531 if (!ctx->object) 5532 return len; 5533 buf = (uint8_t *)ctx->object + arg->offset; 5534 memcpy(buf, &tmp, size); 5535 if (ctx->objmask) 5536 memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size); 5537 return len; 5538 error: 5539 push_args(ctx, arg); 5540 return -1; 5541 } 5542 5543 /** Boolean values (even indices stand for false). */ 5544 static const char *const boolean_name[] = { 5545 "0", "1", 5546 "false", "true", 5547 "no", "yes", 5548 "N", "Y", 5549 "off", "on", 5550 NULL, 5551 }; 5552 5553 /** 5554 * Parse a boolean value. 5555 * 5556 * Last argument (ctx->args) is retrieved to determine storage size and 5557 * location. 5558 */ 5559 static int 5560 parse_boolean(struct context *ctx, const struct token *token, 5561 const char *str, unsigned int len, 5562 void *buf, unsigned int size) 5563 { 5564 const struct arg *arg = pop_args(ctx); 5565 unsigned int i; 5566 int ret; 5567 5568 /* Argument is expected. */ 5569 if (!arg) 5570 return -1; 5571 for (i = 0; boolean_name[i]; ++i) 5572 if (!strcmp_partial(boolean_name[i], str, len)) 5573 break; 5574 /* Process token as integer. */ 5575 if (boolean_name[i]) 5576 str = i & 1 ? "1" : "0"; 5577 push_args(ctx, arg); 5578 ret = parse_int(ctx, token, str, strlen(str), buf, size); 5579 return ret > 0 ? (int)len : ret; 5580 } 5581 5582 /** Parse port and update context. */ 5583 static int 5584 parse_port(struct context *ctx, const struct token *token, 5585 const char *str, unsigned int len, 5586 void *buf, unsigned int size) 5587 { 5588 struct buffer *out = &(struct buffer){ .port = 0 }; 5589 int ret; 5590 5591 if (buf) 5592 out = buf; 5593 else { 5594 ctx->objdata = 0; 5595 ctx->object = out; 5596 ctx->objmask = NULL; 5597 size = sizeof(*out); 5598 } 5599 ret = parse_int(ctx, token, str, len, out, size); 5600 if (ret >= 0) 5601 ctx->port = out->port; 5602 if (!buf) 5603 ctx->object = NULL; 5604 return ret; 5605 } 5606 5607 /** Parse set command, initialize output buffer for subsequent tokens. */ 5608 static int 5609 parse_set_raw_encap_decap(struct context *ctx, const struct token *token, 5610 const char *str, unsigned int len, 5611 void *buf, unsigned int size) 5612 { 5613 struct buffer *out = buf; 5614 5615 /* Token name must match. */ 5616 if (parse_default(ctx, token, str, len, NULL, 0) < 0) 5617 return -1; 5618 /* Nothing else to do if there is no buffer. */ 5619 if (!out) 5620 return len; 5621 /* Make sure buffer is large enough. */ 5622 if (size < sizeof(*out)) 5623 return -1; 5624 ctx->objdata = 0; 5625 ctx->objmask = NULL; 5626 ctx->object = out; 5627 if (!out->command) 5628 return -1; 5629 out->command = ctx->curr; 5630 return len; 5631 } 5632 5633 /** 5634 * Parse set raw_encap/raw_decap command, 5635 * initialize output buffer for subsequent tokens. 5636 */ 5637 static int 5638 parse_set_init(struct context *ctx, const struct token *token, 5639 const char *str, unsigned int len, 5640 void *buf, unsigned int size) 5641 { 5642 struct buffer *out = buf; 5643 5644 /* Token name must match. */ 5645 if (parse_default(ctx, token, str, len, NULL, 0) < 0) 5646 return -1; 5647 /* Nothing else to do if there is no buffer. */ 5648 if (!out) 5649 return len; 5650 /* Make sure buffer is large enough. */ 5651 if (size < sizeof(*out)) 5652 return -1; 5653 /* Initialize buffer. */ 5654 memset(out, 0x00, sizeof(*out)); 5655 memset((uint8_t *)out + sizeof(*out), 0x22, size - sizeof(*out)); 5656 ctx->objdata = 0; 5657 ctx->object = out; 5658 ctx->objmask = NULL; 5659 if (!out->command) { 5660 if (ctx->curr != SET) 5661 return -1; 5662 if (sizeof(*out) > size) 5663 return -1; 5664 out->command = ctx->curr; 5665 out->args.vc.data = (uint8_t *)out + size; 5666 /* All we need is pattern */ 5667 out->args.vc.pattern = 5668 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1), 5669 sizeof(double)); 5670 ctx->object = out->args.vc.pattern; 5671 } 5672 return len; 5673 } 5674 5675 /** No completion. */ 5676 static int 5677 comp_none(struct context *ctx, const struct token *token, 5678 unsigned int ent, char *buf, unsigned int size) 5679 { 5680 (void)ctx; 5681 (void)token; 5682 (void)ent; 5683 (void)buf; 5684 (void)size; 5685 return 0; 5686 } 5687 5688 /** Complete boolean values. */ 5689 static int 5690 comp_boolean(struct context *ctx, const struct token *token, 5691 unsigned int ent, char *buf, unsigned int size) 5692 { 5693 unsigned int i; 5694 5695 (void)ctx; 5696 (void)token; 5697 for (i = 0; boolean_name[i]; ++i) 5698 if (buf && i == ent) 5699 return strlcpy(buf, boolean_name[i], size); 5700 if (buf) 5701 return -1; 5702 return i; 5703 } 5704 5705 /** Complete action names. */ 5706 static int 5707 comp_action(struct context *ctx, const struct token *token, 5708 unsigned int ent, char *buf, unsigned int size) 5709 { 5710 unsigned int i; 5711 5712 (void)ctx; 5713 (void)token; 5714 for (i = 0; next_action[i]; ++i) 5715 if (buf && i == ent) 5716 return strlcpy(buf, token_list[next_action[i]].name, 5717 size); 5718 if (buf) 5719 return -1; 5720 return i; 5721 } 5722 5723 /** Complete available ports. */ 5724 static int 5725 comp_port(struct context *ctx, const struct token *token, 5726 unsigned int ent, char *buf, unsigned int size) 5727 { 5728 unsigned int i = 0; 5729 portid_t p; 5730 5731 (void)ctx; 5732 (void)token; 5733 RTE_ETH_FOREACH_DEV(p) { 5734 if (buf && i == ent) 5735 return snprintf(buf, size, "%u", p); 5736 ++i; 5737 } 5738 if (buf) 5739 return -1; 5740 return i; 5741 } 5742 5743 /** Complete available rule IDs. */ 5744 static int 5745 comp_rule_id(struct context *ctx, const struct token *token, 5746 unsigned int ent, char *buf, unsigned int size) 5747 { 5748 unsigned int i = 0; 5749 struct rte_port *port; 5750 struct port_flow *pf; 5751 5752 (void)token; 5753 if (port_id_is_invalid(ctx->port, DISABLED_WARN) || 5754 ctx->port == (portid_t)RTE_PORT_ALL) 5755 return -1; 5756 port = &ports[ctx->port]; 5757 for (pf = port->flow_list; pf != NULL; pf = pf->next) { 5758 if (buf && i == ent) 5759 return snprintf(buf, size, "%u", pf->id); 5760 ++i; 5761 } 5762 if (buf) 5763 return -1; 5764 return i; 5765 } 5766 5767 /** Complete type field for RSS action. */ 5768 static int 5769 comp_vc_action_rss_type(struct context *ctx, const struct token *token, 5770 unsigned int ent, char *buf, unsigned int size) 5771 { 5772 unsigned int i; 5773 5774 (void)ctx; 5775 (void)token; 5776 for (i = 0; rss_type_table[i].str; ++i) 5777 ; 5778 if (!buf) 5779 return i + 1; 5780 if (ent < i) 5781 return strlcpy(buf, rss_type_table[ent].str, size); 5782 if (ent == i) 5783 return snprintf(buf, size, "end"); 5784 return -1; 5785 } 5786 5787 /** Complete queue field for RSS action. */ 5788 static int 5789 comp_vc_action_rss_queue(struct context *ctx, const struct token *token, 5790 unsigned int ent, char *buf, unsigned int size) 5791 { 5792 (void)ctx; 5793 (void)token; 5794 if (!buf) 5795 return nb_rxq + 1; 5796 if (ent < nb_rxq) 5797 return snprintf(buf, size, "%u", ent); 5798 if (ent == nb_rxq) 5799 return snprintf(buf, size, "end"); 5800 return -1; 5801 } 5802 5803 /** Complete index number for set raw_encap/raw_decap commands. */ 5804 static int 5805 comp_set_raw_index(struct context *ctx, const struct token *token, 5806 unsigned int ent, char *buf, unsigned int size) 5807 { 5808 uint16_t idx = 0; 5809 uint16_t nb = 0; 5810 5811 RTE_SET_USED(ctx); 5812 RTE_SET_USED(token); 5813 for (idx = 0; idx < RAW_ENCAP_CONFS_MAX_NUM; ++idx) { 5814 if (buf && idx == ent) 5815 return snprintf(buf, size, "%u", idx); 5816 ++nb; 5817 } 5818 return nb; 5819 } 5820 5821 /** Internal context. */ 5822 static struct context cmd_flow_context; 5823 5824 /** Global parser instance (cmdline API). */ 5825 cmdline_parse_inst_t cmd_flow; 5826 cmdline_parse_inst_t cmd_set_raw; 5827 5828 /** Initialize context. */ 5829 static void 5830 cmd_flow_context_init(struct context *ctx) 5831 { 5832 /* A full memset() is not necessary. */ 5833 ctx->curr = ZERO; 5834 ctx->prev = ZERO; 5835 ctx->next_num = 0; 5836 ctx->args_num = 0; 5837 ctx->eol = 0; 5838 ctx->last = 0; 5839 ctx->port = 0; 5840 ctx->objdata = 0; 5841 ctx->object = NULL; 5842 ctx->objmask = NULL; 5843 } 5844 5845 /** Parse a token (cmdline API). */ 5846 static int 5847 cmd_flow_parse(cmdline_parse_token_hdr_t *hdr, const char *src, void *result, 5848 unsigned int size) 5849 { 5850 struct context *ctx = &cmd_flow_context; 5851 const struct token *token; 5852 const enum index *list; 5853 int len; 5854 int i; 5855 5856 (void)hdr; 5857 token = &token_list[ctx->curr]; 5858 /* Check argument length. */ 5859 ctx->eol = 0; 5860 ctx->last = 1; 5861 for (len = 0; src[len]; ++len) 5862 if (src[len] == '#' || isspace(src[len])) 5863 break; 5864 if (!len) 5865 return -1; 5866 /* Last argument and EOL detection. */ 5867 for (i = len; src[i]; ++i) 5868 if (src[i] == '#' || src[i] == '\r' || src[i] == '\n') 5869 break; 5870 else if (!isspace(src[i])) { 5871 ctx->last = 0; 5872 break; 5873 } 5874 for (; src[i]; ++i) 5875 if (src[i] == '\r' || src[i] == '\n') { 5876 ctx->eol = 1; 5877 break; 5878 } 5879 /* Initialize context if necessary. */ 5880 if (!ctx->next_num) { 5881 if (!token->next) 5882 return 0; 5883 ctx->next[ctx->next_num++] = token->next[0]; 5884 } 5885 /* Process argument through candidates. */ 5886 ctx->prev = ctx->curr; 5887 list = ctx->next[ctx->next_num - 1]; 5888 for (i = 0; list[i]; ++i) { 5889 const struct token *next = &token_list[list[i]]; 5890 int tmp; 5891 5892 ctx->curr = list[i]; 5893 if (next->call) 5894 tmp = next->call(ctx, next, src, len, result, size); 5895 else 5896 tmp = parse_default(ctx, next, src, len, result, size); 5897 if (tmp == -1 || tmp != len) 5898 continue; 5899 token = next; 5900 break; 5901 } 5902 if (!list[i]) 5903 return -1; 5904 --ctx->next_num; 5905 /* Push subsequent tokens if any. */ 5906 if (token->next) 5907 for (i = 0; token->next[i]; ++i) { 5908 if (ctx->next_num == RTE_DIM(ctx->next)) 5909 return -1; 5910 ctx->next[ctx->next_num++] = token->next[i]; 5911 } 5912 /* Push arguments if any. */ 5913 if (token->args) 5914 for (i = 0; token->args[i]; ++i) { 5915 if (ctx->args_num == RTE_DIM(ctx->args)) 5916 return -1; 5917 ctx->args[ctx->args_num++] = token->args[i]; 5918 } 5919 return len; 5920 } 5921 5922 /** Return number of completion entries (cmdline API). */ 5923 static int 5924 cmd_flow_complete_get_nb(cmdline_parse_token_hdr_t *hdr) 5925 { 5926 struct context *ctx = &cmd_flow_context; 5927 const struct token *token = &token_list[ctx->curr]; 5928 const enum index *list; 5929 int i; 5930 5931 (void)hdr; 5932 /* Count number of tokens in current list. */ 5933 if (ctx->next_num) 5934 list = ctx->next[ctx->next_num - 1]; 5935 else 5936 list = token->next[0]; 5937 for (i = 0; list[i]; ++i) 5938 ; 5939 if (!i) 5940 return 0; 5941 /* 5942 * If there is a single token, use its completion callback, otherwise 5943 * return the number of entries. 5944 */ 5945 token = &token_list[list[0]]; 5946 if (i == 1 && token->comp) { 5947 /* Save index for cmd_flow_get_help(). */ 5948 ctx->prev = list[0]; 5949 return token->comp(ctx, token, 0, NULL, 0); 5950 } 5951 return i; 5952 } 5953 5954 /** Return a completion entry (cmdline API). */ 5955 static int 5956 cmd_flow_complete_get_elt(cmdline_parse_token_hdr_t *hdr, int index, 5957 char *dst, unsigned int size) 5958 { 5959 struct context *ctx = &cmd_flow_context; 5960 const struct token *token = &token_list[ctx->curr]; 5961 const enum index *list; 5962 int i; 5963 5964 (void)hdr; 5965 /* Count number of tokens in current list. */ 5966 if (ctx->next_num) 5967 list = ctx->next[ctx->next_num - 1]; 5968 else 5969 list = token->next[0]; 5970 for (i = 0; list[i]; ++i) 5971 ; 5972 if (!i) 5973 return -1; 5974 /* If there is a single token, use its completion callback. */ 5975 token = &token_list[list[0]]; 5976 if (i == 1 && token->comp) { 5977 /* Save index for cmd_flow_get_help(). */ 5978 ctx->prev = list[0]; 5979 return token->comp(ctx, token, index, dst, size) < 0 ? -1 : 0; 5980 } 5981 /* Otherwise make sure the index is valid and use defaults. */ 5982 if (index >= i) 5983 return -1; 5984 token = &token_list[list[index]]; 5985 strlcpy(dst, token->name, size); 5986 /* Save index for cmd_flow_get_help(). */ 5987 ctx->prev = list[index]; 5988 return 0; 5989 } 5990 5991 /** Populate help strings for current token (cmdline API). */ 5992 static int 5993 cmd_flow_get_help(cmdline_parse_token_hdr_t *hdr, char *dst, unsigned int size) 5994 { 5995 struct context *ctx = &cmd_flow_context; 5996 const struct token *token = &token_list[ctx->prev]; 5997 5998 (void)hdr; 5999 if (!size) 6000 return -1; 6001 /* Set token type and update global help with details. */ 6002 strlcpy(dst, (token->type ? token->type : "TOKEN"), size); 6003 if (token->help) 6004 cmd_flow.help_str = token->help; 6005 else 6006 cmd_flow.help_str = token->name; 6007 return 0; 6008 } 6009 6010 /** Token definition template (cmdline API). */ 6011 static struct cmdline_token_hdr cmd_flow_token_hdr = { 6012 .ops = &(struct cmdline_token_ops){ 6013 .parse = cmd_flow_parse, 6014 .complete_get_nb = cmd_flow_complete_get_nb, 6015 .complete_get_elt = cmd_flow_complete_get_elt, 6016 .get_help = cmd_flow_get_help, 6017 }, 6018 .offset = 0, 6019 }; 6020 6021 /** Populate the next dynamic token. */ 6022 static void 6023 cmd_flow_tok(cmdline_parse_token_hdr_t **hdr, 6024 cmdline_parse_token_hdr_t **hdr_inst) 6025 { 6026 struct context *ctx = &cmd_flow_context; 6027 6028 /* Always reinitialize context before requesting the first token. */ 6029 if (!(hdr_inst - cmd_flow.tokens)) 6030 cmd_flow_context_init(ctx); 6031 /* Return NULL when no more tokens are expected. */ 6032 if (!ctx->next_num && ctx->curr) { 6033 *hdr = NULL; 6034 return; 6035 } 6036 /* Determine if command should end here. */ 6037 if (ctx->eol && ctx->last && ctx->next_num) { 6038 const enum index *list = ctx->next[ctx->next_num - 1]; 6039 int i; 6040 6041 for (i = 0; list[i]; ++i) { 6042 if (list[i] != END) 6043 continue; 6044 *hdr = NULL; 6045 return; 6046 } 6047 } 6048 *hdr = &cmd_flow_token_hdr; 6049 } 6050 6051 /** Dispatch parsed buffer to function calls. */ 6052 static void 6053 cmd_flow_parsed(const struct buffer *in) 6054 { 6055 switch (in->command) { 6056 case VALIDATE: 6057 port_flow_validate(in->port, &in->args.vc.attr, 6058 in->args.vc.pattern, in->args.vc.actions); 6059 break; 6060 case CREATE: 6061 port_flow_create(in->port, &in->args.vc.attr, 6062 in->args.vc.pattern, in->args.vc.actions); 6063 break; 6064 case DESTROY: 6065 port_flow_destroy(in->port, in->args.destroy.rule_n, 6066 in->args.destroy.rule); 6067 break; 6068 case FLUSH: 6069 port_flow_flush(in->port); 6070 break; 6071 case QUERY: 6072 port_flow_query(in->port, in->args.query.rule, 6073 &in->args.query.action); 6074 break; 6075 case LIST: 6076 port_flow_list(in->port, in->args.list.group_n, 6077 in->args.list.group); 6078 break; 6079 case ISOLATE: 6080 port_flow_isolate(in->port, in->args.isolate.set); 6081 break; 6082 default: 6083 break; 6084 } 6085 } 6086 6087 /** Token generator and output processing callback (cmdline API). */ 6088 static void 6089 cmd_flow_cb(void *arg0, struct cmdline *cl, void *arg2) 6090 { 6091 if (cl == NULL) 6092 cmd_flow_tok(arg0, arg2); 6093 else 6094 cmd_flow_parsed(arg0); 6095 } 6096 6097 /** Global parser instance (cmdline API). */ 6098 cmdline_parse_inst_t cmd_flow = { 6099 .f = cmd_flow_cb, 6100 .data = NULL, /**< Unused. */ 6101 .help_str = NULL, /**< Updated by cmd_flow_get_help(). */ 6102 .tokens = { 6103 NULL, 6104 }, /**< Tokens are returned by cmd_flow_tok(). */ 6105 }; 6106 6107 /** set cmd facility. Reuse cmd flow's infrastructure as much as possible. */ 6108 6109 static void 6110 update_fields(uint8_t *buf, struct rte_flow_item *item, uint16_t next_proto) 6111 { 6112 struct rte_flow_item_ipv4 *ipv4; 6113 struct rte_flow_item_eth *eth; 6114 struct rte_flow_item_ipv6 *ipv6; 6115 struct rte_flow_item_vxlan *vxlan; 6116 struct rte_flow_item_vxlan_gpe *gpe; 6117 struct rte_flow_item_nvgre *nvgre; 6118 uint32_t ipv6_vtc_flow; 6119 6120 switch (item->type) { 6121 case RTE_FLOW_ITEM_TYPE_ETH: 6122 eth = (struct rte_flow_item_eth *)buf; 6123 if (next_proto) 6124 eth->type = rte_cpu_to_be_16(next_proto); 6125 break; 6126 case RTE_FLOW_ITEM_TYPE_IPV4: 6127 ipv4 = (struct rte_flow_item_ipv4 *)buf; 6128 ipv4->hdr.version_ihl = 0x45; 6129 if (next_proto && ipv4->hdr.next_proto_id == 0) 6130 ipv4->hdr.next_proto_id = (uint8_t)next_proto; 6131 break; 6132 case RTE_FLOW_ITEM_TYPE_IPV6: 6133 ipv6 = (struct rte_flow_item_ipv6 *)buf; 6134 if (next_proto && ipv6->hdr.proto == 0) 6135 ipv6->hdr.proto = (uint8_t)next_proto; 6136 ipv6_vtc_flow = rte_be_to_cpu_32(ipv6->hdr.vtc_flow); 6137 ipv6_vtc_flow &= 0x0FFFFFFF; /*< reset version bits. */ 6138 ipv6_vtc_flow |= 0x60000000; /*< set ipv6 version. */ 6139 ipv6->hdr.vtc_flow = rte_cpu_to_be_32(ipv6_vtc_flow); 6140 break; 6141 case RTE_FLOW_ITEM_TYPE_VXLAN: 6142 vxlan = (struct rte_flow_item_vxlan *)buf; 6143 vxlan->flags = 0x08; 6144 break; 6145 case RTE_FLOW_ITEM_TYPE_VXLAN_GPE: 6146 gpe = (struct rte_flow_item_vxlan_gpe *)buf; 6147 gpe->flags = 0x0C; 6148 break; 6149 case RTE_FLOW_ITEM_TYPE_NVGRE: 6150 nvgre = (struct rte_flow_item_nvgre *)buf; 6151 nvgre->protocol = rte_cpu_to_be_16(0x6558); 6152 nvgre->c_k_s_rsvd0_ver = rte_cpu_to_be_16(0x2000); 6153 break; 6154 default: 6155 break; 6156 } 6157 } 6158 6159 /** Helper of get item's default mask. */ 6160 static const void * 6161 flow_item_default_mask(const struct rte_flow_item *item) 6162 { 6163 const void *mask = NULL; 6164 static rte_be32_t gre_key_default_mask = RTE_BE32(UINT32_MAX); 6165 6166 switch (item->type) { 6167 case RTE_FLOW_ITEM_TYPE_ANY: 6168 mask = &rte_flow_item_any_mask; 6169 break; 6170 case RTE_FLOW_ITEM_TYPE_VF: 6171 mask = &rte_flow_item_vf_mask; 6172 break; 6173 case RTE_FLOW_ITEM_TYPE_PORT_ID: 6174 mask = &rte_flow_item_port_id_mask; 6175 break; 6176 case RTE_FLOW_ITEM_TYPE_RAW: 6177 mask = &rte_flow_item_raw_mask; 6178 break; 6179 case RTE_FLOW_ITEM_TYPE_ETH: 6180 mask = &rte_flow_item_eth_mask; 6181 break; 6182 case RTE_FLOW_ITEM_TYPE_VLAN: 6183 mask = &rte_flow_item_vlan_mask; 6184 break; 6185 case RTE_FLOW_ITEM_TYPE_IPV4: 6186 mask = &rte_flow_item_ipv4_mask; 6187 break; 6188 case RTE_FLOW_ITEM_TYPE_IPV6: 6189 mask = &rte_flow_item_ipv6_mask; 6190 break; 6191 case RTE_FLOW_ITEM_TYPE_ICMP: 6192 mask = &rte_flow_item_icmp_mask; 6193 break; 6194 case RTE_FLOW_ITEM_TYPE_UDP: 6195 mask = &rte_flow_item_udp_mask; 6196 break; 6197 case RTE_FLOW_ITEM_TYPE_TCP: 6198 mask = &rte_flow_item_tcp_mask; 6199 break; 6200 case RTE_FLOW_ITEM_TYPE_SCTP: 6201 mask = &rte_flow_item_sctp_mask; 6202 break; 6203 case RTE_FLOW_ITEM_TYPE_VXLAN: 6204 mask = &rte_flow_item_vxlan_mask; 6205 break; 6206 case RTE_FLOW_ITEM_TYPE_VXLAN_GPE: 6207 mask = &rte_flow_item_vxlan_gpe_mask; 6208 break; 6209 case RTE_FLOW_ITEM_TYPE_E_TAG: 6210 mask = &rte_flow_item_e_tag_mask; 6211 break; 6212 case RTE_FLOW_ITEM_TYPE_NVGRE: 6213 mask = &rte_flow_item_nvgre_mask; 6214 break; 6215 case RTE_FLOW_ITEM_TYPE_MPLS: 6216 mask = &rte_flow_item_mpls_mask; 6217 break; 6218 case RTE_FLOW_ITEM_TYPE_GRE: 6219 mask = &rte_flow_item_gre_mask; 6220 break; 6221 case RTE_FLOW_ITEM_TYPE_GRE_KEY: 6222 mask = &gre_key_default_mask; 6223 break; 6224 case RTE_FLOW_ITEM_TYPE_META: 6225 mask = &rte_flow_item_meta_mask; 6226 break; 6227 case RTE_FLOW_ITEM_TYPE_FUZZY: 6228 mask = &rte_flow_item_fuzzy_mask; 6229 break; 6230 case RTE_FLOW_ITEM_TYPE_GTP: 6231 mask = &rte_flow_item_gtp_mask; 6232 break; 6233 case RTE_FLOW_ITEM_TYPE_ESP: 6234 mask = &rte_flow_item_esp_mask; 6235 break; 6236 case RTE_FLOW_ITEM_TYPE_GTP_PSC: 6237 mask = &rte_flow_item_gtp_psc_mask; 6238 break; 6239 case RTE_FLOW_ITEM_TYPE_PPPOE_PROTO_ID: 6240 mask = &rte_flow_item_pppoe_proto_id_mask; 6241 default: 6242 break; 6243 } 6244 return mask; 6245 } 6246 6247 6248 6249 /** Dispatch parsed buffer to function calls. */ 6250 static void 6251 cmd_set_raw_parsed(const struct buffer *in) 6252 { 6253 uint32_t n = in->args.vc.pattern_n; 6254 int i = 0; 6255 struct rte_flow_item *item = NULL; 6256 size_t size = 0; 6257 uint8_t *data = NULL; 6258 uint8_t *data_tail = NULL; 6259 size_t *total_size = NULL; 6260 uint16_t upper_layer = 0; 6261 uint16_t proto = 0; 6262 uint16_t idx = in->port; /* We borrow port field as index */ 6263 6264 RTE_ASSERT(in->command == SET_RAW_ENCAP || 6265 in->command == SET_RAW_DECAP); 6266 if (in->command == SET_RAW_ENCAP) { 6267 total_size = &raw_encap_confs[idx].size; 6268 data = (uint8_t *)&raw_encap_confs[idx].data; 6269 } else { 6270 total_size = &raw_decap_confs[idx].size; 6271 data = (uint8_t *)&raw_decap_confs[idx].data; 6272 } 6273 *total_size = 0; 6274 memset(data, 0x00, ACTION_RAW_ENCAP_MAX_DATA); 6275 /* process hdr from upper layer to low layer (L3/L4 -> L2). */ 6276 data_tail = data + ACTION_RAW_ENCAP_MAX_DATA; 6277 for (i = n - 1 ; i >= 0; --i) { 6278 item = in->args.vc.pattern + i; 6279 if (item->spec == NULL) 6280 item->spec = flow_item_default_mask(item); 6281 switch (item->type) { 6282 case RTE_FLOW_ITEM_TYPE_ETH: 6283 size = sizeof(struct rte_flow_item_eth); 6284 break; 6285 case RTE_FLOW_ITEM_TYPE_VLAN: 6286 size = sizeof(struct rte_flow_item_vlan); 6287 proto = RTE_ETHER_TYPE_VLAN; 6288 break; 6289 case RTE_FLOW_ITEM_TYPE_IPV4: 6290 size = sizeof(struct rte_flow_item_ipv4); 6291 proto = RTE_ETHER_TYPE_IPV4; 6292 break; 6293 case RTE_FLOW_ITEM_TYPE_IPV6: 6294 size = sizeof(struct rte_flow_item_ipv6); 6295 proto = RTE_ETHER_TYPE_IPV6; 6296 break; 6297 case RTE_FLOW_ITEM_TYPE_UDP: 6298 size = sizeof(struct rte_flow_item_udp); 6299 proto = 0x11; 6300 break; 6301 case RTE_FLOW_ITEM_TYPE_TCP: 6302 size = sizeof(struct rte_flow_item_tcp); 6303 proto = 0x06; 6304 break; 6305 case RTE_FLOW_ITEM_TYPE_VXLAN: 6306 size = sizeof(struct rte_flow_item_vxlan); 6307 break; 6308 case RTE_FLOW_ITEM_TYPE_VXLAN_GPE: 6309 size = sizeof(struct rte_flow_item_vxlan_gpe); 6310 break; 6311 case RTE_FLOW_ITEM_TYPE_GRE: 6312 size = sizeof(struct rte_flow_item_gre); 6313 proto = 0x2F; 6314 break; 6315 case RTE_FLOW_ITEM_TYPE_GRE_KEY: 6316 size = sizeof(rte_be32_t); 6317 proto = 0x0; 6318 break; 6319 case RTE_FLOW_ITEM_TYPE_MPLS: 6320 size = sizeof(struct rte_flow_item_mpls); 6321 proto = 0x0; 6322 break; 6323 case RTE_FLOW_ITEM_TYPE_NVGRE: 6324 size = sizeof(struct rte_flow_item_nvgre); 6325 proto = 0x2F; 6326 break; 6327 case RTE_FLOW_ITEM_TYPE_GENEVE: 6328 size = sizeof(struct rte_flow_item_geneve); 6329 break; 6330 default: 6331 printf("Error - Not supported item\n"); 6332 *total_size = 0; 6333 memset(data, 0x00, ACTION_RAW_ENCAP_MAX_DATA); 6334 return; 6335 } 6336 *total_size += size; 6337 rte_memcpy(data_tail - (*total_size), item->spec, size); 6338 /* update some fields which cannot be set by cmdline */ 6339 update_fields((data_tail - (*total_size)), item, 6340 upper_layer); 6341 upper_layer = proto; 6342 } 6343 if (verbose_level & 0x1) 6344 printf("total data size is %zu\n", (*total_size)); 6345 RTE_ASSERT((*total_size) <= ACTION_RAW_ENCAP_MAX_DATA); 6346 memmove(data, (data_tail - (*total_size)), *total_size); 6347 } 6348 6349 /** Populate help strings for current token (cmdline API). */ 6350 static int 6351 cmd_set_raw_get_help(cmdline_parse_token_hdr_t *hdr, char *dst, 6352 unsigned int size) 6353 { 6354 struct context *ctx = &cmd_flow_context; 6355 const struct token *token = &token_list[ctx->prev]; 6356 6357 (void)hdr; 6358 if (!size) 6359 return -1; 6360 /* Set token type and update global help with details. */ 6361 snprintf(dst, size, "%s", (token->type ? token->type : "TOKEN")); 6362 if (token->help) 6363 cmd_set_raw.help_str = token->help; 6364 else 6365 cmd_set_raw.help_str = token->name; 6366 return 0; 6367 } 6368 6369 /** Token definition template (cmdline API). */ 6370 static struct cmdline_token_hdr cmd_set_raw_token_hdr = { 6371 .ops = &(struct cmdline_token_ops){ 6372 .parse = cmd_flow_parse, 6373 .complete_get_nb = cmd_flow_complete_get_nb, 6374 .complete_get_elt = cmd_flow_complete_get_elt, 6375 .get_help = cmd_set_raw_get_help, 6376 }, 6377 .offset = 0, 6378 }; 6379 6380 /** Populate the next dynamic token. */ 6381 static void 6382 cmd_set_raw_tok(cmdline_parse_token_hdr_t **hdr, 6383 cmdline_parse_token_hdr_t **hdr_inst) 6384 { 6385 struct context *ctx = &cmd_flow_context; 6386 6387 /* Always reinitialize context before requesting the first token. */ 6388 if (!(hdr_inst - cmd_set_raw.tokens)) { 6389 cmd_flow_context_init(ctx); 6390 ctx->curr = START_SET; 6391 } 6392 /* Return NULL when no more tokens are expected. */ 6393 if (!ctx->next_num && (ctx->curr != START_SET)) { 6394 *hdr = NULL; 6395 return; 6396 } 6397 /* Determine if command should end here. */ 6398 if (ctx->eol && ctx->last && ctx->next_num) { 6399 const enum index *list = ctx->next[ctx->next_num - 1]; 6400 int i; 6401 6402 for (i = 0; list[i]; ++i) { 6403 if (list[i] != END) 6404 continue; 6405 *hdr = NULL; 6406 return; 6407 } 6408 } 6409 *hdr = &cmd_set_raw_token_hdr; 6410 } 6411 6412 /** Token generator and output processing callback (cmdline API). */ 6413 static void 6414 cmd_set_raw_cb(void *arg0, struct cmdline *cl, void *arg2) 6415 { 6416 if (cl == NULL) 6417 cmd_set_raw_tok(arg0, arg2); 6418 else 6419 cmd_set_raw_parsed(arg0); 6420 } 6421 6422 /** Global parser instance (cmdline API). */ 6423 cmdline_parse_inst_t cmd_set_raw = { 6424 .f = cmd_set_raw_cb, 6425 .data = NULL, /**< Unused. */ 6426 .help_str = NULL, /**< Updated by cmd_flow_get_help(). */ 6427 .tokens = { 6428 NULL, 6429 }, /**< Tokens are returned by cmd_flow_tok(). */ 6430 }; 6431 6432 /* *** display raw_encap/raw_decap buf */ 6433 struct cmd_show_set_raw_result { 6434 cmdline_fixed_string_t cmd_show; 6435 cmdline_fixed_string_t cmd_what; 6436 cmdline_fixed_string_t cmd_all; 6437 uint16_t cmd_index; 6438 }; 6439 6440 static void 6441 cmd_show_set_raw_parsed(void *parsed_result, struct cmdline *cl, void *data) 6442 { 6443 struct cmd_show_set_raw_result *res = parsed_result; 6444 uint16_t index = res->cmd_index; 6445 uint8_t all = 0; 6446 uint8_t *raw_data = NULL; 6447 size_t raw_size = 0; 6448 char title[16] = {0}; 6449 6450 RTE_SET_USED(cl); 6451 RTE_SET_USED(data); 6452 if (!strcmp(res->cmd_all, "all")) { 6453 all = 1; 6454 index = 0; 6455 } else if (index >= RAW_ENCAP_CONFS_MAX_NUM) { 6456 printf("index should be 0-%u\n", RAW_ENCAP_CONFS_MAX_NUM - 1); 6457 return; 6458 } 6459 do { 6460 if (!strcmp(res->cmd_what, "raw_encap")) { 6461 raw_data = (uint8_t *)&raw_encap_confs[index].data; 6462 raw_size = raw_encap_confs[index].size; 6463 snprintf(title, 16, "\nindex: %u", index); 6464 rte_hexdump(stdout, title, raw_data, raw_size); 6465 } else { 6466 raw_data = (uint8_t *)&raw_decap_confs[index].data; 6467 raw_size = raw_decap_confs[index].size; 6468 snprintf(title, 16, "\nindex: %u", index); 6469 rte_hexdump(stdout, title, raw_data, raw_size); 6470 } 6471 } while (all && ++index < RAW_ENCAP_CONFS_MAX_NUM); 6472 } 6473 6474 cmdline_parse_token_string_t cmd_show_set_raw_cmd_show = 6475 TOKEN_STRING_INITIALIZER(struct cmd_show_set_raw_result, 6476 cmd_show, "show"); 6477 cmdline_parse_token_string_t cmd_show_set_raw_cmd_what = 6478 TOKEN_STRING_INITIALIZER(struct cmd_show_set_raw_result, 6479 cmd_what, "raw_encap#raw_decap"); 6480 cmdline_parse_token_num_t cmd_show_set_raw_cmd_index = 6481 TOKEN_NUM_INITIALIZER(struct cmd_show_set_raw_result, 6482 cmd_index, UINT16); 6483 cmdline_parse_token_string_t cmd_show_set_raw_cmd_all = 6484 TOKEN_STRING_INITIALIZER(struct cmd_show_set_raw_result, 6485 cmd_all, "all"); 6486 cmdline_parse_inst_t cmd_show_set_raw = { 6487 .f = cmd_show_set_raw_parsed, 6488 .data = NULL, 6489 .help_str = "show <raw_encap|raw_decap> <index>", 6490 .tokens = { 6491 (void *)&cmd_show_set_raw_cmd_show, 6492 (void *)&cmd_show_set_raw_cmd_what, 6493 (void *)&cmd_show_set_raw_cmd_index, 6494 NULL, 6495 }, 6496 }; 6497 cmdline_parse_inst_t cmd_show_set_raw_all = { 6498 .f = cmd_show_set_raw_parsed, 6499 .data = NULL, 6500 .help_str = "show <raw_encap|raw_decap> all", 6501 .tokens = { 6502 (void *)&cmd_show_set_raw_cmd_show, 6503 (void *)&cmd_show_set_raw_cmd_what, 6504 (void *)&cmd_show_set_raw_cmd_all, 6505 NULL, 6506 }, 6507 }; 6508