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,
59 COMMON_PATTERN_TEMPLATE_ID,
60 COMMON_ACTIONS_TEMPLATE_ID,
64 /* TOP-level command. */
67 /* Top-level command. */
69 /* Sub-leve commands. */
76 /* Top-level command. */
78 /* Sub-level commands. */
105 /* Pattern template arguments. */
106 PATTERN_TEMPLATE_CREATE,
107 PATTERN_TEMPLATE_DESTROY,
108 PATTERN_TEMPLATE_CREATE_ID,
109 PATTERN_TEMPLATE_DESTROY_ID,
110 PATTERN_TEMPLATE_RELAXED_MATCHING,
111 PATTERN_TEMPLATE_INGRESS,
112 PATTERN_TEMPLATE_EGRESS,
113 PATTERN_TEMPLATE_TRANSFER,
114 PATTERN_TEMPLATE_SPEC,
116 /* Actions template arguments. */
117 ACTIONS_TEMPLATE_CREATE,
118 ACTIONS_TEMPLATE_DESTROY,
119 ACTIONS_TEMPLATE_CREATE_ID,
120 ACTIONS_TEMPLATE_DESTROY_ID,
121 ACTIONS_TEMPLATE_INGRESS,
122 ACTIONS_TEMPLATE_EGRESS,
123 ACTIONS_TEMPLATE_TRANSFER,
124 ACTIONS_TEMPLATE_SPEC,
125 ACTIONS_TEMPLATE_MASK,
127 /* Queue arguments. */
130 QUEUE_INDIRECT_ACTION,
132 /* Queue create arguments. */
134 QUEUE_CREATE_POSTPONE,
135 QUEUE_TEMPLATE_TABLE,
136 QUEUE_PATTERN_TEMPLATE,
137 QUEUE_ACTIONS_TEMPLATE,
140 /* Queue destroy arguments. */
142 QUEUE_DESTROY_POSTPONE,
144 /* Queue indirect action arguments */
145 QUEUE_INDIRECT_ACTION_CREATE,
146 QUEUE_INDIRECT_ACTION_UPDATE,
147 QUEUE_INDIRECT_ACTION_DESTROY,
149 /* Queue indirect action create arguments */
150 QUEUE_INDIRECT_ACTION_CREATE_ID,
151 QUEUE_INDIRECT_ACTION_INGRESS,
152 QUEUE_INDIRECT_ACTION_EGRESS,
153 QUEUE_INDIRECT_ACTION_TRANSFER,
154 QUEUE_INDIRECT_ACTION_CREATE_POSTPONE,
155 QUEUE_INDIRECT_ACTION_SPEC,
157 /* Queue indirect action update arguments */
158 QUEUE_INDIRECT_ACTION_UPDATE_POSTPONE,
160 /* Queue indirect action destroy arguments */
161 QUEUE_INDIRECT_ACTION_DESTROY_ID,
162 QUEUE_INDIRECT_ACTION_DESTROY_POSTPONE,
164 /* Push arguments. */
167 /* Pull arguments. */
170 /* Table arguments. */
181 TABLE_PATTERN_TEMPLATE,
182 TABLE_ACTIONS_TEMPLATE,
184 /* Tunnel arguments. */
191 /* Destroy arguments. */
194 /* Query arguments. */
197 /* List arguments. */
200 /* Destroy aged flow arguments. */
203 /* Validate/create arguments. */
216 /* Configure arguments */
217 CONFIG_QUEUES_NUMBER,
219 CONFIG_COUNTERS_NUMBER,
220 CONFIG_AGING_OBJECTS_NUMBER,
221 CONFIG_METERS_NUMBER,
223 /* Indirect action arguments */
224 INDIRECT_ACTION_CREATE,
225 INDIRECT_ACTION_UPDATE,
226 INDIRECT_ACTION_DESTROY,
227 INDIRECT_ACTION_QUERY,
229 /* Indirect action create arguments */
230 INDIRECT_ACTION_CREATE_ID,
231 INDIRECT_ACTION_INGRESS,
232 INDIRECT_ACTION_EGRESS,
233 INDIRECT_ACTION_TRANSFER,
234 INDIRECT_ACTION_SPEC,
236 /* Indirect action destroy arguments */
237 INDIRECT_ACTION_DESTROY_ID,
239 /* Validate/create pattern. */
267 ITEM_RAW_PATTERN_HEX,
278 ITEM_VLAN_INNER_TYPE,
279 ITEM_VLAN_HAS_MORE_VLAN,
284 ITEM_IPV4_FRAGMENT_OFFSET,
296 ITEM_IPV6_HAS_FRAG_EXT,
316 ITEM_VXLAN_LAST_RSVD,
318 ITEM_E_TAG_GRP_ECID_B,
327 ITEM_GRE_C_RSVD0_VER,
346 ITEM_ARP_ETH_IPV4_SHA,
347 ITEM_ARP_ETH_IPV4_SPA,
348 ITEM_ARP_ETH_IPV4_THA,
349 ITEM_ARP_ETH_IPV4_TPA,
351 ITEM_IPV6_EXT_NEXT_HDR,
353 ITEM_IPV6_FRAG_EXT_NEXT_HDR,
354 ITEM_IPV6_FRAG_EXT_FRAG_DATA,
355 ITEM_IPV6_FRAG_EXT_ID,
360 ITEM_ICMP6_ND_NS_TARGET_ADDR,
362 ITEM_ICMP6_ND_NA_TARGET_ADDR,
364 ITEM_ICMP6_ND_OPT_TYPE,
365 ITEM_ICMP6_ND_OPT_SLA_ETH,
366 ITEM_ICMP6_ND_OPT_SLA_ETH_SLA,
367 ITEM_ICMP6_ND_OPT_TLA_ETH,
368 ITEM_ICMP6_ND_OPT_TLA_ETH_TLA,
374 ITEM_GRE_OPTION_CHECKSUM,
376 ITEM_GRE_OPTION_SEQUENCE,
385 ITEM_HIGIG2_CLASSIFICATION,
391 ITEM_L2TPV3OIP_SESSION_ID,
401 ITEM_ECPRI_COMMON_TYPE,
402 ITEM_ECPRI_COMMON_TYPE_IQ_DATA,
403 ITEM_ECPRI_COMMON_TYPE_RTC_CTRL,
404 ITEM_ECPRI_COMMON_TYPE_DLY_MSR,
405 ITEM_ECPRI_MSG_IQ_DATA_PCID,
406 ITEM_ECPRI_MSG_RTC_CTRL_RTCID,
407 ITEM_ECPRI_MSG_DLY_MSR_MSRID,
409 ITEM_GENEVE_OPT_CLASS,
410 ITEM_GENEVE_OPT_TYPE,
411 ITEM_GENEVE_OPT_LENGTH,
412 ITEM_GENEVE_OPT_DATA,
414 ITEM_INTEGRITY_LEVEL,
415 ITEM_INTEGRITY_VALUE,
420 ITEM_PORT_REPRESENTOR,
421 ITEM_PORT_REPRESENTOR_PORT_ID,
422 ITEM_REPRESENTED_PORT,
423 ITEM_REPRESENTED_PORT_ETHDEV_PORT_ID,
425 ITEM_FLEX_ITEM_HANDLE,
426 ITEM_FLEX_PATTERN_HANDLE,
429 ITEM_L2TPV2_TYPE_DATA,
430 ITEM_L2TPV2_TYPE_DATA_L,
431 ITEM_L2TPV2_TYPE_DATA_S,
432 ITEM_L2TPV2_TYPE_DATA_O,
433 ITEM_L2TPV2_TYPE_DATA_L_S,
434 ITEM_L2TPV2_TYPE_CTRL,
435 ITEM_L2TPV2_MSG_DATA_TUNNEL_ID,
436 ITEM_L2TPV2_MSG_DATA_SESSION_ID,
437 ITEM_L2TPV2_MSG_DATA_L_LENGTH,
438 ITEM_L2TPV2_MSG_DATA_L_TUNNEL_ID,
439 ITEM_L2TPV2_MSG_DATA_L_SESSION_ID,
440 ITEM_L2TPV2_MSG_DATA_S_TUNNEL_ID,
441 ITEM_L2TPV2_MSG_DATA_S_SESSION_ID,
442 ITEM_L2TPV2_MSG_DATA_S_NS,
443 ITEM_L2TPV2_MSG_DATA_S_NR,
444 ITEM_L2TPV2_MSG_DATA_O_TUNNEL_ID,
445 ITEM_L2TPV2_MSG_DATA_O_SESSION_ID,
446 ITEM_L2TPV2_MSG_DATA_O_OFFSET,
447 ITEM_L2TPV2_MSG_DATA_L_S_LENGTH,
448 ITEM_L2TPV2_MSG_DATA_L_S_TUNNEL_ID,
449 ITEM_L2TPV2_MSG_DATA_L_S_SESSION_ID,
450 ITEM_L2TPV2_MSG_DATA_L_S_NS,
451 ITEM_L2TPV2_MSG_DATA_L_S_NR,
452 ITEM_L2TPV2_MSG_CTRL_LENGTH,
453 ITEM_L2TPV2_MSG_CTRL_TUNNEL_ID,
454 ITEM_L2TPV2_MSG_CTRL_SESSION_ID,
455 ITEM_L2TPV2_MSG_CTRL_NS,
456 ITEM_L2TPV2_MSG_CTRL_NR,
462 /* Validate/create actions. */
481 ACTION_RSS_FUNC_DEFAULT,
482 ACTION_RSS_FUNC_TOEPLITZ,
483 ACTION_RSS_FUNC_SIMPLE_XOR,
484 ACTION_RSS_FUNC_SYMMETRIC_TOEPLITZ,
496 ACTION_PHY_PORT_ORIGINAL,
497 ACTION_PHY_PORT_INDEX,
499 ACTION_PORT_ID_ORIGINAL,
503 ACTION_METER_COLOR_TYPE,
504 ACTION_METER_COLOR_GREEN,
505 ACTION_METER_COLOR_YELLOW,
506 ACTION_METER_COLOR_RED,
508 ACTION_OF_SET_MPLS_TTL,
509 ACTION_OF_SET_MPLS_TTL_MPLS_TTL,
510 ACTION_OF_DEC_MPLS_TTL,
511 ACTION_OF_SET_NW_TTL,
512 ACTION_OF_SET_NW_TTL_NW_TTL,
513 ACTION_OF_DEC_NW_TTL,
514 ACTION_OF_COPY_TTL_OUT,
515 ACTION_OF_COPY_TTL_IN,
518 ACTION_OF_PUSH_VLAN_ETHERTYPE,
519 ACTION_OF_SET_VLAN_VID,
520 ACTION_OF_SET_VLAN_VID_VLAN_VID,
521 ACTION_OF_SET_VLAN_PCP,
522 ACTION_OF_SET_VLAN_PCP_VLAN_PCP,
524 ACTION_OF_POP_MPLS_ETHERTYPE,
526 ACTION_OF_PUSH_MPLS_ETHERTYPE,
533 ACTION_MPLSOGRE_ENCAP,
534 ACTION_MPLSOGRE_DECAP,
535 ACTION_MPLSOUDP_ENCAP,
536 ACTION_MPLSOUDP_DECAP,
538 ACTION_SET_IPV4_SRC_IPV4_SRC,
540 ACTION_SET_IPV4_DST_IPV4_DST,
542 ACTION_SET_IPV6_SRC_IPV6_SRC,
544 ACTION_SET_IPV6_DST_IPV6_DST,
546 ACTION_SET_TP_SRC_TP_SRC,
548 ACTION_SET_TP_DST_TP_DST,
554 ACTION_SET_MAC_SRC_MAC_SRC,
556 ACTION_SET_MAC_DST_MAC_DST,
558 ACTION_INC_TCP_SEQ_VALUE,
560 ACTION_DEC_TCP_SEQ_VALUE,
562 ACTION_INC_TCP_ACK_VALUE,
564 ACTION_DEC_TCP_ACK_VALUE,
567 ACTION_RAW_ENCAP_INDEX,
568 ACTION_RAW_ENCAP_INDEX_VALUE,
569 ACTION_RAW_DECAP_INDEX,
570 ACTION_RAW_DECAP_INDEX_VALUE,
573 ACTION_SET_TAG_INDEX,
576 ACTION_SET_META_DATA,
577 ACTION_SET_META_MASK,
578 ACTION_SET_IPV4_DSCP,
579 ACTION_SET_IPV4_DSCP_VALUE,
580 ACTION_SET_IPV6_DSCP,
581 ACTION_SET_IPV6_DSCP_VALUE,
587 ACTION_SAMPLE_INDEX_VALUE,
589 INDIRECT_ACTION_ID2PTR,
591 ACTION_MODIFY_FIELD_OP,
592 ACTION_MODIFY_FIELD_OP_VALUE,
593 ACTION_MODIFY_FIELD_DST_TYPE,
594 ACTION_MODIFY_FIELD_DST_TYPE_VALUE,
595 ACTION_MODIFY_FIELD_DST_LEVEL,
596 ACTION_MODIFY_FIELD_DST_OFFSET,
597 ACTION_MODIFY_FIELD_SRC_TYPE,
598 ACTION_MODIFY_FIELD_SRC_TYPE_VALUE,
599 ACTION_MODIFY_FIELD_SRC_LEVEL,
600 ACTION_MODIFY_FIELD_SRC_OFFSET,
601 ACTION_MODIFY_FIELD_SRC_VALUE,
602 ACTION_MODIFY_FIELD_SRC_POINTER,
603 ACTION_MODIFY_FIELD_WIDTH,
605 ACTION_CONNTRACK_UPDATE,
606 ACTION_CONNTRACK_UPDATE_DIR,
607 ACTION_CONNTRACK_UPDATE_CTX,
611 ACTION_PORT_REPRESENTOR,
612 ACTION_PORT_REPRESENTOR_PORT_ID,
613 ACTION_REPRESENTED_PORT,
614 ACTION_REPRESENTED_PORT_ETHDEV_PORT_ID,
617 /** Maximum size for pattern in struct rte_flow_item_raw. */
618 #define ITEM_RAW_PATTERN_SIZE 512
620 /** Maximum size for GENEVE option data pattern in bytes. */
621 #define ITEM_GENEVE_OPT_DATA_SIZE 124
623 /** Storage size for struct rte_flow_item_raw including pattern. */
624 #define ITEM_RAW_SIZE \
625 (sizeof(struct rte_flow_item_raw) + ITEM_RAW_PATTERN_SIZE)
627 /** Maximum size for external pattern in struct rte_flow_action_modify_data. */
628 #define ACTION_MODIFY_PATTERN_SIZE 32
630 /** Storage size for struct rte_flow_action_modify_field including pattern. */
631 #define ACTION_MODIFY_SIZE \
632 (sizeof(struct rte_flow_action_modify_field) + \
633 ACTION_MODIFY_PATTERN_SIZE)
635 /** Maximum number of queue indices in struct rte_flow_action_rss. */
636 #define ACTION_RSS_QUEUE_NUM 128
638 /** Storage for struct rte_flow_action_rss including external data. */
639 struct action_rss_data {
640 struct rte_flow_action_rss conf;
641 uint8_t key[RSS_HASH_KEY_LENGTH];
642 uint16_t queue[ACTION_RSS_QUEUE_NUM];
645 /** Maximum data size in struct rte_flow_action_raw_encap. */
646 #define ACTION_RAW_ENCAP_MAX_DATA 512
647 #define RAW_ENCAP_CONFS_MAX_NUM 8
649 /** Storage for struct rte_flow_action_raw_encap. */
650 struct raw_encap_conf {
651 uint8_t data[ACTION_RAW_ENCAP_MAX_DATA];
652 uint8_t preserve[ACTION_RAW_ENCAP_MAX_DATA];
656 struct raw_encap_conf raw_encap_confs[RAW_ENCAP_CONFS_MAX_NUM];
658 /** Storage for struct rte_flow_action_raw_encap including external data. */
659 struct action_raw_encap_data {
660 struct rte_flow_action_raw_encap conf;
661 uint8_t data[ACTION_RAW_ENCAP_MAX_DATA];
662 uint8_t preserve[ACTION_RAW_ENCAP_MAX_DATA];
666 /** Storage for struct rte_flow_action_raw_decap. */
667 struct raw_decap_conf {
668 uint8_t data[ACTION_RAW_ENCAP_MAX_DATA];
672 struct raw_decap_conf raw_decap_confs[RAW_ENCAP_CONFS_MAX_NUM];
674 /** Storage for struct rte_flow_action_raw_decap including external data. */
675 struct action_raw_decap_data {
676 struct rte_flow_action_raw_decap conf;
677 uint8_t data[ACTION_RAW_ENCAP_MAX_DATA];
681 struct vxlan_encap_conf vxlan_encap_conf = {
685 .vni = "\x00\x00\x00",
687 .udp_dst = RTE_BE16(RTE_VXLAN_DEFAULT_PORT),
688 .ipv4_src = RTE_IPV4(127, 0, 0, 1),
689 .ipv4_dst = RTE_IPV4(255, 255, 255, 255),
690 .ipv6_src = "\x00\x00\x00\x00\x00\x00\x00\x00"
691 "\x00\x00\x00\x00\x00\x00\x00\x01",
692 .ipv6_dst = "\x00\x00\x00\x00\x00\x00\x00\x00"
693 "\x00\x00\x00\x00\x00\x00\x11\x11",
697 .eth_src = "\x00\x00\x00\x00\x00\x00",
698 .eth_dst = "\xff\xff\xff\xff\xff\xff",
701 /** Maximum number of items in struct rte_flow_action_vxlan_encap. */
702 #define ACTION_VXLAN_ENCAP_ITEMS_NUM 6
704 /** Storage for struct rte_flow_action_vxlan_encap including external data. */
705 struct action_vxlan_encap_data {
706 struct rte_flow_action_vxlan_encap conf;
707 struct rte_flow_item items[ACTION_VXLAN_ENCAP_ITEMS_NUM];
708 struct rte_flow_item_eth item_eth;
709 struct rte_flow_item_vlan item_vlan;
711 struct rte_flow_item_ipv4 item_ipv4;
712 struct rte_flow_item_ipv6 item_ipv6;
714 struct rte_flow_item_udp item_udp;
715 struct rte_flow_item_vxlan item_vxlan;
718 struct nvgre_encap_conf nvgre_encap_conf = {
721 .tni = "\x00\x00\x00",
722 .ipv4_src = RTE_IPV4(127, 0, 0, 1),
723 .ipv4_dst = RTE_IPV4(255, 255, 255, 255),
724 .ipv6_src = "\x00\x00\x00\x00\x00\x00\x00\x00"
725 "\x00\x00\x00\x00\x00\x00\x00\x01",
726 .ipv6_dst = "\x00\x00\x00\x00\x00\x00\x00\x00"
727 "\x00\x00\x00\x00\x00\x00\x11\x11",
729 .eth_src = "\x00\x00\x00\x00\x00\x00",
730 .eth_dst = "\xff\xff\xff\xff\xff\xff",
733 /** Maximum number of items in struct rte_flow_action_nvgre_encap. */
734 #define ACTION_NVGRE_ENCAP_ITEMS_NUM 5
736 /** Storage for struct rte_flow_action_nvgre_encap including external data. */
737 struct action_nvgre_encap_data {
738 struct rte_flow_action_nvgre_encap conf;
739 struct rte_flow_item items[ACTION_NVGRE_ENCAP_ITEMS_NUM];
740 struct rte_flow_item_eth item_eth;
741 struct rte_flow_item_vlan item_vlan;
743 struct rte_flow_item_ipv4 item_ipv4;
744 struct rte_flow_item_ipv6 item_ipv6;
746 struct rte_flow_item_nvgre item_nvgre;
749 struct l2_encap_conf l2_encap_conf;
751 struct l2_decap_conf l2_decap_conf;
753 struct mplsogre_encap_conf mplsogre_encap_conf;
755 struct mplsogre_decap_conf mplsogre_decap_conf;
757 struct mplsoudp_encap_conf mplsoudp_encap_conf;
759 struct mplsoudp_decap_conf mplsoudp_decap_conf;
761 struct rte_flow_action_conntrack conntrack_context;
763 #define ACTION_SAMPLE_ACTIONS_NUM 10
764 #define RAW_SAMPLE_CONFS_MAX_NUM 8
765 /** Storage for struct rte_flow_action_sample including external data. */
766 struct action_sample_data {
767 struct rte_flow_action_sample conf;
770 /** Storage for struct rte_flow_action_sample. */
771 struct raw_sample_conf {
772 struct rte_flow_action data[ACTION_SAMPLE_ACTIONS_NUM];
774 struct raw_sample_conf raw_sample_confs[RAW_SAMPLE_CONFS_MAX_NUM];
775 struct rte_flow_action_mark sample_mark[RAW_SAMPLE_CONFS_MAX_NUM];
776 struct rte_flow_action_queue sample_queue[RAW_SAMPLE_CONFS_MAX_NUM];
777 struct rte_flow_action_count sample_count[RAW_SAMPLE_CONFS_MAX_NUM];
778 struct rte_flow_action_port_id sample_port_id[RAW_SAMPLE_CONFS_MAX_NUM];
779 struct rte_flow_action_raw_encap sample_encap[RAW_SAMPLE_CONFS_MAX_NUM];
780 struct action_vxlan_encap_data sample_vxlan_encap[RAW_SAMPLE_CONFS_MAX_NUM];
781 struct action_nvgre_encap_data sample_nvgre_encap[RAW_SAMPLE_CONFS_MAX_NUM];
782 struct action_rss_data sample_rss_data[RAW_SAMPLE_CONFS_MAX_NUM];
783 struct rte_flow_action_vf sample_vf[RAW_SAMPLE_CONFS_MAX_NUM];
785 static const char *const modify_field_ops[] = {
786 "set", "add", "sub", NULL
789 static const char *const modify_field_ids[] = {
790 "start", "mac_dst", "mac_src",
791 "vlan_type", "vlan_id", "mac_type",
792 "ipv4_dscp", "ipv4_ttl", "ipv4_src", "ipv4_dst",
793 "ipv6_dscp", "ipv6_hoplimit", "ipv6_src", "ipv6_dst",
794 "tcp_port_src", "tcp_port_dst",
795 "tcp_seq_num", "tcp_ack_num", "tcp_flags",
796 "udp_port_src", "udp_port_dst",
797 "vxlan_vni", "geneve_vni", "gtp_teid",
798 "tag", "mark", "meta", "pointer", "value",
799 "ipv4_ecn", "ipv6_ecn", NULL
802 /** Maximum number of subsequent tokens and arguments on the stack. */
803 #define CTX_STACK_SIZE 16
805 /** Parser context. */
807 /** Stack of subsequent token lists to process. */
808 const enum index *next[CTX_STACK_SIZE];
809 /** Arguments for stacked tokens. */
810 const void *args[CTX_STACK_SIZE];
811 enum index curr; /**< Current token index. */
812 enum index prev; /**< Index of the last token seen. */
813 int next_num; /**< Number of entries in next[]. */
814 int args_num; /**< Number of entries in args[]. */
815 uint32_t eol:1; /**< EOL has been detected. */
816 uint32_t last:1; /**< No more arguments. */
817 portid_t port; /**< Current port ID (for completions). */
818 uint32_t objdata; /**< Object-specific data. */
819 void *object; /**< Address of current object for relative offsets. */
820 void *objmask; /**< Object a full mask must be written to. */
823 /** Token argument. */
825 uint32_t hton:1; /**< Use network byte ordering. */
826 uint32_t sign:1; /**< Value is signed. */
827 uint32_t bounded:1; /**< Value is bounded. */
828 uintmax_t min; /**< Minimum value if bounded. */
829 uintmax_t max; /**< Maximum value if bounded. */
830 uint32_t offset; /**< Relative offset from ctx->object. */
831 uint32_t size; /**< Field size. */
832 const uint8_t *mask; /**< Bit-mask to use instead of offset/size. */
835 /** Parser token definition. */
837 /** Type displayed during completion (defaults to "TOKEN"). */
839 /** Help displayed during completion (defaults to token name). */
841 /** Private data used by parser functions. */
844 * Lists of subsequent tokens to push on the stack. Each call to the
845 * parser consumes the last entry of that stack.
847 const enum index *const *next;
848 /** Arguments stack for subsequent tokens that need them. */
849 const struct arg *const *args;
851 * Token-processing callback, returns -1 in case of error, the
852 * length of the matched string otherwise. If NULL, attempts to
853 * match the token name.
855 * If buf is not NULL, the result should be stored in it according
856 * to context. An error is returned if not large enough.
858 int (*call)(struct context *ctx, const struct token *token,
859 const char *str, unsigned int len,
860 void *buf, unsigned int size);
862 * Callback that provides possible values for this token, used for
863 * completion. Returns -1 in case of error, the number of possible
864 * values otherwise. If NULL, the token name is used.
866 * If buf is not NULL, entry index ent is written to buf and the
867 * full length of the entry is returned (same behavior as
870 int (*comp)(struct context *ctx, const struct token *token,
871 unsigned int ent, char *buf, unsigned int size);
872 /** Mandatory token name, no default value. */
876 /** Static initializer for the next field. */
877 #define NEXT(...) (const enum index *const []){ __VA_ARGS__, NULL, }
879 /** Static initializer for a NEXT() entry. */
880 #define NEXT_ENTRY(...) (const enum index []){ __VA_ARGS__, ZERO, }
882 /** Static initializer for the args field. */
883 #define ARGS(...) (const struct arg *const []){ __VA_ARGS__, NULL, }
885 /** Static initializer for ARGS() to target a field. */
886 #define ARGS_ENTRY(s, f) \
887 (&(const struct arg){ \
888 .offset = offsetof(s, f), \
889 .size = sizeof(((s *)0)->f), \
892 /** Static initializer for ARGS() to target a bit-field. */
893 #define ARGS_ENTRY_BF(s, f, b) \
894 (&(const struct arg){ \
896 .mask = (const void *)&(const s){ .f = (1 << (b)) - 1 }, \
899 /** Static initializer for ARGS() to target a field with limits. */
900 #define ARGS_ENTRY_BOUNDED(s, f, i, a) \
901 (&(const struct arg){ \
905 .offset = offsetof(s, f), \
906 .size = sizeof(((s *)0)->f), \
909 /** Static initializer for ARGS() to target an arbitrary bit-mask. */
910 #define ARGS_ENTRY_MASK(s, f, m) \
911 (&(const struct arg){ \
912 .offset = offsetof(s, f), \
913 .size = sizeof(((s *)0)->f), \
914 .mask = (const void *)(m), \
917 /** Same as ARGS_ENTRY_MASK() using network byte ordering for the value. */
918 #define ARGS_ENTRY_MASK_HTON(s, f, m) \
919 (&(const struct arg){ \
921 .offset = offsetof(s, f), \
922 .size = sizeof(((s *)0)->f), \
923 .mask = (const void *)(m), \
926 /** Static initializer for ARGS() to target a pointer. */
927 #define ARGS_ENTRY_PTR(s, f) \
928 (&(const struct arg){ \
929 .size = sizeof(*((s *)0)->f), \
932 /** Static initializer for ARGS() with arbitrary offset and size. */
933 #define ARGS_ENTRY_ARB(o, s) \
934 (&(const struct arg){ \
939 /** Same as ARGS_ENTRY_ARB() with bounded values. */
940 #define ARGS_ENTRY_ARB_BOUNDED(o, s, i, a) \
941 (&(const struct arg){ \
949 /** Same as ARGS_ENTRY() using network byte ordering. */
950 #define ARGS_ENTRY_HTON(s, f) \
951 (&(const struct arg){ \
953 .offset = offsetof(s, f), \
954 .size = sizeof(((s *)0)->f), \
957 /** Same as ARGS_ENTRY_HTON() for a single argument, without structure. */
958 #define ARG_ENTRY_HTON(s) \
959 (&(const struct arg){ \
965 /** Parser output buffer layout expected by cmd_flow_parsed(). */
967 enum index command; /**< Flow command. */
968 portid_t port; /**< Affected port ID. */
969 queueid_t queue; /** Async queue ID. */
970 bool postpone; /** Postpone async operation */
973 struct rte_flow_port_attr port_attr;
975 struct rte_flow_queue_attr queue_attr;
976 } configure; /**< Configuration arguments. */
978 uint32_t *template_id;
979 uint32_t template_id_n;
980 } templ_destroy; /**< Template destroy arguments. */
983 struct rte_flow_template_table_attr attr;
984 uint32_t *pat_templ_id;
985 uint32_t pat_templ_id_n;
986 uint32_t *act_templ_id;
987 uint32_t act_templ_id_n;
988 } table; /**< Table arguments. */
992 } table_destroy; /**< Template destroy arguments. */
995 uint32_t action_id_n;
996 } ia_destroy; /**< Indirect action destroy arguments. */
999 } ia; /* Indirect action query arguments */
1002 uint32_t pat_templ_id;
1003 uint32_t act_templ_id;
1004 struct rte_flow_attr attr;
1005 struct tunnel_ops tunnel_ops;
1006 struct rte_flow_item *pattern;
1007 struct rte_flow_action *actions;
1008 struct rte_flow_action *masks;
1012 } vc; /**< Validate/create arguments. */
1016 } destroy; /**< Destroy arguments. */
1021 } dump; /**< Dump arguments. */
1024 struct rte_flow_action action;
1025 } query; /**< Query arguments. */
1029 } list; /**< List arguments. */
1032 } isolate; /**< Isolated mode arguments. */
1035 } aged; /**< Aged arguments. */
1038 } policy;/**< Policy arguments. */
1043 } flex; /**< Flex arguments*/
1044 } args; /**< Command arguments. */
1047 /** Private data for pattern items. */
1048 struct parse_item_priv {
1049 enum rte_flow_item_type type; /**< Item type. */
1050 uint32_t size; /**< Size of item specification structure. */
1053 #define PRIV_ITEM(t, s) \
1054 (&(const struct parse_item_priv){ \
1055 .type = RTE_FLOW_ITEM_TYPE_ ## t, \
1059 /** Private data for actions. */
1060 struct parse_action_priv {
1061 enum rte_flow_action_type type; /**< Action type. */
1062 uint32_t size; /**< Size of action configuration structure. */
1065 #define PRIV_ACTION(t, s) \
1066 (&(const struct parse_action_priv){ \
1067 .type = RTE_FLOW_ACTION_TYPE_ ## t, \
1071 static const enum index next_flex_item[] = {
1078 static const enum index next_config_attr[] = {
1079 CONFIG_QUEUES_NUMBER,
1081 CONFIG_COUNTERS_NUMBER,
1082 CONFIG_AGING_OBJECTS_NUMBER,
1083 CONFIG_METERS_NUMBER,
1088 static const enum index next_pt_subcmd[] = {
1089 PATTERN_TEMPLATE_CREATE,
1090 PATTERN_TEMPLATE_DESTROY,
1094 static const enum index next_pt_attr[] = {
1095 PATTERN_TEMPLATE_CREATE_ID,
1096 PATTERN_TEMPLATE_RELAXED_MATCHING,
1097 PATTERN_TEMPLATE_INGRESS,
1098 PATTERN_TEMPLATE_EGRESS,
1099 PATTERN_TEMPLATE_TRANSFER,
1100 PATTERN_TEMPLATE_SPEC,
1104 static const enum index next_pt_destroy_attr[] = {
1105 PATTERN_TEMPLATE_DESTROY_ID,
1110 static const enum index next_at_subcmd[] = {
1111 ACTIONS_TEMPLATE_CREATE,
1112 ACTIONS_TEMPLATE_DESTROY,
1116 static const enum index next_at_attr[] = {
1117 ACTIONS_TEMPLATE_CREATE_ID,
1118 ACTIONS_TEMPLATE_INGRESS,
1119 ACTIONS_TEMPLATE_EGRESS,
1120 ACTIONS_TEMPLATE_TRANSFER,
1121 ACTIONS_TEMPLATE_SPEC,
1125 static const enum index next_at_destroy_attr[] = {
1126 ACTIONS_TEMPLATE_DESTROY_ID,
1131 static const enum index next_table_subcmd[] = {
1137 static const enum index next_table_attr[] = {
1145 TABLE_PATTERN_TEMPLATE,
1146 TABLE_ACTIONS_TEMPLATE,
1151 static const enum index next_table_destroy_attr[] = {
1157 static const enum index next_queue_subcmd[] = {
1160 QUEUE_INDIRECT_ACTION,
1164 static const enum index next_queue_destroy_attr[] = {
1170 static const enum index next_qia_subcmd[] = {
1171 QUEUE_INDIRECT_ACTION_CREATE,
1172 QUEUE_INDIRECT_ACTION_UPDATE,
1173 QUEUE_INDIRECT_ACTION_DESTROY,
1177 static const enum index next_qia_create_attr[] = {
1178 QUEUE_INDIRECT_ACTION_CREATE_ID,
1179 QUEUE_INDIRECT_ACTION_INGRESS,
1180 QUEUE_INDIRECT_ACTION_EGRESS,
1181 QUEUE_INDIRECT_ACTION_TRANSFER,
1182 QUEUE_INDIRECT_ACTION_CREATE_POSTPONE,
1183 QUEUE_INDIRECT_ACTION_SPEC,
1187 static const enum index next_qia_update_attr[] = {
1188 QUEUE_INDIRECT_ACTION_UPDATE_POSTPONE,
1189 QUEUE_INDIRECT_ACTION_SPEC,
1193 static const enum index next_qia_destroy_attr[] = {
1194 QUEUE_INDIRECT_ACTION_DESTROY_POSTPONE,
1195 QUEUE_INDIRECT_ACTION_DESTROY_ID,
1200 static const enum index next_ia_create_attr[] = {
1201 INDIRECT_ACTION_CREATE_ID,
1202 INDIRECT_ACTION_INGRESS,
1203 INDIRECT_ACTION_EGRESS,
1204 INDIRECT_ACTION_TRANSFER,
1205 INDIRECT_ACTION_SPEC,
1209 static const enum index next_dump_subcmd[] = {
1215 static const enum index next_ia_subcmd[] = {
1216 INDIRECT_ACTION_CREATE,
1217 INDIRECT_ACTION_UPDATE,
1218 INDIRECT_ACTION_DESTROY,
1219 INDIRECT_ACTION_QUERY,
1223 static const enum index next_vc_attr[] = {
1235 static const enum index next_destroy_attr[] = {
1241 static const enum index next_dump_attr[] = {
1247 static const enum index next_list_attr[] = {
1253 static const enum index next_aged_attr[] = {
1259 static const enum index next_ia_destroy_attr[] = {
1260 INDIRECT_ACTION_DESTROY_ID,
1265 static const enum index item_param[] = {
1274 static const enum index next_item[] = {
1311 ITEM_ICMP6_ND_OPT_SLA_ETH,
1312 ITEM_ICMP6_ND_OPT_TLA_ETH,
1319 ITEM_PPPOE_PROTO_ID,
1330 ITEM_PORT_REPRESENTOR,
1331 ITEM_REPRESENTED_PORT,
1339 static const enum index item_fuzzy[] = {
1345 static const enum index item_any[] = {
1351 static const enum index item_vf[] = {
1357 static const enum index item_phy_port[] = {
1358 ITEM_PHY_PORT_INDEX,
1363 static const enum index item_port_id[] = {
1369 static const enum index item_mark[] = {
1375 static const enum index item_raw[] = {
1381 ITEM_RAW_PATTERN_HEX,
1386 static const enum index item_eth[] = {
1395 static const enum index item_vlan[] = {
1400 ITEM_VLAN_INNER_TYPE,
1401 ITEM_VLAN_HAS_MORE_VLAN,
1406 static const enum index item_ipv4[] = {
1410 ITEM_IPV4_FRAGMENT_OFFSET,
1419 static const enum index item_ipv6[] = {
1426 ITEM_IPV6_HAS_FRAG_EXT,
1431 static const enum index item_icmp[] = {
1440 static const enum index item_udp[] = {
1447 static const enum index item_tcp[] = {
1455 static const enum index item_sctp[] = {
1464 static const enum index item_vxlan[] = {
1466 ITEM_VXLAN_LAST_RSVD,
1471 static const enum index item_e_tag[] = {
1472 ITEM_E_TAG_GRP_ECID_B,
1477 static const enum index item_nvgre[] = {
1483 static const enum index item_mpls[] = {
1491 static const enum index item_gre[] = {
1493 ITEM_GRE_C_RSVD0_VER,
1501 static const enum index item_gre_key[] = {
1507 static const enum index item_gre_option[] = {
1508 ITEM_GRE_OPTION_CHECKSUM,
1509 ITEM_GRE_OPTION_KEY,
1510 ITEM_GRE_OPTION_SEQUENCE,
1515 static const enum index item_gtp[] = {
1523 static const enum index item_geneve[] = {
1531 static const enum index item_vxlan_gpe[] = {
1537 static const enum index item_arp_eth_ipv4[] = {
1538 ITEM_ARP_ETH_IPV4_SHA,
1539 ITEM_ARP_ETH_IPV4_SPA,
1540 ITEM_ARP_ETH_IPV4_THA,
1541 ITEM_ARP_ETH_IPV4_TPA,
1546 static const enum index item_ipv6_ext[] = {
1547 ITEM_IPV6_EXT_NEXT_HDR,
1552 static const enum index item_ipv6_frag_ext[] = {
1553 ITEM_IPV6_FRAG_EXT_NEXT_HDR,
1554 ITEM_IPV6_FRAG_EXT_FRAG_DATA,
1555 ITEM_IPV6_FRAG_EXT_ID,
1560 static const enum index item_icmp6[] = {
1567 static const enum index item_icmp6_nd_ns[] = {
1568 ITEM_ICMP6_ND_NS_TARGET_ADDR,
1573 static const enum index item_icmp6_nd_na[] = {
1574 ITEM_ICMP6_ND_NA_TARGET_ADDR,
1579 static const enum index item_icmp6_nd_opt[] = {
1580 ITEM_ICMP6_ND_OPT_TYPE,
1585 static const enum index item_icmp6_nd_opt_sla_eth[] = {
1586 ITEM_ICMP6_ND_OPT_SLA_ETH_SLA,
1591 static const enum index item_icmp6_nd_opt_tla_eth[] = {
1592 ITEM_ICMP6_ND_OPT_TLA_ETH_TLA,
1597 static const enum index item_meta[] = {
1603 static const enum index item_gtp_psc[] = {
1610 static const enum index item_pppoed[] = {
1616 static const enum index item_pppoes[] = {
1622 static const enum index item_pppoe_proto_id[] = {
1627 static const enum index item_higig2[] = {
1628 ITEM_HIGIG2_CLASSIFICATION,
1634 static const enum index item_esp[] = {
1640 static const enum index item_ah[] = {
1646 static const enum index item_pfcp[] = {
1653 static const enum index next_set_raw[] = {
1659 static const enum index item_tag[] = {
1666 static const enum index item_l2tpv3oip[] = {
1667 ITEM_L2TPV3OIP_SESSION_ID,
1672 static const enum index item_ecpri[] = {
1678 static const enum index item_ecpri_common[] = {
1679 ITEM_ECPRI_COMMON_TYPE,
1683 static const enum index item_ecpri_common_type[] = {
1684 ITEM_ECPRI_COMMON_TYPE_IQ_DATA,
1685 ITEM_ECPRI_COMMON_TYPE_RTC_CTRL,
1686 ITEM_ECPRI_COMMON_TYPE_DLY_MSR,
1690 static const enum index item_geneve_opt[] = {
1691 ITEM_GENEVE_OPT_CLASS,
1692 ITEM_GENEVE_OPT_TYPE,
1693 ITEM_GENEVE_OPT_LENGTH,
1694 ITEM_GENEVE_OPT_DATA,
1699 static const enum index item_integrity[] = {
1700 ITEM_INTEGRITY_LEVEL,
1701 ITEM_INTEGRITY_VALUE,
1705 static const enum index item_integrity_lv[] = {
1706 ITEM_INTEGRITY_LEVEL,
1707 ITEM_INTEGRITY_VALUE,
1712 static const enum index item_port_representor[] = {
1713 ITEM_PORT_REPRESENTOR_PORT_ID,
1718 static const enum index item_represented_port[] = {
1719 ITEM_REPRESENTED_PORT_ETHDEV_PORT_ID,
1724 static const enum index item_flex[] = {
1725 ITEM_FLEX_PATTERN_HANDLE,
1726 ITEM_FLEX_ITEM_HANDLE,
1731 static const enum index item_l2tpv2[] = {
1737 static const enum index item_l2tpv2_type[] = {
1738 ITEM_L2TPV2_TYPE_DATA,
1739 ITEM_L2TPV2_TYPE_DATA_L,
1740 ITEM_L2TPV2_TYPE_DATA_S,
1741 ITEM_L2TPV2_TYPE_DATA_O,
1742 ITEM_L2TPV2_TYPE_DATA_L_S,
1743 ITEM_L2TPV2_TYPE_CTRL,
1747 static const enum index item_l2tpv2_type_data[] = {
1748 ITEM_L2TPV2_MSG_DATA_TUNNEL_ID,
1749 ITEM_L2TPV2_MSG_DATA_SESSION_ID,
1754 static const enum index item_l2tpv2_type_data_l[] = {
1755 ITEM_L2TPV2_MSG_DATA_L_LENGTH,
1756 ITEM_L2TPV2_MSG_DATA_L_TUNNEL_ID,
1757 ITEM_L2TPV2_MSG_DATA_L_SESSION_ID,
1762 static const enum index item_l2tpv2_type_data_s[] = {
1763 ITEM_L2TPV2_MSG_DATA_S_TUNNEL_ID,
1764 ITEM_L2TPV2_MSG_DATA_S_SESSION_ID,
1765 ITEM_L2TPV2_MSG_DATA_S_NS,
1766 ITEM_L2TPV2_MSG_DATA_S_NR,
1771 static const enum index item_l2tpv2_type_data_o[] = {
1772 ITEM_L2TPV2_MSG_DATA_O_TUNNEL_ID,
1773 ITEM_L2TPV2_MSG_DATA_O_SESSION_ID,
1774 ITEM_L2TPV2_MSG_DATA_O_OFFSET,
1779 static const enum index item_l2tpv2_type_data_l_s[] = {
1780 ITEM_L2TPV2_MSG_DATA_L_S_LENGTH,
1781 ITEM_L2TPV2_MSG_DATA_L_S_TUNNEL_ID,
1782 ITEM_L2TPV2_MSG_DATA_L_S_SESSION_ID,
1783 ITEM_L2TPV2_MSG_DATA_L_S_NS,
1784 ITEM_L2TPV2_MSG_DATA_L_S_NR,
1789 static const enum index item_l2tpv2_type_ctrl[] = {
1790 ITEM_L2TPV2_MSG_CTRL_LENGTH,
1791 ITEM_L2TPV2_MSG_CTRL_TUNNEL_ID,
1792 ITEM_L2TPV2_MSG_CTRL_SESSION_ID,
1793 ITEM_L2TPV2_MSG_CTRL_NS,
1794 ITEM_L2TPV2_MSG_CTRL_NR,
1799 static const enum index item_ppp[] = {
1807 static const enum index next_action[] = {
1824 ACTION_OF_SET_MPLS_TTL,
1825 ACTION_OF_DEC_MPLS_TTL,
1826 ACTION_OF_SET_NW_TTL,
1827 ACTION_OF_DEC_NW_TTL,
1828 ACTION_OF_COPY_TTL_OUT,
1829 ACTION_OF_COPY_TTL_IN,
1831 ACTION_OF_PUSH_VLAN,
1832 ACTION_OF_SET_VLAN_VID,
1833 ACTION_OF_SET_VLAN_PCP,
1835 ACTION_OF_PUSH_MPLS,
1842 ACTION_MPLSOGRE_ENCAP,
1843 ACTION_MPLSOGRE_DECAP,
1844 ACTION_MPLSOUDP_ENCAP,
1845 ACTION_MPLSOUDP_DECAP,
1846 ACTION_SET_IPV4_SRC,
1847 ACTION_SET_IPV4_DST,
1848 ACTION_SET_IPV6_SRC,
1849 ACTION_SET_IPV6_DST,
1865 ACTION_SET_IPV4_DSCP,
1866 ACTION_SET_IPV6_DSCP,
1870 ACTION_MODIFY_FIELD,
1872 ACTION_CONNTRACK_UPDATE,
1873 ACTION_PORT_REPRESENTOR,
1874 ACTION_REPRESENTED_PORT,
1878 static const enum index action_mark[] = {
1884 static const enum index action_queue[] = {
1890 static const enum index action_count[] = {
1896 static const enum index action_rss[] = {
1907 static const enum index action_vf[] = {
1914 static const enum index action_phy_port[] = {
1915 ACTION_PHY_PORT_ORIGINAL,
1916 ACTION_PHY_PORT_INDEX,
1921 static const enum index action_port_id[] = {
1922 ACTION_PORT_ID_ORIGINAL,
1928 static const enum index action_meter[] = {
1934 static const enum index action_meter_color[] = {
1935 ACTION_METER_COLOR_TYPE,
1940 static const enum index action_of_set_mpls_ttl[] = {
1941 ACTION_OF_SET_MPLS_TTL_MPLS_TTL,
1946 static const enum index action_of_set_nw_ttl[] = {
1947 ACTION_OF_SET_NW_TTL_NW_TTL,
1952 static const enum index action_of_push_vlan[] = {
1953 ACTION_OF_PUSH_VLAN_ETHERTYPE,
1958 static const enum index action_of_set_vlan_vid[] = {
1959 ACTION_OF_SET_VLAN_VID_VLAN_VID,
1964 static const enum index action_of_set_vlan_pcp[] = {
1965 ACTION_OF_SET_VLAN_PCP_VLAN_PCP,
1970 static const enum index action_of_pop_mpls[] = {
1971 ACTION_OF_POP_MPLS_ETHERTYPE,
1976 static const enum index action_of_push_mpls[] = {
1977 ACTION_OF_PUSH_MPLS_ETHERTYPE,
1982 static const enum index action_set_ipv4_src[] = {
1983 ACTION_SET_IPV4_SRC_IPV4_SRC,
1988 static const enum index action_set_mac_src[] = {
1989 ACTION_SET_MAC_SRC_MAC_SRC,
1994 static const enum index action_set_ipv4_dst[] = {
1995 ACTION_SET_IPV4_DST_IPV4_DST,
2000 static const enum index action_set_ipv6_src[] = {
2001 ACTION_SET_IPV6_SRC_IPV6_SRC,
2006 static const enum index action_set_ipv6_dst[] = {
2007 ACTION_SET_IPV6_DST_IPV6_DST,
2012 static const enum index action_set_tp_src[] = {
2013 ACTION_SET_TP_SRC_TP_SRC,
2018 static const enum index action_set_tp_dst[] = {
2019 ACTION_SET_TP_DST_TP_DST,
2024 static const enum index action_set_ttl[] = {
2030 static const enum index action_jump[] = {
2036 static const enum index action_set_mac_dst[] = {
2037 ACTION_SET_MAC_DST_MAC_DST,
2042 static const enum index action_inc_tcp_seq[] = {
2043 ACTION_INC_TCP_SEQ_VALUE,
2048 static const enum index action_dec_tcp_seq[] = {
2049 ACTION_DEC_TCP_SEQ_VALUE,
2054 static const enum index action_inc_tcp_ack[] = {
2055 ACTION_INC_TCP_ACK_VALUE,
2060 static const enum index action_dec_tcp_ack[] = {
2061 ACTION_DEC_TCP_ACK_VALUE,
2066 static const enum index action_raw_encap[] = {
2067 ACTION_RAW_ENCAP_INDEX,
2072 static const enum index action_raw_decap[] = {
2073 ACTION_RAW_DECAP_INDEX,
2078 static const enum index action_set_tag[] = {
2079 ACTION_SET_TAG_DATA,
2080 ACTION_SET_TAG_INDEX,
2081 ACTION_SET_TAG_MASK,
2086 static const enum index action_set_meta[] = {
2087 ACTION_SET_META_DATA,
2088 ACTION_SET_META_MASK,
2093 static const enum index action_set_ipv4_dscp[] = {
2094 ACTION_SET_IPV4_DSCP_VALUE,
2099 static const enum index action_set_ipv6_dscp[] = {
2100 ACTION_SET_IPV6_DSCP_VALUE,
2105 static const enum index action_age[] = {
2112 static const enum index action_sample[] = {
2114 ACTION_SAMPLE_RATIO,
2115 ACTION_SAMPLE_INDEX,
2120 static const enum index next_action_sample[] = {
2133 static const enum index action_modify_field_dst[] = {
2134 ACTION_MODIFY_FIELD_DST_LEVEL,
2135 ACTION_MODIFY_FIELD_DST_OFFSET,
2136 ACTION_MODIFY_FIELD_SRC_TYPE,
2140 static const enum index action_modify_field_src[] = {
2141 ACTION_MODIFY_FIELD_SRC_LEVEL,
2142 ACTION_MODIFY_FIELD_SRC_OFFSET,
2143 ACTION_MODIFY_FIELD_SRC_VALUE,
2144 ACTION_MODIFY_FIELD_SRC_POINTER,
2145 ACTION_MODIFY_FIELD_WIDTH,
2149 static const enum index action_update_conntrack[] = {
2150 ACTION_CONNTRACK_UPDATE_DIR,
2151 ACTION_CONNTRACK_UPDATE_CTX,
2156 static const enum index action_port_representor[] = {
2157 ACTION_PORT_REPRESENTOR_PORT_ID,
2162 static const enum index action_represented_port[] = {
2163 ACTION_REPRESENTED_PORT_ETHDEV_PORT_ID,
2168 static int parse_set_raw_encap_decap(struct context *, const struct token *,
2169 const char *, unsigned int,
2170 void *, unsigned int);
2171 static int parse_set_sample_action(struct context *, const struct token *,
2172 const char *, unsigned int,
2173 void *, unsigned int);
2174 static int parse_set_init(struct context *, const struct token *,
2175 const char *, unsigned int,
2176 void *, unsigned int);
2178 parse_flex_handle(struct context *, const struct token *,
2179 const char *, unsigned int, void *, unsigned int);
2180 static int parse_init(struct context *, const struct token *,
2181 const char *, unsigned int,
2182 void *, unsigned int);
2183 static int parse_vc(struct context *, const struct token *,
2184 const char *, unsigned int,
2185 void *, unsigned int);
2186 static int parse_vc_spec(struct context *, const struct token *,
2187 const char *, unsigned int, void *, unsigned int);
2188 static int parse_vc_conf(struct context *, const struct token *,
2189 const char *, unsigned int, void *, unsigned int);
2190 static int parse_vc_item_ecpri_type(struct context *, const struct token *,
2191 const char *, unsigned int,
2192 void *, unsigned int);
2193 static int parse_vc_item_l2tpv2_type(struct context *, const struct token *,
2194 const char *, unsigned int,
2195 void *, unsigned int);
2196 static int parse_vc_action_meter_color_type(struct context *,
2197 const struct token *,
2198 const char *, unsigned int, void *,
2200 static int parse_vc_action_rss(struct context *, const struct token *,
2201 const char *, unsigned int, void *,
2203 static int parse_vc_action_rss_func(struct context *, const struct token *,
2204 const char *, unsigned int, void *,
2206 static int parse_vc_action_rss_type(struct context *, const struct token *,
2207 const char *, unsigned int, void *,
2209 static int parse_vc_action_rss_queue(struct context *, const struct token *,
2210 const char *, unsigned int, void *,
2212 static int parse_vc_action_vxlan_encap(struct context *, const struct token *,
2213 const char *, unsigned int, void *,
2215 static int parse_vc_action_nvgre_encap(struct context *, const struct token *,
2216 const char *, unsigned int, void *,
2218 static int parse_vc_action_l2_encap(struct context *, const struct token *,
2219 const char *, unsigned int, void *,
2221 static int parse_vc_action_l2_decap(struct context *, const struct token *,
2222 const char *, unsigned int, void *,
2224 static int parse_vc_action_mplsogre_encap(struct context *,
2225 const struct token *, const char *,
2226 unsigned int, void *, unsigned int);
2227 static int parse_vc_action_mplsogre_decap(struct context *,
2228 const struct token *, const char *,
2229 unsigned int, void *, unsigned int);
2230 static int parse_vc_action_mplsoudp_encap(struct context *,
2231 const struct token *, const char *,
2232 unsigned int, void *, unsigned int);
2233 static int parse_vc_action_mplsoudp_decap(struct context *,
2234 const struct token *, const char *,
2235 unsigned int, void *, unsigned int);
2236 static int parse_vc_action_raw_encap(struct context *,
2237 const struct token *, const char *,
2238 unsigned int, void *, unsigned int);
2239 static int parse_vc_action_raw_decap(struct context *,
2240 const struct token *, const char *,
2241 unsigned int, void *, unsigned int);
2242 static int parse_vc_action_raw_encap_index(struct context *,
2243 const struct token *, const char *,
2244 unsigned int, void *, unsigned int);
2245 static int parse_vc_action_raw_decap_index(struct context *,
2246 const struct token *, const char *,
2247 unsigned int, void *, unsigned int);
2248 static int parse_vc_action_set_meta(struct context *ctx,
2249 const struct token *token, const char *str,
2250 unsigned int len, void *buf,
2252 static int parse_vc_action_sample(struct context *ctx,
2253 const struct token *token, const char *str,
2254 unsigned int len, void *buf,
2257 parse_vc_action_sample_index(struct context *ctx, const struct token *token,
2258 const char *str, unsigned int len, void *buf,
2261 parse_vc_modify_field_op(struct context *ctx, const struct token *token,
2262 const char *str, unsigned int len, void *buf,
2265 parse_vc_modify_field_id(struct context *ctx, const struct token *token,
2266 const char *str, unsigned int len, void *buf,
2269 parse_vc_action_conntrack_update(struct context *ctx, const struct token *token,
2270 const char *str, unsigned int len, void *buf,
2272 static int parse_destroy(struct context *, const struct token *,
2273 const char *, unsigned int,
2274 void *, unsigned int);
2275 static int parse_flush(struct context *, const struct token *,
2276 const char *, unsigned int,
2277 void *, unsigned int);
2278 static int parse_dump(struct context *, const struct token *,
2279 const char *, unsigned int,
2280 void *, unsigned int);
2281 static int parse_query(struct context *, const struct token *,
2282 const char *, unsigned int,
2283 void *, unsigned int);
2284 static int parse_action(struct context *, const struct token *,
2285 const char *, unsigned int,
2286 void *, unsigned int);
2287 static int parse_list(struct context *, const struct token *,
2288 const char *, unsigned int,
2289 void *, unsigned int);
2290 static int parse_aged(struct context *, const struct token *,
2291 const char *, unsigned int,
2292 void *, unsigned int);
2293 static int parse_isolate(struct context *, const struct token *,
2294 const char *, unsigned int,
2295 void *, unsigned int);
2296 static int parse_configure(struct context *, const struct token *,
2297 const char *, unsigned int,
2298 void *, unsigned int);
2299 static int parse_template(struct context *, const struct token *,
2300 const char *, unsigned int,
2301 void *, unsigned int);
2302 static int parse_template_destroy(struct context *, const struct token *,
2303 const char *, unsigned int,
2304 void *, unsigned int);
2305 static int parse_table(struct context *, const struct token *,
2306 const char *, unsigned int, void *, unsigned int);
2307 static int parse_table_destroy(struct context *, const struct token *,
2308 const char *, unsigned int,
2309 void *, unsigned int);
2310 static int parse_qo(struct context *, const struct token *,
2311 const char *, unsigned int,
2312 void *, unsigned int);
2313 static int parse_qo_destroy(struct context *, const struct token *,
2314 const char *, unsigned int,
2315 void *, unsigned int);
2316 static int parse_qia(struct context *, const struct token *,
2317 const char *, unsigned int,
2318 void *, unsigned int);
2319 static int parse_qia_destroy(struct context *, const struct token *,
2320 const char *, unsigned int,
2321 void *, unsigned int);
2322 static int parse_push(struct context *, const struct token *,
2323 const char *, unsigned int,
2324 void *, unsigned int);
2325 static int parse_pull(struct context *, const struct token *,
2326 const char *, unsigned int,
2327 void *, unsigned int);
2328 static int parse_tunnel(struct context *, const struct token *,
2329 const char *, unsigned int,
2330 void *, unsigned int);
2331 static int parse_flex(struct context *, const struct token *,
2332 const char *, unsigned int, void *, unsigned int);
2333 static int parse_int(struct context *, const struct token *,
2334 const char *, unsigned int,
2335 void *, unsigned int);
2336 static int parse_prefix(struct context *, const struct token *,
2337 const char *, unsigned int,
2338 void *, unsigned int);
2339 static int parse_boolean(struct context *, const struct token *,
2340 const char *, unsigned int,
2341 void *, unsigned int);
2342 static int parse_string(struct context *, const struct token *,
2343 const char *, unsigned int,
2344 void *, unsigned int);
2345 static int parse_hex(struct context *ctx, const struct token *token,
2346 const char *str, unsigned int len,
2347 void *buf, unsigned int size);
2348 static int parse_string0(struct context *, const struct token *,
2349 const char *, unsigned int,
2350 void *, unsigned int);
2351 static int parse_mac_addr(struct context *, const struct token *,
2352 const char *, unsigned int,
2353 void *, unsigned int);
2354 static int parse_ipv4_addr(struct context *, const struct token *,
2355 const char *, unsigned int,
2356 void *, unsigned int);
2357 static int parse_ipv6_addr(struct context *, const struct token *,
2358 const char *, unsigned int,
2359 void *, unsigned int);
2360 static int parse_port(struct context *, const struct token *,
2361 const char *, unsigned int,
2362 void *, unsigned int);
2363 static int parse_ia(struct context *, const struct token *,
2364 const char *, unsigned int,
2365 void *, unsigned int);
2366 static int parse_ia_destroy(struct context *ctx, const struct token *token,
2367 const char *str, unsigned int len,
2368 void *buf, unsigned int size);
2369 static int parse_ia_id2ptr(struct context *ctx, const struct token *token,
2370 const char *str, unsigned int len, void *buf,
2372 static int parse_mp(struct context *, const struct token *,
2373 const char *, unsigned int,
2374 void *, unsigned int);
2375 static int comp_none(struct context *, const struct token *,
2376 unsigned int, char *, unsigned int);
2377 static int comp_boolean(struct context *, const struct token *,
2378 unsigned int, char *, unsigned int);
2379 static int comp_action(struct context *, const struct token *,
2380 unsigned int, char *, unsigned int);
2381 static int comp_port(struct context *, const struct token *,
2382 unsigned int, char *, unsigned int);
2383 static int comp_rule_id(struct context *, const struct token *,
2384 unsigned int, char *, unsigned int);
2385 static int comp_vc_action_rss_type(struct context *, const struct token *,
2386 unsigned int, char *, unsigned int);
2387 static int comp_vc_action_rss_queue(struct context *, const struct token *,
2388 unsigned int, char *, unsigned int);
2389 static int comp_set_raw_index(struct context *, const struct token *,
2390 unsigned int, char *, unsigned int);
2391 static int comp_set_sample_index(struct context *, const struct token *,
2392 unsigned int, char *, unsigned int);
2393 static int comp_set_modify_field_op(struct context *, const struct token *,
2394 unsigned int, char *, unsigned int);
2395 static int comp_set_modify_field_id(struct context *, const struct token *,
2396 unsigned int, char *, unsigned int);
2397 static int comp_pattern_template_id(struct context *, const struct token *,
2398 unsigned int, char *, unsigned int);
2399 static int comp_actions_template_id(struct context *, const struct token *,
2400 unsigned int, char *, unsigned int);
2401 static int comp_table_id(struct context *, const struct token *,
2402 unsigned int, char *, unsigned int);
2403 static int comp_queue_id(struct context *, const struct token *,
2404 unsigned int, char *, unsigned int);
2406 /** Token definitions. */
2407 static const struct token token_list[] = {
2408 /* Special tokens. */
2411 .help = "null entry, abused as the entry point",
2412 .next = NEXT(NEXT_ENTRY(FLOW, ADD)),
2417 .help = "command may end here",
2420 .name = "START_SET",
2421 .help = "null entry, abused as the entry point for set",
2422 .next = NEXT(NEXT_ENTRY(SET)),
2427 .help = "set command may end here",
2429 /* Common tokens. */
2430 [COMMON_INTEGER] = {
2433 .help = "integer value",
2437 [COMMON_UNSIGNED] = {
2438 .name = "{unsigned}",
2440 .help = "unsigned integer value",
2447 .help = "prefix length for bit-mask",
2448 .call = parse_prefix,
2451 [COMMON_BOOLEAN] = {
2452 .name = "{boolean}",
2454 .help = "any boolean value",
2455 .call = parse_boolean,
2456 .comp = comp_boolean,
2461 .help = "fixed string",
2462 .call = parse_string,
2468 .help = "fixed string",
2471 [COMMON_FILE_PATH] = {
2472 .name = "{file path}",
2474 .help = "file path",
2475 .call = parse_string0,
2478 [COMMON_MAC_ADDR] = {
2479 .name = "{MAC address}",
2481 .help = "standard MAC address notation",
2482 .call = parse_mac_addr,
2485 [COMMON_IPV4_ADDR] = {
2486 .name = "{IPv4 address}",
2487 .type = "IPV4 ADDRESS",
2488 .help = "standard IPv4 address notation",
2489 .call = parse_ipv4_addr,
2492 [COMMON_IPV6_ADDR] = {
2493 .name = "{IPv6 address}",
2494 .type = "IPV6 ADDRESS",
2495 .help = "standard IPv6 address notation",
2496 .call = parse_ipv6_addr,
2499 [COMMON_RULE_ID] = {
2500 .name = "{rule id}",
2502 .help = "rule identifier",
2504 .comp = comp_rule_id,
2506 [COMMON_PORT_ID] = {
2507 .name = "{port_id}",
2509 .help = "port identifier",
2513 [COMMON_GROUP_ID] = {
2514 .name = "{group_id}",
2516 .help = "group identifier",
2520 [COMMON_PRIORITY_LEVEL] = {
2523 .help = "priority level",
2527 [COMMON_INDIRECT_ACTION_ID] = {
2528 .name = "{indirect_action_id}",
2529 .type = "INDIRECT_ACTION_ID",
2530 .help = "indirect action id",
2534 [COMMON_POLICY_ID] = {
2535 .name = "{policy_id}",
2536 .type = "POLICY_ID",
2537 .help = "policy id",
2541 [COMMON_FLEX_TOKEN] = {
2542 .name = "{flex token}",
2543 .type = "flex token",
2544 .help = "flex token",
2548 [COMMON_FLEX_HANDLE] = {
2549 .name = "{flex handle}",
2550 .type = "FLEX HANDLE",
2551 .help = "fill flex item data",
2552 .call = parse_flex_handle,
2555 [COMMON_PATTERN_TEMPLATE_ID] = {
2556 .name = "{pattern_template_id}",
2557 .type = "PATTERN_TEMPLATE_ID",
2558 .help = "pattern template id",
2560 .comp = comp_pattern_template_id,
2562 [COMMON_ACTIONS_TEMPLATE_ID] = {
2563 .name = "{actions_template_id}",
2564 .type = "ACTIONS_TEMPLATE_ID",
2565 .help = "actions template id",
2567 .comp = comp_actions_template_id,
2569 [COMMON_TABLE_ID] = {
2570 .name = "{table_id}",
2574 .comp = comp_table_id,
2576 [COMMON_QUEUE_ID] = {
2577 .name = "{queue_id}",
2581 .comp = comp_queue_id,
2583 /* Top-level command. */
2586 .type = "{command} {port_id} [{arg} [...]]",
2587 .help = "manage ingress/egress flow rules",
2588 .next = NEXT(NEXT_ENTRY
2611 /* Top-level command. */
2614 .help = "get information about flow engine",
2615 .next = NEXT(NEXT_ENTRY(END),
2616 NEXT_ENTRY(COMMON_PORT_ID)),
2617 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2618 .call = parse_configure,
2620 /* Top-level command. */
2622 .name = "configure",
2623 .help = "configure flow engine",
2624 .next = NEXT(next_config_attr,
2625 NEXT_ENTRY(COMMON_PORT_ID)),
2626 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2627 .call = parse_configure,
2629 /* Configure arguments. */
2630 [CONFIG_QUEUES_NUMBER] = {
2631 .name = "queues_number",
2632 .help = "number of queues",
2633 .next = NEXT(next_config_attr,
2634 NEXT_ENTRY(COMMON_UNSIGNED)),
2635 .args = ARGS(ARGS_ENTRY(struct buffer,
2636 args.configure.nb_queue)),
2638 [CONFIG_QUEUES_SIZE] = {
2639 .name = "queues_size",
2640 .help = "number of elements in queues",
2641 .next = NEXT(next_config_attr,
2642 NEXT_ENTRY(COMMON_UNSIGNED)),
2643 .args = ARGS(ARGS_ENTRY(struct buffer,
2644 args.configure.queue_attr.size)),
2646 [CONFIG_COUNTERS_NUMBER] = {
2647 .name = "counters_number",
2648 .help = "number of counters",
2649 .next = NEXT(next_config_attr,
2650 NEXT_ENTRY(COMMON_UNSIGNED)),
2651 .args = ARGS(ARGS_ENTRY(struct buffer,
2652 args.configure.port_attr.nb_counters)),
2654 [CONFIG_AGING_OBJECTS_NUMBER] = {
2655 .name = "aging_counters_number",
2656 .help = "number of aging objects",
2657 .next = NEXT(next_config_attr,
2658 NEXT_ENTRY(COMMON_UNSIGNED)),
2659 .args = ARGS(ARGS_ENTRY(struct buffer,
2660 args.configure.port_attr.nb_aging_objects)),
2662 [CONFIG_METERS_NUMBER] = {
2663 .name = "meters_number",
2664 .help = "number of meters",
2665 .next = NEXT(next_config_attr,
2666 NEXT_ENTRY(COMMON_UNSIGNED)),
2667 .args = ARGS(ARGS_ENTRY(struct buffer,
2668 args.configure.port_attr.nb_meters)),
2670 /* Top-level command. */
2671 [PATTERN_TEMPLATE] = {
2672 .name = "pattern_template",
2673 .type = "{command} {port_id} [{arg} [...]]",
2674 .help = "manage pattern templates",
2675 .next = NEXT(next_pt_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
2676 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2677 .call = parse_template,
2679 /* Sub-level commands. */
2680 [PATTERN_TEMPLATE_CREATE] = {
2682 .help = "create pattern template",
2683 .next = NEXT(next_pt_attr),
2684 .call = parse_template,
2686 [PATTERN_TEMPLATE_DESTROY] = {
2688 .help = "destroy pattern template",
2689 .next = NEXT(NEXT_ENTRY(PATTERN_TEMPLATE_DESTROY_ID)),
2690 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2691 .call = parse_template_destroy,
2693 /* Pattern template arguments. */
2694 [PATTERN_TEMPLATE_CREATE_ID] = {
2695 .name = "pattern_template_id",
2696 .help = "specify a pattern template id to create",
2697 .next = NEXT(next_pt_attr,
2698 NEXT_ENTRY(COMMON_PATTERN_TEMPLATE_ID)),
2699 .args = ARGS(ARGS_ENTRY(struct buffer, args.vc.pat_templ_id)),
2701 [PATTERN_TEMPLATE_DESTROY_ID] = {
2702 .name = "pattern_template",
2703 .help = "specify a pattern template id to destroy",
2704 .next = NEXT(next_pt_destroy_attr,
2705 NEXT_ENTRY(COMMON_PATTERN_TEMPLATE_ID)),
2706 .args = ARGS(ARGS_ENTRY_PTR(struct buffer,
2707 args.templ_destroy.template_id)),
2708 .call = parse_template_destroy,
2710 [PATTERN_TEMPLATE_RELAXED_MATCHING] = {
2712 .help = "is matching relaxed",
2713 .next = NEXT(next_pt_attr,
2714 NEXT_ENTRY(COMMON_BOOLEAN)),
2715 .args = ARGS(ARGS_ENTRY_BF(struct buffer,
2716 args.vc.attr.reserved, 1)),
2718 [PATTERN_TEMPLATE_INGRESS] = {
2720 .help = "attribute pattern to ingress",
2721 .next = NEXT(next_pt_attr),
2722 .call = parse_template,
2724 [PATTERN_TEMPLATE_EGRESS] = {
2726 .help = "attribute pattern to egress",
2727 .next = NEXT(next_pt_attr),
2728 .call = parse_template,
2730 [PATTERN_TEMPLATE_TRANSFER] = {
2732 .help = "attribute pattern to transfer",
2733 .next = NEXT(next_pt_attr),
2734 .call = parse_template,
2736 [PATTERN_TEMPLATE_SPEC] = {
2738 .help = "specify item to create pattern template",
2739 .next = NEXT(next_item),
2741 /* Top-level command. */
2742 [ACTIONS_TEMPLATE] = {
2743 .name = "actions_template",
2744 .type = "{command} {port_id} [{arg} [...]]",
2745 .help = "manage actions templates",
2746 .next = NEXT(next_at_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
2747 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2748 .call = parse_template,
2750 /* Sub-level commands. */
2751 [ACTIONS_TEMPLATE_CREATE] = {
2753 .help = "create actions template",
2754 .next = NEXT(next_at_attr),
2755 .call = parse_template,
2757 [ACTIONS_TEMPLATE_DESTROY] = {
2759 .help = "destroy actions template",
2760 .next = NEXT(NEXT_ENTRY(ACTIONS_TEMPLATE_DESTROY_ID)),
2761 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2762 .call = parse_template_destroy,
2764 /* Actions template arguments. */
2765 [ACTIONS_TEMPLATE_CREATE_ID] = {
2766 .name = "actions_template_id",
2767 .help = "specify an actions template id to create",
2768 .next = NEXT(NEXT_ENTRY(ACTIONS_TEMPLATE_MASK),
2769 NEXT_ENTRY(ACTIONS_TEMPLATE_SPEC),
2770 NEXT_ENTRY(COMMON_ACTIONS_TEMPLATE_ID)),
2771 .args = ARGS(ARGS_ENTRY(struct buffer, args.vc.act_templ_id)),
2773 [ACTIONS_TEMPLATE_DESTROY_ID] = {
2774 .name = "actions_template",
2775 .help = "specify an actions template id to destroy",
2776 .next = NEXT(next_at_destroy_attr,
2777 NEXT_ENTRY(COMMON_ACTIONS_TEMPLATE_ID)),
2778 .args = ARGS(ARGS_ENTRY_PTR(struct buffer,
2779 args.templ_destroy.template_id)),
2780 .call = parse_template_destroy,
2782 [ACTIONS_TEMPLATE_INGRESS] = {
2784 .help = "attribute actions to ingress",
2785 .next = NEXT(next_at_attr),
2786 .call = parse_template,
2788 [ACTIONS_TEMPLATE_EGRESS] = {
2790 .help = "attribute actions to egress",
2791 .next = NEXT(next_at_attr),
2792 .call = parse_template,
2794 [ACTIONS_TEMPLATE_TRANSFER] = {
2796 .help = "attribute actions to transfer",
2797 .next = NEXT(next_at_attr),
2798 .call = parse_template,
2800 [ACTIONS_TEMPLATE_SPEC] = {
2802 .help = "specify action to create actions template",
2803 .next = NEXT(next_action),
2804 .call = parse_template,
2806 [ACTIONS_TEMPLATE_MASK] = {
2808 .help = "specify action mask to create actions template",
2809 .next = NEXT(next_action),
2810 .call = parse_template,
2812 /* Top-level command. */
2814 .name = "template_table",
2815 .type = "{command} {port_id} [{arg} [...]]",
2816 .help = "manage template tables",
2817 .next = NEXT(next_table_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
2818 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2819 .call = parse_table,
2821 /* Sub-level commands. */
2824 .help = "create template table",
2825 .next = NEXT(next_table_attr),
2826 .call = parse_table,
2830 .help = "destroy template table",
2831 .next = NEXT(NEXT_ENTRY(TABLE_DESTROY_ID)),
2832 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2833 .call = parse_table_destroy,
2835 /* Table arguments. */
2836 [TABLE_CREATE_ID] = {
2838 .help = "specify table id to create",
2839 .next = NEXT(next_table_attr,
2840 NEXT_ENTRY(COMMON_TABLE_ID)),
2841 .args = ARGS(ARGS_ENTRY(struct buffer, args.table.id)),
2843 [TABLE_DESTROY_ID] = {
2845 .help = "specify table id to destroy",
2846 .next = NEXT(next_table_destroy_attr,
2847 NEXT_ENTRY(COMMON_TABLE_ID)),
2848 .args = ARGS(ARGS_ENTRY_PTR(struct buffer,
2849 args.table_destroy.table_id)),
2850 .call = parse_table_destroy,
2854 .help = "specify a group",
2855 .next = NEXT(next_table_attr, NEXT_ENTRY(COMMON_GROUP_ID)),
2856 .args = ARGS(ARGS_ENTRY(struct buffer,
2857 args.table.attr.flow_attr.group)),
2859 [TABLE_PRIORITY] = {
2861 .help = "specify a priority level",
2862 .next = NEXT(next_table_attr, NEXT_ENTRY(COMMON_PRIORITY_LEVEL)),
2863 .args = ARGS(ARGS_ENTRY(struct buffer,
2864 args.table.attr.flow_attr.priority)),
2868 .help = "affect rule to egress",
2869 .next = NEXT(next_table_attr),
2870 .call = parse_table,
2874 .help = "affect rule to ingress",
2875 .next = NEXT(next_table_attr),
2876 .call = parse_table,
2878 [TABLE_TRANSFER] = {
2880 .help = "affect rule to transfer",
2881 .next = NEXT(next_table_attr),
2882 .call = parse_table,
2884 [TABLE_RULES_NUMBER] = {
2885 .name = "rules_number",
2886 .help = "number of rules in table",
2887 .next = NEXT(next_table_attr,
2888 NEXT_ENTRY(COMMON_UNSIGNED)),
2889 .args = ARGS(ARGS_ENTRY(struct buffer,
2890 args.table.attr.nb_flows)),
2892 [TABLE_PATTERN_TEMPLATE] = {
2893 .name = "pattern_template",
2894 .help = "specify pattern template id",
2895 .next = NEXT(next_table_attr,
2896 NEXT_ENTRY(COMMON_PATTERN_TEMPLATE_ID)),
2897 .args = ARGS(ARGS_ENTRY_PTR(struct buffer,
2898 args.table.pat_templ_id)),
2899 .call = parse_table,
2901 [TABLE_ACTIONS_TEMPLATE] = {
2902 .name = "actions_template",
2903 .help = "specify actions template id",
2904 .next = NEXT(next_table_attr,
2905 NEXT_ENTRY(COMMON_ACTIONS_TEMPLATE_ID)),
2906 .args = ARGS(ARGS_ENTRY_PTR(struct buffer,
2907 args.table.act_templ_id)),
2908 .call = parse_table,
2910 /* Top-level command. */
2913 .help = "queue a flow rule operation",
2914 .next = NEXT(next_queue_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
2915 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2918 /* Sub-level commands. */
2921 .help = "create a flow rule",
2922 .next = NEXT(NEXT_ENTRY(QUEUE_TEMPLATE_TABLE),
2923 NEXT_ENTRY(COMMON_QUEUE_ID)),
2924 .args = ARGS(ARGS_ENTRY(struct buffer, queue)),
2929 .help = "destroy a flow rule",
2930 .next = NEXT(NEXT_ENTRY(QUEUE_DESTROY_ID),
2931 NEXT_ENTRY(COMMON_QUEUE_ID)),
2932 .args = ARGS(ARGS_ENTRY(struct buffer, queue)),
2933 .call = parse_qo_destroy,
2935 [QUEUE_INDIRECT_ACTION] = {
2936 .name = "indirect_action",
2937 .help = "queue indirect actions",
2938 .next = NEXT(next_qia_subcmd, NEXT_ENTRY(COMMON_QUEUE_ID)),
2939 .args = ARGS(ARGS_ENTRY(struct buffer, queue)),
2942 /* Queue arguments. */
2943 [QUEUE_TEMPLATE_TABLE] = {
2944 .name = "template table",
2945 .help = "specify table id",
2946 .next = NEXT(NEXT_ENTRY(QUEUE_PATTERN_TEMPLATE),
2947 NEXT_ENTRY(COMMON_TABLE_ID)),
2948 .args = ARGS(ARGS_ENTRY(struct buffer,
2952 [QUEUE_PATTERN_TEMPLATE] = {
2953 .name = "pattern_template",
2954 .help = "specify pattern template index",
2955 .next = NEXT(NEXT_ENTRY(QUEUE_ACTIONS_TEMPLATE),
2956 NEXT_ENTRY(COMMON_UNSIGNED)),
2957 .args = ARGS(ARGS_ENTRY(struct buffer,
2958 args.vc.pat_templ_id)),
2961 [QUEUE_ACTIONS_TEMPLATE] = {
2962 .name = "actions_template",
2963 .help = "specify actions template index",
2964 .next = NEXT(NEXT_ENTRY(QUEUE_CREATE_POSTPONE),
2965 NEXT_ENTRY(COMMON_UNSIGNED)),
2966 .args = ARGS(ARGS_ENTRY(struct buffer,
2967 args.vc.act_templ_id)),
2970 [QUEUE_CREATE_POSTPONE] = {
2972 .help = "postpone create operation",
2973 .next = NEXT(NEXT_ENTRY(ITEM_PATTERN),
2974 NEXT_ENTRY(COMMON_BOOLEAN)),
2975 .args = ARGS(ARGS_ENTRY(struct buffer, postpone)),
2978 [QUEUE_DESTROY_POSTPONE] = {
2980 .help = "postpone destroy operation",
2981 .next = NEXT(NEXT_ENTRY(QUEUE_DESTROY_ID),
2982 NEXT_ENTRY(COMMON_BOOLEAN)),
2983 .args = ARGS(ARGS_ENTRY(struct buffer, postpone)),
2984 .call = parse_qo_destroy,
2986 [QUEUE_DESTROY_ID] = {
2988 .help = "specify rule id to destroy",
2989 .next = NEXT(next_queue_destroy_attr,
2990 NEXT_ENTRY(COMMON_UNSIGNED)),
2991 .args = ARGS(ARGS_ENTRY_PTR(struct buffer,
2992 args.destroy.rule)),
2993 .call = parse_qo_destroy,
2995 /* Queue indirect action arguments */
2996 [QUEUE_INDIRECT_ACTION_CREATE] = {
2998 .help = "create indirect action",
2999 .next = NEXT(next_qia_create_attr),
3002 [QUEUE_INDIRECT_ACTION_UPDATE] = {
3004 .help = "update indirect action",
3005 .next = NEXT(next_qia_update_attr,
3006 NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
3007 .args = ARGS(ARGS_ENTRY(struct buffer, args.vc.attr.group)),
3010 [QUEUE_INDIRECT_ACTION_DESTROY] = {
3012 .help = "destroy indirect action",
3013 .next = NEXT(next_qia_destroy_attr),
3014 .call = parse_qia_destroy,
3016 /* Indirect action destroy arguments. */
3017 [QUEUE_INDIRECT_ACTION_DESTROY_POSTPONE] = {
3019 .help = "postpone destroy operation",
3020 .next = NEXT(next_qia_destroy_attr,
3021 NEXT_ENTRY(COMMON_BOOLEAN)),
3022 .args = ARGS(ARGS_ENTRY(struct buffer, postpone)),
3024 [QUEUE_INDIRECT_ACTION_DESTROY_ID] = {
3025 .name = "action_id",
3026 .help = "specify a indirect action id to destroy",
3027 .next = NEXT(next_qia_destroy_attr,
3028 NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
3029 .args = ARGS(ARGS_ENTRY_PTR(struct buffer,
3030 args.ia_destroy.action_id)),
3031 .call = parse_qia_destroy,
3033 /* Indirect action update arguments. */
3034 [QUEUE_INDIRECT_ACTION_UPDATE_POSTPONE] = {
3036 .help = "postpone update operation",
3037 .next = NEXT(next_qia_update_attr,
3038 NEXT_ENTRY(COMMON_BOOLEAN)),
3039 .args = ARGS(ARGS_ENTRY(struct buffer, postpone)),
3041 /* Indirect action create arguments. */
3042 [QUEUE_INDIRECT_ACTION_CREATE_ID] = {
3043 .name = "action_id",
3044 .help = "specify a indirect action id to create",
3045 .next = NEXT(next_qia_create_attr,
3046 NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
3047 .args = ARGS(ARGS_ENTRY(struct buffer, args.vc.attr.group)),
3049 [QUEUE_INDIRECT_ACTION_INGRESS] = {
3051 .help = "affect rule to ingress",
3052 .next = NEXT(next_qia_create_attr),
3055 [QUEUE_INDIRECT_ACTION_EGRESS] = {
3057 .help = "affect rule to egress",
3058 .next = NEXT(next_qia_create_attr),
3061 [QUEUE_INDIRECT_ACTION_TRANSFER] = {
3063 .help = "affect rule to transfer",
3064 .next = NEXT(next_qia_create_attr),
3067 [QUEUE_INDIRECT_ACTION_CREATE_POSTPONE] = {
3069 .help = "postpone create operation",
3070 .next = NEXT(next_qia_create_attr,
3071 NEXT_ENTRY(COMMON_BOOLEAN)),
3072 .args = ARGS(ARGS_ENTRY(struct buffer, postpone)),
3074 [QUEUE_INDIRECT_ACTION_SPEC] = {
3076 .help = "specify action to create indirect handle",
3077 .next = NEXT(next_action),
3079 /* Top-level command. */
3082 .help = "push enqueued operations",
3083 .next = NEXT(NEXT_ENTRY(PUSH_QUEUE), NEXT_ENTRY(COMMON_PORT_ID)),
3084 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
3087 /* Sub-level commands. */
3090 .help = "specify queue id",
3091 .next = NEXT(NEXT_ENTRY(END), NEXT_ENTRY(COMMON_QUEUE_ID)),
3092 .args = ARGS(ARGS_ENTRY(struct buffer, queue)),
3094 /* Top-level command. */
3097 .help = "pull flow operations results",
3098 .next = NEXT(NEXT_ENTRY(PULL_QUEUE), NEXT_ENTRY(COMMON_PORT_ID)),
3099 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
3102 /* Sub-level commands. */
3105 .help = "specify queue id",
3106 .next = NEXT(NEXT_ENTRY(END), NEXT_ENTRY(COMMON_QUEUE_ID)),
3107 .args = ARGS(ARGS_ENTRY(struct buffer, queue)),
3109 /* Top-level command. */
3110 [INDIRECT_ACTION] = {
3111 .name = "indirect_action",
3112 .type = "{command} {port_id} [{arg} [...]]",
3113 .help = "manage indirect actions",
3114 .next = NEXT(next_ia_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
3115 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
3118 /* Sub-level commands. */
3119 [INDIRECT_ACTION_CREATE] = {
3121 .help = "create indirect action",
3122 .next = NEXT(next_ia_create_attr),
3125 [INDIRECT_ACTION_UPDATE] = {
3127 .help = "update indirect action",
3128 .next = NEXT(NEXT_ENTRY(INDIRECT_ACTION_SPEC),
3129 NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
3130 .args = ARGS(ARGS_ENTRY(struct buffer, args.vc.attr.group)),
3133 [INDIRECT_ACTION_DESTROY] = {
3135 .help = "destroy indirect action",
3136 .next = NEXT(NEXT_ENTRY(INDIRECT_ACTION_DESTROY_ID)),
3137 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
3138 .call = parse_ia_destroy,
3140 [INDIRECT_ACTION_QUERY] = {
3142 .help = "query indirect action",
3143 .next = NEXT(NEXT_ENTRY(END),
3144 NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
3145 .args = ARGS(ARGS_ENTRY(struct buffer, args.ia.action_id)),
3150 .help = "check whether a flow rule can be created",
3151 .next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_PORT_ID)),
3152 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
3157 .help = "create a flow rule",
3158 .next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_PORT_ID)),
3159 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
3164 .help = "destroy specific flow rules",
3165 .next = NEXT(NEXT_ENTRY(DESTROY_RULE),
3166 NEXT_ENTRY(COMMON_PORT_ID)),
3167 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
3168 .call = parse_destroy,
3172 .help = "destroy all flow rules",
3173 .next = NEXT(NEXT_ENTRY(COMMON_PORT_ID)),
3174 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
3175 .call = parse_flush,
3179 .help = "dump single/all flow rules to file",
3180 .next = NEXT(next_dump_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
3181 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
3186 .help = "query an existing flow rule",
3187 .next = NEXT(NEXT_ENTRY(QUERY_ACTION),
3188 NEXT_ENTRY(COMMON_RULE_ID),
3189 NEXT_ENTRY(COMMON_PORT_ID)),
3190 .args = ARGS(ARGS_ENTRY(struct buffer, args.query.action.type),
3191 ARGS_ENTRY(struct buffer, args.query.rule),
3192 ARGS_ENTRY(struct buffer, port)),
3193 .call = parse_query,
3197 .help = "list existing flow rules",
3198 .next = NEXT(next_list_attr, NEXT_ENTRY(COMMON_PORT_ID)),
3199 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
3204 .help = "list and destroy aged flows",
3205 .next = NEXT(next_aged_attr, NEXT_ENTRY(COMMON_PORT_ID)),
3206 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
3211 .help = "restrict ingress traffic to the defined flow rules",
3212 .next = NEXT(NEXT_ENTRY(COMMON_BOOLEAN),
3213 NEXT_ENTRY(COMMON_PORT_ID)),
3214 .args = ARGS(ARGS_ENTRY(struct buffer, args.isolate.set),
3215 ARGS_ENTRY(struct buffer, port)),
3216 .call = parse_isolate,
3219 .name = "flex_item",
3220 .help = "flex item API",
3221 .next = NEXT(next_flex_item),
3224 [FLEX_ITEM_INIT] = {
3226 .help = "flex item init",
3227 .args = ARGS(ARGS_ENTRY(struct buffer, args.flex.token),
3228 ARGS_ENTRY(struct buffer, port)),
3229 .next = NEXT(NEXT_ENTRY(COMMON_FLEX_TOKEN),
3230 NEXT_ENTRY(COMMON_PORT_ID)),
3233 [FLEX_ITEM_CREATE] = {
3235 .help = "flex item create",
3236 .args = ARGS(ARGS_ENTRY(struct buffer, args.flex.filename),
3237 ARGS_ENTRY(struct buffer, args.flex.token),
3238 ARGS_ENTRY(struct buffer, port)),
3239 .next = NEXT(NEXT_ENTRY(COMMON_FILE_PATH),
3240 NEXT_ENTRY(COMMON_FLEX_TOKEN),
3241 NEXT_ENTRY(COMMON_PORT_ID)),
3244 [FLEX_ITEM_DESTROY] = {
3246 .help = "flex item destroy",
3247 .args = ARGS(ARGS_ENTRY(struct buffer, args.flex.token),
3248 ARGS_ENTRY(struct buffer, port)),
3249 .next = NEXT(NEXT_ENTRY(COMMON_FLEX_TOKEN),
3250 NEXT_ENTRY(COMMON_PORT_ID)),
3255 .help = "new tunnel API",
3256 .next = NEXT(NEXT_ENTRY
3257 (TUNNEL_CREATE, TUNNEL_LIST, TUNNEL_DESTROY)),
3258 .call = parse_tunnel,
3260 /* Tunnel arguments. */
3263 .help = "create new tunnel object",
3264 .next = NEXT(NEXT_ENTRY(TUNNEL_CREATE_TYPE),
3265 NEXT_ENTRY(COMMON_PORT_ID)),
3266 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
3267 .call = parse_tunnel,
3269 [TUNNEL_CREATE_TYPE] = {
3271 .help = "create new tunnel",
3272 .next = NEXT(NEXT_ENTRY(COMMON_FILE_PATH)),
3273 .args = ARGS(ARGS_ENTRY(struct tunnel_ops, type)),
3274 .call = parse_tunnel,
3276 [TUNNEL_DESTROY] = {
3278 .help = "destroy tunnel",
3279 .next = NEXT(NEXT_ENTRY(TUNNEL_DESTROY_ID),
3280 NEXT_ENTRY(COMMON_PORT_ID)),
3281 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
3282 .call = parse_tunnel,
3284 [TUNNEL_DESTROY_ID] = {
3286 .help = "tunnel identifier to destroy",
3287 .next = NEXT(NEXT_ENTRY(COMMON_UNSIGNED)),
3288 .args = ARGS(ARGS_ENTRY(struct tunnel_ops, id)),
3289 .call = parse_tunnel,
3293 .help = "list existing tunnels",
3294 .next = NEXT(NEXT_ENTRY(COMMON_PORT_ID)),
3295 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
3296 .call = parse_tunnel,
3298 /* Destroy arguments. */
3301 .help = "specify a rule identifier",
3302 .next = NEXT(next_destroy_attr, NEXT_ENTRY(COMMON_RULE_ID)),
3303 .args = ARGS(ARGS_ENTRY_PTR(struct buffer, args.destroy.rule)),
3304 .call = parse_destroy,
3306 /* Dump arguments. */
3310 .next = NEXT(next_dump_attr),
3311 .args = ARGS(ARGS_ENTRY(struct buffer, args.dump.file)),
3316 .help = "dump one rule",
3317 .next = NEXT(next_dump_attr, NEXT_ENTRY(COMMON_RULE_ID)),
3318 .args = ARGS(ARGS_ENTRY(struct buffer, args.dump.file),
3319 ARGS_ENTRY(struct buffer, args.dump.rule)),
3322 /* Query arguments. */
3326 .help = "action to query, must be part of the rule",
3327 .call = parse_action,
3328 .comp = comp_action,
3330 /* List arguments. */
3333 .help = "specify a group",
3334 .next = NEXT(next_list_attr, NEXT_ENTRY(COMMON_GROUP_ID)),
3335 .args = ARGS(ARGS_ENTRY_PTR(struct buffer, args.list.group)),
3340 .help = "specify aged flows need be destroyed",
3344 /* Validate/create attributes. */
3347 .help = "specify a group",
3348 .next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_GROUP_ID)),
3349 .args = ARGS(ARGS_ENTRY(struct rte_flow_attr, group)),
3354 .help = "specify a priority level",
3355 .next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_PRIORITY_LEVEL)),
3356 .args = ARGS(ARGS_ENTRY(struct rte_flow_attr, priority)),
3361 .help = "affect rule to ingress",
3362 .next = NEXT(next_vc_attr),
3367 .help = "affect rule to egress",
3368 .next = NEXT(next_vc_attr),
3373 .help = "apply rule directly to endpoints found in pattern",
3374 .next = NEXT(next_vc_attr),
3378 .name = "tunnel_set",
3379 .help = "tunnel steer rule",
3380 .next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_UNSIGNED)),
3381 .args = ARGS(ARGS_ENTRY(struct tunnel_ops, id)),
3384 [VC_TUNNEL_MATCH] = {
3385 .name = "tunnel_match",
3386 .help = "tunnel match rule",
3387 .next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_UNSIGNED)),
3388 .args = ARGS(ARGS_ENTRY(struct tunnel_ops, id)),
3391 /* Validate/create pattern. */
3394 .help = "submit a list of pattern items",
3395 .next = NEXT(next_item),
3400 .help = "match value perfectly (with full bit-mask)",
3401 .call = parse_vc_spec,
3403 [ITEM_PARAM_SPEC] = {
3405 .help = "match value according to configured bit-mask",
3406 .call = parse_vc_spec,
3408 [ITEM_PARAM_LAST] = {
3410 .help = "specify upper bound to establish a range",
3411 .call = parse_vc_spec,
3413 [ITEM_PARAM_MASK] = {
3415 .help = "specify bit-mask with relevant bits set to one",
3416 .call = parse_vc_spec,
3418 [ITEM_PARAM_PREFIX] = {
3420 .help = "generate bit-mask from a prefix length",
3421 .call = parse_vc_spec,
3425 .help = "specify next pattern item",
3426 .next = NEXT(next_item),
3430 .help = "end list of pattern items",
3431 .priv = PRIV_ITEM(END, 0),
3432 .next = NEXT(NEXT_ENTRY(ACTIONS, END)),
3437 .help = "no-op pattern item",
3438 .priv = PRIV_ITEM(VOID, 0),
3439 .next = NEXT(NEXT_ENTRY(ITEM_NEXT)),
3444 .help = "perform actions when pattern does not match",
3445 .priv = PRIV_ITEM(INVERT, 0),
3446 .next = NEXT(NEXT_ENTRY(ITEM_NEXT)),
3451 .help = "match any protocol for the current layer",
3452 .priv = PRIV_ITEM(ANY, sizeof(struct rte_flow_item_any)),
3453 .next = NEXT(item_any),
3458 .help = "number of layers covered",
3459 .next = NEXT(item_any, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
3460 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_any, num)),
3464 .help = "match traffic from/to the physical function",
3465 .priv = PRIV_ITEM(PF, 0),
3466 .next = NEXT(NEXT_ENTRY(ITEM_NEXT)),
3471 .help = "match traffic from/to a virtual function ID",
3472 .priv = PRIV_ITEM(VF, sizeof(struct rte_flow_item_vf)),
3473 .next = NEXT(item_vf),
3479 .next = NEXT(item_vf, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
3480 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_vf, id)),
3484 .help = "match traffic from/to a specific physical port",
3485 .priv = PRIV_ITEM(PHY_PORT,
3486 sizeof(struct rte_flow_item_phy_port)),
3487 .next = NEXT(item_phy_port),
3490 [ITEM_PHY_PORT_INDEX] = {
3492 .help = "physical port index",
3493 .next = NEXT(item_phy_port, NEXT_ENTRY(COMMON_UNSIGNED),
3495 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_phy_port, index)),
3499 .help = "match traffic from/to a given DPDK port ID",
3500 .priv = PRIV_ITEM(PORT_ID,
3501 sizeof(struct rte_flow_item_port_id)),
3502 .next = NEXT(item_port_id),
3505 [ITEM_PORT_ID_ID] = {
3507 .help = "DPDK port ID",
3508 .next = NEXT(item_port_id, NEXT_ENTRY(COMMON_UNSIGNED),
3510 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_port_id, id)),
3514 .help = "match traffic against value set in previously matched rule",
3515 .priv = PRIV_ITEM(MARK, sizeof(struct rte_flow_item_mark)),
3516 .next = NEXT(item_mark),
3521 .help = "Integer value to match against",
3522 .next = NEXT(item_mark, NEXT_ENTRY(COMMON_UNSIGNED),
3524 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_mark, id)),
3528 .help = "match an arbitrary byte string",
3529 .priv = PRIV_ITEM(RAW, ITEM_RAW_SIZE),
3530 .next = NEXT(item_raw),
3533 [ITEM_RAW_RELATIVE] = {
3535 .help = "look for pattern after the previous item",
3536 .next = NEXT(item_raw, NEXT_ENTRY(COMMON_BOOLEAN), item_param),
3537 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_raw,
3540 [ITEM_RAW_SEARCH] = {
3542 .help = "search pattern from offset (see also limit)",
3543 .next = NEXT(item_raw, NEXT_ENTRY(COMMON_BOOLEAN), item_param),
3544 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_raw,
3547 [ITEM_RAW_OFFSET] = {
3549 .help = "absolute or relative offset for pattern",
3550 .next = NEXT(item_raw, NEXT_ENTRY(COMMON_INTEGER), item_param),
3551 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, offset)),
3553 [ITEM_RAW_LIMIT] = {
3555 .help = "search area limit for start of pattern",
3556 .next = NEXT(item_raw, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
3557 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, limit)),
3559 [ITEM_RAW_PATTERN] = {
3561 .help = "byte string to look for",
3562 .next = NEXT(item_raw,
3563 NEXT_ENTRY(COMMON_STRING),
3564 NEXT_ENTRY(ITEM_PARAM_IS,
3567 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, pattern),
3568 ARGS_ENTRY(struct rte_flow_item_raw, length),
3569 ARGS_ENTRY_ARB(sizeof(struct rte_flow_item_raw),
3570 ITEM_RAW_PATTERN_SIZE)),
3572 [ITEM_RAW_PATTERN_HEX] = {
3573 .name = "pattern_hex",
3574 .help = "hex string to look for",
3575 .next = NEXT(item_raw,
3576 NEXT_ENTRY(COMMON_HEX),
3577 NEXT_ENTRY(ITEM_PARAM_IS,
3580 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, pattern),
3581 ARGS_ENTRY(struct rte_flow_item_raw, length),
3582 ARGS_ENTRY_ARB(sizeof(struct rte_flow_item_raw),
3583 ITEM_RAW_PATTERN_SIZE)),
3587 .help = "match Ethernet header",
3588 .priv = PRIV_ITEM(ETH, sizeof(struct rte_flow_item_eth)),
3589 .next = NEXT(item_eth),
3594 .help = "destination MAC",
3595 .next = NEXT(item_eth, NEXT_ENTRY(COMMON_MAC_ADDR), item_param),
3596 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_eth, dst)),
3600 .help = "source MAC",
3601 .next = NEXT(item_eth, NEXT_ENTRY(COMMON_MAC_ADDR), item_param),
3602 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_eth, src)),
3606 .help = "EtherType",
3607 .next = NEXT(item_eth, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
3608 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_eth, type)),
3610 [ITEM_ETH_HAS_VLAN] = {
3612 .help = "packet header contains VLAN",
3613 .next = NEXT(item_eth, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
3614 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_eth,
3619 .help = "match 802.1Q/ad VLAN tag",
3620 .priv = PRIV_ITEM(VLAN, sizeof(struct rte_flow_item_vlan)),
3621 .next = NEXT(item_vlan),
3626 .help = "tag control information",
3627 .next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
3629 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vlan, tci)),
3633 .help = "priority code point",
3634 .next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
3636 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_vlan,
3641 .help = "drop eligible indicator",
3642 .next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
3644 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_vlan,
3649 .help = "VLAN identifier",
3650 .next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
3652 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_vlan,
3655 [ITEM_VLAN_INNER_TYPE] = {
3656 .name = "inner_type",
3657 .help = "inner EtherType",
3658 .next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
3660 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vlan,
3663 [ITEM_VLAN_HAS_MORE_VLAN] = {
3664 .name = "has_more_vlan",
3665 .help = "packet header contains another VLAN",
3666 .next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
3668 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_vlan,
3673 .help = "match IPv4 header",
3674 .priv = PRIV_ITEM(IPV4, sizeof(struct rte_flow_item_ipv4)),
3675 .next = NEXT(item_ipv4),
3678 [ITEM_IPV4_VER_IHL] = {
3679 .name = "version_ihl",
3680 .help = "match header length",
3681 .next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
3683 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_ipv4,
3688 .help = "type of service",
3689 .next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
3691 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
3692 hdr.type_of_service)),
3695 .name = "packet_id",
3696 .help = "fragment packet id",
3697 .next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
3699 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
3702 [ITEM_IPV4_FRAGMENT_OFFSET] = {
3703 .name = "fragment_offset",
3704 .help = "fragmentation flags and fragment offset",
3705 .next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
3707 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
3708 hdr.fragment_offset)),
3712 .help = "time to live",
3713 .next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
3715 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
3718 [ITEM_IPV4_PROTO] = {
3720 .help = "next protocol ID",
3721 .next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
3723 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
3724 hdr.next_proto_id)),
3728 .help = "source address",
3729 .next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_IPV4_ADDR),
3731 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
3736 .help = "destination address",
3737 .next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_IPV4_ADDR),
3739 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
3744 .help = "match IPv6 header",
3745 .priv = PRIV_ITEM(IPV6, sizeof(struct rte_flow_item_ipv6)),
3746 .next = NEXT(item_ipv6),
3751 .help = "traffic class",
3752 .next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED),
3754 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_ipv6,
3756 "\x0f\xf0\x00\x00")),
3758 [ITEM_IPV6_FLOW] = {
3760 .help = "flow label",
3761 .next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED),
3763 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_ipv6,
3765 "\x00\x0f\xff\xff")),
3767 [ITEM_IPV6_PROTO] = {
3769 .help = "protocol (next header)",
3770 .next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED),
3772 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
3777 .help = "hop limit",
3778 .next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED),
3780 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
3785 .help = "source address",
3786 .next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_IPV6_ADDR),
3788 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
3793 .help = "destination address",
3794 .next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_IPV6_ADDR),
3796 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
3799 [ITEM_IPV6_HAS_FRAG_EXT] = {
3800 .name = "has_frag_ext",
3801 .help = "fragment packet attribute",
3802 .next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED),
3804 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_ipv6,
3809 .help = "match ICMP header",
3810 .priv = PRIV_ITEM(ICMP, sizeof(struct rte_flow_item_icmp)),
3811 .next = NEXT(item_icmp),
3814 [ITEM_ICMP_TYPE] = {
3816 .help = "ICMP packet type",
3817 .next = NEXT(item_icmp, NEXT_ENTRY(COMMON_UNSIGNED),
3819 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp,
3822 [ITEM_ICMP_CODE] = {
3824 .help = "ICMP packet code",
3825 .next = NEXT(item_icmp, NEXT_ENTRY(COMMON_UNSIGNED),
3827 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp,
3830 [ITEM_ICMP_IDENT] = {
3832 .help = "ICMP packet identifier",
3833 .next = NEXT(item_icmp, NEXT_ENTRY(COMMON_UNSIGNED),
3835 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp,
3840 .help = "ICMP packet sequence number",
3841 .next = NEXT(item_icmp, NEXT_ENTRY(COMMON_UNSIGNED),
3843 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp,
3848 .help = "match UDP header",
3849 .priv = PRIV_ITEM(UDP, sizeof(struct rte_flow_item_udp)),
3850 .next = NEXT(item_udp),
3855 .help = "UDP source port",
3856 .next = NEXT(item_udp, NEXT_ENTRY(COMMON_UNSIGNED),
3858 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_udp,
3863 .help = "UDP destination port",
3864 .next = NEXT(item_udp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
3865 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_udp,
3870 .help = "match TCP header",
3871 .priv = PRIV_ITEM(TCP, sizeof(struct rte_flow_item_tcp)),
3872 .next = NEXT(item_tcp),
3877 .help = "TCP source port",
3878 .next = NEXT(item_tcp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
3879 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_tcp,
3884 .help = "TCP destination port",
3885 .next = NEXT(item_tcp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
3886 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_tcp,
3889 [ITEM_TCP_FLAGS] = {
3891 .help = "TCP flags",
3892 .next = NEXT(item_tcp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
3893 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_tcp,
3898 .help = "match SCTP header",
3899 .priv = PRIV_ITEM(SCTP, sizeof(struct rte_flow_item_sctp)),
3900 .next = NEXT(item_sctp),
3905 .help = "SCTP source port",
3906 .next = NEXT(item_sctp, NEXT_ENTRY(COMMON_UNSIGNED),
3908 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
3913 .help = "SCTP destination port",
3914 .next = NEXT(item_sctp, NEXT_ENTRY(COMMON_UNSIGNED),
3916 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
3921 .help = "validation tag",
3922 .next = NEXT(item_sctp, NEXT_ENTRY(COMMON_UNSIGNED),
3924 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
3927 [ITEM_SCTP_CKSUM] = {
3930 .next = NEXT(item_sctp, NEXT_ENTRY(COMMON_UNSIGNED),
3932 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
3937 .help = "match VXLAN header",
3938 .priv = PRIV_ITEM(VXLAN, sizeof(struct rte_flow_item_vxlan)),
3939 .next = NEXT(item_vxlan),
3942 [ITEM_VXLAN_VNI] = {
3944 .help = "VXLAN identifier",
3945 .next = NEXT(item_vxlan, NEXT_ENTRY(COMMON_UNSIGNED),
3947 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan, vni)),
3949 [ITEM_VXLAN_LAST_RSVD] = {
3950 .name = "last_rsvd",
3951 .help = "VXLAN last reserved bits",
3952 .next = NEXT(item_vxlan, NEXT_ENTRY(COMMON_UNSIGNED),
3954 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan,
3959 .help = "match E-Tag header",
3960 .priv = PRIV_ITEM(E_TAG, sizeof(struct rte_flow_item_e_tag)),
3961 .next = NEXT(item_e_tag),
3964 [ITEM_E_TAG_GRP_ECID_B] = {
3965 .name = "grp_ecid_b",
3966 .help = "GRP and E-CID base",
3967 .next = NEXT(item_e_tag, NEXT_ENTRY(COMMON_UNSIGNED),
3969 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_e_tag,
3975 .help = "match NVGRE header",
3976 .priv = PRIV_ITEM(NVGRE, sizeof(struct rte_flow_item_nvgre)),
3977 .next = NEXT(item_nvgre),
3980 [ITEM_NVGRE_TNI] = {
3982 .help = "virtual subnet ID",
3983 .next = NEXT(item_nvgre, NEXT_ENTRY(COMMON_UNSIGNED),
3985 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_nvgre, tni)),
3989 .help = "match MPLS header",
3990 .priv = PRIV_ITEM(MPLS, sizeof(struct rte_flow_item_mpls)),
3991 .next = NEXT(item_mpls),
3994 [ITEM_MPLS_LABEL] = {
3996 .help = "MPLS label",
3997 .next = NEXT(item_mpls, NEXT_ENTRY(COMMON_UNSIGNED),
3999 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_mpls,
4005 .help = "MPLS Traffic Class",
4006 .next = NEXT(item_mpls, NEXT_ENTRY(COMMON_UNSIGNED),
4008 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_mpls,
4014 .help = "MPLS Bottom-of-Stack",
4015 .next = NEXT(item_mpls, NEXT_ENTRY(COMMON_UNSIGNED),
4017 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_mpls,
4023 .help = "match GRE header",
4024 .priv = PRIV_ITEM(GRE, sizeof(struct rte_flow_item_gre)),
4025 .next = NEXT(item_gre),
4028 [ITEM_GRE_PROTO] = {
4030 .help = "GRE protocol type",
4031 .next = NEXT(item_gre, NEXT_ENTRY(COMMON_UNSIGNED),
4033 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre,
4036 [ITEM_GRE_C_RSVD0_VER] = {
4037 .name = "c_rsvd0_ver",
4039 "checksum (1b), undefined (1b), key bit (1b),"
4040 " sequence number (1b), reserved 0 (9b),"
4042 .next = NEXT(item_gre, NEXT_ENTRY(COMMON_UNSIGNED),
4044 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre,
4047 [ITEM_GRE_C_BIT] = {
4049 .help = "checksum bit (C)",
4050 .next = NEXT(item_gre, NEXT_ENTRY(COMMON_BOOLEAN),
4052 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_gre,
4054 "\x80\x00\x00\x00")),
4056 [ITEM_GRE_S_BIT] = {
4058 .help = "sequence number bit (S)",
4059 .next = NEXT(item_gre, NEXT_ENTRY(COMMON_BOOLEAN), item_param),
4060 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_gre,
4062 "\x10\x00\x00\x00")),
4064 [ITEM_GRE_K_BIT] = {
4066 .help = "key bit (K)",
4067 .next = NEXT(item_gre, NEXT_ENTRY(COMMON_BOOLEAN), item_param),
4068 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_gre,
4070 "\x20\x00\x00\x00")),
4074 .help = "fuzzy pattern match, expect faster than default",
4075 .priv = PRIV_ITEM(FUZZY,
4076 sizeof(struct rte_flow_item_fuzzy)),
4077 .next = NEXT(item_fuzzy),
4080 [ITEM_FUZZY_THRESH] = {
4082 .help = "match accuracy threshold",
4083 .next = NEXT(item_fuzzy, NEXT_ENTRY(COMMON_UNSIGNED),
4085 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_fuzzy,
4090 .help = "match GTP header",
4091 .priv = PRIV_ITEM(GTP, sizeof(struct rte_flow_item_gtp)),
4092 .next = NEXT(item_gtp),
4095 [ITEM_GTP_FLAGS] = {
4096 .name = "v_pt_rsv_flags",
4097 .help = "GTP flags",
4098 .next = NEXT(item_gtp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
4099 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_gtp,
4102 [ITEM_GTP_MSG_TYPE] = {
4104 .help = "GTP message type",
4105 .next = NEXT(item_gtp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
4106 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_gtp, msg_type)),
4110 .help = "tunnel endpoint identifier",
4111 .next = NEXT(item_gtp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
4112 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gtp, teid)),
4116 .help = "match GTP header",
4117 .priv = PRIV_ITEM(GTPC, sizeof(struct rte_flow_item_gtp)),
4118 .next = NEXT(item_gtp),
4123 .help = "match GTP header",
4124 .priv = PRIV_ITEM(GTPU, sizeof(struct rte_flow_item_gtp)),
4125 .next = NEXT(item_gtp),
4130 .help = "match GENEVE header",
4131 .priv = PRIV_ITEM(GENEVE, sizeof(struct rte_flow_item_geneve)),
4132 .next = NEXT(item_geneve),
4135 [ITEM_GENEVE_VNI] = {
4137 .help = "virtual network identifier",
4138 .next = NEXT(item_geneve, NEXT_ENTRY(COMMON_UNSIGNED),
4140 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_geneve, vni)),
4142 [ITEM_GENEVE_PROTO] = {
4144 .help = "GENEVE protocol type",
4145 .next = NEXT(item_geneve, NEXT_ENTRY(COMMON_UNSIGNED),
4147 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_geneve,
4150 [ITEM_GENEVE_OPTLEN] = {
4152 .help = "GENEVE options length in dwords",
4153 .next = NEXT(item_geneve, NEXT_ENTRY(COMMON_UNSIGNED),
4155 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_geneve,
4156 ver_opt_len_o_c_rsvd0,
4159 [ITEM_VXLAN_GPE] = {
4160 .name = "vxlan-gpe",
4161 .help = "match VXLAN-GPE header",
4162 .priv = PRIV_ITEM(VXLAN_GPE,
4163 sizeof(struct rte_flow_item_vxlan_gpe)),
4164 .next = NEXT(item_vxlan_gpe),
4167 [ITEM_VXLAN_GPE_VNI] = {
4169 .help = "VXLAN-GPE identifier",
4170 .next = NEXT(item_vxlan_gpe, NEXT_ENTRY(COMMON_UNSIGNED),
4172 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan_gpe,
4175 [ITEM_ARP_ETH_IPV4] = {
4176 .name = "arp_eth_ipv4",
4177 .help = "match ARP header for Ethernet/IPv4",
4178 .priv = PRIV_ITEM(ARP_ETH_IPV4,
4179 sizeof(struct rte_flow_item_arp_eth_ipv4)),
4180 .next = NEXT(item_arp_eth_ipv4),
4183 [ITEM_ARP_ETH_IPV4_SHA] = {
4185 .help = "sender hardware address",
4186 .next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(COMMON_MAC_ADDR),
4188 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4,
4191 [ITEM_ARP_ETH_IPV4_SPA] = {
4193 .help = "sender IPv4 address",
4194 .next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(COMMON_IPV4_ADDR),
4196 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4,
4199 [ITEM_ARP_ETH_IPV4_THA] = {
4201 .help = "target hardware address",
4202 .next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(COMMON_MAC_ADDR),
4204 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4,
4207 [ITEM_ARP_ETH_IPV4_TPA] = {
4209 .help = "target IPv4 address",
4210 .next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(COMMON_IPV4_ADDR),
4212 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4,
4217 .help = "match presence of any IPv6 extension header",
4218 .priv = PRIV_ITEM(IPV6_EXT,
4219 sizeof(struct rte_flow_item_ipv6_ext)),
4220 .next = NEXT(item_ipv6_ext),
4223 [ITEM_IPV6_EXT_NEXT_HDR] = {
4225 .help = "next header",
4226 .next = NEXT(item_ipv6_ext, NEXT_ENTRY(COMMON_UNSIGNED),
4228 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_ext,
4231 [ITEM_IPV6_FRAG_EXT] = {
4232 .name = "ipv6_frag_ext",
4233 .help = "match presence of IPv6 fragment extension header",
4234 .priv = PRIV_ITEM(IPV6_FRAG_EXT,
4235 sizeof(struct rte_flow_item_ipv6_frag_ext)),
4236 .next = NEXT(item_ipv6_frag_ext),
4239 [ITEM_IPV6_FRAG_EXT_NEXT_HDR] = {
4241 .help = "next header",
4242 .next = NEXT(item_ipv6_frag_ext, NEXT_ENTRY(COMMON_UNSIGNED),
4244 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_ipv6_frag_ext,
4247 [ITEM_IPV6_FRAG_EXT_FRAG_DATA] = {
4248 .name = "frag_data",
4249 .help = "fragment flags and offset",
4250 .next = NEXT(item_ipv6_frag_ext, NEXT_ENTRY(COMMON_UNSIGNED),
4252 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_frag_ext,
4255 [ITEM_IPV6_FRAG_EXT_ID] = {
4256 .name = "packet_id",
4257 .help = "fragment packet id",
4258 .next = NEXT(item_ipv6_frag_ext, NEXT_ENTRY(COMMON_UNSIGNED),
4260 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_frag_ext,
4265 .help = "match any ICMPv6 header",
4266 .priv = PRIV_ITEM(ICMP6, sizeof(struct rte_flow_item_icmp6)),
4267 .next = NEXT(item_icmp6),
4270 [ITEM_ICMP6_TYPE] = {
4272 .help = "ICMPv6 type",
4273 .next = NEXT(item_icmp6, NEXT_ENTRY(COMMON_UNSIGNED),
4275 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6,
4278 [ITEM_ICMP6_CODE] = {
4280 .help = "ICMPv6 code",
4281 .next = NEXT(item_icmp6, NEXT_ENTRY(COMMON_UNSIGNED),
4283 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6,
4286 [ITEM_ICMP6_ND_NS] = {
4287 .name = "icmp6_nd_ns",
4288 .help = "match ICMPv6 neighbor discovery solicitation",
4289 .priv = PRIV_ITEM(ICMP6_ND_NS,
4290 sizeof(struct rte_flow_item_icmp6_nd_ns)),
4291 .next = NEXT(item_icmp6_nd_ns),
4294 [ITEM_ICMP6_ND_NS_TARGET_ADDR] = {
4295 .name = "target_addr",
4296 .help = "target address",
4297 .next = NEXT(item_icmp6_nd_ns, NEXT_ENTRY(COMMON_IPV6_ADDR),
4299 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_nd_ns,
4302 [ITEM_ICMP6_ND_NA] = {
4303 .name = "icmp6_nd_na",
4304 .help = "match ICMPv6 neighbor discovery advertisement",
4305 .priv = PRIV_ITEM(ICMP6_ND_NA,
4306 sizeof(struct rte_flow_item_icmp6_nd_na)),
4307 .next = NEXT(item_icmp6_nd_na),
4310 [ITEM_ICMP6_ND_NA_TARGET_ADDR] = {
4311 .name = "target_addr",
4312 .help = "target address",
4313 .next = NEXT(item_icmp6_nd_na, NEXT_ENTRY(COMMON_IPV6_ADDR),
4315 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_nd_na,
4318 [ITEM_ICMP6_ND_OPT] = {
4319 .name = "icmp6_nd_opt",
4320 .help = "match presence of any ICMPv6 neighbor discovery"
4322 .priv = PRIV_ITEM(ICMP6_ND_OPT,
4323 sizeof(struct rte_flow_item_icmp6_nd_opt)),
4324 .next = NEXT(item_icmp6_nd_opt),
4327 [ITEM_ICMP6_ND_OPT_TYPE] = {
4329 .help = "ND option type",
4330 .next = NEXT(item_icmp6_nd_opt, NEXT_ENTRY(COMMON_UNSIGNED),
4332 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_nd_opt,
4335 [ITEM_ICMP6_ND_OPT_SLA_ETH] = {
4336 .name = "icmp6_nd_opt_sla_eth",
4337 .help = "match ICMPv6 neighbor discovery source Ethernet"
4338 " link-layer address option",
4340 (ICMP6_ND_OPT_SLA_ETH,
4341 sizeof(struct rte_flow_item_icmp6_nd_opt_sla_eth)),
4342 .next = NEXT(item_icmp6_nd_opt_sla_eth),
4345 [ITEM_ICMP6_ND_OPT_SLA_ETH_SLA] = {
4347 .help = "source Ethernet LLA",
4348 .next = NEXT(item_icmp6_nd_opt_sla_eth,
4349 NEXT_ENTRY(COMMON_MAC_ADDR), item_param),
4350 .args = ARGS(ARGS_ENTRY_HTON
4351 (struct rte_flow_item_icmp6_nd_opt_sla_eth, sla)),
4353 [ITEM_ICMP6_ND_OPT_TLA_ETH] = {
4354 .name = "icmp6_nd_opt_tla_eth",
4355 .help = "match ICMPv6 neighbor discovery target Ethernet"
4356 " link-layer address option",
4358 (ICMP6_ND_OPT_TLA_ETH,
4359 sizeof(struct rte_flow_item_icmp6_nd_opt_tla_eth)),
4360 .next = NEXT(item_icmp6_nd_opt_tla_eth),
4363 [ITEM_ICMP6_ND_OPT_TLA_ETH_TLA] = {
4365 .help = "target Ethernet LLA",
4366 .next = NEXT(item_icmp6_nd_opt_tla_eth,
4367 NEXT_ENTRY(COMMON_MAC_ADDR), item_param),
4368 .args = ARGS(ARGS_ENTRY_HTON
4369 (struct rte_flow_item_icmp6_nd_opt_tla_eth, tla)),
4373 .help = "match metadata header",
4374 .priv = PRIV_ITEM(META, sizeof(struct rte_flow_item_meta)),
4375 .next = NEXT(item_meta),
4378 [ITEM_META_DATA] = {
4380 .help = "metadata value",
4381 .next = NEXT(item_meta, NEXT_ENTRY(COMMON_UNSIGNED),
4383 .args = ARGS(ARGS_ENTRY_MASK(struct rte_flow_item_meta,
4384 data, "\xff\xff\xff\xff")),
4388 .help = "match GRE key",
4389 .priv = PRIV_ITEM(GRE_KEY, sizeof(rte_be32_t)),
4390 .next = NEXT(item_gre_key),
4393 [ITEM_GRE_KEY_VALUE] = {
4395 .help = "key value",
4396 .next = NEXT(item_gre_key, NEXT_ENTRY(COMMON_UNSIGNED),
4398 .args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
4400 [ITEM_GRE_OPTION] = {
4401 .name = "gre_option",
4402 .help = "match GRE optional fields",
4403 .priv = PRIV_ITEM(GRE_OPTION,
4404 sizeof(struct rte_flow_item_gre_opt)),
4405 .next = NEXT(item_gre_option),
4408 [ITEM_GRE_OPTION_CHECKSUM] = {
4410 .help = "match GRE checksum",
4411 .next = NEXT(item_gre_option, NEXT_ENTRY(COMMON_UNSIGNED),
4413 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre_opt,
4414 checksum_rsvd.checksum)),
4416 [ITEM_GRE_OPTION_KEY] = {
4418 .help = "match GRE key",
4419 .next = NEXT(item_gre_option, NEXT_ENTRY(COMMON_UNSIGNED),
4421 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre_opt,
4424 [ITEM_GRE_OPTION_SEQUENCE] = {
4426 .help = "match GRE sequence",
4427 .next = NEXT(item_gre_option, NEXT_ENTRY(COMMON_UNSIGNED),
4429 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre_opt,
4430 sequence.sequence)),
4434 .help = "match GTP extension header with type 0x85",
4435 .priv = PRIV_ITEM(GTP_PSC,
4436 sizeof(struct rte_flow_item_gtp_psc)),
4437 .next = NEXT(item_gtp_psc),
4440 [ITEM_GTP_PSC_QFI] = {
4442 .help = "QoS flow identifier",
4443 .next = NEXT(item_gtp_psc, NEXT_ENTRY(COMMON_UNSIGNED),
4445 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_gtp_psc,
4448 [ITEM_GTP_PSC_PDU_T] = {
4451 .next = NEXT(item_gtp_psc, NEXT_ENTRY(COMMON_UNSIGNED),
4453 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_gtp_psc,
4458 .help = "match PPPoE session header",
4459 .priv = PRIV_ITEM(PPPOES, sizeof(struct rte_flow_item_pppoe)),
4460 .next = NEXT(item_pppoes),
4465 .help = "match PPPoE discovery header",
4466 .priv = PRIV_ITEM(PPPOED, sizeof(struct rte_flow_item_pppoe)),
4467 .next = NEXT(item_pppoed),
4470 [ITEM_PPPOE_SEID] = {
4472 .help = "session identifier",
4473 .next = NEXT(item_pppoes, NEXT_ENTRY(COMMON_UNSIGNED),
4475 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_pppoe,
4478 [ITEM_PPPOE_PROTO_ID] = {
4479 .name = "pppoe_proto_id",
4480 .help = "match PPPoE session protocol identifier",
4481 .priv = PRIV_ITEM(PPPOE_PROTO_ID,
4482 sizeof(struct rte_flow_item_pppoe_proto_id)),
4483 .next = NEXT(item_pppoe_proto_id, NEXT_ENTRY(COMMON_UNSIGNED),
4485 .args = ARGS(ARGS_ENTRY_HTON
4486 (struct rte_flow_item_pppoe_proto_id, proto_id)),
4491 .help = "matches higig2 header",
4492 .priv = PRIV_ITEM(HIGIG2,
4493 sizeof(struct rte_flow_item_higig2_hdr)),
4494 .next = NEXT(item_higig2),
4497 [ITEM_HIGIG2_CLASSIFICATION] = {
4498 .name = "classification",
4499 .help = "matches classification of higig2 header",
4500 .next = NEXT(item_higig2, NEXT_ENTRY(COMMON_UNSIGNED),
4502 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_higig2_hdr,
4503 hdr.ppt1.classification)),
4505 [ITEM_HIGIG2_VID] = {
4507 .help = "matches vid of higig2 header",
4508 .next = NEXT(item_higig2, NEXT_ENTRY(COMMON_UNSIGNED),
4510 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_higig2_hdr,
4515 .help = "match tag value",
4516 .priv = PRIV_ITEM(TAG, sizeof(struct rte_flow_item_tag)),
4517 .next = NEXT(item_tag),
4522 .help = "tag value to match",
4523 .next = NEXT(item_tag, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
4524 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_tag, data)),
4526 [ITEM_TAG_INDEX] = {
4528 .help = "index of tag array to match",
4529 .next = NEXT(item_tag, NEXT_ENTRY(COMMON_UNSIGNED),
4530 NEXT_ENTRY(ITEM_PARAM_IS)),
4531 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_tag, index)),
4533 [ITEM_L2TPV3OIP] = {
4534 .name = "l2tpv3oip",
4535 .help = "match L2TPv3 over IP header",
4536 .priv = PRIV_ITEM(L2TPV3OIP,
4537 sizeof(struct rte_flow_item_l2tpv3oip)),
4538 .next = NEXT(item_l2tpv3oip),
4541 [ITEM_L2TPV3OIP_SESSION_ID] = {
4542 .name = "session_id",
4543 .help = "session identifier",
4544 .next = NEXT(item_l2tpv3oip, NEXT_ENTRY(COMMON_UNSIGNED),
4546 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv3oip,
4551 .help = "match ESP header",
4552 .priv = PRIV_ITEM(ESP, sizeof(struct rte_flow_item_esp)),
4553 .next = NEXT(item_esp),
4558 .help = "security policy index",
4559 .next = NEXT(item_esp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
4560 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_esp,
4565 .help = "match AH header",
4566 .priv = PRIV_ITEM(AH, sizeof(struct rte_flow_item_ah)),
4567 .next = NEXT(item_ah),
4572 .help = "security parameters index",
4573 .next = NEXT(item_ah, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
4574 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ah, spi)),
4578 .help = "match pfcp header",
4579 .priv = PRIV_ITEM(PFCP, sizeof(struct rte_flow_item_pfcp)),
4580 .next = NEXT(item_pfcp),
4583 [ITEM_PFCP_S_FIELD] = {
4586 .next = NEXT(item_pfcp, NEXT_ENTRY(COMMON_UNSIGNED),
4588 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_pfcp,
4591 [ITEM_PFCP_SEID] = {
4593 .help = "session endpoint identifier",
4594 .next = NEXT(item_pfcp, NEXT_ENTRY(COMMON_UNSIGNED),
4596 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_pfcp, seid)),
4600 .help = "match eCPRI header",
4601 .priv = PRIV_ITEM(ECPRI, sizeof(struct rte_flow_item_ecpri)),
4602 .next = NEXT(item_ecpri),
4605 [ITEM_ECPRI_COMMON] = {
4607 .help = "eCPRI common header",
4608 .next = NEXT(item_ecpri_common),
4610 [ITEM_ECPRI_COMMON_TYPE] = {
4612 .help = "type of common header",
4613 .next = NEXT(item_ecpri_common_type),
4614 .args = ARGS(ARG_ENTRY_HTON(struct rte_flow_item_ecpri)),
4616 [ITEM_ECPRI_COMMON_TYPE_IQ_DATA] = {
4618 .help = "Type #0: IQ Data",
4619 .next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_IQ_DATA_PCID,
4621 .call = parse_vc_item_ecpri_type,
4623 [ITEM_ECPRI_MSG_IQ_DATA_PCID] = {
4625 .help = "Physical Channel ID",
4626 .next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_IQ_DATA_PCID,
4627 ITEM_ECPRI_COMMON, ITEM_NEXT),
4628 NEXT_ENTRY(COMMON_UNSIGNED), item_param),
4629 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ecpri,
4632 [ITEM_ECPRI_COMMON_TYPE_RTC_CTRL] = {
4634 .help = "Type #2: Real-Time Control Data",
4635 .next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_RTC_CTRL_RTCID,
4637 .call = parse_vc_item_ecpri_type,
4639 [ITEM_ECPRI_MSG_RTC_CTRL_RTCID] = {
4641 .help = "Real-Time Control Data ID",
4642 .next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_RTC_CTRL_RTCID,
4643 ITEM_ECPRI_COMMON, ITEM_NEXT),
4644 NEXT_ENTRY(COMMON_UNSIGNED), item_param),
4645 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ecpri,
4648 [ITEM_ECPRI_COMMON_TYPE_DLY_MSR] = {
4649 .name = "delay_measure",
4650 .help = "Type #5: One-Way Delay Measurement",
4651 .next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_DLY_MSR_MSRID,
4653 .call = parse_vc_item_ecpri_type,
4655 [ITEM_ECPRI_MSG_DLY_MSR_MSRID] = {
4657 .help = "Measurement ID",
4658 .next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_DLY_MSR_MSRID,
4659 ITEM_ECPRI_COMMON, ITEM_NEXT),
4660 NEXT_ENTRY(COMMON_UNSIGNED), item_param),
4661 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ecpri,
4664 [ITEM_GENEVE_OPT] = {
4665 .name = "geneve-opt",
4666 .help = "GENEVE header option",
4667 .priv = PRIV_ITEM(GENEVE_OPT,
4668 sizeof(struct rte_flow_item_geneve_opt) +
4669 ITEM_GENEVE_OPT_DATA_SIZE),
4670 .next = NEXT(item_geneve_opt),
4673 [ITEM_GENEVE_OPT_CLASS] = {
4675 .help = "GENEVE option class",
4676 .next = NEXT(item_geneve_opt, NEXT_ENTRY(COMMON_UNSIGNED),
4678 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_geneve_opt,
4681 [ITEM_GENEVE_OPT_TYPE] = {
4683 .help = "GENEVE option type",
4684 .next = NEXT(item_geneve_opt, NEXT_ENTRY(COMMON_UNSIGNED),
4686 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_geneve_opt,
4689 [ITEM_GENEVE_OPT_LENGTH] = {
4691 .help = "GENEVE option data length (in 32b words)",
4692 .next = NEXT(item_geneve_opt, NEXT_ENTRY(COMMON_UNSIGNED),
4694 .args = ARGS(ARGS_ENTRY_BOUNDED(
4695 struct rte_flow_item_geneve_opt, option_len,
4698 [ITEM_GENEVE_OPT_DATA] = {
4700 .help = "GENEVE option data pattern",
4701 .next = NEXT(item_geneve_opt, NEXT_ENTRY(COMMON_HEX),
4703 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_geneve_opt, data),
4704 ARGS_ENTRY_ARB(0, 0),
4706 (sizeof(struct rte_flow_item_geneve_opt),
4707 ITEM_GENEVE_OPT_DATA_SIZE)),
4709 [ITEM_INTEGRITY] = {
4710 .name = "integrity",
4711 .help = "match packet integrity",
4712 .priv = PRIV_ITEM(INTEGRITY,
4713 sizeof(struct rte_flow_item_integrity)),
4714 .next = NEXT(item_integrity),
4717 [ITEM_INTEGRITY_LEVEL] = {
4719 .help = "integrity level",
4720 .next = NEXT(item_integrity_lv, NEXT_ENTRY(COMMON_UNSIGNED),
4722 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_integrity, level)),
4724 [ITEM_INTEGRITY_VALUE] = {
4726 .help = "integrity value",
4727 .next = NEXT(item_integrity_lv, NEXT_ENTRY(COMMON_UNSIGNED),
4729 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_integrity, value)),
4731 [ITEM_CONNTRACK] = {
4732 .name = "conntrack",
4733 .help = "conntrack state",
4734 .next = NEXT(NEXT_ENTRY(ITEM_NEXT), NEXT_ENTRY(COMMON_UNSIGNED),
4736 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_conntrack, flags)),
4738 [ITEM_PORT_REPRESENTOR] = {
4739 .name = "port_representor",
4740 .help = "match traffic entering the embedded switch from the given ethdev",
4741 .priv = PRIV_ITEM(PORT_REPRESENTOR,
4742 sizeof(struct rte_flow_item_ethdev)),
4743 .next = NEXT(item_port_representor),
4746 [ITEM_PORT_REPRESENTOR_PORT_ID] = {
4748 .help = "ethdev port ID",
4749 .next = NEXT(item_port_representor, NEXT_ENTRY(COMMON_UNSIGNED),
4751 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_ethdev, port_id)),
4753 [ITEM_REPRESENTED_PORT] = {
4754 .name = "represented_port",
4755 .help = "match traffic entering the embedded switch from the entity represented by the given ethdev",
4756 .priv = PRIV_ITEM(REPRESENTED_PORT,
4757 sizeof(struct rte_flow_item_ethdev)),
4758 .next = NEXT(item_represented_port),
4761 [ITEM_REPRESENTED_PORT_ETHDEV_PORT_ID] = {
4762 .name = "ethdev_port_id",
4763 .help = "ethdev port ID",
4764 .next = NEXT(item_represented_port, NEXT_ENTRY(COMMON_UNSIGNED),
4766 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_ethdev, port_id)),
4770 .help = "match flex header",
4771 .priv = PRIV_ITEM(FLEX, sizeof(struct rte_flow_item_flex)),
4772 .next = NEXT(item_flex),
4775 [ITEM_FLEX_ITEM_HANDLE] = {
4777 .help = "flex item handle",
4778 .next = NEXT(item_flex, NEXT_ENTRY(COMMON_FLEX_HANDLE),
4779 NEXT_ENTRY(ITEM_PARAM_IS)),
4780 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_flex, handle)),
4782 [ITEM_FLEX_PATTERN_HANDLE] = {
4784 .help = "flex pattern handle",
4785 .next = NEXT(item_flex, NEXT_ENTRY(COMMON_FLEX_HANDLE),
4786 NEXT_ENTRY(ITEM_PARAM_IS)),
4787 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_flex, pattern)),
4791 .help = "match L2TPv2 header",
4792 .priv = PRIV_ITEM(L2TPV2, sizeof(struct rte_flow_item_l2tpv2)),
4793 .next = NEXT(item_l2tpv2),
4796 [ITEM_L2TPV2_TYPE] = {
4798 .help = "type of l2tpv2",
4799 .next = NEXT(item_l2tpv2_type),
4800 .args = ARGS(ARG_ENTRY_HTON(struct rte_flow_item_l2tpv2)),
4802 [ITEM_L2TPV2_TYPE_DATA] = {
4804 .help = "Type #7: data message without any options",
4805 .next = NEXT(item_l2tpv2_type_data),
4806 .call = parse_vc_item_l2tpv2_type,
4808 [ITEM_L2TPV2_MSG_DATA_TUNNEL_ID] = {
4809 .name = "tunnel_id",
4810 .help = "tunnel identifier",
4811 .next = NEXT(item_l2tpv2_type_data,
4812 NEXT_ENTRY(COMMON_UNSIGNED),
4814 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4815 hdr.type7.tunnel_id)),
4817 [ITEM_L2TPV2_MSG_DATA_SESSION_ID] = {
4818 .name = "session_id",
4819 .help = "session identifier",
4820 .next = NEXT(item_l2tpv2_type_data,
4821 NEXT_ENTRY(COMMON_UNSIGNED),
4823 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4824 hdr.type7.session_id)),
4826 [ITEM_L2TPV2_TYPE_DATA_L] = {
4828 .help = "Type #6: data message with length option",
4829 .next = NEXT(item_l2tpv2_type_data_l),
4830 .call = parse_vc_item_l2tpv2_type,
4832 [ITEM_L2TPV2_MSG_DATA_L_LENGTH] = {
4834 .help = "message length",
4835 .next = NEXT(item_l2tpv2_type_data_l,
4836 NEXT_ENTRY(COMMON_UNSIGNED),
4838 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4841 [ITEM_L2TPV2_MSG_DATA_L_TUNNEL_ID] = {
4842 .name = "tunnel_id",
4843 .help = "tunnel identifier",
4844 .next = NEXT(item_l2tpv2_type_data_l,
4845 NEXT_ENTRY(COMMON_UNSIGNED),
4847 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4848 hdr.type6.tunnel_id)),
4850 [ITEM_L2TPV2_MSG_DATA_L_SESSION_ID] = {
4851 .name = "session_id",
4852 .help = "session identifier",
4853 .next = NEXT(item_l2tpv2_type_data_l,
4854 NEXT_ENTRY(COMMON_UNSIGNED),
4856 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4857 hdr.type6.session_id)),
4859 [ITEM_L2TPV2_TYPE_DATA_S] = {
4861 .help = "Type #5: data message with ns, nr option",
4862 .next = NEXT(item_l2tpv2_type_data_s),
4863 .call = parse_vc_item_l2tpv2_type,
4865 [ITEM_L2TPV2_MSG_DATA_S_TUNNEL_ID] = {
4866 .name = "tunnel_id",
4867 .help = "tunnel identifier",
4868 .next = NEXT(item_l2tpv2_type_data_s,
4869 NEXT_ENTRY(COMMON_UNSIGNED),
4871 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4872 hdr.type5.tunnel_id)),
4874 [ITEM_L2TPV2_MSG_DATA_S_SESSION_ID] = {
4875 .name = "session_id",
4876 .help = "session identifier",
4877 .next = NEXT(item_l2tpv2_type_data_s,
4878 NEXT_ENTRY(COMMON_UNSIGNED),
4880 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4881 hdr.type5.session_id)),
4883 [ITEM_L2TPV2_MSG_DATA_S_NS] = {
4885 .help = "sequence number for message",
4886 .next = NEXT(item_l2tpv2_type_data_s,
4887 NEXT_ENTRY(COMMON_UNSIGNED),
4889 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4892 [ITEM_L2TPV2_MSG_DATA_S_NR] = {
4894 .help = "sequence number for next receive message",
4895 .next = NEXT(item_l2tpv2_type_data_s,
4896 NEXT_ENTRY(COMMON_UNSIGNED),
4898 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4901 [ITEM_L2TPV2_TYPE_DATA_O] = {
4903 .help = "Type #4: data message with offset option",
4904 .next = NEXT(item_l2tpv2_type_data_o),
4905 .call = parse_vc_item_l2tpv2_type,
4907 [ITEM_L2TPV2_MSG_DATA_O_TUNNEL_ID] = {
4908 .name = "tunnel_id",
4909 .help = "tunnel identifier",
4910 .next = NEXT(item_l2tpv2_type_data_o,
4911 NEXT_ENTRY(COMMON_UNSIGNED),
4913 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4914 hdr.type4.tunnel_id)),
4916 [ITEM_L2TPV2_MSG_DATA_O_SESSION_ID] = {
4917 .name = "session_id",
4918 .help = "session identifier",
4919 .next = NEXT(item_l2tpv2_type_data_o,
4920 NEXT_ENTRY(COMMON_UNSIGNED),
4922 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4923 hdr.type5.session_id)),
4925 [ITEM_L2TPV2_MSG_DATA_O_OFFSET] = {
4926 .name = "offset_size",
4927 .help = "the size of offset padding",
4928 .next = NEXT(item_l2tpv2_type_data_o,
4929 NEXT_ENTRY(COMMON_UNSIGNED),
4931 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4932 hdr.type4.offset_size)),
4934 [ITEM_L2TPV2_TYPE_DATA_L_S] = {
4936 .help = "Type #3: data message contains length, ns, nr "
4938 .next = NEXT(item_l2tpv2_type_data_l_s),
4939 .call = parse_vc_item_l2tpv2_type,
4941 [ITEM_L2TPV2_MSG_DATA_L_S_LENGTH] = {
4943 .help = "message length",
4944 .next = NEXT(item_l2tpv2_type_data_l_s,
4945 NEXT_ENTRY(COMMON_UNSIGNED),
4947 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4950 [ITEM_L2TPV2_MSG_DATA_L_S_TUNNEL_ID] = {
4951 .name = "tunnel_id",
4952 .help = "tunnel identifier",
4953 .next = NEXT(item_l2tpv2_type_data_l_s,
4954 NEXT_ENTRY(COMMON_UNSIGNED),
4956 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4957 hdr.type3.tunnel_id)),
4959 [ITEM_L2TPV2_MSG_DATA_L_S_SESSION_ID] = {
4960 .name = "session_id",
4961 .help = "session identifier",
4962 .next = NEXT(item_l2tpv2_type_data_l_s,
4963 NEXT_ENTRY(COMMON_UNSIGNED),
4965 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4966 hdr.type3.session_id)),
4968 [ITEM_L2TPV2_MSG_DATA_L_S_NS] = {
4970 .help = "sequence number for message",
4971 .next = NEXT(item_l2tpv2_type_data_l_s,
4972 NEXT_ENTRY(COMMON_UNSIGNED),
4974 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4977 [ITEM_L2TPV2_MSG_DATA_L_S_NR] = {
4979 .help = "sequence number for next receive message",
4980 .next = NEXT(item_l2tpv2_type_data_l_s,
4981 NEXT_ENTRY(COMMON_UNSIGNED),
4983 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4986 [ITEM_L2TPV2_TYPE_CTRL] = {
4988 .help = "Type #3: conrtol message contains length, ns, nr "
4990 .next = NEXT(item_l2tpv2_type_ctrl),
4991 .call = parse_vc_item_l2tpv2_type,
4993 [ITEM_L2TPV2_MSG_CTRL_LENGTH] = {
4995 .help = "message length",
4996 .next = NEXT(item_l2tpv2_type_ctrl,
4997 NEXT_ENTRY(COMMON_UNSIGNED),
4999 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5002 [ITEM_L2TPV2_MSG_CTRL_TUNNEL_ID] = {
5003 .name = "tunnel_id",
5004 .help = "tunnel identifier",
5005 .next = NEXT(item_l2tpv2_type_ctrl,
5006 NEXT_ENTRY(COMMON_UNSIGNED),
5008 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5009 hdr.type3.tunnel_id)),
5011 [ITEM_L2TPV2_MSG_CTRL_SESSION_ID] = {
5012 .name = "session_id",
5013 .help = "session identifier",
5014 .next = NEXT(item_l2tpv2_type_ctrl,
5015 NEXT_ENTRY(COMMON_UNSIGNED),
5017 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5018 hdr.type3.session_id)),
5020 [ITEM_L2TPV2_MSG_CTRL_NS] = {
5022 .help = "sequence number for message",
5023 .next = NEXT(item_l2tpv2_type_ctrl,
5024 NEXT_ENTRY(COMMON_UNSIGNED),
5026 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5029 [ITEM_L2TPV2_MSG_CTRL_NR] = {
5031 .help = "sequence number for next receive message",
5032 .next = NEXT(item_l2tpv2_type_ctrl,
5033 NEXT_ENTRY(COMMON_UNSIGNED),
5035 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5040 .help = "match PPP header",
5041 .priv = PRIV_ITEM(PPP, sizeof(struct rte_flow_item_ppp)),
5042 .next = NEXT(item_ppp),
5047 .help = "PPP address",
5048 .next = NEXT(item_ppp, NEXT_ENTRY(COMMON_UNSIGNED),
5050 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_ppp, hdr.addr)),
5054 .help = "PPP control",
5055 .next = NEXT(item_ppp, NEXT_ENTRY(COMMON_UNSIGNED),
5057 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_ppp, hdr.ctrl)),
5059 [ITEM_PPP_PROTO_ID] = {
5061 .help = "PPP protocol identifier",
5062 .next = NEXT(item_ppp, NEXT_ENTRY(COMMON_UNSIGNED),
5064 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_ppp,
5067 /* Validate/create actions. */
5070 .help = "submit a list of associated actions",
5071 .next = NEXT(next_action),
5076 .help = "specify next action",
5077 .next = NEXT(next_action),
5081 .help = "end list of actions",
5082 .priv = PRIV_ACTION(END, 0),
5087 .help = "no-op action",
5088 .priv = PRIV_ACTION(VOID, 0),
5089 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
5092 [ACTION_PASSTHRU] = {
5094 .help = "let subsequent rule process matched packets",
5095 .priv = PRIV_ACTION(PASSTHRU, 0),
5096 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
5101 .help = "redirect traffic to a given group",
5102 .priv = PRIV_ACTION(JUMP, sizeof(struct rte_flow_action_jump)),
5103 .next = NEXT(action_jump),
5106 [ACTION_JUMP_GROUP] = {
5108 .help = "group to redirect traffic to",
5109 .next = NEXT(action_jump, NEXT_ENTRY(COMMON_UNSIGNED)),
5110 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_jump, group)),
5111 .call = parse_vc_conf,
5115 .help = "attach 32 bit value to packets",
5116 .priv = PRIV_ACTION(MARK, sizeof(struct rte_flow_action_mark)),
5117 .next = NEXT(action_mark),
5120 [ACTION_MARK_ID] = {
5122 .help = "32 bit value to return with packets",
5123 .next = NEXT(action_mark, NEXT_ENTRY(COMMON_UNSIGNED)),
5124 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_mark, id)),
5125 .call = parse_vc_conf,
5129 .help = "flag packets",
5130 .priv = PRIV_ACTION(FLAG, 0),
5131 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
5136 .help = "assign packets to a given queue index",
5137 .priv = PRIV_ACTION(QUEUE,
5138 sizeof(struct rte_flow_action_queue)),
5139 .next = NEXT(action_queue),
5142 [ACTION_QUEUE_INDEX] = {
5144 .help = "queue index to use",
5145 .next = NEXT(action_queue, NEXT_ENTRY(COMMON_UNSIGNED)),
5146 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_queue, index)),
5147 .call = parse_vc_conf,
5151 .help = "drop packets (note: passthru has priority)",
5152 .priv = PRIV_ACTION(DROP, 0),
5153 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
5158 .help = "enable counters for this rule",
5159 .priv = PRIV_ACTION(COUNT,
5160 sizeof(struct rte_flow_action_count)),
5161 .next = NEXT(action_count),
5164 [ACTION_COUNT_ID] = {
5165 .name = "identifier",
5166 .help = "counter identifier to use",
5167 .next = NEXT(action_count, NEXT_ENTRY(COMMON_UNSIGNED)),
5168 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_count, id)),
5169 .call = parse_vc_conf,
5173 .help = "spread packets among several queues",
5174 .priv = PRIV_ACTION(RSS, sizeof(struct action_rss_data)),
5175 .next = NEXT(action_rss),
5176 .call = parse_vc_action_rss,
5178 [ACTION_RSS_FUNC] = {
5180 .help = "RSS hash function to apply",
5181 .next = NEXT(action_rss,
5182 NEXT_ENTRY(ACTION_RSS_FUNC_DEFAULT,
5183 ACTION_RSS_FUNC_TOEPLITZ,
5184 ACTION_RSS_FUNC_SIMPLE_XOR,
5185 ACTION_RSS_FUNC_SYMMETRIC_TOEPLITZ)),
5187 [ACTION_RSS_FUNC_DEFAULT] = {
5189 .help = "default hash function",
5190 .call = parse_vc_action_rss_func,
5192 [ACTION_RSS_FUNC_TOEPLITZ] = {
5194 .help = "Toeplitz hash function",
5195 .call = parse_vc_action_rss_func,
5197 [ACTION_RSS_FUNC_SIMPLE_XOR] = {
5198 .name = "simple_xor",
5199 .help = "simple XOR hash function",
5200 .call = parse_vc_action_rss_func,
5202 [ACTION_RSS_FUNC_SYMMETRIC_TOEPLITZ] = {
5203 .name = "symmetric_toeplitz",
5204 .help = "Symmetric Toeplitz hash function",
5205 .call = parse_vc_action_rss_func,
5207 [ACTION_RSS_LEVEL] = {
5209 .help = "encapsulation level for \"types\"",
5210 .next = NEXT(action_rss, NEXT_ENTRY(COMMON_UNSIGNED)),
5211 .args = ARGS(ARGS_ENTRY_ARB
5212 (offsetof(struct action_rss_data, conf) +
5213 offsetof(struct rte_flow_action_rss, level),
5214 sizeof(((struct rte_flow_action_rss *)0)->
5217 [ACTION_RSS_TYPES] = {
5219 .help = "specific RSS hash types",
5220 .next = NEXT(action_rss, NEXT_ENTRY(ACTION_RSS_TYPE)),
5222 [ACTION_RSS_TYPE] = {
5224 .help = "RSS hash type",
5225 .call = parse_vc_action_rss_type,
5226 .comp = comp_vc_action_rss_type,
5228 [ACTION_RSS_KEY] = {
5230 .help = "RSS hash key",
5231 .next = NEXT(action_rss, NEXT_ENTRY(COMMON_HEX)),
5232 .args = ARGS(ARGS_ENTRY_ARB
5233 (offsetof(struct action_rss_data, conf) +
5234 offsetof(struct rte_flow_action_rss, key),
5235 sizeof(((struct rte_flow_action_rss *)0)->key)),
5237 (offsetof(struct action_rss_data, conf) +
5238 offsetof(struct rte_flow_action_rss, key_len),
5239 sizeof(((struct rte_flow_action_rss *)0)->
5241 ARGS_ENTRY(struct action_rss_data, key)),
5243 [ACTION_RSS_KEY_LEN] = {
5245 .help = "RSS hash key length in bytes",
5246 .next = NEXT(action_rss, NEXT_ENTRY(COMMON_UNSIGNED)),
5247 .args = ARGS(ARGS_ENTRY_ARB_BOUNDED
5248 (offsetof(struct action_rss_data, conf) +
5249 offsetof(struct rte_flow_action_rss, key_len),
5250 sizeof(((struct rte_flow_action_rss *)0)->
5253 RSS_HASH_KEY_LENGTH)),
5255 [ACTION_RSS_QUEUES] = {
5257 .help = "queue indices to use",
5258 .next = NEXT(action_rss, NEXT_ENTRY(ACTION_RSS_QUEUE)),
5259 .call = parse_vc_conf,
5261 [ACTION_RSS_QUEUE] = {
5263 .help = "queue index",
5264 .call = parse_vc_action_rss_queue,
5265 .comp = comp_vc_action_rss_queue,
5269 .help = "direct traffic to physical function",
5270 .priv = PRIV_ACTION(PF, 0),
5271 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
5276 .help = "direct traffic to a virtual function ID",
5277 .priv = PRIV_ACTION(VF, sizeof(struct rte_flow_action_vf)),
5278 .next = NEXT(action_vf),
5281 [ACTION_VF_ORIGINAL] = {
5283 .help = "use original VF ID if possible",
5284 .next = NEXT(action_vf, NEXT_ENTRY(COMMON_BOOLEAN)),
5285 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_vf,
5287 .call = parse_vc_conf,
5292 .next = NEXT(action_vf, NEXT_ENTRY(COMMON_UNSIGNED)),
5293 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_vf, id)),
5294 .call = parse_vc_conf,
5296 [ACTION_PHY_PORT] = {
5298 .help = "direct packets to physical port index",
5299 .priv = PRIV_ACTION(PHY_PORT,
5300 sizeof(struct rte_flow_action_phy_port)),
5301 .next = NEXT(action_phy_port),
5304 [ACTION_PHY_PORT_ORIGINAL] = {
5306 .help = "use original port index if possible",
5307 .next = NEXT(action_phy_port, NEXT_ENTRY(COMMON_BOOLEAN)),
5308 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_phy_port,
5310 .call = parse_vc_conf,
5312 [ACTION_PHY_PORT_INDEX] = {
5314 .help = "physical port index",
5315 .next = NEXT(action_phy_port, NEXT_ENTRY(COMMON_UNSIGNED)),
5316 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_phy_port,
5318 .call = parse_vc_conf,
5320 [ACTION_PORT_ID] = {
5322 .help = "direct matching traffic to a given DPDK port ID",
5323 .priv = PRIV_ACTION(PORT_ID,
5324 sizeof(struct rte_flow_action_port_id)),
5325 .next = NEXT(action_port_id),
5328 [ACTION_PORT_ID_ORIGINAL] = {
5330 .help = "use original DPDK port ID if possible",
5331 .next = NEXT(action_port_id, NEXT_ENTRY(COMMON_BOOLEAN)),
5332 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_port_id,
5334 .call = parse_vc_conf,
5336 [ACTION_PORT_ID_ID] = {
5338 .help = "DPDK port ID",
5339 .next = NEXT(action_port_id, NEXT_ENTRY(COMMON_UNSIGNED)),
5340 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_port_id, id)),
5341 .call = parse_vc_conf,
5345 .help = "meter the directed packets at given id",
5346 .priv = PRIV_ACTION(METER,
5347 sizeof(struct rte_flow_action_meter)),
5348 .next = NEXT(action_meter),
5351 [ACTION_METER_COLOR] = {
5353 .help = "meter color for the packets",
5354 .priv = PRIV_ACTION(METER_COLOR,
5355 sizeof(struct rte_flow_action_meter_color)),
5356 .next = NEXT(action_meter_color),
5359 [ACTION_METER_COLOR_TYPE] = {
5361 .help = "specific meter color",
5362 .next = NEXT(NEXT_ENTRY(ACTION_NEXT),
5363 NEXT_ENTRY(ACTION_METER_COLOR_GREEN,
5364 ACTION_METER_COLOR_YELLOW,
5365 ACTION_METER_COLOR_RED)),
5367 [ACTION_METER_COLOR_GREEN] = {
5369 .help = "meter color green",
5370 .call = parse_vc_action_meter_color_type,
5372 [ACTION_METER_COLOR_YELLOW] = {
5374 .help = "meter color yellow",
5375 .call = parse_vc_action_meter_color_type,
5377 [ACTION_METER_COLOR_RED] = {
5379 .help = "meter color red",
5380 .call = parse_vc_action_meter_color_type,
5382 [ACTION_METER_ID] = {
5384 .help = "meter id to use",
5385 .next = NEXT(action_meter, NEXT_ENTRY(COMMON_UNSIGNED)),
5386 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_meter, mtr_id)),
5387 .call = parse_vc_conf,
5389 [ACTION_OF_SET_MPLS_TTL] = {
5390 .name = "of_set_mpls_ttl",
5391 .help = "OpenFlow's OFPAT_SET_MPLS_TTL",
5394 sizeof(struct rte_flow_action_of_set_mpls_ttl)),
5395 .next = NEXT(action_of_set_mpls_ttl),
5398 [ACTION_OF_SET_MPLS_TTL_MPLS_TTL] = {
5401 .next = NEXT(action_of_set_mpls_ttl,
5402 NEXT_ENTRY(COMMON_UNSIGNED)),
5403 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_of_set_mpls_ttl,
5405 .call = parse_vc_conf,
5407 [ACTION_OF_DEC_MPLS_TTL] = {
5408 .name = "of_dec_mpls_ttl",
5409 .help = "OpenFlow's OFPAT_DEC_MPLS_TTL",
5410 .priv = PRIV_ACTION(OF_DEC_MPLS_TTL, 0),
5411 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
5414 [ACTION_OF_SET_NW_TTL] = {
5415 .name = "of_set_nw_ttl",
5416 .help = "OpenFlow's OFPAT_SET_NW_TTL",
5419 sizeof(struct rte_flow_action_of_set_nw_ttl)),
5420 .next = NEXT(action_of_set_nw_ttl),
5423 [ACTION_OF_SET_NW_TTL_NW_TTL] = {
5426 .next = NEXT(action_of_set_nw_ttl, NEXT_ENTRY(COMMON_UNSIGNED)),
5427 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_of_set_nw_ttl,
5429 .call = parse_vc_conf,
5431 [ACTION_OF_DEC_NW_TTL] = {
5432 .name = "of_dec_nw_ttl",
5433 .help = "OpenFlow's OFPAT_DEC_NW_TTL",
5434 .priv = PRIV_ACTION(OF_DEC_NW_TTL, 0),
5435 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
5438 [ACTION_OF_COPY_TTL_OUT] = {
5439 .name = "of_copy_ttl_out",
5440 .help = "OpenFlow's OFPAT_COPY_TTL_OUT",
5441 .priv = PRIV_ACTION(OF_COPY_TTL_OUT, 0),
5442 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
5445 [ACTION_OF_COPY_TTL_IN] = {
5446 .name = "of_copy_ttl_in",
5447 .help = "OpenFlow's OFPAT_COPY_TTL_IN",
5448 .priv = PRIV_ACTION(OF_COPY_TTL_IN, 0),
5449 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
5452 [ACTION_OF_POP_VLAN] = {
5453 .name = "of_pop_vlan",
5454 .help = "OpenFlow's OFPAT_POP_VLAN",
5455 .priv = PRIV_ACTION(OF_POP_VLAN, 0),
5456 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
5459 [ACTION_OF_PUSH_VLAN] = {
5460 .name = "of_push_vlan",
5461 .help = "OpenFlow's OFPAT_PUSH_VLAN",
5464 sizeof(struct rte_flow_action_of_push_vlan)),
5465 .next = NEXT(action_of_push_vlan),
5468 [ACTION_OF_PUSH_VLAN_ETHERTYPE] = {
5469 .name = "ethertype",
5470 .help = "EtherType",
5471 .next = NEXT(action_of_push_vlan, NEXT_ENTRY(COMMON_UNSIGNED)),
5472 .args = ARGS(ARGS_ENTRY_HTON
5473 (struct rte_flow_action_of_push_vlan,
5475 .call = parse_vc_conf,
5477 [ACTION_OF_SET_VLAN_VID] = {
5478 .name = "of_set_vlan_vid",
5479 .help = "OpenFlow's OFPAT_SET_VLAN_VID",
5482 sizeof(struct rte_flow_action_of_set_vlan_vid)),
5483 .next = NEXT(action_of_set_vlan_vid),
5486 [ACTION_OF_SET_VLAN_VID_VLAN_VID] = {
5489 .next = NEXT(action_of_set_vlan_vid,
5490 NEXT_ENTRY(COMMON_UNSIGNED)),
5491 .args = ARGS(ARGS_ENTRY_HTON
5492 (struct rte_flow_action_of_set_vlan_vid,
5494 .call = parse_vc_conf,
5496 [ACTION_OF_SET_VLAN_PCP] = {
5497 .name = "of_set_vlan_pcp",
5498 .help = "OpenFlow's OFPAT_SET_VLAN_PCP",
5501 sizeof(struct rte_flow_action_of_set_vlan_pcp)),
5502 .next = NEXT(action_of_set_vlan_pcp),
5505 [ACTION_OF_SET_VLAN_PCP_VLAN_PCP] = {
5507 .help = "VLAN priority",
5508 .next = NEXT(action_of_set_vlan_pcp,
5509 NEXT_ENTRY(COMMON_UNSIGNED)),
5510 .args = ARGS(ARGS_ENTRY_HTON
5511 (struct rte_flow_action_of_set_vlan_pcp,
5513 .call = parse_vc_conf,
5515 [ACTION_OF_POP_MPLS] = {
5516 .name = "of_pop_mpls",
5517 .help = "OpenFlow's OFPAT_POP_MPLS",
5518 .priv = PRIV_ACTION(OF_POP_MPLS,
5519 sizeof(struct rte_flow_action_of_pop_mpls)),
5520 .next = NEXT(action_of_pop_mpls),
5523 [ACTION_OF_POP_MPLS_ETHERTYPE] = {
5524 .name = "ethertype",
5525 .help = "EtherType",
5526 .next = NEXT(action_of_pop_mpls, NEXT_ENTRY(COMMON_UNSIGNED)),
5527 .args = ARGS(ARGS_ENTRY_HTON
5528 (struct rte_flow_action_of_pop_mpls,
5530 .call = parse_vc_conf,
5532 [ACTION_OF_PUSH_MPLS] = {
5533 .name = "of_push_mpls",
5534 .help = "OpenFlow's OFPAT_PUSH_MPLS",
5537 sizeof(struct rte_flow_action_of_push_mpls)),
5538 .next = NEXT(action_of_push_mpls),
5541 [ACTION_OF_PUSH_MPLS_ETHERTYPE] = {
5542 .name = "ethertype",
5543 .help = "EtherType",
5544 .next = NEXT(action_of_push_mpls, NEXT_ENTRY(COMMON_UNSIGNED)),
5545 .args = ARGS(ARGS_ENTRY_HTON
5546 (struct rte_flow_action_of_push_mpls,
5548 .call = parse_vc_conf,
5550 [ACTION_VXLAN_ENCAP] = {
5551 .name = "vxlan_encap",
5552 .help = "VXLAN encapsulation, uses configuration set by \"set"
5554 .priv = PRIV_ACTION(VXLAN_ENCAP,
5555 sizeof(struct action_vxlan_encap_data)),
5556 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
5557 .call = parse_vc_action_vxlan_encap,
5559 [ACTION_VXLAN_DECAP] = {
5560 .name = "vxlan_decap",
5561 .help = "Performs a decapsulation action by stripping all"
5562 " headers of the VXLAN tunnel network overlay from the"
5564 .priv = PRIV_ACTION(VXLAN_DECAP, 0),
5565 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
5568 [ACTION_NVGRE_ENCAP] = {
5569 .name = "nvgre_encap",
5570 .help = "NVGRE encapsulation, uses configuration set by \"set"
5572 .priv = PRIV_ACTION(NVGRE_ENCAP,
5573 sizeof(struct action_nvgre_encap_data)),
5574 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
5575 .call = parse_vc_action_nvgre_encap,
5577 [ACTION_NVGRE_DECAP] = {
5578 .name = "nvgre_decap",
5579 .help = "Performs a decapsulation action by stripping all"
5580 " headers of the NVGRE tunnel network overlay from the"
5582 .priv = PRIV_ACTION(NVGRE_DECAP, 0),
5583 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
5586 [ACTION_L2_ENCAP] = {
5588 .help = "l2 encap, uses configuration set by"
5589 " \"set l2_encap\"",
5590 .priv = PRIV_ACTION(RAW_ENCAP,
5591 sizeof(struct action_raw_encap_data)),
5592 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
5593 .call = parse_vc_action_l2_encap,
5595 [ACTION_L2_DECAP] = {
5597 .help = "l2 decap, uses configuration set by"
5598 " \"set l2_decap\"",
5599 .priv = PRIV_ACTION(RAW_DECAP,
5600 sizeof(struct action_raw_decap_data)),
5601 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
5602 .call = parse_vc_action_l2_decap,
5604 [ACTION_MPLSOGRE_ENCAP] = {
5605 .name = "mplsogre_encap",
5606 .help = "mplsogre encapsulation, uses configuration set by"
5607 " \"set mplsogre_encap\"",
5608 .priv = PRIV_ACTION(RAW_ENCAP,
5609 sizeof(struct action_raw_encap_data)),
5610 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
5611 .call = parse_vc_action_mplsogre_encap,
5613 [ACTION_MPLSOGRE_DECAP] = {
5614 .name = "mplsogre_decap",
5615 .help = "mplsogre decapsulation, uses configuration set by"
5616 " \"set mplsogre_decap\"",
5617 .priv = PRIV_ACTION(RAW_DECAP,
5618 sizeof(struct action_raw_decap_data)),
5619 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
5620 .call = parse_vc_action_mplsogre_decap,
5622 [ACTION_MPLSOUDP_ENCAP] = {
5623 .name = "mplsoudp_encap",
5624 .help = "mplsoudp encapsulation, uses configuration set by"
5625 " \"set mplsoudp_encap\"",
5626 .priv = PRIV_ACTION(RAW_ENCAP,
5627 sizeof(struct action_raw_encap_data)),
5628 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
5629 .call = parse_vc_action_mplsoudp_encap,
5631 [ACTION_MPLSOUDP_DECAP] = {
5632 .name = "mplsoudp_decap",
5633 .help = "mplsoudp decapsulation, uses configuration set by"
5634 " \"set mplsoudp_decap\"",
5635 .priv = PRIV_ACTION(RAW_DECAP,
5636 sizeof(struct action_raw_decap_data)),
5637 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
5638 .call = parse_vc_action_mplsoudp_decap,
5640 [ACTION_SET_IPV4_SRC] = {
5641 .name = "set_ipv4_src",
5642 .help = "Set a new IPv4 source address in the outermost"
5644 .priv = PRIV_ACTION(SET_IPV4_SRC,
5645 sizeof(struct rte_flow_action_set_ipv4)),
5646 .next = NEXT(action_set_ipv4_src),
5649 [ACTION_SET_IPV4_SRC_IPV4_SRC] = {
5650 .name = "ipv4_addr",
5651 .help = "new IPv4 source address to set",
5652 .next = NEXT(action_set_ipv4_src, NEXT_ENTRY(COMMON_IPV4_ADDR)),
5653 .args = ARGS(ARGS_ENTRY_HTON
5654 (struct rte_flow_action_set_ipv4, ipv4_addr)),
5655 .call = parse_vc_conf,
5657 [ACTION_SET_IPV4_DST] = {
5658 .name = "set_ipv4_dst",
5659 .help = "Set a new IPv4 destination address in the outermost"
5661 .priv = PRIV_ACTION(SET_IPV4_DST,
5662 sizeof(struct rte_flow_action_set_ipv4)),
5663 .next = NEXT(action_set_ipv4_dst),
5666 [ACTION_SET_IPV4_DST_IPV4_DST] = {
5667 .name = "ipv4_addr",
5668 .help = "new IPv4 destination address to set",
5669 .next = NEXT(action_set_ipv4_dst, NEXT_ENTRY(COMMON_IPV4_ADDR)),
5670 .args = ARGS(ARGS_ENTRY_HTON
5671 (struct rte_flow_action_set_ipv4, ipv4_addr)),
5672 .call = parse_vc_conf,
5674 [ACTION_SET_IPV6_SRC] = {
5675 .name = "set_ipv6_src",
5676 .help = "Set a new IPv6 source address in the outermost"
5678 .priv = PRIV_ACTION(SET_IPV6_SRC,
5679 sizeof(struct rte_flow_action_set_ipv6)),
5680 .next = NEXT(action_set_ipv6_src),
5683 [ACTION_SET_IPV6_SRC_IPV6_SRC] = {
5684 .name = "ipv6_addr",
5685 .help = "new IPv6 source address to set",
5686 .next = NEXT(action_set_ipv6_src, NEXT_ENTRY(COMMON_IPV6_ADDR)),
5687 .args = ARGS(ARGS_ENTRY_HTON
5688 (struct rte_flow_action_set_ipv6, ipv6_addr)),
5689 .call = parse_vc_conf,
5691 [ACTION_SET_IPV6_DST] = {
5692 .name = "set_ipv6_dst",
5693 .help = "Set a new IPv6 destination address in the outermost"
5695 .priv = PRIV_ACTION(SET_IPV6_DST,
5696 sizeof(struct rte_flow_action_set_ipv6)),
5697 .next = NEXT(action_set_ipv6_dst),
5700 [ACTION_SET_IPV6_DST_IPV6_DST] = {
5701 .name = "ipv6_addr",
5702 .help = "new IPv6 destination address to set",
5703 .next = NEXT(action_set_ipv6_dst, NEXT_ENTRY(COMMON_IPV6_ADDR)),
5704 .args = ARGS(ARGS_ENTRY_HTON
5705 (struct rte_flow_action_set_ipv6, ipv6_addr)),
5706 .call = parse_vc_conf,
5708 [ACTION_SET_TP_SRC] = {
5709 .name = "set_tp_src",
5710 .help = "set a new source port number in the outermost"
5712 .priv = PRIV_ACTION(SET_TP_SRC,
5713 sizeof(struct rte_flow_action_set_tp)),
5714 .next = NEXT(action_set_tp_src),
5717 [ACTION_SET_TP_SRC_TP_SRC] = {
5719 .help = "new source port number to set",
5720 .next = NEXT(action_set_tp_src, NEXT_ENTRY(COMMON_UNSIGNED)),
5721 .args = ARGS(ARGS_ENTRY_HTON
5722 (struct rte_flow_action_set_tp, port)),
5723 .call = parse_vc_conf,
5725 [ACTION_SET_TP_DST] = {
5726 .name = "set_tp_dst",
5727 .help = "set a new destination port number in the outermost"
5729 .priv = PRIV_ACTION(SET_TP_DST,
5730 sizeof(struct rte_flow_action_set_tp)),
5731 .next = NEXT(action_set_tp_dst),
5734 [ACTION_SET_TP_DST_TP_DST] = {
5736 .help = "new destination port number to set",
5737 .next = NEXT(action_set_tp_dst, NEXT_ENTRY(COMMON_UNSIGNED)),
5738 .args = ARGS(ARGS_ENTRY_HTON
5739 (struct rte_flow_action_set_tp, port)),
5740 .call = parse_vc_conf,
5742 [ACTION_MAC_SWAP] = {
5744 .help = "Swap the source and destination MAC addresses"
5745 " in the outermost Ethernet header",
5746 .priv = PRIV_ACTION(MAC_SWAP, 0),
5747 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
5750 [ACTION_DEC_TTL] = {
5752 .help = "decrease network TTL if available",
5753 .priv = PRIV_ACTION(DEC_TTL, 0),
5754 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
5757 [ACTION_SET_TTL] = {
5759 .help = "set ttl value",
5760 .priv = PRIV_ACTION(SET_TTL,
5761 sizeof(struct rte_flow_action_set_ttl)),
5762 .next = NEXT(action_set_ttl),
5765 [ACTION_SET_TTL_TTL] = {
5766 .name = "ttl_value",
5767 .help = "new ttl value to set",
5768 .next = NEXT(action_set_ttl, NEXT_ENTRY(COMMON_UNSIGNED)),
5769 .args = ARGS(ARGS_ENTRY_HTON
5770 (struct rte_flow_action_set_ttl, ttl_value)),
5771 .call = parse_vc_conf,
5773 [ACTION_SET_MAC_SRC] = {
5774 .name = "set_mac_src",
5775 .help = "set source mac address",
5776 .priv = PRIV_ACTION(SET_MAC_SRC,
5777 sizeof(struct rte_flow_action_set_mac)),
5778 .next = NEXT(action_set_mac_src),
5781 [ACTION_SET_MAC_SRC_MAC_SRC] = {
5783 .help = "new source mac address",
5784 .next = NEXT(action_set_mac_src, NEXT_ENTRY(COMMON_MAC_ADDR)),
5785 .args = ARGS(ARGS_ENTRY_HTON
5786 (struct rte_flow_action_set_mac, mac_addr)),
5787 .call = parse_vc_conf,
5789 [ACTION_SET_MAC_DST] = {
5790 .name = "set_mac_dst",
5791 .help = "set destination mac address",
5792 .priv = PRIV_ACTION(SET_MAC_DST,
5793 sizeof(struct rte_flow_action_set_mac)),
5794 .next = NEXT(action_set_mac_dst),
5797 [ACTION_SET_MAC_DST_MAC_DST] = {
5799 .help = "new destination mac address to set",
5800 .next = NEXT(action_set_mac_dst, NEXT_ENTRY(COMMON_MAC_ADDR)),
5801 .args = ARGS(ARGS_ENTRY_HTON
5802 (struct rte_flow_action_set_mac, mac_addr)),
5803 .call = parse_vc_conf,
5805 [ACTION_INC_TCP_SEQ] = {
5806 .name = "inc_tcp_seq",
5807 .help = "increase TCP sequence number",
5808 .priv = PRIV_ACTION(INC_TCP_SEQ, sizeof(rte_be32_t)),
5809 .next = NEXT(action_inc_tcp_seq),
5812 [ACTION_INC_TCP_SEQ_VALUE] = {
5814 .help = "the value to increase TCP sequence number by",
5815 .next = NEXT(action_inc_tcp_seq, NEXT_ENTRY(COMMON_UNSIGNED)),
5816 .args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
5817 .call = parse_vc_conf,
5819 [ACTION_DEC_TCP_SEQ] = {
5820 .name = "dec_tcp_seq",
5821 .help = "decrease TCP sequence number",
5822 .priv = PRIV_ACTION(DEC_TCP_SEQ, sizeof(rte_be32_t)),
5823 .next = NEXT(action_dec_tcp_seq),
5826 [ACTION_DEC_TCP_SEQ_VALUE] = {
5828 .help = "the value to decrease TCP sequence number by",
5829 .next = NEXT(action_dec_tcp_seq, NEXT_ENTRY(COMMON_UNSIGNED)),
5830 .args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
5831 .call = parse_vc_conf,
5833 [ACTION_INC_TCP_ACK] = {
5834 .name = "inc_tcp_ack",
5835 .help = "increase TCP acknowledgment number",
5836 .priv = PRIV_ACTION(INC_TCP_ACK, sizeof(rte_be32_t)),
5837 .next = NEXT(action_inc_tcp_ack),
5840 [ACTION_INC_TCP_ACK_VALUE] = {
5842 .help = "the value to increase TCP acknowledgment number by",
5843 .next = NEXT(action_inc_tcp_ack, NEXT_ENTRY(COMMON_UNSIGNED)),
5844 .args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
5845 .call = parse_vc_conf,
5847 [ACTION_DEC_TCP_ACK] = {
5848 .name = "dec_tcp_ack",
5849 .help = "decrease TCP acknowledgment number",
5850 .priv = PRIV_ACTION(DEC_TCP_ACK, sizeof(rte_be32_t)),
5851 .next = NEXT(action_dec_tcp_ack),
5854 [ACTION_DEC_TCP_ACK_VALUE] = {
5856 .help = "the value to decrease TCP acknowledgment number by",
5857 .next = NEXT(action_dec_tcp_ack, NEXT_ENTRY(COMMON_UNSIGNED)),
5858 .args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
5859 .call = parse_vc_conf,
5861 [ACTION_RAW_ENCAP] = {
5862 .name = "raw_encap",
5863 .help = "encapsulation data, defined by set raw_encap",
5864 .priv = PRIV_ACTION(RAW_ENCAP,
5865 sizeof(struct action_raw_encap_data)),
5866 .next = NEXT(action_raw_encap),
5867 .call = parse_vc_action_raw_encap,
5869 [ACTION_RAW_ENCAP_INDEX] = {
5871 .help = "the index of raw_encap_confs",
5872 .next = NEXT(NEXT_ENTRY(ACTION_RAW_ENCAP_INDEX_VALUE)),
5874 [ACTION_RAW_ENCAP_INDEX_VALUE] = {
5877 .help = "unsigned integer value",
5878 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
5879 .call = parse_vc_action_raw_encap_index,
5880 .comp = comp_set_raw_index,
5882 [ACTION_RAW_DECAP] = {
5883 .name = "raw_decap",
5884 .help = "decapsulation data, defined by set raw_encap",
5885 .priv = PRIV_ACTION(RAW_DECAP,
5886 sizeof(struct action_raw_decap_data)),
5887 .next = NEXT(action_raw_decap),
5888 .call = parse_vc_action_raw_decap,
5890 [ACTION_RAW_DECAP_INDEX] = {
5892 .help = "the index of raw_encap_confs",
5893 .next = NEXT(NEXT_ENTRY(ACTION_RAW_DECAP_INDEX_VALUE)),
5895 [ACTION_RAW_DECAP_INDEX_VALUE] = {
5898 .help = "unsigned integer value",
5899 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
5900 .call = parse_vc_action_raw_decap_index,
5901 .comp = comp_set_raw_index,
5903 [ACTION_MODIFY_FIELD] = {
5904 .name = "modify_field",
5905 .help = "modify destination field with data from source field",
5906 .priv = PRIV_ACTION(MODIFY_FIELD, ACTION_MODIFY_SIZE),
5907 .next = NEXT(NEXT_ENTRY(ACTION_MODIFY_FIELD_OP)),
5910 [ACTION_MODIFY_FIELD_OP] = {
5912 .help = "operation type",
5913 .next = NEXT(NEXT_ENTRY(ACTION_MODIFY_FIELD_DST_TYPE),
5914 NEXT_ENTRY(ACTION_MODIFY_FIELD_OP_VALUE)),
5915 .call = parse_vc_conf,
5917 [ACTION_MODIFY_FIELD_OP_VALUE] = {
5918 .name = "{operation}",
5919 .help = "operation type value",
5920 .call = parse_vc_modify_field_op,
5921 .comp = comp_set_modify_field_op,
5923 [ACTION_MODIFY_FIELD_DST_TYPE] = {
5925 .help = "destination field type",
5926 .next = NEXT(action_modify_field_dst,
5927 NEXT_ENTRY(ACTION_MODIFY_FIELD_DST_TYPE_VALUE)),
5928 .call = parse_vc_conf,
5930 [ACTION_MODIFY_FIELD_DST_TYPE_VALUE] = {
5931 .name = "{dst_type}",
5932 .help = "destination field type value",
5933 .call = parse_vc_modify_field_id,
5934 .comp = comp_set_modify_field_id,
5936 [ACTION_MODIFY_FIELD_DST_LEVEL] = {
5937 .name = "dst_level",
5938 .help = "destination field level",
5939 .next = NEXT(action_modify_field_dst,
5940 NEXT_ENTRY(COMMON_UNSIGNED)),
5941 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
5943 .call = parse_vc_conf,
5945 [ACTION_MODIFY_FIELD_DST_OFFSET] = {
5946 .name = "dst_offset",
5947 .help = "destination field bit offset",
5948 .next = NEXT(action_modify_field_dst,
5949 NEXT_ENTRY(COMMON_UNSIGNED)),
5950 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
5952 .call = parse_vc_conf,
5954 [ACTION_MODIFY_FIELD_SRC_TYPE] = {
5956 .help = "source field type",
5957 .next = NEXT(action_modify_field_src,
5958 NEXT_ENTRY(ACTION_MODIFY_FIELD_SRC_TYPE_VALUE)),
5959 .call = parse_vc_conf,
5961 [ACTION_MODIFY_FIELD_SRC_TYPE_VALUE] = {
5962 .name = "{src_type}",
5963 .help = "source field type value",
5964 .call = parse_vc_modify_field_id,
5965 .comp = comp_set_modify_field_id,
5967 [ACTION_MODIFY_FIELD_SRC_LEVEL] = {
5968 .name = "src_level",
5969 .help = "source field level",
5970 .next = NEXT(action_modify_field_src,
5971 NEXT_ENTRY(COMMON_UNSIGNED)),
5972 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
5974 .call = parse_vc_conf,
5976 [ACTION_MODIFY_FIELD_SRC_OFFSET] = {
5977 .name = "src_offset",
5978 .help = "source field bit offset",
5979 .next = NEXT(action_modify_field_src,
5980 NEXT_ENTRY(COMMON_UNSIGNED)),
5981 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
5983 .call = parse_vc_conf,
5985 [ACTION_MODIFY_FIELD_SRC_VALUE] = {
5986 .name = "src_value",
5987 .help = "source immediate value",
5988 .next = NEXT(NEXT_ENTRY(ACTION_MODIFY_FIELD_WIDTH),
5989 NEXT_ENTRY(COMMON_HEX)),
5990 .args = ARGS(ARGS_ENTRY_ARB(0, 0),
5991 ARGS_ENTRY_ARB(0, 0),
5992 ARGS_ENTRY(struct rte_flow_action_modify_field,
5994 .call = parse_vc_conf,
5996 [ACTION_MODIFY_FIELD_SRC_POINTER] = {
5998 .help = "pointer to source immediate value",
5999 .next = NEXT(NEXT_ENTRY(ACTION_MODIFY_FIELD_WIDTH),
6000 NEXT_ENTRY(COMMON_HEX)),
6001 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
6003 ARGS_ENTRY_ARB(0, 0),
6005 (sizeof(struct rte_flow_action_modify_field),
6006 ACTION_MODIFY_PATTERN_SIZE)),
6007 .call = parse_vc_conf,
6009 [ACTION_MODIFY_FIELD_WIDTH] = {
6011 .help = "number of bits to copy",
6012 .next = NEXT(NEXT_ENTRY(ACTION_NEXT),
6013 NEXT_ENTRY(COMMON_UNSIGNED)),
6014 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
6016 .call = parse_vc_conf,
6018 /* Top level command. */
6021 .help = "set raw encap/decap/sample data",
6022 .type = "set raw_encap|raw_decap <index> <pattern>"
6023 " or set sample_actions <index> <action>",
6024 .next = NEXT(NEXT_ENTRY
6027 SET_SAMPLE_ACTIONS)),
6028 .call = parse_set_init,
6030 /* Sub-level commands. */
6032 .name = "raw_encap",
6033 .help = "set raw encap data",
6034 .next = NEXT(next_set_raw),
6035 .args = ARGS(ARGS_ENTRY_ARB_BOUNDED
6036 (offsetof(struct buffer, port),
6037 sizeof(((struct buffer *)0)->port),
6038 0, RAW_ENCAP_CONFS_MAX_NUM - 1)),
6039 .call = parse_set_raw_encap_decap,
6042 .name = "raw_decap",
6043 .help = "set raw decap data",
6044 .next = NEXT(next_set_raw),
6045 .args = ARGS(ARGS_ENTRY_ARB_BOUNDED
6046 (offsetof(struct buffer, port),
6047 sizeof(((struct buffer *)0)->port),
6048 0, RAW_ENCAP_CONFS_MAX_NUM - 1)),
6049 .call = parse_set_raw_encap_decap,
6053 .type = "COMMON_UNSIGNED",
6054 .help = "index of raw_encap/raw_decap data",
6055 .next = NEXT(next_item),
6058 [SET_SAMPLE_INDEX] = {
6061 .help = "index of sample actions",
6062 .next = NEXT(next_action_sample),
6065 [SET_SAMPLE_ACTIONS] = {
6066 .name = "sample_actions",
6067 .help = "set sample actions list",
6068 .next = NEXT(NEXT_ENTRY(SET_SAMPLE_INDEX)),
6069 .args = ARGS(ARGS_ENTRY_ARB_BOUNDED
6070 (offsetof(struct buffer, port),
6071 sizeof(((struct buffer *)0)->port),
6072 0, RAW_SAMPLE_CONFS_MAX_NUM - 1)),
6073 .call = parse_set_sample_action,
6075 [ACTION_SET_TAG] = {
6078 .priv = PRIV_ACTION(SET_TAG,
6079 sizeof(struct rte_flow_action_set_tag)),
6080 .next = NEXT(action_set_tag),
6083 [ACTION_SET_TAG_INDEX] = {
6085 .help = "index of tag array",
6086 .next = NEXT(action_set_tag, NEXT_ENTRY(COMMON_UNSIGNED)),
6087 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_set_tag, index)),
6088 .call = parse_vc_conf,
6090 [ACTION_SET_TAG_DATA] = {
6092 .help = "tag value",
6093 .next = NEXT(action_set_tag, NEXT_ENTRY(COMMON_UNSIGNED)),
6094 .args = ARGS(ARGS_ENTRY
6095 (struct rte_flow_action_set_tag, data)),
6096 .call = parse_vc_conf,
6098 [ACTION_SET_TAG_MASK] = {
6100 .help = "mask for tag value",
6101 .next = NEXT(action_set_tag, NEXT_ENTRY(COMMON_UNSIGNED)),
6102 .args = ARGS(ARGS_ENTRY
6103 (struct rte_flow_action_set_tag, mask)),
6104 .call = parse_vc_conf,
6106 [ACTION_SET_META] = {
6108 .help = "set metadata",
6109 .priv = PRIV_ACTION(SET_META,
6110 sizeof(struct rte_flow_action_set_meta)),
6111 .next = NEXT(action_set_meta),
6112 .call = parse_vc_action_set_meta,
6114 [ACTION_SET_META_DATA] = {
6116 .help = "metadata value",
6117 .next = NEXT(action_set_meta, NEXT_ENTRY(COMMON_UNSIGNED)),
6118 .args = ARGS(ARGS_ENTRY
6119 (struct rte_flow_action_set_meta, data)),
6120 .call = parse_vc_conf,
6122 [ACTION_SET_META_MASK] = {
6124 .help = "mask for metadata value",
6125 .next = NEXT(action_set_meta, NEXT_ENTRY(COMMON_UNSIGNED)),
6126 .args = ARGS(ARGS_ENTRY
6127 (struct rte_flow_action_set_meta, mask)),
6128 .call = parse_vc_conf,
6130 [ACTION_SET_IPV4_DSCP] = {
6131 .name = "set_ipv4_dscp",
6132 .help = "set DSCP value",
6133 .priv = PRIV_ACTION(SET_IPV4_DSCP,
6134 sizeof(struct rte_flow_action_set_dscp)),
6135 .next = NEXT(action_set_ipv4_dscp),
6138 [ACTION_SET_IPV4_DSCP_VALUE] = {
6139 .name = "dscp_value",
6140 .help = "new IPv4 DSCP value to set",
6141 .next = NEXT(action_set_ipv4_dscp, NEXT_ENTRY(COMMON_UNSIGNED)),
6142 .args = ARGS(ARGS_ENTRY
6143 (struct rte_flow_action_set_dscp, dscp)),
6144 .call = parse_vc_conf,
6146 [ACTION_SET_IPV6_DSCP] = {
6147 .name = "set_ipv6_dscp",
6148 .help = "set DSCP value",
6149 .priv = PRIV_ACTION(SET_IPV6_DSCP,
6150 sizeof(struct rte_flow_action_set_dscp)),
6151 .next = NEXT(action_set_ipv6_dscp),
6154 [ACTION_SET_IPV6_DSCP_VALUE] = {
6155 .name = "dscp_value",
6156 .help = "new IPv6 DSCP value to set",
6157 .next = NEXT(action_set_ipv6_dscp, NEXT_ENTRY(COMMON_UNSIGNED)),
6158 .args = ARGS(ARGS_ENTRY
6159 (struct rte_flow_action_set_dscp, dscp)),
6160 .call = parse_vc_conf,
6164 .help = "set a specific metadata header",
6165 .next = NEXT(action_age),
6166 .priv = PRIV_ACTION(AGE,
6167 sizeof(struct rte_flow_action_age)),
6170 [ACTION_AGE_TIMEOUT] = {
6172 .help = "flow age timeout value",
6173 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_age,
6175 .next = NEXT(action_age, NEXT_ENTRY(COMMON_UNSIGNED)),
6176 .call = parse_vc_conf,
6180 .help = "set a sample action",
6181 .next = NEXT(action_sample),
6182 .priv = PRIV_ACTION(SAMPLE,
6183 sizeof(struct action_sample_data)),
6184 .call = parse_vc_action_sample,
6186 [ACTION_SAMPLE_RATIO] = {
6188 .help = "flow sample ratio value",
6189 .next = NEXT(action_sample, NEXT_ENTRY(COMMON_UNSIGNED)),
6190 .args = ARGS(ARGS_ENTRY_ARB
6191 (offsetof(struct action_sample_data, conf) +
6192 offsetof(struct rte_flow_action_sample, ratio),
6193 sizeof(((struct rte_flow_action_sample *)0)->
6196 [ACTION_SAMPLE_INDEX] = {
6198 .help = "the index of sample actions list",
6199 .next = NEXT(NEXT_ENTRY(ACTION_SAMPLE_INDEX_VALUE)),
6201 [ACTION_SAMPLE_INDEX_VALUE] = {
6203 .type = "COMMON_UNSIGNED",
6204 .help = "unsigned integer value",
6205 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6206 .call = parse_vc_action_sample_index,
6207 .comp = comp_set_sample_index,
6209 [ACTION_CONNTRACK] = {
6210 .name = "conntrack",
6211 .help = "create a conntrack object",
6212 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6213 .priv = PRIV_ACTION(CONNTRACK,
6214 sizeof(struct rte_flow_action_conntrack)),
6217 [ACTION_CONNTRACK_UPDATE] = {
6218 .name = "conntrack_update",
6219 .help = "update a conntrack object",
6220 .next = NEXT(action_update_conntrack),
6221 .priv = PRIV_ACTION(CONNTRACK,
6222 sizeof(struct rte_flow_modify_conntrack)),
6225 [ACTION_CONNTRACK_UPDATE_DIR] = {
6227 .help = "update a conntrack object direction",
6228 .next = NEXT(action_update_conntrack),
6229 .call = parse_vc_action_conntrack_update,
6231 [ACTION_CONNTRACK_UPDATE_CTX] = {
6233 .help = "update a conntrack object context",
6234 .next = NEXT(action_update_conntrack),
6235 .call = parse_vc_action_conntrack_update,
6237 [ACTION_PORT_REPRESENTOR] = {
6238 .name = "port_representor",
6239 .help = "at embedded switch level, send matching traffic to the given ethdev",
6240 .priv = PRIV_ACTION(PORT_REPRESENTOR,
6241 sizeof(struct rte_flow_action_ethdev)),
6242 .next = NEXT(action_port_representor),
6245 [ACTION_PORT_REPRESENTOR_PORT_ID] = {
6247 .help = "ethdev port ID",
6248 .next = NEXT(action_port_representor,
6249 NEXT_ENTRY(COMMON_UNSIGNED)),
6250 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_ethdev,
6252 .call = parse_vc_conf,
6254 [ACTION_REPRESENTED_PORT] = {
6255 .name = "represented_port",
6256 .help = "at embedded switch level, send matching traffic to the entity represented by the given ethdev",
6257 .priv = PRIV_ACTION(REPRESENTED_PORT,
6258 sizeof(struct rte_flow_action_ethdev)),
6259 .next = NEXT(action_represented_port),
6262 [ACTION_REPRESENTED_PORT_ETHDEV_PORT_ID] = {
6263 .name = "ethdev_port_id",
6264 .help = "ethdev port ID",
6265 .next = NEXT(action_represented_port,
6266 NEXT_ENTRY(COMMON_UNSIGNED)),
6267 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_ethdev,
6269 .call = parse_vc_conf,
6271 /* Indirect action destroy arguments. */
6272 [INDIRECT_ACTION_DESTROY_ID] = {
6273 .name = "action_id",
6274 .help = "specify a indirect action id to destroy",
6275 .next = NEXT(next_ia_destroy_attr,
6276 NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
6277 .args = ARGS(ARGS_ENTRY_PTR(struct buffer,
6278 args.ia_destroy.action_id)),
6279 .call = parse_ia_destroy,
6281 /* Indirect action create arguments. */
6282 [INDIRECT_ACTION_CREATE_ID] = {
6283 .name = "action_id",
6284 .help = "specify a indirect action id to create",
6285 .next = NEXT(next_ia_create_attr,
6286 NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
6287 .args = ARGS(ARGS_ENTRY(struct buffer, args.vc.attr.group)),
6289 [ACTION_INDIRECT] = {
6291 .help = "apply indirect action by id",
6292 .priv = PRIV_ACTION(INDIRECT, 0),
6293 .next = NEXT(NEXT_ENTRY(INDIRECT_ACTION_ID2PTR)),
6294 .args = ARGS(ARGS_ENTRY_ARB(0, sizeof(uint32_t))),
6297 [INDIRECT_ACTION_ID2PTR] = {
6298 .name = "{action_id}",
6299 .type = "INDIRECT_ACTION_ID",
6300 .help = "indirect action id",
6301 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6302 .call = parse_ia_id2ptr,
6305 [INDIRECT_ACTION_INGRESS] = {
6307 .help = "affect rule to ingress",
6308 .next = NEXT(next_ia_create_attr),
6311 [INDIRECT_ACTION_EGRESS] = {
6313 .help = "affect rule to egress",
6314 .next = NEXT(next_ia_create_attr),
6317 [INDIRECT_ACTION_TRANSFER] = {
6319 .help = "affect rule to transfer",
6320 .next = NEXT(next_ia_create_attr),
6323 [INDIRECT_ACTION_SPEC] = {
6325 .help = "specify action to create indirect handle",
6326 .next = NEXT(next_action),
6329 .name = "g_actions",
6330 .help = "submit a list of associated actions for green",
6331 .next = NEXT(next_action),
6335 .name = "y_actions",
6336 .help = "submit a list of associated actions for yellow",
6337 .next = NEXT(next_action),
6340 .name = "r_actions",
6341 .help = "submit a list of associated actions for red",
6342 .next = NEXT(next_action),
6345 /* Top-level command. */
6348 .type = "port meter policy {port_id} {arg}",
6349 .help = "add port meter policy",
6350 .next = NEXT(NEXT_ENTRY(ITEM_POL_PORT)),
6353 /* Sub-level commands. */
6356 .help = "add port meter policy",
6357 .next = NEXT(NEXT_ENTRY(ITEM_POL_METER)),
6359 [ITEM_POL_METER] = {
6361 .help = "add port meter policy",
6362 .next = NEXT(NEXT_ENTRY(ITEM_POL_POLICY)),
6364 [ITEM_POL_POLICY] = {
6366 .help = "add port meter policy",
6367 .next = NEXT(NEXT_ENTRY(ACTION_POL_R),
6368 NEXT_ENTRY(ACTION_POL_Y),
6369 NEXT_ENTRY(ACTION_POL_G),
6370 NEXT_ENTRY(COMMON_POLICY_ID),
6371 NEXT_ENTRY(COMMON_PORT_ID)),
6372 .args = ARGS(ARGS_ENTRY(struct buffer, args.policy.policy_id),
6373 ARGS_ENTRY(struct buffer, port)),
6378 /** Remove and return last entry from argument stack. */
6379 static const struct arg *
6380 pop_args(struct context *ctx)
6382 return ctx->args_num ? ctx->args[--ctx->args_num] : NULL;
6385 /** Add entry on top of the argument stack. */
6387 push_args(struct context *ctx, const struct arg *arg)
6389 if (ctx->args_num == CTX_STACK_SIZE)
6391 ctx->args[ctx->args_num++] = arg;
6395 /** Spread value into buffer according to bit-mask. */
6397 arg_entry_bf_fill(void *dst, uintmax_t val, const struct arg *arg)
6399 uint32_t i = arg->size;
6407 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
6416 unsigned int shift = 0;
6417 uint8_t *buf = (uint8_t *)dst + arg->offset + (i -= sub);
6419 for (shift = 0; arg->mask[i] >> shift; ++shift) {
6420 if (!(arg->mask[i] & (1 << shift)))
6425 *buf &= ~(1 << shift);
6426 *buf |= (val & 1) << shift;
6434 /** Compare a string with a partial one of a given length. */
6436 strcmp_partial(const char *full, const char *partial, size_t partial_len)
6438 int r = strncmp(full, partial, partial_len);
6442 if (strlen(full) <= partial_len)
6444 return full[partial_len];
6448 * Parse a prefix length and generate a bit-mask.
6450 * Last argument (ctx->args) is retrieved to determine mask size, storage
6451 * location and whether the result must use network byte ordering.
6454 parse_prefix(struct context *ctx, const struct token *token,
6455 const char *str, unsigned int len,
6456 void *buf, unsigned int size)
6458 const struct arg *arg = pop_args(ctx);
6459 static const uint8_t conv[] = "\x00\x80\xc0\xe0\xf0\xf8\xfc\xfe\xff";
6466 /* Argument is expected. */
6470 u = strtoumax(str, &end, 0);
6471 if (errno || (size_t)(end - str) != len)
6476 extra = arg_entry_bf_fill(NULL, 0, arg);
6485 if (!arg_entry_bf_fill(ctx->object, v, arg) ||
6486 !arg_entry_bf_fill(ctx->objmask, -1, arg))
6493 if (bytes > size || bytes + !!extra > size)
6497 buf = (uint8_t *)ctx->object + arg->offset;
6498 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
6500 memset((uint8_t *)buf + size - bytes, 0xff, bytes);
6501 memset(buf, 0x00, size - bytes);
6503 ((uint8_t *)buf)[size - bytes - 1] = conv[extra];
6507 memset(buf, 0xff, bytes);
6508 memset((uint8_t *)buf + bytes, 0x00, size - bytes);
6510 ((uint8_t *)buf)[bytes] = conv[extra];
6513 memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
6516 push_args(ctx, arg);
6520 /** Default parsing function for token name matching. */
6522 parse_default(struct context *ctx, const struct token *token,
6523 const char *str, unsigned int len,
6524 void *buf, unsigned int size)
6529 if (strcmp_partial(token->name, str, len))
6534 /** Parse flow command, initialize output buffer for subsequent tokens. */
6536 parse_init(struct context *ctx, const struct token *token,
6537 const char *str, unsigned int len,
6538 void *buf, unsigned int size)
6540 struct buffer *out = buf;
6542 /* Token name must match. */
6543 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
6545 /* Nothing else to do if there is no buffer. */
6548 /* Make sure buffer is large enough. */
6549 if (size < sizeof(*out))
6551 /* Initialize buffer. */
6552 memset(out, 0x00, sizeof(*out));
6553 memset((uint8_t *)out + sizeof(*out), 0x22, size - sizeof(*out));
6556 ctx->objmask = NULL;
6560 /** Parse tokens for indirect action commands. */
6562 parse_ia(struct context *ctx, const struct token *token,
6563 const char *str, unsigned int len,
6564 void *buf, unsigned int size)
6566 struct buffer *out = buf;
6568 /* Token name must match. */
6569 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
6571 /* Nothing else to do if there is no buffer. */
6574 if (!out->command) {
6575 if (ctx->curr != INDIRECT_ACTION)
6577 if (sizeof(*out) > size)
6579 out->command = ctx->curr;
6582 ctx->objmask = NULL;
6583 out->args.vc.data = (uint8_t *)out + size;
6586 switch (ctx->curr) {
6587 case INDIRECT_ACTION_CREATE:
6588 case INDIRECT_ACTION_UPDATE:
6589 out->args.vc.actions =
6590 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
6592 out->args.vc.attr.group = UINT32_MAX;
6594 case INDIRECT_ACTION_QUERY:
6595 out->command = ctx->curr;
6598 ctx->objmask = NULL;
6600 case INDIRECT_ACTION_EGRESS:
6601 out->args.vc.attr.egress = 1;
6603 case INDIRECT_ACTION_INGRESS:
6604 out->args.vc.attr.ingress = 1;
6606 case INDIRECT_ACTION_TRANSFER:
6607 out->args.vc.attr.transfer = 1;
6615 /** Parse tokens for indirect action destroy command. */
6617 parse_ia_destroy(struct context *ctx, const struct token *token,
6618 const char *str, unsigned int len,
6619 void *buf, unsigned int size)
6621 struct buffer *out = buf;
6622 uint32_t *action_id;
6624 /* Token name must match. */
6625 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
6627 /* Nothing else to do if there is no buffer. */
6630 if (!out->command || out->command == INDIRECT_ACTION) {
6631 if (ctx->curr != INDIRECT_ACTION_DESTROY)
6633 if (sizeof(*out) > size)
6635 out->command = ctx->curr;
6638 ctx->objmask = NULL;
6639 out->args.ia_destroy.action_id =
6640 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
6644 action_id = out->args.ia_destroy.action_id
6645 + out->args.ia_destroy.action_id_n++;
6646 if ((uint8_t *)action_id > (uint8_t *)out + size)
6649 ctx->object = action_id;
6650 ctx->objmask = NULL;
6654 /** Parse tokens for indirect action commands. */
6656 parse_qia(struct context *ctx, const struct token *token,
6657 const char *str, unsigned int len,
6658 void *buf, unsigned int size)
6660 struct buffer *out = buf;
6662 /* Token name must match. */
6663 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
6665 /* Nothing else to do if there is no buffer. */
6668 if (!out->command) {
6669 if (ctx->curr != QUEUE)
6671 if (sizeof(*out) > size)
6673 out->args.vc.data = (uint8_t *)out + size;
6676 switch (ctx->curr) {
6677 case QUEUE_INDIRECT_ACTION:
6679 case QUEUE_INDIRECT_ACTION_CREATE:
6680 case QUEUE_INDIRECT_ACTION_UPDATE:
6681 out->args.vc.actions =
6682 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
6684 out->args.vc.attr.group = UINT32_MAX;
6685 out->command = ctx->curr;
6688 ctx->objmask = NULL;
6690 case QUEUE_INDIRECT_ACTION_EGRESS:
6691 out->args.vc.attr.egress = 1;
6693 case QUEUE_INDIRECT_ACTION_INGRESS:
6694 out->args.vc.attr.ingress = 1;
6696 case QUEUE_INDIRECT_ACTION_TRANSFER:
6697 out->args.vc.attr.transfer = 1;
6699 case QUEUE_INDIRECT_ACTION_CREATE_POSTPONE:
6706 /** Parse tokens for indirect action destroy command. */
6708 parse_qia_destroy(struct context *ctx, const struct token *token,
6709 const char *str, unsigned int len,
6710 void *buf, unsigned int size)
6712 struct buffer *out = buf;
6713 uint32_t *action_id;
6715 /* Token name must match. */
6716 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
6718 /* Nothing else to do if there is no buffer. */
6721 if (!out->command || out->command == QUEUE) {
6722 if (ctx->curr != QUEUE_INDIRECT_ACTION_DESTROY)
6724 if (sizeof(*out) > size)
6726 out->command = ctx->curr;
6729 ctx->objmask = NULL;
6730 out->args.ia_destroy.action_id =
6731 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
6735 switch (ctx->curr) {
6736 case QUEUE_INDIRECT_ACTION:
6737 out->command = ctx->curr;
6740 ctx->objmask = NULL;
6742 case QUEUE_INDIRECT_ACTION_DESTROY_ID:
6743 action_id = out->args.ia_destroy.action_id
6744 + out->args.ia_destroy.action_id_n++;
6745 if ((uint8_t *)action_id > (uint8_t *)out + size)
6748 ctx->object = action_id;
6749 ctx->objmask = NULL;
6751 case QUEUE_INDIRECT_ACTION_DESTROY_POSTPONE:
6758 /** Parse tokens for meter policy action commands. */
6760 parse_mp(struct context *ctx, const struct token *token,
6761 const char *str, unsigned int len,
6762 void *buf, unsigned int size)
6764 struct buffer *out = buf;
6766 /* Token name must match. */
6767 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
6769 /* Nothing else to do if there is no buffer. */
6772 if (!out->command) {
6773 if (ctx->curr != ITEM_POL_POLICY)
6775 if (sizeof(*out) > size)
6777 out->command = ctx->curr;
6780 ctx->objmask = NULL;
6781 out->args.vc.data = (uint8_t *)out + size;
6784 switch (ctx->curr) {
6786 out->args.vc.actions =
6787 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
6789 out->command = ctx->curr;
6792 ctx->objmask = NULL;
6799 /** Parse tokens for validate/create commands. */
6801 parse_vc(struct context *ctx, const struct token *token,
6802 const char *str, unsigned int len,
6803 void *buf, unsigned int size)
6805 struct buffer *out = buf;
6809 /* Token name must match. */
6810 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
6812 /* Nothing else to do if there is no buffer. */
6815 if (!out->command) {
6816 if (ctx->curr != VALIDATE && ctx->curr != CREATE &&
6817 ctx->curr != PATTERN_TEMPLATE_CREATE &&
6818 ctx->curr != ACTIONS_TEMPLATE_CREATE)
6820 if (sizeof(*out) > size)
6822 out->command = ctx->curr;
6825 ctx->objmask = NULL;
6826 out->args.vc.data = (uint8_t *)out + size;
6830 switch (ctx->curr) {
6832 ctx->object = &out->args.vc.attr;
6835 case VC_TUNNEL_MATCH:
6836 ctx->object = &out->args.vc.tunnel_ops;
6839 ctx->objmask = NULL;
6840 switch (ctx->curr) {
6845 out->args.vc.tunnel_ops.enabled = 1;
6846 out->args.vc.tunnel_ops.actions = 1;
6848 case VC_TUNNEL_MATCH:
6849 out->args.vc.tunnel_ops.enabled = 1;
6850 out->args.vc.tunnel_ops.items = 1;
6853 out->args.vc.attr.ingress = 1;
6856 out->args.vc.attr.egress = 1;
6859 out->args.vc.attr.transfer = 1;
6862 out->args.vc.pattern =
6863 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
6865 ctx->object = out->args.vc.pattern;
6866 ctx->objmask = NULL;
6869 if ((out->command == VALIDATE || out->command == CREATE) &&
6872 if (out->command == PATTERN_TEMPLATE_CREATE &&
6877 out->args.vc.actions =
6878 (void *)RTE_ALIGN_CEIL((uintptr_t)
6879 (out->args.vc.pattern +
6880 out->args.vc.pattern_n),
6882 ctx->object = out->args.vc.actions;
6883 ctx->objmask = NULL;
6890 if (!out->args.vc.actions) {
6891 const struct parse_item_priv *priv = token->priv;
6892 struct rte_flow_item *item =
6893 out->args.vc.pattern + out->args.vc.pattern_n;
6895 data_size = priv->size * 3; /* spec, last, mask */
6896 data = (void *)RTE_ALIGN_FLOOR((uintptr_t)
6897 (out->args.vc.data - data_size),
6899 if ((uint8_t *)item + sizeof(*item) > data)
6901 *item = (struct rte_flow_item){
6904 ++out->args.vc.pattern_n;
6906 ctx->objmask = NULL;
6908 const struct parse_action_priv *priv = token->priv;
6909 struct rte_flow_action *action =
6910 out->args.vc.actions + out->args.vc.actions_n;
6912 data_size = priv->size; /* configuration */
6913 data = (void *)RTE_ALIGN_FLOOR((uintptr_t)
6914 (out->args.vc.data - data_size),
6916 if ((uint8_t *)action + sizeof(*action) > data)
6918 *action = (struct rte_flow_action){
6920 .conf = data_size ? data : NULL,
6922 ++out->args.vc.actions_n;
6923 ctx->object = action;
6924 ctx->objmask = NULL;
6926 memset(data, 0, data_size);
6927 out->args.vc.data = data;
6928 ctx->objdata = data_size;
6932 /** Parse pattern item parameter type. */
6934 parse_vc_spec(struct context *ctx, const struct token *token,
6935 const char *str, unsigned int len,
6936 void *buf, unsigned int size)
6938 struct buffer *out = buf;
6939 struct rte_flow_item *item;
6945 /* Token name must match. */
6946 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
6948 /* Parse parameter types. */
6949 switch (ctx->curr) {
6950 static const enum index prefix[] = NEXT_ENTRY(COMMON_PREFIX);
6956 case ITEM_PARAM_SPEC:
6959 case ITEM_PARAM_LAST:
6962 case ITEM_PARAM_PREFIX:
6963 /* Modify next token to expect a prefix. */
6964 if (ctx->next_num < 2)
6966 ctx->next[ctx->next_num - 2] = prefix;
6968 case ITEM_PARAM_MASK:
6974 /* Nothing else to do if there is no buffer. */
6977 if (!out->args.vc.pattern_n)
6979 item = &out->args.vc.pattern[out->args.vc.pattern_n - 1];
6980 data_size = ctx->objdata / 3; /* spec, last, mask */
6981 /* Point to selected object. */
6982 ctx->object = out->args.vc.data + (data_size * index);
6984 ctx->objmask = out->args.vc.data + (data_size * 2); /* mask */
6985 item->mask = ctx->objmask;
6987 ctx->objmask = NULL;
6988 /* Update relevant item pointer. */
6989 *((const void **[]){ &item->spec, &item->last, &item->mask })[index] =
6994 /** Parse action configuration field. */
6996 parse_vc_conf(struct context *ctx, const struct token *token,
6997 const char *str, unsigned int len,
6998 void *buf, unsigned int size)
7000 struct buffer *out = buf;
7003 /* Token name must match. */
7004 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
7006 /* Nothing else to do if there is no buffer. */
7009 /* Point to selected object. */
7010 ctx->object = out->args.vc.data;
7011 ctx->objmask = NULL;
7015 /** Parse eCPRI common header type field. */
7017 parse_vc_item_ecpri_type(struct context *ctx, const struct token *token,
7018 const char *str, unsigned int len,
7019 void *buf, unsigned int size)
7021 struct rte_flow_item_ecpri *ecpri;
7022 struct rte_flow_item_ecpri *ecpri_mask;
7023 struct rte_flow_item *item;
7026 struct buffer *out = buf;
7027 const struct arg *arg;
7030 /* Token name must match. */
7031 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
7033 switch (ctx->curr) {
7034 case ITEM_ECPRI_COMMON_TYPE_IQ_DATA:
7035 msg_type = RTE_ECPRI_MSG_TYPE_IQ_DATA;
7037 case ITEM_ECPRI_COMMON_TYPE_RTC_CTRL:
7038 msg_type = RTE_ECPRI_MSG_TYPE_RTC_CTRL;
7040 case ITEM_ECPRI_COMMON_TYPE_DLY_MSR:
7041 msg_type = RTE_ECPRI_MSG_TYPE_DLY_MSR;
7048 arg = pop_args(ctx);
7051 ecpri = (struct rte_flow_item_ecpri *)out->args.vc.data;
7052 ecpri->hdr.common.type = msg_type;
7053 data_size = ctx->objdata / 3; /* spec, last, mask */
7054 ecpri_mask = (struct rte_flow_item_ecpri *)(out->args.vc.data +
7056 ecpri_mask->hdr.common.type = 0xFF;
7058 ecpri->hdr.common.u32 = rte_cpu_to_be_32(ecpri->hdr.common.u32);
7059 ecpri_mask->hdr.common.u32 =
7060 rte_cpu_to_be_32(ecpri_mask->hdr.common.u32);
7062 item = &out->args.vc.pattern[out->args.vc.pattern_n - 1];
7064 item->mask = ecpri_mask;
7068 /** Parse L2TPv2 common header type field. */
7070 parse_vc_item_l2tpv2_type(struct context *ctx, const struct token *token,
7071 const char *str, unsigned int len,
7072 void *buf, unsigned int size)
7074 struct rte_flow_item_l2tpv2 *l2tpv2;
7075 struct rte_flow_item_l2tpv2 *l2tpv2_mask;
7076 struct rte_flow_item *item;
7078 uint16_t msg_type = 0;
7079 struct buffer *out = buf;
7080 const struct arg *arg;
7083 /* Token name must match. */
7084 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
7086 switch (ctx->curr) {
7087 case ITEM_L2TPV2_TYPE_DATA:
7088 msg_type |= RTE_L2TPV2_MSG_TYPE_DATA;
7090 case ITEM_L2TPV2_TYPE_DATA_L:
7091 msg_type |= RTE_L2TPV2_MSG_TYPE_DATA_L;
7093 case ITEM_L2TPV2_TYPE_DATA_S:
7094 msg_type |= RTE_L2TPV2_MSG_TYPE_DATA_S;
7096 case ITEM_L2TPV2_TYPE_DATA_O:
7097 msg_type |= RTE_L2TPV2_MSG_TYPE_DATA_O;
7099 case ITEM_L2TPV2_TYPE_DATA_L_S:
7100 msg_type |= RTE_L2TPV2_MSG_TYPE_DATA_L_S;
7102 case ITEM_L2TPV2_TYPE_CTRL:
7103 msg_type |= RTE_L2TPV2_MSG_TYPE_CONTROL;
7110 arg = pop_args(ctx);
7113 l2tpv2 = (struct rte_flow_item_l2tpv2 *)out->args.vc.data;
7114 l2tpv2->hdr.common.flags_version |= msg_type;
7115 data_size = ctx->objdata / 3; /* spec, last, mask */
7116 l2tpv2_mask = (struct rte_flow_item_l2tpv2 *)(out->args.vc.data +
7118 l2tpv2_mask->hdr.common.flags_version = 0xFFFF;
7120 l2tpv2->hdr.common.flags_version =
7121 rte_cpu_to_be_16(l2tpv2->hdr.common.flags_version);
7122 l2tpv2_mask->hdr.common.flags_version =
7123 rte_cpu_to_be_16(l2tpv2_mask->hdr.common.flags_version);
7125 item = &out->args.vc.pattern[out->args.vc.pattern_n - 1];
7126 item->spec = l2tpv2;
7127 item->mask = l2tpv2_mask;
7131 /** Parse meter color action type. */
7133 parse_vc_action_meter_color_type(struct context *ctx, const struct token *token,
7134 const char *str, unsigned int len,
7135 void *buf, unsigned int size)
7137 struct rte_flow_action *action_data;
7138 struct rte_flow_action_meter_color *conf;
7139 enum rte_color color;
7143 /* Token name must match. */
7144 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
7146 switch (ctx->curr) {
7147 case ACTION_METER_COLOR_GREEN:
7148 color = RTE_COLOR_GREEN;
7150 case ACTION_METER_COLOR_YELLOW:
7151 color = RTE_COLOR_YELLOW;
7153 case ACTION_METER_COLOR_RED:
7154 color = RTE_COLOR_RED;
7162 action_data = ctx->object;
7163 conf = (struct rte_flow_action_meter_color *)
7164 (uintptr_t)(action_data->conf);
7165 conf->color = color;
7169 /** Parse RSS action. */
7171 parse_vc_action_rss(struct context *ctx, const struct token *token,
7172 const char *str, unsigned int len,
7173 void *buf, unsigned int size)
7175 struct buffer *out = buf;
7176 struct rte_flow_action *action;
7177 struct action_rss_data *action_rss_data;
7181 ret = parse_vc(ctx, token, str, len, buf, size);
7184 /* Nothing else to do if there is no buffer. */
7187 if (!out->args.vc.actions_n)
7189 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
7190 /* Point to selected object. */
7191 ctx->object = out->args.vc.data;
7192 ctx->objmask = NULL;
7193 /* Set up default configuration. */
7194 action_rss_data = ctx->object;
7195 *action_rss_data = (struct action_rss_data){
7196 .conf = (struct rte_flow_action_rss){
7197 .func = RTE_ETH_HASH_FUNCTION_DEFAULT,
7201 .queue_num = RTE_MIN(nb_rxq, ACTION_RSS_QUEUE_NUM),
7203 .queue = action_rss_data->queue,
7207 for (i = 0; i < action_rss_data->conf.queue_num; ++i)
7208 action_rss_data->queue[i] = i;
7209 action->conf = &action_rss_data->conf;
7214 * Parse func field for RSS action.
7216 * The RTE_ETH_HASH_FUNCTION_* value to assign is derived from the
7217 * ACTION_RSS_FUNC_* index that called this function.
7220 parse_vc_action_rss_func(struct context *ctx, const struct token *token,
7221 const char *str, unsigned int len,
7222 void *buf, unsigned int size)
7224 struct action_rss_data *action_rss_data;
7225 enum rte_eth_hash_function func;
7229 /* Token name must match. */
7230 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
7232 switch (ctx->curr) {
7233 case ACTION_RSS_FUNC_DEFAULT:
7234 func = RTE_ETH_HASH_FUNCTION_DEFAULT;
7236 case ACTION_RSS_FUNC_TOEPLITZ:
7237 func = RTE_ETH_HASH_FUNCTION_TOEPLITZ;
7239 case ACTION_RSS_FUNC_SIMPLE_XOR:
7240 func = RTE_ETH_HASH_FUNCTION_SIMPLE_XOR;
7242 case ACTION_RSS_FUNC_SYMMETRIC_TOEPLITZ:
7243 func = RTE_ETH_HASH_FUNCTION_SYMMETRIC_TOEPLITZ;
7250 action_rss_data = ctx->object;
7251 action_rss_data->conf.func = func;
7256 * Parse type field for RSS action.
7258 * Valid tokens are type field names and the "end" token.
7261 parse_vc_action_rss_type(struct context *ctx, const struct token *token,
7262 const char *str, unsigned int len,
7263 void *buf, unsigned int size)
7265 static const enum index next[] = NEXT_ENTRY(ACTION_RSS_TYPE);
7266 struct action_rss_data *action_rss_data;
7272 if (ctx->curr != ACTION_RSS_TYPE)
7274 if (!(ctx->objdata >> 16) && ctx->object) {
7275 action_rss_data = ctx->object;
7276 action_rss_data->conf.types = 0;
7278 if (!strcmp_partial("end", str, len)) {
7279 ctx->objdata &= 0xffff;
7282 for (i = 0; rss_type_table[i].str; ++i)
7283 if (!strcmp_partial(rss_type_table[i].str, str, len))
7285 if (!rss_type_table[i].str)
7287 ctx->objdata = 1 << 16 | (ctx->objdata & 0xffff);
7289 if (ctx->next_num == RTE_DIM(ctx->next))
7291 ctx->next[ctx->next_num++] = next;
7294 action_rss_data = ctx->object;
7295 action_rss_data->conf.types |= rss_type_table[i].rss_type;
7300 * Parse queue field for RSS action.
7302 * Valid tokens are queue indices and the "end" token.
7305 parse_vc_action_rss_queue(struct context *ctx, const struct token *token,
7306 const char *str, unsigned int len,
7307 void *buf, unsigned int size)
7309 static const enum index next[] = NEXT_ENTRY(ACTION_RSS_QUEUE);
7310 struct action_rss_data *action_rss_data;
7311 const struct arg *arg;
7318 if (ctx->curr != ACTION_RSS_QUEUE)
7320 i = ctx->objdata >> 16;
7321 if (!strcmp_partial("end", str, len)) {
7322 ctx->objdata &= 0xffff;
7325 if (i >= ACTION_RSS_QUEUE_NUM)
7327 arg = ARGS_ENTRY_ARB(offsetof(struct action_rss_data, queue) +
7328 i * sizeof(action_rss_data->queue[i]),
7329 sizeof(action_rss_data->queue[i]));
7330 if (push_args(ctx, arg))
7332 ret = parse_int(ctx, token, str, len, NULL, 0);
7338 ctx->objdata = i << 16 | (ctx->objdata & 0xffff);
7340 if (ctx->next_num == RTE_DIM(ctx->next))
7342 ctx->next[ctx->next_num++] = next;
7346 action_rss_data = ctx->object;
7347 action_rss_data->conf.queue_num = i;
7348 action_rss_data->conf.queue = i ? action_rss_data->queue : NULL;
7352 /** Setup VXLAN encap configuration. */
7354 parse_setup_vxlan_encap_data(struct action_vxlan_encap_data *action_vxlan_encap_data)
7356 /* Set up default configuration. */
7357 *action_vxlan_encap_data = (struct action_vxlan_encap_data){
7358 .conf = (struct rte_flow_action_vxlan_encap){
7359 .definition = action_vxlan_encap_data->items,
7363 .type = RTE_FLOW_ITEM_TYPE_ETH,
7364 .spec = &action_vxlan_encap_data->item_eth,
7365 .mask = &rte_flow_item_eth_mask,
7368 .type = RTE_FLOW_ITEM_TYPE_VLAN,
7369 .spec = &action_vxlan_encap_data->item_vlan,
7370 .mask = &rte_flow_item_vlan_mask,
7373 .type = RTE_FLOW_ITEM_TYPE_IPV4,
7374 .spec = &action_vxlan_encap_data->item_ipv4,
7375 .mask = &rte_flow_item_ipv4_mask,
7378 .type = RTE_FLOW_ITEM_TYPE_UDP,
7379 .spec = &action_vxlan_encap_data->item_udp,
7380 .mask = &rte_flow_item_udp_mask,
7383 .type = RTE_FLOW_ITEM_TYPE_VXLAN,
7384 .spec = &action_vxlan_encap_data->item_vxlan,
7385 .mask = &rte_flow_item_vxlan_mask,
7388 .type = RTE_FLOW_ITEM_TYPE_END,
7393 .tci = vxlan_encap_conf.vlan_tci,
7397 .src_addr = vxlan_encap_conf.ipv4_src,
7398 .dst_addr = vxlan_encap_conf.ipv4_dst,
7401 .src_port = vxlan_encap_conf.udp_src,
7402 .dst_port = vxlan_encap_conf.udp_dst,
7404 .item_vxlan.flags = 0,
7406 memcpy(action_vxlan_encap_data->item_eth.dst.addr_bytes,
7407 vxlan_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
7408 memcpy(action_vxlan_encap_data->item_eth.src.addr_bytes,
7409 vxlan_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
7410 if (!vxlan_encap_conf.select_ipv4) {
7411 memcpy(&action_vxlan_encap_data->item_ipv6.hdr.src_addr,
7412 &vxlan_encap_conf.ipv6_src,
7413 sizeof(vxlan_encap_conf.ipv6_src));
7414 memcpy(&action_vxlan_encap_data->item_ipv6.hdr.dst_addr,
7415 &vxlan_encap_conf.ipv6_dst,
7416 sizeof(vxlan_encap_conf.ipv6_dst));
7417 action_vxlan_encap_data->items[2] = (struct rte_flow_item){
7418 .type = RTE_FLOW_ITEM_TYPE_IPV6,
7419 .spec = &action_vxlan_encap_data->item_ipv6,
7420 .mask = &rte_flow_item_ipv6_mask,
7423 if (!vxlan_encap_conf.select_vlan)
7424 action_vxlan_encap_data->items[1].type =
7425 RTE_FLOW_ITEM_TYPE_VOID;
7426 if (vxlan_encap_conf.select_tos_ttl) {
7427 if (vxlan_encap_conf.select_ipv4) {
7428 static struct rte_flow_item_ipv4 ipv4_mask_tos;
7430 memcpy(&ipv4_mask_tos, &rte_flow_item_ipv4_mask,
7431 sizeof(ipv4_mask_tos));
7432 ipv4_mask_tos.hdr.type_of_service = 0xff;
7433 ipv4_mask_tos.hdr.time_to_live = 0xff;
7434 action_vxlan_encap_data->item_ipv4.hdr.type_of_service =
7435 vxlan_encap_conf.ip_tos;
7436 action_vxlan_encap_data->item_ipv4.hdr.time_to_live =
7437 vxlan_encap_conf.ip_ttl;
7438 action_vxlan_encap_data->items[2].mask =
7441 static struct rte_flow_item_ipv6 ipv6_mask_tos;
7443 memcpy(&ipv6_mask_tos, &rte_flow_item_ipv6_mask,
7444 sizeof(ipv6_mask_tos));
7445 ipv6_mask_tos.hdr.vtc_flow |=
7446 RTE_BE32(0xfful << RTE_IPV6_HDR_TC_SHIFT);
7447 ipv6_mask_tos.hdr.hop_limits = 0xff;
7448 action_vxlan_encap_data->item_ipv6.hdr.vtc_flow |=
7450 ((uint32_t)vxlan_encap_conf.ip_tos <<
7451 RTE_IPV6_HDR_TC_SHIFT);
7452 action_vxlan_encap_data->item_ipv6.hdr.hop_limits =
7453 vxlan_encap_conf.ip_ttl;
7454 action_vxlan_encap_data->items[2].mask =
7458 memcpy(action_vxlan_encap_data->item_vxlan.vni, vxlan_encap_conf.vni,
7459 RTE_DIM(vxlan_encap_conf.vni));
7463 /** Parse VXLAN encap action. */
7465 parse_vc_action_vxlan_encap(struct context *ctx, const struct token *token,
7466 const char *str, unsigned int len,
7467 void *buf, unsigned int size)
7469 struct buffer *out = buf;
7470 struct rte_flow_action *action;
7471 struct action_vxlan_encap_data *action_vxlan_encap_data;
7474 ret = parse_vc(ctx, token, str, len, buf, size);
7477 /* Nothing else to do if there is no buffer. */
7480 if (!out->args.vc.actions_n)
7482 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
7483 /* Point to selected object. */
7484 ctx->object = out->args.vc.data;
7485 ctx->objmask = NULL;
7486 action_vxlan_encap_data = ctx->object;
7487 parse_setup_vxlan_encap_data(action_vxlan_encap_data);
7488 action->conf = &action_vxlan_encap_data->conf;
7492 /** Setup NVGRE encap configuration. */
7494 parse_setup_nvgre_encap_data(struct action_nvgre_encap_data *action_nvgre_encap_data)
7496 /* Set up default configuration. */
7497 *action_nvgre_encap_data = (struct action_nvgre_encap_data){
7498 .conf = (struct rte_flow_action_nvgre_encap){
7499 .definition = action_nvgre_encap_data->items,
7503 .type = RTE_FLOW_ITEM_TYPE_ETH,
7504 .spec = &action_nvgre_encap_data->item_eth,
7505 .mask = &rte_flow_item_eth_mask,
7508 .type = RTE_FLOW_ITEM_TYPE_VLAN,
7509 .spec = &action_nvgre_encap_data->item_vlan,
7510 .mask = &rte_flow_item_vlan_mask,
7513 .type = RTE_FLOW_ITEM_TYPE_IPV4,
7514 .spec = &action_nvgre_encap_data->item_ipv4,
7515 .mask = &rte_flow_item_ipv4_mask,
7518 .type = RTE_FLOW_ITEM_TYPE_NVGRE,
7519 .spec = &action_nvgre_encap_data->item_nvgre,
7520 .mask = &rte_flow_item_nvgre_mask,
7523 .type = RTE_FLOW_ITEM_TYPE_END,
7528 .tci = nvgre_encap_conf.vlan_tci,
7532 .src_addr = nvgre_encap_conf.ipv4_src,
7533 .dst_addr = nvgre_encap_conf.ipv4_dst,
7535 .item_nvgre.c_k_s_rsvd0_ver = RTE_BE16(0x2000),
7536 .item_nvgre.protocol = RTE_BE16(RTE_ETHER_TYPE_TEB),
7537 .item_nvgre.flow_id = 0,
7539 memcpy(action_nvgre_encap_data->item_eth.dst.addr_bytes,
7540 nvgre_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
7541 memcpy(action_nvgre_encap_data->item_eth.src.addr_bytes,
7542 nvgre_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
7543 if (!nvgre_encap_conf.select_ipv4) {
7544 memcpy(&action_nvgre_encap_data->item_ipv6.hdr.src_addr,
7545 &nvgre_encap_conf.ipv6_src,
7546 sizeof(nvgre_encap_conf.ipv6_src));
7547 memcpy(&action_nvgre_encap_data->item_ipv6.hdr.dst_addr,
7548 &nvgre_encap_conf.ipv6_dst,
7549 sizeof(nvgre_encap_conf.ipv6_dst));
7550 action_nvgre_encap_data->items[2] = (struct rte_flow_item){
7551 .type = RTE_FLOW_ITEM_TYPE_IPV6,
7552 .spec = &action_nvgre_encap_data->item_ipv6,
7553 .mask = &rte_flow_item_ipv6_mask,
7556 if (!nvgre_encap_conf.select_vlan)
7557 action_nvgre_encap_data->items[1].type =
7558 RTE_FLOW_ITEM_TYPE_VOID;
7559 memcpy(action_nvgre_encap_data->item_nvgre.tni, nvgre_encap_conf.tni,
7560 RTE_DIM(nvgre_encap_conf.tni));
7564 /** Parse NVGRE encap action. */
7566 parse_vc_action_nvgre_encap(struct context *ctx, const struct token *token,
7567 const char *str, unsigned int len,
7568 void *buf, unsigned int size)
7570 struct buffer *out = buf;
7571 struct rte_flow_action *action;
7572 struct action_nvgre_encap_data *action_nvgre_encap_data;
7575 ret = parse_vc(ctx, token, str, len, buf, size);
7578 /* Nothing else to do if there is no buffer. */
7581 if (!out->args.vc.actions_n)
7583 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
7584 /* Point to selected object. */
7585 ctx->object = out->args.vc.data;
7586 ctx->objmask = NULL;
7587 action_nvgre_encap_data = ctx->object;
7588 parse_setup_nvgre_encap_data(action_nvgre_encap_data);
7589 action->conf = &action_nvgre_encap_data->conf;
7593 /** Parse l2 encap action. */
7595 parse_vc_action_l2_encap(struct context *ctx, const struct token *token,
7596 const char *str, unsigned int len,
7597 void *buf, unsigned int size)
7599 struct buffer *out = buf;
7600 struct rte_flow_action *action;
7601 struct action_raw_encap_data *action_encap_data;
7602 struct rte_flow_item_eth eth = { .type = 0, };
7603 struct rte_flow_item_vlan vlan = {
7604 .tci = mplsoudp_encap_conf.vlan_tci,
7610 ret = parse_vc(ctx, token, str, len, buf, size);
7613 /* Nothing else to do if there is no buffer. */
7616 if (!out->args.vc.actions_n)
7618 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
7619 /* Point to selected object. */
7620 ctx->object = out->args.vc.data;
7621 ctx->objmask = NULL;
7622 /* Copy the headers to the buffer. */
7623 action_encap_data = ctx->object;
7624 *action_encap_data = (struct action_raw_encap_data) {
7625 .conf = (struct rte_flow_action_raw_encap){
7626 .data = action_encap_data->data,
7630 header = action_encap_data->data;
7631 if (l2_encap_conf.select_vlan)
7632 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
7633 else if (l2_encap_conf.select_ipv4)
7634 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
7636 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
7637 memcpy(eth.dst.addr_bytes,
7638 l2_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
7639 memcpy(eth.src.addr_bytes,
7640 l2_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
7641 memcpy(header, ð, sizeof(eth));
7642 header += sizeof(eth);
7643 if (l2_encap_conf.select_vlan) {
7644 if (l2_encap_conf.select_ipv4)
7645 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
7647 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
7648 memcpy(header, &vlan, sizeof(vlan));
7649 header += sizeof(vlan);
7651 action_encap_data->conf.size = header -
7652 action_encap_data->data;
7653 action->conf = &action_encap_data->conf;
7657 /** Parse l2 decap action. */
7659 parse_vc_action_l2_decap(struct context *ctx, const struct token *token,
7660 const char *str, unsigned int len,
7661 void *buf, unsigned int size)
7663 struct buffer *out = buf;
7664 struct rte_flow_action *action;
7665 struct action_raw_decap_data *action_decap_data;
7666 struct rte_flow_item_eth eth = { .type = 0, };
7667 struct rte_flow_item_vlan vlan = {
7668 .tci = mplsoudp_encap_conf.vlan_tci,
7674 ret = parse_vc(ctx, token, str, len, buf, size);
7677 /* Nothing else to do if there is no buffer. */
7680 if (!out->args.vc.actions_n)
7682 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
7683 /* Point to selected object. */
7684 ctx->object = out->args.vc.data;
7685 ctx->objmask = NULL;
7686 /* Copy the headers to the buffer. */
7687 action_decap_data = ctx->object;
7688 *action_decap_data = (struct action_raw_decap_data) {
7689 .conf = (struct rte_flow_action_raw_decap){
7690 .data = action_decap_data->data,
7694 header = action_decap_data->data;
7695 if (l2_decap_conf.select_vlan)
7696 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
7697 memcpy(header, ð, sizeof(eth));
7698 header += sizeof(eth);
7699 if (l2_decap_conf.select_vlan) {
7700 memcpy(header, &vlan, sizeof(vlan));
7701 header += sizeof(vlan);
7703 action_decap_data->conf.size = header -
7704 action_decap_data->data;
7705 action->conf = &action_decap_data->conf;
7709 #define ETHER_TYPE_MPLS_UNICAST 0x8847
7711 /** Parse MPLSOGRE encap action. */
7713 parse_vc_action_mplsogre_encap(struct context *ctx, const struct token *token,
7714 const char *str, unsigned int len,
7715 void *buf, unsigned int size)
7717 struct buffer *out = buf;
7718 struct rte_flow_action *action;
7719 struct action_raw_encap_data *action_encap_data;
7720 struct rte_flow_item_eth eth = { .type = 0, };
7721 struct rte_flow_item_vlan vlan = {
7722 .tci = mplsogre_encap_conf.vlan_tci,
7725 struct rte_flow_item_ipv4 ipv4 = {
7727 .src_addr = mplsogre_encap_conf.ipv4_src,
7728 .dst_addr = mplsogre_encap_conf.ipv4_dst,
7729 .next_proto_id = IPPROTO_GRE,
7730 .version_ihl = RTE_IPV4_VHL_DEF,
7731 .time_to_live = IPDEFTTL,
7734 struct rte_flow_item_ipv6 ipv6 = {
7736 .proto = IPPROTO_GRE,
7737 .hop_limits = IPDEFTTL,
7740 struct rte_flow_item_gre gre = {
7741 .protocol = rte_cpu_to_be_16(ETHER_TYPE_MPLS_UNICAST),
7743 struct rte_flow_item_mpls mpls = {
7749 ret = parse_vc(ctx, token, str, len, buf, size);
7752 /* Nothing else to do if there is no buffer. */
7755 if (!out->args.vc.actions_n)
7757 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
7758 /* Point to selected object. */
7759 ctx->object = out->args.vc.data;
7760 ctx->objmask = NULL;
7761 /* Copy the headers to the buffer. */
7762 action_encap_data = ctx->object;
7763 *action_encap_data = (struct action_raw_encap_data) {
7764 .conf = (struct rte_flow_action_raw_encap){
7765 .data = action_encap_data->data,
7770 header = action_encap_data->data;
7771 if (mplsogre_encap_conf.select_vlan)
7772 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
7773 else if (mplsogre_encap_conf.select_ipv4)
7774 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
7776 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
7777 memcpy(eth.dst.addr_bytes,
7778 mplsogre_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
7779 memcpy(eth.src.addr_bytes,
7780 mplsogre_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
7781 memcpy(header, ð, sizeof(eth));
7782 header += sizeof(eth);
7783 if (mplsogre_encap_conf.select_vlan) {
7784 if (mplsogre_encap_conf.select_ipv4)
7785 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
7787 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
7788 memcpy(header, &vlan, sizeof(vlan));
7789 header += sizeof(vlan);
7791 if (mplsogre_encap_conf.select_ipv4) {
7792 memcpy(header, &ipv4, sizeof(ipv4));
7793 header += sizeof(ipv4);
7795 memcpy(&ipv6.hdr.src_addr,
7796 &mplsogre_encap_conf.ipv6_src,
7797 sizeof(mplsogre_encap_conf.ipv6_src));
7798 memcpy(&ipv6.hdr.dst_addr,
7799 &mplsogre_encap_conf.ipv6_dst,
7800 sizeof(mplsogre_encap_conf.ipv6_dst));
7801 memcpy(header, &ipv6, sizeof(ipv6));
7802 header += sizeof(ipv6);
7804 memcpy(header, &gre, sizeof(gre));
7805 header += sizeof(gre);
7806 memcpy(mpls.label_tc_s, mplsogre_encap_conf.label,
7807 RTE_DIM(mplsogre_encap_conf.label));
7808 mpls.label_tc_s[2] |= 0x1;
7809 memcpy(header, &mpls, sizeof(mpls));
7810 header += sizeof(mpls);
7811 action_encap_data->conf.size = header -
7812 action_encap_data->data;
7813 action->conf = &action_encap_data->conf;
7817 /** Parse MPLSOGRE decap action. */
7819 parse_vc_action_mplsogre_decap(struct context *ctx, const struct token *token,
7820 const char *str, unsigned int len,
7821 void *buf, unsigned int size)
7823 struct buffer *out = buf;
7824 struct rte_flow_action *action;
7825 struct action_raw_decap_data *action_decap_data;
7826 struct rte_flow_item_eth eth = { .type = 0, };
7827 struct rte_flow_item_vlan vlan = {.tci = 0};
7828 struct rte_flow_item_ipv4 ipv4 = {
7830 .next_proto_id = IPPROTO_GRE,
7833 struct rte_flow_item_ipv6 ipv6 = {
7835 .proto = IPPROTO_GRE,
7838 struct rte_flow_item_gre gre = {
7839 .protocol = rte_cpu_to_be_16(ETHER_TYPE_MPLS_UNICAST),
7841 struct rte_flow_item_mpls mpls;
7845 ret = parse_vc(ctx, token, str, len, buf, size);
7848 /* Nothing else to do if there is no buffer. */
7851 if (!out->args.vc.actions_n)
7853 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
7854 /* Point to selected object. */
7855 ctx->object = out->args.vc.data;
7856 ctx->objmask = NULL;
7857 /* Copy the headers to the buffer. */
7858 action_decap_data = ctx->object;
7859 *action_decap_data = (struct action_raw_decap_data) {
7860 .conf = (struct rte_flow_action_raw_decap){
7861 .data = action_decap_data->data,
7865 header = action_decap_data->data;
7866 if (mplsogre_decap_conf.select_vlan)
7867 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
7868 else if (mplsogre_encap_conf.select_ipv4)
7869 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
7871 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
7872 memcpy(eth.dst.addr_bytes,
7873 mplsogre_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
7874 memcpy(eth.src.addr_bytes,
7875 mplsogre_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
7876 memcpy(header, ð, sizeof(eth));
7877 header += sizeof(eth);
7878 if (mplsogre_encap_conf.select_vlan) {
7879 if (mplsogre_encap_conf.select_ipv4)
7880 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
7882 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
7883 memcpy(header, &vlan, sizeof(vlan));
7884 header += sizeof(vlan);
7886 if (mplsogre_encap_conf.select_ipv4) {
7887 memcpy(header, &ipv4, sizeof(ipv4));
7888 header += sizeof(ipv4);
7890 memcpy(header, &ipv6, sizeof(ipv6));
7891 header += sizeof(ipv6);
7893 memcpy(header, &gre, sizeof(gre));
7894 header += sizeof(gre);
7895 memset(&mpls, 0, sizeof(mpls));
7896 memcpy(header, &mpls, sizeof(mpls));
7897 header += sizeof(mpls);
7898 action_decap_data->conf.size = header -
7899 action_decap_data->data;
7900 action->conf = &action_decap_data->conf;
7904 /** Parse MPLSOUDP encap action. */
7906 parse_vc_action_mplsoudp_encap(struct context *ctx, const struct token *token,
7907 const char *str, unsigned int len,
7908 void *buf, unsigned int size)
7910 struct buffer *out = buf;
7911 struct rte_flow_action *action;
7912 struct action_raw_encap_data *action_encap_data;
7913 struct rte_flow_item_eth eth = { .type = 0, };
7914 struct rte_flow_item_vlan vlan = {
7915 .tci = mplsoudp_encap_conf.vlan_tci,
7918 struct rte_flow_item_ipv4 ipv4 = {
7920 .src_addr = mplsoudp_encap_conf.ipv4_src,
7921 .dst_addr = mplsoudp_encap_conf.ipv4_dst,
7922 .next_proto_id = IPPROTO_UDP,
7923 .version_ihl = RTE_IPV4_VHL_DEF,
7924 .time_to_live = IPDEFTTL,
7927 struct rte_flow_item_ipv6 ipv6 = {
7929 .proto = IPPROTO_UDP,
7930 .hop_limits = IPDEFTTL,
7933 struct rte_flow_item_udp udp = {
7935 .src_port = mplsoudp_encap_conf.udp_src,
7936 .dst_port = mplsoudp_encap_conf.udp_dst,
7939 struct rte_flow_item_mpls mpls;
7943 ret = parse_vc(ctx, token, str, len, buf, size);
7946 /* Nothing else to do if there is no buffer. */
7949 if (!out->args.vc.actions_n)
7951 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
7952 /* Point to selected object. */
7953 ctx->object = out->args.vc.data;
7954 ctx->objmask = NULL;
7955 /* Copy the headers to the buffer. */
7956 action_encap_data = ctx->object;
7957 *action_encap_data = (struct action_raw_encap_data) {
7958 .conf = (struct rte_flow_action_raw_encap){
7959 .data = action_encap_data->data,
7964 header = action_encap_data->data;
7965 if (mplsoudp_encap_conf.select_vlan)
7966 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
7967 else if (mplsoudp_encap_conf.select_ipv4)
7968 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
7970 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
7971 memcpy(eth.dst.addr_bytes,
7972 mplsoudp_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
7973 memcpy(eth.src.addr_bytes,
7974 mplsoudp_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
7975 memcpy(header, ð, sizeof(eth));
7976 header += sizeof(eth);
7977 if (mplsoudp_encap_conf.select_vlan) {
7978 if (mplsoudp_encap_conf.select_ipv4)
7979 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
7981 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
7982 memcpy(header, &vlan, sizeof(vlan));
7983 header += sizeof(vlan);
7985 if (mplsoudp_encap_conf.select_ipv4) {
7986 memcpy(header, &ipv4, sizeof(ipv4));
7987 header += sizeof(ipv4);
7989 memcpy(&ipv6.hdr.src_addr,
7990 &mplsoudp_encap_conf.ipv6_src,
7991 sizeof(mplsoudp_encap_conf.ipv6_src));
7992 memcpy(&ipv6.hdr.dst_addr,
7993 &mplsoudp_encap_conf.ipv6_dst,
7994 sizeof(mplsoudp_encap_conf.ipv6_dst));
7995 memcpy(header, &ipv6, sizeof(ipv6));
7996 header += sizeof(ipv6);
7998 memcpy(header, &udp, sizeof(udp));
7999 header += sizeof(udp);
8000 memcpy(mpls.label_tc_s, mplsoudp_encap_conf.label,
8001 RTE_DIM(mplsoudp_encap_conf.label));
8002 mpls.label_tc_s[2] |= 0x1;
8003 memcpy(header, &mpls, sizeof(mpls));
8004 header += sizeof(mpls);
8005 action_encap_data->conf.size = header -
8006 action_encap_data->data;
8007 action->conf = &action_encap_data->conf;
8011 /** Parse MPLSOUDP decap action. */
8013 parse_vc_action_mplsoudp_decap(struct context *ctx, const struct token *token,
8014 const char *str, unsigned int len,
8015 void *buf, unsigned int size)
8017 struct buffer *out = buf;
8018 struct rte_flow_action *action;
8019 struct action_raw_decap_data *action_decap_data;
8020 struct rte_flow_item_eth eth = { .type = 0, };
8021 struct rte_flow_item_vlan vlan = {.tci = 0};
8022 struct rte_flow_item_ipv4 ipv4 = {
8024 .next_proto_id = IPPROTO_UDP,
8027 struct rte_flow_item_ipv6 ipv6 = {
8029 .proto = IPPROTO_UDP,
8032 struct rte_flow_item_udp udp = {
8034 .dst_port = rte_cpu_to_be_16(6635),
8037 struct rte_flow_item_mpls mpls;
8041 ret = parse_vc(ctx, token, str, len, buf, size);
8044 /* Nothing else to do if there is no buffer. */
8047 if (!out->args.vc.actions_n)
8049 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
8050 /* Point to selected object. */
8051 ctx->object = out->args.vc.data;
8052 ctx->objmask = NULL;
8053 /* Copy the headers to the buffer. */
8054 action_decap_data = ctx->object;
8055 *action_decap_data = (struct action_raw_decap_data) {
8056 .conf = (struct rte_flow_action_raw_decap){
8057 .data = action_decap_data->data,
8061 header = action_decap_data->data;
8062 if (mplsoudp_decap_conf.select_vlan)
8063 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
8064 else if (mplsoudp_encap_conf.select_ipv4)
8065 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
8067 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
8068 memcpy(eth.dst.addr_bytes,
8069 mplsoudp_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
8070 memcpy(eth.src.addr_bytes,
8071 mplsoudp_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
8072 memcpy(header, ð, sizeof(eth));
8073 header += sizeof(eth);
8074 if (mplsoudp_encap_conf.select_vlan) {
8075 if (mplsoudp_encap_conf.select_ipv4)
8076 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
8078 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
8079 memcpy(header, &vlan, sizeof(vlan));
8080 header += sizeof(vlan);
8082 if (mplsoudp_encap_conf.select_ipv4) {
8083 memcpy(header, &ipv4, sizeof(ipv4));
8084 header += sizeof(ipv4);
8086 memcpy(header, &ipv6, sizeof(ipv6));
8087 header += sizeof(ipv6);
8089 memcpy(header, &udp, sizeof(udp));
8090 header += sizeof(udp);
8091 memset(&mpls, 0, sizeof(mpls));
8092 memcpy(header, &mpls, sizeof(mpls));
8093 header += sizeof(mpls);
8094 action_decap_data->conf.size = header -
8095 action_decap_data->data;
8096 action->conf = &action_decap_data->conf;
8101 parse_vc_action_raw_decap_index(struct context *ctx, const struct token *token,
8102 const char *str, unsigned int len, void *buf,
8105 struct action_raw_decap_data *action_raw_decap_data;
8106 struct rte_flow_action *action;
8107 const struct arg *arg;
8108 struct buffer *out = buf;
8112 RTE_SET_USED(token);
8115 arg = ARGS_ENTRY_ARB_BOUNDED
8116 (offsetof(struct action_raw_decap_data, idx),
8117 sizeof(((struct action_raw_decap_data *)0)->idx),
8118 0, RAW_ENCAP_CONFS_MAX_NUM - 1);
8119 if (push_args(ctx, arg))
8121 ret = parse_int(ctx, token, str, len, NULL, 0);
8128 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
8129 action_raw_decap_data = ctx->object;
8130 idx = action_raw_decap_data->idx;
8131 action_raw_decap_data->conf.data = raw_decap_confs[idx].data;
8132 action_raw_decap_data->conf.size = raw_decap_confs[idx].size;
8133 action->conf = &action_raw_decap_data->conf;
8139 parse_vc_action_raw_encap_index(struct context *ctx, const struct token *token,
8140 const char *str, unsigned int len, void *buf,
8143 struct action_raw_encap_data *action_raw_encap_data;
8144 struct rte_flow_action *action;
8145 const struct arg *arg;
8146 struct buffer *out = buf;
8150 RTE_SET_USED(token);
8153 if (ctx->curr != ACTION_RAW_ENCAP_INDEX_VALUE)
8155 arg = ARGS_ENTRY_ARB_BOUNDED
8156 (offsetof(struct action_raw_encap_data, idx),
8157 sizeof(((struct action_raw_encap_data *)0)->idx),
8158 0, RAW_ENCAP_CONFS_MAX_NUM - 1);
8159 if (push_args(ctx, arg))
8161 ret = parse_int(ctx, token, str, len, NULL, 0);
8168 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
8169 action_raw_encap_data = ctx->object;
8170 idx = action_raw_encap_data->idx;
8171 action_raw_encap_data->conf.data = raw_encap_confs[idx].data;
8172 action_raw_encap_data->conf.size = raw_encap_confs[idx].size;
8173 action_raw_encap_data->conf.preserve = NULL;
8174 action->conf = &action_raw_encap_data->conf;
8179 parse_vc_action_raw_encap(struct context *ctx, const struct token *token,
8180 const char *str, unsigned int len, void *buf,
8183 struct buffer *out = buf;
8184 struct rte_flow_action *action;
8185 struct action_raw_encap_data *action_raw_encap_data = NULL;
8188 ret = parse_vc(ctx, token, str, len, buf, size);
8191 /* Nothing else to do if there is no buffer. */
8194 if (!out->args.vc.actions_n)
8196 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
8197 /* Point to selected object. */
8198 ctx->object = out->args.vc.data;
8199 ctx->objmask = NULL;
8200 /* Copy the headers to the buffer. */
8201 action_raw_encap_data = ctx->object;
8202 action_raw_encap_data->conf.data = raw_encap_confs[0].data;
8203 action_raw_encap_data->conf.preserve = NULL;
8204 action_raw_encap_data->conf.size = raw_encap_confs[0].size;
8205 action->conf = &action_raw_encap_data->conf;
8210 parse_vc_action_raw_decap(struct context *ctx, const struct token *token,
8211 const char *str, unsigned int len, void *buf,
8214 struct buffer *out = buf;
8215 struct rte_flow_action *action;
8216 struct action_raw_decap_data *action_raw_decap_data = NULL;
8219 ret = parse_vc(ctx, token, str, len, buf, size);
8222 /* Nothing else to do if there is no buffer. */
8225 if (!out->args.vc.actions_n)
8227 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
8228 /* Point to selected object. */
8229 ctx->object = out->args.vc.data;
8230 ctx->objmask = NULL;
8231 /* Copy the headers to the buffer. */
8232 action_raw_decap_data = ctx->object;
8233 action_raw_decap_data->conf.data = raw_decap_confs[0].data;
8234 action_raw_decap_data->conf.size = raw_decap_confs[0].size;
8235 action->conf = &action_raw_decap_data->conf;
8240 parse_vc_action_set_meta(struct context *ctx, const struct token *token,
8241 const char *str, unsigned int len, void *buf,
8246 ret = parse_vc(ctx, token, str, len, buf, size);
8249 ret = rte_flow_dynf_metadata_register();
8256 parse_vc_action_sample(struct context *ctx, const struct token *token,
8257 const char *str, unsigned int len, void *buf,
8260 struct buffer *out = buf;
8261 struct rte_flow_action *action;
8262 struct action_sample_data *action_sample_data = NULL;
8263 static struct rte_flow_action end_action = {
8264 RTE_FLOW_ACTION_TYPE_END, 0
8268 ret = parse_vc(ctx, token, str, len, buf, size);
8271 /* Nothing else to do if there is no buffer. */
8274 if (!out->args.vc.actions_n)
8276 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
8277 /* Point to selected object. */
8278 ctx->object = out->args.vc.data;
8279 ctx->objmask = NULL;
8280 /* Copy the headers to the buffer. */
8281 action_sample_data = ctx->object;
8282 action_sample_data->conf.actions = &end_action;
8283 action->conf = &action_sample_data->conf;
8288 parse_vc_action_sample_index(struct context *ctx, const struct token *token,
8289 const char *str, unsigned int len, void *buf,
8292 struct action_sample_data *action_sample_data;
8293 struct rte_flow_action *action;
8294 const struct arg *arg;
8295 struct buffer *out = buf;
8299 RTE_SET_USED(token);
8302 if (ctx->curr != ACTION_SAMPLE_INDEX_VALUE)
8304 arg = ARGS_ENTRY_ARB_BOUNDED
8305 (offsetof(struct action_sample_data, idx),
8306 sizeof(((struct action_sample_data *)0)->idx),
8307 0, RAW_SAMPLE_CONFS_MAX_NUM - 1);
8308 if (push_args(ctx, arg))
8310 ret = parse_int(ctx, token, str, len, NULL, 0);
8317 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
8318 action_sample_data = ctx->object;
8319 idx = action_sample_data->idx;
8320 action_sample_data->conf.actions = raw_sample_confs[idx].data;
8321 action->conf = &action_sample_data->conf;
8325 /** Parse operation for modify_field command. */
8327 parse_vc_modify_field_op(struct context *ctx, const struct token *token,
8328 const char *str, unsigned int len, void *buf,
8331 struct rte_flow_action_modify_field *action_modify_field;
8337 if (ctx->curr != ACTION_MODIFY_FIELD_OP_VALUE)
8339 for (i = 0; modify_field_ops[i]; ++i)
8340 if (!strcmp_partial(modify_field_ops[i], str, len))
8342 if (!modify_field_ops[i])
8346 action_modify_field = ctx->object;
8347 action_modify_field->operation = (enum rte_flow_modify_op)i;
8351 /** Parse id for modify_field command. */
8353 parse_vc_modify_field_id(struct context *ctx, const struct token *token,
8354 const char *str, unsigned int len, void *buf,
8357 struct rte_flow_action_modify_field *action_modify_field;
8363 if (ctx->curr != ACTION_MODIFY_FIELD_DST_TYPE_VALUE &&
8364 ctx->curr != ACTION_MODIFY_FIELD_SRC_TYPE_VALUE)
8366 for (i = 0; modify_field_ids[i]; ++i)
8367 if (!strcmp_partial(modify_field_ids[i], str, len))
8369 if (!modify_field_ids[i])
8373 action_modify_field = ctx->object;
8374 if (ctx->curr == ACTION_MODIFY_FIELD_DST_TYPE_VALUE)
8375 action_modify_field->dst.field = (enum rte_flow_field_id)i;
8377 action_modify_field->src.field = (enum rte_flow_field_id)i;
8381 /** Parse the conntrack update, not a rte_flow_action. */
8383 parse_vc_action_conntrack_update(struct context *ctx, const struct token *token,
8384 const char *str, unsigned int len, void *buf,
8387 struct buffer *out = buf;
8388 struct rte_flow_modify_conntrack *ct_modify = NULL;
8391 if (ctx->curr != ACTION_CONNTRACK_UPDATE_CTX &&
8392 ctx->curr != ACTION_CONNTRACK_UPDATE_DIR)
8394 /* Token name must match. */
8395 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8397 /* Nothing else to do if there is no buffer. */
8400 ct_modify = (struct rte_flow_modify_conntrack *)out->args.vc.data;
8401 if (ctx->curr == ACTION_CONNTRACK_UPDATE_DIR) {
8402 ct_modify->new_ct.is_original_dir =
8403 conntrack_context.is_original_dir;
8404 ct_modify->direction = 1;
8408 old_dir = ct_modify->new_ct.is_original_dir;
8409 memcpy(&ct_modify->new_ct, &conntrack_context,
8410 sizeof(conntrack_context));
8411 ct_modify->new_ct.is_original_dir = old_dir;
8412 ct_modify->state = 1;
8417 /** Parse tokens for destroy command. */
8419 parse_destroy(struct context *ctx, const struct token *token,
8420 const char *str, unsigned int len,
8421 void *buf, unsigned int size)
8423 struct buffer *out = buf;
8425 /* Token name must match. */
8426 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8428 /* Nothing else to do if there is no buffer. */
8431 if (!out->command) {
8432 if (ctx->curr != DESTROY)
8434 if (sizeof(*out) > size)
8436 out->command = ctx->curr;
8439 ctx->objmask = NULL;
8440 out->args.destroy.rule =
8441 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8445 if (((uint8_t *)(out->args.destroy.rule + out->args.destroy.rule_n) +
8446 sizeof(*out->args.destroy.rule)) > (uint8_t *)out + size)
8449 ctx->object = out->args.destroy.rule + out->args.destroy.rule_n++;
8450 ctx->objmask = NULL;
8454 /** Parse tokens for flush command. */
8456 parse_flush(struct context *ctx, const struct token *token,
8457 const char *str, unsigned int len,
8458 void *buf, unsigned int size)
8460 struct buffer *out = buf;
8462 /* Token name must match. */
8463 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8465 /* Nothing else to do if there is no buffer. */
8468 if (!out->command) {
8469 if (ctx->curr != FLUSH)
8471 if (sizeof(*out) > size)
8473 out->command = ctx->curr;
8476 ctx->objmask = NULL;
8481 /** Parse tokens for dump command. */
8483 parse_dump(struct context *ctx, const struct token *token,
8484 const char *str, unsigned int len,
8485 void *buf, unsigned int size)
8487 struct buffer *out = buf;
8489 /* Token name must match. */
8490 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8492 /* Nothing else to do if there is no buffer. */
8495 if (!out->command) {
8496 if (ctx->curr != DUMP)
8498 if (sizeof(*out) > size)
8500 out->command = ctx->curr;
8503 ctx->objmask = NULL;
8506 switch (ctx->curr) {
8509 out->args.dump.mode = (ctx->curr == DUMP_ALL) ? true : false;
8510 out->command = ctx->curr;
8513 ctx->objmask = NULL;
8520 /** Parse tokens for query command. */
8522 parse_query(struct context *ctx, const struct token *token,
8523 const char *str, unsigned int len,
8524 void *buf, unsigned int size)
8526 struct buffer *out = buf;
8528 /* Token name must match. */
8529 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8531 /* Nothing else to do if there is no buffer. */
8534 if (!out->command) {
8535 if (ctx->curr != QUERY)
8537 if (sizeof(*out) > size)
8539 out->command = ctx->curr;
8542 ctx->objmask = NULL;
8547 /** Parse action names. */
8549 parse_action(struct context *ctx, const struct token *token,
8550 const char *str, unsigned int len,
8551 void *buf, unsigned int size)
8553 struct buffer *out = buf;
8554 const struct arg *arg = pop_args(ctx);
8558 /* Argument is expected. */
8561 /* Parse action name. */
8562 for (i = 0; next_action[i]; ++i) {
8563 const struct parse_action_priv *priv;
8565 token = &token_list[next_action[i]];
8566 if (strcmp_partial(token->name, str, len))
8572 memcpy((uint8_t *)ctx->object + arg->offset,
8578 push_args(ctx, arg);
8582 /** Parse tokens for list command. */
8584 parse_list(struct context *ctx, const struct token *token,
8585 const char *str, unsigned int len,
8586 void *buf, unsigned int size)
8588 struct buffer *out = buf;
8590 /* Token name must match. */
8591 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8593 /* Nothing else to do if there is no buffer. */
8596 if (!out->command) {
8597 if (ctx->curr != LIST)
8599 if (sizeof(*out) > size)
8601 out->command = ctx->curr;
8604 ctx->objmask = NULL;
8605 out->args.list.group =
8606 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8610 if (((uint8_t *)(out->args.list.group + out->args.list.group_n) +
8611 sizeof(*out->args.list.group)) > (uint8_t *)out + size)
8614 ctx->object = out->args.list.group + out->args.list.group_n++;
8615 ctx->objmask = NULL;
8619 /** Parse tokens for list all aged flows command. */
8621 parse_aged(struct context *ctx, const struct token *token,
8622 const char *str, unsigned int len,
8623 void *buf, unsigned int size)
8625 struct buffer *out = buf;
8627 /* Token name must match. */
8628 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8630 /* Nothing else to do if there is no buffer. */
8633 if (!out->command) {
8634 if (ctx->curr != AGED)
8636 if (sizeof(*out) > size)
8638 out->command = ctx->curr;
8641 ctx->objmask = NULL;
8643 if (ctx->curr == AGED_DESTROY)
8644 out->args.aged.destroy = 1;
8648 /** Parse tokens for isolate command. */
8650 parse_isolate(struct context *ctx, const struct token *token,
8651 const char *str, unsigned int len,
8652 void *buf, unsigned int size)
8654 struct buffer *out = buf;
8656 /* Token name must match. */
8657 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8659 /* Nothing else to do if there is no buffer. */
8662 if (!out->command) {
8663 if (ctx->curr != ISOLATE)
8665 if (sizeof(*out) > size)
8667 out->command = ctx->curr;
8670 ctx->objmask = NULL;
8675 /** Parse tokens for info/configure command. */
8677 parse_configure(struct context *ctx, const struct token *token,
8678 const char *str, unsigned int len,
8679 void *buf, unsigned int size)
8681 struct buffer *out = buf;
8683 /* Token name must match. */
8684 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8686 /* Nothing else to do if there is no buffer. */
8689 if (!out->command) {
8690 if (ctx->curr != INFO && ctx->curr != CONFIGURE)
8692 if (sizeof(*out) > size)
8694 out->command = ctx->curr;
8697 ctx->objmask = NULL;
8702 /** Parse tokens for template create command. */
8704 parse_template(struct context *ctx, const struct token *token,
8705 const char *str, unsigned int len,
8706 void *buf, unsigned int size)
8708 struct buffer *out = buf;
8710 /* Token name must match. */
8711 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8713 /* Nothing else to do if there is no buffer. */
8716 if (!out->command) {
8717 if (ctx->curr != PATTERN_TEMPLATE &&
8718 ctx->curr != ACTIONS_TEMPLATE)
8720 if (sizeof(*out) > size)
8722 out->command = ctx->curr;
8725 ctx->objmask = NULL;
8726 out->args.vc.data = (uint8_t *)out + size;
8729 switch (ctx->curr) {
8730 case PATTERN_TEMPLATE_CREATE:
8731 out->args.vc.pattern =
8732 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8734 out->args.vc.pat_templ_id = UINT32_MAX;
8735 out->command = ctx->curr;
8738 ctx->objmask = NULL;
8740 case PATTERN_TEMPLATE_EGRESS:
8741 out->args.vc.attr.egress = 1;
8743 case PATTERN_TEMPLATE_INGRESS:
8744 out->args.vc.attr.ingress = 1;
8746 case PATTERN_TEMPLATE_TRANSFER:
8747 out->args.vc.attr.transfer = 1;
8749 case ACTIONS_TEMPLATE_CREATE:
8750 out->args.vc.act_templ_id = UINT32_MAX;
8751 out->command = ctx->curr;
8754 ctx->objmask = NULL;
8756 case ACTIONS_TEMPLATE_SPEC:
8757 out->args.vc.actions =
8758 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8760 ctx->object = out->args.vc.actions;
8761 ctx->objmask = NULL;
8763 case ACTIONS_TEMPLATE_MASK:
8764 out->args.vc.masks =
8765 (void *)RTE_ALIGN_CEIL((uintptr_t)
8766 (out->args.vc.actions +
8767 out->args.vc.actions_n),
8769 ctx->object = out->args.vc.masks;
8770 ctx->objmask = NULL;
8772 case ACTIONS_TEMPLATE_EGRESS:
8773 out->args.vc.attr.egress = 1;
8775 case ACTIONS_TEMPLATE_INGRESS:
8776 out->args.vc.attr.ingress = 1;
8778 case ACTIONS_TEMPLATE_TRANSFER:
8779 out->args.vc.attr.transfer = 1;
8786 /** Parse tokens for template destroy command. */
8788 parse_template_destroy(struct context *ctx, const struct token *token,
8789 const char *str, unsigned int len,
8790 void *buf, unsigned int size)
8792 struct buffer *out = buf;
8793 uint32_t *template_id;
8795 /* Token name must match. */
8796 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8798 /* Nothing else to do if there is no buffer. */
8801 if (!out->command ||
8802 out->command == PATTERN_TEMPLATE ||
8803 out->command == ACTIONS_TEMPLATE) {
8804 if (ctx->curr != PATTERN_TEMPLATE_DESTROY &&
8805 ctx->curr != ACTIONS_TEMPLATE_DESTROY)
8807 if (sizeof(*out) > size)
8809 out->command = ctx->curr;
8812 ctx->objmask = NULL;
8813 out->args.templ_destroy.template_id =
8814 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8818 template_id = out->args.templ_destroy.template_id
8819 + out->args.templ_destroy.template_id_n++;
8820 if ((uint8_t *)template_id > (uint8_t *)out + size)
8823 ctx->object = template_id;
8824 ctx->objmask = NULL;
8828 /** Parse tokens for table create command. */
8830 parse_table(struct context *ctx, const struct token *token,
8831 const char *str, unsigned int len,
8832 void *buf, unsigned int size)
8834 struct buffer *out = buf;
8835 uint32_t *template_id;
8837 /* Token name must match. */
8838 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8840 /* Nothing else to do if there is no buffer. */
8843 if (!out->command) {
8844 if (ctx->curr != TABLE)
8846 if (sizeof(*out) > size)
8848 out->command = ctx->curr;
8851 ctx->objmask = NULL;
8854 switch (ctx->curr) {
8856 out->command = ctx->curr;
8859 ctx->objmask = NULL;
8860 out->args.table.id = UINT32_MAX;
8862 case TABLE_PATTERN_TEMPLATE:
8863 out->args.table.pat_templ_id =
8864 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8866 template_id = out->args.table.pat_templ_id
8867 + out->args.table.pat_templ_id_n++;
8868 if ((uint8_t *)template_id > (uint8_t *)out + size)
8871 ctx->object = template_id;
8872 ctx->objmask = NULL;
8874 case TABLE_ACTIONS_TEMPLATE:
8875 out->args.table.act_templ_id =
8876 (void *)RTE_ALIGN_CEIL((uintptr_t)
8877 (out->args.table.pat_templ_id +
8878 out->args.table.pat_templ_id_n),
8880 template_id = out->args.table.act_templ_id
8881 + out->args.table.act_templ_id_n++;
8882 if ((uint8_t *)template_id > (uint8_t *)out + size)
8885 ctx->object = template_id;
8886 ctx->objmask = NULL;
8889 out->args.table.attr.flow_attr.ingress = 1;
8892 out->args.table.attr.flow_attr.egress = 1;
8894 case TABLE_TRANSFER:
8895 out->args.table.attr.flow_attr.transfer = 1;
8902 /** Parse tokens for table destroy command. */
8904 parse_table_destroy(struct context *ctx, const struct token *token,
8905 const char *str, unsigned int len,
8906 void *buf, unsigned int size)
8908 struct buffer *out = buf;
8911 /* Token name must match. */
8912 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8914 /* Nothing else to do if there is no buffer. */
8917 if (!out->command || out->command == TABLE) {
8918 if (ctx->curr != TABLE_DESTROY)
8920 if (sizeof(*out) > size)
8922 out->command = ctx->curr;
8925 ctx->objmask = NULL;
8926 out->args.table_destroy.table_id =
8927 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8931 table_id = out->args.table_destroy.table_id
8932 + out->args.table_destroy.table_id_n++;
8933 if ((uint8_t *)table_id > (uint8_t *)out + size)
8936 ctx->object = table_id;
8937 ctx->objmask = NULL;
8941 /** Parse tokens for queue create commands. */
8943 parse_qo(struct context *ctx, const struct token *token,
8944 const char *str, unsigned int len,
8945 void *buf, unsigned int size)
8947 struct buffer *out = buf;
8949 /* Token name must match. */
8950 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8952 /* Nothing else to do if there is no buffer. */
8955 if (!out->command) {
8956 if (ctx->curr != QUEUE)
8958 if (sizeof(*out) > size)
8960 out->command = ctx->curr;
8963 ctx->objmask = NULL;
8964 out->args.vc.data = (uint8_t *)out + size;
8967 switch (ctx->curr) {
8969 out->command = ctx->curr;
8972 ctx->objmask = NULL;
8974 case QUEUE_TEMPLATE_TABLE:
8975 case QUEUE_PATTERN_TEMPLATE:
8976 case QUEUE_ACTIONS_TEMPLATE:
8977 case QUEUE_CREATE_POSTPONE:
8980 out->args.vc.pattern =
8981 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8983 ctx->object = out->args.vc.pattern;
8984 ctx->objmask = NULL;
8987 out->args.vc.actions =
8988 (void *)RTE_ALIGN_CEIL((uintptr_t)
8989 (out->args.vc.pattern +
8990 out->args.vc.pattern_n),
8992 ctx->object = out->args.vc.actions;
8993 ctx->objmask = NULL;
9000 /** Parse tokens for queue destroy command. */
9002 parse_qo_destroy(struct context *ctx, const struct token *token,
9003 const char *str, unsigned int len,
9004 void *buf, unsigned int size)
9006 struct buffer *out = buf;
9009 /* Token name must match. */
9010 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
9012 /* Nothing else to do if there is no buffer. */
9015 if (!out->command || out->command == QUEUE) {
9016 if (ctx->curr != QUEUE_DESTROY)
9018 if (sizeof(*out) > size)
9020 out->command = ctx->curr;
9023 ctx->objmask = NULL;
9024 out->args.destroy.rule =
9025 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
9029 switch (ctx->curr) {
9030 case QUEUE_DESTROY_ID:
9031 flow_id = out->args.destroy.rule
9032 + out->args.destroy.rule_n++;
9033 if ((uint8_t *)flow_id > (uint8_t *)out + size)
9036 ctx->object = flow_id;
9037 ctx->objmask = NULL;
9039 case QUEUE_DESTROY_POSTPONE:
9046 /** Parse tokens for push queue command. */
9048 parse_push(struct context *ctx, const struct token *token,
9049 const char *str, unsigned int len,
9050 void *buf, unsigned int size)
9052 struct buffer *out = buf;
9054 /* Token name must match. */
9055 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
9057 /* Nothing else to do if there is no buffer. */
9060 if (!out->command) {
9061 if (ctx->curr != PUSH)
9063 if (sizeof(*out) > size)
9065 out->command = ctx->curr;
9068 ctx->objmask = NULL;
9069 out->args.vc.data = (uint8_t *)out + size;
9074 /** Parse tokens for pull command. */
9076 parse_pull(struct context *ctx, const struct token *token,
9077 const char *str, unsigned int len,
9078 void *buf, unsigned int size)
9080 struct buffer *out = buf;
9082 /* Token name must match. */
9083 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
9085 /* Nothing else to do if there is no buffer. */
9088 if (!out->command) {
9089 if (ctx->curr != PULL)
9091 if (sizeof(*out) > size)
9093 out->command = ctx->curr;
9096 ctx->objmask = NULL;
9097 out->args.vc.data = (uint8_t *)out + size;
9103 parse_flex(struct context *ctx, const struct token *token,
9104 const char *str, unsigned int len,
9105 void *buf, unsigned int size)
9107 struct buffer *out = buf;
9109 /* Token name must match. */
9110 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
9112 /* Nothing else to do if there is no buffer. */
9115 if (out->command == ZERO) {
9116 if (ctx->curr != FLEX)
9118 if (sizeof(*out) > size)
9120 out->command = ctx->curr;
9123 ctx->objmask = NULL;
9125 switch (ctx->curr) {
9128 case FLEX_ITEM_INIT:
9129 case FLEX_ITEM_CREATE:
9130 case FLEX_ITEM_DESTROY:
9131 out->command = ctx->curr;
9140 parse_tunnel(struct context *ctx, const struct token *token,
9141 const char *str, unsigned int len,
9142 void *buf, unsigned int size)
9144 struct buffer *out = buf;
9146 /* Token name must match. */
9147 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
9149 /* Nothing else to do if there is no buffer. */
9152 if (!out->command) {
9153 if (ctx->curr != TUNNEL)
9155 if (sizeof(*out) > size)
9157 out->command = ctx->curr;
9160 ctx->objmask = NULL;
9162 switch (ctx->curr) {
9166 case TUNNEL_DESTROY:
9168 out->command = ctx->curr;
9170 case TUNNEL_CREATE_TYPE:
9171 case TUNNEL_DESTROY_ID:
9172 ctx->object = &out->args.vc.tunnel_ops;
9181 * Parse signed/unsigned integers 8 to 64-bit long.
9183 * Last argument (ctx->args) is retrieved to determine integer type and
9187 parse_int(struct context *ctx, const struct token *token,
9188 const char *str, unsigned int len,
9189 void *buf, unsigned int size)
9191 const struct arg *arg = pop_args(ctx);
9196 /* Argument is expected. */
9201 (uintmax_t)strtoimax(str, &end, 0) :
9202 strtoumax(str, &end, 0);
9203 if (errno || (size_t)(end - str) != len)
9206 ((arg->sign && ((intmax_t)u < (intmax_t)arg->min ||
9207 (intmax_t)u > (intmax_t)arg->max)) ||
9208 (!arg->sign && (u < arg->min || u > arg->max))))
9213 if (!arg_entry_bf_fill(ctx->object, u, arg) ||
9214 !arg_entry_bf_fill(ctx->objmask, -1, arg))
9218 buf = (uint8_t *)ctx->object + arg->offset;
9220 if (u > RTE_LEN2MASK(size * CHAR_BIT, uint64_t))
9224 case sizeof(uint8_t):
9225 *(uint8_t *)buf = u;
9227 case sizeof(uint16_t):
9228 *(uint16_t *)buf = arg->hton ? rte_cpu_to_be_16(u) : u;
9230 case sizeof(uint8_t [3]):
9231 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
9233 ((uint8_t *)buf)[0] = u;
9234 ((uint8_t *)buf)[1] = u >> 8;
9235 ((uint8_t *)buf)[2] = u >> 16;
9239 ((uint8_t *)buf)[0] = u >> 16;
9240 ((uint8_t *)buf)[1] = u >> 8;
9241 ((uint8_t *)buf)[2] = u;
9243 case sizeof(uint32_t):
9244 *(uint32_t *)buf = arg->hton ? rte_cpu_to_be_32(u) : u;
9246 case sizeof(uint64_t):
9247 *(uint64_t *)buf = arg->hton ? rte_cpu_to_be_64(u) : u;
9252 if (ctx->objmask && buf != (uint8_t *)ctx->objmask + arg->offset) {
9254 buf = (uint8_t *)ctx->objmask + arg->offset;
9259 push_args(ctx, arg);
9266 * Three arguments (ctx->args) are retrieved from the stack to store data,
9267 * its actual length and address (in that order).
9270 parse_string(struct context *ctx, const struct token *token,
9271 const char *str, unsigned int len,
9272 void *buf, unsigned int size)
9274 const struct arg *arg_data = pop_args(ctx);
9275 const struct arg *arg_len = pop_args(ctx);
9276 const struct arg *arg_addr = pop_args(ctx);
9277 char tmp[16]; /* Ought to be enough. */
9280 /* Arguments are expected. */
9284 push_args(ctx, arg_data);
9288 push_args(ctx, arg_len);
9289 push_args(ctx, arg_data);
9292 size = arg_data->size;
9293 /* Bit-mask fill is not supported. */
9294 if (arg_data->mask || size < len)
9298 /* Let parse_int() fill length information first. */
9299 ret = snprintf(tmp, sizeof(tmp), "%u", len);
9302 push_args(ctx, arg_len);
9303 ret = parse_int(ctx, token, tmp, ret, NULL, 0);
9308 buf = (uint8_t *)ctx->object + arg_data->offset;
9309 /* Output buffer is not necessarily NUL-terminated. */
9310 memcpy(buf, str, len);
9311 memset((uint8_t *)buf + len, 0x00, size - len);
9313 memset((uint8_t *)ctx->objmask + arg_data->offset, 0xff, len);
9314 /* Save address if requested. */
9315 if (arg_addr->size) {
9316 memcpy((uint8_t *)ctx->object + arg_addr->offset,
9318 (uint8_t *)ctx->object + arg_data->offset
9322 memcpy((uint8_t *)ctx->objmask + arg_addr->offset,
9324 (uint8_t *)ctx->objmask + arg_data->offset
9330 push_args(ctx, arg_addr);
9331 push_args(ctx, arg_len);
9332 push_args(ctx, arg_data);
9337 parse_hex_string(const char *src, uint8_t *dst, uint32_t *size)
9339 const uint8_t *head = dst;
9347 /* Convert chars to bytes */
9349 char tmp[3], *end = tmp;
9350 uint32_t read_lim = left & 1 ? 1 : 2;
9352 snprintf(tmp, read_lim + 1, "%s", src);
9353 *dst = strtoul(tmp, &end, 16);
9356 *size = (uint32_t)(dst - head);
9364 *size = (uint32_t)(dst - head);
9369 parse_hex(struct context *ctx, const struct token *token,
9370 const char *str, unsigned int len,
9371 void *buf, unsigned int size)
9373 const struct arg *arg_data = pop_args(ctx);
9374 const struct arg *arg_len = pop_args(ctx);
9375 const struct arg *arg_addr = pop_args(ctx);
9376 char tmp[16]; /* Ought to be enough. */
9378 unsigned int hexlen = len;
9379 unsigned int length = 256;
9380 uint8_t hex_tmp[length];
9382 /* Arguments are expected. */
9386 push_args(ctx, arg_data);
9390 push_args(ctx, arg_len);
9391 push_args(ctx, arg_data);
9394 size = arg_data->size;
9395 /* Bit-mask fill is not supported. */
9401 /* translate bytes string to array. */
9402 if (str[0] == '0' && ((str[1] == 'x') ||
9407 if (hexlen > length)
9409 ret = parse_hex_string(str, hex_tmp, &hexlen);
9412 /* Check the converted binary fits into data buffer. */
9415 /* Let parse_int() fill length information first. */
9416 ret = snprintf(tmp, sizeof(tmp), "%u", hexlen);
9419 /* Save length if requested. */
9420 if (arg_len->size) {
9421 push_args(ctx, arg_len);
9422 ret = parse_int(ctx, token, tmp, ret, NULL, 0);
9428 buf = (uint8_t *)ctx->object + arg_data->offset;
9429 /* Output buffer is not necessarily NUL-terminated. */
9430 memcpy(buf, hex_tmp, hexlen);
9431 memset((uint8_t *)buf + hexlen, 0x00, size - hexlen);
9433 memset((uint8_t *)ctx->objmask + arg_data->offset,
9435 /* Save address if requested. */
9436 if (arg_addr->size) {
9437 memcpy((uint8_t *)ctx->object + arg_addr->offset,
9439 (uint8_t *)ctx->object + arg_data->offset
9443 memcpy((uint8_t *)ctx->objmask + arg_addr->offset,
9445 (uint8_t *)ctx->objmask + arg_data->offset
9451 push_args(ctx, arg_addr);
9452 push_args(ctx, arg_len);
9453 push_args(ctx, arg_data);
9459 * Parse a zero-ended string.
9462 parse_string0(struct context *ctx, const struct token *token __rte_unused,
9463 const char *str, unsigned int len,
9464 void *buf, unsigned int size)
9466 const struct arg *arg_data = pop_args(ctx);
9468 /* Arguments are expected. */
9471 size = arg_data->size;
9472 /* Bit-mask fill is not supported. */
9473 if (arg_data->mask || size < len + 1)
9477 buf = (uint8_t *)ctx->object + arg_data->offset;
9478 strncpy(buf, str, len);
9480 memset((uint8_t *)ctx->objmask + arg_data->offset, 0xff, len);
9483 push_args(ctx, arg_data);
9488 * Parse a MAC address.
9490 * Last argument (ctx->args) is retrieved to determine storage size and
9494 parse_mac_addr(struct context *ctx, const struct token *token,
9495 const char *str, unsigned int len,
9496 void *buf, unsigned int size)
9498 const struct arg *arg = pop_args(ctx);
9499 struct rte_ether_addr tmp;
9503 /* Argument is expected. */
9507 /* Bit-mask fill is not supported. */
9508 if (arg->mask || size != sizeof(tmp))
9510 /* Only network endian is supported. */
9513 ret = cmdline_parse_etheraddr(NULL, str, &tmp, size);
9514 if (ret < 0 || (unsigned int)ret != len)
9518 buf = (uint8_t *)ctx->object + arg->offset;
9519 memcpy(buf, &tmp, size);
9521 memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
9524 push_args(ctx, arg);
9529 * Parse an IPv4 address.
9531 * Last argument (ctx->args) is retrieved to determine storage size and
9535 parse_ipv4_addr(struct context *ctx, const struct token *token,
9536 const char *str, unsigned int len,
9537 void *buf, unsigned int size)
9539 const struct arg *arg = pop_args(ctx);
9544 /* Argument is expected. */
9548 /* Bit-mask fill is not supported. */
9549 if (arg->mask || size != sizeof(tmp))
9551 /* Only network endian is supported. */
9554 memcpy(str2, str, len);
9556 ret = inet_pton(AF_INET, str2, &tmp);
9558 /* Attempt integer parsing. */
9559 push_args(ctx, arg);
9560 return parse_int(ctx, token, str, len, buf, size);
9564 buf = (uint8_t *)ctx->object + arg->offset;
9565 memcpy(buf, &tmp, size);
9567 memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
9570 push_args(ctx, arg);
9575 * Parse an IPv6 address.
9577 * Last argument (ctx->args) is retrieved to determine storage size and
9581 parse_ipv6_addr(struct context *ctx, const struct token *token,
9582 const char *str, unsigned int len,
9583 void *buf, unsigned int size)
9585 const struct arg *arg = pop_args(ctx);
9587 struct in6_addr tmp;
9591 /* Argument is expected. */
9595 /* Bit-mask fill is not supported. */
9596 if (arg->mask || size != sizeof(tmp))
9598 /* Only network endian is supported. */
9601 memcpy(str2, str, len);
9603 ret = inet_pton(AF_INET6, str2, &tmp);
9608 buf = (uint8_t *)ctx->object + arg->offset;
9609 memcpy(buf, &tmp, size);
9611 memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
9614 push_args(ctx, arg);
9618 /** Boolean values (even indices stand for false). */
9619 static const char *const boolean_name[] = {
9629 * Parse a boolean value.
9631 * Last argument (ctx->args) is retrieved to determine storage size and
9635 parse_boolean(struct context *ctx, const struct token *token,
9636 const char *str, unsigned int len,
9637 void *buf, unsigned int size)
9639 const struct arg *arg = pop_args(ctx);
9643 /* Argument is expected. */
9646 for (i = 0; boolean_name[i]; ++i)
9647 if (!strcmp_partial(boolean_name[i], str, len))
9649 /* Process token as integer. */
9650 if (boolean_name[i])
9651 str = i & 1 ? "1" : "0";
9652 push_args(ctx, arg);
9653 ret = parse_int(ctx, token, str, strlen(str), buf, size);
9654 return ret > 0 ? (int)len : ret;
9657 /** Parse port and update context. */
9659 parse_port(struct context *ctx, const struct token *token,
9660 const char *str, unsigned int len,
9661 void *buf, unsigned int size)
9663 struct buffer *out = &(struct buffer){ .port = 0 };
9671 ctx->objmask = NULL;
9672 size = sizeof(*out);
9674 ret = parse_int(ctx, token, str, len, out, size);
9676 ctx->port = out->port;
9683 parse_ia_id2ptr(struct context *ctx, const struct token *token,
9684 const char *str, unsigned int len,
9685 void *buf, unsigned int size)
9687 struct rte_flow_action *action = ctx->object;
9695 ctx->objmask = NULL;
9696 ret = parse_int(ctx, token, str, len, ctx->object, sizeof(id));
9697 ctx->object = action;
9698 if (ret != (int)len)
9700 /* set indirect action */
9702 action->conf = port_action_handle_get_by_id(ctx->port, id);
9703 ret = (action->conf) ? ret : -1;
9708 /** Parse set command, initialize output buffer for subsequent tokens. */
9710 parse_set_raw_encap_decap(struct context *ctx, const struct token *token,
9711 const char *str, unsigned int len,
9712 void *buf, unsigned int size)
9714 struct buffer *out = buf;
9716 /* Token name must match. */
9717 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
9719 /* Nothing else to do if there is no buffer. */
9722 /* Make sure buffer is large enough. */
9723 if (size < sizeof(*out))
9726 ctx->objmask = NULL;
9730 out->command = ctx->curr;
9731 /* For encap/decap we need is pattern */
9732 out->args.vc.pattern = (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
9737 /** Parse set command, initialize output buffer for subsequent tokens. */
9739 parse_set_sample_action(struct context *ctx, const struct token *token,
9740 const char *str, unsigned int len,
9741 void *buf, unsigned int size)
9743 struct buffer *out = buf;
9745 /* Token name must match. */
9746 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
9748 /* Nothing else to do if there is no buffer. */
9751 /* Make sure buffer is large enough. */
9752 if (size < sizeof(*out))
9755 ctx->objmask = NULL;
9759 out->command = ctx->curr;
9760 /* For sampler we need is actions */
9761 out->args.vc.actions = (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
9767 * Parse set raw_encap/raw_decap command,
9768 * initialize output buffer for subsequent tokens.
9771 parse_set_init(struct context *ctx, const struct token *token,
9772 const char *str, unsigned int len,
9773 void *buf, unsigned int size)
9775 struct buffer *out = buf;
9777 /* Token name must match. */
9778 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
9780 /* Nothing else to do if there is no buffer. */
9783 /* Make sure buffer is large enough. */
9784 if (size < sizeof(*out))
9786 /* Initialize buffer. */
9787 memset(out, 0x00, sizeof(*out));
9788 memset((uint8_t *)out + sizeof(*out), 0x22, size - sizeof(*out));
9791 ctx->objmask = NULL;
9792 if (!out->command) {
9793 if (ctx->curr != SET)
9795 if (sizeof(*out) > size)
9797 out->command = ctx->curr;
9798 out->args.vc.data = (uint8_t *)out + size;
9799 ctx->object = (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
9806 * Replace testpmd handles in a flex flow item with real values.
9809 parse_flex_handle(struct context *ctx, const struct token *token,
9810 const char *str, unsigned int len,
9811 void *buf, unsigned int size)
9813 struct rte_flow_item_flex *spec, *mask;
9814 const struct rte_flow_item_flex *src_spec, *src_mask;
9815 const struct arg *arg = pop_args(ctx);
9821 printf("Bad environment\n");
9824 offset = arg->offset;
9825 push_args(ctx, arg);
9826 ret = parse_int(ctx, token, str, len, buf, size);
9827 if (ret <= 0 || !ctx->object)
9829 if (ctx->port >= RTE_MAX_ETHPORTS) {
9830 printf("Bad port\n");
9833 if (offset == offsetof(struct rte_flow_item_flex, handle)) {
9834 const struct flex_item *fp;
9835 struct rte_flow_item_flex *item_flex = ctx->object;
9836 handle = (uint16_t)(uintptr_t)item_flex->handle;
9837 if (handle >= FLEX_MAX_PARSERS_NUM) {
9838 printf("Bad flex item handle\n");
9841 fp = flex_items[ctx->port][handle];
9843 printf("Bad flex item handle\n");
9846 item_flex->handle = fp->flex_handle;
9847 } else if (offset == offsetof(struct rte_flow_item_flex, pattern)) {
9848 handle = (uint16_t)(uintptr_t)
9849 ((struct rte_flow_item_flex *)ctx->object)->pattern;
9850 if (handle >= FLEX_MAX_PATTERNS_NUM) {
9851 printf("Bad pattern handle\n");
9854 src_spec = &flex_patterns[handle].spec;
9855 src_mask = &flex_patterns[handle].mask;
9857 mask = spec + 2; /* spec, last, mask */
9858 /* fill flow rule spec and mask parameters */
9859 spec->length = src_spec->length;
9860 spec->pattern = src_spec->pattern;
9861 mask->length = src_mask->length;
9862 mask->pattern = src_mask->pattern;
9864 printf("Bad arguments - unknown flex item offset\n");
9870 /** No completion. */
9872 comp_none(struct context *ctx, const struct token *token,
9873 unsigned int ent, char *buf, unsigned int size)
9883 /** Complete boolean values. */
9885 comp_boolean(struct context *ctx, const struct token *token,
9886 unsigned int ent, char *buf, unsigned int size)
9892 for (i = 0; boolean_name[i]; ++i)
9893 if (buf && i == ent)
9894 return strlcpy(buf, boolean_name[i], size);
9900 /** Complete action names. */
9902 comp_action(struct context *ctx, const struct token *token,
9903 unsigned int ent, char *buf, unsigned int size)
9909 for (i = 0; next_action[i]; ++i)
9910 if (buf && i == ent)
9911 return strlcpy(buf, token_list[next_action[i]].name,
9918 /** Complete available ports. */
9920 comp_port(struct context *ctx, const struct token *token,
9921 unsigned int ent, char *buf, unsigned int size)
9928 RTE_ETH_FOREACH_DEV(p) {
9929 if (buf && i == ent)
9930 return snprintf(buf, size, "%u", p);
9938 /** Complete available rule IDs. */
9940 comp_rule_id(struct context *ctx, const struct token *token,
9941 unsigned int ent, char *buf, unsigned int size)
9944 struct rte_port *port;
9945 struct port_flow *pf;
9948 if (port_id_is_invalid(ctx->port, DISABLED_WARN) ||
9949 ctx->port == (portid_t)RTE_PORT_ALL)
9951 port = &ports[ctx->port];
9952 for (pf = port->flow_list; pf != NULL; pf = pf->next) {
9953 if (buf && i == ent)
9954 return snprintf(buf, size, "%u", pf->id);
9962 /** Complete type field for RSS action. */
9964 comp_vc_action_rss_type(struct context *ctx, const struct token *token,
9965 unsigned int ent, char *buf, unsigned int size)
9971 for (i = 0; rss_type_table[i].str; ++i)
9976 return strlcpy(buf, rss_type_table[ent].str, size);
9978 return snprintf(buf, size, "end");
9982 /** Complete queue field for RSS action. */
9984 comp_vc_action_rss_queue(struct context *ctx, const struct token *token,
9985 unsigned int ent, char *buf, unsigned int size)
9992 return snprintf(buf, size, "%u", ent);
9994 return snprintf(buf, size, "end");
9998 /** Complete index number for set raw_encap/raw_decap commands. */
10000 comp_set_raw_index(struct context *ctx, const struct token *token,
10001 unsigned int ent, char *buf, unsigned int size)
10007 RTE_SET_USED(token);
10008 for (idx = 0; idx < RAW_ENCAP_CONFS_MAX_NUM; ++idx) {
10009 if (buf && idx == ent)
10010 return snprintf(buf, size, "%u", idx);
10016 /** Complete index number for set raw_encap/raw_decap commands. */
10018 comp_set_sample_index(struct context *ctx, const struct token *token,
10019 unsigned int ent, char *buf, unsigned int size)
10025 RTE_SET_USED(token);
10026 for (idx = 0; idx < RAW_SAMPLE_CONFS_MAX_NUM; ++idx) {
10027 if (buf && idx == ent)
10028 return snprintf(buf, size, "%u", idx);
10034 /** Complete operation for modify_field command. */
10036 comp_set_modify_field_op(struct context *ctx, const struct token *token,
10037 unsigned int ent, char *buf, unsigned int size)
10040 RTE_SET_USED(token);
10042 return RTE_DIM(modify_field_ops);
10043 if (ent < RTE_DIM(modify_field_ops) - 1)
10044 return strlcpy(buf, modify_field_ops[ent], size);
10048 /** Complete field id for modify_field command. */
10050 comp_set_modify_field_id(struct context *ctx, const struct token *token,
10051 unsigned int ent, char *buf, unsigned int size)
10055 RTE_SET_USED(token);
10057 return RTE_DIM(modify_field_ids);
10058 if (ent >= RTE_DIM(modify_field_ids) - 1)
10060 name = modify_field_ids[ent];
10061 if (ctx->curr == ACTION_MODIFY_FIELD_SRC_TYPE ||
10062 (strcmp(name, "pointer") && strcmp(name, "value")))
10063 return strlcpy(buf, name, size);
10067 /** Complete available pattern template IDs. */
10069 comp_pattern_template_id(struct context *ctx, const struct token *token,
10070 unsigned int ent, char *buf, unsigned int size)
10072 unsigned int i = 0;
10073 struct rte_port *port;
10074 struct port_template *pt;
10077 if (port_id_is_invalid(ctx->port, DISABLED_WARN) ||
10078 ctx->port == (portid_t)RTE_PORT_ALL)
10080 port = &ports[ctx->port];
10081 for (pt = port->pattern_templ_list; pt != NULL; pt = pt->next) {
10082 if (buf && i == ent)
10083 return snprintf(buf, size, "%u", pt->id);
10091 /** Complete available actions template IDs. */
10093 comp_actions_template_id(struct context *ctx, const struct token *token,
10094 unsigned int ent, char *buf, unsigned int size)
10096 unsigned int i = 0;
10097 struct rte_port *port;
10098 struct port_template *pt;
10101 if (port_id_is_invalid(ctx->port, DISABLED_WARN) ||
10102 ctx->port == (portid_t)RTE_PORT_ALL)
10104 port = &ports[ctx->port];
10105 for (pt = port->actions_templ_list; pt != NULL; pt = pt->next) {
10106 if (buf && i == ent)
10107 return snprintf(buf, size, "%u", pt->id);
10115 /** Complete available table IDs. */
10117 comp_table_id(struct context *ctx, const struct token *token,
10118 unsigned int ent, char *buf, unsigned int size)
10120 unsigned int i = 0;
10121 struct rte_port *port;
10122 struct port_table *pt;
10125 if (port_id_is_invalid(ctx->port, DISABLED_WARN) ||
10126 ctx->port == (portid_t)RTE_PORT_ALL)
10128 port = &ports[ctx->port];
10129 for (pt = port->table_list; pt != NULL; pt = pt->next) {
10130 if (buf && i == ent)
10131 return snprintf(buf, size, "%u", pt->id);
10139 /** Complete available queue IDs. */
10141 comp_queue_id(struct context *ctx, const struct token *token,
10142 unsigned int ent, char *buf, unsigned int size)
10144 unsigned int i = 0;
10145 struct rte_port *port;
10148 if (port_id_is_invalid(ctx->port, DISABLED_WARN) ||
10149 ctx->port == (portid_t)RTE_PORT_ALL)
10151 port = &ports[ctx->port];
10152 for (i = 0; i < port->queue_nb; i++) {
10153 if (buf && i == ent)
10154 return snprintf(buf, size, "%u", i);
10161 /** Internal context. */
10162 static struct context cmd_flow_context;
10164 /** Global parser instance (cmdline API). */
10165 cmdline_parse_inst_t cmd_flow;
10166 cmdline_parse_inst_t cmd_set_raw;
10168 /** Initialize context. */
10170 cmd_flow_context_init(struct context *ctx)
10172 /* A full memset() is not necessary. */
10181 ctx->object = NULL;
10182 ctx->objmask = NULL;
10185 /** Parse a token (cmdline API). */
10187 cmd_flow_parse(cmdline_parse_token_hdr_t *hdr, const char *src, void *result,
10190 struct context *ctx = &cmd_flow_context;
10191 const struct token *token;
10192 const enum index *list;
10197 token = &token_list[ctx->curr];
10198 /* Check argument length. */
10201 for (len = 0; src[len]; ++len)
10202 if (src[len] == '#' || isspace(src[len]))
10206 /* Last argument and EOL detection. */
10207 for (i = len; src[i]; ++i)
10208 if (src[i] == '#' || src[i] == '\r' || src[i] == '\n')
10210 else if (!isspace(src[i])) {
10214 for (; src[i]; ++i)
10215 if (src[i] == '\r' || src[i] == '\n') {
10219 /* Initialize context if necessary. */
10220 if (!ctx->next_num) {
10223 ctx->next[ctx->next_num++] = token->next[0];
10225 /* Process argument through candidates. */
10226 ctx->prev = ctx->curr;
10227 list = ctx->next[ctx->next_num - 1];
10228 for (i = 0; list[i]; ++i) {
10229 const struct token *next = &token_list[list[i]];
10232 ctx->curr = list[i];
10234 tmp = next->call(ctx, next, src, len, result, size);
10236 tmp = parse_default(ctx, next, src, len, result, size);
10237 if (tmp == -1 || tmp != len)
10245 /* Push subsequent tokens if any. */
10247 for (i = 0; token->next[i]; ++i) {
10248 if (ctx->next_num == RTE_DIM(ctx->next))
10250 ctx->next[ctx->next_num++] = token->next[i];
10252 /* Push arguments if any. */
10254 for (i = 0; token->args[i]; ++i) {
10255 if (ctx->args_num == RTE_DIM(ctx->args))
10257 ctx->args[ctx->args_num++] = token->args[i];
10263 flow_parse(const char *src, void *result, unsigned int size,
10264 struct rte_flow_attr **attr,
10265 struct rte_flow_item **pattern, struct rte_flow_action **actions)
10268 struct context saved_flow_ctx = cmd_flow_context;
10270 cmd_flow_context_init(&cmd_flow_context);
10272 ret = cmd_flow_parse(NULL, src, result, size);
10275 while (isspace(*src))
10278 } while (ret > 0 && strlen(src));
10279 cmd_flow_context = saved_flow_ctx;
10280 *attr = &((struct buffer *)result)->args.vc.attr;
10281 *pattern = ((struct buffer *)result)->args.vc.pattern;
10282 *actions = ((struct buffer *)result)->args.vc.actions;
10283 return (ret >= 0 && !strlen(src)) ? 0 : -1;
10286 /** Return number of completion entries (cmdline API). */
10288 cmd_flow_complete_get_nb(cmdline_parse_token_hdr_t *hdr)
10290 struct context *ctx = &cmd_flow_context;
10291 const struct token *token = &token_list[ctx->curr];
10292 const enum index *list;
10296 /* Count number of tokens in current list. */
10298 list = ctx->next[ctx->next_num - 1];
10300 list = token->next[0];
10301 for (i = 0; list[i]; ++i)
10306 * If there is a single token, use its completion callback, otherwise
10307 * return the number of entries.
10309 token = &token_list[list[0]];
10310 if (i == 1 && token->comp) {
10311 /* Save index for cmd_flow_get_help(). */
10312 ctx->prev = list[0];
10313 return token->comp(ctx, token, 0, NULL, 0);
10318 /** Return a completion entry (cmdline API). */
10320 cmd_flow_complete_get_elt(cmdline_parse_token_hdr_t *hdr, int index,
10321 char *dst, unsigned int size)
10323 struct context *ctx = &cmd_flow_context;
10324 const struct token *token = &token_list[ctx->curr];
10325 const enum index *list;
10329 /* Count number of tokens in current list. */
10331 list = ctx->next[ctx->next_num - 1];
10333 list = token->next[0];
10334 for (i = 0; list[i]; ++i)
10338 /* If there is a single token, use its completion callback. */
10339 token = &token_list[list[0]];
10340 if (i == 1 && token->comp) {
10341 /* Save index for cmd_flow_get_help(). */
10342 ctx->prev = list[0];
10343 return token->comp(ctx, token, index, dst, size) < 0 ? -1 : 0;
10345 /* Otherwise make sure the index is valid and use defaults. */
10348 token = &token_list[list[index]];
10349 strlcpy(dst, token->name, size);
10350 /* Save index for cmd_flow_get_help(). */
10351 ctx->prev = list[index];
10355 /** Populate help strings for current token (cmdline API). */
10357 cmd_flow_get_help(cmdline_parse_token_hdr_t *hdr, char *dst, unsigned int size)
10359 struct context *ctx = &cmd_flow_context;
10360 const struct token *token = &token_list[ctx->prev];
10365 /* Set token type and update global help with details. */
10366 strlcpy(dst, (token->type ? token->type : "TOKEN"), size);
10368 cmd_flow.help_str = token->help;
10370 cmd_flow.help_str = token->name;
10374 /** Token definition template (cmdline API). */
10375 static struct cmdline_token_hdr cmd_flow_token_hdr = {
10376 .ops = &(struct cmdline_token_ops){
10377 .parse = cmd_flow_parse,
10378 .complete_get_nb = cmd_flow_complete_get_nb,
10379 .complete_get_elt = cmd_flow_complete_get_elt,
10380 .get_help = cmd_flow_get_help,
10385 /** Populate the next dynamic token. */
10387 cmd_flow_tok(cmdline_parse_token_hdr_t **hdr,
10388 cmdline_parse_token_hdr_t **hdr_inst)
10390 struct context *ctx = &cmd_flow_context;
10392 /* Always reinitialize context before requesting the first token. */
10393 if (!(hdr_inst - cmd_flow.tokens))
10394 cmd_flow_context_init(ctx);
10395 /* Return NULL when no more tokens are expected. */
10396 if (!ctx->next_num && ctx->curr) {
10400 /* Determine if command should end here. */
10401 if (ctx->eol && ctx->last && ctx->next_num) {
10402 const enum index *list = ctx->next[ctx->next_num - 1];
10405 for (i = 0; list[i]; ++i) {
10406 if (list[i] != END)
10412 *hdr = &cmd_flow_token_hdr;
10415 /** Dispatch parsed buffer to function calls. */
10417 cmd_flow_parsed(const struct buffer *in)
10419 switch (in->command) {
10421 port_flow_get_info(in->port);
10424 port_flow_configure(in->port,
10425 &in->args.configure.port_attr,
10426 in->args.configure.nb_queue,
10427 &in->args.configure.queue_attr);
10429 case PATTERN_TEMPLATE_CREATE:
10430 port_flow_pattern_template_create(in->port,
10431 in->args.vc.pat_templ_id,
10432 &((const struct rte_flow_pattern_template_attr) {
10433 .relaxed_matching = in->args.vc.attr.reserved,
10434 .ingress = in->args.vc.attr.ingress,
10435 .egress = in->args.vc.attr.egress,
10436 .transfer = in->args.vc.attr.transfer,
10438 in->args.vc.pattern);
10440 case PATTERN_TEMPLATE_DESTROY:
10441 port_flow_pattern_template_destroy(in->port,
10442 in->args.templ_destroy.template_id_n,
10443 in->args.templ_destroy.template_id);
10445 case ACTIONS_TEMPLATE_CREATE:
10446 port_flow_actions_template_create(in->port,
10447 in->args.vc.act_templ_id,
10448 &((const struct rte_flow_actions_template_attr) {
10449 .ingress = in->args.vc.attr.ingress,
10450 .egress = in->args.vc.attr.egress,
10451 .transfer = in->args.vc.attr.transfer,
10453 in->args.vc.actions,
10454 in->args.vc.masks);
10456 case ACTIONS_TEMPLATE_DESTROY:
10457 port_flow_actions_template_destroy(in->port,
10458 in->args.templ_destroy.template_id_n,
10459 in->args.templ_destroy.template_id);
10462 port_flow_template_table_create(in->port, in->args.table.id,
10463 &in->args.table.attr, in->args.table.pat_templ_id_n,
10464 in->args.table.pat_templ_id, in->args.table.act_templ_id_n,
10465 in->args.table.act_templ_id);
10467 case TABLE_DESTROY:
10468 port_flow_template_table_destroy(in->port,
10469 in->args.table_destroy.table_id_n,
10470 in->args.table_destroy.table_id);
10473 port_queue_flow_create(in->port, in->queue, in->postpone,
10474 in->args.vc.table_id, in->args.vc.pat_templ_id,
10475 in->args.vc.act_templ_id, in->args.vc.pattern,
10476 in->args.vc.actions);
10478 case QUEUE_DESTROY:
10479 port_queue_flow_destroy(in->port, in->queue, in->postpone,
10480 in->args.destroy.rule_n,
10481 in->args.destroy.rule);
10484 port_queue_flow_push(in->port, in->queue);
10487 port_queue_flow_pull(in->port, in->queue);
10489 case QUEUE_INDIRECT_ACTION_CREATE:
10490 port_queue_action_handle_create(
10491 in->port, in->queue, in->postpone,
10492 in->args.vc.attr.group,
10493 &((const struct rte_flow_indir_action_conf) {
10494 .ingress = in->args.vc.attr.ingress,
10495 .egress = in->args.vc.attr.egress,
10496 .transfer = in->args.vc.attr.transfer,
10498 in->args.vc.actions);
10500 case QUEUE_INDIRECT_ACTION_DESTROY:
10501 port_queue_action_handle_destroy(in->port,
10502 in->queue, in->postpone,
10503 in->args.ia_destroy.action_id_n,
10504 in->args.ia_destroy.action_id);
10506 case QUEUE_INDIRECT_ACTION_UPDATE:
10507 port_queue_action_handle_update(in->port,
10508 in->queue, in->postpone,
10509 in->args.vc.attr.group,
10510 in->args.vc.actions);
10512 case INDIRECT_ACTION_CREATE:
10513 port_action_handle_create(
10514 in->port, in->args.vc.attr.group,
10515 &((const struct rte_flow_indir_action_conf) {
10516 .ingress = in->args.vc.attr.ingress,
10517 .egress = in->args.vc.attr.egress,
10518 .transfer = in->args.vc.attr.transfer,
10520 in->args.vc.actions);
10522 case INDIRECT_ACTION_DESTROY:
10523 port_action_handle_destroy(in->port,
10524 in->args.ia_destroy.action_id_n,
10525 in->args.ia_destroy.action_id);
10527 case INDIRECT_ACTION_UPDATE:
10528 port_action_handle_update(in->port, in->args.vc.attr.group,
10529 in->args.vc.actions);
10531 case INDIRECT_ACTION_QUERY:
10532 port_action_handle_query(in->port, in->args.ia.action_id);
10535 port_flow_validate(in->port, &in->args.vc.attr,
10536 in->args.vc.pattern, in->args.vc.actions,
10537 &in->args.vc.tunnel_ops);
10540 port_flow_create(in->port, &in->args.vc.attr,
10541 in->args.vc.pattern, in->args.vc.actions,
10542 &in->args.vc.tunnel_ops);
10545 port_flow_destroy(in->port, in->args.destroy.rule_n,
10546 in->args.destroy.rule);
10549 port_flow_flush(in->port);
10553 port_flow_dump(in->port, in->args.dump.mode,
10554 in->args.dump.rule, in->args.dump.file);
10557 port_flow_query(in->port, in->args.query.rule,
10558 &in->args.query.action);
10561 port_flow_list(in->port, in->args.list.group_n,
10562 in->args.list.group);
10565 port_flow_isolate(in->port, in->args.isolate.set);
10568 port_flow_aged(in->port, in->args.aged.destroy);
10570 case TUNNEL_CREATE:
10571 port_flow_tunnel_create(in->port, &in->args.vc.tunnel_ops);
10573 case TUNNEL_DESTROY:
10574 port_flow_tunnel_destroy(in->port, in->args.vc.tunnel_ops.id);
10577 port_flow_tunnel_list(in->port);
10580 port_meter_policy_add(in->port, in->args.policy.policy_id,
10581 in->args.vc.actions);
10583 case FLEX_ITEM_CREATE:
10584 flex_item_create(in->port, in->args.flex.token,
10585 in->args.flex.filename);
10587 case FLEX_ITEM_DESTROY:
10588 flex_item_destroy(in->port, in->args.flex.token);
10595 /** Token generator and output processing callback (cmdline API). */
10597 cmd_flow_cb(void *arg0, struct cmdline *cl, void *arg2)
10600 cmd_flow_tok(arg0, arg2);
10602 cmd_flow_parsed(arg0);
10605 /** Global parser instance (cmdline API). */
10606 cmdline_parse_inst_t cmd_flow = {
10608 .data = NULL, /**< Unused. */
10609 .help_str = NULL, /**< Updated by cmd_flow_get_help(). */
10612 }, /**< Tokens are returned by cmd_flow_tok(). */
10615 /** set cmd facility. Reuse cmd flow's infrastructure as much as possible. */
10618 update_fields(uint8_t *buf, struct rte_flow_item *item, uint16_t next_proto)
10620 struct rte_ipv4_hdr *ipv4;
10621 struct rte_ether_hdr *eth;
10622 struct rte_ipv6_hdr *ipv6;
10623 struct rte_vxlan_hdr *vxlan;
10624 struct rte_vxlan_gpe_hdr *gpe;
10625 struct rte_flow_item_nvgre *nvgre;
10626 uint32_t ipv6_vtc_flow;
10628 switch (item->type) {
10629 case RTE_FLOW_ITEM_TYPE_ETH:
10630 eth = (struct rte_ether_hdr *)buf;
10632 eth->ether_type = rte_cpu_to_be_16(next_proto);
10634 case RTE_FLOW_ITEM_TYPE_IPV4:
10635 ipv4 = (struct rte_ipv4_hdr *)buf;
10636 if (!ipv4->version_ihl)
10637 ipv4->version_ihl = RTE_IPV4_VHL_DEF;
10638 if (next_proto && ipv4->next_proto_id == 0)
10639 ipv4->next_proto_id = (uint8_t)next_proto;
10641 case RTE_FLOW_ITEM_TYPE_IPV6:
10642 ipv6 = (struct rte_ipv6_hdr *)buf;
10643 if (next_proto && ipv6->proto == 0)
10644 ipv6->proto = (uint8_t)next_proto;
10645 ipv6_vtc_flow = rte_be_to_cpu_32(ipv6->vtc_flow);
10646 ipv6_vtc_flow &= 0x0FFFFFFF; /*< reset version bits. */
10647 ipv6_vtc_flow |= 0x60000000; /*< set ipv6 version. */
10648 ipv6->vtc_flow = rte_cpu_to_be_32(ipv6_vtc_flow);
10650 case RTE_FLOW_ITEM_TYPE_VXLAN:
10651 vxlan = (struct rte_vxlan_hdr *)buf;
10652 vxlan->vx_flags = 0x08;
10654 case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
10655 gpe = (struct rte_vxlan_gpe_hdr *)buf;
10656 gpe->vx_flags = 0x0C;
10658 case RTE_FLOW_ITEM_TYPE_NVGRE:
10659 nvgre = (struct rte_flow_item_nvgre *)buf;
10660 nvgre->protocol = rte_cpu_to_be_16(0x6558);
10661 nvgre->c_k_s_rsvd0_ver = rte_cpu_to_be_16(0x2000);
10668 /** Helper of get item's default mask. */
10669 static const void *
10670 flow_item_default_mask(const struct rte_flow_item *item)
10672 const void *mask = NULL;
10673 static rte_be32_t gre_key_default_mask = RTE_BE32(UINT32_MAX);
10675 switch (item->type) {
10676 case RTE_FLOW_ITEM_TYPE_ANY:
10677 mask = &rte_flow_item_any_mask;
10679 case RTE_FLOW_ITEM_TYPE_VF:
10680 mask = &rte_flow_item_vf_mask;
10682 case RTE_FLOW_ITEM_TYPE_PORT_ID:
10683 mask = &rte_flow_item_port_id_mask;
10685 case RTE_FLOW_ITEM_TYPE_RAW:
10686 mask = &rte_flow_item_raw_mask;
10688 case RTE_FLOW_ITEM_TYPE_ETH:
10689 mask = &rte_flow_item_eth_mask;
10691 case RTE_FLOW_ITEM_TYPE_VLAN:
10692 mask = &rte_flow_item_vlan_mask;
10694 case RTE_FLOW_ITEM_TYPE_IPV4:
10695 mask = &rte_flow_item_ipv4_mask;
10697 case RTE_FLOW_ITEM_TYPE_IPV6:
10698 mask = &rte_flow_item_ipv6_mask;
10700 case RTE_FLOW_ITEM_TYPE_ICMP:
10701 mask = &rte_flow_item_icmp_mask;
10703 case RTE_FLOW_ITEM_TYPE_UDP:
10704 mask = &rte_flow_item_udp_mask;
10706 case RTE_FLOW_ITEM_TYPE_TCP:
10707 mask = &rte_flow_item_tcp_mask;
10709 case RTE_FLOW_ITEM_TYPE_SCTP:
10710 mask = &rte_flow_item_sctp_mask;
10712 case RTE_FLOW_ITEM_TYPE_VXLAN:
10713 mask = &rte_flow_item_vxlan_mask;
10715 case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
10716 mask = &rte_flow_item_vxlan_gpe_mask;
10718 case RTE_FLOW_ITEM_TYPE_E_TAG:
10719 mask = &rte_flow_item_e_tag_mask;
10721 case RTE_FLOW_ITEM_TYPE_NVGRE:
10722 mask = &rte_flow_item_nvgre_mask;
10724 case RTE_FLOW_ITEM_TYPE_MPLS:
10725 mask = &rte_flow_item_mpls_mask;
10727 case RTE_FLOW_ITEM_TYPE_GRE:
10728 mask = &rte_flow_item_gre_mask;
10730 case RTE_FLOW_ITEM_TYPE_GRE_KEY:
10731 mask = &gre_key_default_mask;
10733 case RTE_FLOW_ITEM_TYPE_META:
10734 mask = &rte_flow_item_meta_mask;
10736 case RTE_FLOW_ITEM_TYPE_FUZZY:
10737 mask = &rte_flow_item_fuzzy_mask;
10739 case RTE_FLOW_ITEM_TYPE_GTP:
10740 mask = &rte_flow_item_gtp_mask;
10742 case RTE_FLOW_ITEM_TYPE_GTP_PSC:
10743 mask = &rte_flow_item_gtp_psc_mask;
10745 case RTE_FLOW_ITEM_TYPE_GENEVE:
10746 mask = &rte_flow_item_geneve_mask;
10748 case RTE_FLOW_ITEM_TYPE_GENEVE_OPT:
10749 mask = &rte_flow_item_geneve_opt_mask;
10751 case RTE_FLOW_ITEM_TYPE_PPPOE_PROTO_ID:
10752 mask = &rte_flow_item_pppoe_proto_id_mask;
10754 case RTE_FLOW_ITEM_TYPE_L2TPV3OIP:
10755 mask = &rte_flow_item_l2tpv3oip_mask;
10757 case RTE_FLOW_ITEM_TYPE_ESP:
10758 mask = &rte_flow_item_esp_mask;
10760 case RTE_FLOW_ITEM_TYPE_AH:
10761 mask = &rte_flow_item_ah_mask;
10763 case RTE_FLOW_ITEM_TYPE_PFCP:
10764 mask = &rte_flow_item_pfcp_mask;
10766 case RTE_FLOW_ITEM_TYPE_PORT_REPRESENTOR:
10767 case RTE_FLOW_ITEM_TYPE_REPRESENTED_PORT:
10768 mask = &rte_flow_item_ethdev_mask;
10770 case RTE_FLOW_ITEM_TYPE_L2TPV2:
10771 mask = &rte_flow_item_l2tpv2_mask;
10773 case RTE_FLOW_ITEM_TYPE_PPP:
10774 mask = &rte_flow_item_ppp_mask;
10782 /** Dispatch parsed buffer to function calls. */
10784 cmd_set_raw_parsed_sample(const struct buffer *in)
10786 uint32_t n = in->args.vc.actions_n;
10788 struct rte_flow_action *action = NULL;
10789 struct rte_flow_action *data = NULL;
10790 const struct rte_flow_action_rss *rss = NULL;
10792 uint16_t idx = in->port; /* We borrow port field as index */
10793 uint32_t max_size = sizeof(struct rte_flow_action) *
10794 ACTION_SAMPLE_ACTIONS_NUM;
10796 RTE_ASSERT(in->command == SET_SAMPLE_ACTIONS);
10797 data = (struct rte_flow_action *)&raw_sample_confs[idx].data;
10798 memset(data, 0x00, max_size);
10799 for (; i <= n - 1; i++) {
10800 action = in->args.vc.actions + i;
10801 if (action->type == RTE_FLOW_ACTION_TYPE_END)
10803 switch (action->type) {
10804 case RTE_FLOW_ACTION_TYPE_MARK:
10805 size = sizeof(struct rte_flow_action_mark);
10806 rte_memcpy(&sample_mark[idx],
10807 (const void *)action->conf, size);
10808 action->conf = &sample_mark[idx];
10810 case RTE_FLOW_ACTION_TYPE_COUNT:
10811 size = sizeof(struct rte_flow_action_count);
10812 rte_memcpy(&sample_count[idx],
10813 (const void *)action->conf, size);
10814 action->conf = &sample_count[idx];
10816 case RTE_FLOW_ACTION_TYPE_QUEUE:
10817 size = sizeof(struct rte_flow_action_queue);
10818 rte_memcpy(&sample_queue[idx],
10819 (const void *)action->conf, size);
10820 action->conf = &sample_queue[idx];
10822 case RTE_FLOW_ACTION_TYPE_RSS:
10823 size = sizeof(struct rte_flow_action_rss);
10824 rss = action->conf;
10825 rte_memcpy(&sample_rss_data[idx].conf,
10826 (const void *)rss, size);
10827 if (rss->key_len && rss->key) {
10828 sample_rss_data[idx].conf.key =
10829 sample_rss_data[idx].key;
10830 rte_memcpy((void *)((uintptr_t)
10831 sample_rss_data[idx].conf.key),
10832 (const void *)rss->key,
10833 sizeof(uint8_t) * rss->key_len);
10835 if (rss->queue_num && rss->queue) {
10836 sample_rss_data[idx].conf.queue =
10837 sample_rss_data[idx].queue;
10838 rte_memcpy((void *)((uintptr_t)
10839 sample_rss_data[idx].conf.queue),
10840 (const void *)rss->queue,
10841 sizeof(uint16_t) * rss->queue_num);
10843 action->conf = &sample_rss_data[idx].conf;
10845 case RTE_FLOW_ACTION_TYPE_RAW_ENCAP:
10846 size = sizeof(struct rte_flow_action_raw_encap);
10847 rte_memcpy(&sample_encap[idx],
10848 (const void *)action->conf, size);
10849 action->conf = &sample_encap[idx];
10851 case RTE_FLOW_ACTION_TYPE_PORT_ID:
10852 size = sizeof(struct rte_flow_action_port_id);
10853 rte_memcpy(&sample_port_id[idx],
10854 (const void *)action->conf, size);
10855 action->conf = &sample_port_id[idx];
10857 case RTE_FLOW_ACTION_TYPE_PF:
10859 case RTE_FLOW_ACTION_TYPE_VF:
10860 size = sizeof(struct rte_flow_action_vf);
10861 rte_memcpy(&sample_vf[idx],
10862 (const void *)action->conf, size);
10863 action->conf = &sample_vf[idx];
10865 case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:
10866 size = sizeof(struct rte_flow_action_vxlan_encap);
10867 parse_setup_vxlan_encap_data(&sample_vxlan_encap[idx]);
10868 action->conf = &sample_vxlan_encap[idx].conf;
10870 case RTE_FLOW_ACTION_TYPE_NVGRE_ENCAP:
10871 size = sizeof(struct rte_flow_action_nvgre_encap);
10872 parse_setup_nvgre_encap_data(&sample_nvgre_encap[idx]);
10873 action->conf = &sample_nvgre_encap[idx];
10876 fprintf(stderr, "Error - Not supported action\n");
10879 rte_memcpy(data, action, sizeof(struct rte_flow_action));
10884 /** Dispatch parsed buffer to function calls. */
10886 cmd_set_raw_parsed(const struct buffer *in)
10888 uint32_t n = in->args.vc.pattern_n;
10890 struct rte_flow_item *item = NULL;
10892 uint8_t *data = NULL;
10893 uint8_t *data_tail = NULL;
10894 size_t *total_size = NULL;
10895 uint16_t upper_layer = 0;
10896 uint16_t proto = 0;
10897 uint16_t idx = in->port; /* We borrow port field as index */
10898 int gtp_psc = -1; /* GTP PSC option index. */
10900 if (in->command == SET_SAMPLE_ACTIONS)
10901 return cmd_set_raw_parsed_sample(in);
10902 RTE_ASSERT(in->command == SET_RAW_ENCAP ||
10903 in->command == SET_RAW_DECAP);
10904 if (in->command == SET_RAW_ENCAP) {
10905 total_size = &raw_encap_confs[idx].size;
10906 data = (uint8_t *)&raw_encap_confs[idx].data;
10908 total_size = &raw_decap_confs[idx].size;
10909 data = (uint8_t *)&raw_decap_confs[idx].data;
10912 memset(data, 0x00, ACTION_RAW_ENCAP_MAX_DATA);
10913 /* process hdr from upper layer to low layer (L3/L4 -> L2). */
10914 data_tail = data + ACTION_RAW_ENCAP_MAX_DATA;
10915 for (i = n - 1 ; i >= 0; --i) {
10916 const struct rte_flow_item_gtp *gtp;
10917 const struct rte_flow_item_geneve_opt *opt;
10919 item = in->args.vc.pattern + i;
10920 if (item->spec == NULL)
10921 item->spec = flow_item_default_mask(item);
10922 switch (item->type) {
10923 case RTE_FLOW_ITEM_TYPE_ETH:
10924 size = sizeof(struct rte_ether_hdr);
10926 case RTE_FLOW_ITEM_TYPE_VLAN:
10927 size = sizeof(struct rte_vlan_hdr);
10928 proto = RTE_ETHER_TYPE_VLAN;
10930 case RTE_FLOW_ITEM_TYPE_IPV4:
10931 size = sizeof(struct rte_ipv4_hdr);
10932 proto = RTE_ETHER_TYPE_IPV4;
10934 case RTE_FLOW_ITEM_TYPE_IPV6:
10935 size = sizeof(struct rte_ipv6_hdr);
10936 proto = RTE_ETHER_TYPE_IPV6;
10938 case RTE_FLOW_ITEM_TYPE_UDP:
10939 size = sizeof(struct rte_udp_hdr);
10942 case RTE_FLOW_ITEM_TYPE_TCP:
10943 size = sizeof(struct rte_tcp_hdr);
10946 case RTE_FLOW_ITEM_TYPE_VXLAN:
10947 size = sizeof(struct rte_vxlan_hdr);
10949 case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
10950 size = sizeof(struct rte_vxlan_gpe_hdr);
10952 case RTE_FLOW_ITEM_TYPE_GRE:
10953 size = sizeof(struct rte_gre_hdr);
10956 case RTE_FLOW_ITEM_TYPE_GRE_KEY:
10957 size = sizeof(rte_be32_t);
10960 case RTE_FLOW_ITEM_TYPE_MPLS:
10961 size = sizeof(struct rte_mpls_hdr);
10964 case RTE_FLOW_ITEM_TYPE_NVGRE:
10965 size = sizeof(struct rte_flow_item_nvgre);
10968 case RTE_FLOW_ITEM_TYPE_GENEVE:
10969 size = sizeof(struct rte_geneve_hdr);
10971 case RTE_FLOW_ITEM_TYPE_GENEVE_OPT:
10972 opt = (const struct rte_flow_item_geneve_opt *)
10974 size = offsetof(struct rte_flow_item_geneve_opt,
10975 option_len) + sizeof(uint8_t);
10976 if (opt->option_len && opt->data) {
10977 *total_size += opt->option_len *
10979 rte_memcpy(data_tail - (*total_size),
10981 opt->option_len * sizeof(uint32_t));
10984 case RTE_FLOW_ITEM_TYPE_L2TPV3OIP:
10985 size = sizeof(rte_be32_t);
10988 case RTE_FLOW_ITEM_TYPE_ESP:
10989 size = sizeof(struct rte_esp_hdr);
10992 case RTE_FLOW_ITEM_TYPE_AH:
10993 size = sizeof(struct rte_flow_item_ah);
10996 case RTE_FLOW_ITEM_TYPE_GTP:
10998 size = sizeof(struct rte_gtp_hdr);
11001 if (gtp_psc != i + 1) {
11003 "Error - GTP PSC does not follow GTP\n");
11007 if ((gtp->v_pt_rsv_flags & 0x07) != 0x04) {
11008 /* Only E flag should be set. */
11010 "Error - GTP unsupported flags\n");
11013 struct rte_gtp_hdr_ext_word ext_word = {
11017 /* We have to add GTP header extra word. */
11018 *total_size += sizeof(ext_word);
11019 rte_memcpy(data_tail - (*total_size),
11020 &ext_word, sizeof(ext_word));
11022 size = sizeof(struct rte_gtp_hdr);
11024 case RTE_FLOW_ITEM_TYPE_GTP_PSC:
11025 if (gtp_psc >= 0) {
11027 "Error - Multiple GTP PSC items\n");
11030 const struct rte_flow_item_gtp_psc
11034 uint8_t pdu_type:4;
11038 psc.len = sizeof(psc) / 4;
11039 psc.pdu_type = opt->hdr.type;
11040 psc.qfi = opt->hdr.qfi;
11042 *total_size += sizeof(psc);
11043 rte_memcpy(data_tail - (*total_size),
11044 &psc, sizeof(psc));
11049 case RTE_FLOW_ITEM_TYPE_PFCP:
11050 size = sizeof(struct rte_flow_item_pfcp);
11052 case RTE_FLOW_ITEM_TYPE_FLEX:
11053 size = item->spec ?
11054 ((const struct rte_flow_item_flex *)
11055 item->spec)->length : 0;
11057 case RTE_FLOW_ITEM_TYPE_GRE_OPTION:
11060 const struct rte_flow_item_gre_opt
11062 if (opt->checksum_rsvd.checksum) {
11064 sizeof(opt->checksum_rsvd);
11065 rte_memcpy(data_tail - (*total_size),
11066 &opt->checksum_rsvd,
11067 sizeof(opt->checksum_rsvd));
11069 if (opt->key.key) {
11070 *total_size += sizeof(opt->key.key);
11071 rte_memcpy(data_tail - (*total_size),
11073 sizeof(opt->key.key));
11075 if (opt->sequence.sequence) {
11076 *total_size += sizeof(opt->sequence.sequence);
11077 rte_memcpy(data_tail - (*total_size),
11078 &opt->sequence.sequence,
11079 sizeof(opt->sequence.sequence));
11085 fprintf(stderr, "Error - Not supported item\n");
11088 *total_size += size;
11089 rte_memcpy(data_tail - (*total_size), item->spec, size);
11090 /* update some fields which cannot be set by cmdline */
11091 update_fields((data_tail - (*total_size)), item,
11093 upper_layer = proto;
11095 if (verbose_level & 0x1)
11096 printf("total data size is %zu\n", (*total_size));
11097 RTE_ASSERT((*total_size) <= ACTION_RAW_ENCAP_MAX_DATA);
11098 memmove(data, (data_tail - (*total_size)), *total_size);
11103 memset(data, 0x00, ACTION_RAW_ENCAP_MAX_DATA);
11106 /** Populate help strings for current token (cmdline API). */
11108 cmd_set_raw_get_help(cmdline_parse_token_hdr_t *hdr, char *dst,
11111 struct context *ctx = &cmd_flow_context;
11112 const struct token *token = &token_list[ctx->prev];
11117 /* Set token type and update global help with details. */
11118 snprintf(dst, size, "%s", (token->type ? token->type : "TOKEN"));
11120 cmd_set_raw.help_str = token->help;
11122 cmd_set_raw.help_str = token->name;
11126 /** Token definition template (cmdline API). */
11127 static struct cmdline_token_hdr cmd_set_raw_token_hdr = {
11128 .ops = &(struct cmdline_token_ops){
11129 .parse = cmd_flow_parse,
11130 .complete_get_nb = cmd_flow_complete_get_nb,
11131 .complete_get_elt = cmd_flow_complete_get_elt,
11132 .get_help = cmd_set_raw_get_help,
11137 /** Populate the next dynamic token. */
11139 cmd_set_raw_tok(cmdline_parse_token_hdr_t **hdr,
11140 cmdline_parse_token_hdr_t **hdr_inst)
11142 struct context *ctx = &cmd_flow_context;
11144 /* Always reinitialize context before requesting the first token. */
11145 if (!(hdr_inst - cmd_set_raw.tokens)) {
11146 cmd_flow_context_init(ctx);
11147 ctx->curr = START_SET;
11149 /* Return NULL when no more tokens are expected. */
11150 if (!ctx->next_num && (ctx->curr != START_SET)) {
11154 /* Determine if command should end here. */
11155 if (ctx->eol && ctx->last && ctx->next_num) {
11156 const enum index *list = ctx->next[ctx->next_num - 1];
11159 for (i = 0; list[i]; ++i) {
11160 if (list[i] != END)
11166 *hdr = &cmd_set_raw_token_hdr;
11169 /** Token generator and output processing callback (cmdline API). */
11171 cmd_set_raw_cb(void *arg0, struct cmdline *cl, void *arg2)
11174 cmd_set_raw_tok(arg0, arg2);
11176 cmd_set_raw_parsed(arg0);
11179 /** Global parser instance (cmdline API). */
11180 cmdline_parse_inst_t cmd_set_raw = {
11181 .f = cmd_set_raw_cb,
11182 .data = NULL, /**< Unused. */
11183 .help_str = NULL, /**< Updated by cmd_flow_get_help(). */
11186 }, /**< Tokens are returned by cmd_flow_tok(). */
11189 /* *** display raw_encap/raw_decap buf */
11190 struct cmd_show_set_raw_result {
11191 cmdline_fixed_string_t cmd_show;
11192 cmdline_fixed_string_t cmd_what;
11193 cmdline_fixed_string_t cmd_all;
11194 uint16_t cmd_index;
11198 cmd_show_set_raw_parsed(void *parsed_result, struct cmdline *cl, void *data)
11200 struct cmd_show_set_raw_result *res = parsed_result;
11201 uint16_t index = res->cmd_index;
11203 uint8_t *raw_data = NULL;
11204 size_t raw_size = 0;
11205 char title[16] = {0};
11208 RTE_SET_USED(data);
11209 if (!strcmp(res->cmd_all, "all")) {
11212 } else if (index >= RAW_ENCAP_CONFS_MAX_NUM) {
11213 fprintf(stderr, "index should be 0-%u\n",
11214 RAW_ENCAP_CONFS_MAX_NUM - 1);
11218 if (!strcmp(res->cmd_what, "raw_encap")) {
11219 raw_data = (uint8_t *)&raw_encap_confs[index].data;
11220 raw_size = raw_encap_confs[index].size;
11221 snprintf(title, 16, "\nindex: %u", index);
11222 rte_hexdump(stdout, title, raw_data, raw_size);
11224 raw_data = (uint8_t *)&raw_decap_confs[index].data;
11225 raw_size = raw_decap_confs[index].size;
11226 snprintf(title, 16, "\nindex: %u", index);
11227 rte_hexdump(stdout, title, raw_data, raw_size);
11229 } while (all && ++index < RAW_ENCAP_CONFS_MAX_NUM);
11232 static cmdline_parse_token_string_t cmd_show_set_raw_cmd_show =
11233 TOKEN_STRING_INITIALIZER(struct cmd_show_set_raw_result,
11235 static cmdline_parse_token_string_t cmd_show_set_raw_cmd_what =
11236 TOKEN_STRING_INITIALIZER(struct cmd_show_set_raw_result,
11237 cmd_what, "raw_encap#raw_decap");
11238 static cmdline_parse_token_num_t cmd_show_set_raw_cmd_index =
11239 TOKEN_NUM_INITIALIZER(struct cmd_show_set_raw_result,
11240 cmd_index, RTE_UINT16);
11241 static cmdline_parse_token_string_t cmd_show_set_raw_cmd_all =
11242 TOKEN_STRING_INITIALIZER(struct cmd_show_set_raw_result,
11244 cmdline_parse_inst_t cmd_show_set_raw = {
11245 .f = cmd_show_set_raw_parsed,
11247 .help_str = "show <raw_encap|raw_decap> <index>",
11249 (void *)&cmd_show_set_raw_cmd_show,
11250 (void *)&cmd_show_set_raw_cmd_what,
11251 (void *)&cmd_show_set_raw_cmd_index,
11255 cmdline_parse_inst_t cmd_show_set_raw_all = {
11256 .f = cmd_show_set_raw_parsed,
11258 .help_str = "show <raw_encap|raw_decap> all",
11260 (void *)&cmd_show_set_raw_cmd_show,
11261 (void *)&cmd_show_set_raw_cmd_what,
11262 (void *)&cmd_show_set_raw_cmd_all,