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