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