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