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