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