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