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 .ttl = 0, 4539 }; 4540 uint8_t *header; 4541 int ret; 4542 4543 ret = parse_vc(ctx, token, str, len, buf, size); 4544 if (ret < 0) 4545 return ret; 4546 /* Nothing else to do if there is no buffer. */ 4547 if (!out) 4548 return ret; 4549 if (!out->args.vc.actions_n) 4550 return -1; 4551 action = &out->args.vc.actions[out->args.vc.actions_n - 1]; 4552 /* Point to selected object. */ 4553 ctx->object = out->args.vc.data; 4554 ctx->objmask = NULL; 4555 /* Copy the headers to the buffer. */ 4556 action_decap_data = ctx->object; 4557 *action_decap_data = (struct action_raw_decap_data) { 4558 .conf = (struct rte_flow_action_raw_decap){ 4559 .data = action_decap_data->data, 4560 }, 4561 .data = {}, 4562 }; 4563 header = action_decap_data->data; 4564 if (mplsogre_decap_conf.select_vlan) 4565 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN); 4566 else if (mplsogre_encap_conf.select_ipv4) 4567 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4); 4568 else 4569 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6); 4570 memcpy(eth.dst.addr_bytes, 4571 mplsogre_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN); 4572 memcpy(eth.src.addr_bytes, 4573 mplsogre_encap_conf.eth_src, RTE_ETHER_ADDR_LEN); 4574 memcpy(header, ð, sizeof(eth)); 4575 header += sizeof(eth); 4576 if (mplsogre_encap_conf.select_vlan) { 4577 if (mplsogre_encap_conf.select_ipv4) 4578 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4); 4579 else 4580 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6); 4581 memcpy(header, &vlan, sizeof(vlan)); 4582 header += sizeof(vlan); 4583 } 4584 if (mplsogre_encap_conf.select_ipv4) { 4585 memcpy(header, &ipv4, sizeof(ipv4)); 4586 header += sizeof(ipv4); 4587 } else { 4588 memcpy(header, &ipv6, sizeof(ipv6)); 4589 header += sizeof(ipv6); 4590 } 4591 memcpy(header, &gre, sizeof(gre)); 4592 header += sizeof(gre); 4593 memset(&mpls, 0, sizeof(mpls)); 4594 memcpy(header, &mpls, sizeof(mpls)); 4595 header += sizeof(mpls); 4596 action_decap_data->conf.size = header - 4597 action_decap_data->data; 4598 action->conf = &action_decap_data->conf; 4599 return ret; 4600 } 4601 4602 /** Parse MPLSOUDP encap action. */ 4603 static int 4604 parse_vc_action_mplsoudp_encap(struct context *ctx, const struct token *token, 4605 const char *str, unsigned int len, 4606 void *buf, unsigned int size) 4607 { 4608 struct buffer *out = buf; 4609 struct rte_flow_action *action; 4610 struct action_raw_encap_data *action_encap_data; 4611 struct rte_flow_item_eth eth = { .type = 0, }; 4612 struct rte_flow_item_vlan vlan = { 4613 .tci = mplsoudp_encap_conf.vlan_tci, 4614 .inner_type = 0, 4615 }; 4616 struct rte_flow_item_ipv4 ipv4 = { 4617 .hdr = { 4618 .src_addr = mplsoudp_encap_conf.ipv4_src, 4619 .dst_addr = mplsoudp_encap_conf.ipv4_dst, 4620 .next_proto_id = IPPROTO_UDP, 4621 .version_ihl = RTE_IPV4_VHL_DEF, 4622 .time_to_live = IPDEFTTL, 4623 }, 4624 }; 4625 struct rte_flow_item_ipv6 ipv6 = { 4626 .hdr = { 4627 .proto = IPPROTO_UDP, 4628 .hop_limits = IPDEFTTL, 4629 }, 4630 }; 4631 struct rte_flow_item_udp udp = { 4632 .hdr = { 4633 .src_port = mplsoudp_encap_conf.udp_src, 4634 .dst_port = mplsoudp_encap_conf.udp_dst, 4635 }, 4636 }; 4637 struct rte_flow_item_mpls mpls; 4638 uint8_t *header; 4639 int ret; 4640 4641 ret = parse_vc(ctx, token, str, len, buf, size); 4642 if (ret < 0) 4643 return ret; 4644 /* Nothing else to do if there is no buffer. */ 4645 if (!out) 4646 return ret; 4647 if (!out->args.vc.actions_n) 4648 return -1; 4649 action = &out->args.vc.actions[out->args.vc.actions_n - 1]; 4650 /* Point to selected object. */ 4651 ctx->object = out->args.vc.data; 4652 ctx->objmask = NULL; 4653 /* Copy the headers to the buffer. */ 4654 action_encap_data = ctx->object; 4655 *action_encap_data = (struct action_raw_encap_data) { 4656 .conf = (struct rte_flow_action_raw_encap){ 4657 .data = action_encap_data->data, 4658 }, 4659 .data = {}, 4660 .preserve = {}, 4661 }; 4662 header = action_encap_data->data; 4663 if (mplsoudp_encap_conf.select_vlan) 4664 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN); 4665 else if (mplsoudp_encap_conf.select_ipv4) 4666 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4); 4667 else 4668 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6); 4669 memcpy(eth.dst.addr_bytes, 4670 mplsoudp_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN); 4671 memcpy(eth.src.addr_bytes, 4672 mplsoudp_encap_conf.eth_src, RTE_ETHER_ADDR_LEN); 4673 memcpy(header, ð, sizeof(eth)); 4674 header += sizeof(eth); 4675 if (mplsoudp_encap_conf.select_vlan) { 4676 if (mplsoudp_encap_conf.select_ipv4) 4677 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4); 4678 else 4679 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6); 4680 memcpy(header, &vlan, sizeof(vlan)); 4681 header += sizeof(vlan); 4682 } 4683 if (mplsoudp_encap_conf.select_ipv4) { 4684 memcpy(header, &ipv4, sizeof(ipv4)); 4685 header += sizeof(ipv4); 4686 } else { 4687 memcpy(&ipv6.hdr.src_addr, 4688 &mplsoudp_encap_conf.ipv6_src, 4689 sizeof(mplsoudp_encap_conf.ipv6_src)); 4690 memcpy(&ipv6.hdr.dst_addr, 4691 &mplsoudp_encap_conf.ipv6_dst, 4692 sizeof(mplsoudp_encap_conf.ipv6_dst)); 4693 memcpy(header, &ipv6, sizeof(ipv6)); 4694 header += sizeof(ipv6); 4695 } 4696 memcpy(header, &udp, sizeof(udp)); 4697 header += sizeof(udp); 4698 memcpy(mpls.label_tc_s, mplsoudp_encap_conf.label, 4699 RTE_DIM(mplsoudp_encap_conf.label)); 4700 mpls.label_tc_s[2] |= 0x1; 4701 memcpy(header, &mpls, sizeof(mpls)); 4702 header += sizeof(mpls); 4703 action_encap_data->conf.size = header - 4704 action_encap_data->data; 4705 action->conf = &action_encap_data->conf; 4706 return ret; 4707 } 4708 4709 /** Parse MPLSOUDP decap action. */ 4710 static int 4711 parse_vc_action_mplsoudp_decap(struct context *ctx, const struct token *token, 4712 const char *str, unsigned int len, 4713 void *buf, unsigned int size) 4714 { 4715 struct buffer *out = buf; 4716 struct rte_flow_action *action; 4717 struct action_raw_decap_data *action_decap_data; 4718 struct rte_flow_item_eth eth = { .type = 0, }; 4719 struct rte_flow_item_vlan vlan = {.tci = 0}; 4720 struct rte_flow_item_ipv4 ipv4 = { 4721 .hdr = { 4722 .next_proto_id = IPPROTO_UDP, 4723 }, 4724 }; 4725 struct rte_flow_item_ipv6 ipv6 = { 4726 .hdr = { 4727 .proto = IPPROTO_UDP, 4728 }, 4729 }; 4730 struct rte_flow_item_udp udp = { 4731 .hdr = { 4732 .dst_port = rte_cpu_to_be_16(6635), 4733 }, 4734 }; 4735 struct rte_flow_item_mpls mpls; 4736 uint8_t *header; 4737 int ret; 4738 4739 ret = parse_vc(ctx, token, str, len, buf, size); 4740 if (ret < 0) 4741 return ret; 4742 /* Nothing else to do if there is no buffer. */ 4743 if (!out) 4744 return ret; 4745 if (!out->args.vc.actions_n) 4746 return -1; 4747 action = &out->args.vc.actions[out->args.vc.actions_n - 1]; 4748 /* Point to selected object. */ 4749 ctx->object = out->args.vc.data; 4750 ctx->objmask = NULL; 4751 /* Copy the headers to the buffer. */ 4752 action_decap_data = ctx->object; 4753 *action_decap_data = (struct action_raw_decap_data) { 4754 .conf = (struct rte_flow_action_raw_decap){ 4755 .data = action_decap_data->data, 4756 }, 4757 .data = {}, 4758 }; 4759 header = action_decap_data->data; 4760 if (mplsoudp_decap_conf.select_vlan) 4761 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN); 4762 else if (mplsoudp_encap_conf.select_ipv4) 4763 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4); 4764 else 4765 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6); 4766 memcpy(eth.dst.addr_bytes, 4767 mplsoudp_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN); 4768 memcpy(eth.src.addr_bytes, 4769 mplsoudp_encap_conf.eth_src, RTE_ETHER_ADDR_LEN); 4770 memcpy(header, ð, sizeof(eth)); 4771 header += sizeof(eth); 4772 if (mplsoudp_encap_conf.select_vlan) { 4773 if (mplsoudp_encap_conf.select_ipv4) 4774 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4); 4775 else 4776 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6); 4777 memcpy(header, &vlan, sizeof(vlan)); 4778 header += sizeof(vlan); 4779 } 4780 if (mplsoudp_encap_conf.select_ipv4) { 4781 memcpy(header, &ipv4, sizeof(ipv4)); 4782 header += sizeof(ipv4); 4783 } else { 4784 memcpy(header, &ipv6, sizeof(ipv6)); 4785 header += sizeof(ipv6); 4786 } 4787 memcpy(header, &udp, sizeof(udp)); 4788 header += sizeof(udp); 4789 memset(&mpls, 0, sizeof(mpls)); 4790 memcpy(header, &mpls, sizeof(mpls)); 4791 header += sizeof(mpls); 4792 action_decap_data->conf.size = header - 4793 action_decap_data->data; 4794 action->conf = &action_decap_data->conf; 4795 return ret; 4796 } 4797 4798 static int 4799 parse_vc_action_raw_decap_index(struct context *ctx, const struct token *token, 4800 const char *str, unsigned int len, void *buf, 4801 unsigned int size) 4802 { 4803 struct action_raw_decap_data *action_raw_decap_data; 4804 struct rte_flow_action *action; 4805 const struct arg *arg; 4806 struct buffer *out = buf; 4807 int ret; 4808 uint16_t idx; 4809 4810 RTE_SET_USED(token); 4811 RTE_SET_USED(buf); 4812 RTE_SET_USED(size); 4813 arg = ARGS_ENTRY_ARB_BOUNDED 4814 (offsetof(struct action_raw_decap_data, idx), 4815 sizeof(((struct action_raw_decap_data *)0)->idx), 4816 0, RAW_ENCAP_CONFS_MAX_NUM - 1); 4817 if (push_args(ctx, arg)) 4818 return -1; 4819 ret = parse_int(ctx, token, str, len, NULL, 0); 4820 if (ret < 0) { 4821 pop_args(ctx); 4822 return -1; 4823 } 4824 if (!ctx->object) 4825 return len; 4826 action = &out->args.vc.actions[out->args.vc.actions_n - 1]; 4827 action_raw_decap_data = ctx->object; 4828 idx = action_raw_decap_data->idx; 4829 action_raw_decap_data->conf.data = raw_decap_confs[idx].data; 4830 action_raw_decap_data->conf.size = raw_decap_confs[idx].size; 4831 action->conf = &action_raw_decap_data->conf; 4832 return len; 4833 } 4834 4835 4836 static int 4837 parse_vc_action_raw_encap_index(struct context *ctx, const struct token *token, 4838 const char *str, unsigned int len, void *buf, 4839 unsigned int size) 4840 { 4841 struct action_raw_encap_data *action_raw_encap_data; 4842 struct rte_flow_action *action; 4843 const struct arg *arg; 4844 struct buffer *out = buf; 4845 int ret; 4846 uint16_t idx; 4847 4848 RTE_SET_USED(token); 4849 RTE_SET_USED(buf); 4850 RTE_SET_USED(size); 4851 if (ctx->curr != ACTION_RAW_ENCAP_INDEX_VALUE) 4852 return -1; 4853 arg = ARGS_ENTRY_ARB_BOUNDED 4854 (offsetof(struct action_raw_encap_data, idx), 4855 sizeof(((struct action_raw_encap_data *)0)->idx), 4856 0, RAW_ENCAP_CONFS_MAX_NUM - 1); 4857 if (push_args(ctx, arg)) 4858 return -1; 4859 ret = parse_int(ctx, token, str, len, NULL, 0); 4860 if (ret < 0) { 4861 pop_args(ctx); 4862 return -1; 4863 } 4864 if (!ctx->object) 4865 return len; 4866 action = &out->args.vc.actions[out->args.vc.actions_n - 1]; 4867 action_raw_encap_data = ctx->object; 4868 idx = action_raw_encap_data->idx; 4869 action_raw_encap_data->conf.data = raw_encap_confs[idx].data; 4870 action_raw_encap_data->conf.size = raw_encap_confs[idx].size; 4871 action_raw_encap_data->conf.preserve = NULL; 4872 action->conf = &action_raw_encap_data->conf; 4873 return len; 4874 } 4875 4876 static int 4877 parse_vc_action_raw_encap(struct context *ctx, const struct token *token, 4878 const char *str, unsigned int len, void *buf, 4879 unsigned int size) 4880 { 4881 struct buffer *out = buf; 4882 struct rte_flow_action *action; 4883 struct action_raw_encap_data *action_raw_encap_data = NULL; 4884 int ret; 4885 4886 ret = parse_vc(ctx, token, str, len, buf, size); 4887 if (ret < 0) 4888 return ret; 4889 /* Nothing else to do if there is no buffer. */ 4890 if (!out) 4891 return ret; 4892 if (!out->args.vc.actions_n) 4893 return -1; 4894 action = &out->args.vc.actions[out->args.vc.actions_n - 1]; 4895 /* Point to selected object. */ 4896 ctx->object = out->args.vc.data; 4897 ctx->objmask = NULL; 4898 /* Copy the headers to the buffer. */ 4899 action_raw_encap_data = ctx->object; 4900 action_raw_encap_data->conf.data = raw_encap_confs[0].data; 4901 action_raw_encap_data->conf.preserve = NULL; 4902 action_raw_encap_data->conf.size = raw_encap_confs[0].size; 4903 action->conf = &action_raw_encap_data->conf; 4904 return ret; 4905 } 4906 4907 static int 4908 parse_vc_action_raw_decap(struct context *ctx, const struct token *token, 4909 const char *str, unsigned int len, void *buf, 4910 unsigned int size) 4911 { 4912 struct buffer *out = buf; 4913 struct rte_flow_action *action; 4914 struct action_raw_decap_data *action_raw_decap_data = NULL; 4915 int ret; 4916 4917 ret = parse_vc(ctx, token, str, len, buf, size); 4918 if (ret < 0) 4919 return ret; 4920 /* Nothing else to do if there is no buffer. */ 4921 if (!out) 4922 return ret; 4923 if (!out->args.vc.actions_n) 4924 return -1; 4925 action = &out->args.vc.actions[out->args.vc.actions_n - 1]; 4926 /* Point to selected object. */ 4927 ctx->object = out->args.vc.data; 4928 ctx->objmask = NULL; 4929 /* Copy the headers to the buffer. */ 4930 action_raw_decap_data = ctx->object; 4931 action_raw_decap_data->conf.data = raw_decap_confs[0].data; 4932 action_raw_decap_data->conf.size = raw_decap_confs[0].size; 4933 action->conf = &action_raw_decap_data->conf; 4934 return ret; 4935 } 4936 4937 static int 4938 parse_vc_action_set_meta(struct context *ctx, const struct token *token, 4939 const char *str, unsigned int len, void *buf, 4940 unsigned int size) 4941 { 4942 int ret; 4943 4944 ret = parse_vc(ctx, token, str, len, buf, size); 4945 if (ret < 0) 4946 return ret; 4947 ret = rte_flow_dynf_metadata_register(); 4948 if (ret < 0) 4949 return -1; 4950 return len; 4951 } 4952 4953 /** Parse tokens for destroy command. */ 4954 static int 4955 parse_destroy(struct context *ctx, const struct token *token, 4956 const char *str, unsigned int len, 4957 void *buf, unsigned int size) 4958 { 4959 struct buffer *out = buf; 4960 4961 /* Token name must match. */ 4962 if (parse_default(ctx, token, str, len, NULL, 0) < 0) 4963 return -1; 4964 /* Nothing else to do if there is no buffer. */ 4965 if (!out) 4966 return len; 4967 if (!out->command) { 4968 if (ctx->curr != DESTROY) 4969 return -1; 4970 if (sizeof(*out) > size) 4971 return -1; 4972 out->command = ctx->curr; 4973 ctx->objdata = 0; 4974 ctx->object = out; 4975 ctx->objmask = NULL; 4976 out->args.destroy.rule = 4977 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1), 4978 sizeof(double)); 4979 return len; 4980 } 4981 if (((uint8_t *)(out->args.destroy.rule + out->args.destroy.rule_n) + 4982 sizeof(*out->args.destroy.rule)) > (uint8_t *)out + size) 4983 return -1; 4984 ctx->objdata = 0; 4985 ctx->object = out->args.destroy.rule + out->args.destroy.rule_n++; 4986 ctx->objmask = NULL; 4987 return len; 4988 } 4989 4990 /** Parse tokens for flush command. */ 4991 static int 4992 parse_flush(struct context *ctx, const struct token *token, 4993 const char *str, unsigned int len, 4994 void *buf, unsigned int size) 4995 { 4996 struct buffer *out = buf; 4997 4998 /* Token name must match. */ 4999 if (parse_default(ctx, token, str, len, NULL, 0) < 0) 5000 return -1; 5001 /* Nothing else to do if there is no buffer. */ 5002 if (!out) 5003 return len; 5004 if (!out->command) { 5005 if (ctx->curr != FLUSH) 5006 return -1; 5007 if (sizeof(*out) > size) 5008 return -1; 5009 out->command = ctx->curr; 5010 ctx->objdata = 0; 5011 ctx->object = out; 5012 ctx->objmask = NULL; 5013 } 5014 return len; 5015 } 5016 5017 /** Parse tokens for query command. */ 5018 static int 5019 parse_query(struct context *ctx, const struct token *token, 5020 const char *str, unsigned int len, 5021 void *buf, unsigned int size) 5022 { 5023 struct buffer *out = buf; 5024 5025 /* Token name must match. */ 5026 if (parse_default(ctx, token, str, len, NULL, 0) < 0) 5027 return -1; 5028 /* Nothing else to do if there is no buffer. */ 5029 if (!out) 5030 return len; 5031 if (!out->command) { 5032 if (ctx->curr != QUERY) 5033 return -1; 5034 if (sizeof(*out) > size) 5035 return -1; 5036 out->command = ctx->curr; 5037 ctx->objdata = 0; 5038 ctx->object = out; 5039 ctx->objmask = NULL; 5040 } 5041 return len; 5042 } 5043 5044 /** Parse action names. */ 5045 static int 5046 parse_action(struct context *ctx, const struct token *token, 5047 const char *str, unsigned int len, 5048 void *buf, unsigned int size) 5049 { 5050 struct buffer *out = buf; 5051 const struct arg *arg = pop_args(ctx); 5052 unsigned int i; 5053 5054 (void)size; 5055 /* Argument is expected. */ 5056 if (!arg) 5057 return -1; 5058 /* Parse action name. */ 5059 for (i = 0; next_action[i]; ++i) { 5060 const struct parse_action_priv *priv; 5061 5062 token = &token_list[next_action[i]]; 5063 if (strcmp_partial(token->name, str, len)) 5064 continue; 5065 priv = token->priv; 5066 if (!priv) 5067 goto error; 5068 if (out) 5069 memcpy((uint8_t *)ctx->object + arg->offset, 5070 &priv->type, 5071 arg->size); 5072 return len; 5073 } 5074 error: 5075 push_args(ctx, arg); 5076 return -1; 5077 } 5078 5079 /** Parse tokens for list command. */ 5080 static int 5081 parse_list(struct context *ctx, const struct token *token, 5082 const char *str, unsigned int len, 5083 void *buf, unsigned int size) 5084 { 5085 struct buffer *out = buf; 5086 5087 /* Token name must match. */ 5088 if (parse_default(ctx, token, str, len, NULL, 0) < 0) 5089 return -1; 5090 /* Nothing else to do if there is no buffer. */ 5091 if (!out) 5092 return len; 5093 if (!out->command) { 5094 if (ctx->curr != LIST) 5095 return -1; 5096 if (sizeof(*out) > size) 5097 return -1; 5098 out->command = ctx->curr; 5099 ctx->objdata = 0; 5100 ctx->object = out; 5101 ctx->objmask = NULL; 5102 out->args.list.group = 5103 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1), 5104 sizeof(double)); 5105 return len; 5106 } 5107 if (((uint8_t *)(out->args.list.group + out->args.list.group_n) + 5108 sizeof(*out->args.list.group)) > (uint8_t *)out + size) 5109 return -1; 5110 ctx->objdata = 0; 5111 ctx->object = out->args.list.group + out->args.list.group_n++; 5112 ctx->objmask = NULL; 5113 return len; 5114 } 5115 5116 /** Parse tokens for isolate command. */ 5117 static int 5118 parse_isolate(struct context *ctx, const struct token *token, 5119 const char *str, unsigned int len, 5120 void *buf, unsigned int size) 5121 { 5122 struct buffer *out = buf; 5123 5124 /* Token name must match. */ 5125 if (parse_default(ctx, token, str, len, NULL, 0) < 0) 5126 return -1; 5127 /* Nothing else to do if there is no buffer. */ 5128 if (!out) 5129 return len; 5130 if (!out->command) { 5131 if (ctx->curr != ISOLATE) 5132 return -1; 5133 if (sizeof(*out) > size) 5134 return -1; 5135 out->command = ctx->curr; 5136 ctx->objdata = 0; 5137 ctx->object = out; 5138 ctx->objmask = NULL; 5139 } 5140 return len; 5141 } 5142 5143 /** 5144 * Parse signed/unsigned integers 8 to 64-bit long. 5145 * 5146 * Last argument (ctx->args) is retrieved to determine integer type and 5147 * storage location. 5148 */ 5149 static int 5150 parse_int(struct context *ctx, const struct token *token, 5151 const char *str, unsigned int len, 5152 void *buf, unsigned int size) 5153 { 5154 const struct arg *arg = pop_args(ctx); 5155 uintmax_t u; 5156 char *end; 5157 5158 (void)token; 5159 /* Argument is expected. */ 5160 if (!arg) 5161 return -1; 5162 errno = 0; 5163 u = arg->sign ? 5164 (uintmax_t)strtoimax(str, &end, 0) : 5165 strtoumax(str, &end, 0); 5166 if (errno || (size_t)(end - str) != len) 5167 goto error; 5168 if (arg->bounded && 5169 ((arg->sign && ((intmax_t)u < (intmax_t)arg->min || 5170 (intmax_t)u > (intmax_t)arg->max)) || 5171 (!arg->sign && (u < arg->min || u > arg->max)))) 5172 goto error; 5173 if (!ctx->object) 5174 return len; 5175 if (arg->mask) { 5176 if (!arg_entry_bf_fill(ctx->object, u, arg) || 5177 !arg_entry_bf_fill(ctx->objmask, -1, arg)) 5178 goto error; 5179 return len; 5180 } 5181 buf = (uint8_t *)ctx->object + arg->offset; 5182 size = arg->size; 5183 if (u > RTE_LEN2MASK(size * CHAR_BIT, uint64_t)) 5184 return -1; 5185 objmask: 5186 switch (size) { 5187 case sizeof(uint8_t): 5188 *(uint8_t *)buf = u; 5189 break; 5190 case sizeof(uint16_t): 5191 *(uint16_t *)buf = arg->hton ? rte_cpu_to_be_16(u) : u; 5192 break; 5193 case sizeof(uint8_t [3]): 5194 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN 5195 if (!arg->hton) { 5196 ((uint8_t *)buf)[0] = u; 5197 ((uint8_t *)buf)[1] = u >> 8; 5198 ((uint8_t *)buf)[2] = u >> 16; 5199 break; 5200 } 5201 #endif 5202 ((uint8_t *)buf)[0] = u >> 16; 5203 ((uint8_t *)buf)[1] = u >> 8; 5204 ((uint8_t *)buf)[2] = u; 5205 break; 5206 case sizeof(uint32_t): 5207 *(uint32_t *)buf = arg->hton ? rte_cpu_to_be_32(u) : u; 5208 break; 5209 case sizeof(uint64_t): 5210 *(uint64_t *)buf = arg->hton ? rte_cpu_to_be_64(u) : u; 5211 break; 5212 default: 5213 goto error; 5214 } 5215 if (ctx->objmask && buf != (uint8_t *)ctx->objmask + arg->offset) { 5216 u = -1; 5217 buf = (uint8_t *)ctx->objmask + arg->offset; 5218 goto objmask; 5219 } 5220 return len; 5221 error: 5222 push_args(ctx, arg); 5223 return -1; 5224 } 5225 5226 /** 5227 * Parse a string. 5228 * 5229 * Three arguments (ctx->args) are retrieved from the stack to store data, 5230 * its actual length and address (in that order). 5231 */ 5232 static int 5233 parse_string(struct context *ctx, const struct token *token, 5234 const char *str, unsigned int len, 5235 void *buf, unsigned int size) 5236 { 5237 const struct arg *arg_data = pop_args(ctx); 5238 const struct arg *arg_len = pop_args(ctx); 5239 const struct arg *arg_addr = pop_args(ctx); 5240 char tmp[16]; /* Ought to be enough. */ 5241 int ret; 5242 5243 /* Arguments are expected. */ 5244 if (!arg_data) 5245 return -1; 5246 if (!arg_len) { 5247 push_args(ctx, arg_data); 5248 return -1; 5249 } 5250 if (!arg_addr) { 5251 push_args(ctx, arg_len); 5252 push_args(ctx, arg_data); 5253 return -1; 5254 } 5255 size = arg_data->size; 5256 /* Bit-mask fill is not supported. */ 5257 if (arg_data->mask || size < len) 5258 goto error; 5259 if (!ctx->object) 5260 return len; 5261 /* Let parse_int() fill length information first. */ 5262 ret = snprintf(tmp, sizeof(tmp), "%u", len); 5263 if (ret < 0) 5264 goto error; 5265 push_args(ctx, arg_len); 5266 ret = parse_int(ctx, token, tmp, ret, NULL, 0); 5267 if (ret < 0) { 5268 pop_args(ctx); 5269 goto error; 5270 } 5271 buf = (uint8_t *)ctx->object + arg_data->offset; 5272 /* Output buffer is not necessarily NUL-terminated. */ 5273 memcpy(buf, str, len); 5274 memset((uint8_t *)buf + len, 0x00, size - len); 5275 if (ctx->objmask) 5276 memset((uint8_t *)ctx->objmask + arg_data->offset, 0xff, len); 5277 /* Save address if requested. */ 5278 if (arg_addr->size) { 5279 memcpy((uint8_t *)ctx->object + arg_addr->offset, 5280 (void *[]){ 5281 (uint8_t *)ctx->object + arg_data->offset 5282 }, 5283 arg_addr->size); 5284 if (ctx->objmask) 5285 memcpy((uint8_t *)ctx->objmask + arg_addr->offset, 5286 (void *[]){ 5287 (uint8_t *)ctx->objmask + arg_data->offset 5288 }, 5289 arg_addr->size); 5290 } 5291 return len; 5292 error: 5293 push_args(ctx, arg_addr); 5294 push_args(ctx, arg_len); 5295 push_args(ctx, arg_data); 5296 return -1; 5297 } 5298 5299 static int 5300 parse_hex_string(const char *src, uint8_t *dst, uint32_t *size) 5301 { 5302 char *c = NULL; 5303 uint32_t i, len; 5304 char tmp[3]; 5305 5306 /* Check input parameters */ 5307 if ((src == NULL) || 5308 (dst == NULL) || 5309 (size == NULL) || 5310 (*size == 0)) 5311 return -1; 5312 5313 /* Convert chars to bytes */ 5314 for (i = 0, len = 0; i < *size; i += 2) { 5315 snprintf(tmp, 3, "%s", src + i); 5316 dst[len++] = strtoul(tmp, &c, 16); 5317 if (*c != 0) { 5318 len--; 5319 dst[len] = 0; 5320 *size = len; 5321 return -1; 5322 } 5323 } 5324 dst[len] = 0; 5325 *size = len; 5326 5327 return 0; 5328 } 5329 5330 static int 5331 parse_hex(struct context *ctx, const struct token *token, 5332 const char *str, unsigned int len, 5333 void *buf, unsigned int size) 5334 { 5335 const struct arg *arg_data = pop_args(ctx); 5336 const struct arg *arg_len = pop_args(ctx); 5337 const struct arg *arg_addr = pop_args(ctx); 5338 char tmp[16]; /* Ought to be enough. */ 5339 int ret; 5340 unsigned int hexlen = len; 5341 unsigned int length = 256; 5342 uint8_t hex_tmp[length]; 5343 5344 /* Arguments are expected. */ 5345 if (!arg_data) 5346 return -1; 5347 if (!arg_len) { 5348 push_args(ctx, arg_data); 5349 return -1; 5350 } 5351 if (!arg_addr) { 5352 push_args(ctx, arg_len); 5353 push_args(ctx, arg_data); 5354 return -1; 5355 } 5356 size = arg_data->size; 5357 /* Bit-mask fill is not supported. */ 5358 if (arg_data->mask) 5359 goto error; 5360 if (!ctx->object) 5361 return len; 5362 5363 /* translate bytes string to array. */ 5364 if (str[0] == '0' && ((str[1] == 'x') || 5365 (str[1] == 'X'))) { 5366 str += 2; 5367 hexlen -= 2; 5368 } 5369 if (hexlen > length) 5370 return -1; 5371 ret = parse_hex_string(str, hex_tmp, &hexlen); 5372 if (ret < 0) 5373 goto error; 5374 /* Let parse_int() fill length information first. */ 5375 ret = snprintf(tmp, sizeof(tmp), "%u", hexlen); 5376 if (ret < 0) 5377 goto error; 5378 push_args(ctx, arg_len); 5379 ret = parse_int(ctx, token, tmp, ret, NULL, 0); 5380 if (ret < 0) { 5381 pop_args(ctx); 5382 goto error; 5383 } 5384 buf = (uint8_t *)ctx->object + arg_data->offset; 5385 /* Output buffer is not necessarily NUL-terminated. */ 5386 memcpy(buf, hex_tmp, hexlen); 5387 memset((uint8_t *)buf + hexlen, 0x00, size - hexlen); 5388 if (ctx->objmask) 5389 memset((uint8_t *)ctx->objmask + arg_data->offset, 5390 0xff, hexlen); 5391 /* Save address if requested. */ 5392 if (arg_addr->size) { 5393 memcpy((uint8_t *)ctx->object + arg_addr->offset, 5394 (void *[]){ 5395 (uint8_t *)ctx->object + arg_data->offset 5396 }, 5397 arg_addr->size); 5398 if (ctx->objmask) 5399 memcpy((uint8_t *)ctx->objmask + arg_addr->offset, 5400 (void *[]){ 5401 (uint8_t *)ctx->objmask + arg_data->offset 5402 }, 5403 arg_addr->size); 5404 } 5405 return len; 5406 error: 5407 push_args(ctx, arg_addr); 5408 push_args(ctx, arg_len); 5409 push_args(ctx, arg_data); 5410 return -1; 5411 5412 } 5413 5414 /** 5415 * Parse a MAC address. 5416 * 5417 * Last argument (ctx->args) is retrieved to determine storage size and 5418 * location. 5419 */ 5420 static int 5421 parse_mac_addr(struct context *ctx, const struct token *token, 5422 const char *str, unsigned int len, 5423 void *buf, unsigned int size) 5424 { 5425 const struct arg *arg = pop_args(ctx); 5426 struct rte_ether_addr tmp; 5427 int ret; 5428 5429 (void)token; 5430 /* Argument is expected. */ 5431 if (!arg) 5432 return -1; 5433 size = arg->size; 5434 /* Bit-mask fill is not supported. */ 5435 if (arg->mask || size != sizeof(tmp)) 5436 goto error; 5437 /* Only network endian is supported. */ 5438 if (!arg->hton) 5439 goto error; 5440 ret = cmdline_parse_etheraddr(NULL, str, &tmp, size); 5441 if (ret < 0 || (unsigned int)ret != len) 5442 goto error; 5443 if (!ctx->object) 5444 return len; 5445 buf = (uint8_t *)ctx->object + arg->offset; 5446 memcpy(buf, &tmp, size); 5447 if (ctx->objmask) 5448 memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size); 5449 return len; 5450 error: 5451 push_args(ctx, arg); 5452 return -1; 5453 } 5454 5455 /** 5456 * Parse an IPv4 address. 5457 * 5458 * Last argument (ctx->args) is retrieved to determine storage size and 5459 * location. 5460 */ 5461 static int 5462 parse_ipv4_addr(struct context *ctx, const struct token *token, 5463 const char *str, unsigned int len, 5464 void *buf, unsigned int size) 5465 { 5466 const struct arg *arg = pop_args(ctx); 5467 char str2[len + 1]; 5468 struct in_addr tmp; 5469 int ret; 5470 5471 /* Argument is expected. */ 5472 if (!arg) 5473 return -1; 5474 size = arg->size; 5475 /* Bit-mask fill is not supported. */ 5476 if (arg->mask || size != sizeof(tmp)) 5477 goto error; 5478 /* Only network endian is supported. */ 5479 if (!arg->hton) 5480 goto error; 5481 memcpy(str2, str, len); 5482 str2[len] = '\0'; 5483 ret = inet_pton(AF_INET, str2, &tmp); 5484 if (ret != 1) { 5485 /* Attempt integer parsing. */ 5486 push_args(ctx, arg); 5487 return parse_int(ctx, token, str, len, buf, size); 5488 } 5489 if (!ctx->object) 5490 return len; 5491 buf = (uint8_t *)ctx->object + arg->offset; 5492 memcpy(buf, &tmp, size); 5493 if (ctx->objmask) 5494 memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size); 5495 return len; 5496 error: 5497 push_args(ctx, arg); 5498 return -1; 5499 } 5500 5501 /** 5502 * Parse an IPv6 address. 5503 * 5504 * Last argument (ctx->args) is retrieved to determine storage size and 5505 * location. 5506 */ 5507 static int 5508 parse_ipv6_addr(struct context *ctx, const struct token *token, 5509 const char *str, unsigned int len, 5510 void *buf, unsigned int size) 5511 { 5512 const struct arg *arg = pop_args(ctx); 5513 char str2[len + 1]; 5514 struct in6_addr tmp; 5515 int ret; 5516 5517 (void)token; 5518 /* Argument is expected. */ 5519 if (!arg) 5520 return -1; 5521 size = arg->size; 5522 /* Bit-mask fill is not supported. */ 5523 if (arg->mask || size != sizeof(tmp)) 5524 goto error; 5525 /* Only network endian is supported. */ 5526 if (!arg->hton) 5527 goto error; 5528 memcpy(str2, str, len); 5529 str2[len] = '\0'; 5530 ret = inet_pton(AF_INET6, str2, &tmp); 5531 if (ret != 1) 5532 goto error; 5533 if (!ctx->object) 5534 return len; 5535 buf = (uint8_t *)ctx->object + arg->offset; 5536 memcpy(buf, &tmp, size); 5537 if (ctx->objmask) 5538 memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size); 5539 return len; 5540 error: 5541 push_args(ctx, arg); 5542 return -1; 5543 } 5544 5545 /** Boolean values (even indices stand for false). */ 5546 static const char *const boolean_name[] = { 5547 "0", "1", 5548 "false", "true", 5549 "no", "yes", 5550 "N", "Y", 5551 "off", "on", 5552 NULL, 5553 }; 5554 5555 /** 5556 * Parse a boolean value. 5557 * 5558 * Last argument (ctx->args) is retrieved to determine storage size and 5559 * location. 5560 */ 5561 static int 5562 parse_boolean(struct context *ctx, const struct token *token, 5563 const char *str, unsigned int len, 5564 void *buf, unsigned int size) 5565 { 5566 const struct arg *arg = pop_args(ctx); 5567 unsigned int i; 5568 int ret; 5569 5570 /* Argument is expected. */ 5571 if (!arg) 5572 return -1; 5573 for (i = 0; boolean_name[i]; ++i) 5574 if (!strcmp_partial(boolean_name[i], str, len)) 5575 break; 5576 /* Process token as integer. */ 5577 if (boolean_name[i]) 5578 str = i & 1 ? "1" : "0"; 5579 push_args(ctx, arg); 5580 ret = parse_int(ctx, token, str, strlen(str), buf, size); 5581 return ret > 0 ? (int)len : ret; 5582 } 5583 5584 /** Parse port and update context. */ 5585 static int 5586 parse_port(struct context *ctx, const struct token *token, 5587 const char *str, unsigned int len, 5588 void *buf, unsigned int size) 5589 { 5590 struct buffer *out = &(struct buffer){ .port = 0 }; 5591 int ret; 5592 5593 if (buf) 5594 out = buf; 5595 else { 5596 ctx->objdata = 0; 5597 ctx->object = out; 5598 ctx->objmask = NULL; 5599 size = sizeof(*out); 5600 } 5601 ret = parse_int(ctx, token, str, len, out, size); 5602 if (ret >= 0) 5603 ctx->port = out->port; 5604 if (!buf) 5605 ctx->object = NULL; 5606 return ret; 5607 } 5608 5609 /** Parse set command, initialize output buffer for subsequent tokens. */ 5610 static int 5611 parse_set_raw_encap_decap(struct context *ctx, const struct token *token, 5612 const char *str, unsigned int len, 5613 void *buf, unsigned int size) 5614 { 5615 struct buffer *out = buf; 5616 5617 /* Token name must match. */ 5618 if (parse_default(ctx, token, str, len, NULL, 0) < 0) 5619 return -1; 5620 /* Nothing else to do if there is no buffer. */ 5621 if (!out) 5622 return len; 5623 /* Make sure buffer is large enough. */ 5624 if (size < sizeof(*out)) 5625 return -1; 5626 ctx->objdata = 0; 5627 ctx->objmask = NULL; 5628 ctx->object = out; 5629 if (!out->command) 5630 return -1; 5631 out->command = ctx->curr; 5632 return len; 5633 } 5634 5635 /** 5636 * Parse set raw_encap/raw_decap command, 5637 * initialize output buffer for subsequent tokens. 5638 */ 5639 static int 5640 parse_set_init(struct context *ctx, const struct token *token, 5641 const char *str, unsigned int len, 5642 void *buf, unsigned int size) 5643 { 5644 struct buffer *out = buf; 5645 5646 /* Token name must match. */ 5647 if (parse_default(ctx, token, str, len, NULL, 0) < 0) 5648 return -1; 5649 /* Nothing else to do if there is no buffer. */ 5650 if (!out) 5651 return len; 5652 /* Make sure buffer is large enough. */ 5653 if (size < sizeof(*out)) 5654 return -1; 5655 /* Initialize buffer. */ 5656 memset(out, 0x00, sizeof(*out)); 5657 memset((uint8_t *)out + sizeof(*out), 0x22, size - sizeof(*out)); 5658 ctx->objdata = 0; 5659 ctx->object = out; 5660 ctx->objmask = NULL; 5661 if (!out->command) { 5662 if (ctx->curr != SET) 5663 return -1; 5664 if (sizeof(*out) > size) 5665 return -1; 5666 out->command = ctx->curr; 5667 out->args.vc.data = (uint8_t *)out + size; 5668 /* All we need is pattern */ 5669 out->args.vc.pattern = 5670 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1), 5671 sizeof(double)); 5672 ctx->object = out->args.vc.pattern; 5673 } 5674 return len; 5675 } 5676 5677 /** No completion. */ 5678 static int 5679 comp_none(struct context *ctx, const struct token *token, 5680 unsigned int ent, char *buf, unsigned int size) 5681 { 5682 (void)ctx; 5683 (void)token; 5684 (void)ent; 5685 (void)buf; 5686 (void)size; 5687 return 0; 5688 } 5689 5690 /** Complete boolean values. */ 5691 static int 5692 comp_boolean(struct context *ctx, const struct token *token, 5693 unsigned int ent, char *buf, unsigned int size) 5694 { 5695 unsigned int i; 5696 5697 (void)ctx; 5698 (void)token; 5699 for (i = 0; boolean_name[i]; ++i) 5700 if (buf && i == ent) 5701 return strlcpy(buf, boolean_name[i], size); 5702 if (buf) 5703 return -1; 5704 return i; 5705 } 5706 5707 /** Complete action names. */ 5708 static int 5709 comp_action(struct context *ctx, const struct token *token, 5710 unsigned int ent, char *buf, unsigned int size) 5711 { 5712 unsigned int i; 5713 5714 (void)ctx; 5715 (void)token; 5716 for (i = 0; next_action[i]; ++i) 5717 if (buf && i == ent) 5718 return strlcpy(buf, token_list[next_action[i]].name, 5719 size); 5720 if (buf) 5721 return -1; 5722 return i; 5723 } 5724 5725 /** Complete available ports. */ 5726 static int 5727 comp_port(struct context *ctx, const struct token *token, 5728 unsigned int ent, char *buf, unsigned int size) 5729 { 5730 unsigned int i = 0; 5731 portid_t p; 5732 5733 (void)ctx; 5734 (void)token; 5735 RTE_ETH_FOREACH_DEV(p) { 5736 if (buf && i == ent) 5737 return snprintf(buf, size, "%u", p); 5738 ++i; 5739 } 5740 if (buf) 5741 return -1; 5742 return i; 5743 } 5744 5745 /** Complete available rule IDs. */ 5746 static int 5747 comp_rule_id(struct context *ctx, const struct token *token, 5748 unsigned int ent, char *buf, unsigned int size) 5749 { 5750 unsigned int i = 0; 5751 struct rte_port *port; 5752 struct port_flow *pf; 5753 5754 (void)token; 5755 if (port_id_is_invalid(ctx->port, DISABLED_WARN) || 5756 ctx->port == (portid_t)RTE_PORT_ALL) 5757 return -1; 5758 port = &ports[ctx->port]; 5759 for (pf = port->flow_list; pf != NULL; pf = pf->next) { 5760 if (buf && i == ent) 5761 return snprintf(buf, size, "%u", pf->id); 5762 ++i; 5763 } 5764 if (buf) 5765 return -1; 5766 return i; 5767 } 5768 5769 /** Complete type field for RSS action. */ 5770 static int 5771 comp_vc_action_rss_type(struct context *ctx, const struct token *token, 5772 unsigned int ent, char *buf, unsigned int size) 5773 { 5774 unsigned int i; 5775 5776 (void)ctx; 5777 (void)token; 5778 for (i = 0; rss_type_table[i].str; ++i) 5779 ; 5780 if (!buf) 5781 return i + 1; 5782 if (ent < i) 5783 return strlcpy(buf, rss_type_table[ent].str, size); 5784 if (ent == i) 5785 return snprintf(buf, size, "end"); 5786 return -1; 5787 } 5788 5789 /** Complete queue field for RSS action. */ 5790 static int 5791 comp_vc_action_rss_queue(struct context *ctx, const struct token *token, 5792 unsigned int ent, char *buf, unsigned int size) 5793 { 5794 (void)ctx; 5795 (void)token; 5796 if (!buf) 5797 return nb_rxq + 1; 5798 if (ent < nb_rxq) 5799 return snprintf(buf, size, "%u", ent); 5800 if (ent == nb_rxq) 5801 return snprintf(buf, size, "end"); 5802 return -1; 5803 } 5804 5805 /** Complete index number for set raw_encap/raw_decap commands. */ 5806 static int 5807 comp_set_raw_index(struct context *ctx, const struct token *token, 5808 unsigned int ent, char *buf, unsigned int size) 5809 { 5810 uint16_t idx = 0; 5811 uint16_t nb = 0; 5812 5813 RTE_SET_USED(ctx); 5814 RTE_SET_USED(token); 5815 for (idx = 0; idx < RAW_ENCAP_CONFS_MAX_NUM; ++idx) { 5816 if (buf && idx == ent) 5817 return snprintf(buf, size, "%u", idx); 5818 ++nb; 5819 } 5820 return nb; 5821 } 5822 5823 /** Internal context. */ 5824 static struct context cmd_flow_context; 5825 5826 /** Global parser instance (cmdline API). */ 5827 cmdline_parse_inst_t cmd_flow; 5828 cmdline_parse_inst_t cmd_set_raw; 5829 5830 /** Initialize context. */ 5831 static void 5832 cmd_flow_context_init(struct context *ctx) 5833 { 5834 /* A full memset() is not necessary. */ 5835 ctx->curr = ZERO; 5836 ctx->prev = ZERO; 5837 ctx->next_num = 0; 5838 ctx->args_num = 0; 5839 ctx->eol = 0; 5840 ctx->last = 0; 5841 ctx->port = 0; 5842 ctx->objdata = 0; 5843 ctx->object = NULL; 5844 ctx->objmask = NULL; 5845 } 5846 5847 /** Parse a token (cmdline API). */ 5848 static int 5849 cmd_flow_parse(cmdline_parse_token_hdr_t *hdr, const char *src, void *result, 5850 unsigned int size) 5851 { 5852 struct context *ctx = &cmd_flow_context; 5853 const struct token *token; 5854 const enum index *list; 5855 int len; 5856 int i; 5857 5858 (void)hdr; 5859 token = &token_list[ctx->curr]; 5860 /* Check argument length. */ 5861 ctx->eol = 0; 5862 ctx->last = 1; 5863 for (len = 0; src[len]; ++len) 5864 if (src[len] == '#' || isspace(src[len])) 5865 break; 5866 if (!len) 5867 return -1; 5868 /* Last argument and EOL detection. */ 5869 for (i = len; src[i]; ++i) 5870 if (src[i] == '#' || src[i] == '\r' || src[i] == '\n') 5871 break; 5872 else if (!isspace(src[i])) { 5873 ctx->last = 0; 5874 break; 5875 } 5876 for (; src[i]; ++i) 5877 if (src[i] == '\r' || src[i] == '\n') { 5878 ctx->eol = 1; 5879 break; 5880 } 5881 /* Initialize context if necessary. */ 5882 if (!ctx->next_num) { 5883 if (!token->next) 5884 return 0; 5885 ctx->next[ctx->next_num++] = token->next[0]; 5886 } 5887 /* Process argument through candidates. */ 5888 ctx->prev = ctx->curr; 5889 list = ctx->next[ctx->next_num - 1]; 5890 for (i = 0; list[i]; ++i) { 5891 const struct token *next = &token_list[list[i]]; 5892 int tmp; 5893 5894 ctx->curr = list[i]; 5895 if (next->call) 5896 tmp = next->call(ctx, next, src, len, result, size); 5897 else 5898 tmp = parse_default(ctx, next, src, len, result, size); 5899 if (tmp == -1 || tmp != len) 5900 continue; 5901 token = next; 5902 break; 5903 } 5904 if (!list[i]) 5905 return -1; 5906 --ctx->next_num; 5907 /* Push subsequent tokens if any. */ 5908 if (token->next) 5909 for (i = 0; token->next[i]; ++i) { 5910 if (ctx->next_num == RTE_DIM(ctx->next)) 5911 return -1; 5912 ctx->next[ctx->next_num++] = token->next[i]; 5913 } 5914 /* Push arguments if any. */ 5915 if (token->args) 5916 for (i = 0; token->args[i]; ++i) { 5917 if (ctx->args_num == RTE_DIM(ctx->args)) 5918 return -1; 5919 ctx->args[ctx->args_num++] = token->args[i]; 5920 } 5921 return len; 5922 } 5923 5924 /** Return number of completion entries (cmdline API). */ 5925 static int 5926 cmd_flow_complete_get_nb(cmdline_parse_token_hdr_t *hdr) 5927 { 5928 struct context *ctx = &cmd_flow_context; 5929 const struct token *token = &token_list[ctx->curr]; 5930 const enum index *list; 5931 int i; 5932 5933 (void)hdr; 5934 /* Count number of tokens in current list. */ 5935 if (ctx->next_num) 5936 list = ctx->next[ctx->next_num - 1]; 5937 else 5938 list = token->next[0]; 5939 for (i = 0; list[i]; ++i) 5940 ; 5941 if (!i) 5942 return 0; 5943 /* 5944 * If there is a single token, use its completion callback, otherwise 5945 * return the number of entries. 5946 */ 5947 token = &token_list[list[0]]; 5948 if (i == 1 && token->comp) { 5949 /* Save index for cmd_flow_get_help(). */ 5950 ctx->prev = list[0]; 5951 return token->comp(ctx, token, 0, NULL, 0); 5952 } 5953 return i; 5954 } 5955 5956 /** Return a completion entry (cmdline API). */ 5957 static int 5958 cmd_flow_complete_get_elt(cmdline_parse_token_hdr_t *hdr, int index, 5959 char *dst, unsigned int size) 5960 { 5961 struct context *ctx = &cmd_flow_context; 5962 const struct token *token = &token_list[ctx->curr]; 5963 const enum index *list; 5964 int i; 5965 5966 (void)hdr; 5967 /* Count number of tokens in current list. */ 5968 if (ctx->next_num) 5969 list = ctx->next[ctx->next_num - 1]; 5970 else 5971 list = token->next[0]; 5972 for (i = 0; list[i]; ++i) 5973 ; 5974 if (!i) 5975 return -1; 5976 /* If there is a single token, use its completion callback. */ 5977 token = &token_list[list[0]]; 5978 if (i == 1 && token->comp) { 5979 /* Save index for cmd_flow_get_help(). */ 5980 ctx->prev = list[0]; 5981 return token->comp(ctx, token, index, dst, size) < 0 ? -1 : 0; 5982 } 5983 /* Otherwise make sure the index is valid and use defaults. */ 5984 if (index >= i) 5985 return -1; 5986 token = &token_list[list[index]]; 5987 strlcpy(dst, token->name, size); 5988 /* Save index for cmd_flow_get_help(). */ 5989 ctx->prev = list[index]; 5990 return 0; 5991 } 5992 5993 /** Populate help strings for current token (cmdline API). */ 5994 static int 5995 cmd_flow_get_help(cmdline_parse_token_hdr_t *hdr, char *dst, unsigned int size) 5996 { 5997 struct context *ctx = &cmd_flow_context; 5998 const struct token *token = &token_list[ctx->prev]; 5999 6000 (void)hdr; 6001 if (!size) 6002 return -1; 6003 /* Set token type and update global help with details. */ 6004 strlcpy(dst, (token->type ? token->type : "TOKEN"), size); 6005 if (token->help) 6006 cmd_flow.help_str = token->help; 6007 else 6008 cmd_flow.help_str = token->name; 6009 return 0; 6010 } 6011 6012 /** Token definition template (cmdline API). */ 6013 static struct cmdline_token_hdr cmd_flow_token_hdr = { 6014 .ops = &(struct cmdline_token_ops){ 6015 .parse = cmd_flow_parse, 6016 .complete_get_nb = cmd_flow_complete_get_nb, 6017 .complete_get_elt = cmd_flow_complete_get_elt, 6018 .get_help = cmd_flow_get_help, 6019 }, 6020 .offset = 0, 6021 }; 6022 6023 /** Populate the next dynamic token. */ 6024 static void 6025 cmd_flow_tok(cmdline_parse_token_hdr_t **hdr, 6026 cmdline_parse_token_hdr_t **hdr_inst) 6027 { 6028 struct context *ctx = &cmd_flow_context; 6029 6030 /* Always reinitialize context before requesting the first token. */ 6031 if (!(hdr_inst - cmd_flow.tokens)) 6032 cmd_flow_context_init(ctx); 6033 /* Return NULL when no more tokens are expected. */ 6034 if (!ctx->next_num && ctx->curr) { 6035 *hdr = NULL; 6036 return; 6037 } 6038 /* Determine if command should end here. */ 6039 if (ctx->eol && ctx->last && ctx->next_num) { 6040 const enum index *list = ctx->next[ctx->next_num - 1]; 6041 int i; 6042 6043 for (i = 0; list[i]; ++i) { 6044 if (list[i] != END) 6045 continue; 6046 *hdr = NULL; 6047 return; 6048 } 6049 } 6050 *hdr = &cmd_flow_token_hdr; 6051 } 6052 6053 /** Dispatch parsed buffer to function calls. */ 6054 static void 6055 cmd_flow_parsed(const struct buffer *in) 6056 { 6057 switch (in->command) { 6058 case VALIDATE: 6059 port_flow_validate(in->port, &in->args.vc.attr, 6060 in->args.vc.pattern, in->args.vc.actions); 6061 break; 6062 case CREATE: 6063 port_flow_create(in->port, &in->args.vc.attr, 6064 in->args.vc.pattern, in->args.vc.actions); 6065 break; 6066 case DESTROY: 6067 port_flow_destroy(in->port, in->args.destroy.rule_n, 6068 in->args.destroy.rule); 6069 break; 6070 case FLUSH: 6071 port_flow_flush(in->port); 6072 break; 6073 case QUERY: 6074 port_flow_query(in->port, in->args.query.rule, 6075 &in->args.query.action); 6076 break; 6077 case LIST: 6078 port_flow_list(in->port, in->args.list.group_n, 6079 in->args.list.group); 6080 break; 6081 case ISOLATE: 6082 port_flow_isolate(in->port, in->args.isolate.set); 6083 break; 6084 default: 6085 break; 6086 } 6087 } 6088 6089 /** Token generator and output processing callback (cmdline API). */ 6090 static void 6091 cmd_flow_cb(void *arg0, struct cmdline *cl, void *arg2) 6092 { 6093 if (cl == NULL) 6094 cmd_flow_tok(arg0, arg2); 6095 else 6096 cmd_flow_parsed(arg0); 6097 } 6098 6099 /** Global parser instance (cmdline API). */ 6100 cmdline_parse_inst_t cmd_flow = { 6101 .f = cmd_flow_cb, 6102 .data = NULL, /**< Unused. */ 6103 .help_str = NULL, /**< Updated by cmd_flow_get_help(). */ 6104 .tokens = { 6105 NULL, 6106 }, /**< Tokens are returned by cmd_flow_tok(). */ 6107 }; 6108 6109 /** set cmd facility. Reuse cmd flow's infrastructure as much as possible. */ 6110 6111 static void 6112 update_fields(uint8_t *buf, struct rte_flow_item *item, uint16_t next_proto) 6113 { 6114 struct rte_flow_item_ipv4 *ipv4; 6115 struct rte_flow_item_eth *eth; 6116 struct rte_flow_item_ipv6 *ipv6; 6117 struct rte_flow_item_vxlan *vxlan; 6118 struct rte_flow_item_vxlan_gpe *gpe; 6119 struct rte_flow_item_nvgre *nvgre; 6120 uint32_t ipv6_vtc_flow; 6121 6122 switch (item->type) { 6123 case RTE_FLOW_ITEM_TYPE_ETH: 6124 eth = (struct rte_flow_item_eth *)buf; 6125 if (next_proto) 6126 eth->type = rte_cpu_to_be_16(next_proto); 6127 break; 6128 case RTE_FLOW_ITEM_TYPE_IPV4: 6129 ipv4 = (struct rte_flow_item_ipv4 *)buf; 6130 ipv4->hdr.version_ihl = 0x45; 6131 if (next_proto && ipv4->hdr.next_proto_id == 0) 6132 ipv4->hdr.next_proto_id = (uint8_t)next_proto; 6133 break; 6134 case RTE_FLOW_ITEM_TYPE_IPV6: 6135 ipv6 = (struct rte_flow_item_ipv6 *)buf; 6136 if (next_proto && ipv6->hdr.proto == 0) 6137 ipv6->hdr.proto = (uint8_t)next_proto; 6138 ipv6_vtc_flow = rte_be_to_cpu_32(ipv6->hdr.vtc_flow); 6139 ipv6_vtc_flow &= 0x0FFFFFFF; /*< reset version bits. */ 6140 ipv6_vtc_flow |= 0x60000000; /*< set ipv6 version. */ 6141 ipv6->hdr.vtc_flow = rte_cpu_to_be_32(ipv6_vtc_flow); 6142 break; 6143 case RTE_FLOW_ITEM_TYPE_VXLAN: 6144 vxlan = (struct rte_flow_item_vxlan *)buf; 6145 vxlan->flags = 0x08; 6146 break; 6147 case RTE_FLOW_ITEM_TYPE_VXLAN_GPE: 6148 gpe = (struct rte_flow_item_vxlan_gpe *)buf; 6149 gpe->flags = 0x0C; 6150 break; 6151 case RTE_FLOW_ITEM_TYPE_NVGRE: 6152 nvgre = (struct rte_flow_item_nvgre *)buf; 6153 nvgre->protocol = rte_cpu_to_be_16(0x6558); 6154 nvgre->c_k_s_rsvd0_ver = rte_cpu_to_be_16(0x2000); 6155 break; 6156 default: 6157 break; 6158 } 6159 } 6160 6161 /** Helper of get item's default mask. */ 6162 static const void * 6163 flow_item_default_mask(const struct rte_flow_item *item) 6164 { 6165 const void *mask = NULL; 6166 static rte_be32_t gre_key_default_mask = RTE_BE32(UINT32_MAX); 6167 6168 switch (item->type) { 6169 case RTE_FLOW_ITEM_TYPE_ANY: 6170 mask = &rte_flow_item_any_mask; 6171 break; 6172 case RTE_FLOW_ITEM_TYPE_VF: 6173 mask = &rte_flow_item_vf_mask; 6174 break; 6175 case RTE_FLOW_ITEM_TYPE_PORT_ID: 6176 mask = &rte_flow_item_port_id_mask; 6177 break; 6178 case RTE_FLOW_ITEM_TYPE_RAW: 6179 mask = &rte_flow_item_raw_mask; 6180 break; 6181 case RTE_FLOW_ITEM_TYPE_ETH: 6182 mask = &rte_flow_item_eth_mask; 6183 break; 6184 case RTE_FLOW_ITEM_TYPE_VLAN: 6185 mask = &rte_flow_item_vlan_mask; 6186 break; 6187 case RTE_FLOW_ITEM_TYPE_IPV4: 6188 mask = &rte_flow_item_ipv4_mask; 6189 break; 6190 case RTE_FLOW_ITEM_TYPE_IPV6: 6191 mask = &rte_flow_item_ipv6_mask; 6192 break; 6193 case RTE_FLOW_ITEM_TYPE_ICMP: 6194 mask = &rte_flow_item_icmp_mask; 6195 break; 6196 case RTE_FLOW_ITEM_TYPE_UDP: 6197 mask = &rte_flow_item_udp_mask; 6198 break; 6199 case RTE_FLOW_ITEM_TYPE_TCP: 6200 mask = &rte_flow_item_tcp_mask; 6201 break; 6202 case RTE_FLOW_ITEM_TYPE_SCTP: 6203 mask = &rte_flow_item_sctp_mask; 6204 break; 6205 case RTE_FLOW_ITEM_TYPE_VXLAN: 6206 mask = &rte_flow_item_vxlan_mask; 6207 break; 6208 case RTE_FLOW_ITEM_TYPE_VXLAN_GPE: 6209 mask = &rte_flow_item_vxlan_gpe_mask; 6210 break; 6211 case RTE_FLOW_ITEM_TYPE_E_TAG: 6212 mask = &rte_flow_item_e_tag_mask; 6213 break; 6214 case RTE_FLOW_ITEM_TYPE_NVGRE: 6215 mask = &rte_flow_item_nvgre_mask; 6216 break; 6217 case RTE_FLOW_ITEM_TYPE_MPLS: 6218 mask = &rte_flow_item_mpls_mask; 6219 break; 6220 case RTE_FLOW_ITEM_TYPE_GRE: 6221 mask = &rte_flow_item_gre_mask; 6222 break; 6223 case RTE_FLOW_ITEM_TYPE_GRE_KEY: 6224 mask = &gre_key_default_mask; 6225 break; 6226 case RTE_FLOW_ITEM_TYPE_META: 6227 mask = &rte_flow_item_meta_mask; 6228 break; 6229 case RTE_FLOW_ITEM_TYPE_FUZZY: 6230 mask = &rte_flow_item_fuzzy_mask; 6231 break; 6232 case RTE_FLOW_ITEM_TYPE_GTP: 6233 mask = &rte_flow_item_gtp_mask; 6234 break; 6235 case RTE_FLOW_ITEM_TYPE_ESP: 6236 mask = &rte_flow_item_esp_mask; 6237 break; 6238 case RTE_FLOW_ITEM_TYPE_GTP_PSC: 6239 mask = &rte_flow_item_gtp_psc_mask; 6240 break; 6241 case RTE_FLOW_ITEM_TYPE_GENEVE: 6242 mask = &rte_flow_item_geneve_mask; 6243 break; 6244 case RTE_FLOW_ITEM_TYPE_PPPOE_PROTO_ID: 6245 mask = &rte_flow_item_pppoe_proto_id_mask; 6246 default: 6247 break; 6248 } 6249 return mask; 6250 } 6251 6252 6253 6254 /** Dispatch parsed buffer to function calls. */ 6255 static void 6256 cmd_set_raw_parsed(const struct buffer *in) 6257 { 6258 uint32_t n = in->args.vc.pattern_n; 6259 int i = 0; 6260 struct rte_flow_item *item = NULL; 6261 size_t size = 0; 6262 uint8_t *data = NULL; 6263 uint8_t *data_tail = NULL; 6264 size_t *total_size = NULL; 6265 uint16_t upper_layer = 0; 6266 uint16_t proto = 0; 6267 uint16_t idx = in->port; /* We borrow port field as index */ 6268 6269 RTE_ASSERT(in->command == SET_RAW_ENCAP || 6270 in->command == SET_RAW_DECAP); 6271 if (in->command == SET_RAW_ENCAP) { 6272 total_size = &raw_encap_confs[idx].size; 6273 data = (uint8_t *)&raw_encap_confs[idx].data; 6274 } else { 6275 total_size = &raw_decap_confs[idx].size; 6276 data = (uint8_t *)&raw_decap_confs[idx].data; 6277 } 6278 *total_size = 0; 6279 memset(data, 0x00, ACTION_RAW_ENCAP_MAX_DATA); 6280 /* process hdr from upper layer to low layer (L3/L4 -> L2). */ 6281 data_tail = data + ACTION_RAW_ENCAP_MAX_DATA; 6282 for (i = n - 1 ; i >= 0; --i) { 6283 item = in->args.vc.pattern + i; 6284 if (item->spec == NULL) 6285 item->spec = flow_item_default_mask(item); 6286 switch (item->type) { 6287 case RTE_FLOW_ITEM_TYPE_ETH: 6288 size = sizeof(struct rte_flow_item_eth); 6289 break; 6290 case RTE_FLOW_ITEM_TYPE_VLAN: 6291 size = sizeof(struct rte_flow_item_vlan); 6292 proto = RTE_ETHER_TYPE_VLAN; 6293 break; 6294 case RTE_FLOW_ITEM_TYPE_IPV4: 6295 size = sizeof(struct rte_flow_item_ipv4); 6296 proto = RTE_ETHER_TYPE_IPV4; 6297 break; 6298 case RTE_FLOW_ITEM_TYPE_IPV6: 6299 size = sizeof(struct rte_flow_item_ipv6); 6300 proto = RTE_ETHER_TYPE_IPV6; 6301 break; 6302 case RTE_FLOW_ITEM_TYPE_UDP: 6303 size = sizeof(struct rte_flow_item_udp); 6304 proto = 0x11; 6305 break; 6306 case RTE_FLOW_ITEM_TYPE_TCP: 6307 size = sizeof(struct rte_flow_item_tcp); 6308 proto = 0x06; 6309 break; 6310 case RTE_FLOW_ITEM_TYPE_VXLAN: 6311 size = sizeof(struct rte_flow_item_vxlan); 6312 break; 6313 case RTE_FLOW_ITEM_TYPE_VXLAN_GPE: 6314 size = sizeof(struct rte_flow_item_vxlan_gpe); 6315 break; 6316 case RTE_FLOW_ITEM_TYPE_GRE: 6317 size = sizeof(struct rte_flow_item_gre); 6318 proto = 0x2F; 6319 break; 6320 case RTE_FLOW_ITEM_TYPE_GRE_KEY: 6321 size = sizeof(rte_be32_t); 6322 proto = 0x0; 6323 break; 6324 case RTE_FLOW_ITEM_TYPE_MPLS: 6325 size = sizeof(struct rte_flow_item_mpls); 6326 proto = 0x0; 6327 break; 6328 case RTE_FLOW_ITEM_TYPE_NVGRE: 6329 size = sizeof(struct rte_flow_item_nvgre); 6330 proto = 0x2F; 6331 break; 6332 case RTE_FLOW_ITEM_TYPE_GENEVE: 6333 size = sizeof(struct rte_flow_item_geneve); 6334 break; 6335 default: 6336 printf("Error - Not supported item\n"); 6337 *total_size = 0; 6338 memset(data, 0x00, ACTION_RAW_ENCAP_MAX_DATA); 6339 return; 6340 } 6341 *total_size += size; 6342 rte_memcpy(data_tail - (*total_size), item->spec, size); 6343 /* update some fields which cannot be set by cmdline */ 6344 update_fields((data_tail - (*total_size)), item, 6345 upper_layer); 6346 upper_layer = proto; 6347 } 6348 if (verbose_level & 0x1) 6349 printf("total data size is %zu\n", (*total_size)); 6350 RTE_ASSERT((*total_size) <= ACTION_RAW_ENCAP_MAX_DATA); 6351 memmove(data, (data_tail - (*total_size)), *total_size); 6352 } 6353 6354 /** Populate help strings for current token (cmdline API). */ 6355 static int 6356 cmd_set_raw_get_help(cmdline_parse_token_hdr_t *hdr, char *dst, 6357 unsigned int size) 6358 { 6359 struct context *ctx = &cmd_flow_context; 6360 const struct token *token = &token_list[ctx->prev]; 6361 6362 (void)hdr; 6363 if (!size) 6364 return -1; 6365 /* Set token type and update global help with details. */ 6366 snprintf(dst, size, "%s", (token->type ? token->type : "TOKEN")); 6367 if (token->help) 6368 cmd_set_raw.help_str = token->help; 6369 else 6370 cmd_set_raw.help_str = token->name; 6371 return 0; 6372 } 6373 6374 /** Token definition template (cmdline API). */ 6375 static struct cmdline_token_hdr cmd_set_raw_token_hdr = { 6376 .ops = &(struct cmdline_token_ops){ 6377 .parse = cmd_flow_parse, 6378 .complete_get_nb = cmd_flow_complete_get_nb, 6379 .complete_get_elt = cmd_flow_complete_get_elt, 6380 .get_help = cmd_set_raw_get_help, 6381 }, 6382 .offset = 0, 6383 }; 6384 6385 /** Populate the next dynamic token. */ 6386 static void 6387 cmd_set_raw_tok(cmdline_parse_token_hdr_t **hdr, 6388 cmdline_parse_token_hdr_t **hdr_inst) 6389 { 6390 struct context *ctx = &cmd_flow_context; 6391 6392 /* Always reinitialize context before requesting the first token. */ 6393 if (!(hdr_inst - cmd_set_raw.tokens)) { 6394 cmd_flow_context_init(ctx); 6395 ctx->curr = START_SET; 6396 } 6397 /* Return NULL when no more tokens are expected. */ 6398 if (!ctx->next_num && (ctx->curr != START_SET)) { 6399 *hdr = NULL; 6400 return; 6401 } 6402 /* Determine if command should end here. */ 6403 if (ctx->eol && ctx->last && ctx->next_num) { 6404 const enum index *list = ctx->next[ctx->next_num - 1]; 6405 int i; 6406 6407 for (i = 0; list[i]; ++i) { 6408 if (list[i] != END) 6409 continue; 6410 *hdr = NULL; 6411 return; 6412 } 6413 } 6414 *hdr = &cmd_set_raw_token_hdr; 6415 } 6416 6417 /** Token generator and output processing callback (cmdline API). */ 6418 static void 6419 cmd_set_raw_cb(void *arg0, struct cmdline *cl, void *arg2) 6420 { 6421 if (cl == NULL) 6422 cmd_set_raw_tok(arg0, arg2); 6423 else 6424 cmd_set_raw_parsed(arg0); 6425 } 6426 6427 /** Global parser instance (cmdline API). */ 6428 cmdline_parse_inst_t cmd_set_raw = { 6429 .f = cmd_set_raw_cb, 6430 .data = NULL, /**< Unused. */ 6431 .help_str = NULL, /**< Updated by cmd_flow_get_help(). */ 6432 .tokens = { 6433 NULL, 6434 }, /**< Tokens are returned by cmd_flow_tok(). */ 6435 }; 6436 6437 /* *** display raw_encap/raw_decap buf */ 6438 struct cmd_show_set_raw_result { 6439 cmdline_fixed_string_t cmd_show; 6440 cmdline_fixed_string_t cmd_what; 6441 cmdline_fixed_string_t cmd_all; 6442 uint16_t cmd_index; 6443 }; 6444 6445 static void 6446 cmd_show_set_raw_parsed(void *parsed_result, struct cmdline *cl, void *data) 6447 { 6448 struct cmd_show_set_raw_result *res = parsed_result; 6449 uint16_t index = res->cmd_index; 6450 uint8_t all = 0; 6451 uint8_t *raw_data = NULL; 6452 size_t raw_size = 0; 6453 char title[16] = {0}; 6454 6455 RTE_SET_USED(cl); 6456 RTE_SET_USED(data); 6457 if (!strcmp(res->cmd_all, "all")) { 6458 all = 1; 6459 index = 0; 6460 } else if (index >= RAW_ENCAP_CONFS_MAX_NUM) { 6461 printf("index should be 0-%u\n", RAW_ENCAP_CONFS_MAX_NUM - 1); 6462 return; 6463 } 6464 do { 6465 if (!strcmp(res->cmd_what, "raw_encap")) { 6466 raw_data = (uint8_t *)&raw_encap_confs[index].data; 6467 raw_size = raw_encap_confs[index].size; 6468 snprintf(title, 16, "\nindex: %u", index); 6469 rte_hexdump(stdout, title, raw_data, raw_size); 6470 } else { 6471 raw_data = (uint8_t *)&raw_decap_confs[index].data; 6472 raw_size = raw_decap_confs[index].size; 6473 snprintf(title, 16, "\nindex: %u", index); 6474 rte_hexdump(stdout, title, raw_data, raw_size); 6475 } 6476 } while (all && ++index < RAW_ENCAP_CONFS_MAX_NUM); 6477 } 6478 6479 cmdline_parse_token_string_t cmd_show_set_raw_cmd_show = 6480 TOKEN_STRING_INITIALIZER(struct cmd_show_set_raw_result, 6481 cmd_show, "show"); 6482 cmdline_parse_token_string_t cmd_show_set_raw_cmd_what = 6483 TOKEN_STRING_INITIALIZER(struct cmd_show_set_raw_result, 6484 cmd_what, "raw_encap#raw_decap"); 6485 cmdline_parse_token_num_t cmd_show_set_raw_cmd_index = 6486 TOKEN_NUM_INITIALIZER(struct cmd_show_set_raw_result, 6487 cmd_index, UINT16); 6488 cmdline_parse_token_string_t cmd_show_set_raw_cmd_all = 6489 TOKEN_STRING_INITIALIZER(struct cmd_show_set_raw_result, 6490 cmd_all, "all"); 6491 cmdline_parse_inst_t cmd_show_set_raw = { 6492 .f = cmd_show_set_raw_parsed, 6493 .data = NULL, 6494 .help_str = "show <raw_encap|raw_decap> <index>", 6495 .tokens = { 6496 (void *)&cmd_show_set_raw_cmd_show, 6497 (void *)&cmd_show_set_raw_cmd_what, 6498 (void *)&cmd_show_set_raw_cmd_index, 6499 NULL, 6500 }, 6501 }; 6502 cmdline_parse_inst_t cmd_show_set_raw_all = { 6503 .f = cmd_show_set_raw_parsed, 6504 .data = NULL, 6505 .help_str = "show <raw_encap|raw_decap> all", 6506 .tokens = { 6507 (void *)&cmd_show_set_raw_cmd_show, 6508 (void *)&cmd_show_set_raw_cmd_what, 6509 (void *)&cmd_show_set_raw_cmd_all, 6510 NULL, 6511 }, 6512 }; 6513