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