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