1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright 2016 6WIND S.A.
3 * Copyright 2016 Mellanox Technologies, Ltd
14 #include <rte_string_fns.h>
15 #include <rte_common.h>
16 #include <rte_ethdev.h>
17 #include <rte_byteorder.h>
18 #include <cmdline_parse.h>
19 #include <cmdline_parse_etheraddr.h>
20 #include <cmdline_parse_string.h>
21 #include <cmdline_parse_num.h>
23 #include <rte_hexdump.h>
24 #include <rte_vxlan.h>
28 #include <rte_geneve.h>
32 /** Parser token indices. */
54 COMMON_PRIORITY_LEVEL,
55 COMMON_INDIRECT_ACTION_ID,
60 /* TOP-level command. */
63 /* Top-level command. */
65 /* Sub-leve commands. */
72 /* Top-level command. */
74 /* Sub-level commands. */
93 /* Tunnel arguments. */
100 /* Destroy arguments. */
103 /* Query arguments. */
106 /* List arguments. */
109 /* Destroy aged flow arguments. */
112 /* Validate/create arguments. */
125 /* Indirect action arguments */
126 INDIRECT_ACTION_CREATE,
127 INDIRECT_ACTION_UPDATE,
128 INDIRECT_ACTION_DESTROY,
129 INDIRECT_ACTION_QUERY,
131 /* Indirect action create arguments */
132 INDIRECT_ACTION_CREATE_ID,
133 INDIRECT_ACTION_INGRESS,
134 INDIRECT_ACTION_EGRESS,
135 INDIRECT_ACTION_TRANSFER,
136 INDIRECT_ACTION_SPEC,
138 /* Indirect action destroy arguments */
139 INDIRECT_ACTION_DESTROY_ID,
141 /* Validate/create pattern. */
169 ITEM_RAW_PATTERN_HEX,
180 ITEM_VLAN_INNER_TYPE,
181 ITEM_VLAN_HAS_MORE_VLAN,
186 ITEM_IPV4_FRAGMENT_OFFSET,
198 ITEM_IPV6_HAS_FRAG_EXT,
218 ITEM_VXLAN_LAST_RSVD,
220 ITEM_E_TAG_GRP_ECID_B,
229 ITEM_GRE_C_RSVD0_VER,
248 ITEM_ARP_ETH_IPV4_SHA,
249 ITEM_ARP_ETH_IPV4_SPA,
250 ITEM_ARP_ETH_IPV4_THA,
251 ITEM_ARP_ETH_IPV4_TPA,
253 ITEM_IPV6_EXT_NEXT_HDR,
255 ITEM_IPV6_FRAG_EXT_NEXT_HDR,
256 ITEM_IPV6_FRAG_EXT_FRAG_DATA,
257 ITEM_IPV6_FRAG_EXT_ID,
262 ITEM_ICMP6_ND_NS_TARGET_ADDR,
264 ITEM_ICMP6_ND_NA_TARGET_ADDR,
266 ITEM_ICMP6_ND_OPT_TYPE,
267 ITEM_ICMP6_ND_OPT_SLA_ETH,
268 ITEM_ICMP6_ND_OPT_SLA_ETH_SLA,
269 ITEM_ICMP6_ND_OPT_TLA_ETH,
270 ITEM_ICMP6_ND_OPT_TLA_ETH_TLA,
276 ITEM_GRE_OPTION_CHECKSUM,
278 ITEM_GRE_OPTION_SEQUENCE,
287 ITEM_HIGIG2_CLASSIFICATION,
293 ITEM_L2TPV3OIP_SESSION_ID,
303 ITEM_ECPRI_COMMON_TYPE,
304 ITEM_ECPRI_COMMON_TYPE_IQ_DATA,
305 ITEM_ECPRI_COMMON_TYPE_RTC_CTRL,
306 ITEM_ECPRI_COMMON_TYPE_DLY_MSR,
307 ITEM_ECPRI_MSG_IQ_DATA_PCID,
308 ITEM_ECPRI_MSG_RTC_CTRL_RTCID,
309 ITEM_ECPRI_MSG_DLY_MSR_MSRID,
311 ITEM_GENEVE_OPT_CLASS,
312 ITEM_GENEVE_OPT_TYPE,
313 ITEM_GENEVE_OPT_LENGTH,
314 ITEM_GENEVE_OPT_DATA,
316 ITEM_INTEGRITY_LEVEL,
317 ITEM_INTEGRITY_VALUE,
322 ITEM_PORT_REPRESENTOR,
323 ITEM_PORT_REPRESENTOR_PORT_ID,
324 ITEM_REPRESENTED_PORT,
325 ITEM_REPRESENTED_PORT_ETHDEV_PORT_ID,
327 ITEM_FLEX_ITEM_HANDLE,
328 ITEM_FLEX_PATTERN_HANDLE,
331 ITEM_L2TPV2_TYPE_DATA,
332 ITEM_L2TPV2_TYPE_DATA_L,
333 ITEM_L2TPV2_TYPE_DATA_S,
334 ITEM_L2TPV2_TYPE_DATA_O,
335 ITEM_L2TPV2_TYPE_DATA_L_S,
336 ITEM_L2TPV2_TYPE_CTRL,
337 ITEM_L2TPV2_MSG_DATA_TUNNEL_ID,
338 ITEM_L2TPV2_MSG_DATA_SESSION_ID,
339 ITEM_L2TPV2_MSG_DATA_L_LENGTH,
340 ITEM_L2TPV2_MSG_DATA_L_TUNNEL_ID,
341 ITEM_L2TPV2_MSG_DATA_L_SESSION_ID,
342 ITEM_L2TPV2_MSG_DATA_S_TUNNEL_ID,
343 ITEM_L2TPV2_MSG_DATA_S_SESSION_ID,
344 ITEM_L2TPV2_MSG_DATA_S_NS,
345 ITEM_L2TPV2_MSG_DATA_S_NR,
346 ITEM_L2TPV2_MSG_DATA_O_TUNNEL_ID,
347 ITEM_L2TPV2_MSG_DATA_O_SESSION_ID,
348 ITEM_L2TPV2_MSG_DATA_O_OFFSET,
349 ITEM_L2TPV2_MSG_DATA_L_S_LENGTH,
350 ITEM_L2TPV2_MSG_DATA_L_S_TUNNEL_ID,
351 ITEM_L2TPV2_MSG_DATA_L_S_SESSION_ID,
352 ITEM_L2TPV2_MSG_DATA_L_S_NS,
353 ITEM_L2TPV2_MSG_DATA_L_S_NR,
354 ITEM_L2TPV2_MSG_CTRL_LENGTH,
355 ITEM_L2TPV2_MSG_CTRL_TUNNEL_ID,
356 ITEM_L2TPV2_MSG_CTRL_SESSION_ID,
357 ITEM_L2TPV2_MSG_CTRL_NS,
358 ITEM_L2TPV2_MSG_CTRL_NR,
364 /* Validate/create actions. */
383 ACTION_RSS_FUNC_DEFAULT,
384 ACTION_RSS_FUNC_TOEPLITZ,
385 ACTION_RSS_FUNC_SIMPLE_XOR,
386 ACTION_RSS_FUNC_SYMMETRIC_TOEPLITZ,
398 ACTION_PHY_PORT_ORIGINAL,
399 ACTION_PHY_PORT_INDEX,
401 ACTION_PORT_ID_ORIGINAL,
405 ACTION_METER_COLOR_TYPE,
406 ACTION_METER_COLOR_GREEN,
407 ACTION_METER_COLOR_YELLOW,
408 ACTION_METER_COLOR_RED,
410 ACTION_OF_SET_MPLS_TTL,
411 ACTION_OF_SET_MPLS_TTL_MPLS_TTL,
412 ACTION_OF_DEC_MPLS_TTL,
413 ACTION_OF_SET_NW_TTL,
414 ACTION_OF_SET_NW_TTL_NW_TTL,
415 ACTION_OF_DEC_NW_TTL,
416 ACTION_OF_COPY_TTL_OUT,
417 ACTION_OF_COPY_TTL_IN,
420 ACTION_OF_PUSH_VLAN_ETHERTYPE,
421 ACTION_OF_SET_VLAN_VID,
422 ACTION_OF_SET_VLAN_VID_VLAN_VID,
423 ACTION_OF_SET_VLAN_PCP,
424 ACTION_OF_SET_VLAN_PCP_VLAN_PCP,
426 ACTION_OF_POP_MPLS_ETHERTYPE,
428 ACTION_OF_PUSH_MPLS_ETHERTYPE,
435 ACTION_MPLSOGRE_ENCAP,
436 ACTION_MPLSOGRE_DECAP,
437 ACTION_MPLSOUDP_ENCAP,
438 ACTION_MPLSOUDP_DECAP,
440 ACTION_SET_IPV4_SRC_IPV4_SRC,
442 ACTION_SET_IPV4_DST_IPV4_DST,
444 ACTION_SET_IPV6_SRC_IPV6_SRC,
446 ACTION_SET_IPV6_DST_IPV6_DST,
448 ACTION_SET_TP_SRC_TP_SRC,
450 ACTION_SET_TP_DST_TP_DST,
456 ACTION_SET_MAC_SRC_MAC_SRC,
458 ACTION_SET_MAC_DST_MAC_DST,
460 ACTION_INC_TCP_SEQ_VALUE,
462 ACTION_DEC_TCP_SEQ_VALUE,
464 ACTION_INC_TCP_ACK_VALUE,
466 ACTION_DEC_TCP_ACK_VALUE,
469 ACTION_RAW_ENCAP_INDEX,
470 ACTION_RAW_ENCAP_INDEX_VALUE,
471 ACTION_RAW_DECAP_INDEX,
472 ACTION_RAW_DECAP_INDEX_VALUE,
475 ACTION_SET_TAG_INDEX,
478 ACTION_SET_META_DATA,
479 ACTION_SET_META_MASK,
480 ACTION_SET_IPV4_DSCP,
481 ACTION_SET_IPV4_DSCP_VALUE,
482 ACTION_SET_IPV6_DSCP,
483 ACTION_SET_IPV6_DSCP_VALUE,
489 ACTION_SAMPLE_INDEX_VALUE,
491 INDIRECT_ACTION_ID2PTR,
493 ACTION_MODIFY_FIELD_OP,
494 ACTION_MODIFY_FIELD_OP_VALUE,
495 ACTION_MODIFY_FIELD_DST_TYPE,
496 ACTION_MODIFY_FIELD_DST_TYPE_VALUE,
497 ACTION_MODIFY_FIELD_DST_LEVEL,
498 ACTION_MODIFY_FIELD_DST_OFFSET,
499 ACTION_MODIFY_FIELD_SRC_TYPE,
500 ACTION_MODIFY_FIELD_SRC_TYPE_VALUE,
501 ACTION_MODIFY_FIELD_SRC_LEVEL,
502 ACTION_MODIFY_FIELD_SRC_OFFSET,
503 ACTION_MODIFY_FIELD_SRC_VALUE,
504 ACTION_MODIFY_FIELD_SRC_POINTER,
505 ACTION_MODIFY_FIELD_WIDTH,
507 ACTION_CONNTRACK_UPDATE,
508 ACTION_CONNTRACK_UPDATE_DIR,
509 ACTION_CONNTRACK_UPDATE_CTX,
513 ACTION_PORT_REPRESENTOR,
514 ACTION_PORT_REPRESENTOR_PORT_ID,
515 ACTION_REPRESENTED_PORT,
516 ACTION_REPRESENTED_PORT_ETHDEV_PORT_ID,
519 /** Maximum size for pattern in struct rte_flow_item_raw. */
520 #define ITEM_RAW_PATTERN_SIZE 512
522 /** Maximum size for GENEVE option data pattern in bytes. */
523 #define ITEM_GENEVE_OPT_DATA_SIZE 124
525 /** Storage size for struct rte_flow_item_raw including pattern. */
526 #define ITEM_RAW_SIZE \
527 (sizeof(struct rte_flow_item_raw) + ITEM_RAW_PATTERN_SIZE)
529 /** Maximum size for external pattern in struct rte_flow_action_modify_data. */
530 #define ACTION_MODIFY_PATTERN_SIZE 32
532 /** Storage size for struct rte_flow_action_modify_field including pattern. */
533 #define ACTION_MODIFY_SIZE \
534 (sizeof(struct rte_flow_action_modify_field) + \
535 ACTION_MODIFY_PATTERN_SIZE)
537 /** Maximum number of queue indices in struct rte_flow_action_rss. */
538 #define ACTION_RSS_QUEUE_NUM 128
540 /** Storage for struct rte_flow_action_rss including external data. */
541 struct action_rss_data {
542 struct rte_flow_action_rss conf;
543 uint8_t key[RSS_HASH_KEY_LENGTH];
544 uint16_t queue[ACTION_RSS_QUEUE_NUM];
547 /** Maximum data size in struct rte_flow_action_raw_encap. */
548 #define ACTION_RAW_ENCAP_MAX_DATA 512
549 #define RAW_ENCAP_CONFS_MAX_NUM 8
551 /** Storage for struct rte_flow_action_raw_encap. */
552 struct raw_encap_conf {
553 uint8_t data[ACTION_RAW_ENCAP_MAX_DATA];
554 uint8_t preserve[ACTION_RAW_ENCAP_MAX_DATA];
558 struct raw_encap_conf raw_encap_confs[RAW_ENCAP_CONFS_MAX_NUM];
560 /** Storage for struct rte_flow_action_raw_encap including external data. */
561 struct action_raw_encap_data {
562 struct rte_flow_action_raw_encap conf;
563 uint8_t data[ACTION_RAW_ENCAP_MAX_DATA];
564 uint8_t preserve[ACTION_RAW_ENCAP_MAX_DATA];
568 /** Storage for struct rte_flow_action_raw_decap. */
569 struct raw_decap_conf {
570 uint8_t data[ACTION_RAW_ENCAP_MAX_DATA];
574 struct raw_decap_conf raw_decap_confs[RAW_ENCAP_CONFS_MAX_NUM];
576 /** Storage for struct rte_flow_action_raw_decap including external data. */
577 struct action_raw_decap_data {
578 struct rte_flow_action_raw_decap conf;
579 uint8_t data[ACTION_RAW_ENCAP_MAX_DATA];
583 struct vxlan_encap_conf vxlan_encap_conf = {
587 .vni = "\x00\x00\x00",
589 .udp_dst = RTE_BE16(RTE_VXLAN_DEFAULT_PORT),
590 .ipv4_src = RTE_IPV4(127, 0, 0, 1),
591 .ipv4_dst = RTE_IPV4(255, 255, 255, 255),
592 .ipv6_src = "\x00\x00\x00\x00\x00\x00\x00\x00"
593 "\x00\x00\x00\x00\x00\x00\x00\x01",
594 .ipv6_dst = "\x00\x00\x00\x00\x00\x00\x00\x00"
595 "\x00\x00\x00\x00\x00\x00\x11\x11",
599 .eth_src = "\x00\x00\x00\x00\x00\x00",
600 .eth_dst = "\xff\xff\xff\xff\xff\xff",
603 /** Maximum number of items in struct rte_flow_action_vxlan_encap. */
604 #define ACTION_VXLAN_ENCAP_ITEMS_NUM 6
606 /** Storage for struct rte_flow_action_vxlan_encap including external data. */
607 struct action_vxlan_encap_data {
608 struct rte_flow_action_vxlan_encap conf;
609 struct rte_flow_item items[ACTION_VXLAN_ENCAP_ITEMS_NUM];
610 struct rte_flow_item_eth item_eth;
611 struct rte_flow_item_vlan item_vlan;
613 struct rte_flow_item_ipv4 item_ipv4;
614 struct rte_flow_item_ipv6 item_ipv6;
616 struct rte_flow_item_udp item_udp;
617 struct rte_flow_item_vxlan item_vxlan;
620 struct nvgre_encap_conf nvgre_encap_conf = {
623 .tni = "\x00\x00\x00",
624 .ipv4_src = RTE_IPV4(127, 0, 0, 1),
625 .ipv4_dst = RTE_IPV4(255, 255, 255, 255),
626 .ipv6_src = "\x00\x00\x00\x00\x00\x00\x00\x00"
627 "\x00\x00\x00\x00\x00\x00\x00\x01",
628 .ipv6_dst = "\x00\x00\x00\x00\x00\x00\x00\x00"
629 "\x00\x00\x00\x00\x00\x00\x11\x11",
631 .eth_src = "\x00\x00\x00\x00\x00\x00",
632 .eth_dst = "\xff\xff\xff\xff\xff\xff",
635 /** Maximum number of items in struct rte_flow_action_nvgre_encap. */
636 #define ACTION_NVGRE_ENCAP_ITEMS_NUM 5
638 /** Storage for struct rte_flow_action_nvgre_encap including external data. */
639 struct action_nvgre_encap_data {
640 struct rte_flow_action_nvgre_encap conf;
641 struct rte_flow_item items[ACTION_NVGRE_ENCAP_ITEMS_NUM];
642 struct rte_flow_item_eth item_eth;
643 struct rte_flow_item_vlan item_vlan;
645 struct rte_flow_item_ipv4 item_ipv4;
646 struct rte_flow_item_ipv6 item_ipv6;
648 struct rte_flow_item_nvgre item_nvgre;
651 struct l2_encap_conf l2_encap_conf;
653 struct l2_decap_conf l2_decap_conf;
655 struct mplsogre_encap_conf mplsogre_encap_conf;
657 struct mplsogre_decap_conf mplsogre_decap_conf;
659 struct mplsoudp_encap_conf mplsoudp_encap_conf;
661 struct mplsoudp_decap_conf mplsoudp_decap_conf;
663 struct rte_flow_action_conntrack conntrack_context;
665 #define ACTION_SAMPLE_ACTIONS_NUM 10
666 #define RAW_SAMPLE_CONFS_MAX_NUM 8
667 /** Storage for struct rte_flow_action_sample including external data. */
668 struct action_sample_data {
669 struct rte_flow_action_sample conf;
672 /** Storage for struct rte_flow_action_sample. */
673 struct raw_sample_conf {
674 struct rte_flow_action data[ACTION_SAMPLE_ACTIONS_NUM];
676 struct raw_sample_conf raw_sample_confs[RAW_SAMPLE_CONFS_MAX_NUM];
677 struct rte_flow_action_mark sample_mark[RAW_SAMPLE_CONFS_MAX_NUM];
678 struct rte_flow_action_queue sample_queue[RAW_SAMPLE_CONFS_MAX_NUM];
679 struct rte_flow_action_count sample_count[RAW_SAMPLE_CONFS_MAX_NUM];
680 struct rte_flow_action_port_id sample_port_id[RAW_SAMPLE_CONFS_MAX_NUM];
681 struct rte_flow_action_raw_encap sample_encap[RAW_SAMPLE_CONFS_MAX_NUM];
682 struct action_vxlan_encap_data sample_vxlan_encap[RAW_SAMPLE_CONFS_MAX_NUM];
683 struct action_nvgre_encap_data sample_nvgre_encap[RAW_SAMPLE_CONFS_MAX_NUM];
684 struct action_rss_data sample_rss_data[RAW_SAMPLE_CONFS_MAX_NUM];
685 struct rte_flow_action_vf sample_vf[RAW_SAMPLE_CONFS_MAX_NUM];
687 static const char *const modify_field_ops[] = {
688 "set", "add", "sub", NULL
691 static const char *const modify_field_ids[] = {
692 "start", "mac_dst", "mac_src",
693 "vlan_type", "vlan_id", "mac_type",
694 "ipv4_dscp", "ipv4_ttl", "ipv4_src", "ipv4_dst",
695 "ipv6_dscp", "ipv6_hoplimit", "ipv6_src", "ipv6_dst",
696 "tcp_port_src", "tcp_port_dst",
697 "tcp_seq_num", "tcp_ack_num", "tcp_flags",
698 "udp_port_src", "udp_port_dst",
699 "vxlan_vni", "geneve_vni", "gtp_teid",
700 "tag", "mark", "meta", "pointer", "value", NULL
703 /** Maximum number of subsequent tokens and arguments on the stack. */
704 #define CTX_STACK_SIZE 16
706 /** Parser context. */
708 /** Stack of subsequent token lists to process. */
709 const enum index *next[CTX_STACK_SIZE];
710 /** Arguments for stacked tokens. */
711 const void *args[CTX_STACK_SIZE];
712 enum index curr; /**< Current token index. */
713 enum index prev; /**< Index of the last token seen. */
714 int next_num; /**< Number of entries in next[]. */
715 int args_num; /**< Number of entries in args[]. */
716 uint32_t eol:1; /**< EOL has been detected. */
717 uint32_t last:1; /**< No more arguments. */
718 portid_t port; /**< Current port ID (for completions). */
719 uint32_t objdata; /**< Object-specific data. */
720 void *object; /**< Address of current object for relative offsets. */
721 void *objmask; /**< Object a full mask must be written to. */
724 /** Token argument. */
726 uint32_t hton:1; /**< Use network byte ordering. */
727 uint32_t sign:1; /**< Value is signed. */
728 uint32_t bounded:1; /**< Value is bounded. */
729 uintmax_t min; /**< Minimum value if bounded. */
730 uintmax_t max; /**< Maximum value if bounded. */
731 uint32_t offset; /**< Relative offset from ctx->object. */
732 uint32_t size; /**< Field size. */
733 const uint8_t *mask; /**< Bit-mask to use instead of offset/size. */
736 /** Parser token definition. */
738 /** Type displayed during completion (defaults to "TOKEN"). */
740 /** Help displayed during completion (defaults to token name). */
742 /** Private data used by parser functions. */
745 * Lists of subsequent tokens to push on the stack. Each call to the
746 * parser consumes the last entry of that stack.
748 const enum index *const *next;
749 /** Arguments stack for subsequent tokens that need them. */
750 const struct arg *const *args;
752 * Token-processing callback, returns -1 in case of error, the
753 * length of the matched string otherwise. If NULL, attempts to
754 * match the token name.
756 * If buf is not NULL, the result should be stored in it according
757 * to context. An error is returned if not large enough.
759 int (*call)(struct context *ctx, const struct token *token,
760 const char *str, unsigned int len,
761 void *buf, unsigned int size);
763 * Callback that provides possible values for this token, used for
764 * completion. Returns -1 in case of error, the number of possible
765 * values otherwise. If NULL, the token name is used.
767 * If buf is not NULL, entry index ent is written to buf and the
768 * full length of the entry is returned (same behavior as
771 int (*comp)(struct context *ctx, const struct token *token,
772 unsigned int ent, char *buf, unsigned int size);
773 /** Mandatory token name, no default value. */
777 /** Static initializer for the next field. */
778 #define NEXT(...) (const enum index *const []){ __VA_ARGS__, NULL, }
780 /** Static initializer for a NEXT() entry. */
781 #define NEXT_ENTRY(...) (const enum index []){ __VA_ARGS__, ZERO, }
783 /** Static initializer for the args field. */
784 #define ARGS(...) (const struct arg *const []){ __VA_ARGS__, NULL, }
786 /** Static initializer for ARGS() to target a field. */
787 #define ARGS_ENTRY(s, f) \
788 (&(const struct arg){ \
789 .offset = offsetof(s, f), \
790 .size = sizeof(((s *)0)->f), \
793 /** Static initializer for ARGS() to target a bit-field. */
794 #define ARGS_ENTRY_BF(s, f, b) \
795 (&(const struct arg){ \
797 .mask = (const void *)&(const s){ .f = (1 << (b)) - 1 }, \
800 /** Static initializer for ARGS() to target a field with limits. */
801 #define ARGS_ENTRY_BOUNDED(s, f, i, a) \
802 (&(const struct arg){ \
806 .offset = offsetof(s, f), \
807 .size = sizeof(((s *)0)->f), \
810 /** Static initializer for ARGS() to target an arbitrary bit-mask. */
811 #define ARGS_ENTRY_MASK(s, f, m) \
812 (&(const struct arg){ \
813 .offset = offsetof(s, f), \
814 .size = sizeof(((s *)0)->f), \
815 .mask = (const void *)(m), \
818 /** Same as ARGS_ENTRY_MASK() using network byte ordering for the value. */
819 #define ARGS_ENTRY_MASK_HTON(s, f, m) \
820 (&(const struct arg){ \
822 .offset = offsetof(s, f), \
823 .size = sizeof(((s *)0)->f), \
824 .mask = (const void *)(m), \
827 /** Static initializer for ARGS() to target a pointer. */
828 #define ARGS_ENTRY_PTR(s, f) \
829 (&(const struct arg){ \
830 .size = sizeof(*((s *)0)->f), \
833 /** Static initializer for ARGS() with arbitrary offset and size. */
834 #define ARGS_ENTRY_ARB(o, s) \
835 (&(const struct arg){ \
840 /** Same as ARGS_ENTRY_ARB() with bounded values. */
841 #define ARGS_ENTRY_ARB_BOUNDED(o, s, i, a) \
842 (&(const struct arg){ \
850 /** Same as ARGS_ENTRY() using network byte ordering. */
851 #define ARGS_ENTRY_HTON(s, f) \
852 (&(const struct arg){ \
854 .offset = offsetof(s, f), \
855 .size = sizeof(((s *)0)->f), \
858 /** Same as ARGS_ENTRY_HTON() for a single argument, without structure. */
859 #define ARG_ENTRY_HTON(s) \
860 (&(const struct arg){ \
866 /** Parser output buffer layout expected by cmd_flow_parsed(). */
868 enum index command; /**< Flow command. */
869 portid_t port; /**< Affected port ID. */
873 uint32_t action_id_n;
874 } ia_destroy; /**< Indirect action destroy arguments. */
877 } ia; /* Indirect action query arguments */
879 struct rte_flow_attr attr;
880 struct tunnel_ops tunnel_ops;
881 struct rte_flow_item *pattern;
882 struct rte_flow_action *actions;
886 } vc; /**< Validate/create arguments. */
890 } destroy; /**< Destroy arguments. */
895 } dump; /**< Dump arguments. */
898 struct rte_flow_action action;
899 } query; /**< Query arguments. */
903 } list; /**< List arguments. */
906 } isolate; /**< Isolated mode arguments. */
909 } aged; /**< Aged arguments. */
912 } policy;/**< Policy arguments. */
917 } flex; /**< Flex arguments*/
918 } args; /**< Command arguments. */
921 /** Private data for pattern items. */
922 struct parse_item_priv {
923 enum rte_flow_item_type type; /**< Item type. */
924 uint32_t size; /**< Size of item specification structure. */
927 #define PRIV_ITEM(t, s) \
928 (&(const struct parse_item_priv){ \
929 .type = RTE_FLOW_ITEM_TYPE_ ## t, \
933 /** Private data for actions. */
934 struct parse_action_priv {
935 enum rte_flow_action_type type; /**< Action type. */
936 uint32_t size; /**< Size of action configuration structure. */
939 #define PRIV_ACTION(t, s) \
940 (&(const struct parse_action_priv){ \
941 .type = RTE_FLOW_ACTION_TYPE_ ## t, \
945 static const enum index next_flex_item[] = {
952 static const enum index next_ia_create_attr[] = {
953 INDIRECT_ACTION_CREATE_ID,
954 INDIRECT_ACTION_INGRESS,
955 INDIRECT_ACTION_EGRESS,
956 INDIRECT_ACTION_TRANSFER,
957 INDIRECT_ACTION_SPEC,
961 static const enum index next_dump_subcmd[] = {
967 static const enum index next_ia_subcmd[] = {
968 INDIRECT_ACTION_CREATE,
969 INDIRECT_ACTION_UPDATE,
970 INDIRECT_ACTION_DESTROY,
971 INDIRECT_ACTION_QUERY,
975 static const enum index next_vc_attr[] = {
987 static const enum index next_destroy_attr[] = {
993 static const enum index next_dump_attr[] = {
999 static const enum index next_list_attr[] = {
1005 static const enum index next_aged_attr[] = {
1011 static const enum index next_ia_destroy_attr[] = {
1012 INDIRECT_ACTION_DESTROY_ID,
1017 static const enum index item_param[] = {
1026 static const enum index next_item[] = {
1063 ITEM_ICMP6_ND_OPT_SLA_ETH,
1064 ITEM_ICMP6_ND_OPT_TLA_ETH,
1071 ITEM_PPPOE_PROTO_ID,
1082 ITEM_PORT_REPRESENTOR,
1083 ITEM_REPRESENTED_PORT,
1091 static const enum index item_fuzzy[] = {
1097 static const enum index item_any[] = {
1103 static const enum index item_vf[] = {
1109 static const enum index item_phy_port[] = {
1110 ITEM_PHY_PORT_INDEX,
1115 static const enum index item_port_id[] = {
1121 static const enum index item_mark[] = {
1127 static const enum index item_raw[] = {
1133 ITEM_RAW_PATTERN_HEX,
1138 static const enum index item_eth[] = {
1147 static const enum index item_vlan[] = {
1152 ITEM_VLAN_INNER_TYPE,
1153 ITEM_VLAN_HAS_MORE_VLAN,
1158 static const enum index item_ipv4[] = {
1162 ITEM_IPV4_FRAGMENT_OFFSET,
1171 static const enum index item_ipv6[] = {
1178 ITEM_IPV6_HAS_FRAG_EXT,
1183 static const enum index item_icmp[] = {
1192 static const enum index item_udp[] = {
1199 static const enum index item_tcp[] = {
1207 static const enum index item_sctp[] = {
1216 static const enum index item_vxlan[] = {
1218 ITEM_VXLAN_LAST_RSVD,
1223 static const enum index item_e_tag[] = {
1224 ITEM_E_TAG_GRP_ECID_B,
1229 static const enum index item_nvgre[] = {
1235 static const enum index item_mpls[] = {
1243 static const enum index item_gre[] = {
1245 ITEM_GRE_C_RSVD0_VER,
1253 static const enum index item_gre_key[] = {
1259 static const enum index item_gre_option[] = {
1260 ITEM_GRE_OPTION_CHECKSUM,
1261 ITEM_GRE_OPTION_KEY,
1262 ITEM_GRE_OPTION_SEQUENCE,
1267 static const enum index item_gtp[] = {
1275 static const enum index item_geneve[] = {
1283 static const enum index item_vxlan_gpe[] = {
1289 static const enum index item_arp_eth_ipv4[] = {
1290 ITEM_ARP_ETH_IPV4_SHA,
1291 ITEM_ARP_ETH_IPV4_SPA,
1292 ITEM_ARP_ETH_IPV4_THA,
1293 ITEM_ARP_ETH_IPV4_TPA,
1298 static const enum index item_ipv6_ext[] = {
1299 ITEM_IPV6_EXT_NEXT_HDR,
1304 static const enum index item_ipv6_frag_ext[] = {
1305 ITEM_IPV6_FRAG_EXT_NEXT_HDR,
1306 ITEM_IPV6_FRAG_EXT_FRAG_DATA,
1307 ITEM_IPV6_FRAG_EXT_ID,
1312 static const enum index item_icmp6[] = {
1319 static const enum index item_icmp6_nd_ns[] = {
1320 ITEM_ICMP6_ND_NS_TARGET_ADDR,
1325 static const enum index item_icmp6_nd_na[] = {
1326 ITEM_ICMP6_ND_NA_TARGET_ADDR,
1331 static const enum index item_icmp6_nd_opt[] = {
1332 ITEM_ICMP6_ND_OPT_TYPE,
1337 static const enum index item_icmp6_nd_opt_sla_eth[] = {
1338 ITEM_ICMP6_ND_OPT_SLA_ETH_SLA,
1343 static const enum index item_icmp6_nd_opt_tla_eth[] = {
1344 ITEM_ICMP6_ND_OPT_TLA_ETH_TLA,
1349 static const enum index item_meta[] = {
1355 static const enum index item_gtp_psc[] = {
1362 static const enum index item_pppoed[] = {
1368 static const enum index item_pppoes[] = {
1374 static const enum index item_pppoe_proto_id[] = {
1379 static const enum index item_higig2[] = {
1380 ITEM_HIGIG2_CLASSIFICATION,
1386 static const enum index item_esp[] = {
1392 static const enum index item_ah[] = {
1398 static const enum index item_pfcp[] = {
1405 static const enum index next_set_raw[] = {
1411 static const enum index item_tag[] = {
1418 static const enum index item_l2tpv3oip[] = {
1419 ITEM_L2TPV3OIP_SESSION_ID,
1424 static const enum index item_ecpri[] = {
1430 static const enum index item_ecpri_common[] = {
1431 ITEM_ECPRI_COMMON_TYPE,
1435 static const enum index item_ecpri_common_type[] = {
1436 ITEM_ECPRI_COMMON_TYPE_IQ_DATA,
1437 ITEM_ECPRI_COMMON_TYPE_RTC_CTRL,
1438 ITEM_ECPRI_COMMON_TYPE_DLY_MSR,
1442 static const enum index item_geneve_opt[] = {
1443 ITEM_GENEVE_OPT_CLASS,
1444 ITEM_GENEVE_OPT_TYPE,
1445 ITEM_GENEVE_OPT_LENGTH,
1446 ITEM_GENEVE_OPT_DATA,
1451 static const enum index item_integrity[] = {
1452 ITEM_INTEGRITY_LEVEL,
1453 ITEM_INTEGRITY_VALUE,
1457 static const enum index item_integrity_lv[] = {
1458 ITEM_INTEGRITY_LEVEL,
1459 ITEM_INTEGRITY_VALUE,
1464 static const enum index item_port_representor[] = {
1465 ITEM_PORT_REPRESENTOR_PORT_ID,
1470 static const enum index item_represented_port[] = {
1471 ITEM_REPRESENTED_PORT_ETHDEV_PORT_ID,
1476 static const enum index item_flex[] = {
1477 ITEM_FLEX_PATTERN_HANDLE,
1478 ITEM_FLEX_ITEM_HANDLE,
1483 static const enum index item_l2tpv2[] = {
1489 static const enum index item_l2tpv2_type[] = {
1490 ITEM_L2TPV2_TYPE_DATA,
1491 ITEM_L2TPV2_TYPE_DATA_L,
1492 ITEM_L2TPV2_TYPE_DATA_S,
1493 ITEM_L2TPV2_TYPE_DATA_O,
1494 ITEM_L2TPV2_TYPE_DATA_L_S,
1495 ITEM_L2TPV2_TYPE_CTRL,
1499 static const enum index item_l2tpv2_type_data[] = {
1500 ITEM_L2TPV2_MSG_DATA_TUNNEL_ID,
1501 ITEM_L2TPV2_MSG_DATA_SESSION_ID,
1506 static const enum index item_l2tpv2_type_data_l[] = {
1507 ITEM_L2TPV2_MSG_DATA_L_LENGTH,
1508 ITEM_L2TPV2_MSG_DATA_L_TUNNEL_ID,
1509 ITEM_L2TPV2_MSG_DATA_L_SESSION_ID,
1514 static const enum index item_l2tpv2_type_data_s[] = {
1515 ITEM_L2TPV2_MSG_DATA_S_TUNNEL_ID,
1516 ITEM_L2TPV2_MSG_DATA_S_SESSION_ID,
1517 ITEM_L2TPV2_MSG_DATA_S_NS,
1518 ITEM_L2TPV2_MSG_DATA_S_NR,
1523 static const enum index item_l2tpv2_type_data_o[] = {
1524 ITEM_L2TPV2_MSG_DATA_O_TUNNEL_ID,
1525 ITEM_L2TPV2_MSG_DATA_O_SESSION_ID,
1526 ITEM_L2TPV2_MSG_DATA_O_OFFSET,
1531 static const enum index item_l2tpv2_type_data_l_s[] = {
1532 ITEM_L2TPV2_MSG_DATA_L_S_LENGTH,
1533 ITEM_L2TPV2_MSG_DATA_L_S_TUNNEL_ID,
1534 ITEM_L2TPV2_MSG_DATA_L_S_SESSION_ID,
1535 ITEM_L2TPV2_MSG_DATA_L_S_NS,
1536 ITEM_L2TPV2_MSG_DATA_L_S_NR,
1541 static const enum index item_l2tpv2_type_ctrl[] = {
1542 ITEM_L2TPV2_MSG_CTRL_LENGTH,
1543 ITEM_L2TPV2_MSG_CTRL_TUNNEL_ID,
1544 ITEM_L2TPV2_MSG_CTRL_SESSION_ID,
1545 ITEM_L2TPV2_MSG_CTRL_NS,
1546 ITEM_L2TPV2_MSG_CTRL_NR,
1551 static const enum index item_ppp[] = {
1559 static const enum index next_action[] = {
1576 ACTION_OF_SET_MPLS_TTL,
1577 ACTION_OF_DEC_MPLS_TTL,
1578 ACTION_OF_SET_NW_TTL,
1579 ACTION_OF_DEC_NW_TTL,
1580 ACTION_OF_COPY_TTL_OUT,
1581 ACTION_OF_COPY_TTL_IN,
1583 ACTION_OF_PUSH_VLAN,
1584 ACTION_OF_SET_VLAN_VID,
1585 ACTION_OF_SET_VLAN_PCP,
1587 ACTION_OF_PUSH_MPLS,
1594 ACTION_MPLSOGRE_ENCAP,
1595 ACTION_MPLSOGRE_DECAP,
1596 ACTION_MPLSOUDP_ENCAP,
1597 ACTION_MPLSOUDP_DECAP,
1598 ACTION_SET_IPV4_SRC,
1599 ACTION_SET_IPV4_DST,
1600 ACTION_SET_IPV6_SRC,
1601 ACTION_SET_IPV6_DST,
1617 ACTION_SET_IPV4_DSCP,
1618 ACTION_SET_IPV6_DSCP,
1622 ACTION_MODIFY_FIELD,
1624 ACTION_CONNTRACK_UPDATE,
1625 ACTION_PORT_REPRESENTOR,
1626 ACTION_REPRESENTED_PORT,
1630 static const enum index action_mark[] = {
1636 static const enum index action_queue[] = {
1642 static const enum index action_count[] = {
1648 static const enum index action_rss[] = {
1659 static const enum index action_vf[] = {
1666 static const enum index action_phy_port[] = {
1667 ACTION_PHY_PORT_ORIGINAL,
1668 ACTION_PHY_PORT_INDEX,
1673 static const enum index action_port_id[] = {
1674 ACTION_PORT_ID_ORIGINAL,
1680 static const enum index action_meter[] = {
1686 static const enum index action_meter_color[] = {
1687 ACTION_METER_COLOR_TYPE,
1692 static const enum index action_of_set_mpls_ttl[] = {
1693 ACTION_OF_SET_MPLS_TTL_MPLS_TTL,
1698 static const enum index action_of_set_nw_ttl[] = {
1699 ACTION_OF_SET_NW_TTL_NW_TTL,
1704 static const enum index action_of_push_vlan[] = {
1705 ACTION_OF_PUSH_VLAN_ETHERTYPE,
1710 static const enum index action_of_set_vlan_vid[] = {
1711 ACTION_OF_SET_VLAN_VID_VLAN_VID,
1716 static const enum index action_of_set_vlan_pcp[] = {
1717 ACTION_OF_SET_VLAN_PCP_VLAN_PCP,
1722 static const enum index action_of_pop_mpls[] = {
1723 ACTION_OF_POP_MPLS_ETHERTYPE,
1728 static const enum index action_of_push_mpls[] = {
1729 ACTION_OF_PUSH_MPLS_ETHERTYPE,
1734 static const enum index action_set_ipv4_src[] = {
1735 ACTION_SET_IPV4_SRC_IPV4_SRC,
1740 static const enum index action_set_mac_src[] = {
1741 ACTION_SET_MAC_SRC_MAC_SRC,
1746 static const enum index action_set_ipv4_dst[] = {
1747 ACTION_SET_IPV4_DST_IPV4_DST,
1752 static const enum index action_set_ipv6_src[] = {
1753 ACTION_SET_IPV6_SRC_IPV6_SRC,
1758 static const enum index action_set_ipv6_dst[] = {
1759 ACTION_SET_IPV6_DST_IPV6_DST,
1764 static const enum index action_set_tp_src[] = {
1765 ACTION_SET_TP_SRC_TP_SRC,
1770 static const enum index action_set_tp_dst[] = {
1771 ACTION_SET_TP_DST_TP_DST,
1776 static const enum index action_set_ttl[] = {
1782 static const enum index action_jump[] = {
1788 static const enum index action_set_mac_dst[] = {
1789 ACTION_SET_MAC_DST_MAC_DST,
1794 static const enum index action_inc_tcp_seq[] = {
1795 ACTION_INC_TCP_SEQ_VALUE,
1800 static const enum index action_dec_tcp_seq[] = {
1801 ACTION_DEC_TCP_SEQ_VALUE,
1806 static const enum index action_inc_tcp_ack[] = {
1807 ACTION_INC_TCP_ACK_VALUE,
1812 static const enum index action_dec_tcp_ack[] = {
1813 ACTION_DEC_TCP_ACK_VALUE,
1818 static const enum index action_raw_encap[] = {
1819 ACTION_RAW_ENCAP_INDEX,
1824 static const enum index action_raw_decap[] = {
1825 ACTION_RAW_DECAP_INDEX,
1830 static const enum index action_set_tag[] = {
1831 ACTION_SET_TAG_DATA,
1832 ACTION_SET_TAG_INDEX,
1833 ACTION_SET_TAG_MASK,
1838 static const enum index action_set_meta[] = {
1839 ACTION_SET_META_DATA,
1840 ACTION_SET_META_MASK,
1845 static const enum index action_set_ipv4_dscp[] = {
1846 ACTION_SET_IPV4_DSCP_VALUE,
1851 static const enum index action_set_ipv6_dscp[] = {
1852 ACTION_SET_IPV6_DSCP_VALUE,
1857 static const enum index action_age[] = {
1864 static const enum index action_sample[] = {
1866 ACTION_SAMPLE_RATIO,
1867 ACTION_SAMPLE_INDEX,
1872 static const enum index next_action_sample[] = {
1885 static const enum index action_modify_field_dst[] = {
1886 ACTION_MODIFY_FIELD_DST_LEVEL,
1887 ACTION_MODIFY_FIELD_DST_OFFSET,
1888 ACTION_MODIFY_FIELD_SRC_TYPE,
1892 static const enum index action_modify_field_src[] = {
1893 ACTION_MODIFY_FIELD_SRC_LEVEL,
1894 ACTION_MODIFY_FIELD_SRC_OFFSET,
1895 ACTION_MODIFY_FIELD_SRC_VALUE,
1896 ACTION_MODIFY_FIELD_SRC_POINTER,
1897 ACTION_MODIFY_FIELD_WIDTH,
1901 static const enum index action_update_conntrack[] = {
1902 ACTION_CONNTRACK_UPDATE_DIR,
1903 ACTION_CONNTRACK_UPDATE_CTX,
1908 static const enum index action_port_representor[] = {
1909 ACTION_PORT_REPRESENTOR_PORT_ID,
1914 static const enum index action_represented_port[] = {
1915 ACTION_REPRESENTED_PORT_ETHDEV_PORT_ID,
1920 static int parse_set_raw_encap_decap(struct context *, const struct token *,
1921 const char *, unsigned int,
1922 void *, unsigned int);
1923 static int parse_set_sample_action(struct context *, const struct token *,
1924 const char *, unsigned int,
1925 void *, unsigned int);
1926 static int parse_set_init(struct context *, const struct token *,
1927 const char *, unsigned int,
1928 void *, unsigned int);
1930 parse_flex_handle(struct context *, const struct token *,
1931 const char *, unsigned int, void *, unsigned int);
1932 static int parse_init(struct context *, const struct token *,
1933 const char *, unsigned int,
1934 void *, unsigned int);
1935 static int parse_vc(struct context *, const struct token *,
1936 const char *, unsigned int,
1937 void *, unsigned int);
1938 static int parse_vc_spec(struct context *, const struct token *,
1939 const char *, unsigned int, void *, unsigned int);
1940 static int parse_vc_conf(struct context *, const struct token *,
1941 const char *, unsigned int, void *, unsigned int);
1942 static int parse_vc_item_ecpri_type(struct context *, const struct token *,
1943 const char *, unsigned int,
1944 void *, unsigned int);
1945 static int parse_vc_item_l2tpv2_type(struct context *, const struct token *,
1946 const char *, unsigned int,
1947 void *, unsigned int);
1948 static int parse_vc_action_meter_color_type(struct context *,
1949 const struct token *,
1950 const char *, unsigned int, void *,
1952 static int parse_vc_action_rss(struct context *, const struct token *,
1953 const char *, unsigned int, void *,
1955 static int parse_vc_action_rss_func(struct context *, const struct token *,
1956 const char *, unsigned int, void *,
1958 static int parse_vc_action_rss_type(struct context *, const struct token *,
1959 const char *, unsigned int, void *,
1961 static int parse_vc_action_rss_queue(struct context *, const struct token *,
1962 const char *, unsigned int, void *,
1964 static int parse_vc_action_vxlan_encap(struct context *, const struct token *,
1965 const char *, unsigned int, void *,
1967 static int parse_vc_action_nvgre_encap(struct context *, const struct token *,
1968 const char *, unsigned int, void *,
1970 static int parse_vc_action_l2_encap(struct context *, const struct token *,
1971 const char *, unsigned int, void *,
1973 static int parse_vc_action_l2_decap(struct context *, const struct token *,
1974 const char *, unsigned int, void *,
1976 static int parse_vc_action_mplsogre_encap(struct context *,
1977 const struct token *, const char *,
1978 unsigned int, void *, unsigned int);
1979 static int parse_vc_action_mplsogre_decap(struct context *,
1980 const struct token *, const char *,
1981 unsigned int, void *, unsigned int);
1982 static int parse_vc_action_mplsoudp_encap(struct context *,
1983 const struct token *, const char *,
1984 unsigned int, void *, unsigned int);
1985 static int parse_vc_action_mplsoudp_decap(struct context *,
1986 const struct token *, const char *,
1987 unsigned int, void *, unsigned int);
1988 static int parse_vc_action_raw_encap(struct context *,
1989 const struct token *, const char *,
1990 unsigned int, void *, unsigned int);
1991 static int parse_vc_action_raw_decap(struct context *,
1992 const struct token *, const char *,
1993 unsigned int, void *, unsigned int);
1994 static int parse_vc_action_raw_encap_index(struct context *,
1995 const struct token *, const char *,
1996 unsigned int, void *, unsigned int);
1997 static int parse_vc_action_raw_decap_index(struct context *,
1998 const struct token *, const char *,
1999 unsigned int, void *, unsigned int);
2000 static int parse_vc_action_set_meta(struct context *ctx,
2001 const struct token *token, const char *str,
2002 unsigned int len, void *buf,
2004 static int parse_vc_action_sample(struct context *ctx,
2005 const struct token *token, const char *str,
2006 unsigned int len, void *buf,
2009 parse_vc_action_sample_index(struct context *ctx, const struct token *token,
2010 const char *str, unsigned int len, void *buf,
2013 parse_vc_modify_field_op(struct context *ctx, const struct token *token,
2014 const char *str, unsigned int len, void *buf,
2017 parse_vc_modify_field_id(struct context *ctx, const struct token *token,
2018 const char *str, unsigned int len, void *buf,
2021 parse_vc_action_conntrack_update(struct context *ctx, const struct token *token,
2022 const char *str, unsigned int len, void *buf,
2024 static int parse_destroy(struct context *, const struct token *,
2025 const char *, unsigned int,
2026 void *, unsigned int);
2027 static int parse_flush(struct context *, const struct token *,
2028 const char *, unsigned int,
2029 void *, unsigned int);
2030 static int parse_dump(struct context *, const struct token *,
2031 const char *, unsigned int,
2032 void *, unsigned int);
2033 static int parse_query(struct context *, const struct token *,
2034 const char *, unsigned int,
2035 void *, unsigned int);
2036 static int parse_action(struct context *, const struct token *,
2037 const char *, unsigned int,
2038 void *, unsigned int);
2039 static int parse_list(struct context *, const struct token *,
2040 const char *, unsigned int,
2041 void *, unsigned int);
2042 static int parse_aged(struct context *, const struct token *,
2043 const char *, unsigned int,
2044 void *, unsigned int);
2045 static int parse_isolate(struct context *, const struct token *,
2046 const char *, unsigned int,
2047 void *, unsigned int);
2048 static int parse_tunnel(struct context *, const struct token *,
2049 const char *, unsigned int,
2050 void *, unsigned int);
2051 static int parse_flex(struct context *, const struct token *,
2052 const char *, unsigned int, void *, unsigned int);
2053 static int parse_int(struct context *, const struct token *,
2054 const char *, unsigned int,
2055 void *, unsigned int);
2056 static int parse_prefix(struct context *, const struct token *,
2057 const char *, unsigned int,
2058 void *, unsigned int);
2059 static int parse_boolean(struct context *, const struct token *,
2060 const char *, unsigned int,
2061 void *, unsigned int);
2062 static int parse_string(struct context *, const struct token *,
2063 const char *, unsigned int,
2064 void *, unsigned int);
2065 static int parse_hex(struct context *ctx, const struct token *token,
2066 const char *str, unsigned int len,
2067 void *buf, unsigned int size);
2068 static int parse_string0(struct context *, const struct token *,
2069 const char *, unsigned int,
2070 void *, unsigned int);
2071 static int parse_mac_addr(struct context *, const struct token *,
2072 const char *, unsigned int,
2073 void *, unsigned int);
2074 static int parse_ipv4_addr(struct context *, const struct token *,
2075 const char *, unsigned int,
2076 void *, unsigned int);
2077 static int parse_ipv6_addr(struct context *, const struct token *,
2078 const char *, unsigned int,
2079 void *, unsigned int);
2080 static int parse_port(struct context *, const struct token *,
2081 const char *, unsigned int,
2082 void *, unsigned int);
2083 static int parse_ia(struct context *, const struct token *,
2084 const char *, unsigned int,
2085 void *, unsigned int);
2086 static int parse_ia_destroy(struct context *ctx, const struct token *token,
2087 const char *str, unsigned int len,
2088 void *buf, unsigned int size);
2089 static int parse_ia_id2ptr(struct context *ctx, const struct token *token,
2090 const char *str, unsigned int len, void *buf,
2092 static int parse_mp(struct context *, const struct token *,
2093 const char *, unsigned int,
2094 void *, unsigned int);
2095 static int comp_none(struct context *, const struct token *,
2096 unsigned int, char *, unsigned int);
2097 static int comp_boolean(struct context *, const struct token *,
2098 unsigned int, char *, unsigned int);
2099 static int comp_action(struct context *, const struct token *,
2100 unsigned int, char *, unsigned int);
2101 static int comp_port(struct context *, const struct token *,
2102 unsigned int, char *, unsigned int);
2103 static int comp_rule_id(struct context *, const struct token *,
2104 unsigned int, char *, unsigned int);
2105 static int comp_vc_action_rss_type(struct context *, const struct token *,
2106 unsigned int, char *, unsigned int);
2107 static int comp_vc_action_rss_queue(struct context *, const struct token *,
2108 unsigned int, char *, unsigned int);
2109 static int comp_set_raw_index(struct context *, const struct token *,
2110 unsigned int, char *, unsigned int);
2111 static int comp_set_sample_index(struct context *, const struct token *,
2112 unsigned int, char *, unsigned int);
2113 static int comp_set_modify_field_op(struct context *, const struct token *,
2114 unsigned int, char *, unsigned int);
2115 static int comp_set_modify_field_id(struct context *, const struct token *,
2116 unsigned int, char *, unsigned int);
2118 /** Token definitions. */
2119 static const struct token token_list[] = {
2120 /* Special tokens. */
2123 .help = "null entry, abused as the entry point",
2124 .next = NEXT(NEXT_ENTRY(FLOW, ADD)),
2129 .help = "command may end here",
2132 .name = "START_SET",
2133 .help = "null entry, abused as the entry point for set",
2134 .next = NEXT(NEXT_ENTRY(SET)),
2139 .help = "set command may end here",
2141 /* Common tokens. */
2142 [COMMON_INTEGER] = {
2145 .help = "integer value",
2149 [COMMON_UNSIGNED] = {
2150 .name = "{unsigned}",
2152 .help = "unsigned integer value",
2159 .help = "prefix length for bit-mask",
2160 .call = parse_prefix,
2163 [COMMON_BOOLEAN] = {
2164 .name = "{boolean}",
2166 .help = "any boolean value",
2167 .call = parse_boolean,
2168 .comp = comp_boolean,
2173 .help = "fixed string",
2174 .call = parse_string,
2180 .help = "fixed string",
2183 [COMMON_FILE_PATH] = {
2184 .name = "{file path}",
2186 .help = "file path",
2187 .call = parse_string0,
2190 [COMMON_MAC_ADDR] = {
2191 .name = "{MAC address}",
2193 .help = "standard MAC address notation",
2194 .call = parse_mac_addr,
2197 [COMMON_IPV4_ADDR] = {
2198 .name = "{IPv4 address}",
2199 .type = "IPV4 ADDRESS",
2200 .help = "standard IPv4 address notation",
2201 .call = parse_ipv4_addr,
2204 [COMMON_IPV6_ADDR] = {
2205 .name = "{IPv6 address}",
2206 .type = "IPV6 ADDRESS",
2207 .help = "standard IPv6 address notation",
2208 .call = parse_ipv6_addr,
2211 [COMMON_RULE_ID] = {
2212 .name = "{rule id}",
2214 .help = "rule identifier",
2216 .comp = comp_rule_id,
2218 [COMMON_PORT_ID] = {
2219 .name = "{port_id}",
2221 .help = "port identifier",
2225 [COMMON_GROUP_ID] = {
2226 .name = "{group_id}",
2228 .help = "group identifier",
2232 [COMMON_PRIORITY_LEVEL] = {
2235 .help = "priority level",
2239 [COMMON_INDIRECT_ACTION_ID] = {
2240 .name = "{indirect_action_id}",
2241 .type = "INDIRECT_ACTION_ID",
2242 .help = "indirect action id",
2246 [COMMON_POLICY_ID] = {
2247 .name = "{policy_id}",
2248 .type = "POLICY_ID",
2249 .help = "policy id",
2253 [COMMON_FLEX_TOKEN] = {
2254 .name = "{flex token}",
2255 .type = "flex token",
2256 .help = "flex token",
2260 [COMMON_FLEX_HANDLE] = {
2261 .name = "{flex handle}",
2262 .type = "FLEX HANDLE",
2263 .help = "fill flex item data",
2264 .call = parse_flex_handle,
2267 /* Top-level command. */
2270 .type = "{command} {port_id} [{arg} [...]]",
2271 .help = "manage ingress/egress flow rules",
2272 .next = NEXT(NEXT_ENTRY
2287 /* Top-level command. */
2288 [INDIRECT_ACTION] = {
2289 .name = "indirect_action",
2290 .type = "{command} {port_id} [{arg} [...]]",
2291 .help = "manage indirect actions",
2292 .next = NEXT(next_ia_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
2293 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2296 /* Sub-level commands. */
2297 [INDIRECT_ACTION_CREATE] = {
2299 .help = "create indirect action",
2300 .next = NEXT(next_ia_create_attr),
2303 [INDIRECT_ACTION_UPDATE] = {
2305 .help = "update indirect action",
2306 .next = NEXT(NEXT_ENTRY(INDIRECT_ACTION_SPEC),
2307 NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
2308 .args = ARGS(ARGS_ENTRY(struct buffer, args.vc.attr.group)),
2311 [INDIRECT_ACTION_DESTROY] = {
2313 .help = "destroy indirect action",
2314 .next = NEXT(NEXT_ENTRY(INDIRECT_ACTION_DESTROY_ID)),
2315 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2316 .call = parse_ia_destroy,
2318 [INDIRECT_ACTION_QUERY] = {
2320 .help = "query indirect action",
2321 .next = NEXT(NEXT_ENTRY(END),
2322 NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
2323 .args = ARGS(ARGS_ENTRY(struct buffer, args.ia.action_id)),
2328 .help = "check whether a flow rule can be created",
2329 .next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_PORT_ID)),
2330 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2335 .help = "create a flow rule",
2336 .next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_PORT_ID)),
2337 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2342 .help = "destroy specific flow rules",
2343 .next = NEXT(NEXT_ENTRY(DESTROY_RULE),
2344 NEXT_ENTRY(COMMON_PORT_ID)),
2345 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2346 .call = parse_destroy,
2350 .help = "destroy all flow rules",
2351 .next = NEXT(NEXT_ENTRY(COMMON_PORT_ID)),
2352 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2353 .call = parse_flush,
2357 .help = "dump single/all flow rules to file",
2358 .next = NEXT(next_dump_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
2359 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2364 .help = "query an existing flow rule",
2365 .next = NEXT(NEXT_ENTRY(QUERY_ACTION),
2366 NEXT_ENTRY(COMMON_RULE_ID),
2367 NEXT_ENTRY(COMMON_PORT_ID)),
2368 .args = ARGS(ARGS_ENTRY(struct buffer, args.query.action.type),
2369 ARGS_ENTRY(struct buffer, args.query.rule),
2370 ARGS_ENTRY(struct buffer, port)),
2371 .call = parse_query,
2375 .help = "list existing flow rules",
2376 .next = NEXT(next_list_attr, NEXT_ENTRY(COMMON_PORT_ID)),
2377 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2382 .help = "list and destroy aged flows",
2383 .next = NEXT(next_aged_attr, NEXT_ENTRY(COMMON_PORT_ID)),
2384 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2389 .help = "restrict ingress traffic to the defined flow rules",
2390 .next = NEXT(NEXT_ENTRY(COMMON_BOOLEAN),
2391 NEXT_ENTRY(COMMON_PORT_ID)),
2392 .args = ARGS(ARGS_ENTRY(struct buffer, args.isolate.set),
2393 ARGS_ENTRY(struct buffer, port)),
2394 .call = parse_isolate,
2397 .name = "flex_item",
2398 .help = "flex item API",
2399 .next = NEXT(next_flex_item),
2402 [FLEX_ITEM_INIT] = {
2404 .help = "flex item init",
2405 .args = ARGS(ARGS_ENTRY(struct buffer, args.flex.token),
2406 ARGS_ENTRY(struct buffer, port)),
2407 .next = NEXT(NEXT_ENTRY(COMMON_FLEX_TOKEN),
2408 NEXT_ENTRY(COMMON_PORT_ID)),
2411 [FLEX_ITEM_CREATE] = {
2413 .help = "flex item create",
2414 .args = ARGS(ARGS_ENTRY(struct buffer, args.flex.filename),
2415 ARGS_ENTRY(struct buffer, args.flex.token),
2416 ARGS_ENTRY(struct buffer, port)),
2417 .next = NEXT(NEXT_ENTRY(COMMON_FILE_PATH),
2418 NEXT_ENTRY(COMMON_FLEX_TOKEN),
2419 NEXT_ENTRY(COMMON_PORT_ID)),
2422 [FLEX_ITEM_DESTROY] = {
2424 .help = "flex item destroy",
2425 .args = ARGS(ARGS_ENTRY(struct buffer, args.flex.token),
2426 ARGS_ENTRY(struct buffer, port)),
2427 .next = NEXT(NEXT_ENTRY(COMMON_FLEX_TOKEN),
2428 NEXT_ENTRY(COMMON_PORT_ID)),
2433 .help = "new tunnel API",
2434 .next = NEXT(NEXT_ENTRY
2435 (TUNNEL_CREATE, TUNNEL_LIST, TUNNEL_DESTROY)),
2436 .call = parse_tunnel,
2438 /* Tunnel arguments. */
2441 .help = "create new tunnel object",
2442 .next = NEXT(NEXT_ENTRY(TUNNEL_CREATE_TYPE),
2443 NEXT_ENTRY(COMMON_PORT_ID)),
2444 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2445 .call = parse_tunnel,
2447 [TUNNEL_CREATE_TYPE] = {
2449 .help = "create new tunnel",
2450 .next = NEXT(NEXT_ENTRY(COMMON_FILE_PATH)),
2451 .args = ARGS(ARGS_ENTRY(struct tunnel_ops, type)),
2452 .call = parse_tunnel,
2454 [TUNNEL_DESTROY] = {
2456 .help = "destroy tunnel",
2457 .next = NEXT(NEXT_ENTRY(TUNNEL_DESTROY_ID),
2458 NEXT_ENTRY(COMMON_PORT_ID)),
2459 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2460 .call = parse_tunnel,
2462 [TUNNEL_DESTROY_ID] = {
2464 .help = "tunnel identifier to destroy",
2465 .next = NEXT(NEXT_ENTRY(COMMON_UNSIGNED)),
2466 .args = ARGS(ARGS_ENTRY(struct tunnel_ops, id)),
2467 .call = parse_tunnel,
2471 .help = "list existing tunnels",
2472 .next = NEXT(NEXT_ENTRY(COMMON_PORT_ID)),
2473 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2474 .call = parse_tunnel,
2476 /* Destroy arguments. */
2479 .help = "specify a rule identifier",
2480 .next = NEXT(next_destroy_attr, NEXT_ENTRY(COMMON_RULE_ID)),
2481 .args = ARGS(ARGS_ENTRY_PTR(struct buffer, args.destroy.rule)),
2482 .call = parse_destroy,
2484 /* Dump arguments. */
2488 .next = NEXT(next_dump_attr),
2489 .args = ARGS(ARGS_ENTRY(struct buffer, args.dump.file)),
2494 .help = "dump one rule",
2495 .next = NEXT(next_dump_attr, NEXT_ENTRY(COMMON_RULE_ID)),
2496 .args = ARGS(ARGS_ENTRY(struct buffer, args.dump.file),
2497 ARGS_ENTRY(struct buffer, args.dump.rule)),
2500 /* Query arguments. */
2504 .help = "action to query, must be part of the rule",
2505 .call = parse_action,
2506 .comp = comp_action,
2508 /* List arguments. */
2511 .help = "specify a group",
2512 .next = NEXT(next_list_attr, NEXT_ENTRY(COMMON_GROUP_ID)),
2513 .args = ARGS(ARGS_ENTRY_PTR(struct buffer, args.list.group)),
2518 .help = "specify aged flows need be destroyed",
2522 /* Validate/create attributes. */
2525 .help = "specify a group",
2526 .next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_GROUP_ID)),
2527 .args = ARGS(ARGS_ENTRY(struct rte_flow_attr, group)),
2532 .help = "specify a priority level",
2533 .next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_PRIORITY_LEVEL)),
2534 .args = ARGS(ARGS_ENTRY(struct rte_flow_attr, priority)),
2539 .help = "affect rule to ingress",
2540 .next = NEXT(next_vc_attr),
2545 .help = "affect rule to egress",
2546 .next = NEXT(next_vc_attr),
2551 .help = "apply rule directly to endpoints found in pattern",
2552 .next = NEXT(next_vc_attr),
2556 .name = "tunnel_set",
2557 .help = "tunnel steer rule",
2558 .next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_UNSIGNED)),
2559 .args = ARGS(ARGS_ENTRY(struct tunnel_ops, id)),
2562 [VC_TUNNEL_MATCH] = {
2563 .name = "tunnel_match",
2564 .help = "tunnel match rule",
2565 .next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_UNSIGNED)),
2566 .args = ARGS(ARGS_ENTRY(struct tunnel_ops, id)),
2569 /* Validate/create pattern. */
2572 .help = "submit a list of pattern items",
2573 .next = NEXT(next_item),
2578 .help = "match value perfectly (with full bit-mask)",
2579 .call = parse_vc_spec,
2581 [ITEM_PARAM_SPEC] = {
2583 .help = "match value according to configured bit-mask",
2584 .call = parse_vc_spec,
2586 [ITEM_PARAM_LAST] = {
2588 .help = "specify upper bound to establish a range",
2589 .call = parse_vc_spec,
2591 [ITEM_PARAM_MASK] = {
2593 .help = "specify bit-mask with relevant bits set to one",
2594 .call = parse_vc_spec,
2596 [ITEM_PARAM_PREFIX] = {
2598 .help = "generate bit-mask from a prefix length",
2599 .call = parse_vc_spec,
2603 .help = "specify next pattern item",
2604 .next = NEXT(next_item),
2608 .help = "end list of pattern items",
2609 .priv = PRIV_ITEM(END, 0),
2610 .next = NEXT(NEXT_ENTRY(ACTIONS)),
2615 .help = "no-op pattern item",
2616 .priv = PRIV_ITEM(VOID, 0),
2617 .next = NEXT(NEXT_ENTRY(ITEM_NEXT)),
2622 .help = "perform actions when pattern does not match",
2623 .priv = PRIV_ITEM(INVERT, 0),
2624 .next = NEXT(NEXT_ENTRY(ITEM_NEXT)),
2629 .help = "match any protocol for the current layer",
2630 .priv = PRIV_ITEM(ANY, sizeof(struct rte_flow_item_any)),
2631 .next = NEXT(item_any),
2636 .help = "number of layers covered",
2637 .next = NEXT(item_any, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
2638 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_any, num)),
2642 .help = "match traffic from/to the physical function",
2643 .priv = PRIV_ITEM(PF, 0),
2644 .next = NEXT(NEXT_ENTRY(ITEM_NEXT)),
2649 .help = "match traffic from/to a virtual function ID",
2650 .priv = PRIV_ITEM(VF, sizeof(struct rte_flow_item_vf)),
2651 .next = NEXT(item_vf),
2657 .next = NEXT(item_vf, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
2658 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_vf, id)),
2662 .help = "match traffic from/to a specific physical port",
2663 .priv = PRIV_ITEM(PHY_PORT,
2664 sizeof(struct rte_flow_item_phy_port)),
2665 .next = NEXT(item_phy_port),
2668 [ITEM_PHY_PORT_INDEX] = {
2670 .help = "physical port index",
2671 .next = NEXT(item_phy_port, NEXT_ENTRY(COMMON_UNSIGNED),
2673 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_phy_port, index)),
2677 .help = "match traffic from/to a given DPDK port ID",
2678 .priv = PRIV_ITEM(PORT_ID,
2679 sizeof(struct rte_flow_item_port_id)),
2680 .next = NEXT(item_port_id),
2683 [ITEM_PORT_ID_ID] = {
2685 .help = "DPDK port ID",
2686 .next = NEXT(item_port_id, NEXT_ENTRY(COMMON_UNSIGNED),
2688 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_port_id, id)),
2692 .help = "match traffic against value set in previously matched rule",
2693 .priv = PRIV_ITEM(MARK, sizeof(struct rte_flow_item_mark)),
2694 .next = NEXT(item_mark),
2699 .help = "Integer value to match against",
2700 .next = NEXT(item_mark, NEXT_ENTRY(COMMON_UNSIGNED),
2702 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_mark, id)),
2706 .help = "match an arbitrary byte string",
2707 .priv = PRIV_ITEM(RAW, ITEM_RAW_SIZE),
2708 .next = NEXT(item_raw),
2711 [ITEM_RAW_RELATIVE] = {
2713 .help = "look for pattern after the previous item",
2714 .next = NEXT(item_raw, NEXT_ENTRY(COMMON_BOOLEAN), item_param),
2715 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_raw,
2718 [ITEM_RAW_SEARCH] = {
2720 .help = "search pattern from offset (see also limit)",
2721 .next = NEXT(item_raw, NEXT_ENTRY(COMMON_BOOLEAN), item_param),
2722 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_raw,
2725 [ITEM_RAW_OFFSET] = {
2727 .help = "absolute or relative offset for pattern",
2728 .next = NEXT(item_raw, NEXT_ENTRY(COMMON_INTEGER), item_param),
2729 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, offset)),
2731 [ITEM_RAW_LIMIT] = {
2733 .help = "search area limit for start of pattern",
2734 .next = NEXT(item_raw, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
2735 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, limit)),
2737 [ITEM_RAW_PATTERN] = {
2739 .help = "byte string to look for",
2740 .next = NEXT(item_raw,
2741 NEXT_ENTRY(COMMON_STRING),
2742 NEXT_ENTRY(ITEM_PARAM_IS,
2745 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, pattern),
2746 ARGS_ENTRY(struct rte_flow_item_raw, length),
2747 ARGS_ENTRY_ARB(sizeof(struct rte_flow_item_raw),
2748 ITEM_RAW_PATTERN_SIZE)),
2750 [ITEM_RAW_PATTERN_HEX] = {
2751 .name = "pattern_hex",
2752 .help = "hex string to look for",
2753 .next = NEXT(item_raw,
2754 NEXT_ENTRY(COMMON_HEX),
2755 NEXT_ENTRY(ITEM_PARAM_IS,
2758 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, pattern),
2759 ARGS_ENTRY(struct rte_flow_item_raw, length),
2760 ARGS_ENTRY_ARB(sizeof(struct rte_flow_item_raw),
2761 ITEM_RAW_PATTERN_SIZE)),
2765 .help = "match Ethernet header",
2766 .priv = PRIV_ITEM(ETH, sizeof(struct rte_flow_item_eth)),
2767 .next = NEXT(item_eth),
2772 .help = "destination MAC",
2773 .next = NEXT(item_eth, NEXT_ENTRY(COMMON_MAC_ADDR), item_param),
2774 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_eth, dst)),
2778 .help = "source MAC",
2779 .next = NEXT(item_eth, NEXT_ENTRY(COMMON_MAC_ADDR), item_param),
2780 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_eth, src)),
2784 .help = "EtherType",
2785 .next = NEXT(item_eth, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
2786 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_eth, type)),
2788 [ITEM_ETH_HAS_VLAN] = {
2790 .help = "packet header contains VLAN",
2791 .next = NEXT(item_eth, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
2792 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_eth,
2797 .help = "match 802.1Q/ad VLAN tag",
2798 .priv = PRIV_ITEM(VLAN, sizeof(struct rte_flow_item_vlan)),
2799 .next = NEXT(item_vlan),
2804 .help = "tag control information",
2805 .next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
2807 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vlan, tci)),
2811 .help = "priority code point",
2812 .next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
2814 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_vlan,
2819 .help = "drop eligible indicator",
2820 .next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
2822 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_vlan,
2827 .help = "VLAN identifier",
2828 .next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
2830 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_vlan,
2833 [ITEM_VLAN_INNER_TYPE] = {
2834 .name = "inner_type",
2835 .help = "inner EtherType",
2836 .next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
2838 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vlan,
2841 [ITEM_VLAN_HAS_MORE_VLAN] = {
2842 .name = "has_more_vlan",
2843 .help = "packet header contains another VLAN",
2844 .next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
2846 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_vlan,
2851 .help = "match IPv4 header",
2852 .priv = PRIV_ITEM(IPV4, sizeof(struct rte_flow_item_ipv4)),
2853 .next = NEXT(item_ipv4),
2856 [ITEM_IPV4_VER_IHL] = {
2857 .name = "version_ihl",
2858 .help = "match header length",
2859 .next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
2861 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_ipv4,
2866 .help = "type of service",
2867 .next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
2869 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
2870 hdr.type_of_service)),
2873 .name = "packet_id",
2874 .help = "fragment packet id",
2875 .next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
2877 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
2880 [ITEM_IPV4_FRAGMENT_OFFSET] = {
2881 .name = "fragment_offset",
2882 .help = "fragmentation flags and fragment offset",
2883 .next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
2885 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
2886 hdr.fragment_offset)),
2890 .help = "time to live",
2891 .next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
2893 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
2896 [ITEM_IPV4_PROTO] = {
2898 .help = "next protocol ID",
2899 .next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
2901 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
2902 hdr.next_proto_id)),
2906 .help = "source address",
2907 .next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_IPV4_ADDR),
2909 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
2914 .help = "destination address",
2915 .next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_IPV4_ADDR),
2917 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
2922 .help = "match IPv6 header",
2923 .priv = PRIV_ITEM(IPV6, sizeof(struct rte_flow_item_ipv6)),
2924 .next = NEXT(item_ipv6),
2929 .help = "traffic class",
2930 .next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED),
2932 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_ipv6,
2934 "\x0f\xf0\x00\x00")),
2936 [ITEM_IPV6_FLOW] = {
2938 .help = "flow label",
2939 .next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED),
2941 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_ipv6,
2943 "\x00\x0f\xff\xff")),
2945 [ITEM_IPV6_PROTO] = {
2947 .help = "protocol (next header)",
2948 .next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED),
2950 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
2955 .help = "hop limit",
2956 .next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED),
2958 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
2963 .help = "source address",
2964 .next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_IPV6_ADDR),
2966 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
2971 .help = "destination address",
2972 .next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_IPV6_ADDR),
2974 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
2977 [ITEM_IPV6_HAS_FRAG_EXT] = {
2978 .name = "has_frag_ext",
2979 .help = "fragment packet attribute",
2980 .next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED),
2982 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_ipv6,
2987 .help = "match ICMP header",
2988 .priv = PRIV_ITEM(ICMP, sizeof(struct rte_flow_item_icmp)),
2989 .next = NEXT(item_icmp),
2992 [ITEM_ICMP_TYPE] = {
2994 .help = "ICMP packet type",
2995 .next = NEXT(item_icmp, NEXT_ENTRY(COMMON_UNSIGNED),
2997 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp,
3000 [ITEM_ICMP_CODE] = {
3002 .help = "ICMP packet code",
3003 .next = NEXT(item_icmp, NEXT_ENTRY(COMMON_UNSIGNED),
3005 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp,
3008 [ITEM_ICMP_IDENT] = {
3010 .help = "ICMP packet identifier",
3011 .next = NEXT(item_icmp, NEXT_ENTRY(COMMON_UNSIGNED),
3013 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp,
3018 .help = "ICMP packet sequence number",
3019 .next = NEXT(item_icmp, NEXT_ENTRY(COMMON_UNSIGNED),
3021 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp,
3026 .help = "match UDP header",
3027 .priv = PRIV_ITEM(UDP, sizeof(struct rte_flow_item_udp)),
3028 .next = NEXT(item_udp),
3033 .help = "UDP source port",
3034 .next = NEXT(item_udp, NEXT_ENTRY(COMMON_UNSIGNED),
3036 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_udp,
3041 .help = "UDP destination port",
3042 .next = NEXT(item_udp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
3043 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_udp,
3048 .help = "match TCP header",
3049 .priv = PRIV_ITEM(TCP, sizeof(struct rte_flow_item_tcp)),
3050 .next = NEXT(item_tcp),
3055 .help = "TCP source port",
3056 .next = NEXT(item_tcp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
3057 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_tcp,
3062 .help = "TCP destination port",
3063 .next = NEXT(item_tcp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
3064 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_tcp,
3067 [ITEM_TCP_FLAGS] = {
3069 .help = "TCP flags",
3070 .next = NEXT(item_tcp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
3071 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_tcp,
3076 .help = "match SCTP header",
3077 .priv = PRIV_ITEM(SCTP, sizeof(struct rte_flow_item_sctp)),
3078 .next = NEXT(item_sctp),
3083 .help = "SCTP source port",
3084 .next = NEXT(item_sctp, NEXT_ENTRY(COMMON_UNSIGNED),
3086 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
3091 .help = "SCTP destination port",
3092 .next = NEXT(item_sctp, NEXT_ENTRY(COMMON_UNSIGNED),
3094 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
3099 .help = "validation tag",
3100 .next = NEXT(item_sctp, NEXT_ENTRY(COMMON_UNSIGNED),
3102 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
3105 [ITEM_SCTP_CKSUM] = {
3108 .next = NEXT(item_sctp, NEXT_ENTRY(COMMON_UNSIGNED),
3110 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
3115 .help = "match VXLAN header",
3116 .priv = PRIV_ITEM(VXLAN, sizeof(struct rte_flow_item_vxlan)),
3117 .next = NEXT(item_vxlan),
3120 [ITEM_VXLAN_VNI] = {
3122 .help = "VXLAN identifier",
3123 .next = NEXT(item_vxlan, NEXT_ENTRY(COMMON_UNSIGNED),
3125 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan, vni)),
3127 [ITEM_VXLAN_LAST_RSVD] = {
3128 .name = "last_rsvd",
3129 .help = "VXLAN last reserved bits",
3130 .next = NEXT(item_vxlan, NEXT_ENTRY(COMMON_UNSIGNED),
3132 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan,
3137 .help = "match E-Tag header",
3138 .priv = PRIV_ITEM(E_TAG, sizeof(struct rte_flow_item_e_tag)),
3139 .next = NEXT(item_e_tag),
3142 [ITEM_E_TAG_GRP_ECID_B] = {
3143 .name = "grp_ecid_b",
3144 .help = "GRP and E-CID base",
3145 .next = NEXT(item_e_tag, NEXT_ENTRY(COMMON_UNSIGNED),
3147 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_e_tag,
3153 .help = "match NVGRE header",
3154 .priv = PRIV_ITEM(NVGRE, sizeof(struct rte_flow_item_nvgre)),
3155 .next = NEXT(item_nvgre),
3158 [ITEM_NVGRE_TNI] = {
3160 .help = "virtual subnet ID",
3161 .next = NEXT(item_nvgre, NEXT_ENTRY(COMMON_UNSIGNED),
3163 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_nvgre, tni)),
3167 .help = "match MPLS header",
3168 .priv = PRIV_ITEM(MPLS, sizeof(struct rte_flow_item_mpls)),
3169 .next = NEXT(item_mpls),
3172 [ITEM_MPLS_LABEL] = {
3174 .help = "MPLS label",
3175 .next = NEXT(item_mpls, NEXT_ENTRY(COMMON_UNSIGNED),
3177 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_mpls,
3183 .help = "MPLS Traffic Class",
3184 .next = NEXT(item_mpls, NEXT_ENTRY(COMMON_UNSIGNED),
3186 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_mpls,
3192 .help = "MPLS Bottom-of-Stack",
3193 .next = NEXT(item_mpls, NEXT_ENTRY(COMMON_UNSIGNED),
3195 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_mpls,
3201 .help = "match GRE header",
3202 .priv = PRIV_ITEM(GRE, sizeof(struct rte_flow_item_gre)),
3203 .next = NEXT(item_gre),
3206 [ITEM_GRE_PROTO] = {
3208 .help = "GRE protocol type",
3209 .next = NEXT(item_gre, NEXT_ENTRY(COMMON_UNSIGNED),
3211 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre,
3214 [ITEM_GRE_C_RSVD0_VER] = {
3215 .name = "c_rsvd0_ver",
3217 "checksum (1b), undefined (1b), key bit (1b),"
3218 " sequence number (1b), reserved 0 (9b),"
3220 .next = NEXT(item_gre, NEXT_ENTRY(COMMON_UNSIGNED),
3222 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre,
3225 [ITEM_GRE_C_BIT] = {
3227 .help = "checksum bit (C)",
3228 .next = NEXT(item_gre, NEXT_ENTRY(COMMON_BOOLEAN),
3230 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_gre,
3232 "\x80\x00\x00\x00")),
3234 [ITEM_GRE_S_BIT] = {
3236 .help = "sequence number bit (S)",
3237 .next = NEXT(item_gre, NEXT_ENTRY(COMMON_BOOLEAN), item_param),
3238 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_gre,
3240 "\x10\x00\x00\x00")),
3242 [ITEM_GRE_K_BIT] = {
3244 .help = "key bit (K)",
3245 .next = NEXT(item_gre, NEXT_ENTRY(COMMON_BOOLEAN), item_param),
3246 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_gre,
3248 "\x20\x00\x00\x00")),
3252 .help = "fuzzy pattern match, expect faster than default",
3253 .priv = PRIV_ITEM(FUZZY,
3254 sizeof(struct rte_flow_item_fuzzy)),
3255 .next = NEXT(item_fuzzy),
3258 [ITEM_FUZZY_THRESH] = {
3260 .help = "match accuracy threshold",
3261 .next = NEXT(item_fuzzy, NEXT_ENTRY(COMMON_UNSIGNED),
3263 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_fuzzy,
3268 .help = "match GTP header",
3269 .priv = PRIV_ITEM(GTP, sizeof(struct rte_flow_item_gtp)),
3270 .next = NEXT(item_gtp),
3273 [ITEM_GTP_FLAGS] = {
3274 .name = "v_pt_rsv_flags",
3275 .help = "GTP flags",
3276 .next = NEXT(item_gtp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
3277 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_gtp,
3280 [ITEM_GTP_MSG_TYPE] = {
3282 .help = "GTP message type",
3283 .next = NEXT(item_gtp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
3284 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_gtp, msg_type)),
3288 .help = "tunnel endpoint identifier",
3289 .next = NEXT(item_gtp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
3290 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gtp, teid)),
3294 .help = "match GTP header",
3295 .priv = PRIV_ITEM(GTPC, sizeof(struct rte_flow_item_gtp)),
3296 .next = NEXT(item_gtp),
3301 .help = "match GTP header",
3302 .priv = PRIV_ITEM(GTPU, sizeof(struct rte_flow_item_gtp)),
3303 .next = NEXT(item_gtp),
3308 .help = "match GENEVE header",
3309 .priv = PRIV_ITEM(GENEVE, sizeof(struct rte_flow_item_geneve)),
3310 .next = NEXT(item_geneve),
3313 [ITEM_GENEVE_VNI] = {
3315 .help = "virtual network identifier",
3316 .next = NEXT(item_geneve, NEXT_ENTRY(COMMON_UNSIGNED),
3318 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_geneve, vni)),
3320 [ITEM_GENEVE_PROTO] = {
3322 .help = "GENEVE protocol type",
3323 .next = NEXT(item_geneve, NEXT_ENTRY(COMMON_UNSIGNED),
3325 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_geneve,
3328 [ITEM_GENEVE_OPTLEN] = {
3330 .help = "GENEVE options length in dwords",
3331 .next = NEXT(item_geneve, NEXT_ENTRY(COMMON_UNSIGNED),
3333 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_geneve,
3334 ver_opt_len_o_c_rsvd0,
3337 [ITEM_VXLAN_GPE] = {
3338 .name = "vxlan-gpe",
3339 .help = "match VXLAN-GPE header",
3340 .priv = PRIV_ITEM(VXLAN_GPE,
3341 sizeof(struct rte_flow_item_vxlan_gpe)),
3342 .next = NEXT(item_vxlan_gpe),
3345 [ITEM_VXLAN_GPE_VNI] = {
3347 .help = "VXLAN-GPE identifier",
3348 .next = NEXT(item_vxlan_gpe, NEXT_ENTRY(COMMON_UNSIGNED),
3350 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan_gpe,
3353 [ITEM_ARP_ETH_IPV4] = {
3354 .name = "arp_eth_ipv4",
3355 .help = "match ARP header for Ethernet/IPv4",
3356 .priv = PRIV_ITEM(ARP_ETH_IPV4,
3357 sizeof(struct rte_flow_item_arp_eth_ipv4)),
3358 .next = NEXT(item_arp_eth_ipv4),
3361 [ITEM_ARP_ETH_IPV4_SHA] = {
3363 .help = "sender hardware address",
3364 .next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(COMMON_MAC_ADDR),
3366 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4,
3369 [ITEM_ARP_ETH_IPV4_SPA] = {
3371 .help = "sender IPv4 address",
3372 .next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(COMMON_IPV4_ADDR),
3374 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4,
3377 [ITEM_ARP_ETH_IPV4_THA] = {
3379 .help = "target hardware address",
3380 .next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(COMMON_MAC_ADDR),
3382 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4,
3385 [ITEM_ARP_ETH_IPV4_TPA] = {
3387 .help = "target IPv4 address",
3388 .next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(COMMON_IPV4_ADDR),
3390 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4,
3395 .help = "match presence of any IPv6 extension header",
3396 .priv = PRIV_ITEM(IPV6_EXT,
3397 sizeof(struct rte_flow_item_ipv6_ext)),
3398 .next = NEXT(item_ipv6_ext),
3401 [ITEM_IPV6_EXT_NEXT_HDR] = {
3403 .help = "next header",
3404 .next = NEXT(item_ipv6_ext, NEXT_ENTRY(COMMON_UNSIGNED),
3406 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_ext,
3409 [ITEM_IPV6_FRAG_EXT] = {
3410 .name = "ipv6_frag_ext",
3411 .help = "match presence of IPv6 fragment extension header",
3412 .priv = PRIV_ITEM(IPV6_FRAG_EXT,
3413 sizeof(struct rte_flow_item_ipv6_frag_ext)),
3414 .next = NEXT(item_ipv6_frag_ext),
3417 [ITEM_IPV6_FRAG_EXT_NEXT_HDR] = {
3419 .help = "next header",
3420 .next = NEXT(item_ipv6_frag_ext, NEXT_ENTRY(COMMON_UNSIGNED),
3422 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_ipv6_frag_ext,
3425 [ITEM_IPV6_FRAG_EXT_FRAG_DATA] = {
3426 .name = "frag_data",
3427 .help = "fragment flags and offset",
3428 .next = NEXT(item_ipv6_frag_ext, NEXT_ENTRY(COMMON_UNSIGNED),
3430 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_frag_ext,
3433 [ITEM_IPV6_FRAG_EXT_ID] = {
3434 .name = "packet_id",
3435 .help = "fragment packet id",
3436 .next = NEXT(item_ipv6_frag_ext, NEXT_ENTRY(COMMON_UNSIGNED),
3438 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_frag_ext,
3443 .help = "match any ICMPv6 header",
3444 .priv = PRIV_ITEM(ICMP6, sizeof(struct rte_flow_item_icmp6)),
3445 .next = NEXT(item_icmp6),
3448 [ITEM_ICMP6_TYPE] = {
3450 .help = "ICMPv6 type",
3451 .next = NEXT(item_icmp6, NEXT_ENTRY(COMMON_UNSIGNED),
3453 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6,
3456 [ITEM_ICMP6_CODE] = {
3458 .help = "ICMPv6 code",
3459 .next = NEXT(item_icmp6, NEXT_ENTRY(COMMON_UNSIGNED),
3461 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6,
3464 [ITEM_ICMP6_ND_NS] = {
3465 .name = "icmp6_nd_ns",
3466 .help = "match ICMPv6 neighbor discovery solicitation",
3467 .priv = PRIV_ITEM(ICMP6_ND_NS,
3468 sizeof(struct rte_flow_item_icmp6_nd_ns)),
3469 .next = NEXT(item_icmp6_nd_ns),
3472 [ITEM_ICMP6_ND_NS_TARGET_ADDR] = {
3473 .name = "target_addr",
3474 .help = "target address",
3475 .next = NEXT(item_icmp6_nd_ns, NEXT_ENTRY(COMMON_IPV6_ADDR),
3477 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_nd_ns,
3480 [ITEM_ICMP6_ND_NA] = {
3481 .name = "icmp6_nd_na",
3482 .help = "match ICMPv6 neighbor discovery advertisement",
3483 .priv = PRIV_ITEM(ICMP6_ND_NA,
3484 sizeof(struct rte_flow_item_icmp6_nd_na)),
3485 .next = NEXT(item_icmp6_nd_na),
3488 [ITEM_ICMP6_ND_NA_TARGET_ADDR] = {
3489 .name = "target_addr",
3490 .help = "target address",
3491 .next = NEXT(item_icmp6_nd_na, NEXT_ENTRY(COMMON_IPV6_ADDR),
3493 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_nd_na,
3496 [ITEM_ICMP6_ND_OPT] = {
3497 .name = "icmp6_nd_opt",
3498 .help = "match presence of any ICMPv6 neighbor discovery"
3500 .priv = PRIV_ITEM(ICMP6_ND_OPT,
3501 sizeof(struct rte_flow_item_icmp6_nd_opt)),
3502 .next = NEXT(item_icmp6_nd_opt),
3505 [ITEM_ICMP6_ND_OPT_TYPE] = {
3507 .help = "ND option type",
3508 .next = NEXT(item_icmp6_nd_opt, NEXT_ENTRY(COMMON_UNSIGNED),
3510 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_nd_opt,
3513 [ITEM_ICMP6_ND_OPT_SLA_ETH] = {
3514 .name = "icmp6_nd_opt_sla_eth",
3515 .help = "match ICMPv6 neighbor discovery source Ethernet"
3516 " link-layer address option",
3518 (ICMP6_ND_OPT_SLA_ETH,
3519 sizeof(struct rte_flow_item_icmp6_nd_opt_sla_eth)),
3520 .next = NEXT(item_icmp6_nd_opt_sla_eth),
3523 [ITEM_ICMP6_ND_OPT_SLA_ETH_SLA] = {
3525 .help = "source Ethernet LLA",
3526 .next = NEXT(item_icmp6_nd_opt_sla_eth,
3527 NEXT_ENTRY(COMMON_MAC_ADDR), item_param),
3528 .args = ARGS(ARGS_ENTRY_HTON
3529 (struct rte_flow_item_icmp6_nd_opt_sla_eth, sla)),
3531 [ITEM_ICMP6_ND_OPT_TLA_ETH] = {
3532 .name = "icmp6_nd_opt_tla_eth",
3533 .help = "match ICMPv6 neighbor discovery target Ethernet"
3534 " link-layer address option",
3536 (ICMP6_ND_OPT_TLA_ETH,
3537 sizeof(struct rte_flow_item_icmp6_nd_opt_tla_eth)),
3538 .next = NEXT(item_icmp6_nd_opt_tla_eth),
3541 [ITEM_ICMP6_ND_OPT_TLA_ETH_TLA] = {
3543 .help = "target Ethernet LLA",
3544 .next = NEXT(item_icmp6_nd_opt_tla_eth,
3545 NEXT_ENTRY(COMMON_MAC_ADDR), item_param),
3546 .args = ARGS(ARGS_ENTRY_HTON
3547 (struct rte_flow_item_icmp6_nd_opt_tla_eth, tla)),
3551 .help = "match metadata header",
3552 .priv = PRIV_ITEM(META, sizeof(struct rte_flow_item_meta)),
3553 .next = NEXT(item_meta),
3556 [ITEM_META_DATA] = {
3558 .help = "metadata value",
3559 .next = NEXT(item_meta, NEXT_ENTRY(COMMON_UNSIGNED),
3561 .args = ARGS(ARGS_ENTRY_MASK(struct rte_flow_item_meta,
3562 data, "\xff\xff\xff\xff")),
3566 .help = "match GRE key",
3567 .priv = PRIV_ITEM(GRE_KEY, sizeof(rte_be32_t)),
3568 .next = NEXT(item_gre_key),
3571 [ITEM_GRE_KEY_VALUE] = {
3573 .help = "key value",
3574 .next = NEXT(item_gre_key, NEXT_ENTRY(COMMON_UNSIGNED),
3576 .args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
3578 [ITEM_GRE_OPTION] = {
3579 .name = "gre_option",
3580 .help = "match GRE optional fields",
3581 .priv = PRIV_ITEM(GRE_OPTION,
3582 sizeof(struct rte_flow_item_gre_opt)),
3583 .next = NEXT(item_gre_option),
3586 [ITEM_GRE_OPTION_CHECKSUM] = {
3588 .help = "match GRE checksum",
3589 .next = NEXT(item_gre_option, NEXT_ENTRY(COMMON_UNSIGNED),
3591 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre_opt,
3592 checksum_rsvd.checksum)),
3594 [ITEM_GRE_OPTION_KEY] = {
3596 .help = "match GRE key",
3597 .next = NEXT(item_gre_option, NEXT_ENTRY(COMMON_UNSIGNED),
3599 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre_opt,
3602 [ITEM_GRE_OPTION_SEQUENCE] = {
3604 .help = "match GRE sequence",
3605 .next = NEXT(item_gre_option, NEXT_ENTRY(COMMON_UNSIGNED),
3607 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre_opt,
3608 sequence.sequence)),
3612 .help = "match GTP extension header with type 0x85",
3613 .priv = PRIV_ITEM(GTP_PSC,
3614 sizeof(struct rte_flow_item_gtp_psc)),
3615 .next = NEXT(item_gtp_psc),
3618 [ITEM_GTP_PSC_QFI] = {
3620 .help = "QoS flow identifier",
3621 .next = NEXT(item_gtp_psc, NEXT_ENTRY(COMMON_UNSIGNED),
3623 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_gtp_psc,
3626 [ITEM_GTP_PSC_PDU_T] = {
3629 .next = NEXT(item_gtp_psc, NEXT_ENTRY(COMMON_UNSIGNED),
3631 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_gtp_psc,
3636 .help = "match PPPoE session header",
3637 .priv = PRIV_ITEM(PPPOES, sizeof(struct rte_flow_item_pppoe)),
3638 .next = NEXT(item_pppoes),
3643 .help = "match PPPoE discovery header",
3644 .priv = PRIV_ITEM(PPPOED, sizeof(struct rte_flow_item_pppoe)),
3645 .next = NEXT(item_pppoed),
3648 [ITEM_PPPOE_SEID] = {
3650 .help = "session identifier",
3651 .next = NEXT(item_pppoes, NEXT_ENTRY(COMMON_UNSIGNED),
3653 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_pppoe,
3656 [ITEM_PPPOE_PROTO_ID] = {
3657 .name = "pppoe_proto_id",
3658 .help = "match PPPoE session protocol identifier",
3659 .priv = PRIV_ITEM(PPPOE_PROTO_ID,
3660 sizeof(struct rte_flow_item_pppoe_proto_id)),
3661 .next = NEXT(item_pppoe_proto_id, NEXT_ENTRY(COMMON_UNSIGNED),
3663 .args = ARGS(ARGS_ENTRY_HTON
3664 (struct rte_flow_item_pppoe_proto_id, proto_id)),
3669 .help = "matches higig2 header",
3670 .priv = PRIV_ITEM(HIGIG2,
3671 sizeof(struct rte_flow_item_higig2_hdr)),
3672 .next = NEXT(item_higig2),
3675 [ITEM_HIGIG2_CLASSIFICATION] = {
3676 .name = "classification",
3677 .help = "matches classification of higig2 header",
3678 .next = NEXT(item_higig2, NEXT_ENTRY(COMMON_UNSIGNED),
3680 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_higig2_hdr,
3681 hdr.ppt1.classification)),
3683 [ITEM_HIGIG2_VID] = {
3685 .help = "matches vid of higig2 header",
3686 .next = NEXT(item_higig2, NEXT_ENTRY(COMMON_UNSIGNED),
3688 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_higig2_hdr,
3693 .help = "match tag value",
3694 .priv = PRIV_ITEM(TAG, sizeof(struct rte_flow_item_tag)),
3695 .next = NEXT(item_tag),
3700 .help = "tag value to match",
3701 .next = NEXT(item_tag, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
3702 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_tag, data)),
3704 [ITEM_TAG_INDEX] = {
3706 .help = "index of tag array to match",
3707 .next = NEXT(item_tag, NEXT_ENTRY(COMMON_UNSIGNED),
3708 NEXT_ENTRY(ITEM_PARAM_IS)),
3709 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_tag, index)),
3711 [ITEM_L2TPV3OIP] = {
3712 .name = "l2tpv3oip",
3713 .help = "match L2TPv3 over IP header",
3714 .priv = PRIV_ITEM(L2TPV3OIP,
3715 sizeof(struct rte_flow_item_l2tpv3oip)),
3716 .next = NEXT(item_l2tpv3oip),
3719 [ITEM_L2TPV3OIP_SESSION_ID] = {
3720 .name = "session_id",
3721 .help = "session identifier",
3722 .next = NEXT(item_l2tpv3oip, NEXT_ENTRY(COMMON_UNSIGNED),
3724 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv3oip,
3729 .help = "match ESP header",
3730 .priv = PRIV_ITEM(ESP, sizeof(struct rte_flow_item_esp)),
3731 .next = NEXT(item_esp),
3736 .help = "security policy index",
3737 .next = NEXT(item_esp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
3738 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_esp,
3743 .help = "match AH header",
3744 .priv = PRIV_ITEM(AH, sizeof(struct rte_flow_item_ah)),
3745 .next = NEXT(item_ah),
3750 .help = "security parameters index",
3751 .next = NEXT(item_ah, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
3752 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ah, spi)),
3756 .help = "match pfcp header",
3757 .priv = PRIV_ITEM(PFCP, sizeof(struct rte_flow_item_pfcp)),
3758 .next = NEXT(item_pfcp),
3761 [ITEM_PFCP_S_FIELD] = {
3764 .next = NEXT(item_pfcp, NEXT_ENTRY(COMMON_UNSIGNED),
3766 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_pfcp,
3769 [ITEM_PFCP_SEID] = {
3771 .help = "session endpoint identifier",
3772 .next = NEXT(item_pfcp, NEXT_ENTRY(COMMON_UNSIGNED),
3774 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_pfcp, seid)),
3778 .help = "match eCPRI header",
3779 .priv = PRIV_ITEM(ECPRI, sizeof(struct rte_flow_item_ecpri)),
3780 .next = NEXT(item_ecpri),
3783 [ITEM_ECPRI_COMMON] = {
3785 .help = "eCPRI common header",
3786 .next = NEXT(item_ecpri_common),
3788 [ITEM_ECPRI_COMMON_TYPE] = {
3790 .help = "type of common header",
3791 .next = NEXT(item_ecpri_common_type),
3792 .args = ARGS(ARG_ENTRY_HTON(struct rte_flow_item_ecpri)),
3794 [ITEM_ECPRI_COMMON_TYPE_IQ_DATA] = {
3796 .help = "Type #0: IQ Data",
3797 .next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_IQ_DATA_PCID,
3799 .call = parse_vc_item_ecpri_type,
3801 [ITEM_ECPRI_MSG_IQ_DATA_PCID] = {
3803 .help = "Physical Channel ID",
3804 .next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_IQ_DATA_PCID,
3805 ITEM_ECPRI_COMMON, ITEM_NEXT),
3806 NEXT_ENTRY(COMMON_UNSIGNED), item_param),
3807 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ecpri,
3810 [ITEM_ECPRI_COMMON_TYPE_RTC_CTRL] = {
3812 .help = "Type #2: Real-Time Control Data",
3813 .next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_RTC_CTRL_RTCID,
3815 .call = parse_vc_item_ecpri_type,
3817 [ITEM_ECPRI_MSG_RTC_CTRL_RTCID] = {
3819 .help = "Real-Time Control Data ID",
3820 .next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_RTC_CTRL_RTCID,
3821 ITEM_ECPRI_COMMON, ITEM_NEXT),
3822 NEXT_ENTRY(COMMON_UNSIGNED), item_param),
3823 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ecpri,
3826 [ITEM_ECPRI_COMMON_TYPE_DLY_MSR] = {
3827 .name = "delay_measure",
3828 .help = "Type #5: One-Way Delay Measurement",
3829 .next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_DLY_MSR_MSRID,
3831 .call = parse_vc_item_ecpri_type,
3833 [ITEM_ECPRI_MSG_DLY_MSR_MSRID] = {
3835 .help = "Measurement ID",
3836 .next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_DLY_MSR_MSRID,
3837 ITEM_ECPRI_COMMON, ITEM_NEXT),
3838 NEXT_ENTRY(COMMON_UNSIGNED), item_param),
3839 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ecpri,
3842 [ITEM_GENEVE_OPT] = {
3843 .name = "geneve-opt",
3844 .help = "GENEVE header option",
3845 .priv = PRIV_ITEM(GENEVE_OPT,
3846 sizeof(struct rte_flow_item_geneve_opt) +
3847 ITEM_GENEVE_OPT_DATA_SIZE),
3848 .next = NEXT(item_geneve_opt),
3851 [ITEM_GENEVE_OPT_CLASS] = {
3853 .help = "GENEVE option class",
3854 .next = NEXT(item_geneve_opt, NEXT_ENTRY(COMMON_UNSIGNED),
3856 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_geneve_opt,
3859 [ITEM_GENEVE_OPT_TYPE] = {
3861 .help = "GENEVE option type",
3862 .next = NEXT(item_geneve_opt, NEXT_ENTRY(COMMON_UNSIGNED),
3864 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_geneve_opt,
3867 [ITEM_GENEVE_OPT_LENGTH] = {
3869 .help = "GENEVE option data length (in 32b words)",
3870 .next = NEXT(item_geneve_opt, NEXT_ENTRY(COMMON_UNSIGNED),
3872 .args = ARGS(ARGS_ENTRY_BOUNDED(
3873 struct rte_flow_item_geneve_opt, option_len,
3876 [ITEM_GENEVE_OPT_DATA] = {
3878 .help = "GENEVE option data pattern",
3879 .next = NEXT(item_geneve_opt, NEXT_ENTRY(COMMON_HEX),
3881 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_geneve_opt, data),
3882 ARGS_ENTRY_ARB(0, 0),
3884 (sizeof(struct rte_flow_item_geneve_opt),
3885 ITEM_GENEVE_OPT_DATA_SIZE)),
3887 [ITEM_INTEGRITY] = {
3888 .name = "integrity",
3889 .help = "match packet integrity",
3890 .priv = PRIV_ITEM(INTEGRITY,
3891 sizeof(struct rte_flow_item_integrity)),
3892 .next = NEXT(item_integrity),
3895 [ITEM_INTEGRITY_LEVEL] = {
3897 .help = "integrity level",
3898 .next = NEXT(item_integrity_lv, NEXT_ENTRY(COMMON_UNSIGNED),
3900 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_integrity, level)),
3902 [ITEM_INTEGRITY_VALUE] = {
3904 .help = "integrity value",
3905 .next = NEXT(item_integrity_lv, NEXT_ENTRY(COMMON_UNSIGNED),
3907 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_integrity, value)),
3909 [ITEM_CONNTRACK] = {
3910 .name = "conntrack",
3911 .help = "conntrack state",
3912 .next = NEXT(NEXT_ENTRY(ITEM_NEXT), NEXT_ENTRY(COMMON_UNSIGNED),
3914 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_conntrack, flags)),
3916 [ITEM_PORT_REPRESENTOR] = {
3917 .name = "port_representor",
3918 .help = "match traffic entering the embedded switch from the given ethdev",
3919 .priv = PRIV_ITEM(PORT_REPRESENTOR,
3920 sizeof(struct rte_flow_item_ethdev)),
3921 .next = NEXT(item_port_representor),
3924 [ITEM_PORT_REPRESENTOR_PORT_ID] = {
3926 .help = "ethdev port ID",
3927 .next = NEXT(item_port_representor, NEXT_ENTRY(COMMON_UNSIGNED),
3929 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_ethdev, port_id)),
3931 [ITEM_REPRESENTED_PORT] = {
3932 .name = "represented_port",
3933 .help = "match traffic entering the embedded switch from the entity represented by the given ethdev",
3934 .priv = PRIV_ITEM(REPRESENTED_PORT,
3935 sizeof(struct rte_flow_item_ethdev)),
3936 .next = NEXT(item_represented_port),
3939 [ITEM_REPRESENTED_PORT_ETHDEV_PORT_ID] = {
3940 .name = "ethdev_port_id",
3941 .help = "ethdev port ID",
3942 .next = NEXT(item_represented_port, NEXT_ENTRY(COMMON_UNSIGNED),
3944 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_ethdev, port_id)),
3948 .help = "match flex header",
3949 .priv = PRIV_ITEM(FLEX, sizeof(struct rte_flow_item_flex)),
3950 .next = NEXT(item_flex),
3953 [ITEM_FLEX_ITEM_HANDLE] = {
3955 .help = "flex item handle",
3956 .next = NEXT(item_flex, NEXT_ENTRY(COMMON_FLEX_HANDLE),
3957 NEXT_ENTRY(ITEM_PARAM_IS)),
3958 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_flex, handle)),
3960 [ITEM_FLEX_PATTERN_HANDLE] = {
3962 .help = "flex pattern handle",
3963 .next = NEXT(item_flex, NEXT_ENTRY(COMMON_FLEX_HANDLE),
3964 NEXT_ENTRY(ITEM_PARAM_IS)),
3965 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_flex, pattern)),
3969 .help = "match L2TPv2 header",
3970 .priv = PRIV_ITEM(L2TPV2, sizeof(struct rte_flow_item_l2tpv2)),
3971 .next = NEXT(item_l2tpv2),
3974 [ITEM_L2TPV2_TYPE] = {
3976 .help = "type of l2tpv2",
3977 .next = NEXT(item_l2tpv2_type),
3978 .args = ARGS(ARG_ENTRY_HTON(struct rte_flow_item_l2tpv2)),
3980 [ITEM_L2TPV2_TYPE_DATA] = {
3982 .help = "Type #7: data message without any options",
3983 .next = NEXT(item_l2tpv2_type_data),
3984 .call = parse_vc_item_l2tpv2_type,
3986 [ITEM_L2TPV2_MSG_DATA_TUNNEL_ID] = {
3987 .name = "tunnel_id",
3988 .help = "tunnel identifier",
3989 .next = NEXT(item_l2tpv2_type_data,
3990 NEXT_ENTRY(COMMON_UNSIGNED),
3992 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
3993 hdr.type7.tunnel_id)),
3995 [ITEM_L2TPV2_MSG_DATA_SESSION_ID] = {
3996 .name = "session_id",
3997 .help = "session identifier",
3998 .next = NEXT(item_l2tpv2_type_data,
3999 NEXT_ENTRY(COMMON_UNSIGNED),
4001 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4002 hdr.type7.session_id)),
4004 [ITEM_L2TPV2_TYPE_DATA_L] = {
4006 .help = "Type #6: data message with length option",
4007 .next = NEXT(item_l2tpv2_type_data_l),
4008 .call = parse_vc_item_l2tpv2_type,
4010 [ITEM_L2TPV2_MSG_DATA_L_LENGTH] = {
4012 .help = "message length",
4013 .next = NEXT(item_l2tpv2_type_data_l,
4014 NEXT_ENTRY(COMMON_UNSIGNED),
4016 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4019 [ITEM_L2TPV2_MSG_DATA_L_TUNNEL_ID] = {
4020 .name = "tunnel_id",
4021 .help = "tunnel identifier",
4022 .next = NEXT(item_l2tpv2_type_data_l,
4023 NEXT_ENTRY(COMMON_UNSIGNED),
4025 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4026 hdr.type6.tunnel_id)),
4028 [ITEM_L2TPV2_MSG_DATA_L_SESSION_ID] = {
4029 .name = "session_id",
4030 .help = "session identifier",
4031 .next = NEXT(item_l2tpv2_type_data_l,
4032 NEXT_ENTRY(COMMON_UNSIGNED),
4034 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4035 hdr.type6.session_id)),
4037 [ITEM_L2TPV2_TYPE_DATA_S] = {
4039 .help = "Type #5: data message with ns, nr option",
4040 .next = NEXT(item_l2tpv2_type_data_s),
4041 .call = parse_vc_item_l2tpv2_type,
4043 [ITEM_L2TPV2_MSG_DATA_S_TUNNEL_ID] = {
4044 .name = "tunnel_id",
4045 .help = "tunnel identifier",
4046 .next = NEXT(item_l2tpv2_type_data_s,
4047 NEXT_ENTRY(COMMON_UNSIGNED),
4049 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4050 hdr.type5.tunnel_id)),
4052 [ITEM_L2TPV2_MSG_DATA_S_SESSION_ID] = {
4053 .name = "session_id",
4054 .help = "session identifier",
4055 .next = NEXT(item_l2tpv2_type_data_s,
4056 NEXT_ENTRY(COMMON_UNSIGNED),
4058 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4059 hdr.type5.session_id)),
4061 [ITEM_L2TPV2_MSG_DATA_S_NS] = {
4063 .help = "sequence number for message",
4064 .next = NEXT(item_l2tpv2_type_data_s,
4065 NEXT_ENTRY(COMMON_UNSIGNED),
4067 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4070 [ITEM_L2TPV2_MSG_DATA_S_NR] = {
4072 .help = "sequence number for next receive message",
4073 .next = NEXT(item_l2tpv2_type_data_s,
4074 NEXT_ENTRY(COMMON_UNSIGNED),
4076 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4079 [ITEM_L2TPV2_TYPE_DATA_O] = {
4081 .help = "Type #4: data message with offset option",
4082 .next = NEXT(item_l2tpv2_type_data_o),
4083 .call = parse_vc_item_l2tpv2_type,
4085 [ITEM_L2TPV2_MSG_DATA_O_TUNNEL_ID] = {
4086 .name = "tunnel_id",
4087 .help = "tunnel identifier",
4088 .next = NEXT(item_l2tpv2_type_data_o,
4089 NEXT_ENTRY(COMMON_UNSIGNED),
4091 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4092 hdr.type4.tunnel_id)),
4094 [ITEM_L2TPV2_MSG_DATA_O_SESSION_ID] = {
4095 .name = "session_id",
4096 .help = "session identifier",
4097 .next = NEXT(item_l2tpv2_type_data_o,
4098 NEXT_ENTRY(COMMON_UNSIGNED),
4100 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4101 hdr.type5.session_id)),
4103 [ITEM_L2TPV2_MSG_DATA_O_OFFSET] = {
4104 .name = "offset_size",
4105 .help = "the size of offset padding",
4106 .next = NEXT(item_l2tpv2_type_data_o,
4107 NEXT_ENTRY(COMMON_UNSIGNED),
4109 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4110 hdr.type4.offset_size)),
4112 [ITEM_L2TPV2_TYPE_DATA_L_S] = {
4114 .help = "Type #3: data message contains length, ns, nr "
4116 .next = NEXT(item_l2tpv2_type_data_l_s),
4117 .call = parse_vc_item_l2tpv2_type,
4119 [ITEM_L2TPV2_MSG_DATA_L_S_LENGTH] = {
4121 .help = "message length",
4122 .next = NEXT(item_l2tpv2_type_data_l_s,
4123 NEXT_ENTRY(COMMON_UNSIGNED),
4125 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4128 [ITEM_L2TPV2_MSG_DATA_L_S_TUNNEL_ID] = {
4129 .name = "tunnel_id",
4130 .help = "tunnel identifier",
4131 .next = NEXT(item_l2tpv2_type_data_l_s,
4132 NEXT_ENTRY(COMMON_UNSIGNED),
4134 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4135 hdr.type3.tunnel_id)),
4137 [ITEM_L2TPV2_MSG_DATA_L_S_SESSION_ID] = {
4138 .name = "session_id",
4139 .help = "session identifier",
4140 .next = NEXT(item_l2tpv2_type_data_l_s,
4141 NEXT_ENTRY(COMMON_UNSIGNED),
4143 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4144 hdr.type3.session_id)),
4146 [ITEM_L2TPV2_MSG_DATA_L_S_NS] = {
4148 .help = "sequence number for message",
4149 .next = NEXT(item_l2tpv2_type_data_l_s,
4150 NEXT_ENTRY(COMMON_UNSIGNED),
4152 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4155 [ITEM_L2TPV2_MSG_DATA_L_S_NR] = {
4157 .help = "sequence number for next receive message",
4158 .next = NEXT(item_l2tpv2_type_data_l_s,
4159 NEXT_ENTRY(COMMON_UNSIGNED),
4161 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4164 [ITEM_L2TPV2_TYPE_CTRL] = {
4166 .help = "Type #3: conrtol message contains length, ns, nr "
4168 .next = NEXT(item_l2tpv2_type_ctrl),
4169 .call = parse_vc_item_l2tpv2_type,
4171 [ITEM_L2TPV2_MSG_CTRL_LENGTH] = {
4173 .help = "message length",
4174 .next = NEXT(item_l2tpv2_type_ctrl,
4175 NEXT_ENTRY(COMMON_UNSIGNED),
4177 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4180 [ITEM_L2TPV2_MSG_CTRL_TUNNEL_ID] = {
4181 .name = "tunnel_id",
4182 .help = "tunnel identifier",
4183 .next = NEXT(item_l2tpv2_type_ctrl,
4184 NEXT_ENTRY(COMMON_UNSIGNED),
4186 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4187 hdr.type3.tunnel_id)),
4189 [ITEM_L2TPV2_MSG_CTRL_SESSION_ID] = {
4190 .name = "session_id",
4191 .help = "session identifier",
4192 .next = NEXT(item_l2tpv2_type_ctrl,
4193 NEXT_ENTRY(COMMON_UNSIGNED),
4195 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4196 hdr.type3.session_id)),
4198 [ITEM_L2TPV2_MSG_CTRL_NS] = {
4200 .help = "sequence number for message",
4201 .next = NEXT(item_l2tpv2_type_ctrl,
4202 NEXT_ENTRY(COMMON_UNSIGNED),
4204 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4207 [ITEM_L2TPV2_MSG_CTRL_NR] = {
4209 .help = "sequence number for next receive message",
4210 .next = NEXT(item_l2tpv2_type_ctrl,
4211 NEXT_ENTRY(COMMON_UNSIGNED),
4213 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4218 .help = "match PPP header",
4219 .priv = PRIV_ITEM(PPP, sizeof(struct rte_flow_item_ppp)),
4220 .next = NEXT(item_ppp),
4225 .help = "PPP address",
4226 .next = NEXT(item_ppp, NEXT_ENTRY(COMMON_UNSIGNED),
4228 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_ppp, hdr.addr)),
4232 .help = "PPP control",
4233 .next = NEXT(item_ppp, NEXT_ENTRY(COMMON_UNSIGNED),
4235 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_ppp, hdr.ctrl)),
4237 [ITEM_PPP_PROTO_ID] = {
4239 .help = "PPP protocol identifier",
4240 .next = NEXT(item_ppp, NEXT_ENTRY(COMMON_UNSIGNED),
4242 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_ppp,
4245 /* Validate/create actions. */
4248 .help = "submit a list of associated actions",
4249 .next = NEXT(next_action),
4254 .help = "specify next action",
4255 .next = NEXT(next_action),
4259 .help = "end list of actions",
4260 .priv = PRIV_ACTION(END, 0),
4265 .help = "no-op action",
4266 .priv = PRIV_ACTION(VOID, 0),
4267 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4270 [ACTION_PASSTHRU] = {
4272 .help = "let subsequent rule process matched packets",
4273 .priv = PRIV_ACTION(PASSTHRU, 0),
4274 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4279 .help = "redirect traffic to a given group",
4280 .priv = PRIV_ACTION(JUMP, sizeof(struct rte_flow_action_jump)),
4281 .next = NEXT(action_jump),
4284 [ACTION_JUMP_GROUP] = {
4286 .help = "group to redirect traffic to",
4287 .next = NEXT(action_jump, NEXT_ENTRY(COMMON_UNSIGNED)),
4288 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_jump, group)),
4289 .call = parse_vc_conf,
4293 .help = "attach 32 bit value to packets",
4294 .priv = PRIV_ACTION(MARK, sizeof(struct rte_flow_action_mark)),
4295 .next = NEXT(action_mark),
4298 [ACTION_MARK_ID] = {
4300 .help = "32 bit value to return with packets",
4301 .next = NEXT(action_mark, NEXT_ENTRY(COMMON_UNSIGNED)),
4302 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_mark, id)),
4303 .call = parse_vc_conf,
4307 .help = "flag packets",
4308 .priv = PRIV_ACTION(FLAG, 0),
4309 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4314 .help = "assign packets to a given queue index",
4315 .priv = PRIV_ACTION(QUEUE,
4316 sizeof(struct rte_flow_action_queue)),
4317 .next = NEXT(action_queue),
4320 [ACTION_QUEUE_INDEX] = {
4322 .help = "queue index to use",
4323 .next = NEXT(action_queue, NEXT_ENTRY(COMMON_UNSIGNED)),
4324 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_queue, index)),
4325 .call = parse_vc_conf,
4329 .help = "drop packets (note: passthru has priority)",
4330 .priv = PRIV_ACTION(DROP, 0),
4331 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4336 .help = "enable counters for this rule",
4337 .priv = PRIV_ACTION(COUNT,
4338 sizeof(struct rte_flow_action_count)),
4339 .next = NEXT(action_count),
4342 [ACTION_COUNT_ID] = {
4343 .name = "identifier",
4344 .help = "counter identifier to use",
4345 .next = NEXT(action_count, NEXT_ENTRY(COMMON_UNSIGNED)),
4346 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_count, id)),
4347 .call = parse_vc_conf,
4351 .help = "spread packets among several queues",
4352 .priv = PRIV_ACTION(RSS, sizeof(struct action_rss_data)),
4353 .next = NEXT(action_rss),
4354 .call = parse_vc_action_rss,
4356 [ACTION_RSS_FUNC] = {
4358 .help = "RSS hash function to apply",
4359 .next = NEXT(action_rss,
4360 NEXT_ENTRY(ACTION_RSS_FUNC_DEFAULT,
4361 ACTION_RSS_FUNC_TOEPLITZ,
4362 ACTION_RSS_FUNC_SIMPLE_XOR,
4363 ACTION_RSS_FUNC_SYMMETRIC_TOEPLITZ)),
4365 [ACTION_RSS_FUNC_DEFAULT] = {
4367 .help = "default hash function",
4368 .call = parse_vc_action_rss_func,
4370 [ACTION_RSS_FUNC_TOEPLITZ] = {
4372 .help = "Toeplitz hash function",
4373 .call = parse_vc_action_rss_func,
4375 [ACTION_RSS_FUNC_SIMPLE_XOR] = {
4376 .name = "simple_xor",
4377 .help = "simple XOR hash function",
4378 .call = parse_vc_action_rss_func,
4380 [ACTION_RSS_FUNC_SYMMETRIC_TOEPLITZ] = {
4381 .name = "symmetric_toeplitz",
4382 .help = "Symmetric Toeplitz hash function",
4383 .call = parse_vc_action_rss_func,
4385 [ACTION_RSS_LEVEL] = {
4387 .help = "encapsulation level for \"types\"",
4388 .next = NEXT(action_rss, NEXT_ENTRY(COMMON_UNSIGNED)),
4389 .args = ARGS(ARGS_ENTRY_ARB
4390 (offsetof(struct action_rss_data, conf) +
4391 offsetof(struct rte_flow_action_rss, level),
4392 sizeof(((struct rte_flow_action_rss *)0)->
4395 [ACTION_RSS_TYPES] = {
4397 .help = "specific RSS hash types",
4398 .next = NEXT(action_rss, NEXT_ENTRY(ACTION_RSS_TYPE)),
4400 [ACTION_RSS_TYPE] = {
4402 .help = "RSS hash type",
4403 .call = parse_vc_action_rss_type,
4404 .comp = comp_vc_action_rss_type,
4406 [ACTION_RSS_KEY] = {
4408 .help = "RSS hash key",
4409 .next = NEXT(action_rss, NEXT_ENTRY(COMMON_HEX)),
4410 .args = ARGS(ARGS_ENTRY_ARB
4411 (offsetof(struct action_rss_data, conf) +
4412 offsetof(struct rte_flow_action_rss, key),
4413 sizeof(((struct rte_flow_action_rss *)0)->key)),
4415 (offsetof(struct action_rss_data, conf) +
4416 offsetof(struct rte_flow_action_rss, key_len),
4417 sizeof(((struct rte_flow_action_rss *)0)->
4419 ARGS_ENTRY(struct action_rss_data, key)),
4421 [ACTION_RSS_KEY_LEN] = {
4423 .help = "RSS hash key length in bytes",
4424 .next = NEXT(action_rss, NEXT_ENTRY(COMMON_UNSIGNED)),
4425 .args = ARGS(ARGS_ENTRY_ARB_BOUNDED
4426 (offsetof(struct action_rss_data, conf) +
4427 offsetof(struct rte_flow_action_rss, key_len),
4428 sizeof(((struct rte_flow_action_rss *)0)->
4431 RSS_HASH_KEY_LENGTH)),
4433 [ACTION_RSS_QUEUES] = {
4435 .help = "queue indices to use",
4436 .next = NEXT(action_rss, NEXT_ENTRY(ACTION_RSS_QUEUE)),
4437 .call = parse_vc_conf,
4439 [ACTION_RSS_QUEUE] = {
4441 .help = "queue index",
4442 .call = parse_vc_action_rss_queue,
4443 .comp = comp_vc_action_rss_queue,
4447 .help = "direct traffic to physical function",
4448 .priv = PRIV_ACTION(PF, 0),
4449 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4454 .help = "direct traffic to a virtual function ID",
4455 .priv = PRIV_ACTION(VF, sizeof(struct rte_flow_action_vf)),
4456 .next = NEXT(action_vf),
4459 [ACTION_VF_ORIGINAL] = {
4461 .help = "use original VF ID if possible",
4462 .next = NEXT(action_vf, NEXT_ENTRY(COMMON_BOOLEAN)),
4463 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_vf,
4465 .call = parse_vc_conf,
4470 .next = NEXT(action_vf, NEXT_ENTRY(COMMON_UNSIGNED)),
4471 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_vf, id)),
4472 .call = parse_vc_conf,
4474 [ACTION_PHY_PORT] = {
4476 .help = "direct packets to physical port index",
4477 .priv = PRIV_ACTION(PHY_PORT,
4478 sizeof(struct rte_flow_action_phy_port)),
4479 .next = NEXT(action_phy_port),
4482 [ACTION_PHY_PORT_ORIGINAL] = {
4484 .help = "use original port index if possible",
4485 .next = NEXT(action_phy_port, NEXT_ENTRY(COMMON_BOOLEAN)),
4486 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_phy_port,
4488 .call = parse_vc_conf,
4490 [ACTION_PHY_PORT_INDEX] = {
4492 .help = "physical port index",
4493 .next = NEXT(action_phy_port, NEXT_ENTRY(COMMON_UNSIGNED)),
4494 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_phy_port,
4496 .call = parse_vc_conf,
4498 [ACTION_PORT_ID] = {
4500 .help = "direct matching traffic to a given DPDK port ID",
4501 .priv = PRIV_ACTION(PORT_ID,
4502 sizeof(struct rte_flow_action_port_id)),
4503 .next = NEXT(action_port_id),
4506 [ACTION_PORT_ID_ORIGINAL] = {
4508 .help = "use original DPDK port ID if possible",
4509 .next = NEXT(action_port_id, NEXT_ENTRY(COMMON_BOOLEAN)),
4510 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_port_id,
4512 .call = parse_vc_conf,
4514 [ACTION_PORT_ID_ID] = {
4516 .help = "DPDK port ID",
4517 .next = NEXT(action_port_id, NEXT_ENTRY(COMMON_UNSIGNED)),
4518 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_port_id, id)),
4519 .call = parse_vc_conf,
4523 .help = "meter the directed packets at given id",
4524 .priv = PRIV_ACTION(METER,
4525 sizeof(struct rte_flow_action_meter)),
4526 .next = NEXT(action_meter),
4529 [ACTION_METER_COLOR] = {
4531 .help = "meter color for the packets",
4532 .priv = PRIV_ACTION(METER_COLOR,
4533 sizeof(struct rte_flow_action_meter_color)),
4534 .next = NEXT(action_meter_color),
4537 [ACTION_METER_COLOR_TYPE] = {
4539 .help = "specific meter color",
4540 .next = NEXT(NEXT_ENTRY(ACTION_NEXT),
4541 NEXT_ENTRY(ACTION_METER_COLOR_GREEN,
4542 ACTION_METER_COLOR_YELLOW,
4543 ACTION_METER_COLOR_RED)),
4545 [ACTION_METER_COLOR_GREEN] = {
4547 .help = "meter color green",
4548 .call = parse_vc_action_meter_color_type,
4550 [ACTION_METER_COLOR_YELLOW] = {
4552 .help = "meter color yellow",
4553 .call = parse_vc_action_meter_color_type,
4555 [ACTION_METER_COLOR_RED] = {
4557 .help = "meter color red",
4558 .call = parse_vc_action_meter_color_type,
4560 [ACTION_METER_ID] = {
4562 .help = "meter id to use",
4563 .next = NEXT(action_meter, NEXT_ENTRY(COMMON_UNSIGNED)),
4564 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_meter, mtr_id)),
4565 .call = parse_vc_conf,
4567 [ACTION_OF_SET_MPLS_TTL] = {
4568 .name = "of_set_mpls_ttl",
4569 .help = "OpenFlow's OFPAT_SET_MPLS_TTL",
4572 sizeof(struct rte_flow_action_of_set_mpls_ttl)),
4573 .next = NEXT(action_of_set_mpls_ttl),
4576 [ACTION_OF_SET_MPLS_TTL_MPLS_TTL] = {
4579 .next = NEXT(action_of_set_mpls_ttl,
4580 NEXT_ENTRY(COMMON_UNSIGNED)),
4581 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_of_set_mpls_ttl,
4583 .call = parse_vc_conf,
4585 [ACTION_OF_DEC_MPLS_TTL] = {
4586 .name = "of_dec_mpls_ttl",
4587 .help = "OpenFlow's OFPAT_DEC_MPLS_TTL",
4588 .priv = PRIV_ACTION(OF_DEC_MPLS_TTL, 0),
4589 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4592 [ACTION_OF_SET_NW_TTL] = {
4593 .name = "of_set_nw_ttl",
4594 .help = "OpenFlow's OFPAT_SET_NW_TTL",
4597 sizeof(struct rte_flow_action_of_set_nw_ttl)),
4598 .next = NEXT(action_of_set_nw_ttl),
4601 [ACTION_OF_SET_NW_TTL_NW_TTL] = {
4604 .next = NEXT(action_of_set_nw_ttl, NEXT_ENTRY(COMMON_UNSIGNED)),
4605 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_of_set_nw_ttl,
4607 .call = parse_vc_conf,
4609 [ACTION_OF_DEC_NW_TTL] = {
4610 .name = "of_dec_nw_ttl",
4611 .help = "OpenFlow's OFPAT_DEC_NW_TTL",
4612 .priv = PRIV_ACTION(OF_DEC_NW_TTL, 0),
4613 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4616 [ACTION_OF_COPY_TTL_OUT] = {
4617 .name = "of_copy_ttl_out",
4618 .help = "OpenFlow's OFPAT_COPY_TTL_OUT",
4619 .priv = PRIV_ACTION(OF_COPY_TTL_OUT, 0),
4620 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4623 [ACTION_OF_COPY_TTL_IN] = {
4624 .name = "of_copy_ttl_in",
4625 .help = "OpenFlow's OFPAT_COPY_TTL_IN",
4626 .priv = PRIV_ACTION(OF_COPY_TTL_IN, 0),
4627 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4630 [ACTION_OF_POP_VLAN] = {
4631 .name = "of_pop_vlan",
4632 .help = "OpenFlow's OFPAT_POP_VLAN",
4633 .priv = PRIV_ACTION(OF_POP_VLAN, 0),
4634 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4637 [ACTION_OF_PUSH_VLAN] = {
4638 .name = "of_push_vlan",
4639 .help = "OpenFlow's OFPAT_PUSH_VLAN",
4642 sizeof(struct rte_flow_action_of_push_vlan)),
4643 .next = NEXT(action_of_push_vlan),
4646 [ACTION_OF_PUSH_VLAN_ETHERTYPE] = {
4647 .name = "ethertype",
4648 .help = "EtherType",
4649 .next = NEXT(action_of_push_vlan, NEXT_ENTRY(COMMON_UNSIGNED)),
4650 .args = ARGS(ARGS_ENTRY_HTON
4651 (struct rte_flow_action_of_push_vlan,
4653 .call = parse_vc_conf,
4655 [ACTION_OF_SET_VLAN_VID] = {
4656 .name = "of_set_vlan_vid",
4657 .help = "OpenFlow's OFPAT_SET_VLAN_VID",
4660 sizeof(struct rte_flow_action_of_set_vlan_vid)),
4661 .next = NEXT(action_of_set_vlan_vid),
4664 [ACTION_OF_SET_VLAN_VID_VLAN_VID] = {
4667 .next = NEXT(action_of_set_vlan_vid,
4668 NEXT_ENTRY(COMMON_UNSIGNED)),
4669 .args = ARGS(ARGS_ENTRY_HTON
4670 (struct rte_flow_action_of_set_vlan_vid,
4672 .call = parse_vc_conf,
4674 [ACTION_OF_SET_VLAN_PCP] = {
4675 .name = "of_set_vlan_pcp",
4676 .help = "OpenFlow's OFPAT_SET_VLAN_PCP",
4679 sizeof(struct rte_flow_action_of_set_vlan_pcp)),
4680 .next = NEXT(action_of_set_vlan_pcp),
4683 [ACTION_OF_SET_VLAN_PCP_VLAN_PCP] = {
4685 .help = "VLAN priority",
4686 .next = NEXT(action_of_set_vlan_pcp,
4687 NEXT_ENTRY(COMMON_UNSIGNED)),
4688 .args = ARGS(ARGS_ENTRY_HTON
4689 (struct rte_flow_action_of_set_vlan_pcp,
4691 .call = parse_vc_conf,
4693 [ACTION_OF_POP_MPLS] = {
4694 .name = "of_pop_mpls",
4695 .help = "OpenFlow's OFPAT_POP_MPLS",
4696 .priv = PRIV_ACTION(OF_POP_MPLS,
4697 sizeof(struct rte_flow_action_of_pop_mpls)),
4698 .next = NEXT(action_of_pop_mpls),
4701 [ACTION_OF_POP_MPLS_ETHERTYPE] = {
4702 .name = "ethertype",
4703 .help = "EtherType",
4704 .next = NEXT(action_of_pop_mpls, NEXT_ENTRY(COMMON_UNSIGNED)),
4705 .args = ARGS(ARGS_ENTRY_HTON
4706 (struct rte_flow_action_of_pop_mpls,
4708 .call = parse_vc_conf,
4710 [ACTION_OF_PUSH_MPLS] = {
4711 .name = "of_push_mpls",
4712 .help = "OpenFlow's OFPAT_PUSH_MPLS",
4715 sizeof(struct rte_flow_action_of_push_mpls)),
4716 .next = NEXT(action_of_push_mpls),
4719 [ACTION_OF_PUSH_MPLS_ETHERTYPE] = {
4720 .name = "ethertype",
4721 .help = "EtherType",
4722 .next = NEXT(action_of_push_mpls, NEXT_ENTRY(COMMON_UNSIGNED)),
4723 .args = ARGS(ARGS_ENTRY_HTON
4724 (struct rte_flow_action_of_push_mpls,
4726 .call = parse_vc_conf,
4728 [ACTION_VXLAN_ENCAP] = {
4729 .name = "vxlan_encap",
4730 .help = "VXLAN encapsulation, uses configuration set by \"set"
4732 .priv = PRIV_ACTION(VXLAN_ENCAP,
4733 sizeof(struct action_vxlan_encap_data)),
4734 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4735 .call = parse_vc_action_vxlan_encap,
4737 [ACTION_VXLAN_DECAP] = {
4738 .name = "vxlan_decap",
4739 .help = "Performs a decapsulation action by stripping all"
4740 " headers of the VXLAN tunnel network overlay from the"
4742 .priv = PRIV_ACTION(VXLAN_DECAP, 0),
4743 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4746 [ACTION_NVGRE_ENCAP] = {
4747 .name = "nvgre_encap",
4748 .help = "NVGRE encapsulation, uses configuration set by \"set"
4750 .priv = PRIV_ACTION(NVGRE_ENCAP,
4751 sizeof(struct action_nvgre_encap_data)),
4752 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4753 .call = parse_vc_action_nvgre_encap,
4755 [ACTION_NVGRE_DECAP] = {
4756 .name = "nvgre_decap",
4757 .help = "Performs a decapsulation action by stripping all"
4758 " headers of the NVGRE tunnel network overlay from the"
4760 .priv = PRIV_ACTION(NVGRE_DECAP, 0),
4761 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4764 [ACTION_L2_ENCAP] = {
4766 .help = "l2 encap, uses configuration set by"
4767 " \"set l2_encap\"",
4768 .priv = PRIV_ACTION(RAW_ENCAP,
4769 sizeof(struct action_raw_encap_data)),
4770 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4771 .call = parse_vc_action_l2_encap,
4773 [ACTION_L2_DECAP] = {
4775 .help = "l2 decap, uses configuration set by"
4776 " \"set l2_decap\"",
4777 .priv = PRIV_ACTION(RAW_DECAP,
4778 sizeof(struct action_raw_decap_data)),
4779 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4780 .call = parse_vc_action_l2_decap,
4782 [ACTION_MPLSOGRE_ENCAP] = {
4783 .name = "mplsogre_encap",
4784 .help = "mplsogre encapsulation, uses configuration set by"
4785 " \"set mplsogre_encap\"",
4786 .priv = PRIV_ACTION(RAW_ENCAP,
4787 sizeof(struct action_raw_encap_data)),
4788 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4789 .call = parse_vc_action_mplsogre_encap,
4791 [ACTION_MPLSOGRE_DECAP] = {
4792 .name = "mplsogre_decap",
4793 .help = "mplsogre decapsulation, uses configuration set by"
4794 " \"set mplsogre_decap\"",
4795 .priv = PRIV_ACTION(RAW_DECAP,
4796 sizeof(struct action_raw_decap_data)),
4797 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4798 .call = parse_vc_action_mplsogre_decap,
4800 [ACTION_MPLSOUDP_ENCAP] = {
4801 .name = "mplsoudp_encap",
4802 .help = "mplsoudp encapsulation, uses configuration set by"
4803 " \"set mplsoudp_encap\"",
4804 .priv = PRIV_ACTION(RAW_ENCAP,
4805 sizeof(struct action_raw_encap_data)),
4806 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4807 .call = parse_vc_action_mplsoudp_encap,
4809 [ACTION_MPLSOUDP_DECAP] = {
4810 .name = "mplsoudp_decap",
4811 .help = "mplsoudp decapsulation, uses configuration set by"
4812 " \"set mplsoudp_decap\"",
4813 .priv = PRIV_ACTION(RAW_DECAP,
4814 sizeof(struct action_raw_decap_data)),
4815 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4816 .call = parse_vc_action_mplsoudp_decap,
4818 [ACTION_SET_IPV4_SRC] = {
4819 .name = "set_ipv4_src",
4820 .help = "Set a new IPv4 source address in the outermost"
4822 .priv = PRIV_ACTION(SET_IPV4_SRC,
4823 sizeof(struct rte_flow_action_set_ipv4)),
4824 .next = NEXT(action_set_ipv4_src),
4827 [ACTION_SET_IPV4_SRC_IPV4_SRC] = {
4828 .name = "ipv4_addr",
4829 .help = "new IPv4 source address to set",
4830 .next = NEXT(action_set_ipv4_src, NEXT_ENTRY(COMMON_IPV4_ADDR)),
4831 .args = ARGS(ARGS_ENTRY_HTON
4832 (struct rte_flow_action_set_ipv4, ipv4_addr)),
4833 .call = parse_vc_conf,
4835 [ACTION_SET_IPV4_DST] = {
4836 .name = "set_ipv4_dst",
4837 .help = "Set a new IPv4 destination address in the outermost"
4839 .priv = PRIV_ACTION(SET_IPV4_DST,
4840 sizeof(struct rte_flow_action_set_ipv4)),
4841 .next = NEXT(action_set_ipv4_dst),
4844 [ACTION_SET_IPV4_DST_IPV4_DST] = {
4845 .name = "ipv4_addr",
4846 .help = "new IPv4 destination address to set",
4847 .next = NEXT(action_set_ipv4_dst, NEXT_ENTRY(COMMON_IPV4_ADDR)),
4848 .args = ARGS(ARGS_ENTRY_HTON
4849 (struct rte_flow_action_set_ipv4, ipv4_addr)),
4850 .call = parse_vc_conf,
4852 [ACTION_SET_IPV6_SRC] = {
4853 .name = "set_ipv6_src",
4854 .help = "Set a new IPv6 source address in the outermost"
4856 .priv = PRIV_ACTION(SET_IPV6_SRC,
4857 sizeof(struct rte_flow_action_set_ipv6)),
4858 .next = NEXT(action_set_ipv6_src),
4861 [ACTION_SET_IPV6_SRC_IPV6_SRC] = {
4862 .name = "ipv6_addr",
4863 .help = "new IPv6 source address to set",
4864 .next = NEXT(action_set_ipv6_src, NEXT_ENTRY(COMMON_IPV6_ADDR)),
4865 .args = ARGS(ARGS_ENTRY_HTON
4866 (struct rte_flow_action_set_ipv6, ipv6_addr)),
4867 .call = parse_vc_conf,
4869 [ACTION_SET_IPV6_DST] = {
4870 .name = "set_ipv6_dst",
4871 .help = "Set a new IPv6 destination address in the outermost"
4873 .priv = PRIV_ACTION(SET_IPV6_DST,
4874 sizeof(struct rte_flow_action_set_ipv6)),
4875 .next = NEXT(action_set_ipv6_dst),
4878 [ACTION_SET_IPV6_DST_IPV6_DST] = {
4879 .name = "ipv6_addr",
4880 .help = "new IPv6 destination address to set",
4881 .next = NEXT(action_set_ipv6_dst, NEXT_ENTRY(COMMON_IPV6_ADDR)),
4882 .args = ARGS(ARGS_ENTRY_HTON
4883 (struct rte_flow_action_set_ipv6, ipv6_addr)),
4884 .call = parse_vc_conf,
4886 [ACTION_SET_TP_SRC] = {
4887 .name = "set_tp_src",
4888 .help = "set a new source port number in the outermost"
4890 .priv = PRIV_ACTION(SET_TP_SRC,
4891 sizeof(struct rte_flow_action_set_tp)),
4892 .next = NEXT(action_set_tp_src),
4895 [ACTION_SET_TP_SRC_TP_SRC] = {
4897 .help = "new source port number to set",
4898 .next = NEXT(action_set_tp_src, NEXT_ENTRY(COMMON_UNSIGNED)),
4899 .args = ARGS(ARGS_ENTRY_HTON
4900 (struct rte_flow_action_set_tp, port)),
4901 .call = parse_vc_conf,
4903 [ACTION_SET_TP_DST] = {
4904 .name = "set_tp_dst",
4905 .help = "set a new destination port number in the outermost"
4907 .priv = PRIV_ACTION(SET_TP_DST,
4908 sizeof(struct rte_flow_action_set_tp)),
4909 .next = NEXT(action_set_tp_dst),
4912 [ACTION_SET_TP_DST_TP_DST] = {
4914 .help = "new destination port number to set",
4915 .next = NEXT(action_set_tp_dst, NEXT_ENTRY(COMMON_UNSIGNED)),
4916 .args = ARGS(ARGS_ENTRY_HTON
4917 (struct rte_flow_action_set_tp, port)),
4918 .call = parse_vc_conf,
4920 [ACTION_MAC_SWAP] = {
4922 .help = "Swap the source and destination MAC addresses"
4923 " in the outermost Ethernet header",
4924 .priv = PRIV_ACTION(MAC_SWAP, 0),
4925 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4928 [ACTION_DEC_TTL] = {
4930 .help = "decrease network TTL if available",
4931 .priv = PRIV_ACTION(DEC_TTL, 0),
4932 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4935 [ACTION_SET_TTL] = {
4937 .help = "set ttl value",
4938 .priv = PRIV_ACTION(SET_TTL,
4939 sizeof(struct rte_flow_action_set_ttl)),
4940 .next = NEXT(action_set_ttl),
4943 [ACTION_SET_TTL_TTL] = {
4944 .name = "ttl_value",
4945 .help = "new ttl value to set",
4946 .next = NEXT(action_set_ttl, NEXT_ENTRY(COMMON_UNSIGNED)),
4947 .args = ARGS(ARGS_ENTRY_HTON
4948 (struct rte_flow_action_set_ttl, ttl_value)),
4949 .call = parse_vc_conf,
4951 [ACTION_SET_MAC_SRC] = {
4952 .name = "set_mac_src",
4953 .help = "set source mac address",
4954 .priv = PRIV_ACTION(SET_MAC_SRC,
4955 sizeof(struct rte_flow_action_set_mac)),
4956 .next = NEXT(action_set_mac_src),
4959 [ACTION_SET_MAC_SRC_MAC_SRC] = {
4961 .help = "new source mac address",
4962 .next = NEXT(action_set_mac_src, NEXT_ENTRY(COMMON_MAC_ADDR)),
4963 .args = ARGS(ARGS_ENTRY_HTON
4964 (struct rte_flow_action_set_mac, mac_addr)),
4965 .call = parse_vc_conf,
4967 [ACTION_SET_MAC_DST] = {
4968 .name = "set_mac_dst",
4969 .help = "set destination mac address",
4970 .priv = PRIV_ACTION(SET_MAC_DST,
4971 sizeof(struct rte_flow_action_set_mac)),
4972 .next = NEXT(action_set_mac_dst),
4975 [ACTION_SET_MAC_DST_MAC_DST] = {
4977 .help = "new destination mac address to set",
4978 .next = NEXT(action_set_mac_dst, NEXT_ENTRY(COMMON_MAC_ADDR)),
4979 .args = ARGS(ARGS_ENTRY_HTON
4980 (struct rte_flow_action_set_mac, mac_addr)),
4981 .call = parse_vc_conf,
4983 [ACTION_INC_TCP_SEQ] = {
4984 .name = "inc_tcp_seq",
4985 .help = "increase TCP sequence number",
4986 .priv = PRIV_ACTION(INC_TCP_SEQ, sizeof(rte_be32_t)),
4987 .next = NEXT(action_inc_tcp_seq),
4990 [ACTION_INC_TCP_SEQ_VALUE] = {
4992 .help = "the value to increase TCP sequence number by",
4993 .next = NEXT(action_inc_tcp_seq, NEXT_ENTRY(COMMON_UNSIGNED)),
4994 .args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
4995 .call = parse_vc_conf,
4997 [ACTION_DEC_TCP_SEQ] = {
4998 .name = "dec_tcp_seq",
4999 .help = "decrease TCP sequence number",
5000 .priv = PRIV_ACTION(DEC_TCP_SEQ, sizeof(rte_be32_t)),
5001 .next = NEXT(action_dec_tcp_seq),
5004 [ACTION_DEC_TCP_SEQ_VALUE] = {
5006 .help = "the value to decrease TCP sequence number by",
5007 .next = NEXT(action_dec_tcp_seq, NEXT_ENTRY(COMMON_UNSIGNED)),
5008 .args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
5009 .call = parse_vc_conf,
5011 [ACTION_INC_TCP_ACK] = {
5012 .name = "inc_tcp_ack",
5013 .help = "increase TCP acknowledgment number",
5014 .priv = PRIV_ACTION(INC_TCP_ACK, sizeof(rte_be32_t)),
5015 .next = NEXT(action_inc_tcp_ack),
5018 [ACTION_INC_TCP_ACK_VALUE] = {
5020 .help = "the value to increase TCP acknowledgment number by",
5021 .next = NEXT(action_inc_tcp_ack, NEXT_ENTRY(COMMON_UNSIGNED)),
5022 .args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
5023 .call = parse_vc_conf,
5025 [ACTION_DEC_TCP_ACK] = {
5026 .name = "dec_tcp_ack",
5027 .help = "decrease TCP acknowledgment number",
5028 .priv = PRIV_ACTION(DEC_TCP_ACK, sizeof(rte_be32_t)),
5029 .next = NEXT(action_dec_tcp_ack),
5032 [ACTION_DEC_TCP_ACK_VALUE] = {
5034 .help = "the value to decrease TCP acknowledgment number by",
5035 .next = NEXT(action_dec_tcp_ack, NEXT_ENTRY(COMMON_UNSIGNED)),
5036 .args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
5037 .call = parse_vc_conf,
5039 [ACTION_RAW_ENCAP] = {
5040 .name = "raw_encap",
5041 .help = "encapsulation data, defined by set raw_encap",
5042 .priv = PRIV_ACTION(RAW_ENCAP,
5043 sizeof(struct action_raw_encap_data)),
5044 .next = NEXT(action_raw_encap),
5045 .call = parse_vc_action_raw_encap,
5047 [ACTION_RAW_ENCAP_INDEX] = {
5049 .help = "the index of raw_encap_confs",
5050 .next = NEXT(NEXT_ENTRY(ACTION_RAW_ENCAP_INDEX_VALUE)),
5052 [ACTION_RAW_ENCAP_INDEX_VALUE] = {
5055 .help = "unsigned integer value",
5056 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
5057 .call = parse_vc_action_raw_encap_index,
5058 .comp = comp_set_raw_index,
5060 [ACTION_RAW_DECAP] = {
5061 .name = "raw_decap",
5062 .help = "decapsulation data, defined by set raw_encap",
5063 .priv = PRIV_ACTION(RAW_DECAP,
5064 sizeof(struct action_raw_decap_data)),
5065 .next = NEXT(action_raw_decap),
5066 .call = parse_vc_action_raw_decap,
5068 [ACTION_RAW_DECAP_INDEX] = {
5070 .help = "the index of raw_encap_confs",
5071 .next = NEXT(NEXT_ENTRY(ACTION_RAW_DECAP_INDEX_VALUE)),
5073 [ACTION_RAW_DECAP_INDEX_VALUE] = {
5076 .help = "unsigned integer value",
5077 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
5078 .call = parse_vc_action_raw_decap_index,
5079 .comp = comp_set_raw_index,
5081 [ACTION_MODIFY_FIELD] = {
5082 .name = "modify_field",
5083 .help = "modify destination field with data from source field",
5084 .priv = PRIV_ACTION(MODIFY_FIELD, ACTION_MODIFY_SIZE),
5085 .next = NEXT(NEXT_ENTRY(ACTION_MODIFY_FIELD_OP)),
5088 [ACTION_MODIFY_FIELD_OP] = {
5090 .help = "operation type",
5091 .next = NEXT(NEXT_ENTRY(ACTION_MODIFY_FIELD_DST_TYPE),
5092 NEXT_ENTRY(ACTION_MODIFY_FIELD_OP_VALUE)),
5093 .call = parse_vc_conf,
5095 [ACTION_MODIFY_FIELD_OP_VALUE] = {
5096 .name = "{operation}",
5097 .help = "operation type value",
5098 .call = parse_vc_modify_field_op,
5099 .comp = comp_set_modify_field_op,
5101 [ACTION_MODIFY_FIELD_DST_TYPE] = {
5103 .help = "destination field type",
5104 .next = NEXT(action_modify_field_dst,
5105 NEXT_ENTRY(ACTION_MODIFY_FIELD_DST_TYPE_VALUE)),
5106 .call = parse_vc_conf,
5108 [ACTION_MODIFY_FIELD_DST_TYPE_VALUE] = {
5109 .name = "{dst_type}",
5110 .help = "destination field type value",
5111 .call = parse_vc_modify_field_id,
5112 .comp = comp_set_modify_field_id,
5114 [ACTION_MODIFY_FIELD_DST_LEVEL] = {
5115 .name = "dst_level",
5116 .help = "destination field level",
5117 .next = NEXT(action_modify_field_dst,
5118 NEXT_ENTRY(COMMON_UNSIGNED)),
5119 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
5121 .call = parse_vc_conf,
5123 [ACTION_MODIFY_FIELD_DST_OFFSET] = {
5124 .name = "dst_offset",
5125 .help = "destination field bit offset",
5126 .next = NEXT(action_modify_field_dst,
5127 NEXT_ENTRY(COMMON_UNSIGNED)),
5128 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
5130 .call = parse_vc_conf,
5132 [ACTION_MODIFY_FIELD_SRC_TYPE] = {
5134 .help = "source field type",
5135 .next = NEXT(action_modify_field_src,
5136 NEXT_ENTRY(ACTION_MODIFY_FIELD_SRC_TYPE_VALUE)),
5137 .call = parse_vc_conf,
5139 [ACTION_MODIFY_FIELD_SRC_TYPE_VALUE] = {
5140 .name = "{src_type}",
5141 .help = "source field type value",
5142 .call = parse_vc_modify_field_id,
5143 .comp = comp_set_modify_field_id,
5145 [ACTION_MODIFY_FIELD_SRC_LEVEL] = {
5146 .name = "src_level",
5147 .help = "source field level",
5148 .next = NEXT(action_modify_field_src,
5149 NEXT_ENTRY(COMMON_UNSIGNED)),
5150 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
5152 .call = parse_vc_conf,
5154 [ACTION_MODIFY_FIELD_SRC_OFFSET] = {
5155 .name = "src_offset",
5156 .help = "source field bit offset",
5157 .next = NEXT(action_modify_field_src,
5158 NEXT_ENTRY(COMMON_UNSIGNED)),
5159 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
5161 .call = parse_vc_conf,
5163 [ACTION_MODIFY_FIELD_SRC_VALUE] = {
5164 .name = "src_value",
5165 .help = "source immediate value",
5166 .next = NEXT(NEXT_ENTRY(ACTION_MODIFY_FIELD_WIDTH),
5167 NEXT_ENTRY(COMMON_HEX)),
5168 .args = ARGS(ARGS_ENTRY_ARB(0, 0),
5169 ARGS_ENTRY_ARB(0, 0),
5170 ARGS_ENTRY(struct rte_flow_action_modify_field,
5172 .call = parse_vc_conf,
5174 [ACTION_MODIFY_FIELD_SRC_POINTER] = {
5176 .help = "pointer to source immediate value",
5177 .next = NEXT(NEXT_ENTRY(ACTION_MODIFY_FIELD_WIDTH),
5178 NEXT_ENTRY(COMMON_HEX)),
5179 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
5181 ARGS_ENTRY_ARB(0, 0),
5183 (sizeof(struct rte_flow_action_modify_field),
5184 ACTION_MODIFY_PATTERN_SIZE)),
5185 .call = parse_vc_conf,
5187 [ACTION_MODIFY_FIELD_WIDTH] = {
5189 .help = "number of bits to copy",
5190 .next = NEXT(NEXT_ENTRY(ACTION_NEXT),
5191 NEXT_ENTRY(COMMON_UNSIGNED)),
5192 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
5194 .call = parse_vc_conf,
5196 /* Top level command. */
5199 .help = "set raw encap/decap/sample data",
5200 .type = "set raw_encap|raw_decap <index> <pattern>"
5201 " or set sample_actions <index> <action>",
5202 .next = NEXT(NEXT_ENTRY
5205 SET_SAMPLE_ACTIONS)),
5206 .call = parse_set_init,
5208 /* Sub-level commands. */
5210 .name = "raw_encap",
5211 .help = "set raw encap data",
5212 .next = NEXT(next_set_raw),
5213 .args = ARGS(ARGS_ENTRY_ARB_BOUNDED
5214 (offsetof(struct buffer, port),
5215 sizeof(((struct buffer *)0)->port),
5216 0, RAW_ENCAP_CONFS_MAX_NUM - 1)),
5217 .call = parse_set_raw_encap_decap,
5220 .name = "raw_decap",
5221 .help = "set raw decap data",
5222 .next = NEXT(next_set_raw),
5223 .args = ARGS(ARGS_ENTRY_ARB_BOUNDED
5224 (offsetof(struct buffer, port),
5225 sizeof(((struct buffer *)0)->port),
5226 0, RAW_ENCAP_CONFS_MAX_NUM - 1)),
5227 .call = parse_set_raw_encap_decap,
5231 .type = "COMMON_UNSIGNED",
5232 .help = "index of raw_encap/raw_decap data",
5233 .next = NEXT(next_item),
5236 [SET_SAMPLE_INDEX] = {
5239 .help = "index of sample actions",
5240 .next = NEXT(next_action_sample),
5243 [SET_SAMPLE_ACTIONS] = {
5244 .name = "sample_actions",
5245 .help = "set sample actions list",
5246 .next = NEXT(NEXT_ENTRY(SET_SAMPLE_INDEX)),
5247 .args = ARGS(ARGS_ENTRY_ARB_BOUNDED
5248 (offsetof(struct buffer, port),
5249 sizeof(((struct buffer *)0)->port),
5250 0, RAW_SAMPLE_CONFS_MAX_NUM - 1)),
5251 .call = parse_set_sample_action,
5253 [ACTION_SET_TAG] = {
5256 .priv = PRIV_ACTION(SET_TAG,
5257 sizeof(struct rte_flow_action_set_tag)),
5258 .next = NEXT(action_set_tag),
5261 [ACTION_SET_TAG_INDEX] = {
5263 .help = "index of tag array",
5264 .next = NEXT(action_set_tag, NEXT_ENTRY(COMMON_UNSIGNED)),
5265 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_set_tag, index)),
5266 .call = parse_vc_conf,
5268 [ACTION_SET_TAG_DATA] = {
5270 .help = "tag value",
5271 .next = NEXT(action_set_tag, NEXT_ENTRY(COMMON_UNSIGNED)),
5272 .args = ARGS(ARGS_ENTRY
5273 (struct rte_flow_action_set_tag, data)),
5274 .call = parse_vc_conf,
5276 [ACTION_SET_TAG_MASK] = {
5278 .help = "mask for tag value",
5279 .next = NEXT(action_set_tag, NEXT_ENTRY(COMMON_UNSIGNED)),
5280 .args = ARGS(ARGS_ENTRY
5281 (struct rte_flow_action_set_tag, mask)),
5282 .call = parse_vc_conf,
5284 [ACTION_SET_META] = {
5286 .help = "set metadata",
5287 .priv = PRIV_ACTION(SET_META,
5288 sizeof(struct rte_flow_action_set_meta)),
5289 .next = NEXT(action_set_meta),
5290 .call = parse_vc_action_set_meta,
5292 [ACTION_SET_META_DATA] = {
5294 .help = "metadata value",
5295 .next = NEXT(action_set_meta, NEXT_ENTRY(COMMON_UNSIGNED)),
5296 .args = ARGS(ARGS_ENTRY
5297 (struct rte_flow_action_set_meta, data)),
5298 .call = parse_vc_conf,
5300 [ACTION_SET_META_MASK] = {
5302 .help = "mask for metadata value",
5303 .next = NEXT(action_set_meta, NEXT_ENTRY(COMMON_UNSIGNED)),
5304 .args = ARGS(ARGS_ENTRY
5305 (struct rte_flow_action_set_meta, mask)),
5306 .call = parse_vc_conf,
5308 [ACTION_SET_IPV4_DSCP] = {
5309 .name = "set_ipv4_dscp",
5310 .help = "set DSCP value",
5311 .priv = PRIV_ACTION(SET_IPV4_DSCP,
5312 sizeof(struct rte_flow_action_set_dscp)),
5313 .next = NEXT(action_set_ipv4_dscp),
5316 [ACTION_SET_IPV4_DSCP_VALUE] = {
5317 .name = "dscp_value",
5318 .help = "new IPv4 DSCP value to set",
5319 .next = NEXT(action_set_ipv4_dscp, NEXT_ENTRY(COMMON_UNSIGNED)),
5320 .args = ARGS(ARGS_ENTRY
5321 (struct rte_flow_action_set_dscp, dscp)),
5322 .call = parse_vc_conf,
5324 [ACTION_SET_IPV6_DSCP] = {
5325 .name = "set_ipv6_dscp",
5326 .help = "set DSCP value",
5327 .priv = PRIV_ACTION(SET_IPV6_DSCP,
5328 sizeof(struct rte_flow_action_set_dscp)),
5329 .next = NEXT(action_set_ipv6_dscp),
5332 [ACTION_SET_IPV6_DSCP_VALUE] = {
5333 .name = "dscp_value",
5334 .help = "new IPv6 DSCP value to set",
5335 .next = NEXT(action_set_ipv6_dscp, NEXT_ENTRY(COMMON_UNSIGNED)),
5336 .args = ARGS(ARGS_ENTRY
5337 (struct rte_flow_action_set_dscp, dscp)),
5338 .call = parse_vc_conf,
5342 .help = "set a specific metadata header",
5343 .next = NEXT(action_age),
5344 .priv = PRIV_ACTION(AGE,
5345 sizeof(struct rte_flow_action_age)),
5348 [ACTION_AGE_TIMEOUT] = {
5350 .help = "flow age timeout value",
5351 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_age,
5353 .next = NEXT(action_age, NEXT_ENTRY(COMMON_UNSIGNED)),
5354 .call = parse_vc_conf,
5358 .help = "set a sample action",
5359 .next = NEXT(action_sample),
5360 .priv = PRIV_ACTION(SAMPLE,
5361 sizeof(struct action_sample_data)),
5362 .call = parse_vc_action_sample,
5364 [ACTION_SAMPLE_RATIO] = {
5366 .help = "flow sample ratio value",
5367 .next = NEXT(action_sample, NEXT_ENTRY(COMMON_UNSIGNED)),
5368 .args = ARGS(ARGS_ENTRY_ARB
5369 (offsetof(struct action_sample_data, conf) +
5370 offsetof(struct rte_flow_action_sample, ratio),
5371 sizeof(((struct rte_flow_action_sample *)0)->
5374 [ACTION_SAMPLE_INDEX] = {
5376 .help = "the index of sample actions list",
5377 .next = NEXT(NEXT_ENTRY(ACTION_SAMPLE_INDEX_VALUE)),
5379 [ACTION_SAMPLE_INDEX_VALUE] = {
5381 .type = "COMMON_UNSIGNED",
5382 .help = "unsigned integer value",
5383 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
5384 .call = parse_vc_action_sample_index,
5385 .comp = comp_set_sample_index,
5387 [ACTION_CONNTRACK] = {
5388 .name = "conntrack",
5389 .help = "create a conntrack object",
5390 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
5391 .priv = PRIV_ACTION(CONNTRACK,
5392 sizeof(struct rte_flow_action_conntrack)),
5395 [ACTION_CONNTRACK_UPDATE] = {
5396 .name = "conntrack_update",
5397 .help = "update a conntrack object",
5398 .next = NEXT(action_update_conntrack),
5399 .priv = PRIV_ACTION(CONNTRACK,
5400 sizeof(struct rte_flow_modify_conntrack)),
5403 [ACTION_CONNTRACK_UPDATE_DIR] = {
5405 .help = "update a conntrack object direction",
5406 .next = NEXT(action_update_conntrack),
5407 .call = parse_vc_action_conntrack_update,
5409 [ACTION_CONNTRACK_UPDATE_CTX] = {
5411 .help = "update a conntrack object context",
5412 .next = NEXT(action_update_conntrack),
5413 .call = parse_vc_action_conntrack_update,
5415 [ACTION_PORT_REPRESENTOR] = {
5416 .name = "port_representor",
5417 .help = "at embedded switch level, send matching traffic to the given ethdev",
5418 .priv = PRIV_ACTION(PORT_REPRESENTOR,
5419 sizeof(struct rte_flow_action_ethdev)),
5420 .next = NEXT(action_port_representor),
5423 [ACTION_PORT_REPRESENTOR_PORT_ID] = {
5425 .help = "ethdev port ID",
5426 .next = NEXT(action_port_representor,
5427 NEXT_ENTRY(COMMON_UNSIGNED)),
5428 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_ethdev,
5430 .call = parse_vc_conf,
5432 [ACTION_REPRESENTED_PORT] = {
5433 .name = "represented_port",
5434 .help = "at embedded switch level, send matching traffic to the entity represented by the given ethdev",
5435 .priv = PRIV_ACTION(REPRESENTED_PORT,
5436 sizeof(struct rte_flow_action_ethdev)),
5437 .next = NEXT(action_represented_port),
5440 [ACTION_REPRESENTED_PORT_ETHDEV_PORT_ID] = {
5441 .name = "ethdev_port_id",
5442 .help = "ethdev port ID",
5443 .next = NEXT(action_represented_port,
5444 NEXT_ENTRY(COMMON_UNSIGNED)),
5445 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_ethdev,
5447 .call = parse_vc_conf,
5449 /* Indirect action destroy arguments. */
5450 [INDIRECT_ACTION_DESTROY_ID] = {
5451 .name = "action_id",
5452 .help = "specify a indirect action id to destroy",
5453 .next = NEXT(next_ia_destroy_attr,
5454 NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
5455 .args = ARGS(ARGS_ENTRY_PTR(struct buffer,
5456 args.ia_destroy.action_id)),
5457 .call = parse_ia_destroy,
5459 /* Indirect action create arguments. */
5460 [INDIRECT_ACTION_CREATE_ID] = {
5461 .name = "action_id",
5462 .help = "specify a indirect action id to create",
5463 .next = NEXT(next_ia_create_attr,
5464 NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
5465 .args = ARGS(ARGS_ENTRY(struct buffer, args.vc.attr.group)),
5467 [ACTION_INDIRECT] = {
5469 .help = "apply indirect action by id",
5470 .priv = PRIV_ACTION(INDIRECT, 0),
5471 .next = NEXT(NEXT_ENTRY(INDIRECT_ACTION_ID2PTR)),
5472 .args = ARGS(ARGS_ENTRY_ARB(0, sizeof(uint32_t))),
5475 [INDIRECT_ACTION_ID2PTR] = {
5476 .name = "{action_id}",
5477 .type = "INDIRECT_ACTION_ID",
5478 .help = "indirect action id",
5479 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
5480 .call = parse_ia_id2ptr,
5483 [INDIRECT_ACTION_INGRESS] = {
5485 .help = "affect rule to ingress",
5486 .next = NEXT(next_ia_create_attr),
5489 [INDIRECT_ACTION_EGRESS] = {
5491 .help = "affect rule to egress",
5492 .next = NEXT(next_ia_create_attr),
5495 [INDIRECT_ACTION_TRANSFER] = {
5497 .help = "affect rule to transfer",
5498 .next = NEXT(next_ia_create_attr),
5501 [INDIRECT_ACTION_SPEC] = {
5503 .help = "specify action to create indirect handle",
5504 .next = NEXT(next_action),
5507 .name = "g_actions",
5508 .help = "submit a list of associated actions for green",
5509 .next = NEXT(next_action),
5513 .name = "y_actions",
5514 .help = "submit a list of associated actions for yellow",
5515 .next = NEXT(next_action),
5518 .name = "r_actions",
5519 .help = "submit a list of associated actions for red",
5520 .next = NEXT(next_action),
5523 /* Top-level command. */
5526 .type = "port meter policy {port_id} {arg}",
5527 .help = "add port meter policy",
5528 .next = NEXT(NEXT_ENTRY(ITEM_POL_PORT)),
5531 /* Sub-level commands. */
5534 .help = "add port meter policy",
5535 .next = NEXT(NEXT_ENTRY(ITEM_POL_METER)),
5537 [ITEM_POL_METER] = {
5539 .help = "add port meter policy",
5540 .next = NEXT(NEXT_ENTRY(ITEM_POL_POLICY)),
5542 [ITEM_POL_POLICY] = {
5544 .help = "add port meter policy",
5545 .next = NEXT(NEXT_ENTRY(ACTION_POL_R),
5546 NEXT_ENTRY(ACTION_POL_Y),
5547 NEXT_ENTRY(ACTION_POL_G),
5548 NEXT_ENTRY(COMMON_POLICY_ID),
5549 NEXT_ENTRY(COMMON_PORT_ID)),
5550 .args = ARGS(ARGS_ENTRY(struct buffer, args.policy.policy_id),
5551 ARGS_ENTRY(struct buffer, port)),
5556 /** Remove and return last entry from argument stack. */
5557 static const struct arg *
5558 pop_args(struct context *ctx)
5560 return ctx->args_num ? ctx->args[--ctx->args_num] : NULL;
5563 /** Add entry on top of the argument stack. */
5565 push_args(struct context *ctx, const struct arg *arg)
5567 if (ctx->args_num == CTX_STACK_SIZE)
5569 ctx->args[ctx->args_num++] = arg;
5573 /** Spread value into buffer according to bit-mask. */
5575 arg_entry_bf_fill(void *dst, uintmax_t val, const struct arg *arg)
5577 uint32_t i = arg->size;
5585 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
5594 unsigned int shift = 0;
5595 uint8_t *buf = (uint8_t *)dst + arg->offset + (i -= sub);
5597 for (shift = 0; arg->mask[i] >> shift; ++shift) {
5598 if (!(arg->mask[i] & (1 << shift)))
5603 *buf &= ~(1 << shift);
5604 *buf |= (val & 1) << shift;
5612 /** Compare a string with a partial one of a given length. */
5614 strcmp_partial(const char *full, const char *partial, size_t partial_len)
5616 int r = strncmp(full, partial, partial_len);
5620 if (strlen(full) <= partial_len)
5622 return full[partial_len];
5626 * Parse a prefix length and generate a bit-mask.
5628 * Last argument (ctx->args) is retrieved to determine mask size, storage
5629 * location and whether the result must use network byte ordering.
5632 parse_prefix(struct context *ctx, const struct token *token,
5633 const char *str, unsigned int len,
5634 void *buf, unsigned int size)
5636 const struct arg *arg = pop_args(ctx);
5637 static const uint8_t conv[] = "\x00\x80\xc0\xe0\xf0\xf8\xfc\xfe\xff";
5644 /* Argument is expected. */
5648 u = strtoumax(str, &end, 0);
5649 if (errno || (size_t)(end - str) != len)
5654 extra = arg_entry_bf_fill(NULL, 0, arg);
5663 if (!arg_entry_bf_fill(ctx->object, v, arg) ||
5664 !arg_entry_bf_fill(ctx->objmask, -1, arg))
5671 if (bytes > size || bytes + !!extra > size)
5675 buf = (uint8_t *)ctx->object + arg->offset;
5676 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
5678 memset((uint8_t *)buf + size - bytes, 0xff, bytes);
5679 memset(buf, 0x00, size - bytes);
5681 ((uint8_t *)buf)[size - bytes - 1] = conv[extra];
5685 memset(buf, 0xff, bytes);
5686 memset((uint8_t *)buf + bytes, 0x00, size - bytes);
5688 ((uint8_t *)buf)[bytes] = conv[extra];
5691 memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
5694 push_args(ctx, arg);
5698 /** Default parsing function for token name matching. */
5700 parse_default(struct context *ctx, const struct token *token,
5701 const char *str, unsigned int len,
5702 void *buf, unsigned int size)
5707 if (strcmp_partial(token->name, str, len))
5712 /** Parse flow command, initialize output buffer for subsequent tokens. */
5714 parse_init(struct context *ctx, const struct token *token,
5715 const char *str, unsigned int len,
5716 void *buf, unsigned int size)
5718 struct buffer *out = buf;
5720 /* Token name must match. */
5721 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
5723 /* Nothing else to do if there is no buffer. */
5726 /* Make sure buffer is large enough. */
5727 if (size < sizeof(*out))
5729 /* Initialize buffer. */
5730 memset(out, 0x00, sizeof(*out));
5731 memset((uint8_t *)out + sizeof(*out), 0x22, size - sizeof(*out));
5734 ctx->objmask = NULL;
5738 /** Parse tokens for indirect action commands. */
5740 parse_ia(struct context *ctx, const struct token *token,
5741 const char *str, unsigned int len,
5742 void *buf, unsigned int size)
5744 struct buffer *out = buf;
5746 /* Token name must match. */
5747 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
5749 /* Nothing else to do if there is no buffer. */
5752 if (!out->command) {
5753 if (ctx->curr != INDIRECT_ACTION)
5755 if (sizeof(*out) > size)
5757 out->command = ctx->curr;
5760 ctx->objmask = NULL;
5761 out->args.vc.data = (uint8_t *)out + size;
5764 switch (ctx->curr) {
5765 case INDIRECT_ACTION_CREATE:
5766 case INDIRECT_ACTION_UPDATE:
5767 out->args.vc.actions =
5768 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
5770 out->args.vc.attr.group = UINT32_MAX;
5772 case INDIRECT_ACTION_QUERY:
5773 out->command = ctx->curr;
5776 ctx->objmask = NULL;
5778 case INDIRECT_ACTION_EGRESS:
5779 out->args.vc.attr.egress = 1;
5781 case INDIRECT_ACTION_INGRESS:
5782 out->args.vc.attr.ingress = 1;
5784 case INDIRECT_ACTION_TRANSFER:
5785 out->args.vc.attr.transfer = 1;
5793 /** Parse tokens for indirect action destroy command. */
5795 parse_ia_destroy(struct context *ctx, const struct token *token,
5796 const char *str, unsigned int len,
5797 void *buf, unsigned int size)
5799 struct buffer *out = buf;
5800 uint32_t *action_id;
5802 /* Token name must match. */
5803 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
5805 /* Nothing else to do if there is no buffer. */
5808 if (!out->command || out->command == INDIRECT_ACTION) {
5809 if (ctx->curr != INDIRECT_ACTION_DESTROY)
5811 if (sizeof(*out) > size)
5813 out->command = ctx->curr;
5816 ctx->objmask = NULL;
5817 out->args.ia_destroy.action_id =
5818 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
5822 action_id = out->args.ia_destroy.action_id
5823 + out->args.ia_destroy.action_id_n++;
5824 if ((uint8_t *)action_id > (uint8_t *)out + size)
5827 ctx->object = action_id;
5828 ctx->objmask = NULL;
5832 /** Parse tokens for meter policy action commands. */
5834 parse_mp(struct context *ctx, const struct token *token,
5835 const char *str, unsigned int len,
5836 void *buf, unsigned int size)
5838 struct buffer *out = buf;
5840 /* Token name must match. */
5841 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
5843 /* Nothing else to do if there is no buffer. */
5846 if (!out->command) {
5847 if (ctx->curr != ITEM_POL_POLICY)
5849 if (sizeof(*out) > size)
5851 out->command = ctx->curr;
5854 ctx->objmask = NULL;
5855 out->args.vc.data = (uint8_t *)out + size;
5858 switch (ctx->curr) {
5860 out->args.vc.actions =
5861 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
5863 out->command = ctx->curr;
5866 ctx->objmask = NULL;
5873 /** Parse tokens for validate/create commands. */
5875 parse_vc(struct context *ctx, const struct token *token,
5876 const char *str, unsigned int len,
5877 void *buf, unsigned int size)
5879 struct buffer *out = buf;
5883 /* Token name must match. */
5884 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
5886 /* Nothing else to do if there is no buffer. */
5889 if (!out->command) {
5890 if (ctx->curr != VALIDATE && ctx->curr != CREATE)
5892 if (sizeof(*out) > size)
5894 out->command = ctx->curr;
5897 ctx->objmask = NULL;
5898 out->args.vc.data = (uint8_t *)out + size;
5902 switch (ctx->curr) {
5904 ctx->object = &out->args.vc.attr;
5907 case VC_TUNNEL_MATCH:
5908 ctx->object = &out->args.vc.tunnel_ops;
5911 ctx->objmask = NULL;
5912 switch (ctx->curr) {
5917 out->args.vc.tunnel_ops.enabled = 1;
5918 out->args.vc.tunnel_ops.actions = 1;
5920 case VC_TUNNEL_MATCH:
5921 out->args.vc.tunnel_ops.enabled = 1;
5922 out->args.vc.tunnel_ops.items = 1;
5925 out->args.vc.attr.ingress = 1;
5928 out->args.vc.attr.egress = 1;
5931 out->args.vc.attr.transfer = 1;
5934 out->args.vc.pattern =
5935 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
5937 ctx->object = out->args.vc.pattern;
5938 ctx->objmask = NULL;
5941 out->args.vc.actions =
5942 (void *)RTE_ALIGN_CEIL((uintptr_t)
5943 (out->args.vc.pattern +
5944 out->args.vc.pattern_n),
5946 ctx->object = out->args.vc.actions;
5947 ctx->objmask = NULL;
5954 if (!out->args.vc.actions) {
5955 const struct parse_item_priv *priv = token->priv;
5956 struct rte_flow_item *item =
5957 out->args.vc.pattern + out->args.vc.pattern_n;
5959 data_size = priv->size * 3; /* spec, last, mask */
5960 data = (void *)RTE_ALIGN_FLOOR((uintptr_t)
5961 (out->args.vc.data - data_size),
5963 if ((uint8_t *)item + sizeof(*item) > data)
5965 *item = (struct rte_flow_item){
5968 ++out->args.vc.pattern_n;
5970 ctx->objmask = NULL;
5972 const struct parse_action_priv *priv = token->priv;
5973 struct rte_flow_action *action =
5974 out->args.vc.actions + out->args.vc.actions_n;
5976 data_size = priv->size; /* configuration */
5977 data = (void *)RTE_ALIGN_FLOOR((uintptr_t)
5978 (out->args.vc.data - data_size),
5980 if ((uint8_t *)action + sizeof(*action) > data)
5982 *action = (struct rte_flow_action){
5984 .conf = data_size ? data : NULL,
5986 ++out->args.vc.actions_n;
5987 ctx->object = action;
5988 ctx->objmask = NULL;
5990 memset(data, 0, data_size);
5991 out->args.vc.data = data;
5992 ctx->objdata = data_size;
5996 /** Parse pattern item parameter type. */
5998 parse_vc_spec(struct context *ctx, const struct token *token,
5999 const char *str, unsigned int len,
6000 void *buf, unsigned int size)
6002 struct buffer *out = buf;
6003 struct rte_flow_item *item;
6009 /* Token name must match. */
6010 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
6012 /* Parse parameter types. */
6013 switch (ctx->curr) {
6014 static const enum index prefix[] = NEXT_ENTRY(COMMON_PREFIX);
6020 case ITEM_PARAM_SPEC:
6023 case ITEM_PARAM_LAST:
6026 case ITEM_PARAM_PREFIX:
6027 /* Modify next token to expect a prefix. */
6028 if (ctx->next_num < 2)
6030 ctx->next[ctx->next_num - 2] = prefix;
6032 case ITEM_PARAM_MASK:
6038 /* Nothing else to do if there is no buffer. */
6041 if (!out->args.vc.pattern_n)
6043 item = &out->args.vc.pattern[out->args.vc.pattern_n - 1];
6044 data_size = ctx->objdata / 3; /* spec, last, mask */
6045 /* Point to selected object. */
6046 ctx->object = out->args.vc.data + (data_size * index);
6048 ctx->objmask = out->args.vc.data + (data_size * 2); /* mask */
6049 item->mask = ctx->objmask;
6051 ctx->objmask = NULL;
6052 /* Update relevant item pointer. */
6053 *((const void **[]){ &item->spec, &item->last, &item->mask })[index] =
6058 /** Parse action configuration field. */
6060 parse_vc_conf(struct context *ctx, const struct token *token,
6061 const char *str, unsigned int len,
6062 void *buf, unsigned int size)
6064 struct buffer *out = buf;
6067 /* Token name must match. */
6068 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
6070 /* Nothing else to do if there is no buffer. */
6073 /* Point to selected object. */
6074 ctx->object = out->args.vc.data;
6075 ctx->objmask = NULL;
6079 /** Parse eCPRI common header type field. */
6081 parse_vc_item_ecpri_type(struct context *ctx, const struct token *token,
6082 const char *str, unsigned int len,
6083 void *buf, unsigned int size)
6085 struct rte_flow_item_ecpri *ecpri;
6086 struct rte_flow_item_ecpri *ecpri_mask;
6087 struct rte_flow_item *item;
6090 struct buffer *out = buf;
6091 const struct arg *arg;
6094 /* Token name must match. */
6095 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
6097 switch (ctx->curr) {
6098 case ITEM_ECPRI_COMMON_TYPE_IQ_DATA:
6099 msg_type = RTE_ECPRI_MSG_TYPE_IQ_DATA;
6101 case ITEM_ECPRI_COMMON_TYPE_RTC_CTRL:
6102 msg_type = RTE_ECPRI_MSG_TYPE_RTC_CTRL;
6104 case ITEM_ECPRI_COMMON_TYPE_DLY_MSR:
6105 msg_type = RTE_ECPRI_MSG_TYPE_DLY_MSR;
6112 arg = pop_args(ctx);
6115 ecpri = (struct rte_flow_item_ecpri *)out->args.vc.data;
6116 ecpri->hdr.common.type = msg_type;
6117 data_size = ctx->objdata / 3; /* spec, last, mask */
6118 ecpri_mask = (struct rte_flow_item_ecpri *)(out->args.vc.data +
6120 ecpri_mask->hdr.common.type = 0xFF;
6122 ecpri->hdr.common.u32 = rte_cpu_to_be_32(ecpri->hdr.common.u32);
6123 ecpri_mask->hdr.common.u32 =
6124 rte_cpu_to_be_32(ecpri_mask->hdr.common.u32);
6126 item = &out->args.vc.pattern[out->args.vc.pattern_n - 1];
6128 item->mask = ecpri_mask;
6132 /** Parse L2TPv2 common header type field. */
6134 parse_vc_item_l2tpv2_type(struct context *ctx, const struct token *token,
6135 const char *str, unsigned int len,
6136 void *buf, unsigned int size)
6138 struct rte_flow_item_l2tpv2 *l2tpv2;
6139 struct rte_flow_item_l2tpv2 *l2tpv2_mask;
6140 struct rte_flow_item *item;
6142 uint16_t msg_type = 0;
6143 struct buffer *out = buf;
6144 const struct arg *arg;
6147 /* Token name must match. */
6148 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
6150 switch (ctx->curr) {
6151 case ITEM_L2TPV2_TYPE_DATA:
6152 msg_type |= RTE_L2TPV2_MSG_TYPE_DATA;
6154 case ITEM_L2TPV2_TYPE_DATA_L:
6155 msg_type |= RTE_L2TPV2_MSG_TYPE_DATA_L;
6157 case ITEM_L2TPV2_TYPE_DATA_S:
6158 msg_type |= RTE_L2TPV2_MSG_TYPE_DATA_S;
6160 case ITEM_L2TPV2_TYPE_DATA_O:
6161 msg_type |= RTE_L2TPV2_MSG_TYPE_DATA_O;
6163 case ITEM_L2TPV2_TYPE_DATA_L_S:
6164 msg_type |= RTE_L2TPV2_MSG_TYPE_DATA_L_S;
6166 case ITEM_L2TPV2_TYPE_CTRL:
6167 msg_type |= RTE_L2TPV2_MSG_TYPE_CONTROL;
6174 arg = pop_args(ctx);
6177 l2tpv2 = (struct rte_flow_item_l2tpv2 *)out->args.vc.data;
6178 l2tpv2->hdr.common.flags_version |= msg_type;
6179 data_size = ctx->objdata / 3; /* spec, last, mask */
6180 l2tpv2_mask = (struct rte_flow_item_l2tpv2 *)(out->args.vc.data +
6182 l2tpv2_mask->hdr.common.flags_version = 0xFFFF;
6184 l2tpv2->hdr.common.flags_version =
6185 rte_cpu_to_be_16(l2tpv2->hdr.common.flags_version);
6186 l2tpv2_mask->hdr.common.flags_version =
6187 rte_cpu_to_be_16(l2tpv2_mask->hdr.common.flags_version);
6189 item = &out->args.vc.pattern[out->args.vc.pattern_n - 1];
6190 item->spec = l2tpv2;
6191 item->mask = l2tpv2_mask;
6195 /** Parse meter color action type. */
6197 parse_vc_action_meter_color_type(struct context *ctx, const struct token *token,
6198 const char *str, unsigned int len,
6199 void *buf, unsigned int size)
6201 struct rte_flow_action *action_data;
6202 struct rte_flow_action_meter_color *conf;
6203 enum rte_color color;
6207 /* Token name must match. */
6208 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
6210 switch (ctx->curr) {
6211 case ACTION_METER_COLOR_GREEN:
6212 color = RTE_COLOR_GREEN;
6214 case ACTION_METER_COLOR_YELLOW:
6215 color = RTE_COLOR_YELLOW;
6217 case ACTION_METER_COLOR_RED:
6218 color = RTE_COLOR_RED;
6226 action_data = ctx->object;
6227 conf = (struct rte_flow_action_meter_color *)
6228 (uintptr_t)(action_data->conf);
6229 conf->color = color;
6233 /** Parse RSS action. */
6235 parse_vc_action_rss(struct context *ctx, const struct token *token,
6236 const char *str, unsigned int len,
6237 void *buf, unsigned int size)
6239 struct buffer *out = buf;
6240 struct rte_flow_action *action;
6241 struct action_rss_data *action_rss_data;
6245 ret = parse_vc(ctx, token, str, len, buf, size);
6248 /* Nothing else to do if there is no buffer. */
6251 if (!out->args.vc.actions_n)
6253 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
6254 /* Point to selected object. */
6255 ctx->object = out->args.vc.data;
6256 ctx->objmask = NULL;
6257 /* Set up default configuration. */
6258 action_rss_data = ctx->object;
6259 *action_rss_data = (struct action_rss_data){
6260 .conf = (struct rte_flow_action_rss){
6261 .func = RTE_ETH_HASH_FUNCTION_DEFAULT,
6265 .queue_num = RTE_MIN(nb_rxq, ACTION_RSS_QUEUE_NUM),
6267 .queue = action_rss_data->queue,
6271 for (i = 0; i < action_rss_data->conf.queue_num; ++i)
6272 action_rss_data->queue[i] = i;
6273 action->conf = &action_rss_data->conf;
6278 * Parse func field for RSS action.
6280 * The RTE_ETH_HASH_FUNCTION_* value to assign is derived from the
6281 * ACTION_RSS_FUNC_* index that called this function.
6284 parse_vc_action_rss_func(struct context *ctx, const struct token *token,
6285 const char *str, unsigned int len,
6286 void *buf, unsigned int size)
6288 struct action_rss_data *action_rss_data;
6289 enum rte_eth_hash_function func;
6293 /* Token name must match. */
6294 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
6296 switch (ctx->curr) {
6297 case ACTION_RSS_FUNC_DEFAULT:
6298 func = RTE_ETH_HASH_FUNCTION_DEFAULT;
6300 case ACTION_RSS_FUNC_TOEPLITZ:
6301 func = RTE_ETH_HASH_FUNCTION_TOEPLITZ;
6303 case ACTION_RSS_FUNC_SIMPLE_XOR:
6304 func = RTE_ETH_HASH_FUNCTION_SIMPLE_XOR;
6306 case ACTION_RSS_FUNC_SYMMETRIC_TOEPLITZ:
6307 func = RTE_ETH_HASH_FUNCTION_SYMMETRIC_TOEPLITZ;
6314 action_rss_data = ctx->object;
6315 action_rss_data->conf.func = func;
6320 * Parse type field for RSS action.
6322 * Valid tokens are type field names and the "end" token.
6325 parse_vc_action_rss_type(struct context *ctx, const struct token *token,
6326 const char *str, unsigned int len,
6327 void *buf, unsigned int size)
6329 static const enum index next[] = NEXT_ENTRY(ACTION_RSS_TYPE);
6330 struct action_rss_data *action_rss_data;
6336 if (ctx->curr != ACTION_RSS_TYPE)
6338 if (!(ctx->objdata >> 16) && ctx->object) {
6339 action_rss_data = ctx->object;
6340 action_rss_data->conf.types = 0;
6342 if (!strcmp_partial("end", str, len)) {
6343 ctx->objdata &= 0xffff;
6346 for (i = 0; rss_type_table[i].str; ++i)
6347 if (!strcmp_partial(rss_type_table[i].str, str, len))
6349 if (!rss_type_table[i].str)
6351 ctx->objdata = 1 << 16 | (ctx->objdata & 0xffff);
6353 if (ctx->next_num == RTE_DIM(ctx->next))
6355 ctx->next[ctx->next_num++] = next;
6358 action_rss_data = ctx->object;
6359 action_rss_data->conf.types |= rss_type_table[i].rss_type;
6364 * Parse queue field for RSS action.
6366 * Valid tokens are queue indices and the "end" token.
6369 parse_vc_action_rss_queue(struct context *ctx, const struct token *token,
6370 const char *str, unsigned int len,
6371 void *buf, unsigned int size)
6373 static const enum index next[] = NEXT_ENTRY(ACTION_RSS_QUEUE);
6374 struct action_rss_data *action_rss_data;
6375 const struct arg *arg;
6382 if (ctx->curr != ACTION_RSS_QUEUE)
6384 i = ctx->objdata >> 16;
6385 if (!strcmp_partial("end", str, len)) {
6386 ctx->objdata &= 0xffff;
6389 if (i >= ACTION_RSS_QUEUE_NUM)
6391 arg = ARGS_ENTRY_ARB(offsetof(struct action_rss_data, queue) +
6392 i * sizeof(action_rss_data->queue[i]),
6393 sizeof(action_rss_data->queue[i]));
6394 if (push_args(ctx, arg))
6396 ret = parse_int(ctx, token, str, len, NULL, 0);
6402 ctx->objdata = i << 16 | (ctx->objdata & 0xffff);
6404 if (ctx->next_num == RTE_DIM(ctx->next))
6406 ctx->next[ctx->next_num++] = next;
6410 action_rss_data = ctx->object;
6411 action_rss_data->conf.queue_num = i;
6412 action_rss_data->conf.queue = i ? action_rss_data->queue : NULL;
6416 /** Setup VXLAN encap configuration. */
6418 parse_setup_vxlan_encap_data(struct action_vxlan_encap_data *action_vxlan_encap_data)
6420 /* Set up default configuration. */
6421 *action_vxlan_encap_data = (struct action_vxlan_encap_data){
6422 .conf = (struct rte_flow_action_vxlan_encap){
6423 .definition = action_vxlan_encap_data->items,
6427 .type = RTE_FLOW_ITEM_TYPE_ETH,
6428 .spec = &action_vxlan_encap_data->item_eth,
6429 .mask = &rte_flow_item_eth_mask,
6432 .type = RTE_FLOW_ITEM_TYPE_VLAN,
6433 .spec = &action_vxlan_encap_data->item_vlan,
6434 .mask = &rte_flow_item_vlan_mask,
6437 .type = RTE_FLOW_ITEM_TYPE_IPV4,
6438 .spec = &action_vxlan_encap_data->item_ipv4,
6439 .mask = &rte_flow_item_ipv4_mask,
6442 .type = RTE_FLOW_ITEM_TYPE_UDP,
6443 .spec = &action_vxlan_encap_data->item_udp,
6444 .mask = &rte_flow_item_udp_mask,
6447 .type = RTE_FLOW_ITEM_TYPE_VXLAN,
6448 .spec = &action_vxlan_encap_data->item_vxlan,
6449 .mask = &rte_flow_item_vxlan_mask,
6452 .type = RTE_FLOW_ITEM_TYPE_END,
6457 .tci = vxlan_encap_conf.vlan_tci,
6461 .src_addr = vxlan_encap_conf.ipv4_src,
6462 .dst_addr = vxlan_encap_conf.ipv4_dst,
6465 .src_port = vxlan_encap_conf.udp_src,
6466 .dst_port = vxlan_encap_conf.udp_dst,
6468 .item_vxlan.flags = 0,
6470 memcpy(action_vxlan_encap_data->item_eth.dst.addr_bytes,
6471 vxlan_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
6472 memcpy(action_vxlan_encap_data->item_eth.src.addr_bytes,
6473 vxlan_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
6474 if (!vxlan_encap_conf.select_ipv4) {
6475 memcpy(&action_vxlan_encap_data->item_ipv6.hdr.src_addr,
6476 &vxlan_encap_conf.ipv6_src,
6477 sizeof(vxlan_encap_conf.ipv6_src));
6478 memcpy(&action_vxlan_encap_data->item_ipv6.hdr.dst_addr,
6479 &vxlan_encap_conf.ipv6_dst,
6480 sizeof(vxlan_encap_conf.ipv6_dst));
6481 action_vxlan_encap_data->items[2] = (struct rte_flow_item){
6482 .type = RTE_FLOW_ITEM_TYPE_IPV6,
6483 .spec = &action_vxlan_encap_data->item_ipv6,
6484 .mask = &rte_flow_item_ipv6_mask,
6487 if (!vxlan_encap_conf.select_vlan)
6488 action_vxlan_encap_data->items[1].type =
6489 RTE_FLOW_ITEM_TYPE_VOID;
6490 if (vxlan_encap_conf.select_tos_ttl) {
6491 if (vxlan_encap_conf.select_ipv4) {
6492 static struct rte_flow_item_ipv4 ipv4_mask_tos;
6494 memcpy(&ipv4_mask_tos, &rte_flow_item_ipv4_mask,
6495 sizeof(ipv4_mask_tos));
6496 ipv4_mask_tos.hdr.type_of_service = 0xff;
6497 ipv4_mask_tos.hdr.time_to_live = 0xff;
6498 action_vxlan_encap_data->item_ipv4.hdr.type_of_service =
6499 vxlan_encap_conf.ip_tos;
6500 action_vxlan_encap_data->item_ipv4.hdr.time_to_live =
6501 vxlan_encap_conf.ip_ttl;
6502 action_vxlan_encap_data->items[2].mask =
6505 static struct rte_flow_item_ipv6 ipv6_mask_tos;
6507 memcpy(&ipv6_mask_tos, &rte_flow_item_ipv6_mask,
6508 sizeof(ipv6_mask_tos));
6509 ipv6_mask_tos.hdr.vtc_flow |=
6510 RTE_BE32(0xfful << RTE_IPV6_HDR_TC_SHIFT);
6511 ipv6_mask_tos.hdr.hop_limits = 0xff;
6512 action_vxlan_encap_data->item_ipv6.hdr.vtc_flow |=
6514 ((uint32_t)vxlan_encap_conf.ip_tos <<
6515 RTE_IPV6_HDR_TC_SHIFT);
6516 action_vxlan_encap_data->item_ipv6.hdr.hop_limits =
6517 vxlan_encap_conf.ip_ttl;
6518 action_vxlan_encap_data->items[2].mask =
6522 memcpy(action_vxlan_encap_data->item_vxlan.vni, vxlan_encap_conf.vni,
6523 RTE_DIM(vxlan_encap_conf.vni));
6527 /** Parse VXLAN encap action. */
6529 parse_vc_action_vxlan_encap(struct context *ctx, const struct token *token,
6530 const char *str, unsigned int len,
6531 void *buf, unsigned int size)
6533 struct buffer *out = buf;
6534 struct rte_flow_action *action;
6535 struct action_vxlan_encap_data *action_vxlan_encap_data;
6538 ret = parse_vc(ctx, token, str, len, buf, size);
6541 /* Nothing else to do if there is no buffer. */
6544 if (!out->args.vc.actions_n)
6546 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
6547 /* Point to selected object. */
6548 ctx->object = out->args.vc.data;
6549 ctx->objmask = NULL;
6550 action_vxlan_encap_data = ctx->object;
6551 parse_setup_vxlan_encap_data(action_vxlan_encap_data);
6552 action->conf = &action_vxlan_encap_data->conf;
6556 /** Setup NVGRE encap configuration. */
6558 parse_setup_nvgre_encap_data(struct action_nvgre_encap_data *action_nvgre_encap_data)
6560 /* Set up default configuration. */
6561 *action_nvgre_encap_data = (struct action_nvgre_encap_data){
6562 .conf = (struct rte_flow_action_nvgre_encap){
6563 .definition = action_nvgre_encap_data->items,
6567 .type = RTE_FLOW_ITEM_TYPE_ETH,
6568 .spec = &action_nvgre_encap_data->item_eth,
6569 .mask = &rte_flow_item_eth_mask,
6572 .type = RTE_FLOW_ITEM_TYPE_VLAN,
6573 .spec = &action_nvgre_encap_data->item_vlan,
6574 .mask = &rte_flow_item_vlan_mask,
6577 .type = RTE_FLOW_ITEM_TYPE_IPV4,
6578 .spec = &action_nvgre_encap_data->item_ipv4,
6579 .mask = &rte_flow_item_ipv4_mask,
6582 .type = RTE_FLOW_ITEM_TYPE_NVGRE,
6583 .spec = &action_nvgre_encap_data->item_nvgre,
6584 .mask = &rte_flow_item_nvgre_mask,
6587 .type = RTE_FLOW_ITEM_TYPE_END,
6592 .tci = nvgre_encap_conf.vlan_tci,
6596 .src_addr = nvgre_encap_conf.ipv4_src,
6597 .dst_addr = nvgre_encap_conf.ipv4_dst,
6599 .item_nvgre.c_k_s_rsvd0_ver = RTE_BE16(0x2000),
6600 .item_nvgre.protocol = RTE_BE16(RTE_ETHER_TYPE_TEB),
6601 .item_nvgre.flow_id = 0,
6603 memcpy(action_nvgre_encap_data->item_eth.dst.addr_bytes,
6604 nvgre_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
6605 memcpy(action_nvgre_encap_data->item_eth.src.addr_bytes,
6606 nvgre_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
6607 if (!nvgre_encap_conf.select_ipv4) {
6608 memcpy(&action_nvgre_encap_data->item_ipv6.hdr.src_addr,
6609 &nvgre_encap_conf.ipv6_src,
6610 sizeof(nvgre_encap_conf.ipv6_src));
6611 memcpy(&action_nvgre_encap_data->item_ipv6.hdr.dst_addr,
6612 &nvgre_encap_conf.ipv6_dst,
6613 sizeof(nvgre_encap_conf.ipv6_dst));
6614 action_nvgre_encap_data->items[2] = (struct rte_flow_item){
6615 .type = RTE_FLOW_ITEM_TYPE_IPV6,
6616 .spec = &action_nvgre_encap_data->item_ipv6,
6617 .mask = &rte_flow_item_ipv6_mask,
6620 if (!nvgre_encap_conf.select_vlan)
6621 action_nvgre_encap_data->items[1].type =
6622 RTE_FLOW_ITEM_TYPE_VOID;
6623 memcpy(action_nvgre_encap_data->item_nvgre.tni, nvgre_encap_conf.tni,
6624 RTE_DIM(nvgre_encap_conf.tni));
6628 /** Parse NVGRE encap action. */
6630 parse_vc_action_nvgre_encap(struct context *ctx, const struct token *token,
6631 const char *str, unsigned int len,
6632 void *buf, unsigned int size)
6634 struct buffer *out = buf;
6635 struct rte_flow_action *action;
6636 struct action_nvgre_encap_data *action_nvgre_encap_data;
6639 ret = parse_vc(ctx, token, str, len, buf, size);
6642 /* Nothing else to do if there is no buffer. */
6645 if (!out->args.vc.actions_n)
6647 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
6648 /* Point to selected object. */
6649 ctx->object = out->args.vc.data;
6650 ctx->objmask = NULL;
6651 action_nvgre_encap_data = ctx->object;
6652 parse_setup_nvgre_encap_data(action_nvgre_encap_data);
6653 action->conf = &action_nvgre_encap_data->conf;
6657 /** Parse l2 encap action. */
6659 parse_vc_action_l2_encap(struct context *ctx, const struct token *token,
6660 const char *str, unsigned int len,
6661 void *buf, unsigned int size)
6663 struct buffer *out = buf;
6664 struct rte_flow_action *action;
6665 struct action_raw_encap_data *action_encap_data;
6666 struct rte_flow_item_eth eth = { .type = 0, };
6667 struct rte_flow_item_vlan vlan = {
6668 .tci = mplsoudp_encap_conf.vlan_tci,
6674 ret = parse_vc(ctx, token, str, len, buf, size);
6677 /* Nothing else to do if there is no buffer. */
6680 if (!out->args.vc.actions_n)
6682 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
6683 /* Point to selected object. */
6684 ctx->object = out->args.vc.data;
6685 ctx->objmask = NULL;
6686 /* Copy the headers to the buffer. */
6687 action_encap_data = ctx->object;
6688 *action_encap_data = (struct action_raw_encap_data) {
6689 .conf = (struct rte_flow_action_raw_encap){
6690 .data = action_encap_data->data,
6694 header = action_encap_data->data;
6695 if (l2_encap_conf.select_vlan)
6696 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
6697 else if (l2_encap_conf.select_ipv4)
6698 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
6700 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
6701 memcpy(eth.dst.addr_bytes,
6702 l2_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
6703 memcpy(eth.src.addr_bytes,
6704 l2_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
6705 memcpy(header, ð, sizeof(eth));
6706 header += sizeof(eth);
6707 if (l2_encap_conf.select_vlan) {
6708 if (l2_encap_conf.select_ipv4)
6709 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
6711 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
6712 memcpy(header, &vlan, sizeof(vlan));
6713 header += sizeof(vlan);
6715 action_encap_data->conf.size = header -
6716 action_encap_data->data;
6717 action->conf = &action_encap_data->conf;
6721 /** Parse l2 decap action. */
6723 parse_vc_action_l2_decap(struct context *ctx, const struct token *token,
6724 const char *str, unsigned int len,
6725 void *buf, unsigned int size)
6727 struct buffer *out = buf;
6728 struct rte_flow_action *action;
6729 struct action_raw_decap_data *action_decap_data;
6730 struct rte_flow_item_eth eth = { .type = 0, };
6731 struct rte_flow_item_vlan vlan = {
6732 .tci = mplsoudp_encap_conf.vlan_tci,
6738 ret = parse_vc(ctx, token, str, len, buf, size);
6741 /* Nothing else to do if there is no buffer. */
6744 if (!out->args.vc.actions_n)
6746 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
6747 /* Point to selected object. */
6748 ctx->object = out->args.vc.data;
6749 ctx->objmask = NULL;
6750 /* Copy the headers to the buffer. */
6751 action_decap_data = ctx->object;
6752 *action_decap_data = (struct action_raw_decap_data) {
6753 .conf = (struct rte_flow_action_raw_decap){
6754 .data = action_decap_data->data,
6758 header = action_decap_data->data;
6759 if (l2_decap_conf.select_vlan)
6760 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
6761 memcpy(header, ð, sizeof(eth));
6762 header += sizeof(eth);
6763 if (l2_decap_conf.select_vlan) {
6764 memcpy(header, &vlan, sizeof(vlan));
6765 header += sizeof(vlan);
6767 action_decap_data->conf.size = header -
6768 action_decap_data->data;
6769 action->conf = &action_decap_data->conf;
6773 #define ETHER_TYPE_MPLS_UNICAST 0x8847
6775 /** Parse MPLSOGRE encap action. */
6777 parse_vc_action_mplsogre_encap(struct context *ctx, const struct token *token,
6778 const char *str, unsigned int len,
6779 void *buf, unsigned int size)
6781 struct buffer *out = buf;
6782 struct rte_flow_action *action;
6783 struct action_raw_encap_data *action_encap_data;
6784 struct rte_flow_item_eth eth = { .type = 0, };
6785 struct rte_flow_item_vlan vlan = {
6786 .tci = mplsogre_encap_conf.vlan_tci,
6789 struct rte_flow_item_ipv4 ipv4 = {
6791 .src_addr = mplsogre_encap_conf.ipv4_src,
6792 .dst_addr = mplsogre_encap_conf.ipv4_dst,
6793 .next_proto_id = IPPROTO_GRE,
6794 .version_ihl = RTE_IPV4_VHL_DEF,
6795 .time_to_live = IPDEFTTL,
6798 struct rte_flow_item_ipv6 ipv6 = {
6800 .proto = IPPROTO_GRE,
6801 .hop_limits = IPDEFTTL,
6804 struct rte_flow_item_gre gre = {
6805 .protocol = rte_cpu_to_be_16(ETHER_TYPE_MPLS_UNICAST),
6807 struct rte_flow_item_mpls mpls = {
6813 ret = parse_vc(ctx, token, str, len, buf, size);
6816 /* Nothing else to do if there is no buffer. */
6819 if (!out->args.vc.actions_n)
6821 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
6822 /* Point to selected object. */
6823 ctx->object = out->args.vc.data;
6824 ctx->objmask = NULL;
6825 /* Copy the headers to the buffer. */
6826 action_encap_data = ctx->object;
6827 *action_encap_data = (struct action_raw_encap_data) {
6828 .conf = (struct rte_flow_action_raw_encap){
6829 .data = action_encap_data->data,
6834 header = action_encap_data->data;
6835 if (mplsogre_encap_conf.select_vlan)
6836 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
6837 else if (mplsogre_encap_conf.select_ipv4)
6838 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
6840 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
6841 memcpy(eth.dst.addr_bytes,
6842 mplsogre_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
6843 memcpy(eth.src.addr_bytes,
6844 mplsogre_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
6845 memcpy(header, ð, sizeof(eth));
6846 header += sizeof(eth);
6847 if (mplsogre_encap_conf.select_vlan) {
6848 if (mplsogre_encap_conf.select_ipv4)
6849 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
6851 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
6852 memcpy(header, &vlan, sizeof(vlan));
6853 header += sizeof(vlan);
6855 if (mplsogre_encap_conf.select_ipv4) {
6856 memcpy(header, &ipv4, sizeof(ipv4));
6857 header += sizeof(ipv4);
6859 memcpy(&ipv6.hdr.src_addr,
6860 &mplsogre_encap_conf.ipv6_src,
6861 sizeof(mplsogre_encap_conf.ipv6_src));
6862 memcpy(&ipv6.hdr.dst_addr,
6863 &mplsogre_encap_conf.ipv6_dst,
6864 sizeof(mplsogre_encap_conf.ipv6_dst));
6865 memcpy(header, &ipv6, sizeof(ipv6));
6866 header += sizeof(ipv6);
6868 memcpy(header, &gre, sizeof(gre));
6869 header += sizeof(gre);
6870 memcpy(mpls.label_tc_s, mplsogre_encap_conf.label,
6871 RTE_DIM(mplsogre_encap_conf.label));
6872 mpls.label_tc_s[2] |= 0x1;
6873 memcpy(header, &mpls, sizeof(mpls));
6874 header += sizeof(mpls);
6875 action_encap_data->conf.size = header -
6876 action_encap_data->data;
6877 action->conf = &action_encap_data->conf;
6881 /** Parse MPLSOGRE decap action. */
6883 parse_vc_action_mplsogre_decap(struct context *ctx, const struct token *token,
6884 const char *str, unsigned int len,
6885 void *buf, unsigned int size)
6887 struct buffer *out = buf;
6888 struct rte_flow_action *action;
6889 struct action_raw_decap_data *action_decap_data;
6890 struct rte_flow_item_eth eth = { .type = 0, };
6891 struct rte_flow_item_vlan vlan = {.tci = 0};
6892 struct rte_flow_item_ipv4 ipv4 = {
6894 .next_proto_id = IPPROTO_GRE,
6897 struct rte_flow_item_ipv6 ipv6 = {
6899 .proto = IPPROTO_GRE,
6902 struct rte_flow_item_gre gre = {
6903 .protocol = rte_cpu_to_be_16(ETHER_TYPE_MPLS_UNICAST),
6905 struct rte_flow_item_mpls mpls;
6909 ret = parse_vc(ctx, token, str, len, buf, size);
6912 /* Nothing else to do if there is no buffer. */
6915 if (!out->args.vc.actions_n)
6917 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
6918 /* Point to selected object. */
6919 ctx->object = out->args.vc.data;
6920 ctx->objmask = NULL;
6921 /* Copy the headers to the buffer. */
6922 action_decap_data = ctx->object;
6923 *action_decap_data = (struct action_raw_decap_data) {
6924 .conf = (struct rte_flow_action_raw_decap){
6925 .data = action_decap_data->data,
6929 header = action_decap_data->data;
6930 if (mplsogre_decap_conf.select_vlan)
6931 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
6932 else if (mplsogre_encap_conf.select_ipv4)
6933 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
6935 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
6936 memcpy(eth.dst.addr_bytes,
6937 mplsogre_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
6938 memcpy(eth.src.addr_bytes,
6939 mplsogre_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
6940 memcpy(header, ð, sizeof(eth));
6941 header += sizeof(eth);
6942 if (mplsogre_encap_conf.select_vlan) {
6943 if (mplsogre_encap_conf.select_ipv4)
6944 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
6946 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
6947 memcpy(header, &vlan, sizeof(vlan));
6948 header += sizeof(vlan);
6950 if (mplsogre_encap_conf.select_ipv4) {
6951 memcpy(header, &ipv4, sizeof(ipv4));
6952 header += sizeof(ipv4);
6954 memcpy(header, &ipv6, sizeof(ipv6));
6955 header += sizeof(ipv6);
6957 memcpy(header, &gre, sizeof(gre));
6958 header += sizeof(gre);
6959 memset(&mpls, 0, sizeof(mpls));
6960 memcpy(header, &mpls, sizeof(mpls));
6961 header += sizeof(mpls);
6962 action_decap_data->conf.size = header -
6963 action_decap_data->data;
6964 action->conf = &action_decap_data->conf;
6968 /** Parse MPLSOUDP encap action. */
6970 parse_vc_action_mplsoudp_encap(struct context *ctx, const struct token *token,
6971 const char *str, unsigned int len,
6972 void *buf, unsigned int size)
6974 struct buffer *out = buf;
6975 struct rte_flow_action *action;
6976 struct action_raw_encap_data *action_encap_data;
6977 struct rte_flow_item_eth eth = { .type = 0, };
6978 struct rte_flow_item_vlan vlan = {
6979 .tci = mplsoudp_encap_conf.vlan_tci,
6982 struct rte_flow_item_ipv4 ipv4 = {
6984 .src_addr = mplsoudp_encap_conf.ipv4_src,
6985 .dst_addr = mplsoudp_encap_conf.ipv4_dst,
6986 .next_proto_id = IPPROTO_UDP,
6987 .version_ihl = RTE_IPV4_VHL_DEF,
6988 .time_to_live = IPDEFTTL,
6991 struct rte_flow_item_ipv6 ipv6 = {
6993 .proto = IPPROTO_UDP,
6994 .hop_limits = IPDEFTTL,
6997 struct rte_flow_item_udp udp = {
6999 .src_port = mplsoudp_encap_conf.udp_src,
7000 .dst_port = mplsoudp_encap_conf.udp_dst,
7003 struct rte_flow_item_mpls mpls;
7007 ret = parse_vc(ctx, token, str, len, buf, size);
7010 /* Nothing else to do if there is no buffer. */
7013 if (!out->args.vc.actions_n)
7015 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
7016 /* Point to selected object. */
7017 ctx->object = out->args.vc.data;
7018 ctx->objmask = NULL;
7019 /* Copy the headers to the buffer. */
7020 action_encap_data = ctx->object;
7021 *action_encap_data = (struct action_raw_encap_data) {
7022 .conf = (struct rte_flow_action_raw_encap){
7023 .data = action_encap_data->data,
7028 header = action_encap_data->data;
7029 if (mplsoudp_encap_conf.select_vlan)
7030 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
7031 else if (mplsoudp_encap_conf.select_ipv4)
7032 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
7034 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
7035 memcpy(eth.dst.addr_bytes,
7036 mplsoudp_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
7037 memcpy(eth.src.addr_bytes,
7038 mplsoudp_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
7039 memcpy(header, ð, sizeof(eth));
7040 header += sizeof(eth);
7041 if (mplsoudp_encap_conf.select_vlan) {
7042 if (mplsoudp_encap_conf.select_ipv4)
7043 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
7045 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
7046 memcpy(header, &vlan, sizeof(vlan));
7047 header += sizeof(vlan);
7049 if (mplsoudp_encap_conf.select_ipv4) {
7050 memcpy(header, &ipv4, sizeof(ipv4));
7051 header += sizeof(ipv4);
7053 memcpy(&ipv6.hdr.src_addr,
7054 &mplsoudp_encap_conf.ipv6_src,
7055 sizeof(mplsoudp_encap_conf.ipv6_src));
7056 memcpy(&ipv6.hdr.dst_addr,
7057 &mplsoudp_encap_conf.ipv6_dst,
7058 sizeof(mplsoudp_encap_conf.ipv6_dst));
7059 memcpy(header, &ipv6, sizeof(ipv6));
7060 header += sizeof(ipv6);
7062 memcpy(header, &udp, sizeof(udp));
7063 header += sizeof(udp);
7064 memcpy(mpls.label_tc_s, mplsoudp_encap_conf.label,
7065 RTE_DIM(mplsoudp_encap_conf.label));
7066 mpls.label_tc_s[2] |= 0x1;
7067 memcpy(header, &mpls, sizeof(mpls));
7068 header += sizeof(mpls);
7069 action_encap_data->conf.size = header -
7070 action_encap_data->data;
7071 action->conf = &action_encap_data->conf;
7075 /** Parse MPLSOUDP decap action. */
7077 parse_vc_action_mplsoudp_decap(struct context *ctx, const struct token *token,
7078 const char *str, unsigned int len,
7079 void *buf, unsigned int size)
7081 struct buffer *out = buf;
7082 struct rte_flow_action *action;
7083 struct action_raw_decap_data *action_decap_data;
7084 struct rte_flow_item_eth eth = { .type = 0, };
7085 struct rte_flow_item_vlan vlan = {.tci = 0};
7086 struct rte_flow_item_ipv4 ipv4 = {
7088 .next_proto_id = IPPROTO_UDP,
7091 struct rte_flow_item_ipv6 ipv6 = {
7093 .proto = IPPROTO_UDP,
7096 struct rte_flow_item_udp udp = {
7098 .dst_port = rte_cpu_to_be_16(6635),
7101 struct rte_flow_item_mpls mpls;
7105 ret = parse_vc(ctx, token, str, len, buf, size);
7108 /* Nothing else to do if there is no buffer. */
7111 if (!out->args.vc.actions_n)
7113 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
7114 /* Point to selected object. */
7115 ctx->object = out->args.vc.data;
7116 ctx->objmask = NULL;
7117 /* Copy the headers to the buffer. */
7118 action_decap_data = ctx->object;
7119 *action_decap_data = (struct action_raw_decap_data) {
7120 .conf = (struct rte_flow_action_raw_decap){
7121 .data = action_decap_data->data,
7125 header = action_decap_data->data;
7126 if (mplsoudp_decap_conf.select_vlan)
7127 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
7128 else if (mplsoudp_encap_conf.select_ipv4)
7129 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
7131 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
7132 memcpy(eth.dst.addr_bytes,
7133 mplsoudp_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
7134 memcpy(eth.src.addr_bytes,
7135 mplsoudp_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
7136 memcpy(header, ð, sizeof(eth));
7137 header += sizeof(eth);
7138 if (mplsoudp_encap_conf.select_vlan) {
7139 if (mplsoudp_encap_conf.select_ipv4)
7140 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
7142 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
7143 memcpy(header, &vlan, sizeof(vlan));
7144 header += sizeof(vlan);
7146 if (mplsoudp_encap_conf.select_ipv4) {
7147 memcpy(header, &ipv4, sizeof(ipv4));
7148 header += sizeof(ipv4);
7150 memcpy(header, &ipv6, sizeof(ipv6));
7151 header += sizeof(ipv6);
7153 memcpy(header, &udp, sizeof(udp));
7154 header += sizeof(udp);
7155 memset(&mpls, 0, sizeof(mpls));
7156 memcpy(header, &mpls, sizeof(mpls));
7157 header += sizeof(mpls);
7158 action_decap_data->conf.size = header -
7159 action_decap_data->data;
7160 action->conf = &action_decap_data->conf;
7165 parse_vc_action_raw_decap_index(struct context *ctx, const struct token *token,
7166 const char *str, unsigned int len, void *buf,
7169 struct action_raw_decap_data *action_raw_decap_data;
7170 struct rte_flow_action *action;
7171 const struct arg *arg;
7172 struct buffer *out = buf;
7176 RTE_SET_USED(token);
7179 arg = ARGS_ENTRY_ARB_BOUNDED
7180 (offsetof(struct action_raw_decap_data, idx),
7181 sizeof(((struct action_raw_decap_data *)0)->idx),
7182 0, RAW_ENCAP_CONFS_MAX_NUM - 1);
7183 if (push_args(ctx, arg))
7185 ret = parse_int(ctx, token, str, len, NULL, 0);
7192 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
7193 action_raw_decap_data = ctx->object;
7194 idx = action_raw_decap_data->idx;
7195 action_raw_decap_data->conf.data = raw_decap_confs[idx].data;
7196 action_raw_decap_data->conf.size = raw_decap_confs[idx].size;
7197 action->conf = &action_raw_decap_data->conf;
7203 parse_vc_action_raw_encap_index(struct context *ctx, const struct token *token,
7204 const char *str, unsigned int len, void *buf,
7207 struct action_raw_encap_data *action_raw_encap_data;
7208 struct rte_flow_action *action;
7209 const struct arg *arg;
7210 struct buffer *out = buf;
7214 RTE_SET_USED(token);
7217 if (ctx->curr != ACTION_RAW_ENCAP_INDEX_VALUE)
7219 arg = ARGS_ENTRY_ARB_BOUNDED
7220 (offsetof(struct action_raw_encap_data, idx),
7221 sizeof(((struct action_raw_encap_data *)0)->idx),
7222 0, RAW_ENCAP_CONFS_MAX_NUM - 1);
7223 if (push_args(ctx, arg))
7225 ret = parse_int(ctx, token, str, len, NULL, 0);
7232 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
7233 action_raw_encap_data = ctx->object;
7234 idx = action_raw_encap_data->idx;
7235 action_raw_encap_data->conf.data = raw_encap_confs[idx].data;
7236 action_raw_encap_data->conf.size = raw_encap_confs[idx].size;
7237 action_raw_encap_data->conf.preserve = NULL;
7238 action->conf = &action_raw_encap_data->conf;
7243 parse_vc_action_raw_encap(struct context *ctx, const struct token *token,
7244 const char *str, unsigned int len, void *buf,
7247 struct buffer *out = buf;
7248 struct rte_flow_action *action;
7249 struct action_raw_encap_data *action_raw_encap_data = NULL;
7252 ret = parse_vc(ctx, token, str, len, buf, size);
7255 /* Nothing else to do if there is no buffer. */
7258 if (!out->args.vc.actions_n)
7260 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
7261 /* Point to selected object. */
7262 ctx->object = out->args.vc.data;
7263 ctx->objmask = NULL;
7264 /* Copy the headers to the buffer. */
7265 action_raw_encap_data = ctx->object;
7266 action_raw_encap_data->conf.data = raw_encap_confs[0].data;
7267 action_raw_encap_data->conf.preserve = NULL;
7268 action_raw_encap_data->conf.size = raw_encap_confs[0].size;
7269 action->conf = &action_raw_encap_data->conf;
7274 parse_vc_action_raw_decap(struct context *ctx, const struct token *token,
7275 const char *str, unsigned int len, void *buf,
7278 struct buffer *out = buf;
7279 struct rte_flow_action *action;
7280 struct action_raw_decap_data *action_raw_decap_data = NULL;
7283 ret = parse_vc(ctx, token, str, len, buf, size);
7286 /* Nothing else to do if there is no buffer. */
7289 if (!out->args.vc.actions_n)
7291 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
7292 /* Point to selected object. */
7293 ctx->object = out->args.vc.data;
7294 ctx->objmask = NULL;
7295 /* Copy the headers to the buffer. */
7296 action_raw_decap_data = ctx->object;
7297 action_raw_decap_data->conf.data = raw_decap_confs[0].data;
7298 action_raw_decap_data->conf.size = raw_decap_confs[0].size;
7299 action->conf = &action_raw_decap_data->conf;
7304 parse_vc_action_set_meta(struct context *ctx, const struct token *token,
7305 const char *str, unsigned int len, void *buf,
7310 ret = parse_vc(ctx, token, str, len, buf, size);
7313 ret = rte_flow_dynf_metadata_register();
7320 parse_vc_action_sample(struct context *ctx, const struct token *token,
7321 const char *str, unsigned int len, void *buf,
7324 struct buffer *out = buf;
7325 struct rte_flow_action *action;
7326 struct action_sample_data *action_sample_data = NULL;
7327 static struct rte_flow_action end_action = {
7328 RTE_FLOW_ACTION_TYPE_END, 0
7332 ret = parse_vc(ctx, token, str, len, buf, size);
7335 /* Nothing else to do if there is no buffer. */
7338 if (!out->args.vc.actions_n)
7340 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
7341 /* Point to selected object. */
7342 ctx->object = out->args.vc.data;
7343 ctx->objmask = NULL;
7344 /* Copy the headers to the buffer. */
7345 action_sample_data = ctx->object;
7346 action_sample_data->conf.actions = &end_action;
7347 action->conf = &action_sample_data->conf;
7352 parse_vc_action_sample_index(struct context *ctx, const struct token *token,
7353 const char *str, unsigned int len, void *buf,
7356 struct action_sample_data *action_sample_data;
7357 struct rte_flow_action *action;
7358 const struct arg *arg;
7359 struct buffer *out = buf;
7363 RTE_SET_USED(token);
7366 if (ctx->curr != ACTION_SAMPLE_INDEX_VALUE)
7368 arg = ARGS_ENTRY_ARB_BOUNDED
7369 (offsetof(struct action_sample_data, idx),
7370 sizeof(((struct action_sample_data *)0)->idx),
7371 0, RAW_SAMPLE_CONFS_MAX_NUM - 1);
7372 if (push_args(ctx, arg))
7374 ret = parse_int(ctx, token, str, len, NULL, 0);
7381 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
7382 action_sample_data = ctx->object;
7383 idx = action_sample_data->idx;
7384 action_sample_data->conf.actions = raw_sample_confs[idx].data;
7385 action->conf = &action_sample_data->conf;
7389 /** Parse operation for modify_field command. */
7391 parse_vc_modify_field_op(struct context *ctx, const struct token *token,
7392 const char *str, unsigned int len, void *buf,
7395 struct rte_flow_action_modify_field *action_modify_field;
7401 if (ctx->curr != ACTION_MODIFY_FIELD_OP_VALUE)
7403 for (i = 0; modify_field_ops[i]; ++i)
7404 if (!strcmp_partial(modify_field_ops[i], str, len))
7406 if (!modify_field_ops[i])
7410 action_modify_field = ctx->object;
7411 action_modify_field->operation = (enum rte_flow_modify_op)i;
7415 /** Parse id for modify_field command. */
7417 parse_vc_modify_field_id(struct context *ctx, const struct token *token,
7418 const char *str, unsigned int len, void *buf,
7421 struct rte_flow_action_modify_field *action_modify_field;
7427 if (ctx->curr != ACTION_MODIFY_FIELD_DST_TYPE_VALUE &&
7428 ctx->curr != ACTION_MODIFY_FIELD_SRC_TYPE_VALUE)
7430 for (i = 0; modify_field_ids[i]; ++i)
7431 if (!strcmp_partial(modify_field_ids[i], str, len))
7433 if (!modify_field_ids[i])
7437 action_modify_field = ctx->object;
7438 if (ctx->curr == ACTION_MODIFY_FIELD_DST_TYPE_VALUE)
7439 action_modify_field->dst.field = (enum rte_flow_field_id)i;
7441 action_modify_field->src.field = (enum rte_flow_field_id)i;
7445 /** Parse the conntrack update, not a rte_flow_action. */
7447 parse_vc_action_conntrack_update(struct context *ctx, const struct token *token,
7448 const char *str, unsigned int len, void *buf,
7451 struct buffer *out = buf;
7452 struct rte_flow_modify_conntrack *ct_modify = NULL;
7455 if (ctx->curr != ACTION_CONNTRACK_UPDATE_CTX &&
7456 ctx->curr != ACTION_CONNTRACK_UPDATE_DIR)
7458 /* Token name must match. */
7459 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
7461 /* Nothing else to do if there is no buffer. */
7464 ct_modify = (struct rte_flow_modify_conntrack *)out->args.vc.data;
7465 if (ctx->curr == ACTION_CONNTRACK_UPDATE_DIR) {
7466 ct_modify->new_ct.is_original_dir =
7467 conntrack_context.is_original_dir;
7468 ct_modify->direction = 1;
7472 old_dir = ct_modify->new_ct.is_original_dir;
7473 memcpy(&ct_modify->new_ct, &conntrack_context,
7474 sizeof(conntrack_context));
7475 ct_modify->new_ct.is_original_dir = old_dir;
7476 ct_modify->state = 1;
7481 /** Parse tokens for destroy command. */
7483 parse_destroy(struct context *ctx, const struct token *token,
7484 const char *str, unsigned int len,
7485 void *buf, unsigned int size)
7487 struct buffer *out = buf;
7489 /* Token name must match. */
7490 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
7492 /* Nothing else to do if there is no buffer. */
7495 if (!out->command) {
7496 if (ctx->curr != DESTROY)
7498 if (sizeof(*out) > size)
7500 out->command = ctx->curr;
7503 ctx->objmask = NULL;
7504 out->args.destroy.rule =
7505 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
7509 if (((uint8_t *)(out->args.destroy.rule + out->args.destroy.rule_n) +
7510 sizeof(*out->args.destroy.rule)) > (uint8_t *)out + size)
7513 ctx->object = out->args.destroy.rule + out->args.destroy.rule_n++;
7514 ctx->objmask = NULL;
7518 /** Parse tokens for flush command. */
7520 parse_flush(struct context *ctx, const struct token *token,
7521 const char *str, unsigned int len,
7522 void *buf, unsigned int size)
7524 struct buffer *out = buf;
7526 /* Token name must match. */
7527 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
7529 /* Nothing else to do if there is no buffer. */
7532 if (!out->command) {
7533 if (ctx->curr != FLUSH)
7535 if (sizeof(*out) > size)
7537 out->command = ctx->curr;
7540 ctx->objmask = NULL;
7545 /** Parse tokens for dump command. */
7547 parse_dump(struct context *ctx, const struct token *token,
7548 const char *str, unsigned int len,
7549 void *buf, unsigned int size)
7551 struct buffer *out = buf;
7553 /* Token name must match. */
7554 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
7556 /* Nothing else to do if there is no buffer. */
7559 if (!out->command) {
7560 if (ctx->curr != DUMP)
7562 if (sizeof(*out) > size)
7564 out->command = ctx->curr;
7567 ctx->objmask = NULL;
7570 switch (ctx->curr) {
7573 out->args.dump.mode = (ctx->curr == DUMP_ALL) ? true : false;
7574 out->command = ctx->curr;
7577 ctx->objmask = NULL;
7584 /** Parse tokens for query command. */
7586 parse_query(struct context *ctx, const struct token *token,
7587 const char *str, unsigned int len,
7588 void *buf, unsigned int size)
7590 struct buffer *out = buf;
7592 /* Token name must match. */
7593 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
7595 /* Nothing else to do if there is no buffer. */
7598 if (!out->command) {
7599 if (ctx->curr != QUERY)
7601 if (sizeof(*out) > size)
7603 out->command = ctx->curr;
7606 ctx->objmask = NULL;
7611 /** Parse action names. */
7613 parse_action(struct context *ctx, const struct token *token,
7614 const char *str, unsigned int len,
7615 void *buf, unsigned int size)
7617 struct buffer *out = buf;
7618 const struct arg *arg = pop_args(ctx);
7622 /* Argument is expected. */
7625 /* Parse action name. */
7626 for (i = 0; next_action[i]; ++i) {
7627 const struct parse_action_priv *priv;
7629 token = &token_list[next_action[i]];
7630 if (strcmp_partial(token->name, str, len))
7636 memcpy((uint8_t *)ctx->object + arg->offset,
7642 push_args(ctx, arg);
7646 /** Parse tokens for list command. */
7648 parse_list(struct context *ctx, const struct token *token,
7649 const char *str, unsigned int len,
7650 void *buf, unsigned int size)
7652 struct buffer *out = buf;
7654 /* Token name must match. */
7655 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
7657 /* Nothing else to do if there is no buffer. */
7660 if (!out->command) {
7661 if (ctx->curr != LIST)
7663 if (sizeof(*out) > size)
7665 out->command = ctx->curr;
7668 ctx->objmask = NULL;
7669 out->args.list.group =
7670 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
7674 if (((uint8_t *)(out->args.list.group + out->args.list.group_n) +
7675 sizeof(*out->args.list.group)) > (uint8_t *)out + size)
7678 ctx->object = out->args.list.group + out->args.list.group_n++;
7679 ctx->objmask = NULL;
7683 /** Parse tokens for list all aged flows command. */
7685 parse_aged(struct context *ctx, const struct token *token,
7686 const char *str, unsigned int len,
7687 void *buf, unsigned int size)
7689 struct buffer *out = buf;
7691 /* Token name must match. */
7692 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
7694 /* Nothing else to do if there is no buffer. */
7697 if (!out->command) {
7698 if (ctx->curr != AGED)
7700 if (sizeof(*out) > size)
7702 out->command = ctx->curr;
7705 ctx->objmask = NULL;
7707 if (ctx->curr == AGED_DESTROY)
7708 out->args.aged.destroy = 1;
7712 /** Parse tokens for isolate command. */
7714 parse_isolate(struct context *ctx, const struct token *token,
7715 const char *str, unsigned int len,
7716 void *buf, unsigned int size)
7718 struct buffer *out = buf;
7720 /* Token name must match. */
7721 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
7723 /* Nothing else to do if there is no buffer. */
7726 if (!out->command) {
7727 if (ctx->curr != ISOLATE)
7729 if (sizeof(*out) > size)
7731 out->command = ctx->curr;
7734 ctx->objmask = NULL;
7740 parse_flex(struct context *ctx, const struct token *token,
7741 const char *str, unsigned int len,
7742 void *buf, unsigned int size)
7744 struct buffer *out = buf;
7746 /* Token name must match. */
7747 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
7749 /* Nothing else to do if there is no buffer. */
7752 if (out->command == ZERO) {
7753 if (ctx->curr != FLEX)
7755 if (sizeof(*out) > size)
7757 out->command = ctx->curr;
7760 ctx->objmask = NULL;
7762 switch (ctx->curr) {
7765 case FLEX_ITEM_INIT:
7766 case FLEX_ITEM_CREATE:
7767 case FLEX_ITEM_DESTROY:
7768 out->command = ctx->curr;
7777 parse_tunnel(struct context *ctx, const struct token *token,
7778 const char *str, unsigned int len,
7779 void *buf, unsigned int size)
7781 struct buffer *out = buf;
7783 /* Token name must match. */
7784 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
7786 /* Nothing else to do if there is no buffer. */
7789 if (!out->command) {
7790 if (ctx->curr != TUNNEL)
7792 if (sizeof(*out) > size)
7794 out->command = ctx->curr;
7797 ctx->objmask = NULL;
7799 switch (ctx->curr) {
7803 case TUNNEL_DESTROY:
7805 out->command = ctx->curr;
7807 case TUNNEL_CREATE_TYPE:
7808 case TUNNEL_DESTROY_ID:
7809 ctx->object = &out->args.vc.tunnel_ops;
7818 * Parse signed/unsigned integers 8 to 64-bit long.
7820 * Last argument (ctx->args) is retrieved to determine integer type and
7824 parse_int(struct context *ctx, const struct token *token,
7825 const char *str, unsigned int len,
7826 void *buf, unsigned int size)
7828 const struct arg *arg = pop_args(ctx);
7833 /* Argument is expected. */
7838 (uintmax_t)strtoimax(str, &end, 0) :
7839 strtoumax(str, &end, 0);
7840 if (errno || (size_t)(end - str) != len)
7843 ((arg->sign && ((intmax_t)u < (intmax_t)arg->min ||
7844 (intmax_t)u > (intmax_t)arg->max)) ||
7845 (!arg->sign && (u < arg->min || u > arg->max))))
7850 if (!arg_entry_bf_fill(ctx->object, u, arg) ||
7851 !arg_entry_bf_fill(ctx->objmask, -1, arg))
7855 buf = (uint8_t *)ctx->object + arg->offset;
7857 if (u > RTE_LEN2MASK(size * CHAR_BIT, uint64_t))
7861 case sizeof(uint8_t):
7862 *(uint8_t *)buf = u;
7864 case sizeof(uint16_t):
7865 *(uint16_t *)buf = arg->hton ? rte_cpu_to_be_16(u) : u;
7867 case sizeof(uint8_t [3]):
7868 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
7870 ((uint8_t *)buf)[0] = u;
7871 ((uint8_t *)buf)[1] = u >> 8;
7872 ((uint8_t *)buf)[2] = u >> 16;
7876 ((uint8_t *)buf)[0] = u >> 16;
7877 ((uint8_t *)buf)[1] = u >> 8;
7878 ((uint8_t *)buf)[2] = u;
7880 case sizeof(uint32_t):
7881 *(uint32_t *)buf = arg->hton ? rte_cpu_to_be_32(u) : u;
7883 case sizeof(uint64_t):
7884 *(uint64_t *)buf = arg->hton ? rte_cpu_to_be_64(u) : u;
7889 if (ctx->objmask && buf != (uint8_t *)ctx->objmask + arg->offset) {
7891 buf = (uint8_t *)ctx->objmask + arg->offset;
7896 push_args(ctx, arg);
7903 * Three arguments (ctx->args) are retrieved from the stack to store data,
7904 * its actual length and address (in that order).
7907 parse_string(struct context *ctx, const struct token *token,
7908 const char *str, unsigned int len,
7909 void *buf, unsigned int size)
7911 const struct arg *arg_data = pop_args(ctx);
7912 const struct arg *arg_len = pop_args(ctx);
7913 const struct arg *arg_addr = pop_args(ctx);
7914 char tmp[16]; /* Ought to be enough. */
7917 /* Arguments are expected. */
7921 push_args(ctx, arg_data);
7925 push_args(ctx, arg_len);
7926 push_args(ctx, arg_data);
7929 size = arg_data->size;
7930 /* Bit-mask fill is not supported. */
7931 if (arg_data->mask || size < len)
7935 /* Let parse_int() fill length information first. */
7936 ret = snprintf(tmp, sizeof(tmp), "%u", len);
7939 push_args(ctx, arg_len);
7940 ret = parse_int(ctx, token, tmp, ret, NULL, 0);
7945 buf = (uint8_t *)ctx->object + arg_data->offset;
7946 /* Output buffer is not necessarily NUL-terminated. */
7947 memcpy(buf, str, len);
7948 memset((uint8_t *)buf + len, 0x00, size - len);
7950 memset((uint8_t *)ctx->objmask + arg_data->offset, 0xff, len);
7951 /* Save address if requested. */
7952 if (arg_addr->size) {
7953 memcpy((uint8_t *)ctx->object + arg_addr->offset,
7955 (uint8_t *)ctx->object + arg_data->offset
7959 memcpy((uint8_t *)ctx->objmask + arg_addr->offset,
7961 (uint8_t *)ctx->objmask + arg_data->offset
7967 push_args(ctx, arg_addr);
7968 push_args(ctx, arg_len);
7969 push_args(ctx, arg_data);
7974 parse_hex_string(const char *src, uint8_t *dst, uint32_t *size)
7976 const uint8_t *head = dst;
7979 /* Check input parameters */
7980 if ((src == NULL) ||
7988 /* Convert chars to bytes */
7990 char tmp[3], *end = tmp;
7991 uint32_t read_lim = left & 1 ? 1 : 2;
7993 snprintf(tmp, read_lim + 1, "%s", src);
7994 *dst = strtoul(tmp, &end, 16);
7997 *size = (uint32_t)(dst - head);
8005 *size = (uint32_t)(dst - head);
8010 parse_hex(struct context *ctx, const struct token *token,
8011 const char *str, unsigned int len,
8012 void *buf, unsigned int size)
8014 const struct arg *arg_data = pop_args(ctx);
8015 const struct arg *arg_len = pop_args(ctx);
8016 const struct arg *arg_addr = pop_args(ctx);
8017 char tmp[16]; /* Ought to be enough. */
8019 unsigned int hexlen = len;
8020 unsigned int length = 256;
8021 uint8_t hex_tmp[length];
8023 /* Arguments are expected. */
8027 push_args(ctx, arg_data);
8031 push_args(ctx, arg_len);
8032 push_args(ctx, arg_data);
8035 size = arg_data->size;
8036 /* Bit-mask fill is not supported. */
8042 /* translate bytes string to array. */
8043 if (str[0] == '0' && ((str[1] == 'x') ||
8048 if (hexlen > length)
8050 ret = parse_hex_string(str, hex_tmp, &hexlen);
8053 /* Check the converted binary fits into data buffer. */
8056 /* Let parse_int() fill length information first. */
8057 ret = snprintf(tmp, sizeof(tmp), "%u", hexlen);
8060 /* Save length if requested. */
8061 if (arg_len->size) {
8062 push_args(ctx, arg_len);
8063 ret = parse_int(ctx, token, tmp, ret, NULL, 0);
8069 buf = (uint8_t *)ctx->object + arg_data->offset;
8070 /* Output buffer is not necessarily NUL-terminated. */
8071 memcpy(buf, hex_tmp, hexlen);
8072 memset((uint8_t *)buf + hexlen, 0x00, size - hexlen);
8074 memset((uint8_t *)ctx->objmask + arg_data->offset,
8076 /* Save address if requested. */
8077 if (arg_addr->size) {
8078 memcpy((uint8_t *)ctx->object + arg_addr->offset,
8080 (uint8_t *)ctx->object + arg_data->offset
8084 memcpy((uint8_t *)ctx->objmask + arg_addr->offset,
8086 (uint8_t *)ctx->objmask + arg_data->offset
8092 push_args(ctx, arg_addr);
8093 push_args(ctx, arg_len);
8094 push_args(ctx, arg_data);
8100 * Parse a zero-ended string.
8103 parse_string0(struct context *ctx, const struct token *token __rte_unused,
8104 const char *str, unsigned int len,
8105 void *buf, unsigned int size)
8107 const struct arg *arg_data = pop_args(ctx);
8109 /* Arguments are expected. */
8112 size = arg_data->size;
8113 /* Bit-mask fill is not supported. */
8114 if (arg_data->mask || size < len + 1)
8118 buf = (uint8_t *)ctx->object + arg_data->offset;
8119 strncpy(buf, str, len);
8121 memset((uint8_t *)ctx->objmask + arg_data->offset, 0xff, len);
8124 push_args(ctx, arg_data);
8129 * Parse a MAC address.
8131 * Last argument (ctx->args) is retrieved to determine storage size and
8135 parse_mac_addr(struct context *ctx, const struct token *token,
8136 const char *str, unsigned int len,
8137 void *buf, unsigned int size)
8139 const struct arg *arg = pop_args(ctx);
8140 struct rte_ether_addr tmp;
8144 /* Argument is expected. */
8148 /* Bit-mask fill is not supported. */
8149 if (arg->mask || size != sizeof(tmp))
8151 /* Only network endian is supported. */
8154 ret = cmdline_parse_etheraddr(NULL, str, &tmp, size);
8155 if (ret < 0 || (unsigned int)ret != len)
8159 buf = (uint8_t *)ctx->object + arg->offset;
8160 memcpy(buf, &tmp, size);
8162 memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
8165 push_args(ctx, arg);
8170 * Parse an IPv4 address.
8172 * Last argument (ctx->args) is retrieved to determine storage size and
8176 parse_ipv4_addr(struct context *ctx, const struct token *token,
8177 const char *str, unsigned int len,
8178 void *buf, unsigned int size)
8180 const struct arg *arg = pop_args(ctx);
8185 /* Argument is expected. */
8189 /* Bit-mask fill is not supported. */
8190 if (arg->mask || size != sizeof(tmp))
8192 /* Only network endian is supported. */
8195 memcpy(str2, str, len);
8197 ret = inet_pton(AF_INET, str2, &tmp);
8199 /* Attempt integer parsing. */
8200 push_args(ctx, arg);
8201 return parse_int(ctx, token, str, len, buf, size);
8205 buf = (uint8_t *)ctx->object + arg->offset;
8206 memcpy(buf, &tmp, size);
8208 memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
8211 push_args(ctx, arg);
8216 * Parse an IPv6 address.
8218 * Last argument (ctx->args) is retrieved to determine storage size and
8222 parse_ipv6_addr(struct context *ctx, const struct token *token,
8223 const char *str, unsigned int len,
8224 void *buf, unsigned int size)
8226 const struct arg *arg = pop_args(ctx);
8228 struct in6_addr tmp;
8232 /* Argument is expected. */
8236 /* Bit-mask fill is not supported. */
8237 if (arg->mask || size != sizeof(tmp))
8239 /* Only network endian is supported. */
8242 memcpy(str2, str, len);
8244 ret = inet_pton(AF_INET6, str2, &tmp);
8249 buf = (uint8_t *)ctx->object + arg->offset;
8250 memcpy(buf, &tmp, size);
8252 memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
8255 push_args(ctx, arg);
8259 /** Boolean values (even indices stand for false). */
8260 static const char *const boolean_name[] = {
8270 * Parse a boolean value.
8272 * Last argument (ctx->args) is retrieved to determine storage size and
8276 parse_boolean(struct context *ctx, const struct token *token,
8277 const char *str, unsigned int len,
8278 void *buf, unsigned int size)
8280 const struct arg *arg = pop_args(ctx);
8284 /* Argument is expected. */
8287 for (i = 0; boolean_name[i]; ++i)
8288 if (!strcmp_partial(boolean_name[i], str, len))
8290 /* Process token as integer. */
8291 if (boolean_name[i])
8292 str = i & 1 ? "1" : "0";
8293 push_args(ctx, arg);
8294 ret = parse_int(ctx, token, str, strlen(str), buf, size);
8295 return ret > 0 ? (int)len : ret;
8298 /** Parse port and update context. */
8300 parse_port(struct context *ctx, const struct token *token,
8301 const char *str, unsigned int len,
8302 void *buf, unsigned int size)
8304 struct buffer *out = &(struct buffer){ .port = 0 };
8312 ctx->objmask = NULL;
8313 size = sizeof(*out);
8315 ret = parse_int(ctx, token, str, len, out, size);
8317 ctx->port = out->port;
8324 parse_ia_id2ptr(struct context *ctx, const struct token *token,
8325 const char *str, unsigned int len,
8326 void *buf, unsigned int size)
8328 struct rte_flow_action *action = ctx->object;
8336 ctx->objmask = NULL;
8337 ret = parse_int(ctx, token, str, len, ctx->object, sizeof(id));
8338 ctx->object = action;
8339 if (ret != (int)len)
8341 /* set indirect action */
8343 action->conf = port_action_handle_get_by_id(ctx->port, id);
8344 ret = (action->conf) ? ret : -1;
8349 /** Parse set command, initialize output buffer for subsequent tokens. */
8351 parse_set_raw_encap_decap(struct context *ctx, const struct token *token,
8352 const char *str, unsigned int len,
8353 void *buf, unsigned int size)
8355 struct buffer *out = buf;
8357 /* Token name must match. */
8358 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8360 /* Nothing else to do if there is no buffer. */
8363 /* Make sure buffer is large enough. */
8364 if (size < sizeof(*out))
8367 ctx->objmask = NULL;
8371 out->command = ctx->curr;
8372 /* For encap/decap we need is pattern */
8373 out->args.vc.pattern = (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8378 /** Parse set command, initialize output buffer for subsequent tokens. */
8380 parse_set_sample_action(struct context *ctx, const struct token *token,
8381 const char *str, unsigned int len,
8382 void *buf, unsigned int size)
8384 struct buffer *out = buf;
8386 /* Token name must match. */
8387 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8389 /* Nothing else to do if there is no buffer. */
8392 /* Make sure buffer is large enough. */
8393 if (size < sizeof(*out))
8396 ctx->objmask = NULL;
8400 out->command = ctx->curr;
8401 /* For sampler we need is actions */
8402 out->args.vc.actions = (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8408 * Parse set raw_encap/raw_decap command,
8409 * initialize output buffer for subsequent tokens.
8412 parse_set_init(struct context *ctx, const struct token *token,
8413 const char *str, unsigned int len,
8414 void *buf, unsigned int size)
8416 struct buffer *out = buf;
8418 /* Token name must match. */
8419 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8421 /* Nothing else to do if there is no buffer. */
8424 /* Make sure buffer is large enough. */
8425 if (size < sizeof(*out))
8427 /* Initialize buffer. */
8428 memset(out, 0x00, sizeof(*out));
8429 memset((uint8_t *)out + sizeof(*out), 0x22, size - sizeof(*out));
8432 ctx->objmask = NULL;
8433 if (!out->command) {
8434 if (ctx->curr != SET)
8436 if (sizeof(*out) > size)
8438 out->command = ctx->curr;
8439 out->args.vc.data = (uint8_t *)out + size;
8440 ctx->object = (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8447 * Replace testpmd handles in a flex flow item with real values.
8450 parse_flex_handle(struct context *ctx, const struct token *token,
8451 const char *str, unsigned int len,
8452 void *buf, unsigned int size)
8454 struct rte_flow_item_flex *spec, *mask;
8455 const struct rte_flow_item_flex *src_spec, *src_mask;
8456 const struct arg *arg = pop_args(ctx);
8462 printf("Bad environment\n");
8465 offset = arg->offset;
8466 push_args(ctx, arg);
8467 ret = parse_int(ctx, token, str, len, buf, size);
8468 if (ret <= 0 || !ctx->object)
8470 if (ctx->port >= RTE_MAX_ETHPORTS) {
8471 printf("Bad port\n");
8474 if (offset == offsetof(struct rte_flow_item_flex, handle)) {
8475 const struct flex_item *fp;
8476 struct rte_flow_item_flex *item_flex = ctx->object;
8477 handle = (uint16_t)(uintptr_t)item_flex->handle;
8478 if (handle >= FLEX_MAX_PARSERS_NUM) {
8479 printf("Bad flex item handle\n");
8482 fp = flex_items[ctx->port][handle];
8484 printf("Bad flex item handle\n");
8487 item_flex->handle = fp->flex_handle;
8488 } else if (offset == offsetof(struct rte_flow_item_flex, pattern)) {
8489 handle = (uint16_t)(uintptr_t)
8490 ((struct rte_flow_item_flex *)ctx->object)->pattern;
8491 if (handle >= FLEX_MAX_PATTERNS_NUM) {
8492 printf("Bad pattern handle\n");
8495 src_spec = &flex_patterns[handle].spec;
8496 src_mask = &flex_patterns[handle].mask;
8498 mask = spec + 2; /* spec, last, mask */
8499 /* fill flow rule spec and mask parameters */
8500 spec->length = src_spec->length;
8501 spec->pattern = src_spec->pattern;
8502 mask->length = src_mask->length;
8503 mask->pattern = src_mask->pattern;
8505 printf("Bad arguments - unknown flex item offset\n");
8511 /** No completion. */
8513 comp_none(struct context *ctx, const struct token *token,
8514 unsigned int ent, char *buf, unsigned int size)
8524 /** Complete boolean values. */
8526 comp_boolean(struct context *ctx, const struct token *token,
8527 unsigned int ent, char *buf, unsigned int size)
8533 for (i = 0; boolean_name[i]; ++i)
8534 if (buf && i == ent)
8535 return strlcpy(buf, boolean_name[i], size);
8541 /** Complete action names. */
8543 comp_action(struct context *ctx, const struct token *token,
8544 unsigned int ent, char *buf, unsigned int size)
8550 for (i = 0; next_action[i]; ++i)
8551 if (buf && i == ent)
8552 return strlcpy(buf, token_list[next_action[i]].name,
8559 /** Complete available ports. */
8561 comp_port(struct context *ctx, const struct token *token,
8562 unsigned int ent, char *buf, unsigned int size)
8569 RTE_ETH_FOREACH_DEV(p) {
8570 if (buf && i == ent)
8571 return snprintf(buf, size, "%u", p);
8579 /** Complete available rule IDs. */
8581 comp_rule_id(struct context *ctx, const struct token *token,
8582 unsigned int ent, char *buf, unsigned int size)
8585 struct rte_port *port;
8586 struct port_flow *pf;
8589 if (port_id_is_invalid(ctx->port, DISABLED_WARN) ||
8590 ctx->port == (portid_t)RTE_PORT_ALL)
8592 port = &ports[ctx->port];
8593 for (pf = port->flow_list; pf != NULL; pf = pf->next) {
8594 if (buf && i == ent)
8595 return snprintf(buf, size, "%u", pf->id);
8603 /** Complete type field for RSS action. */
8605 comp_vc_action_rss_type(struct context *ctx, const struct token *token,
8606 unsigned int ent, char *buf, unsigned int size)
8612 for (i = 0; rss_type_table[i].str; ++i)
8617 return strlcpy(buf, rss_type_table[ent].str, size);
8619 return snprintf(buf, size, "end");
8623 /** Complete queue field for RSS action. */
8625 comp_vc_action_rss_queue(struct context *ctx, const struct token *token,
8626 unsigned int ent, char *buf, unsigned int size)
8633 return snprintf(buf, size, "%u", ent);
8635 return snprintf(buf, size, "end");
8639 /** Complete index number for set raw_encap/raw_decap commands. */
8641 comp_set_raw_index(struct context *ctx, const struct token *token,
8642 unsigned int ent, char *buf, unsigned int size)
8648 RTE_SET_USED(token);
8649 for (idx = 0; idx < RAW_ENCAP_CONFS_MAX_NUM; ++idx) {
8650 if (buf && idx == ent)
8651 return snprintf(buf, size, "%u", idx);
8657 /** Complete index number for set raw_encap/raw_decap commands. */
8659 comp_set_sample_index(struct context *ctx, const struct token *token,
8660 unsigned int ent, char *buf, unsigned int size)
8666 RTE_SET_USED(token);
8667 for (idx = 0; idx < RAW_SAMPLE_CONFS_MAX_NUM; ++idx) {
8668 if (buf && idx == ent)
8669 return snprintf(buf, size, "%u", idx);
8675 /** Complete operation for modify_field command. */
8677 comp_set_modify_field_op(struct context *ctx, const struct token *token,
8678 unsigned int ent, char *buf, unsigned int size)
8681 RTE_SET_USED(token);
8683 return RTE_DIM(modify_field_ops);
8684 if (ent < RTE_DIM(modify_field_ops) - 1)
8685 return strlcpy(buf, modify_field_ops[ent], size);
8689 /** Complete field id for modify_field command. */
8691 comp_set_modify_field_id(struct context *ctx, const struct token *token,
8692 unsigned int ent, char *buf, unsigned int size)
8696 RTE_SET_USED(token);
8698 return RTE_DIM(modify_field_ids);
8699 if (ent >= RTE_DIM(modify_field_ids) - 1)
8701 name = modify_field_ids[ent];
8702 if (ctx->curr == ACTION_MODIFY_FIELD_SRC_TYPE ||
8703 (strcmp(name, "pointer") && strcmp(name, "value")))
8704 return strlcpy(buf, name, size);
8708 /** Internal context. */
8709 static struct context cmd_flow_context;
8711 /** Global parser instance (cmdline API). */
8712 cmdline_parse_inst_t cmd_flow;
8713 cmdline_parse_inst_t cmd_set_raw;
8715 /** Initialize context. */
8717 cmd_flow_context_init(struct context *ctx)
8719 /* A full memset() is not necessary. */
8729 ctx->objmask = NULL;
8732 /** Parse a token (cmdline API). */
8734 cmd_flow_parse(cmdline_parse_token_hdr_t *hdr, const char *src, void *result,
8737 struct context *ctx = &cmd_flow_context;
8738 const struct token *token;
8739 const enum index *list;
8744 token = &token_list[ctx->curr];
8745 /* Check argument length. */
8748 for (len = 0; src[len]; ++len)
8749 if (src[len] == '#' || isspace(src[len]))
8753 /* Last argument and EOL detection. */
8754 for (i = len; src[i]; ++i)
8755 if (src[i] == '#' || src[i] == '\r' || src[i] == '\n')
8757 else if (!isspace(src[i])) {
8762 if (src[i] == '\r' || src[i] == '\n') {
8766 /* Initialize context if necessary. */
8767 if (!ctx->next_num) {
8770 ctx->next[ctx->next_num++] = token->next[0];
8772 /* Process argument through candidates. */
8773 ctx->prev = ctx->curr;
8774 list = ctx->next[ctx->next_num - 1];
8775 for (i = 0; list[i]; ++i) {
8776 const struct token *next = &token_list[list[i]];
8779 ctx->curr = list[i];
8781 tmp = next->call(ctx, next, src, len, result, size);
8783 tmp = parse_default(ctx, next, src, len, result, size);
8784 if (tmp == -1 || tmp != len)
8792 /* Push subsequent tokens if any. */
8794 for (i = 0; token->next[i]; ++i) {
8795 if (ctx->next_num == RTE_DIM(ctx->next))
8797 ctx->next[ctx->next_num++] = token->next[i];
8799 /* Push arguments if any. */
8801 for (i = 0; token->args[i]; ++i) {
8802 if (ctx->args_num == RTE_DIM(ctx->args))
8804 ctx->args[ctx->args_num++] = token->args[i];
8810 flow_parse(const char *src, void *result, unsigned int size,
8811 struct rte_flow_attr **attr,
8812 struct rte_flow_item **pattern, struct rte_flow_action **actions)
8815 struct context saved_flow_ctx = cmd_flow_context;
8817 cmd_flow_context_init(&cmd_flow_context);
8819 ret = cmd_flow_parse(NULL, src, result, size);
8822 while (isspace(*src))
8825 } while (ret > 0 && strlen(src));
8826 cmd_flow_context = saved_flow_ctx;
8827 *attr = &((struct buffer *)result)->args.vc.attr;
8828 *pattern = ((struct buffer *)result)->args.vc.pattern;
8829 *actions = ((struct buffer *)result)->args.vc.actions;
8830 return (ret >= 0 && !strlen(src)) ? 0 : -1;
8833 /** Return number of completion entries (cmdline API). */
8835 cmd_flow_complete_get_nb(cmdline_parse_token_hdr_t *hdr)
8837 struct context *ctx = &cmd_flow_context;
8838 const struct token *token = &token_list[ctx->curr];
8839 const enum index *list;
8843 /* Count number of tokens in current list. */
8845 list = ctx->next[ctx->next_num - 1];
8847 list = token->next[0];
8848 for (i = 0; list[i]; ++i)
8853 * If there is a single token, use its completion callback, otherwise
8854 * return the number of entries.
8856 token = &token_list[list[0]];
8857 if (i == 1 && token->comp) {
8858 /* Save index for cmd_flow_get_help(). */
8859 ctx->prev = list[0];
8860 return token->comp(ctx, token, 0, NULL, 0);
8865 /** Return a completion entry (cmdline API). */
8867 cmd_flow_complete_get_elt(cmdline_parse_token_hdr_t *hdr, int index,
8868 char *dst, unsigned int size)
8870 struct context *ctx = &cmd_flow_context;
8871 const struct token *token = &token_list[ctx->curr];
8872 const enum index *list;
8876 /* Count number of tokens in current list. */
8878 list = ctx->next[ctx->next_num - 1];
8880 list = token->next[0];
8881 for (i = 0; list[i]; ++i)
8885 /* If there is a single token, use its completion callback. */
8886 token = &token_list[list[0]];
8887 if (i == 1 && token->comp) {
8888 /* Save index for cmd_flow_get_help(). */
8889 ctx->prev = list[0];
8890 return token->comp(ctx, token, index, dst, size) < 0 ? -1 : 0;
8892 /* Otherwise make sure the index is valid and use defaults. */
8895 token = &token_list[list[index]];
8896 strlcpy(dst, token->name, size);
8897 /* Save index for cmd_flow_get_help(). */
8898 ctx->prev = list[index];
8902 /** Populate help strings for current token (cmdline API). */
8904 cmd_flow_get_help(cmdline_parse_token_hdr_t *hdr, char *dst, unsigned int size)
8906 struct context *ctx = &cmd_flow_context;
8907 const struct token *token = &token_list[ctx->prev];
8912 /* Set token type and update global help with details. */
8913 strlcpy(dst, (token->type ? token->type : "TOKEN"), size);
8915 cmd_flow.help_str = token->help;
8917 cmd_flow.help_str = token->name;
8921 /** Token definition template (cmdline API). */
8922 static struct cmdline_token_hdr cmd_flow_token_hdr = {
8923 .ops = &(struct cmdline_token_ops){
8924 .parse = cmd_flow_parse,
8925 .complete_get_nb = cmd_flow_complete_get_nb,
8926 .complete_get_elt = cmd_flow_complete_get_elt,
8927 .get_help = cmd_flow_get_help,
8932 /** Populate the next dynamic token. */
8934 cmd_flow_tok(cmdline_parse_token_hdr_t **hdr,
8935 cmdline_parse_token_hdr_t **hdr_inst)
8937 struct context *ctx = &cmd_flow_context;
8939 /* Always reinitialize context before requesting the first token. */
8940 if (!(hdr_inst - cmd_flow.tokens))
8941 cmd_flow_context_init(ctx);
8942 /* Return NULL when no more tokens are expected. */
8943 if (!ctx->next_num && ctx->curr) {
8947 /* Determine if command should end here. */
8948 if (ctx->eol && ctx->last && ctx->next_num) {
8949 const enum index *list = ctx->next[ctx->next_num - 1];
8952 for (i = 0; list[i]; ++i) {
8959 *hdr = &cmd_flow_token_hdr;
8962 /** Dispatch parsed buffer to function calls. */
8964 cmd_flow_parsed(const struct buffer *in)
8966 switch (in->command) {
8967 case INDIRECT_ACTION_CREATE:
8968 port_action_handle_create(
8969 in->port, in->args.vc.attr.group,
8970 &((const struct rte_flow_indir_action_conf) {
8971 .ingress = in->args.vc.attr.ingress,
8972 .egress = in->args.vc.attr.egress,
8973 .transfer = in->args.vc.attr.transfer,
8975 in->args.vc.actions);
8977 case INDIRECT_ACTION_DESTROY:
8978 port_action_handle_destroy(in->port,
8979 in->args.ia_destroy.action_id_n,
8980 in->args.ia_destroy.action_id);
8982 case INDIRECT_ACTION_UPDATE:
8983 port_action_handle_update(in->port, in->args.vc.attr.group,
8984 in->args.vc.actions);
8986 case INDIRECT_ACTION_QUERY:
8987 port_action_handle_query(in->port, in->args.ia.action_id);
8990 port_flow_validate(in->port, &in->args.vc.attr,
8991 in->args.vc.pattern, in->args.vc.actions,
8992 &in->args.vc.tunnel_ops);
8995 port_flow_create(in->port, &in->args.vc.attr,
8996 in->args.vc.pattern, in->args.vc.actions,
8997 &in->args.vc.tunnel_ops);
9000 port_flow_destroy(in->port, in->args.destroy.rule_n,
9001 in->args.destroy.rule);
9004 port_flow_flush(in->port);
9008 port_flow_dump(in->port, in->args.dump.mode,
9009 in->args.dump.rule, in->args.dump.file);
9012 port_flow_query(in->port, in->args.query.rule,
9013 &in->args.query.action);
9016 port_flow_list(in->port, in->args.list.group_n,
9017 in->args.list.group);
9020 port_flow_isolate(in->port, in->args.isolate.set);
9023 port_flow_aged(in->port, in->args.aged.destroy);
9026 port_flow_tunnel_create(in->port, &in->args.vc.tunnel_ops);
9028 case TUNNEL_DESTROY:
9029 port_flow_tunnel_destroy(in->port, in->args.vc.tunnel_ops.id);
9032 port_flow_tunnel_list(in->port);
9035 port_meter_policy_add(in->port, in->args.policy.policy_id,
9036 in->args.vc.actions);
9038 case FLEX_ITEM_CREATE:
9039 flex_item_create(in->port, in->args.flex.token,
9040 in->args.flex.filename);
9042 case FLEX_ITEM_DESTROY:
9043 flex_item_destroy(in->port, in->args.flex.token);
9050 /** Token generator and output processing callback (cmdline API). */
9052 cmd_flow_cb(void *arg0, struct cmdline *cl, void *arg2)
9055 cmd_flow_tok(arg0, arg2);
9057 cmd_flow_parsed(arg0);
9060 /** Global parser instance (cmdline API). */
9061 cmdline_parse_inst_t cmd_flow = {
9063 .data = NULL, /**< Unused. */
9064 .help_str = NULL, /**< Updated by cmd_flow_get_help(). */
9067 }, /**< Tokens are returned by cmd_flow_tok(). */
9070 /** set cmd facility. Reuse cmd flow's infrastructure as much as possible. */
9073 update_fields(uint8_t *buf, struct rte_flow_item *item, uint16_t next_proto)
9075 struct rte_ipv4_hdr *ipv4;
9076 struct rte_ether_hdr *eth;
9077 struct rte_ipv6_hdr *ipv6;
9078 struct rte_vxlan_hdr *vxlan;
9079 struct rte_vxlan_gpe_hdr *gpe;
9080 struct rte_flow_item_nvgre *nvgre;
9081 uint32_t ipv6_vtc_flow;
9083 switch (item->type) {
9084 case RTE_FLOW_ITEM_TYPE_ETH:
9085 eth = (struct rte_ether_hdr *)buf;
9087 eth->ether_type = rte_cpu_to_be_16(next_proto);
9089 case RTE_FLOW_ITEM_TYPE_IPV4:
9090 ipv4 = (struct rte_ipv4_hdr *)buf;
9091 if (!ipv4->version_ihl)
9092 ipv4->version_ihl = RTE_IPV4_VHL_DEF;
9093 if (next_proto && ipv4->next_proto_id == 0)
9094 ipv4->next_proto_id = (uint8_t)next_proto;
9096 case RTE_FLOW_ITEM_TYPE_IPV6:
9097 ipv6 = (struct rte_ipv6_hdr *)buf;
9098 if (next_proto && ipv6->proto == 0)
9099 ipv6->proto = (uint8_t)next_proto;
9100 ipv6_vtc_flow = rte_be_to_cpu_32(ipv6->vtc_flow);
9101 ipv6_vtc_flow &= 0x0FFFFFFF; /*< reset version bits. */
9102 ipv6_vtc_flow |= 0x60000000; /*< set ipv6 version. */
9103 ipv6->vtc_flow = rte_cpu_to_be_32(ipv6_vtc_flow);
9105 case RTE_FLOW_ITEM_TYPE_VXLAN:
9106 vxlan = (struct rte_vxlan_hdr *)buf;
9107 vxlan->vx_flags = 0x08;
9109 case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
9110 gpe = (struct rte_vxlan_gpe_hdr *)buf;
9111 gpe->vx_flags = 0x0C;
9113 case RTE_FLOW_ITEM_TYPE_NVGRE:
9114 nvgre = (struct rte_flow_item_nvgre *)buf;
9115 nvgre->protocol = rte_cpu_to_be_16(0x6558);
9116 nvgre->c_k_s_rsvd0_ver = rte_cpu_to_be_16(0x2000);
9123 /** Helper of get item's default mask. */
9125 flow_item_default_mask(const struct rte_flow_item *item)
9127 const void *mask = NULL;
9128 static rte_be32_t gre_key_default_mask = RTE_BE32(UINT32_MAX);
9130 switch (item->type) {
9131 case RTE_FLOW_ITEM_TYPE_ANY:
9132 mask = &rte_flow_item_any_mask;
9134 case RTE_FLOW_ITEM_TYPE_VF:
9135 mask = &rte_flow_item_vf_mask;
9137 case RTE_FLOW_ITEM_TYPE_PORT_ID:
9138 mask = &rte_flow_item_port_id_mask;
9140 case RTE_FLOW_ITEM_TYPE_RAW:
9141 mask = &rte_flow_item_raw_mask;
9143 case RTE_FLOW_ITEM_TYPE_ETH:
9144 mask = &rte_flow_item_eth_mask;
9146 case RTE_FLOW_ITEM_TYPE_VLAN:
9147 mask = &rte_flow_item_vlan_mask;
9149 case RTE_FLOW_ITEM_TYPE_IPV4:
9150 mask = &rte_flow_item_ipv4_mask;
9152 case RTE_FLOW_ITEM_TYPE_IPV6:
9153 mask = &rte_flow_item_ipv6_mask;
9155 case RTE_FLOW_ITEM_TYPE_ICMP:
9156 mask = &rte_flow_item_icmp_mask;
9158 case RTE_FLOW_ITEM_TYPE_UDP:
9159 mask = &rte_flow_item_udp_mask;
9161 case RTE_FLOW_ITEM_TYPE_TCP:
9162 mask = &rte_flow_item_tcp_mask;
9164 case RTE_FLOW_ITEM_TYPE_SCTP:
9165 mask = &rte_flow_item_sctp_mask;
9167 case RTE_FLOW_ITEM_TYPE_VXLAN:
9168 mask = &rte_flow_item_vxlan_mask;
9170 case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
9171 mask = &rte_flow_item_vxlan_gpe_mask;
9173 case RTE_FLOW_ITEM_TYPE_E_TAG:
9174 mask = &rte_flow_item_e_tag_mask;
9176 case RTE_FLOW_ITEM_TYPE_NVGRE:
9177 mask = &rte_flow_item_nvgre_mask;
9179 case RTE_FLOW_ITEM_TYPE_MPLS:
9180 mask = &rte_flow_item_mpls_mask;
9182 case RTE_FLOW_ITEM_TYPE_GRE:
9183 mask = &rte_flow_item_gre_mask;
9185 case RTE_FLOW_ITEM_TYPE_GRE_KEY:
9186 mask = &gre_key_default_mask;
9188 case RTE_FLOW_ITEM_TYPE_META:
9189 mask = &rte_flow_item_meta_mask;
9191 case RTE_FLOW_ITEM_TYPE_FUZZY:
9192 mask = &rte_flow_item_fuzzy_mask;
9194 case RTE_FLOW_ITEM_TYPE_GTP:
9195 mask = &rte_flow_item_gtp_mask;
9197 case RTE_FLOW_ITEM_TYPE_GTP_PSC:
9198 mask = &rte_flow_item_gtp_psc_mask;
9200 case RTE_FLOW_ITEM_TYPE_GENEVE:
9201 mask = &rte_flow_item_geneve_mask;
9203 case RTE_FLOW_ITEM_TYPE_GENEVE_OPT:
9204 mask = &rte_flow_item_geneve_opt_mask;
9206 case RTE_FLOW_ITEM_TYPE_PPPOE_PROTO_ID:
9207 mask = &rte_flow_item_pppoe_proto_id_mask;
9209 case RTE_FLOW_ITEM_TYPE_L2TPV3OIP:
9210 mask = &rte_flow_item_l2tpv3oip_mask;
9212 case RTE_FLOW_ITEM_TYPE_ESP:
9213 mask = &rte_flow_item_esp_mask;
9215 case RTE_FLOW_ITEM_TYPE_AH:
9216 mask = &rte_flow_item_ah_mask;
9218 case RTE_FLOW_ITEM_TYPE_PFCP:
9219 mask = &rte_flow_item_pfcp_mask;
9221 case RTE_FLOW_ITEM_TYPE_PORT_REPRESENTOR:
9222 case RTE_FLOW_ITEM_TYPE_REPRESENTED_PORT:
9223 mask = &rte_flow_item_ethdev_mask;
9225 case RTE_FLOW_ITEM_TYPE_L2TPV2:
9226 mask = &rte_flow_item_l2tpv2_mask;
9228 case RTE_FLOW_ITEM_TYPE_PPP:
9229 mask = &rte_flow_item_ppp_mask;
9237 /** Dispatch parsed buffer to function calls. */
9239 cmd_set_raw_parsed_sample(const struct buffer *in)
9241 uint32_t n = in->args.vc.actions_n;
9243 struct rte_flow_action *action = NULL;
9244 struct rte_flow_action *data = NULL;
9245 const struct rte_flow_action_rss *rss = NULL;
9247 uint16_t idx = in->port; /* We borrow port field as index */
9248 uint32_t max_size = sizeof(struct rte_flow_action) *
9249 ACTION_SAMPLE_ACTIONS_NUM;
9251 RTE_ASSERT(in->command == SET_SAMPLE_ACTIONS);
9252 data = (struct rte_flow_action *)&raw_sample_confs[idx].data;
9253 memset(data, 0x00, max_size);
9254 for (; i <= n - 1; i++) {
9255 action = in->args.vc.actions + i;
9256 if (action->type == RTE_FLOW_ACTION_TYPE_END)
9258 switch (action->type) {
9259 case RTE_FLOW_ACTION_TYPE_MARK:
9260 size = sizeof(struct rte_flow_action_mark);
9261 rte_memcpy(&sample_mark[idx],
9262 (const void *)action->conf, size);
9263 action->conf = &sample_mark[idx];
9265 case RTE_FLOW_ACTION_TYPE_COUNT:
9266 size = sizeof(struct rte_flow_action_count);
9267 rte_memcpy(&sample_count[idx],
9268 (const void *)action->conf, size);
9269 action->conf = &sample_count[idx];
9271 case RTE_FLOW_ACTION_TYPE_QUEUE:
9272 size = sizeof(struct rte_flow_action_queue);
9273 rte_memcpy(&sample_queue[idx],
9274 (const void *)action->conf, size);
9275 action->conf = &sample_queue[idx];
9277 case RTE_FLOW_ACTION_TYPE_RSS:
9278 size = sizeof(struct rte_flow_action_rss);
9280 rte_memcpy(&sample_rss_data[idx].conf,
9281 (const void *)rss, size);
9282 if (rss->key_len && rss->key) {
9283 sample_rss_data[idx].conf.key =
9284 sample_rss_data[idx].key;
9285 rte_memcpy((void *)((uintptr_t)
9286 sample_rss_data[idx].conf.key),
9287 (const void *)rss->key,
9288 sizeof(uint8_t) * rss->key_len);
9290 if (rss->queue_num && rss->queue) {
9291 sample_rss_data[idx].conf.queue =
9292 sample_rss_data[idx].queue;
9293 rte_memcpy((void *)((uintptr_t)
9294 sample_rss_data[idx].conf.queue),
9295 (const void *)rss->queue,
9296 sizeof(uint16_t) * rss->queue_num);
9298 action->conf = &sample_rss_data[idx].conf;
9300 case RTE_FLOW_ACTION_TYPE_RAW_ENCAP:
9301 size = sizeof(struct rte_flow_action_raw_encap);
9302 rte_memcpy(&sample_encap[idx],
9303 (const void *)action->conf, size);
9304 action->conf = &sample_encap[idx];
9306 case RTE_FLOW_ACTION_TYPE_PORT_ID:
9307 size = sizeof(struct rte_flow_action_port_id);
9308 rte_memcpy(&sample_port_id[idx],
9309 (const void *)action->conf, size);
9310 action->conf = &sample_port_id[idx];
9312 case RTE_FLOW_ACTION_TYPE_PF:
9314 case RTE_FLOW_ACTION_TYPE_VF:
9315 size = sizeof(struct rte_flow_action_vf);
9316 rte_memcpy(&sample_vf[idx],
9317 (const void *)action->conf, size);
9318 action->conf = &sample_vf[idx];
9320 case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:
9321 size = sizeof(struct rte_flow_action_vxlan_encap);
9322 parse_setup_vxlan_encap_data(&sample_vxlan_encap[idx]);
9323 action->conf = &sample_vxlan_encap[idx].conf;
9325 case RTE_FLOW_ACTION_TYPE_NVGRE_ENCAP:
9326 size = sizeof(struct rte_flow_action_nvgre_encap);
9327 parse_setup_nvgre_encap_data(&sample_nvgre_encap[idx]);
9328 action->conf = &sample_nvgre_encap[idx];
9331 fprintf(stderr, "Error - Not supported action\n");
9334 rte_memcpy(data, action, sizeof(struct rte_flow_action));
9339 /** Dispatch parsed buffer to function calls. */
9341 cmd_set_raw_parsed(const struct buffer *in)
9343 uint32_t n = in->args.vc.pattern_n;
9345 struct rte_flow_item *item = NULL;
9347 uint8_t *data = NULL;
9348 uint8_t *data_tail = NULL;
9349 size_t *total_size = NULL;
9350 uint16_t upper_layer = 0;
9352 uint16_t idx = in->port; /* We borrow port field as index */
9353 int gtp_psc = -1; /* GTP PSC option index. */
9355 if (in->command == SET_SAMPLE_ACTIONS)
9356 return cmd_set_raw_parsed_sample(in);
9357 RTE_ASSERT(in->command == SET_RAW_ENCAP ||
9358 in->command == SET_RAW_DECAP);
9359 if (in->command == SET_RAW_ENCAP) {
9360 total_size = &raw_encap_confs[idx].size;
9361 data = (uint8_t *)&raw_encap_confs[idx].data;
9363 total_size = &raw_decap_confs[idx].size;
9364 data = (uint8_t *)&raw_decap_confs[idx].data;
9367 memset(data, 0x00, ACTION_RAW_ENCAP_MAX_DATA);
9368 /* process hdr from upper layer to low layer (L3/L4 -> L2). */
9369 data_tail = data + ACTION_RAW_ENCAP_MAX_DATA;
9370 for (i = n - 1 ; i >= 0; --i) {
9371 const struct rte_flow_item_gtp *gtp;
9372 const struct rte_flow_item_geneve_opt *opt;
9374 item = in->args.vc.pattern + i;
9375 if (item->spec == NULL)
9376 item->spec = flow_item_default_mask(item);
9377 switch (item->type) {
9378 case RTE_FLOW_ITEM_TYPE_ETH:
9379 size = sizeof(struct rte_ether_hdr);
9381 case RTE_FLOW_ITEM_TYPE_VLAN:
9382 size = sizeof(struct rte_vlan_hdr);
9383 proto = RTE_ETHER_TYPE_VLAN;
9385 case RTE_FLOW_ITEM_TYPE_IPV4:
9386 size = sizeof(struct rte_ipv4_hdr);
9387 proto = RTE_ETHER_TYPE_IPV4;
9389 case RTE_FLOW_ITEM_TYPE_IPV6:
9390 size = sizeof(struct rte_ipv6_hdr);
9391 proto = RTE_ETHER_TYPE_IPV6;
9393 case RTE_FLOW_ITEM_TYPE_UDP:
9394 size = sizeof(struct rte_udp_hdr);
9397 case RTE_FLOW_ITEM_TYPE_TCP:
9398 size = sizeof(struct rte_tcp_hdr);
9401 case RTE_FLOW_ITEM_TYPE_VXLAN:
9402 size = sizeof(struct rte_vxlan_hdr);
9404 case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
9405 size = sizeof(struct rte_vxlan_gpe_hdr);
9407 case RTE_FLOW_ITEM_TYPE_GRE:
9408 size = sizeof(struct rte_gre_hdr);
9411 case RTE_FLOW_ITEM_TYPE_GRE_KEY:
9412 size = sizeof(rte_be32_t);
9415 case RTE_FLOW_ITEM_TYPE_MPLS:
9416 size = sizeof(struct rte_mpls_hdr);
9419 case RTE_FLOW_ITEM_TYPE_NVGRE:
9420 size = sizeof(struct rte_flow_item_nvgre);
9423 case RTE_FLOW_ITEM_TYPE_GENEVE:
9424 size = sizeof(struct rte_geneve_hdr);
9426 case RTE_FLOW_ITEM_TYPE_GENEVE_OPT:
9427 opt = (const struct rte_flow_item_geneve_opt *)
9429 size = offsetof(struct rte_flow_item_geneve_opt, data);
9430 if (opt->option_len && opt->data) {
9431 *total_size += opt->option_len *
9433 rte_memcpy(data_tail - (*total_size),
9435 opt->option_len * sizeof(uint32_t));
9438 case RTE_FLOW_ITEM_TYPE_L2TPV3OIP:
9439 size = sizeof(rte_be32_t);
9442 case RTE_FLOW_ITEM_TYPE_ESP:
9443 size = sizeof(struct rte_esp_hdr);
9446 case RTE_FLOW_ITEM_TYPE_AH:
9447 size = sizeof(struct rte_flow_item_ah);
9450 case RTE_FLOW_ITEM_TYPE_GTP:
9452 size = sizeof(struct rte_gtp_hdr);
9455 if (gtp_psc != i + 1) {
9457 "Error - GTP PSC does not follow GTP\n");
9461 if ((gtp->v_pt_rsv_flags & 0x07) != 0x04) {
9462 /* Only E flag should be set. */
9464 "Error - GTP unsupported flags\n");
9467 struct rte_gtp_hdr_ext_word ext_word = {
9471 /* We have to add GTP header extra word. */
9472 *total_size += sizeof(ext_word);
9473 rte_memcpy(data_tail - (*total_size),
9474 &ext_word, sizeof(ext_word));
9476 size = sizeof(struct rte_gtp_hdr);
9478 case RTE_FLOW_ITEM_TYPE_GTP_PSC:
9481 "Error - Multiple GTP PSC items\n");
9484 const struct rte_flow_item_gtp_psc
9492 psc.len = sizeof(psc) / 4;
9493 psc.pdu_type = opt->hdr.type;
9494 psc.qfi = opt->hdr.qfi;
9496 *total_size += sizeof(psc);
9497 rte_memcpy(data_tail - (*total_size),
9503 case RTE_FLOW_ITEM_TYPE_PFCP:
9504 size = sizeof(struct rte_flow_item_pfcp);
9506 case RTE_FLOW_ITEM_TYPE_FLEX:
9508 ((const struct rte_flow_item_flex *)
9509 item->spec)->length : 0;
9511 case RTE_FLOW_ITEM_TYPE_GRE_OPTION:
9514 const struct rte_flow_item_gre_opt
9516 if (opt->checksum_rsvd.checksum) {
9518 sizeof(opt->checksum_rsvd);
9519 rte_memcpy(data_tail - (*total_size),
9520 &opt->checksum_rsvd,
9521 sizeof(opt->checksum_rsvd));
9524 *total_size += sizeof(opt->key.key);
9525 rte_memcpy(data_tail - (*total_size),
9527 sizeof(opt->key.key));
9529 if (opt->sequence.sequence) {
9530 *total_size += sizeof(opt->sequence.sequence);
9531 rte_memcpy(data_tail - (*total_size),
9532 &opt->sequence.sequence,
9533 sizeof(opt->sequence.sequence));
9539 fprintf(stderr, "Error - Not supported item\n");
9542 *total_size += size;
9543 rte_memcpy(data_tail - (*total_size), item->spec, size);
9544 /* update some fields which cannot be set by cmdline */
9545 update_fields((data_tail - (*total_size)), item,
9547 upper_layer = proto;
9549 if (verbose_level & 0x1)
9550 printf("total data size is %zu\n", (*total_size));
9551 RTE_ASSERT((*total_size) <= ACTION_RAW_ENCAP_MAX_DATA);
9552 memmove(data, (data_tail - (*total_size)), *total_size);
9557 memset(data, 0x00, ACTION_RAW_ENCAP_MAX_DATA);
9560 /** Populate help strings for current token (cmdline API). */
9562 cmd_set_raw_get_help(cmdline_parse_token_hdr_t *hdr, char *dst,
9565 struct context *ctx = &cmd_flow_context;
9566 const struct token *token = &token_list[ctx->prev];
9571 /* Set token type and update global help with details. */
9572 snprintf(dst, size, "%s", (token->type ? token->type : "TOKEN"));
9574 cmd_set_raw.help_str = token->help;
9576 cmd_set_raw.help_str = token->name;
9580 /** Token definition template (cmdline API). */
9581 static struct cmdline_token_hdr cmd_set_raw_token_hdr = {
9582 .ops = &(struct cmdline_token_ops){
9583 .parse = cmd_flow_parse,
9584 .complete_get_nb = cmd_flow_complete_get_nb,
9585 .complete_get_elt = cmd_flow_complete_get_elt,
9586 .get_help = cmd_set_raw_get_help,
9591 /** Populate the next dynamic token. */
9593 cmd_set_raw_tok(cmdline_parse_token_hdr_t **hdr,
9594 cmdline_parse_token_hdr_t **hdr_inst)
9596 struct context *ctx = &cmd_flow_context;
9598 /* Always reinitialize context before requesting the first token. */
9599 if (!(hdr_inst - cmd_set_raw.tokens)) {
9600 cmd_flow_context_init(ctx);
9601 ctx->curr = START_SET;
9603 /* Return NULL when no more tokens are expected. */
9604 if (!ctx->next_num && (ctx->curr != START_SET)) {
9608 /* Determine if command should end here. */
9609 if (ctx->eol && ctx->last && ctx->next_num) {
9610 const enum index *list = ctx->next[ctx->next_num - 1];
9613 for (i = 0; list[i]; ++i) {
9620 *hdr = &cmd_set_raw_token_hdr;
9623 /** Token generator and output processing callback (cmdline API). */
9625 cmd_set_raw_cb(void *arg0, struct cmdline *cl, void *arg2)
9628 cmd_set_raw_tok(arg0, arg2);
9630 cmd_set_raw_parsed(arg0);
9633 /** Global parser instance (cmdline API). */
9634 cmdline_parse_inst_t cmd_set_raw = {
9635 .f = cmd_set_raw_cb,
9636 .data = NULL, /**< Unused. */
9637 .help_str = NULL, /**< Updated by cmd_flow_get_help(). */
9640 }, /**< Tokens are returned by cmd_flow_tok(). */
9643 /* *** display raw_encap/raw_decap buf */
9644 struct cmd_show_set_raw_result {
9645 cmdline_fixed_string_t cmd_show;
9646 cmdline_fixed_string_t cmd_what;
9647 cmdline_fixed_string_t cmd_all;
9652 cmd_show_set_raw_parsed(void *parsed_result, struct cmdline *cl, void *data)
9654 struct cmd_show_set_raw_result *res = parsed_result;
9655 uint16_t index = res->cmd_index;
9657 uint8_t *raw_data = NULL;
9658 size_t raw_size = 0;
9659 char title[16] = {0};
9663 if (!strcmp(res->cmd_all, "all")) {
9666 } else if (index >= RAW_ENCAP_CONFS_MAX_NUM) {
9667 fprintf(stderr, "index should be 0-%u\n",
9668 RAW_ENCAP_CONFS_MAX_NUM - 1);
9672 if (!strcmp(res->cmd_what, "raw_encap")) {
9673 raw_data = (uint8_t *)&raw_encap_confs[index].data;
9674 raw_size = raw_encap_confs[index].size;
9675 snprintf(title, 16, "\nindex: %u", index);
9676 rte_hexdump(stdout, title, raw_data, raw_size);
9678 raw_data = (uint8_t *)&raw_decap_confs[index].data;
9679 raw_size = raw_decap_confs[index].size;
9680 snprintf(title, 16, "\nindex: %u", index);
9681 rte_hexdump(stdout, title, raw_data, raw_size);
9683 } while (all && ++index < RAW_ENCAP_CONFS_MAX_NUM);
9686 cmdline_parse_token_string_t cmd_show_set_raw_cmd_show =
9687 TOKEN_STRING_INITIALIZER(struct cmd_show_set_raw_result,
9689 cmdline_parse_token_string_t cmd_show_set_raw_cmd_what =
9690 TOKEN_STRING_INITIALIZER(struct cmd_show_set_raw_result,
9691 cmd_what, "raw_encap#raw_decap");
9692 cmdline_parse_token_num_t cmd_show_set_raw_cmd_index =
9693 TOKEN_NUM_INITIALIZER(struct cmd_show_set_raw_result,
9694 cmd_index, RTE_UINT16);
9695 cmdline_parse_token_string_t cmd_show_set_raw_cmd_all =
9696 TOKEN_STRING_INITIALIZER(struct cmd_show_set_raw_result,
9698 cmdline_parse_inst_t cmd_show_set_raw = {
9699 .f = cmd_show_set_raw_parsed,
9701 .help_str = "show <raw_encap|raw_decap> <index>",
9703 (void *)&cmd_show_set_raw_cmd_show,
9704 (void *)&cmd_show_set_raw_cmd_what,
9705 (void *)&cmd_show_set_raw_cmd_index,
9709 cmdline_parse_inst_t cmd_show_set_raw_all = {
9710 .f = cmd_show_set_raw_parsed,
9712 .help_str = "show <raw_encap|raw_decap> all",
9714 (void *)&cmd_show_set_raw_cmd_show,
9715 (void *)&cmd_show_set_raw_cmd_what,
9716 (void *)&cmd_show_set_raw_cmd_all,