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