xref: /f-stack/dpdk/app/test-pmd/cmdline_flow.c (revision 2d9fd380)
1d30ea906Sjfb8856606 /* SPDX-License-Identifier: BSD-3-Clause
22bfe3f2eSlogwang  * Copyright 2016 6WIND S.A.
3d30ea906Sjfb8856606  * Copyright 2016 Mellanox Technologies, Ltd
42bfe3f2eSlogwang  */
52bfe3f2eSlogwang 
62bfe3f2eSlogwang #include <stddef.h>
72bfe3f2eSlogwang #include <stdint.h>
82bfe3f2eSlogwang #include <stdio.h>
92bfe3f2eSlogwang #include <inttypes.h>
102bfe3f2eSlogwang #include <errno.h>
112bfe3f2eSlogwang #include <ctype.h>
122bfe3f2eSlogwang #include <string.h>
132bfe3f2eSlogwang #include <arpa/inet.h>
142bfe3f2eSlogwang #include <sys/socket.h>
152bfe3f2eSlogwang 
164418919fSjohnjiang #include <rte_string_fns.h>
172bfe3f2eSlogwang #include <rte_common.h>
182bfe3f2eSlogwang #include <rte_ethdev.h>
192bfe3f2eSlogwang #include <rte_byteorder.h>
202bfe3f2eSlogwang #include <cmdline_parse.h>
212bfe3f2eSlogwang #include <cmdline_parse_etheraddr.h>
224418919fSjohnjiang #include <cmdline_parse_string.h>
234418919fSjohnjiang #include <cmdline_parse_num.h>
242bfe3f2eSlogwang #include <rte_flow.h>
254418919fSjohnjiang #include <rte_hexdump.h>
26*2d9fd380Sjfb8856606 #include <rte_vxlan.h>
27*2d9fd380Sjfb8856606 #include <rte_gre.h>
28*2d9fd380Sjfb8856606 #include <rte_mpls.h>
29*2d9fd380Sjfb8856606 #include <rte_gtp.h>
30*2d9fd380Sjfb8856606 #include <rte_geneve.h>
312bfe3f2eSlogwang 
322bfe3f2eSlogwang #include "testpmd.h"
332bfe3f2eSlogwang 
342bfe3f2eSlogwang /** Parser token indices. */
352bfe3f2eSlogwang enum index {
362bfe3f2eSlogwang 	/* Special tokens. */
372bfe3f2eSlogwang 	ZERO = 0,
382bfe3f2eSlogwang 	END,
394418919fSjohnjiang 	START_SET,
404418919fSjohnjiang 	END_SET,
412bfe3f2eSlogwang 
422bfe3f2eSlogwang 	/* Common tokens. */
432bfe3f2eSlogwang 	INTEGER,
442bfe3f2eSlogwang 	UNSIGNED,
452bfe3f2eSlogwang 	PREFIX,
462bfe3f2eSlogwang 	BOOLEAN,
472bfe3f2eSlogwang 	STRING,
481646932aSjfb8856606 	HEX,
49*2d9fd380Sjfb8856606 	FILE_PATH,
502bfe3f2eSlogwang 	MAC_ADDR,
512bfe3f2eSlogwang 	IPV4_ADDR,
522bfe3f2eSlogwang 	IPV6_ADDR,
532bfe3f2eSlogwang 	RULE_ID,
542bfe3f2eSlogwang 	PORT_ID,
552bfe3f2eSlogwang 	GROUP_ID,
562bfe3f2eSlogwang 	PRIORITY_LEVEL,
57*2d9fd380Sjfb8856606 	SHARED_ACTION_ID,
582bfe3f2eSlogwang 
592bfe3f2eSlogwang 	/* Top-level command. */
604418919fSjohnjiang 	SET,
614418919fSjohnjiang 	/* Sub-leve commands. */
624418919fSjohnjiang 	SET_RAW_ENCAP,
634418919fSjohnjiang 	SET_RAW_DECAP,
644418919fSjohnjiang 	SET_RAW_INDEX,
65*2d9fd380Sjfb8856606 	SET_SAMPLE_ACTIONS,
66*2d9fd380Sjfb8856606 	SET_SAMPLE_INDEX,
672bfe3f2eSlogwang 
684418919fSjohnjiang 	/* Top-level command. */
694418919fSjohnjiang 	FLOW,
702bfe3f2eSlogwang 	/* Sub-level commands. */
71*2d9fd380Sjfb8856606 	SHARED_ACTION,
722bfe3f2eSlogwang 	VALIDATE,
732bfe3f2eSlogwang 	CREATE,
742bfe3f2eSlogwang 	DESTROY,
752bfe3f2eSlogwang 	FLUSH,
76*2d9fd380Sjfb8856606 	DUMP,
772bfe3f2eSlogwang 	QUERY,
782bfe3f2eSlogwang 	LIST,
79*2d9fd380Sjfb8856606 	AGED,
802bfe3f2eSlogwang 	ISOLATE,
81*2d9fd380Sjfb8856606 	TUNNEL,
82*2d9fd380Sjfb8856606 
83*2d9fd380Sjfb8856606 	/* Tunnel arguments. */
84*2d9fd380Sjfb8856606 	TUNNEL_CREATE,
85*2d9fd380Sjfb8856606 	TUNNEL_CREATE_TYPE,
86*2d9fd380Sjfb8856606 	TUNNEL_LIST,
87*2d9fd380Sjfb8856606 	TUNNEL_DESTROY,
88*2d9fd380Sjfb8856606 	TUNNEL_DESTROY_ID,
892bfe3f2eSlogwang 
902bfe3f2eSlogwang 	/* Destroy arguments. */
912bfe3f2eSlogwang 	DESTROY_RULE,
922bfe3f2eSlogwang 
932bfe3f2eSlogwang 	/* Query arguments. */
942bfe3f2eSlogwang 	QUERY_ACTION,
952bfe3f2eSlogwang 
962bfe3f2eSlogwang 	/* List arguments. */
972bfe3f2eSlogwang 	LIST_GROUP,
982bfe3f2eSlogwang 
99*2d9fd380Sjfb8856606 	/* Destroy aged flow arguments. */
100*2d9fd380Sjfb8856606 	AGED_DESTROY,
101*2d9fd380Sjfb8856606 
1022bfe3f2eSlogwang 	/* Validate/create arguments. */
1032bfe3f2eSlogwang 	GROUP,
1042bfe3f2eSlogwang 	PRIORITY,
1052bfe3f2eSlogwang 	INGRESS,
1062bfe3f2eSlogwang 	EGRESS,
107d30ea906Sjfb8856606 	TRANSFER,
108*2d9fd380Sjfb8856606 	TUNNEL_SET,
109*2d9fd380Sjfb8856606 	TUNNEL_MATCH,
110*2d9fd380Sjfb8856606 
111*2d9fd380Sjfb8856606 	/* Shared action arguments */
112*2d9fd380Sjfb8856606 	SHARED_ACTION_CREATE,
113*2d9fd380Sjfb8856606 	SHARED_ACTION_UPDATE,
114*2d9fd380Sjfb8856606 	SHARED_ACTION_DESTROY,
115*2d9fd380Sjfb8856606 	SHARED_ACTION_QUERY,
116*2d9fd380Sjfb8856606 
117*2d9fd380Sjfb8856606 	/* Shared action create arguments */
118*2d9fd380Sjfb8856606 	SHARED_ACTION_CREATE_ID,
119*2d9fd380Sjfb8856606 	SHARED_ACTION_INGRESS,
120*2d9fd380Sjfb8856606 	SHARED_ACTION_EGRESS,
121*2d9fd380Sjfb8856606 	SHARED_ACTION_TRANSFER,
122*2d9fd380Sjfb8856606 	SHARED_ACTION_SPEC,
123*2d9fd380Sjfb8856606 
124*2d9fd380Sjfb8856606 	/* Shared action destroy arguments */
125*2d9fd380Sjfb8856606 	SHARED_ACTION_DESTROY_ID,
1262bfe3f2eSlogwang 
1272bfe3f2eSlogwang 	/* Validate/create pattern. */
1282bfe3f2eSlogwang 	PATTERN,
1292bfe3f2eSlogwang 	ITEM_PARAM_IS,
1302bfe3f2eSlogwang 	ITEM_PARAM_SPEC,
1312bfe3f2eSlogwang 	ITEM_PARAM_LAST,
1322bfe3f2eSlogwang 	ITEM_PARAM_MASK,
1332bfe3f2eSlogwang 	ITEM_PARAM_PREFIX,
1342bfe3f2eSlogwang 	ITEM_NEXT,
1352bfe3f2eSlogwang 	ITEM_END,
1362bfe3f2eSlogwang 	ITEM_VOID,
1372bfe3f2eSlogwang 	ITEM_INVERT,
1382bfe3f2eSlogwang 	ITEM_ANY,
1392bfe3f2eSlogwang 	ITEM_ANY_NUM,
1402bfe3f2eSlogwang 	ITEM_PF,
1412bfe3f2eSlogwang 	ITEM_VF,
1422bfe3f2eSlogwang 	ITEM_VF_ID,
143d30ea906Sjfb8856606 	ITEM_PHY_PORT,
144d30ea906Sjfb8856606 	ITEM_PHY_PORT_INDEX,
145d30ea906Sjfb8856606 	ITEM_PORT_ID,
146d30ea906Sjfb8856606 	ITEM_PORT_ID_ID,
147d30ea906Sjfb8856606 	ITEM_MARK,
148d30ea906Sjfb8856606 	ITEM_MARK_ID,
1492bfe3f2eSlogwang 	ITEM_RAW,
1502bfe3f2eSlogwang 	ITEM_RAW_RELATIVE,
1512bfe3f2eSlogwang 	ITEM_RAW_SEARCH,
1522bfe3f2eSlogwang 	ITEM_RAW_OFFSET,
1532bfe3f2eSlogwang 	ITEM_RAW_LIMIT,
1542bfe3f2eSlogwang 	ITEM_RAW_PATTERN,
1552bfe3f2eSlogwang 	ITEM_ETH,
1562bfe3f2eSlogwang 	ITEM_ETH_DST,
1572bfe3f2eSlogwang 	ITEM_ETH_SRC,
1582bfe3f2eSlogwang 	ITEM_ETH_TYPE,
159*2d9fd380Sjfb8856606 	ITEM_ETH_HAS_VLAN,
1602bfe3f2eSlogwang 	ITEM_VLAN,
1612bfe3f2eSlogwang 	ITEM_VLAN_TCI,
1622bfe3f2eSlogwang 	ITEM_VLAN_PCP,
1632bfe3f2eSlogwang 	ITEM_VLAN_DEI,
1642bfe3f2eSlogwang 	ITEM_VLAN_VID,
165d30ea906Sjfb8856606 	ITEM_VLAN_INNER_TYPE,
166*2d9fd380Sjfb8856606 	ITEM_VLAN_HAS_MORE_VLAN,
1672bfe3f2eSlogwang 	ITEM_IPV4,
1682bfe3f2eSlogwang 	ITEM_IPV4_TOS,
169*2d9fd380Sjfb8856606 	ITEM_IPV4_FRAGMENT_OFFSET,
1702bfe3f2eSlogwang 	ITEM_IPV4_TTL,
1712bfe3f2eSlogwang 	ITEM_IPV4_PROTO,
1722bfe3f2eSlogwang 	ITEM_IPV4_SRC,
1732bfe3f2eSlogwang 	ITEM_IPV4_DST,
1742bfe3f2eSlogwang 	ITEM_IPV6,
1752bfe3f2eSlogwang 	ITEM_IPV6_TC,
1762bfe3f2eSlogwang 	ITEM_IPV6_FLOW,
1772bfe3f2eSlogwang 	ITEM_IPV6_PROTO,
1782bfe3f2eSlogwang 	ITEM_IPV6_HOP,
1792bfe3f2eSlogwang 	ITEM_IPV6_SRC,
1802bfe3f2eSlogwang 	ITEM_IPV6_DST,
181*2d9fd380Sjfb8856606 	ITEM_IPV6_HAS_FRAG_EXT,
1822bfe3f2eSlogwang 	ITEM_ICMP,
1832bfe3f2eSlogwang 	ITEM_ICMP_TYPE,
1842bfe3f2eSlogwang 	ITEM_ICMP_CODE,
185*2d9fd380Sjfb8856606 	ITEM_ICMP_IDENT,
186*2d9fd380Sjfb8856606 	ITEM_ICMP_SEQ,
1872bfe3f2eSlogwang 	ITEM_UDP,
1882bfe3f2eSlogwang 	ITEM_UDP_SRC,
1892bfe3f2eSlogwang 	ITEM_UDP_DST,
1902bfe3f2eSlogwang 	ITEM_TCP,
1912bfe3f2eSlogwang 	ITEM_TCP_SRC,
1922bfe3f2eSlogwang 	ITEM_TCP_DST,
1932bfe3f2eSlogwang 	ITEM_TCP_FLAGS,
1942bfe3f2eSlogwang 	ITEM_SCTP,
1952bfe3f2eSlogwang 	ITEM_SCTP_SRC,
1962bfe3f2eSlogwang 	ITEM_SCTP_DST,
1972bfe3f2eSlogwang 	ITEM_SCTP_TAG,
1982bfe3f2eSlogwang 	ITEM_SCTP_CKSUM,
1992bfe3f2eSlogwang 	ITEM_VXLAN,
2002bfe3f2eSlogwang 	ITEM_VXLAN_VNI,
2012bfe3f2eSlogwang 	ITEM_E_TAG,
2022bfe3f2eSlogwang 	ITEM_E_TAG_GRP_ECID_B,
2032bfe3f2eSlogwang 	ITEM_NVGRE,
2042bfe3f2eSlogwang 	ITEM_NVGRE_TNI,
2052bfe3f2eSlogwang 	ITEM_MPLS,
2062bfe3f2eSlogwang 	ITEM_MPLS_LABEL,
2074418919fSjohnjiang 	ITEM_MPLS_TC,
2084418919fSjohnjiang 	ITEM_MPLS_S,
2092bfe3f2eSlogwang 	ITEM_GRE,
2102bfe3f2eSlogwang 	ITEM_GRE_PROTO,
2114418919fSjohnjiang 	ITEM_GRE_C_RSVD0_VER,
2124418919fSjohnjiang 	ITEM_GRE_C_BIT,
2134418919fSjohnjiang 	ITEM_GRE_K_BIT,
2144418919fSjohnjiang 	ITEM_GRE_S_BIT,
2152bfe3f2eSlogwang 	ITEM_FUZZY,
2162bfe3f2eSlogwang 	ITEM_FUZZY_THRESH,
2172bfe3f2eSlogwang 	ITEM_GTP,
218*2d9fd380Sjfb8856606 	ITEM_GTP_FLAGS,
219*2d9fd380Sjfb8856606 	ITEM_GTP_MSG_TYPE,
2202bfe3f2eSlogwang 	ITEM_GTP_TEID,
2212bfe3f2eSlogwang 	ITEM_GTPC,
2222bfe3f2eSlogwang 	ITEM_GTPU,
223d30ea906Sjfb8856606 	ITEM_GENEVE,
224d30ea906Sjfb8856606 	ITEM_GENEVE_VNI,
225d30ea906Sjfb8856606 	ITEM_GENEVE_PROTO,
226d30ea906Sjfb8856606 	ITEM_VXLAN_GPE,
227d30ea906Sjfb8856606 	ITEM_VXLAN_GPE_VNI,
228d30ea906Sjfb8856606 	ITEM_ARP_ETH_IPV4,
229d30ea906Sjfb8856606 	ITEM_ARP_ETH_IPV4_SHA,
230d30ea906Sjfb8856606 	ITEM_ARP_ETH_IPV4_SPA,
231d30ea906Sjfb8856606 	ITEM_ARP_ETH_IPV4_THA,
232d30ea906Sjfb8856606 	ITEM_ARP_ETH_IPV4_TPA,
233d30ea906Sjfb8856606 	ITEM_IPV6_EXT,
234d30ea906Sjfb8856606 	ITEM_IPV6_EXT_NEXT_HDR,
235*2d9fd380Sjfb8856606 	ITEM_IPV6_FRAG_EXT,
236*2d9fd380Sjfb8856606 	ITEM_IPV6_FRAG_EXT_NEXT_HDR,
237*2d9fd380Sjfb8856606 	ITEM_IPV6_FRAG_EXT_FRAG_DATA,
238d30ea906Sjfb8856606 	ITEM_ICMP6,
239d30ea906Sjfb8856606 	ITEM_ICMP6_TYPE,
240d30ea906Sjfb8856606 	ITEM_ICMP6_CODE,
241d30ea906Sjfb8856606 	ITEM_ICMP6_ND_NS,
242d30ea906Sjfb8856606 	ITEM_ICMP6_ND_NS_TARGET_ADDR,
243d30ea906Sjfb8856606 	ITEM_ICMP6_ND_NA,
244d30ea906Sjfb8856606 	ITEM_ICMP6_ND_NA_TARGET_ADDR,
245d30ea906Sjfb8856606 	ITEM_ICMP6_ND_OPT,
246d30ea906Sjfb8856606 	ITEM_ICMP6_ND_OPT_TYPE,
247d30ea906Sjfb8856606 	ITEM_ICMP6_ND_OPT_SLA_ETH,
248d30ea906Sjfb8856606 	ITEM_ICMP6_ND_OPT_SLA_ETH_SLA,
249d30ea906Sjfb8856606 	ITEM_ICMP6_ND_OPT_TLA_ETH,
250d30ea906Sjfb8856606 	ITEM_ICMP6_ND_OPT_TLA_ETH_TLA,
251d30ea906Sjfb8856606 	ITEM_META,
252d30ea906Sjfb8856606 	ITEM_META_DATA,
2534418919fSjohnjiang 	ITEM_GRE_KEY,
2544418919fSjohnjiang 	ITEM_GRE_KEY_VALUE,
2554418919fSjohnjiang 	ITEM_GTP_PSC,
2564418919fSjohnjiang 	ITEM_GTP_PSC_QFI,
2574418919fSjohnjiang 	ITEM_GTP_PSC_PDU_T,
2584418919fSjohnjiang 	ITEM_PPPOES,
2594418919fSjohnjiang 	ITEM_PPPOED,
2604418919fSjohnjiang 	ITEM_PPPOE_SEID,
2614418919fSjohnjiang 	ITEM_PPPOE_PROTO_ID,
2624418919fSjohnjiang 	ITEM_HIGIG2,
2634418919fSjohnjiang 	ITEM_HIGIG2_CLASSIFICATION,
2644418919fSjohnjiang 	ITEM_HIGIG2_VID,
2654418919fSjohnjiang 	ITEM_TAG,
2664418919fSjohnjiang 	ITEM_TAG_DATA,
2674418919fSjohnjiang 	ITEM_TAG_INDEX,
268*2d9fd380Sjfb8856606 	ITEM_L2TPV3OIP,
269*2d9fd380Sjfb8856606 	ITEM_L2TPV3OIP_SESSION_ID,
270*2d9fd380Sjfb8856606 	ITEM_ESP,
271*2d9fd380Sjfb8856606 	ITEM_ESP_SPI,
272*2d9fd380Sjfb8856606 	ITEM_AH,
273*2d9fd380Sjfb8856606 	ITEM_AH_SPI,
274*2d9fd380Sjfb8856606 	ITEM_PFCP,
275*2d9fd380Sjfb8856606 	ITEM_PFCP_S_FIELD,
276*2d9fd380Sjfb8856606 	ITEM_PFCP_SEID,
277*2d9fd380Sjfb8856606 	ITEM_ECPRI,
278*2d9fd380Sjfb8856606 	ITEM_ECPRI_COMMON,
279*2d9fd380Sjfb8856606 	ITEM_ECPRI_COMMON_TYPE,
280*2d9fd380Sjfb8856606 	ITEM_ECPRI_COMMON_TYPE_IQ_DATA,
281*2d9fd380Sjfb8856606 	ITEM_ECPRI_COMMON_TYPE_RTC_CTRL,
282*2d9fd380Sjfb8856606 	ITEM_ECPRI_COMMON_TYPE_DLY_MSR,
283*2d9fd380Sjfb8856606 	ITEM_ECPRI_MSG_IQ_DATA_PCID,
284*2d9fd380Sjfb8856606 	ITEM_ECPRI_MSG_RTC_CTRL_RTCID,
285*2d9fd380Sjfb8856606 	ITEM_ECPRI_MSG_DLY_MSR_MSRID,
2862bfe3f2eSlogwang 
2872bfe3f2eSlogwang 	/* Validate/create actions. */
2882bfe3f2eSlogwang 	ACTIONS,
2892bfe3f2eSlogwang 	ACTION_NEXT,
2902bfe3f2eSlogwang 	ACTION_END,
2912bfe3f2eSlogwang 	ACTION_VOID,
2922bfe3f2eSlogwang 	ACTION_PASSTHRU,
293d30ea906Sjfb8856606 	ACTION_JUMP,
294d30ea906Sjfb8856606 	ACTION_JUMP_GROUP,
2952bfe3f2eSlogwang 	ACTION_MARK,
2962bfe3f2eSlogwang 	ACTION_MARK_ID,
2972bfe3f2eSlogwang 	ACTION_FLAG,
2982bfe3f2eSlogwang 	ACTION_QUEUE,
2992bfe3f2eSlogwang 	ACTION_QUEUE_INDEX,
3002bfe3f2eSlogwang 	ACTION_DROP,
3012bfe3f2eSlogwang 	ACTION_COUNT,
302d30ea906Sjfb8856606 	ACTION_COUNT_SHARED,
303d30ea906Sjfb8856606 	ACTION_COUNT_ID,
3042bfe3f2eSlogwang 	ACTION_RSS,
305d30ea906Sjfb8856606 	ACTION_RSS_FUNC,
306d30ea906Sjfb8856606 	ACTION_RSS_LEVEL,
307d30ea906Sjfb8856606 	ACTION_RSS_FUNC_DEFAULT,
308d30ea906Sjfb8856606 	ACTION_RSS_FUNC_TOEPLITZ,
309d30ea906Sjfb8856606 	ACTION_RSS_FUNC_SIMPLE_XOR,
3104418919fSjohnjiang 	ACTION_RSS_FUNC_SYMMETRIC_TOEPLITZ,
311d30ea906Sjfb8856606 	ACTION_RSS_TYPES,
312d30ea906Sjfb8856606 	ACTION_RSS_TYPE,
313d30ea906Sjfb8856606 	ACTION_RSS_KEY,
314d30ea906Sjfb8856606 	ACTION_RSS_KEY_LEN,
3152bfe3f2eSlogwang 	ACTION_RSS_QUEUES,
3162bfe3f2eSlogwang 	ACTION_RSS_QUEUE,
3172bfe3f2eSlogwang 	ACTION_PF,
3182bfe3f2eSlogwang 	ACTION_VF,
3192bfe3f2eSlogwang 	ACTION_VF_ORIGINAL,
3202bfe3f2eSlogwang 	ACTION_VF_ID,
321d30ea906Sjfb8856606 	ACTION_PHY_PORT,
322d30ea906Sjfb8856606 	ACTION_PHY_PORT_ORIGINAL,
323d30ea906Sjfb8856606 	ACTION_PHY_PORT_INDEX,
324d30ea906Sjfb8856606 	ACTION_PORT_ID,
325d30ea906Sjfb8856606 	ACTION_PORT_ID_ORIGINAL,
326d30ea906Sjfb8856606 	ACTION_PORT_ID_ID,
3272bfe3f2eSlogwang 	ACTION_METER,
3282bfe3f2eSlogwang 	ACTION_METER_ID,
329d30ea906Sjfb8856606 	ACTION_OF_SET_MPLS_TTL,
330d30ea906Sjfb8856606 	ACTION_OF_SET_MPLS_TTL_MPLS_TTL,
331d30ea906Sjfb8856606 	ACTION_OF_DEC_MPLS_TTL,
332d30ea906Sjfb8856606 	ACTION_OF_SET_NW_TTL,
333d30ea906Sjfb8856606 	ACTION_OF_SET_NW_TTL_NW_TTL,
334d30ea906Sjfb8856606 	ACTION_OF_DEC_NW_TTL,
335d30ea906Sjfb8856606 	ACTION_OF_COPY_TTL_OUT,
336d30ea906Sjfb8856606 	ACTION_OF_COPY_TTL_IN,
337d30ea906Sjfb8856606 	ACTION_OF_POP_VLAN,
338d30ea906Sjfb8856606 	ACTION_OF_PUSH_VLAN,
339d30ea906Sjfb8856606 	ACTION_OF_PUSH_VLAN_ETHERTYPE,
340d30ea906Sjfb8856606 	ACTION_OF_SET_VLAN_VID,
341d30ea906Sjfb8856606 	ACTION_OF_SET_VLAN_VID_VLAN_VID,
342d30ea906Sjfb8856606 	ACTION_OF_SET_VLAN_PCP,
343d30ea906Sjfb8856606 	ACTION_OF_SET_VLAN_PCP_VLAN_PCP,
344d30ea906Sjfb8856606 	ACTION_OF_POP_MPLS,
345d30ea906Sjfb8856606 	ACTION_OF_POP_MPLS_ETHERTYPE,
346d30ea906Sjfb8856606 	ACTION_OF_PUSH_MPLS,
347d30ea906Sjfb8856606 	ACTION_OF_PUSH_MPLS_ETHERTYPE,
348d30ea906Sjfb8856606 	ACTION_VXLAN_ENCAP,
349d30ea906Sjfb8856606 	ACTION_VXLAN_DECAP,
350d30ea906Sjfb8856606 	ACTION_NVGRE_ENCAP,
351d30ea906Sjfb8856606 	ACTION_NVGRE_DECAP,
352d30ea906Sjfb8856606 	ACTION_L2_ENCAP,
353d30ea906Sjfb8856606 	ACTION_L2_DECAP,
354d30ea906Sjfb8856606 	ACTION_MPLSOGRE_ENCAP,
355d30ea906Sjfb8856606 	ACTION_MPLSOGRE_DECAP,
356d30ea906Sjfb8856606 	ACTION_MPLSOUDP_ENCAP,
357d30ea906Sjfb8856606 	ACTION_MPLSOUDP_DECAP,
358d30ea906Sjfb8856606 	ACTION_SET_IPV4_SRC,
359d30ea906Sjfb8856606 	ACTION_SET_IPV4_SRC_IPV4_SRC,
360d30ea906Sjfb8856606 	ACTION_SET_IPV4_DST,
361d30ea906Sjfb8856606 	ACTION_SET_IPV4_DST_IPV4_DST,
362d30ea906Sjfb8856606 	ACTION_SET_IPV6_SRC,
363d30ea906Sjfb8856606 	ACTION_SET_IPV6_SRC_IPV6_SRC,
364d30ea906Sjfb8856606 	ACTION_SET_IPV6_DST,
365d30ea906Sjfb8856606 	ACTION_SET_IPV6_DST_IPV6_DST,
366d30ea906Sjfb8856606 	ACTION_SET_TP_SRC,
367d30ea906Sjfb8856606 	ACTION_SET_TP_SRC_TP_SRC,
368d30ea906Sjfb8856606 	ACTION_SET_TP_DST,
369d30ea906Sjfb8856606 	ACTION_SET_TP_DST_TP_DST,
370d30ea906Sjfb8856606 	ACTION_MAC_SWAP,
371d30ea906Sjfb8856606 	ACTION_DEC_TTL,
372d30ea906Sjfb8856606 	ACTION_SET_TTL,
373d30ea906Sjfb8856606 	ACTION_SET_TTL_TTL,
374d30ea906Sjfb8856606 	ACTION_SET_MAC_SRC,
375d30ea906Sjfb8856606 	ACTION_SET_MAC_SRC_MAC_SRC,
376d30ea906Sjfb8856606 	ACTION_SET_MAC_DST,
377d30ea906Sjfb8856606 	ACTION_SET_MAC_DST_MAC_DST,
3784418919fSjohnjiang 	ACTION_INC_TCP_SEQ,
3794418919fSjohnjiang 	ACTION_INC_TCP_SEQ_VALUE,
3804418919fSjohnjiang 	ACTION_DEC_TCP_SEQ,
3814418919fSjohnjiang 	ACTION_DEC_TCP_SEQ_VALUE,
3824418919fSjohnjiang 	ACTION_INC_TCP_ACK,
3834418919fSjohnjiang 	ACTION_INC_TCP_ACK_VALUE,
3844418919fSjohnjiang 	ACTION_DEC_TCP_ACK,
3854418919fSjohnjiang 	ACTION_DEC_TCP_ACK_VALUE,
3864418919fSjohnjiang 	ACTION_RAW_ENCAP,
3874418919fSjohnjiang 	ACTION_RAW_DECAP,
3884418919fSjohnjiang 	ACTION_RAW_ENCAP_INDEX,
3894418919fSjohnjiang 	ACTION_RAW_ENCAP_INDEX_VALUE,
3904418919fSjohnjiang 	ACTION_RAW_DECAP_INDEX,
3914418919fSjohnjiang 	ACTION_RAW_DECAP_INDEX_VALUE,
3924418919fSjohnjiang 	ACTION_SET_TAG,
3934418919fSjohnjiang 	ACTION_SET_TAG_DATA,
3944418919fSjohnjiang 	ACTION_SET_TAG_INDEX,
3954418919fSjohnjiang 	ACTION_SET_TAG_MASK,
3964418919fSjohnjiang 	ACTION_SET_META,
3974418919fSjohnjiang 	ACTION_SET_META_DATA,
3984418919fSjohnjiang 	ACTION_SET_META_MASK,
399*2d9fd380Sjfb8856606 	ACTION_SET_IPV4_DSCP,
400*2d9fd380Sjfb8856606 	ACTION_SET_IPV4_DSCP_VALUE,
401*2d9fd380Sjfb8856606 	ACTION_SET_IPV6_DSCP,
402*2d9fd380Sjfb8856606 	ACTION_SET_IPV6_DSCP_VALUE,
403*2d9fd380Sjfb8856606 	ACTION_AGE,
404*2d9fd380Sjfb8856606 	ACTION_AGE_TIMEOUT,
405*2d9fd380Sjfb8856606 	ACTION_SAMPLE,
406*2d9fd380Sjfb8856606 	ACTION_SAMPLE_RATIO,
407*2d9fd380Sjfb8856606 	ACTION_SAMPLE_INDEX,
408*2d9fd380Sjfb8856606 	ACTION_SAMPLE_INDEX_VALUE,
409*2d9fd380Sjfb8856606 	ACTION_SHARED,
410*2d9fd380Sjfb8856606 	SHARED_ACTION_ID2PTR,
4112bfe3f2eSlogwang };
4122bfe3f2eSlogwang 
413d30ea906Sjfb8856606 /** Maximum size for pattern in struct rte_flow_item_raw. */
414d30ea906Sjfb8856606 #define ITEM_RAW_PATTERN_SIZE 40
4152bfe3f2eSlogwang 
4162bfe3f2eSlogwang /** Storage size for struct rte_flow_item_raw including pattern. */
4172bfe3f2eSlogwang #define ITEM_RAW_SIZE \
418d30ea906Sjfb8856606 	(sizeof(struct rte_flow_item_raw) + ITEM_RAW_PATTERN_SIZE)
4192bfe3f2eSlogwang 
420d30ea906Sjfb8856606 /** Maximum number of queue indices in struct rte_flow_action_rss. */
4214418919fSjohnjiang #define ACTION_RSS_QUEUE_NUM 128
4222bfe3f2eSlogwang 
423d30ea906Sjfb8856606 /** Storage for struct rte_flow_action_rss including external data. */
424d30ea906Sjfb8856606 struct action_rss_data {
425d30ea906Sjfb8856606 	struct rte_flow_action_rss conf;
426d30ea906Sjfb8856606 	uint8_t key[RSS_HASH_KEY_LENGTH];
427d30ea906Sjfb8856606 	uint16_t queue[ACTION_RSS_QUEUE_NUM];
428d30ea906Sjfb8856606 };
429d30ea906Sjfb8856606 
4304418919fSjohnjiang /** Maximum data size in struct rte_flow_action_raw_encap. */
4314418919fSjohnjiang #define ACTION_RAW_ENCAP_MAX_DATA 128
4324418919fSjohnjiang #define RAW_ENCAP_CONFS_MAX_NUM 8
4334418919fSjohnjiang 
4344418919fSjohnjiang /** Storage for struct rte_flow_action_raw_encap. */
4354418919fSjohnjiang struct raw_encap_conf {
4364418919fSjohnjiang 	uint8_t data[ACTION_RAW_ENCAP_MAX_DATA];
4374418919fSjohnjiang 	uint8_t preserve[ACTION_RAW_ENCAP_MAX_DATA];
4384418919fSjohnjiang 	size_t size;
4394418919fSjohnjiang };
4404418919fSjohnjiang 
4414418919fSjohnjiang struct raw_encap_conf raw_encap_confs[RAW_ENCAP_CONFS_MAX_NUM];
4424418919fSjohnjiang 
4434418919fSjohnjiang /** Storage for struct rte_flow_action_raw_encap including external data. */
4444418919fSjohnjiang struct action_raw_encap_data {
4454418919fSjohnjiang 	struct rte_flow_action_raw_encap conf;
4464418919fSjohnjiang 	uint8_t data[ACTION_RAW_ENCAP_MAX_DATA];
4474418919fSjohnjiang 	uint8_t preserve[ACTION_RAW_ENCAP_MAX_DATA];
4484418919fSjohnjiang 	uint16_t idx;
4494418919fSjohnjiang };
4504418919fSjohnjiang 
4514418919fSjohnjiang /** Storage for struct rte_flow_action_raw_decap. */
4524418919fSjohnjiang struct raw_decap_conf {
4534418919fSjohnjiang 	uint8_t data[ACTION_RAW_ENCAP_MAX_DATA];
4544418919fSjohnjiang 	size_t size;
4554418919fSjohnjiang };
4564418919fSjohnjiang 
4574418919fSjohnjiang struct raw_decap_conf raw_decap_confs[RAW_ENCAP_CONFS_MAX_NUM];
4584418919fSjohnjiang 
4594418919fSjohnjiang /** Storage for struct rte_flow_action_raw_decap including external data. */
4604418919fSjohnjiang struct action_raw_decap_data {
4614418919fSjohnjiang 	struct rte_flow_action_raw_decap conf;
4624418919fSjohnjiang 	uint8_t data[ACTION_RAW_ENCAP_MAX_DATA];
4634418919fSjohnjiang 	uint16_t idx;
4644418919fSjohnjiang };
4654418919fSjohnjiang 
4664418919fSjohnjiang struct vxlan_encap_conf vxlan_encap_conf = {
4674418919fSjohnjiang 	.select_ipv4 = 1,
4684418919fSjohnjiang 	.select_vlan = 0,
4694418919fSjohnjiang 	.select_tos_ttl = 0,
4704418919fSjohnjiang 	.vni = "\x00\x00\x00",
4714418919fSjohnjiang 	.udp_src = 0,
472*2d9fd380Sjfb8856606 	.udp_dst = RTE_BE16(RTE_VXLAN_DEFAULT_PORT),
4734418919fSjohnjiang 	.ipv4_src = RTE_IPV4(127, 0, 0, 1),
4744418919fSjohnjiang 	.ipv4_dst = RTE_IPV4(255, 255, 255, 255),
4754418919fSjohnjiang 	.ipv6_src = "\x00\x00\x00\x00\x00\x00\x00\x00"
4764418919fSjohnjiang 		"\x00\x00\x00\x00\x00\x00\x00\x01",
4774418919fSjohnjiang 	.ipv6_dst = "\x00\x00\x00\x00\x00\x00\x00\x00"
4784418919fSjohnjiang 		"\x00\x00\x00\x00\x00\x00\x11\x11",
4794418919fSjohnjiang 	.vlan_tci = 0,
4804418919fSjohnjiang 	.ip_tos = 0,
4814418919fSjohnjiang 	.ip_ttl = 255,
4824418919fSjohnjiang 	.eth_src = "\x00\x00\x00\x00\x00\x00",
4834418919fSjohnjiang 	.eth_dst = "\xff\xff\xff\xff\xff\xff",
4844418919fSjohnjiang };
4854418919fSjohnjiang 
486d30ea906Sjfb8856606 /** Maximum number of items in struct rte_flow_action_vxlan_encap. */
487d30ea906Sjfb8856606 #define ACTION_VXLAN_ENCAP_ITEMS_NUM 6
488d30ea906Sjfb8856606 
489d30ea906Sjfb8856606 /** Storage for struct rte_flow_action_vxlan_encap including external data. */
490d30ea906Sjfb8856606 struct action_vxlan_encap_data {
491d30ea906Sjfb8856606 	struct rte_flow_action_vxlan_encap conf;
492d30ea906Sjfb8856606 	struct rte_flow_item items[ACTION_VXLAN_ENCAP_ITEMS_NUM];
493d30ea906Sjfb8856606 	struct rte_flow_item_eth item_eth;
494d30ea906Sjfb8856606 	struct rte_flow_item_vlan item_vlan;
495d30ea906Sjfb8856606 	union {
496d30ea906Sjfb8856606 		struct rte_flow_item_ipv4 item_ipv4;
497d30ea906Sjfb8856606 		struct rte_flow_item_ipv6 item_ipv6;
498d30ea906Sjfb8856606 	};
499d30ea906Sjfb8856606 	struct rte_flow_item_udp item_udp;
500d30ea906Sjfb8856606 	struct rte_flow_item_vxlan item_vxlan;
501d30ea906Sjfb8856606 };
502d30ea906Sjfb8856606 
5034418919fSjohnjiang struct nvgre_encap_conf nvgre_encap_conf = {
5044418919fSjohnjiang 	.select_ipv4 = 1,
5054418919fSjohnjiang 	.select_vlan = 0,
5064418919fSjohnjiang 	.tni = "\x00\x00\x00",
5074418919fSjohnjiang 	.ipv4_src = RTE_IPV4(127, 0, 0, 1),
5084418919fSjohnjiang 	.ipv4_dst = RTE_IPV4(255, 255, 255, 255),
5094418919fSjohnjiang 	.ipv6_src = "\x00\x00\x00\x00\x00\x00\x00\x00"
5104418919fSjohnjiang 		"\x00\x00\x00\x00\x00\x00\x00\x01",
5114418919fSjohnjiang 	.ipv6_dst = "\x00\x00\x00\x00\x00\x00\x00\x00"
5124418919fSjohnjiang 		"\x00\x00\x00\x00\x00\x00\x11\x11",
5134418919fSjohnjiang 	.vlan_tci = 0,
5144418919fSjohnjiang 	.eth_src = "\x00\x00\x00\x00\x00\x00",
5154418919fSjohnjiang 	.eth_dst = "\xff\xff\xff\xff\xff\xff",
5164418919fSjohnjiang };
5174418919fSjohnjiang 
518d30ea906Sjfb8856606 /** Maximum number of items in struct rte_flow_action_nvgre_encap. */
519d30ea906Sjfb8856606 #define ACTION_NVGRE_ENCAP_ITEMS_NUM 5
520d30ea906Sjfb8856606 
521d30ea906Sjfb8856606 /** Storage for struct rte_flow_action_nvgre_encap including external data. */
522d30ea906Sjfb8856606 struct action_nvgre_encap_data {
523d30ea906Sjfb8856606 	struct rte_flow_action_nvgre_encap conf;
524d30ea906Sjfb8856606 	struct rte_flow_item items[ACTION_NVGRE_ENCAP_ITEMS_NUM];
525d30ea906Sjfb8856606 	struct rte_flow_item_eth item_eth;
526d30ea906Sjfb8856606 	struct rte_flow_item_vlan item_vlan;
527d30ea906Sjfb8856606 	union {
528d30ea906Sjfb8856606 		struct rte_flow_item_ipv4 item_ipv4;
529d30ea906Sjfb8856606 		struct rte_flow_item_ipv6 item_ipv6;
530d30ea906Sjfb8856606 	};
531d30ea906Sjfb8856606 	struct rte_flow_item_nvgre item_nvgre;
532d30ea906Sjfb8856606 };
533d30ea906Sjfb8856606 
5344418919fSjohnjiang struct l2_encap_conf l2_encap_conf;
535d30ea906Sjfb8856606 
5364418919fSjohnjiang struct l2_decap_conf l2_decap_conf;
537d30ea906Sjfb8856606 
5384418919fSjohnjiang struct mplsogre_encap_conf mplsogre_encap_conf;
5394418919fSjohnjiang 
5404418919fSjohnjiang struct mplsogre_decap_conf mplsogre_decap_conf;
5414418919fSjohnjiang 
5424418919fSjohnjiang struct mplsoudp_encap_conf mplsoudp_encap_conf;
5434418919fSjohnjiang 
5444418919fSjohnjiang struct mplsoudp_decap_conf mplsoudp_decap_conf;
5452bfe3f2eSlogwang 
546*2d9fd380Sjfb8856606 #define ACTION_SAMPLE_ACTIONS_NUM 10
547*2d9fd380Sjfb8856606 #define RAW_SAMPLE_CONFS_MAX_NUM 8
548*2d9fd380Sjfb8856606 /** Storage for struct rte_flow_action_sample including external data. */
549*2d9fd380Sjfb8856606 struct action_sample_data {
550*2d9fd380Sjfb8856606 	struct rte_flow_action_sample conf;
551*2d9fd380Sjfb8856606 	uint32_t idx;
552*2d9fd380Sjfb8856606 };
553*2d9fd380Sjfb8856606 /** Storage for struct rte_flow_action_sample. */
554*2d9fd380Sjfb8856606 struct raw_sample_conf {
555*2d9fd380Sjfb8856606 	struct rte_flow_action data[ACTION_SAMPLE_ACTIONS_NUM];
556*2d9fd380Sjfb8856606 };
557*2d9fd380Sjfb8856606 struct raw_sample_conf raw_sample_confs[RAW_SAMPLE_CONFS_MAX_NUM];
558*2d9fd380Sjfb8856606 struct rte_flow_action_mark sample_mark[RAW_SAMPLE_CONFS_MAX_NUM];
559*2d9fd380Sjfb8856606 struct rte_flow_action_queue sample_queue[RAW_SAMPLE_CONFS_MAX_NUM];
560*2d9fd380Sjfb8856606 struct rte_flow_action_count sample_count[RAW_SAMPLE_CONFS_MAX_NUM];
561*2d9fd380Sjfb8856606 struct rte_flow_action_port_id sample_port_id[RAW_SAMPLE_CONFS_MAX_NUM];
562*2d9fd380Sjfb8856606 struct rte_flow_action_raw_encap sample_encap[RAW_SAMPLE_CONFS_MAX_NUM];
563*2d9fd380Sjfb8856606 
5642bfe3f2eSlogwang /** Maximum number of subsequent tokens and arguments on the stack. */
5652bfe3f2eSlogwang #define CTX_STACK_SIZE 16
5662bfe3f2eSlogwang 
5672bfe3f2eSlogwang /** Parser context. */
5682bfe3f2eSlogwang struct context {
5692bfe3f2eSlogwang 	/** Stack of subsequent token lists to process. */
5702bfe3f2eSlogwang 	const enum index *next[CTX_STACK_SIZE];
5712bfe3f2eSlogwang 	/** Arguments for stacked tokens. */
5722bfe3f2eSlogwang 	const void *args[CTX_STACK_SIZE];
5732bfe3f2eSlogwang 	enum index curr; /**< Current token index. */
5742bfe3f2eSlogwang 	enum index prev; /**< Index of the last token seen. */
5752bfe3f2eSlogwang 	int next_num; /**< Number of entries in next[]. */
5762bfe3f2eSlogwang 	int args_num; /**< Number of entries in args[]. */
5772bfe3f2eSlogwang 	uint32_t eol:1; /**< EOL has been detected. */
5782bfe3f2eSlogwang 	uint32_t last:1; /**< No more arguments. */
5792bfe3f2eSlogwang 	portid_t port; /**< Current port ID (for completions). */
5802bfe3f2eSlogwang 	uint32_t objdata; /**< Object-specific data. */
5812bfe3f2eSlogwang 	void *object; /**< Address of current object for relative offsets. */
5822bfe3f2eSlogwang 	void *objmask; /**< Object a full mask must be written to. */
5832bfe3f2eSlogwang };
5842bfe3f2eSlogwang 
5852bfe3f2eSlogwang /** Token argument. */
5862bfe3f2eSlogwang struct arg {
5872bfe3f2eSlogwang 	uint32_t hton:1; /**< Use network byte ordering. */
5882bfe3f2eSlogwang 	uint32_t sign:1; /**< Value is signed. */
589d30ea906Sjfb8856606 	uint32_t bounded:1; /**< Value is bounded. */
590d30ea906Sjfb8856606 	uintmax_t min; /**< Minimum value if bounded. */
591d30ea906Sjfb8856606 	uintmax_t max; /**< Maximum value if bounded. */
5922bfe3f2eSlogwang 	uint32_t offset; /**< Relative offset from ctx->object. */
5932bfe3f2eSlogwang 	uint32_t size; /**< Field size. */
5942bfe3f2eSlogwang 	const uint8_t *mask; /**< Bit-mask to use instead of offset/size. */
5952bfe3f2eSlogwang };
5962bfe3f2eSlogwang 
5972bfe3f2eSlogwang /** Parser token definition. */
5982bfe3f2eSlogwang struct token {
5992bfe3f2eSlogwang 	/** Type displayed during completion (defaults to "TOKEN"). */
6002bfe3f2eSlogwang 	const char *type;
6012bfe3f2eSlogwang 	/** Help displayed during completion (defaults to token name). */
6022bfe3f2eSlogwang 	const char *help;
6032bfe3f2eSlogwang 	/** Private data used by parser functions. */
6042bfe3f2eSlogwang 	const void *priv;
6052bfe3f2eSlogwang 	/**
6062bfe3f2eSlogwang 	 * Lists of subsequent tokens to push on the stack. Each call to the
6072bfe3f2eSlogwang 	 * parser consumes the last entry of that stack.
6082bfe3f2eSlogwang 	 */
6092bfe3f2eSlogwang 	const enum index *const *next;
6102bfe3f2eSlogwang 	/** Arguments stack for subsequent tokens that need them. */
6112bfe3f2eSlogwang 	const struct arg *const *args;
6122bfe3f2eSlogwang 	/**
6132bfe3f2eSlogwang 	 * Token-processing callback, returns -1 in case of error, the
6142bfe3f2eSlogwang 	 * length of the matched string otherwise. If NULL, attempts to
6152bfe3f2eSlogwang 	 * match the token name.
6162bfe3f2eSlogwang 	 *
6172bfe3f2eSlogwang 	 * If buf is not NULL, the result should be stored in it according
6182bfe3f2eSlogwang 	 * to context. An error is returned if not large enough.
6192bfe3f2eSlogwang 	 */
6202bfe3f2eSlogwang 	int (*call)(struct context *ctx, const struct token *token,
6212bfe3f2eSlogwang 		    const char *str, unsigned int len,
6222bfe3f2eSlogwang 		    void *buf, unsigned int size);
6232bfe3f2eSlogwang 	/**
6242bfe3f2eSlogwang 	 * Callback that provides possible values for this token, used for
6252bfe3f2eSlogwang 	 * completion. Returns -1 in case of error, the number of possible
6262bfe3f2eSlogwang 	 * values otherwise. If NULL, the token name is used.
6272bfe3f2eSlogwang 	 *
6282bfe3f2eSlogwang 	 * If buf is not NULL, entry index ent is written to buf and the
6292bfe3f2eSlogwang 	 * full length of the entry is returned (same behavior as
6302bfe3f2eSlogwang 	 * snprintf()).
6312bfe3f2eSlogwang 	 */
6322bfe3f2eSlogwang 	int (*comp)(struct context *ctx, const struct token *token,
6332bfe3f2eSlogwang 		    unsigned int ent, char *buf, unsigned int size);
6342bfe3f2eSlogwang 	/** Mandatory token name, no default value. */
6352bfe3f2eSlogwang 	const char *name;
6362bfe3f2eSlogwang };
6372bfe3f2eSlogwang 
6382bfe3f2eSlogwang /** Static initializer for the next field. */
6392bfe3f2eSlogwang #define NEXT(...) (const enum index *const []){ __VA_ARGS__, NULL, }
6402bfe3f2eSlogwang 
6412bfe3f2eSlogwang /** Static initializer for a NEXT() entry. */
6422bfe3f2eSlogwang #define NEXT_ENTRY(...) (const enum index []){ __VA_ARGS__, ZERO, }
6432bfe3f2eSlogwang 
6442bfe3f2eSlogwang /** Static initializer for the args field. */
6452bfe3f2eSlogwang #define ARGS(...) (const struct arg *const []){ __VA_ARGS__, NULL, }
6462bfe3f2eSlogwang 
6472bfe3f2eSlogwang /** Static initializer for ARGS() to target a field. */
6482bfe3f2eSlogwang #define ARGS_ENTRY(s, f) \
6492bfe3f2eSlogwang 	(&(const struct arg){ \
6502bfe3f2eSlogwang 		.offset = offsetof(s, f), \
6512bfe3f2eSlogwang 		.size = sizeof(((s *)0)->f), \
6522bfe3f2eSlogwang 	})
6532bfe3f2eSlogwang 
6542bfe3f2eSlogwang /** Static initializer for ARGS() to target a bit-field. */
6552bfe3f2eSlogwang #define ARGS_ENTRY_BF(s, f, b) \
6562bfe3f2eSlogwang 	(&(const struct arg){ \
6572bfe3f2eSlogwang 		.size = sizeof(s), \
6582bfe3f2eSlogwang 		.mask = (const void *)&(const s){ .f = (1 << (b)) - 1 }, \
6592bfe3f2eSlogwang 	})
6602bfe3f2eSlogwang 
6612bfe3f2eSlogwang /** Static initializer for ARGS() to target an arbitrary bit-mask. */
6622bfe3f2eSlogwang #define ARGS_ENTRY_MASK(s, f, m) \
6632bfe3f2eSlogwang 	(&(const struct arg){ \
6642bfe3f2eSlogwang 		.offset = offsetof(s, f), \
6652bfe3f2eSlogwang 		.size = sizeof(((s *)0)->f), \
6662bfe3f2eSlogwang 		.mask = (const void *)(m), \
6672bfe3f2eSlogwang 	})
6682bfe3f2eSlogwang 
6692bfe3f2eSlogwang /** Same as ARGS_ENTRY_MASK() using network byte ordering for the value. */
6702bfe3f2eSlogwang #define ARGS_ENTRY_MASK_HTON(s, f, m) \
6712bfe3f2eSlogwang 	(&(const struct arg){ \
6722bfe3f2eSlogwang 		.hton = 1, \
6732bfe3f2eSlogwang 		.offset = offsetof(s, f), \
6742bfe3f2eSlogwang 		.size = sizeof(((s *)0)->f), \
6752bfe3f2eSlogwang 		.mask = (const void *)(m), \
6762bfe3f2eSlogwang 	})
6772bfe3f2eSlogwang 
6782bfe3f2eSlogwang /** Static initializer for ARGS() to target a pointer. */
6792bfe3f2eSlogwang #define ARGS_ENTRY_PTR(s, f) \
6802bfe3f2eSlogwang 	(&(const struct arg){ \
6812bfe3f2eSlogwang 		.size = sizeof(*((s *)0)->f), \
6822bfe3f2eSlogwang 	})
6832bfe3f2eSlogwang 
684d30ea906Sjfb8856606 /** Static initializer for ARGS() with arbitrary offset and size. */
685d30ea906Sjfb8856606 #define ARGS_ENTRY_ARB(o, s) \
6862bfe3f2eSlogwang 	(&(const struct arg){ \
687d30ea906Sjfb8856606 		.offset = (o), \
688d30ea906Sjfb8856606 		.size = (s), \
689d30ea906Sjfb8856606 	})
690d30ea906Sjfb8856606 
691d30ea906Sjfb8856606 /** Same as ARGS_ENTRY_ARB() with bounded values. */
692d30ea906Sjfb8856606 #define ARGS_ENTRY_ARB_BOUNDED(o, s, i, a) \
693d30ea906Sjfb8856606 	(&(const struct arg){ \
694d30ea906Sjfb8856606 		.bounded = 1, \
695d30ea906Sjfb8856606 		.min = (i), \
696d30ea906Sjfb8856606 		.max = (a), \
697d30ea906Sjfb8856606 		.offset = (o), \
698d30ea906Sjfb8856606 		.size = (s), \
6992bfe3f2eSlogwang 	})
7002bfe3f2eSlogwang 
7012bfe3f2eSlogwang /** Same as ARGS_ENTRY() using network byte ordering. */
7022bfe3f2eSlogwang #define ARGS_ENTRY_HTON(s, f) \
7032bfe3f2eSlogwang 	(&(const struct arg){ \
7042bfe3f2eSlogwang 		.hton = 1, \
7052bfe3f2eSlogwang 		.offset = offsetof(s, f), \
7062bfe3f2eSlogwang 		.size = sizeof(((s *)0)->f), \
7072bfe3f2eSlogwang 	})
7082bfe3f2eSlogwang 
7094418919fSjohnjiang /** Same as ARGS_ENTRY_HTON() for a single argument, without structure. */
7104418919fSjohnjiang #define ARG_ENTRY_HTON(s) \
7114418919fSjohnjiang 	(&(const struct arg){ \
7124418919fSjohnjiang 		.hton = 1, \
7134418919fSjohnjiang 		.offset = 0, \
7144418919fSjohnjiang 		.size = sizeof(s), \
7154418919fSjohnjiang 	})
7164418919fSjohnjiang 
7172bfe3f2eSlogwang /** Parser output buffer layout expected by cmd_flow_parsed(). */
7182bfe3f2eSlogwang struct buffer {
7192bfe3f2eSlogwang 	enum index command; /**< Flow command. */
7202bfe3f2eSlogwang 	portid_t port; /**< Affected port ID. */
7212bfe3f2eSlogwang 	union {
7222bfe3f2eSlogwang 		struct {
723*2d9fd380Sjfb8856606 			uint32_t *action_id;
724*2d9fd380Sjfb8856606 			uint32_t action_id_n;
725*2d9fd380Sjfb8856606 		} sa_destroy; /**< Shared action destroy arguments. */
726*2d9fd380Sjfb8856606 		struct {
727*2d9fd380Sjfb8856606 			uint32_t action_id;
728*2d9fd380Sjfb8856606 		} sa; /* Shared action query arguments */
729*2d9fd380Sjfb8856606 		struct {
7302bfe3f2eSlogwang 			struct rte_flow_attr attr;
731*2d9fd380Sjfb8856606 			struct tunnel_ops tunnel_ops;
7322bfe3f2eSlogwang 			struct rte_flow_item *pattern;
7332bfe3f2eSlogwang 			struct rte_flow_action *actions;
7342bfe3f2eSlogwang 			uint32_t pattern_n;
7352bfe3f2eSlogwang 			uint32_t actions_n;
7362bfe3f2eSlogwang 			uint8_t *data;
7372bfe3f2eSlogwang 		} vc; /**< Validate/create arguments. */
7382bfe3f2eSlogwang 		struct {
7392bfe3f2eSlogwang 			uint32_t *rule;
7402bfe3f2eSlogwang 			uint32_t rule_n;
7412bfe3f2eSlogwang 		} destroy; /**< Destroy arguments. */
7422bfe3f2eSlogwang 		struct {
743*2d9fd380Sjfb8856606 			char file[128];
744*2d9fd380Sjfb8856606 		} dump; /**< Dump arguments. */
745*2d9fd380Sjfb8856606 		struct {
7462bfe3f2eSlogwang 			uint32_t rule;
747d30ea906Sjfb8856606 			struct rte_flow_action action;
7482bfe3f2eSlogwang 		} query; /**< Query arguments. */
7492bfe3f2eSlogwang 		struct {
7502bfe3f2eSlogwang 			uint32_t *group;
7512bfe3f2eSlogwang 			uint32_t group_n;
7522bfe3f2eSlogwang 		} list; /**< List arguments. */
7532bfe3f2eSlogwang 		struct {
7542bfe3f2eSlogwang 			int set;
7552bfe3f2eSlogwang 		} isolate; /**< Isolated mode arguments. */
756*2d9fd380Sjfb8856606 		struct {
757*2d9fd380Sjfb8856606 			int destroy;
758*2d9fd380Sjfb8856606 		} aged; /**< Aged arguments. */
7592bfe3f2eSlogwang 	} args; /**< Command arguments. */
7602bfe3f2eSlogwang };
7612bfe3f2eSlogwang 
7622bfe3f2eSlogwang /** Private data for pattern items. */
7632bfe3f2eSlogwang struct parse_item_priv {
7642bfe3f2eSlogwang 	enum rte_flow_item_type type; /**< Item type. */
7652bfe3f2eSlogwang 	uint32_t size; /**< Size of item specification structure. */
7662bfe3f2eSlogwang };
7672bfe3f2eSlogwang 
7682bfe3f2eSlogwang #define PRIV_ITEM(t, s) \
7692bfe3f2eSlogwang 	(&(const struct parse_item_priv){ \
7702bfe3f2eSlogwang 		.type = RTE_FLOW_ITEM_TYPE_ ## t, \
7712bfe3f2eSlogwang 		.size = s, \
7722bfe3f2eSlogwang 	})
7732bfe3f2eSlogwang 
7742bfe3f2eSlogwang /** Private data for actions. */
7752bfe3f2eSlogwang struct parse_action_priv {
7762bfe3f2eSlogwang 	enum rte_flow_action_type type; /**< Action type. */
7772bfe3f2eSlogwang 	uint32_t size; /**< Size of action configuration structure. */
7782bfe3f2eSlogwang };
7792bfe3f2eSlogwang 
7802bfe3f2eSlogwang #define PRIV_ACTION(t, s) \
7812bfe3f2eSlogwang 	(&(const struct parse_action_priv){ \
7822bfe3f2eSlogwang 		.type = RTE_FLOW_ACTION_TYPE_ ## t, \
7832bfe3f2eSlogwang 		.size = s, \
7842bfe3f2eSlogwang 	})
7852bfe3f2eSlogwang 
786*2d9fd380Sjfb8856606 static const enum index next_sa_create_attr[] = {
787*2d9fd380Sjfb8856606 	SHARED_ACTION_CREATE_ID,
788*2d9fd380Sjfb8856606 	SHARED_ACTION_INGRESS,
789*2d9fd380Sjfb8856606 	SHARED_ACTION_EGRESS,
790*2d9fd380Sjfb8856606 	SHARED_ACTION_TRANSFER,
791*2d9fd380Sjfb8856606 	SHARED_ACTION_SPEC,
792*2d9fd380Sjfb8856606 	ZERO,
793*2d9fd380Sjfb8856606 };
794*2d9fd380Sjfb8856606 
795*2d9fd380Sjfb8856606 static const enum index next_sa_subcmd[] = {
796*2d9fd380Sjfb8856606 	SHARED_ACTION_CREATE,
797*2d9fd380Sjfb8856606 	SHARED_ACTION_UPDATE,
798*2d9fd380Sjfb8856606 	SHARED_ACTION_DESTROY,
799*2d9fd380Sjfb8856606 	SHARED_ACTION_QUERY,
800*2d9fd380Sjfb8856606 	ZERO,
801*2d9fd380Sjfb8856606 };
802*2d9fd380Sjfb8856606 
8032bfe3f2eSlogwang static const enum index next_vc_attr[] = {
8042bfe3f2eSlogwang 	GROUP,
8052bfe3f2eSlogwang 	PRIORITY,
8062bfe3f2eSlogwang 	INGRESS,
8072bfe3f2eSlogwang 	EGRESS,
808d30ea906Sjfb8856606 	TRANSFER,
809*2d9fd380Sjfb8856606 	TUNNEL_SET,
810*2d9fd380Sjfb8856606 	TUNNEL_MATCH,
8112bfe3f2eSlogwang 	PATTERN,
8122bfe3f2eSlogwang 	ZERO,
8132bfe3f2eSlogwang };
8142bfe3f2eSlogwang 
8152bfe3f2eSlogwang static const enum index next_destroy_attr[] = {
8162bfe3f2eSlogwang 	DESTROY_RULE,
8172bfe3f2eSlogwang 	END,
8182bfe3f2eSlogwang 	ZERO,
8192bfe3f2eSlogwang };
8202bfe3f2eSlogwang 
821*2d9fd380Sjfb8856606 static const enum index next_dump_attr[] = {
822*2d9fd380Sjfb8856606 	FILE_PATH,
823*2d9fd380Sjfb8856606 	END,
824*2d9fd380Sjfb8856606 	ZERO,
825*2d9fd380Sjfb8856606 };
826*2d9fd380Sjfb8856606 
8272bfe3f2eSlogwang static const enum index next_list_attr[] = {
8282bfe3f2eSlogwang 	LIST_GROUP,
8292bfe3f2eSlogwang 	END,
8302bfe3f2eSlogwang 	ZERO,
8312bfe3f2eSlogwang };
8322bfe3f2eSlogwang 
833*2d9fd380Sjfb8856606 static const enum index next_aged_attr[] = {
834*2d9fd380Sjfb8856606 	AGED_DESTROY,
835*2d9fd380Sjfb8856606 	END,
836*2d9fd380Sjfb8856606 	ZERO,
837*2d9fd380Sjfb8856606 };
838*2d9fd380Sjfb8856606 
839*2d9fd380Sjfb8856606 static const enum index next_sa_destroy_attr[] = {
840*2d9fd380Sjfb8856606 	SHARED_ACTION_DESTROY_ID,
841*2d9fd380Sjfb8856606 	END,
842*2d9fd380Sjfb8856606 	ZERO,
843*2d9fd380Sjfb8856606 };
844*2d9fd380Sjfb8856606 
8452bfe3f2eSlogwang static const enum index item_param[] = {
8462bfe3f2eSlogwang 	ITEM_PARAM_IS,
8472bfe3f2eSlogwang 	ITEM_PARAM_SPEC,
8482bfe3f2eSlogwang 	ITEM_PARAM_LAST,
8492bfe3f2eSlogwang 	ITEM_PARAM_MASK,
8502bfe3f2eSlogwang 	ITEM_PARAM_PREFIX,
8512bfe3f2eSlogwang 	ZERO,
8522bfe3f2eSlogwang };
8532bfe3f2eSlogwang 
8542bfe3f2eSlogwang static const enum index next_item[] = {
8552bfe3f2eSlogwang 	ITEM_END,
8562bfe3f2eSlogwang 	ITEM_VOID,
8572bfe3f2eSlogwang 	ITEM_INVERT,
8582bfe3f2eSlogwang 	ITEM_ANY,
8592bfe3f2eSlogwang 	ITEM_PF,
8602bfe3f2eSlogwang 	ITEM_VF,
861d30ea906Sjfb8856606 	ITEM_PHY_PORT,
862d30ea906Sjfb8856606 	ITEM_PORT_ID,
863d30ea906Sjfb8856606 	ITEM_MARK,
8642bfe3f2eSlogwang 	ITEM_RAW,
8652bfe3f2eSlogwang 	ITEM_ETH,
8662bfe3f2eSlogwang 	ITEM_VLAN,
8672bfe3f2eSlogwang 	ITEM_IPV4,
8682bfe3f2eSlogwang 	ITEM_IPV6,
8692bfe3f2eSlogwang 	ITEM_ICMP,
8702bfe3f2eSlogwang 	ITEM_UDP,
8712bfe3f2eSlogwang 	ITEM_TCP,
8722bfe3f2eSlogwang 	ITEM_SCTP,
8732bfe3f2eSlogwang 	ITEM_VXLAN,
8742bfe3f2eSlogwang 	ITEM_E_TAG,
8752bfe3f2eSlogwang 	ITEM_NVGRE,
8762bfe3f2eSlogwang 	ITEM_MPLS,
8772bfe3f2eSlogwang 	ITEM_GRE,
8782bfe3f2eSlogwang 	ITEM_FUZZY,
8792bfe3f2eSlogwang 	ITEM_GTP,
8802bfe3f2eSlogwang 	ITEM_GTPC,
8812bfe3f2eSlogwang 	ITEM_GTPU,
882d30ea906Sjfb8856606 	ITEM_GENEVE,
883d30ea906Sjfb8856606 	ITEM_VXLAN_GPE,
884d30ea906Sjfb8856606 	ITEM_ARP_ETH_IPV4,
885d30ea906Sjfb8856606 	ITEM_IPV6_EXT,
886*2d9fd380Sjfb8856606 	ITEM_IPV6_FRAG_EXT,
887d30ea906Sjfb8856606 	ITEM_ICMP6,
888d30ea906Sjfb8856606 	ITEM_ICMP6_ND_NS,
889d30ea906Sjfb8856606 	ITEM_ICMP6_ND_NA,
890d30ea906Sjfb8856606 	ITEM_ICMP6_ND_OPT,
891d30ea906Sjfb8856606 	ITEM_ICMP6_ND_OPT_SLA_ETH,
892d30ea906Sjfb8856606 	ITEM_ICMP6_ND_OPT_TLA_ETH,
893d30ea906Sjfb8856606 	ITEM_META,
8944418919fSjohnjiang 	ITEM_GRE_KEY,
8954418919fSjohnjiang 	ITEM_GTP_PSC,
8964418919fSjohnjiang 	ITEM_PPPOES,
8974418919fSjohnjiang 	ITEM_PPPOED,
8984418919fSjohnjiang 	ITEM_PPPOE_PROTO_ID,
8994418919fSjohnjiang 	ITEM_HIGIG2,
9004418919fSjohnjiang 	ITEM_TAG,
901*2d9fd380Sjfb8856606 	ITEM_L2TPV3OIP,
902*2d9fd380Sjfb8856606 	ITEM_ESP,
903*2d9fd380Sjfb8856606 	ITEM_AH,
904*2d9fd380Sjfb8856606 	ITEM_PFCP,
905*2d9fd380Sjfb8856606 	ITEM_ECPRI,
9064418919fSjohnjiang 	END_SET,
9072bfe3f2eSlogwang 	ZERO,
9082bfe3f2eSlogwang };
9092bfe3f2eSlogwang 
9102bfe3f2eSlogwang static const enum index item_fuzzy[] = {
9112bfe3f2eSlogwang 	ITEM_FUZZY_THRESH,
9122bfe3f2eSlogwang 	ITEM_NEXT,
9132bfe3f2eSlogwang 	ZERO,
9142bfe3f2eSlogwang };
9152bfe3f2eSlogwang 
9162bfe3f2eSlogwang static const enum index item_any[] = {
9172bfe3f2eSlogwang 	ITEM_ANY_NUM,
9182bfe3f2eSlogwang 	ITEM_NEXT,
9192bfe3f2eSlogwang 	ZERO,
9202bfe3f2eSlogwang };
9212bfe3f2eSlogwang 
9222bfe3f2eSlogwang static const enum index item_vf[] = {
9232bfe3f2eSlogwang 	ITEM_VF_ID,
9242bfe3f2eSlogwang 	ITEM_NEXT,
9252bfe3f2eSlogwang 	ZERO,
9262bfe3f2eSlogwang };
9272bfe3f2eSlogwang 
928d30ea906Sjfb8856606 static const enum index item_phy_port[] = {
929d30ea906Sjfb8856606 	ITEM_PHY_PORT_INDEX,
930d30ea906Sjfb8856606 	ITEM_NEXT,
931d30ea906Sjfb8856606 	ZERO,
932d30ea906Sjfb8856606 };
933d30ea906Sjfb8856606 
934d30ea906Sjfb8856606 static const enum index item_port_id[] = {
935d30ea906Sjfb8856606 	ITEM_PORT_ID_ID,
936d30ea906Sjfb8856606 	ITEM_NEXT,
937d30ea906Sjfb8856606 	ZERO,
938d30ea906Sjfb8856606 };
939d30ea906Sjfb8856606 
940d30ea906Sjfb8856606 static const enum index item_mark[] = {
941d30ea906Sjfb8856606 	ITEM_MARK_ID,
9422bfe3f2eSlogwang 	ITEM_NEXT,
9432bfe3f2eSlogwang 	ZERO,
9442bfe3f2eSlogwang };
9452bfe3f2eSlogwang 
9462bfe3f2eSlogwang static const enum index item_raw[] = {
9472bfe3f2eSlogwang 	ITEM_RAW_RELATIVE,
9482bfe3f2eSlogwang 	ITEM_RAW_SEARCH,
9492bfe3f2eSlogwang 	ITEM_RAW_OFFSET,
9502bfe3f2eSlogwang 	ITEM_RAW_LIMIT,
9512bfe3f2eSlogwang 	ITEM_RAW_PATTERN,
9522bfe3f2eSlogwang 	ITEM_NEXT,
9532bfe3f2eSlogwang 	ZERO,
9542bfe3f2eSlogwang };
9552bfe3f2eSlogwang 
9562bfe3f2eSlogwang static const enum index item_eth[] = {
9572bfe3f2eSlogwang 	ITEM_ETH_DST,
9582bfe3f2eSlogwang 	ITEM_ETH_SRC,
9592bfe3f2eSlogwang 	ITEM_ETH_TYPE,
960*2d9fd380Sjfb8856606 	ITEM_ETH_HAS_VLAN,
9612bfe3f2eSlogwang 	ITEM_NEXT,
9622bfe3f2eSlogwang 	ZERO,
9632bfe3f2eSlogwang };
9642bfe3f2eSlogwang 
9652bfe3f2eSlogwang static const enum index item_vlan[] = {
9662bfe3f2eSlogwang 	ITEM_VLAN_TCI,
9672bfe3f2eSlogwang 	ITEM_VLAN_PCP,
9682bfe3f2eSlogwang 	ITEM_VLAN_DEI,
9692bfe3f2eSlogwang 	ITEM_VLAN_VID,
970d30ea906Sjfb8856606 	ITEM_VLAN_INNER_TYPE,
971*2d9fd380Sjfb8856606 	ITEM_VLAN_HAS_MORE_VLAN,
9722bfe3f2eSlogwang 	ITEM_NEXT,
9732bfe3f2eSlogwang 	ZERO,
9742bfe3f2eSlogwang };
9752bfe3f2eSlogwang 
9762bfe3f2eSlogwang static const enum index item_ipv4[] = {
9772bfe3f2eSlogwang 	ITEM_IPV4_TOS,
978*2d9fd380Sjfb8856606 	ITEM_IPV4_FRAGMENT_OFFSET,
9792bfe3f2eSlogwang 	ITEM_IPV4_TTL,
9802bfe3f2eSlogwang 	ITEM_IPV4_PROTO,
9812bfe3f2eSlogwang 	ITEM_IPV4_SRC,
9822bfe3f2eSlogwang 	ITEM_IPV4_DST,
9832bfe3f2eSlogwang 	ITEM_NEXT,
9842bfe3f2eSlogwang 	ZERO,
9852bfe3f2eSlogwang };
9862bfe3f2eSlogwang 
9872bfe3f2eSlogwang static const enum index item_ipv6[] = {
9882bfe3f2eSlogwang 	ITEM_IPV6_TC,
9892bfe3f2eSlogwang 	ITEM_IPV6_FLOW,
9902bfe3f2eSlogwang 	ITEM_IPV6_PROTO,
9912bfe3f2eSlogwang 	ITEM_IPV6_HOP,
9922bfe3f2eSlogwang 	ITEM_IPV6_SRC,
9932bfe3f2eSlogwang 	ITEM_IPV6_DST,
994*2d9fd380Sjfb8856606 	ITEM_IPV6_HAS_FRAG_EXT,
9952bfe3f2eSlogwang 	ITEM_NEXT,
9962bfe3f2eSlogwang 	ZERO,
9972bfe3f2eSlogwang };
9982bfe3f2eSlogwang 
9992bfe3f2eSlogwang static const enum index item_icmp[] = {
10002bfe3f2eSlogwang 	ITEM_ICMP_TYPE,
10012bfe3f2eSlogwang 	ITEM_ICMP_CODE,
1002*2d9fd380Sjfb8856606 	ITEM_ICMP_IDENT,
1003*2d9fd380Sjfb8856606 	ITEM_ICMP_SEQ,
10042bfe3f2eSlogwang 	ITEM_NEXT,
10052bfe3f2eSlogwang 	ZERO,
10062bfe3f2eSlogwang };
10072bfe3f2eSlogwang 
10082bfe3f2eSlogwang static const enum index item_udp[] = {
10092bfe3f2eSlogwang 	ITEM_UDP_SRC,
10102bfe3f2eSlogwang 	ITEM_UDP_DST,
10112bfe3f2eSlogwang 	ITEM_NEXT,
10122bfe3f2eSlogwang 	ZERO,
10132bfe3f2eSlogwang };
10142bfe3f2eSlogwang 
10152bfe3f2eSlogwang static const enum index item_tcp[] = {
10162bfe3f2eSlogwang 	ITEM_TCP_SRC,
10172bfe3f2eSlogwang 	ITEM_TCP_DST,
10182bfe3f2eSlogwang 	ITEM_TCP_FLAGS,
10192bfe3f2eSlogwang 	ITEM_NEXT,
10202bfe3f2eSlogwang 	ZERO,
10212bfe3f2eSlogwang };
10222bfe3f2eSlogwang 
10232bfe3f2eSlogwang static const enum index item_sctp[] = {
10242bfe3f2eSlogwang 	ITEM_SCTP_SRC,
10252bfe3f2eSlogwang 	ITEM_SCTP_DST,
10262bfe3f2eSlogwang 	ITEM_SCTP_TAG,
10272bfe3f2eSlogwang 	ITEM_SCTP_CKSUM,
10282bfe3f2eSlogwang 	ITEM_NEXT,
10292bfe3f2eSlogwang 	ZERO,
10302bfe3f2eSlogwang };
10312bfe3f2eSlogwang 
10322bfe3f2eSlogwang static const enum index item_vxlan[] = {
10332bfe3f2eSlogwang 	ITEM_VXLAN_VNI,
10342bfe3f2eSlogwang 	ITEM_NEXT,
10352bfe3f2eSlogwang 	ZERO,
10362bfe3f2eSlogwang };
10372bfe3f2eSlogwang 
10382bfe3f2eSlogwang static const enum index item_e_tag[] = {
10392bfe3f2eSlogwang 	ITEM_E_TAG_GRP_ECID_B,
10402bfe3f2eSlogwang 	ITEM_NEXT,
10412bfe3f2eSlogwang 	ZERO,
10422bfe3f2eSlogwang };
10432bfe3f2eSlogwang 
10442bfe3f2eSlogwang static const enum index item_nvgre[] = {
10452bfe3f2eSlogwang 	ITEM_NVGRE_TNI,
10462bfe3f2eSlogwang 	ITEM_NEXT,
10472bfe3f2eSlogwang 	ZERO,
10482bfe3f2eSlogwang };
10492bfe3f2eSlogwang 
10502bfe3f2eSlogwang static const enum index item_mpls[] = {
10512bfe3f2eSlogwang 	ITEM_MPLS_LABEL,
10524418919fSjohnjiang 	ITEM_MPLS_TC,
10534418919fSjohnjiang 	ITEM_MPLS_S,
10542bfe3f2eSlogwang 	ITEM_NEXT,
10552bfe3f2eSlogwang 	ZERO,
10562bfe3f2eSlogwang };
10572bfe3f2eSlogwang 
10582bfe3f2eSlogwang static const enum index item_gre[] = {
10592bfe3f2eSlogwang 	ITEM_GRE_PROTO,
10604418919fSjohnjiang 	ITEM_GRE_C_RSVD0_VER,
10614418919fSjohnjiang 	ITEM_GRE_C_BIT,
10624418919fSjohnjiang 	ITEM_GRE_K_BIT,
10634418919fSjohnjiang 	ITEM_GRE_S_BIT,
10644418919fSjohnjiang 	ITEM_NEXT,
10654418919fSjohnjiang 	ZERO,
10664418919fSjohnjiang };
10674418919fSjohnjiang 
10684418919fSjohnjiang static const enum index item_gre_key[] = {
10694418919fSjohnjiang 	ITEM_GRE_KEY_VALUE,
10702bfe3f2eSlogwang 	ITEM_NEXT,
10712bfe3f2eSlogwang 	ZERO,
10722bfe3f2eSlogwang };
10732bfe3f2eSlogwang 
10742bfe3f2eSlogwang static const enum index item_gtp[] = {
1075*2d9fd380Sjfb8856606 	ITEM_GTP_FLAGS,
1076*2d9fd380Sjfb8856606 	ITEM_GTP_MSG_TYPE,
10772bfe3f2eSlogwang 	ITEM_GTP_TEID,
10782bfe3f2eSlogwang 	ITEM_NEXT,
10792bfe3f2eSlogwang 	ZERO,
10802bfe3f2eSlogwang };
10812bfe3f2eSlogwang 
1082d30ea906Sjfb8856606 static const enum index item_geneve[] = {
1083d30ea906Sjfb8856606 	ITEM_GENEVE_VNI,
1084d30ea906Sjfb8856606 	ITEM_GENEVE_PROTO,
1085d30ea906Sjfb8856606 	ITEM_NEXT,
1086d30ea906Sjfb8856606 	ZERO,
1087d30ea906Sjfb8856606 };
1088d30ea906Sjfb8856606 
1089d30ea906Sjfb8856606 static const enum index item_vxlan_gpe[] = {
1090d30ea906Sjfb8856606 	ITEM_VXLAN_GPE_VNI,
1091d30ea906Sjfb8856606 	ITEM_NEXT,
1092d30ea906Sjfb8856606 	ZERO,
1093d30ea906Sjfb8856606 };
1094d30ea906Sjfb8856606 
1095d30ea906Sjfb8856606 static const enum index item_arp_eth_ipv4[] = {
1096d30ea906Sjfb8856606 	ITEM_ARP_ETH_IPV4_SHA,
1097d30ea906Sjfb8856606 	ITEM_ARP_ETH_IPV4_SPA,
1098d30ea906Sjfb8856606 	ITEM_ARP_ETH_IPV4_THA,
1099d30ea906Sjfb8856606 	ITEM_ARP_ETH_IPV4_TPA,
1100d30ea906Sjfb8856606 	ITEM_NEXT,
1101d30ea906Sjfb8856606 	ZERO,
1102d30ea906Sjfb8856606 };
1103d30ea906Sjfb8856606 
1104d30ea906Sjfb8856606 static const enum index item_ipv6_ext[] = {
1105d30ea906Sjfb8856606 	ITEM_IPV6_EXT_NEXT_HDR,
1106d30ea906Sjfb8856606 	ITEM_NEXT,
1107d30ea906Sjfb8856606 	ZERO,
1108d30ea906Sjfb8856606 };
1109d30ea906Sjfb8856606 
1110*2d9fd380Sjfb8856606 static const enum index item_ipv6_frag_ext[] = {
1111*2d9fd380Sjfb8856606 	ITEM_IPV6_FRAG_EXT_NEXT_HDR,
1112*2d9fd380Sjfb8856606 	ITEM_IPV6_FRAG_EXT_FRAG_DATA,
1113*2d9fd380Sjfb8856606 	ITEM_NEXT,
1114*2d9fd380Sjfb8856606 	ZERO,
1115*2d9fd380Sjfb8856606 };
1116*2d9fd380Sjfb8856606 
1117d30ea906Sjfb8856606 static const enum index item_icmp6[] = {
1118d30ea906Sjfb8856606 	ITEM_ICMP6_TYPE,
1119d30ea906Sjfb8856606 	ITEM_ICMP6_CODE,
1120d30ea906Sjfb8856606 	ITEM_NEXT,
1121d30ea906Sjfb8856606 	ZERO,
1122d30ea906Sjfb8856606 };
1123d30ea906Sjfb8856606 
1124d30ea906Sjfb8856606 static const enum index item_icmp6_nd_ns[] = {
1125d30ea906Sjfb8856606 	ITEM_ICMP6_ND_NS_TARGET_ADDR,
1126d30ea906Sjfb8856606 	ITEM_NEXT,
1127d30ea906Sjfb8856606 	ZERO,
1128d30ea906Sjfb8856606 };
1129d30ea906Sjfb8856606 
1130d30ea906Sjfb8856606 static const enum index item_icmp6_nd_na[] = {
1131d30ea906Sjfb8856606 	ITEM_ICMP6_ND_NA_TARGET_ADDR,
1132d30ea906Sjfb8856606 	ITEM_NEXT,
1133d30ea906Sjfb8856606 	ZERO,
1134d30ea906Sjfb8856606 };
1135d30ea906Sjfb8856606 
1136d30ea906Sjfb8856606 static const enum index item_icmp6_nd_opt[] = {
1137d30ea906Sjfb8856606 	ITEM_ICMP6_ND_OPT_TYPE,
1138d30ea906Sjfb8856606 	ITEM_NEXT,
1139d30ea906Sjfb8856606 	ZERO,
1140d30ea906Sjfb8856606 };
1141d30ea906Sjfb8856606 
1142d30ea906Sjfb8856606 static const enum index item_icmp6_nd_opt_sla_eth[] = {
1143d30ea906Sjfb8856606 	ITEM_ICMP6_ND_OPT_SLA_ETH_SLA,
1144d30ea906Sjfb8856606 	ITEM_NEXT,
1145d30ea906Sjfb8856606 	ZERO,
1146d30ea906Sjfb8856606 };
1147d30ea906Sjfb8856606 
1148d30ea906Sjfb8856606 static const enum index item_icmp6_nd_opt_tla_eth[] = {
1149d30ea906Sjfb8856606 	ITEM_ICMP6_ND_OPT_TLA_ETH_TLA,
1150d30ea906Sjfb8856606 	ITEM_NEXT,
1151d30ea906Sjfb8856606 	ZERO,
1152d30ea906Sjfb8856606 };
1153d30ea906Sjfb8856606 
1154d30ea906Sjfb8856606 static const enum index item_meta[] = {
1155d30ea906Sjfb8856606 	ITEM_META_DATA,
1156d30ea906Sjfb8856606 	ITEM_NEXT,
1157d30ea906Sjfb8856606 	ZERO,
1158d30ea906Sjfb8856606 };
1159d30ea906Sjfb8856606 
11604418919fSjohnjiang static const enum index item_gtp_psc[] = {
11614418919fSjohnjiang 	ITEM_GTP_PSC_QFI,
11624418919fSjohnjiang 	ITEM_GTP_PSC_PDU_T,
11634418919fSjohnjiang 	ITEM_NEXT,
11644418919fSjohnjiang 	ZERO,
11654418919fSjohnjiang };
11664418919fSjohnjiang 
11674418919fSjohnjiang static const enum index item_pppoed[] = {
11684418919fSjohnjiang 	ITEM_PPPOE_SEID,
11694418919fSjohnjiang 	ITEM_NEXT,
11704418919fSjohnjiang 	ZERO,
11714418919fSjohnjiang };
11724418919fSjohnjiang 
11734418919fSjohnjiang static const enum index item_pppoes[] = {
11744418919fSjohnjiang 	ITEM_PPPOE_SEID,
11754418919fSjohnjiang 	ITEM_NEXT,
11764418919fSjohnjiang 	ZERO,
11774418919fSjohnjiang };
11784418919fSjohnjiang 
11794418919fSjohnjiang static const enum index item_pppoe_proto_id[] = {
11804418919fSjohnjiang 	ITEM_NEXT,
11814418919fSjohnjiang 	ZERO,
11824418919fSjohnjiang };
11834418919fSjohnjiang 
11844418919fSjohnjiang static const enum index item_higig2[] = {
11854418919fSjohnjiang 	ITEM_HIGIG2_CLASSIFICATION,
11864418919fSjohnjiang 	ITEM_HIGIG2_VID,
11874418919fSjohnjiang 	ITEM_NEXT,
11884418919fSjohnjiang 	ZERO,
11894418919fSjohnjiang };
11904418919fSjohnjiang 
1191*2d9fd380Sjfb8856606 static const enum index item_esp[] = {
1192*2d9fd380Sjfb8856606 	ITEM_ESP_SPI,
1193*2d9fd380Sjfb8856606 	ITEM_NEXT,
1194*2d9fd380Sjfb8856606 	ZERO,
1195*2d9fd380Sjfb8856606 };
1196*2d9fd380Sjfb8856606 
1197*2d9fd380Sjfb8856606 static const enum index item_ah[] = {
1198*2d9fd380Sjfb8856606 	ITEM_AH_SPI,
1199*2d9fd380Sjfb8856606 	ITEM_NEXT,
1200*2d9fd380Sjfb8856606 	ZERO,
1201*2d9fd380Sjfb8856606 };
1202*2d9fd380Sjfb8856606 
1203*2d9fd380Sjfb8856606 static const enum index item_pfcp[] = {
1204*2d9fd380Sjfb8856606 	ITEM_PFCP_S_FIELD,
1205*2d9fd380Sjfb8856606 	ITEM_PFCP_SEID,
1206*2d9fd380Sjfb8856606 	ITEM_NEXT,
1207*2d9fd380Sjfb8856606 	ZERO,
1208*2d9fd380Sjfb8856606 };
1209*2d9fd380Sjfb8856606 
12104418919fSjohnjiang static const enum index next_set_raw[] = {
12114418919fSjohnjiang 	SET_RAW_INDEX,
12124418919fSjohnjiang 	ITEM_ETH,
12134418919fSjohnjiang 	ZERO,
12144418919fSjohnjiang };
12154418919fSjohnjiang 
12164418919fSjohnjiang static const enum index item_tag[] = {
12174418919fSjohnjiang 	ITEM_TAG_DATA,
12184418919fSjohnjiang 	ITEM_TAG_INDEX,
12194418919fSjohnjiang 	ITEM_NEXT,
12204418919fSjohnjiang 	ZERO,
12214418919fSjohnjiang };
12224418919fSjohnjiang 
1223*2d9fd380Sjfb8856606 static const enum index item_l2tpv3oip[] = {
1224*2d9fd380Sjfb8856606 	ITEM_L2TPV3OIP_SESSION_ID,
1225*2d9fd380Sjfb8856606 	ITEM_NEXT,
1226*2d9fd380Sjfb8856606 	ZERO,
1227*2d9fd380Sjfb8856606 };
1228*2d9fd380Sjfb8856606 
1229*2d9fd380Sjfb8856606 static const enum index item_ecpri[] = {
1230*2d9fd380Sjfb8856606 	ITEM_ECPRI_COMMON,
1231*2d9fd380Sjfb8856606 	ITEM_NEXT,
1232*2d9fd380Sjfb8856606 	ZERO,
1233*2d9fd380Sjfb8856606 };
1234*2d9fd380Sjfb8856606 
1235*2d9fd380Sjfb8856606 static const enum index item_ecpri_common[] = {
1236*2d9fd380Sjfb8856606 	ITEM_ECPRI_COMMON_TYPE,
1237*2d9fd380Sjfb8856606 	ZERO,
1238*2d9fd380Sjfb8856606 };
1239*2d9fd380Sjfb8856606 
1240*2d9fd380Sjfb8856606 static const enum index item_ecpri_common_type[] = {
1241*2d9fd380Sjfb8856606 	ITEM_ECPRI_COMMON_TYPE_IQ_DATA,
1242*2d9fd380Sjfb8856606 	ITEM_ECPRI_COMMON_TYPE_RTC_CTRL,
1243*2d9fd380Sjfb8856606 	ITEM_ECPRI_COMMON_TYPE_DLY_MSR,
1244*2d9fd380Sjfb8856606 	ZERO,
1245*2d9fd380Sjfb8856606 };
1246*2d9fd380Sjfb8856606 
12472bfe3f2eSlogwang static const enum index next_action[] = {
12482bfe3f2eSlogwang 	ACTION_END,
12492bfe3f2eSlogwang 	ACTION_VOID,
12502bfe3f2eSlogwang 	ACTION_PASSTHRU,
1251d30ea906Sjfb8856606 	ACTION_JUMP,
12522bfe3f2eSlogwang 	ACTION_MARK,
12532bfe3f2eSlogwang 	ACTION_FLAG,
12542bfe3f2eSlogwang 	ACTION_QUEUE,
12552bfe3f2eSlogwang 	ACTION_DROP,
12562bfe3f2eSlogwang 	ACTION_COUNT,
12572bfe3f2eSlogwang 	ACTION_RSS,
12582bfe3f2eSlogwang 	ACTION_PF,
12592bfe3f2eSlogwang 	ACTION_VF,
1260d30ea906Sjfb8856606 	ACTION_PHY_PORT,
1261d30ea906Sjfb8856606 	ACTION_PORT_ID,
12622bfe3f2eSlogwang 	ACTION_METER,
1263d30ea906Sjfb8856606 	ACTION_OF_SET_MPLS_TTL,
1264d30ea906Sjfb8856606 	ACTION_OF_DEC_MPLS_TTL,
1265d30ea906Sjfb8856606 	ACTION_OF_SET_NW_TTL,
1266d30ea906Sjfb8856606 	ACTION_OF_DEC_NW_TTL,
1267d30ea906Sjfb8856606 	ACTION_OF_COPY_TTL_OUT,
1268d30ea906Sjfb8856606 	ACTION_OF_COPY_TTL_IN,
1269d30ea906Sjfb8856606 	ACTION_OF_POP_VLAN,
1270d30ea906Sjfb8856606 	ACTION_OF_PUSH_VLAN,
1271d30ea906Sjfb8856606 	ACTION_OF_SET_VLAN_VID,
1272d30ea906Sjfb8856606 	ACTION_OF_SET_VLAN_PCP,
1273d30ea906Sjfb8856606 	ACTION_OF_POP_MPLS,
1274d30ea906Sjfb8856606 	ACTION_OF_PUSH_MPLS,
1275d30ea906Sjfb8856606 	ACTION_VXLAN_ENCAP,
1276d30ea906Sjfb8856606 	ACTION_VXLAN_DECAP,
1277d30ea906Sjfb8856606 	ACTION_NVGRE_ENCAP,
1278d30ea906Sjfb8856606 	ACTION_NVGRE_DECAP,
1279d30ea906Sjfb8856606 	ACTION_L2_ENCAP,
1280d30ea906Sjfb8856606 	ACTION_L2_DECAP,
1281d30ea906Sjfb8856606 	ACTION_MPLSOGRE_ENCAP,
1282d30ea906Sjfb8856606 	ACTION_MPLSOGRE_DECAP,
1283d30ea906Sjfb8856606 	ACTION_MPLSOUDP_ENCAP,
1284d30ea906Sjfb8856606 	ACTION_MPLSOUDP_DECAP,
1285d30ea906Sjfb8856606 	ACTION_SET_IPV4_SRC,
1286d30ea906Sjfb8856606 	ACTION_SET_IPV4_DST,
1287d30ea906Sjfb8856606 	ACTION_SET_IPV6_SRC,
1288d30ea906Sjfb8856606 	ACTION_SET_IPV6_DST,
1289d30ea906Sjfb8856606 	ACTION_SET_TP_SRC,
1290d30ea906Sjfb8856606 	ACTION_SET_TP_DST,
1291d30ea906Sjfb8856606 	ACTION_MAC_SWAP,
1292d30ea906Sjfb8856606 	ACTION_DEC_TTL,
1293d30ea906Sjfb8856606 	ACTION_SET_TTL,
1294d30ea906Sjfb8856606 	ACTION_SET_MAC_SRC,
1295d30ea906Sjfb8856606 	ACTION_SET_MAC_DST,
12964418919fSjohnjiang 	ACTION_INC_TCP_SEQ,
12974418919fSjohnjiang 	ACTION_DEC_TCP_SEQ,
12984418919fSjohnjiang 	ACTION_INC_TCP_ACK,
12994418919fSjohnjiang 	ACTION_DEC_TCP_ACK,
13004418919fSjohnjiang 	ACTION_RAW_ENCAP,
13014418919fSjohnjiang 	ACTION_RAW_DECAP,
13024418919fSjohnjiang 	ACTION_SET_TAG,
13034418919fSjohnjiang 	ACTION_SET_META,
1304*2d9fd380Sjfb8856606 	ACTION_SET_IPV4_DSCP,
1305*2d9fd380Sjfb8856606 	ACTION_SET_IPV6_DSCP,
1306*2d9fd380Sjfb8856606 	ACTION_AGE,
1307*2d9fd380Sjfb8856606 	ACTION_SAMPLE,
1308*2d9fd380Sjfb8856606 	ACTION_SHARED,
13092bfe3f2eSlogwang 	ZERO,
13102bfe3f2eSlogwang };
13112bfe3f2eSlogwang 
13122bfe3f2eSlogwang static const enum index action_mark[] = {
13132bfe3f2eSlogwang 	ACTION_MARK_ID,
13142bfe3f2eSlogwang 	ACTION_NEXT,
13152bfe3f2eSlogwang 	ZERO,
13162bfe3f2eSlogwang };
13172bfe3f2eSlogwang 
13182bfe3f2eSlogwang static const enum index action_queue[] = {
13192bfe3f2eSlogwang 	ACTION_QUEUE_INDEX,
13202bfe3f2eSlogwang 	ACTION_NEXT,
13212bfe3f2eSlogwang 	ZERO,
13222bfe3f2eSlogwang };
13232bfe3f2eSlogwang 
1324d30ea906Sjfb8856606 static const enum index action_count[] = {
1325d30ea906Sjfb8856606 	ACTION_COUNT_ID,
1326d30ea906Sjfb8856606 	ACTION_COUNT_SHARED,
13272bfe3f2eSlogwang 	ACTION_NEXT,
13282bfe3f2eSlogwang 	ZERO,
13292bfe3f2eSlogwang };
13302bfe3f2eSlogwang 
13312bfe3f2eSlogwang static const enum index action_rss[] = {
1332d30ea906Sjfb8856606 	ACTION_RSS_FUNC,
1333d30ea906Sjfb8856606 	ACTION_RSS_LEVEL,
1334d30ea906Sjfb8856606 	ACTION_RSS_TYPES,
1335d30ea906Sjfb8856606 	ACTION_RSS_KEY,
1336d30ea906Sjfb8856606 	ACTION_RSS_KEY_LEN,
13372bfe3f2eSlogwang 	ACTION_RSS_QUEUES,
13382bfe3f2eSlogwang 	ACTION_NEXT,
13392bfe3f2eSlogwang 	ZERO,
13402bfe3f2eSlogwang };
13412bfe3f2eSlogwang 
13422bfe3f2eSlogwang static const enum index action_vf[] = {
13432bfe3f2eSlogwang 	ACTION_VF_ORIGINAL,
13442bfe3f2eSlogwang 	ACTION_VF_ID,
13452bfe3f2eSlogwang 	ACTION_NEXT,
13462bfe3f2eSlogwang 	ZERO,
13472bfe3f2eSlogwang };
13482bfe3f2eSlogwang 
1349d30ea906Sjfb8856606 static const enum index action_phy_port[] = {
1350d30ea906Sjfb8856606 	ACTION_PHY_PORT_ORIGINAL,
1351d30ea906Sjfb8856606 	ACTION_PHY_PORT_INDEX,
1352d30ea906Sjfb8856606 	ACTION_NEXT,
1353d30ea906Sjfb8856606 	ZERO,
1354d30ea906Sjfb8856606 };
1355d30ea906Sjfb8856606 
1356d30ea906Sjfb8856606 static const enum index action_port_id[] = {
1357d30ea906Sjfb8856606 	ACTION_PORT_ID_ORIGINAL,
1358d30ea906Sjfb8856606 	ACTION_PORT_ID_ID,
1359d30ea906Sjfb8856606 	ACTION_NEXT,
1360d30ea906Sjfb8856606 	ZERO,
1361d30ea906Sjfb8856606 };
1362d30ea906Sjfb8856606 
13632bfe3f2eSlogwang static const enum index action_meter[] = {
13642bfe3f2eSlogwang 	ACTION_METER_ID,
13652bfe3f2eSlogwang 	ACTION_NEXT,
13662bfe3f2eSlogwang 	ZERO,
13672bfe3f2eSlogwang };
13682bfe3f2eSlogwang 
1369d30ea906Sjfb8856606 static const enum index action_of_set_mpls_ttl[] = {
1370d30ea906Sjfb8856606 	ACTION_OF_SET_MPLS_TTL_MPLS_TTL,
1371d30ea906Sjfb8856606 	ACTION_NEXT,
1372d30ea906Sjfb8856606 	ZERO,
1373d30ea906Sjfb8856606 };
1374d30ea906Sjfb8856606 
1375d30ea906Sjfb8856606 static const enum index action_of_set_nw_ttl[] = {
1376d30ea906Sjfb8856606 	ACTION_OF_SET_NW_TTL_NW_TTL,
1377d30ea906Sjfb8856606 	ACTION_NEXT,
1378d30ea906Sjfb8856606 	ZERO,
1379d30ea906Sjfb8856606 };
1380d30ea906Sjfb8856606 
1381d30ea906Sjfb8856606 static const enum index action_of_push_vlan[] = {
1382d30ea906Sjfb8856606 	ACTION_OF_PUSH_VLAN_ETHERTYPE,
1383d30ea906Sjfb8856606 	ACTION_NEXT,
1384d30ea906Sjfb8856606 	ZERO,
1385d30ea906Sjfb8856606 };
1386d30ea906Sjfb8856606 
1387d30ea906Sjfb8856606 static const enum index action_of_set_vlan_vid[] = {
1388d30ea906Sjfb8856606 	ACTION_OF_SET_VLAN_VID_VLAN_VID,
1389d30ea906Sjfb8856606 	ACTION_NEXT,
1390d30ea906Sjfb8856606 	ZERO,
1391d30ea906Sjfb8856606 };
1392d30ea906Sjfb8856606 
1393d30ea906Sjfb8856606 static const enum index action_of_set_vlan_pcp[] = {
1394d30ea906Sjfb8856606 	ACTION_OF_SET_VLAN_PCP_VLAN_PCP,
1395d30ea906Sjfb8856606 	ACTION_NEXT,
1396d30ea906Sjfb8856606 	ZERO,
1397d30ea906Sjfb8856606 };
1398d30ea906Sjfb8856606 
1399d30ea906Sjfb8856606 static const enum index action_of_pop_mpls[] = {
1400d30ea906Sjfb8856606 	ACTION_OF_POP_MPLS_ETHERTYPE,
1401d30ea906Sjfb8856606 	ACTION_NEXT,
1402d30ea906Sjfb8856606 	ZERO,
1403d30ea906Sjfb8856606 };
1404d30ea906Sjfb8856606 
1405d30ea906Sjfb8856606 static const enum index action_of_push_mpls[] = {
1406d30ea906Sjfb8856606 	ACTION_OF_PUSH_MPLS_ETHERTYPE,
1407d30ea906Sjfb8856606 	ACTION_NEXT,
1408d30ea906Sjfb8856606 	ZERO,
1409d30ea906Sjfb8856606 };
1410d30ea906Sjfb8856606 
1411d30ea906Sjfb8856606 static const enum index action_set_ipv4_src[] = {
1412d30ea906Sjfb8856606 	ACTION_SET_IPV4_SRC_IPV4_SRC,
1413d30ea906Sjfb8856606 	ACTION_NEXT,
1414d30ea906Sjfb8856606 	ZERO,
1415d30ea906Sjfb8856606 };
1416d30ea906Sjfb8856606 
1417d30ea906Sjfb8856606 static const enum index action_set_mac_src[] = {
1418d30ea906Sjfb8856606 	ACTION_SET_MAC_SRC_MAC_SRC,
1419d30ea906Sjfb8856606 	ACTION_NEXT,
1420d30ea906Sjfb8856606 	ZERO,
1421d30ea906Sjfb8856606 };
1422d30ea906Sjfb8856606 
1423d30ea906Sjfb8856606 static const enum index action_set_ipv4_dst[] = {
1424d30ea906Sjfb8856606 	ACTION_SET_IPV4_DST_IPV4_DST,
1425d30ea906Sjfb8856606 	ACTION_NEXT,
1426d30ea906Sjfb8856606 	ZERO,
1427d30ea906Sjfb8856606 };
1428d30ea906Sjfb8856606 
1429d30ea906Sjfb8856606 static const enum index action_set_ipv6_src[] = {
1430d30ea906Sjfb8856606 	ACTION_SET_IPV6_SRC_IPV6_SRC,
1431d30ea906Sjfb8856606 	ACTION_NEXT,
1432d30ea906Sjfb8856606 	ZERO,
1433d30ea906Sjfb8856606 };
1434d30ea906Sjfb8856606 
1435d30ea906Sjfb8856606 static const enum index action_set_ipv6_dst[] = {
1436d30ea906Sjfb8856606 	ACTION_SET_IPV6_DST_IPV6_DST,
1437d30ea906Sjfb8856606 	ACTION_NEXT,
1438d30ea906Sjfb8856606 	ZERO,
1439d30ea906Sjfb8856606 };
1440d30ea906Sjfb8856606 
1441d30ea906Sjfb8856606 static const enum index action_set_tp_src[] = {
1442d30ea906Sjfb8856606 	ACTION_SET_TP_SRC_TP_SRC,
1443d30ea906Sjfb8856606 	ACTION_NEXT,
1444d30ea906Sjfb8856606 	ZERO,
1445d30ea906Sjfb8856606 };
1446d30ea906Sjfb8856606 
1447d30ea906Sjfb8856606 static const enum index action_set_tp_dst[] = {
1448d30ea906Sjfb8856606 	ACTION_SET_TP_DST_TP_DST,
1449d30ea906Sjfb8856606 	ACTION_NEXT,
1450d30ea906Sjfb8856606 	ZERO,
1451d30ea906Sjfb8856606 };
1452d30ea906Sjfb8856606 
1453d30ea906Sjfb8856606 static const enum index action_set_ttl[] = {
1454d30ea906Sjfb8856606 	ACTION_SET_TTL_TTL,
1455d30ea906Sjfb8856606 	ACTION_NEXT,
1456d30ea906Sjfb8856606 	ZERO,
1457d30ea906Sjfb8856606 };
1458d30ea906Sjfb8856606 
1459d30ea906Sjfb8856606 static const enum index action_jump[] = {
1460d30ea906Sjfb8856606 	ACTION_JUMP_GROUP,
1461d30ea906Sjfb8856606 	ACTION_NEXT,
1462d30ea906Sjfb8856606 	ZERO,
1463d30ea906Sjfb8856606 };
1464d30ea906Sjfb8856606 
1465d30ea906Sjfb8856606 static const enum index action_set_mac_dst[] = {
1466d30ea906Sjfb8856606 	ACTION_SET_MAC_DST_MAC_DST,
1467d30ea906Sjfb8856606 	ACTION_NEXT,
1468d30ea906Sjfb8856606 	ZERO,
1469d30ea906Sjfb8856606 };
1470d30ea906Sjfb8856606 
14714418919fSjohnjiang static const enum index action_inc_tcp_seq[] = {
14724418919fSjohnjiang 	ACTION_INC_TCP_SEQ_VALUE,
14734418919fSjohnjiang 	ACTION_NEXT,
14744418919fSjohnjiang 	ZERO,
14754418919fSjohnjiang };
14764418919fSjohnjiang 
14774418919fSjohnjiang static const enum index action_dec_tcp_seq[] = {
14784418919fSjohnjiang 	ACTION_DEC_TCP_SEQ_VALUE,
14794418919fSjohnjiang 	ACTION_NEXT,
14804418919fSjohnjiang 	ZERO,
14814418919fSjohnjiang };
14824418919fSjohnjiang 
14834418919fSjohnjiang static const enum index action_inc_tcp_ack[] = {
14844418919fSjohnjiang 	ACTION_INC_TCP_ACK_VALUE,
14854418919fSjohnjiang 	ACTION_NEXT,
14864418919fSjohnjiang 	ZERO,
14874418919fSjohnjiang };
14884418919fSjohnjiang 
14894418919fSjohnjiang static const enum index action_dec_tcp_ack[] = {
14904418919fSjohnjiang 	ACTION_DEC_TCP_ACK_VALUE,
14914418919fSjohnjiang 	ACTION_NEXT,
14924418919fSjohnjiang 	ZERO,
14934418919fSjohnjiang };
14944418919fSjohnjiang 
14954418919fSjohnjiang static const enum index action_raw_encap[] = {
14964418919fSjohnjiang 	ACTION_RAW_ENCAP_INDEX,
14974418919fSjohnjiang 	ACTION_NEXT,
14984418919fSjohnjiang 	ZERO,
14994418919fSjohnjiang };
15004418919fSjohnjiang 
15014418919fSjohnjiang static const enum index action_raw_decap[] = {
15024418919fSjohnjiang 	ACTION_RAW_DECAP_INDEX,
15034418919fSjohnjiang 	ACTION_NEXT,
15044418919fSjohnjiang 	ZERO,
15054418919fSjohnjiang };
15064418919fSjohnjiang 
15074418919fSjohnjiang static const enum index action_set_tag[] = {
15084418919fSjohnjiang 	ACTION_SET_TAG_DATA,
15094418919fSjohnjiang 	ACTION_SET_TAG_INDEX,
15104418919fSjohnjiang 	ACTION_SET_TAG_MASK,
15114418919fSjohnjiang 	ACTION_NEXT,
15124418919fSjohnjiang 	ZERO,
15134418919fSjohnjiang };
15144418919fSjohnjiang 
15154418919fSjohnjiang static const enum index action_set_meta[] = {
15164418919fSjohnjiang 	ACTION_SET_META_DATA,
15174418919fSjohnjiang 	ACTION_SET_META_MASK,
15184418919fSjohnjiang 	ACTION_NEXT,
15194418919fSjohnjiang 	ZERO,
15204418919fSjohnjiang };
15214418919fSjohnjiang 
1522*2d9fd380Sjfb8856606 static const enum index action_set_ipv4_dscp[] = {
1523*2d9fd380Sjfb8856606 	ACTION_SET_IPV4_DSCP_VALUE,
1524*2d9fd380Sjfb8856606 	ACTION_NEXT,
1525*2d9fd380Sjfb8856606 	ZERO,
1526*2d9fd380Sjfb8856606 };
1527*2d9fd380Sjfb8856606 
1528*2d9fd380Sjfb8856606 static const enum index action_set_ipv6_dscp[] = {
1529*2d9fd380Sjfb8856606 	ACTION_SET_IPV6_DSCP_VALUE,
1530*2d9fd380Sjfb8856606 	ACTION_NEXT,
1531*2d9fd380Sjfb8856606 	ZERO,
1532*2d9fd380Sjfb8856606 };
1533*2d9fd380Sjfb8856606 
1534*2d9fd380Sjfb8856606 static const enum index action_age[] = {
1535*2d9fd380Sjfb8856606 	ACTION_AGE,
1536*2d9fd380Sjfb8856606 	ACTION_AGE_TIMEOUT,
1537*2d9fd380Sjfb8856606 	ACTION_NEXT,
1538*2d9fd380Sjfb8856606 	ZERO,
1539*2d9fd380Sjfb8856606 };
1540*2d9fd380Sjfb8856606 
1541*2d9fd380Sjfb8856606 static const enum index action_sample[] = {
1542*2d9fd380Sjfb8856606 	ACTION_SAMPLE,
1543*2d9fd380Sjfb8856606 	ACTION_SAMPLE_RATIO,
1544*2d9fd380Sjfb8856606 	ACTION_SAMPLE_INDEX,
1545*2d9fd380Sjfb8856606 	ACTION_NEXT,
1546*2d9fd380Sjfb8856606 	ZERO,
1547*2d9fd380Sjfb8856606 };
1548*2d9fd380Sjfb8856606 
1549*2d9fd380Sjfb8856606 static const enum index next_action_sample[] = {
1550*2d9fd380Sjfb8856606 	ACTION_QUEUE,
1551*2d9fd380Sjfb8856606 	ACTION_MARK,
1552*2d9fd380Sjfb8856606 	ACTION_COUNT,
1553*2d9fd380Sjfb8856606 	ACTION_PORT_ID,
1554*2d9fd380Sjfb8856606 	ACTION_RAW_ENCAP,
1555*2d9fd380Sjfb8856606 	ACTION_NEXT,
1556*2d9fd380Sjfb8856606 	ZERO,
1557*2d9fd380Sjfb8856606 };
1558*2d9fd380Sjfb8856606 
15594418919fSjohnjiang static int parse_set_raw_encap_decap(struct context *, const struct token *,
15604418919fSjohnjiang 				     const char *, unsigned int,
15614418919fSjohnjiang 				     void *, unsigned int);
1562*2d9fd380Sjfb8856606 static int parse_set_sample_action(struct context *, const struct token *,
1563*2d9fd380Sjfb8856606 				   const char *, unsigned int,
1564*2d9fd380Sjfb8856606 				   void *, unsigned int);
15654418919fSjohnjiang static int parse_set_init(struct context *, const struct token *,
15664418919fSjohnjiang 			  const char *, unsigned int,
15674418919fSjohnjiang 			  void *, unsigned int);
15682bfe3f2eSlogwang static int parse_init(struct context *, const struct token *,
15692bfe3f2eSlogwang 		      const char *, unsigned int,
15702bfe3f2eSlogwang 		      void *, unsigned int);
15712bfe3f2eSlogwang static int parse_vc(struct context *, const struct token *,
15722bfe3f2eSlogwang 		    const char *, unsigned int,
15732bfe3f2eSlogwang 		    void *, unsigned int);
15742bfe3f2eSlogwang static int parse_vc_spec(struct context *, const struct token *,
15752bfe3f2eSlogwang 			 const char *, unsigned int, void *, unsigned int);
15762bfe3f2eSlogwang static int parse_vc_conf(struct context *, const struct token *,
15772bfe3f2eSlogwang 			 const char *, unsigned int, void *, unsigned int);
1578*2d9fd380Sjfb8856606 static int parse_vc_item_ecpri_type(struct context *, const struct token *,
1579*2d9fd380Sjfb8856606 				    const char *, unsigned int,
1580*2d9fd380Sjfb8856606 				    void *, unsigned int);
1581d30ea906Sjfb8856606 static int parse_vc_action_rss(struct context *, const struct token *,
1582d30ea906Sjfb8856606 			       const char *, unsigned int, void *,
1583d30ea906Sjfb8856606 			       unsigned int);
1584d30ea906Sjfb8856606 static int parse_vc_action_rss_func(struct context *, const struct token *,
1585d30ea906Sjfb8856606 				    const char *, unsigned int, void *,
1586d30ea906Sjfb8856606 				    unsigned int);
1587d30ea906Sjfb8856606 static int parse_vc_action_rss_type(struct context *, const struct token *,
1588d30ea906Sjfb8856606 				    const char *, unsigned int, void *,
1589d30ea906Sjfb8856606 				    unsigned int);
15902bfe3f2eSlogwang static int parse_vc_action_rss_queue(struct context *, const struct token *,
15912bfe3f2eSlogwang 				     const char *, unsigned int, void *,
15922bfe3f2eSlogwang 				     unsigned int);
1593d30ea906Sjfb8856606 static int parse_vc_action_vxlan_encap(struct context *, const struct token *,
1594d30ea906Sjfb8856606 				       const char *, unsigned int, void *,
1595d30ea906Sjfb8856606 				       unsigned int);
1596d30ea906Sjfb8856606 static int parse_vc_action_nvgre_encap(struct context *, const struct token *,
1597d30ea906Sjfb8856606 				       const char *, unsigned int, void *,
1598d30ea906Sjfb8856606 				       unsigned int);
1599d30ea906Sjfb8856606 static int parse_vc_action_l2_encap(struct context *, const struct token *,
1600d30ea906Sjfb8856606 				    const char *, unsigned int, void *,
1601d30ea906Sjfb8856606 				    unsigned int);
1602d30ea906Sjfb8856606 static int parse_vc_action_l2_decap(struct context *, const struct token *,
1603d30ea906Sjfb8856606 				    const char *, unsigned int, void *,
1604d30ea906Sjfb8856606 				    unsigned int);
1605d30ea906Sjfb8856606 static int parse_vc_action_mplsogre_encap(struct context *,
1606d30ea906Sjfb8856606 					  const struct token *, const char *,
1607d30ea906Sjfb8856606 					  unsigned int, void *, unsigned int);
1608d30ea906Sjfb8856606 static int parse_vc_action_mplsogre_decap(struct context *,
1609d30ea906Sjfb8856606 					  const struct token *, const char *,
1610d30ea906Sjfb8856606 					  unsigned int, void *, unsigned int);
1611d30ea906Sjfb8856606 static int parse_vc_action_mplsoudp_encap(struct context *,
1612d30ea906Sjfb8856606 					  const struct token *, const char *,
1613d30ea906Sjfb8856606 					  unsigned int, void *, unsigned int);
1614d30ea906Sjfb8856606 static int parse_vc_action_mplsoudp_decap(struct context *,
1615d30ea906Sjfb8856606 					  const struct token *, const char *,
1616d30ea906Sjfb8856606 					  unsigned int, void *, unsigned int);
16174418919fSjohnjiang static int parse_vc_action_raw_encap(struct context *,
16184418919fSjohnjiang 				     const struct token *, const char *,
16194418919fSjohnjiang 				     unsigned int, void *, unsigned int);
16204418919fSjohnjiang static int parse_vc_action_raw_decap(struct context *,
16214418919fSjohnjiang 				     const struct token *, const char *,
16224418919fSjohnjiang 				     unsigned int, void *, unsigned int);
16234418919fSjohnjiang static int parse_vc_action_raw_encap_index(struct context *,
16244418919fSjohnjiang 					   const struct token *, const char *,
16254418919fSjohnjiang 					   unsigned int, void *, unsigned int);
16264418919fSjohnjiang static int parse_vc_action_raw_decap_index(struct context *,
16274418919fSjohnjiang 					   const struct token *, const char *,
16284418919fSjohnjiang 					   unsigned int, void *, unsigned int);
16294418919fSjohnjiang static int parse_vc_action_set_meta(struct context *ctx,
16304418919fSjohnjiang 				    const struct token *token, const char *str,
16314418919fSjohnjiang 				    unsigned int len, void *buf,
16324418919fSjohnjiang 					unsigned int size);
1633*2d9fd380Sjfb8856606 static int parse_vc_action_sample(struct context *ctx,
1634*2d9fd380Sjfb8856606 				    const struct token *token, const char *str,
1635*2d9fd380Sjfb8856606 				    unsigned int len, void *buf,
1636*2d9fd380Sjfb8856606 				    unsigned int size);
1637*2d9fd380Sjfb8856606 static int
1638*2d9fd380Sjfb8856606 parse_vc_action_sample_index(struct context *ctx, const struct token *token,
1639*2d9fd380Sjfb8856606 				const char *str, unsigned int len, void *buf,
1640*2d9fd380Sjfb8856606 				unsigned int size);
16412bfe3f2eSlogwang static int parse_destroy(struct context *, const struct token *,
16422bfe3f2eSlogwang 			 const char *, unsigned int,
16432bfe3f2eSlogwang 			 void *, unsigned int);
16442bfe3f2eSlogwang static int parse_flush(struct context *, const struct token *,
16452bfe3f2eSlogwang 		       const char *, unsigned int,
16462bfe3f2eSlogwang 		       void *, unsigned int);
1647*2d9fd380Sjfb8856606 static int parse_dump(struct context *, const struct token *,
1648*2d9fd380Sjfb8856606 		      const char *, unsigned int,
1649*2d9fd380Sjfb8856606 		      void *, unsigned int);
16502bfe3f2eSlogwang static int parse_query(struct context *, const struct token *,
16512bfe3f2eSlogwang 		       const char *, unsigned int,
16522bfe3f2eSlogwang 		       void *, unsigned int);
16532bfe3f2eSlogwang static int parse_action(struct context *, const struct token *,
16542bfe3f2eSlogwang 			const char *, unsigned int,
16552bfe3f2eSlogwang 			void *, unsigned int);
16562bfe3f2eSlogwang static int parse_list(struct context *, const struct token *,
16572bfe3f2eSlogwang 		      const char *, unsigned int,
16582bfe3f2eSlogwang 		      void *, unsigned int);
1659*2d9fd380Sjfb8856606 static int parse_aged(struct context *, const struct token *,
1660*2d9fd380Sjfb8856606 		      const char *, unsigned int,
1661*2d9fd380Sjfb8856606 		      void *, unsigned int);
16622bfe3f2eSlogwang static int parse_isolate(struct context *, const struct token *,
16632bfe3f2eSlogwang 			 const char *, unsigned int,
16642bfe3f2eSlogwang 			 void *, unsigned int);
1665*2d9fd380Sjfb8856606 static int parse_tunnel(struct context *, const struct token *,
1666*2d9fd380Sjfb8856606 			const char *, unsigned int,
1667*2d9fd380Sjfb8856606 			void *, unsigned int);
16682bfe3f2eSlogwang static int parse_int(struct context *, const struct token *,
16692bfe3f2eSlogwang 		     const char *, unsigned int,
16702bfe3f2eSlogwang 		     void *, unsigned int);
16712bfe3f2eSlogwang static int parse_prefix(struct context *, const struct token *,
16722bfe3f2eSlogwang 			const char *, unsigned int,
16732bfe3f2eSlogwang 			void *, unsigned int);
16742bfe3f2eSlogwang static int parse_boolean(struct context *, const struct token *,
16752bfe3f2eSlogwang 			 const char *, unsigned int,
16762bfe3f2eSlogwang 			 void *, unsigned int);
16772bfe3f2eSlogwang static int parse_string(struct context *, const struct token *,
16782bfe3f2eSlogwang 			const char *, unsigned int,
16792bfe3f2eSlogwang 			void *, unsigned int);
16801646932aSjfb8856606 static int parse_hex(struct context *ctx, const struct token *token,
16811646932aSjfb8856606 			const char *str, unsigned int len,
16821646932aSjfb8856606 			void *buf, unsigned int size);
1683*2d9fd380Sjfb8856606 static int parse_string0(struct context *, const struct token *,
1684*2d9fd380Sjfb8856606 			const char *, unsigned int,
1685*2d9fd380Sjfb8856606 			void *, unsigned int);
16862bfe3f2eSlogwang static int parse_mac_addr(struct context *, const struct token *,
16872bfe3f2eSlogwang 			  const char *, unsigned int,
16882bfe3f2eSlogwang 			  void *, unsigned int);
16892bfe3f2eSlogwang static int parse_ipv4_addr(struct context *, const struct token *,
16902bfe3f2eSlogwang 			   const char *, unsigned int,
16912bfe3f2eSlogwang 			   void *, unsigned int);
16922bfe3f2eSlogwang static int parse_ipv6_addr(struct context *, const struct token *,
16932bfe3f2eSlogwang 			   const char *, unsigned int,
16942bfe3f2eSlogwang 			   void *, unsigned int);
16952bfe3f2eSlogwang static int parse_port(struct context *, const struct token *,
16962bfe3f2eSlogwang 		      const char *, unsigned int,
16972bfe3f2eSlogwang 		      void *, unsigned int);
1698*2d9fd380Sjfb8856606 static int parse_sa(struct context *, const struct token *,
1699*2d9fd380Sjfb8856606 		    const char *, unsigned int,
1700*2d9fd380Sjfb8856606 		    void *, unsigned int);
1701*2d9fd380Sjfb8856606 static int parse_sa_destroy(struct context *ctx, const struct token *token,
1702*2d9fd380Sjfb8856606 			    const char *str, unsigned int len,
1703*2d9fd380Sjfb8856606 			    void *buf, unsigned int size);
1704*2d9fd380Sjfb8856606 static int parse_sa_id2ptr(struct context *ctx, const struct token *token,
1705*2d9fd380Sjfb8856606 			   const char *str, unsigned int len, void *buf,
1706*2d9fd380Sjfb8856606 			   unsigned int size);
17072bfe3f2eSlogwang static int comp_none(struct context *, const struct token *,
17082bfe3f2eSlogwang 		     unsigned int, char *, unsigned int);
17092bfe3f2eSlogwang static int comp_boolean(struct context *, const struct token *,
17102bfe3f2eSlogwang 			unsigned int, char *, unsigned int);
17112bfe3f2eSlogwang static int comp_action(struct context *, const struct token *,
17122bfe3f2eSlogwang 		       unsigned int, char *, unsigned int);
17132bfe3f2eSlogwang static int comp_port(struct context *, const struct token *,
17142bfe3f2eSlogwang 		     unsigned int, char *, unsigned int);
17152bfe3f2eSlogwang static int comp_rule_id(struct context *, const struct token *,
17162bfe3f2eSlogwang 			unsigned int, char *, unsigned int);
1717d30ea906Sjfb8856606 static int comp_vc_action_rss_type(struct context *, const struct token *,
1718d30ea906Sjfb8856606 				   unsigned int, char *, unsigned int);
17192bfe3f2eSlogwang static int comp_vc_action_rss_queue(struct context *, const struct token *,
17202bfe3f2eSlogwang 				    unsigned int, char *, unsigned int);
17214418919fSjohnjiang static int comp_set_raw_index(struct context *, const struct token *,
17224418919fSjohnjiang 			      unsigned int, char *, unsigned int);
1723*2d9fd380Sjfb8856606 static int comp_set_sample_index(struct context *, const struct token *,
1724*2d9fd380Sjfb8856606 			      unsigned int, char *, unsigned int);
17252bfe3f2eSlogwang 
17262bfe3f2eSlogwang /** Token definitions. */
17272bfe3f2eSlogwang static const struct token token_list[] = {
17282bfe3f2eSlogwang 	/* Special tokens. */
17292bfe3f2eSlogwang 	[ZERO] = {
17302bfe3f2eSlogwang 		.name = "ZERO",
17312bfe3f2eSlogwang 		.help = "null entry, abused as the entry point",
17322bfe3f2eSlogwang 		.next = NEXT(NEXT_ENTRY(FLOW)),
17332bfe3f2eSlogwang 	},
17342bfe3f2eSlogwang 	[END] = {
17352bfe3f2eSlogwang 		.name = "",
17362bfe3f2eSlogwang 		.type = "RETURN",
17372bfe3f2eSlogwang 		.help = "command may end here",
17382bfe3f2eSlogwang 	},
17394418919fSjohnjiang 	[START_SET] = {
17404418919fSjohnjiang 		.name = "START_SET",
17414418919fSjohnjiang 		.help = "null entry, abused as the entry point for set",
17424418919fSjohnjiang 		.next = NEXT(NEXT_ENTRY(SET)),
17434418919fSjohnjiang 	},
17444418919fSjohnjiang 	[END_SET] = {
17454418919fSjohnjiang 		.name = "end_set",
17464418919fSjohnjiang 		.type = "RETURN",
17474418919fSjohnjiang 		.help = "set command may end here",
17484418919fSjohnjiang 	},
17492bfe3f2eSlogwang 	/* Common tokens. */
17502bfe3f2eSlogwang 	[INTEGER] = {
17512bfe3f2eSlogwang 		.name = "{int}",
17522bfe3f2eSlogwang 		.type = "INTEGER",
17532bfe3f2eSlogwang 		.help = "integer value",
17542bfe3f2eSlogwang 		.call = parse_int,
17552bfe3f2eSlogwang 		.comp = comp_none,
17562bfe3f2eSlogwang 	},
17572bfe3f2eSlogwang 	[UNSIGNED] = {
17582bfe3f2eSlogwang 		.name = "{unsigned}",
17592bfe3f2eSlogwang 		.type = "UNSIGNED",
17602bfe3f2eSlogwang 		.help = "unsigned integer value",
17612bfe3f2eSlogwang 		.call = parse_int,
17622bfe3f2eSlogwang 		.comp = comp_none,
17632bfe3f2eSlogwang 	},
17642bfe3f2eSlogwang 	[PREFIX] = {
17652bfe3f2eSlogwang 		.name = "{prefix}",
17662bfe3f2eSlogwang 		.type = "PREFIX",
17672bfe3f2eSlogwang 		.help = "prefix length for bit-mask",
17682bfe3f2eSlogwang 		.call = parse_prefix,
17692bfe3f2eSlogwang 		.comp = comp_none,
17702bfe3f2eSlogwang 	},
17712bfe3f2eSlogwang 	[BOOLEAN] = {
17722bfe3f2eSlogwang 		.name = "{boolean}",
17732bfe3f2eSlogwang 		.type = "BOOLEAN",
17742bfe3f2eSlogwang 		.help = "any boolean value",
17752bfe3f2eSlogwang 		.call = parse_boolean,
17762bfe3f2eSlogwang 		.comp = comp_boolean,
17772bfe3f2eSlogwang 	},
17782bfe3f2eSlogwang 	[STRING] = {
17792bfe3f2eSlogwang 		.name = "{string}",
17802bfe3f2eSlogwang 		.type = "STRING",
17812bfe3f2eSlogwang 		.help = "fixed string",
17822bfe3f2eSlogwang 		.call = parse_string,
17832bfe3f2eSlogwang 		.comp = comp_none,
17842bfe3f2eSlogwang 	},
17851646932aSjfb8856606 	[HEX] = {
17861646932aSjfb8856606 		.name = "{hex}",
17871646932aSjfb8856606 		.type = "HEX",
17881646932aSjfb8856606 		.help = "fixed string",
17891646932aSjfb8856606 		.call = parse_hex,
1790*2d9fd380Sjfb8856606 	},
1791*2d9fd380Sjfb8856606 	[FILE_PATH] = {
1792*2d9fd380Sjfb8856606 		.name = "{file path}",
1793*2d9fd380Sjfb8856606 		.type = "STRING",
1794*2d9fd380Sjfb8856606 		.help = "file path",
1795*2d9fd380Sjfb8856606 		.call = parse_string0,
17961646932aSjfb8856606 		.comp = comp_none,
17971646932aSjfb8856606 	},
17982bfe3f2eSlogwang 	[MAC_ADDR] = {
17992bfe3f2eSlogwang 		.name = "{MAC address}",
18002bfe3f2eSlogwang 		.type = "MAC-48",
18012bfe3f2eSlogwang 		.help = "standard MAC address notation",
18022bfe3f2eSlogwang 		.call = parse_mac_addr,
18032bfe3f2eSlogwang 		.comp = comp_none,
18042bfe3f2eSlogwang 	},
18052bfe3f2eSlogwang 	[IPV4_ADDR] = {
18062bfe3f2eSlogwang 		.name = "{IPv4 address}",
18072bfe3f2eSlogwang 		.type = "IPV4 ADDRESS",
18082bfe3f2eSlogwang 		.help = "standard IPv4 address notation",
18092bfe3f2eSlogwang 		.call = parse_ipv4_addr,
18102bfe3f2eSlogwang 		.comp = comp_none,
18112bfe3f2eSlogwang 	},
18122bfe3f2eSlogwang 	[IPV6_ADDR] = {
18132bfe3f2eSlogwang 		.name = "{IPv6 address}",
18142bfe3f2eSlogwang 		.type = "IPV6 ADDRESS",
18152bfe3f2eSlogwang 		.help = "standard IPv6 address notation",
18162bfe3f2eSlogwang 		.call = parse_ipv6_addr,
18172bfe3f2eSlogwang 		.comp = comp_none,
18182bfe3f2eSlogwang 	},
18192bfe3f2eSlogwang 	[RULE_ID] = {
18202bfe3f2eSlogwang 		.name = "{rule id}",
18212bfe3f2eSlogwang 		.type = "RULE ID",
18222bfe3f2eSlogwang 		.help = "rule identifier",
18232bfe3f2eSlogwang 		.call = parse_int,
18242bfe3f2eSlogwang 		.comp = comp_rule_id,
18252bfe3f2eSlogwang 	},
18262bfe3f2eSlogwang 	[PORT_ID] = {
18272bfe3f2eSlogwang 		.name = "{port_id}",
18282bfe3f2eSlogwang 		.type = "PORT ID",
18292bfe3f2eSlogwang 		.help = "port identifier",
18302bfe3f2eSlogwang 		.call = parse_port,
18312bfe3f2eSlogwang 		.comp = comp_port,
18322bfe3f2eSlogwang 	},
18332bfe3f2eSlogwang 	[GROUP_ID] = {
18342bfe3f2eSlogwang 		.name = "{group_id}",
18352bfe3f2eSlogwang 		.type = "GROUP ID",
18362bfe3f2eSlogwang 		.help = "group identifier",
18372bfe3f2eSlogwang 		.call = parse_int,
18382bfe3f2eSlogwang 		.comp = comp_none,
18392bfe3f2eSlogwang 	},
18402bfe3f2eSlogwang 	[PRIORITY_LEVEL] = {
18412bfe3f2eSlogwang 		.name = "{level}",
18422bfe3f2eSlogwang 		.type = "PRIORITY",
18432bfe3f2eSlogwang 		.help = "priority level",
18442bfe3f2eSlogwang 		.call = parse_int,
18452bfe3f2eSlogwang 		.comp = comp_none,
18462bfe3f2eSlogwang 	},
1847*2d9fd380Sjfb8856606 	[SHARED_ACTION_ID] = {
1848*2d9fd380Sjfb8856606 		.name = "{shared_action_id}",
1849*2d9fd380Sjfb8856606 		.type = "SHARED_ACTION_ID",
1850*2d9fd380Sjfb8856606 		.help = "shared action id",
1851*2d9fd380Sjfb8856606 		.call = parse_int,
1852*2d9fd380Sjfb8856606 		.comp = comp_none,
1853*2d9fd380Sjfb8856606 	},
18542bfe3f2eSlogwang 	/* Top-level command. */
18552bfe3f2eSlogwang 	[FLOW] = {
18562bfe3f2eSlogwang 		.name = "flow",
18572bfe3f2eSlogwang 		.type = "{command} {port_id} [{arg} [...]]",
18582bfe3f2eSlogwang 		.help = "manage ingress/egress flow rules",
18592bfe3f2eSlogwang 		.next = NEXT(NEXT_ENTRY
1860*2d9fd380Sjfb8856606 			     (SHARED_ACTION,
1861*2d9fd380Sjfb8856606 			      VALIDATE,
18622bfe3f2eSlogwang 			      CREATE,
18632bfe3f2eSlogwang 			      DESTROY,
18642bfe3f2eSlogwang 			      FLUSH,
1865*2d9fd380Sjfb8856606 			      DUMP,
18662bfe3f2eSlogwang 			      LIST,
1867*2d9fd380Sjfb8856606 			      AGED,
18682bfe3f2eSlogwang 			      QUERY,
1869*2d9fd380Sjfb8856606 			      ISOLATE,
1870*2d9fd380Sjfb8856606 			      TUNNEL)),
18712bfe3f2eSlogwang 		.call = parse_init,
18722bfe3f2eSlogwang 	},
1873*2d9fd380Sjfb8856606 	/* Top-level command. */
1874*2d9fd380Sjfb8856606 	[SHARED_ACTION] = {
1875*2d9fd380Sjfb8856606 		.name = "shared_action",
1876*2d9fd380Sjfb8856606 		.type = "{command} {port_id} [{arg} [...]]",
1877*2d9fd380Sjfb8856606 		.help = "manage shared actions",
1878*2d9fd380Sjfb8856606 		.next = NEXT(next_sa_subcmd, NEXT_ENTRY(PORT_ID)),
1879*2d9fd380Sjfb8856606 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
1880*2d9fd380Sjfb8856606 		.call = parse_sa,
1881*2d9fd380Sjfb8856606 	},
18822bfe3f2eSlogwang 	/* Sub-level commands. */
1883*2d9fd380Sjfb8856606 	[SHARED_ACTION_CREATE] = {
1884*2d9fd380Sjfb8856606 		.name = "create",
1885*2d9fd380Sjfb8856606 		.help = "create shared action",
1886*2d9fd380Sjfb8856606 		.next = NEXT(next_sa_create_attr),
1887*2d9fd380Sjfb8856606 		.call = parse_sa,
1888*2d9fd380Sjfb8856606 	},
1889*2d9fd380Sjfb8856606 	[SHARED_ACTION_UPDATE] = {
1890*2d9fd380Sjfb8856606 		.name = "update",
1891*2d9fd380Sjfb8856606 		.help = "update shared action",
1892*2d9fd380Sjfb8856606 		.next = NEXT(NEXT_ENTRY(SHARED_ACTION_SPEC),
1893*2d9fd380Sjfb8856606 			     NEXT_ENTRY(SHARED_ACTION_ID)),
1894*2d9fd380Sjfb8856606 		.args = ARGS(ARGS_ENTRY(struct buffer, args.vc.attr.group)),
1895*2d9fd380Sjfb8856606 		.call = parse_sa,
1896*2d9fd380Sjfb8856606 	},
1897*2d9fd380Sjfb8856606 	[SHARED_ACTION_DESTROY] = {
1898*2d9fd380Sjfb8856606 		.name = "destroy",
1899*2d9fd380Sjfb8856606 		.help = "destroy shared action",
1900*2d9fd380Sjfb8856606 		.next = NEXT(NEXT_ENTRY(SHARED_ACTION_DESTROY_ID)),
1901*2d9fd380Sjfb8856606 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
1902*2d9fd380Sjfb8856606 		.call = parse_sa_destroy,
1903*2d9fd380Sjfb8856606 	},
1904*2d9fd380Sjfb8856606 	[SHARED_ACTION_QUERY] = {
1905*2d9fd380Sjfb8856606 		.name = "query",
1906*2d9fd380Sjfb8856606 		.help = "query shared action",
1907*2d9fd380Sjfb8856606 		.next = NEXT(NEXT_ENTRY(END), NEXT_ENTRY(SHARED_ACTION_ID)),
1908*2d9fd380Sjfb8856606 		.args = ARGS(ARGS_ENTRY(struct buffer, args.sa.action_id)),
1909*2d9fd380Sjfb8856606 		.call = parse_sa,
1910*2d9fd380Sjfb8856606 	},
19112bfe3f2eSlogwang 	[VALIDATE] = {
19122bfe3f2eSlogwang 		.name = "validate",
19132bfe3f2eSlogwang 		.help = "check whether a flow rule can be created",
19142bfe3f2eSlogwang 		.next = NEXT(next_vc_attr, NEXT_ENTRY(PORT_ID)),
19152bfe3f2eSlogwang 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
19162bfe3f2eSlogwang 		.call = parse_vc,
19172bfe3f2eSlogwang 	},
19182bfe3f2eSlogwang 	[CREATE] = {
19192bfe3f2eSlogwang 		.name = "create",
19202bfe3f2eSlogwang 		.help = "create a flow rule",
19212bfe3f2eSlogwang 		.next = NEXT(next_vc_attr, NEXT_ENTRY(PORT_ID)),
19222bfe3f2eSlogwang 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
19232bfe3f2eSlogwang 		.call = parse_vc,
19242bfe3f2eSlogwang 	},
19252bfe3f2eSlogwang 	[DESTROY] = {
19262bfe3f2eSlogwang 		.name = "destroy",
19272bfe3f2eSlogwang 		.help = "destroy specific flow rules",
19282bfe3f2eSlogwang 		.next = NEXT(NEXT_ENTRY(DESTROY_RULE), NEXT_ENTRY(PORT_ID)),
19292bfe3f2eSlogwang 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
19302bfe3f2eSlogwang 		.call = parse_destroy,
19312bfe3f2eSlogwang 	},
19322bfe3f2eSlogwang 	[FLUSH] = {
19332bfe3f2eSlogwang 		.name = "flush",
19342bfe3f2eSlogwang 		.help = "destroy all flow rules",
19352bfe3f2eSlogwang 		.next = NEXT(NEXT_ENTRY(PORT_ID)),
19362bfe3f2eSlogwang 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
19372bfe3f2eSlogwang 		.call = parse_flush,
19382bfe3f2eSlogwang 	},
1939*2d9fd380Sjfb8856606 	[DUMP] = {
1940*2d9fd380Sjfb8856606 		.name = "dump",
1941*2d9fd380Sjfb8856606 		.help = "dump all flow rules to file",
1942*2d9fd380Sjfb8856606 		.next = NEXT(next_dump_attr, NEXT_ENTRY(PORT_ID)),
1943*2d9fd380Sjfb8856606 		.args = ARGS(ARGS_ENTRY(struct buffer, args.dump.file),
1944*2d9fd380Sjfb8856606 			     ARGS_ENTRY(struct buffer, port)),
1945*2d9fd380Sjfb8856606 		.call = parse_dump,
1946*2d9fd380Sjfb8856606 	},
19472bfe3f2eSlogwang 	[QUERY] = {
19482bfe3f2eSlogwang 		.name = "query",
19492bfe3f2eSlogwang 		.help = "query an existing flow rule",
19502bfe3f2eSlogwang 		.next = NEXT(NEXT_ENTRY(QUERY_ACTION),
19512bfe3f2eSlogwang 			     NEXT_ENTRY(RULE_ID),
19522bfe3f2eSlogwang 			     NEXT_ENTRY(PORT_ID)),
1953d30ea906Sjfb8856606 		.args = ARGS(ARGS_ENTRY(struct buffer, args.query.action.type),
19542bfe3f2eSlogwang 			     ARGS_ENTRY(struct buffer, args.query.rule),
19552bfe3f2eSlogwang 			     ARGS_ENTRY(struct buffer, port)),
19562bfe3f2eSlogwang 		.call = parse_query,
19572bfe3f2eSlogwang 	},
19582bfe3f2eSlogwang 	[LIST] = {
19592bfe3f2eSlogwang 		.name = "list",
19602bfe3f2eSlogwang 		.help = "list existing flow rules",
19612bfe3f2eSlogwang 		.next = NEXT(next_list_attr, NEXT_ENTRY(PORT_ID)),
19622bfe3f2eSlogwang 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
19632bfe3f2eSlogwang 		.call = parse_list,
19642bfe3f2eSlogwang 	},
1965*2d9fd380Sjfb8856606 	[AGED] = {
1966*2d9fd380Sjfb8856606 		.name = "aged",
1967*2d9fd380Sjfb8856606 		.help = "list and destroy aged flows",
1968*2d9fd380Sjfb8856606 		.next = NEXT(next_aged_attr, NEXT_ENTRY(PORT_ID)),
1969*2d9fd380Sjfb8856606 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
1970*2d9fd380Sjfb8856606 		.call = parse_aged,
1971*2d9fd380Sjfb8856606 	},
19722bfe3f2eSlogwang 	[ISOLATE] = {
19732bfe3f2eSlogwang 		.name = "isolate",
19742bfe3f2eSlogwang 		.help = "restrict ingress traffic to the defined flow rules",
19752bfe3f2eSlogwang 		.next = NEXT(NEXT_ENTRY(BOOLEAN),
19762bfe3f2eSlogwang 			     NEXT_ENTRY(PORT_ID)),
19772bfe3f2eSlogwang 		.args = ARGS(ARGS_ENTRY(struct buffer, args.isolate.set),
19782bfe3f2eSlogwang 			     ARGS_ENTRY(struct buffer, port)),
19792bfe3f2eSlogwang 		.call = parse_isolate,
19802bfe3f2eSlogwang 	},
1981*2d9fd380Sjfb8856606 	[TUNNEL] = {
1982*2d9fd380Sjfb8856606 		.name = "tunnel",
1983*2d9fd380Sjfb8856606 		.help = "new tunnel API",
1984*2d9fd380Sjfb8856606 		.next = NEXT(NEXT_ENTRY
1985*2d9fd380Sjfb8856606 			     (TUNNEL_CREATE, TUNNEL_LIST, TUNNEL_DESTROY)),
1986*2d9fd380Sjfb8856606 		.call = parse_tunnel,
1987*2d9fd380Sjfb8856606 	},
1988*2d9fd380Sjfb8856606 	/* Tunnel arguments. */
1989*2d9fd380Sjfb8856606 	[TUNNEL_CREATE] = {
1990*2d9fd380Sjfb8856606 		.name = "create",
1991*2d9fd380Sjfb8856606 		.help = "create new tunnel object",
1992*2d9fd380Sjfb8856606 		.next = NEXT(NEXT_ENTRY(TUNNEL_CREATE_TYPE),
1993*2d9fd380Sjfb8856606 			     NEXT_ENTRY(PORT_ID)),
1994*2d9fd380Sjfb8856606 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
1995*2d9fd380Sjfb8856606 		.call = parse_tunnel,
1996*2d9fd380Sjfb8856606 	},
1997*2d9fd380Sjfb8856606 	[TUNNEL_CREATE_TYPE] = {
1998*2d9fd380Sjfb8856606 		.name = "type",
1999*2d9fd380Sjfb8856606 		.help = "create new tunnel",
2000*2d9fd380Sjfb8856606 		.next = NEXT(NEXT_ENTRY(FILE_PATH)),
2001*2d9fd380Sjfb8856606 		.args = ARGS(ARGS_ENTRY(struct tunnel_ops, type)),
2002*2d9fd380Sjfb8856606 		.call = parse_tunnel,
2003*2d9fd380Sjfb8856606 	},
2004*2d9fd380Sjfb8856606 	[TUNNEL_DESTROY] = {
2005*2d9fd380Sjfb8856606 		.name = "destroy",
2006*2d9fd380Sjfb8856606 		.help = "destroy tunel",
2007*2d9fd380Sjfb8856606 		.next = NEXT(NEXT_ENTRY(TUNNEL_DESTROY_ID),
2008*2d9fd380Sjfb8856606 			     NEXT_ENTRY(PORT_ID)),
2009*2d9fd380Sjfb8856606 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
2010*2d9fd380Sjfb8856606 		.call = parse_tunnel,
2011*2d9fd380Sjfb8856606 	},
2012*2d9fd380Sjfb8856606 	[TUNNEL_DESTROY_ID] = {
2013*2d9fd380Sjfb8856606 		.name = "id",
2014*2d9fd380Sjfb8856606 		.help = "tunnel identifier to testroy",
2015*2d9fd380Sjfb8856606 		.next = NEXT(NEXT_ENTRY(UNSIGNED)),
2016*2d9fd380Sjfb8856606 		.args = ARGS(ARGS_ENTRY(struct tunnel_ops, id)),
2017*2d9fd380Sjfb8856606 		.call = parse_tunnel,
2018*2d9fd380Sjfb8856606 	},
2019*2d9fd380Sjfb8856606 	[TUNNEL_LIST] = {
2020*2d9fd380Sjfb8856606 		.name = "list",
2021*2d9fd380Sjfb8856606 		.help = "list existing tunnels",
2022*2d9fd380Sjfb8856606 		.next = NEXT(NEXT_ENTRY(PORT_ID)),
2023*2d9fd380Sjfb8856606 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
2024*2d9fd380Sjfb8856606 		.call = parse_tunnel,
2025*2d9fd380Sjfb8856606 	},
20262bfe3f2eSlogwang 	/* Destroy arguments. */
20272bfe3f2eSlogwang 	[DESTROY_RULE] = {
20282bfe3f2eSlogwang 		.name = "rule",
20292bfe3f2eSlogwang 		.help = "specify a rule identifier",
20302bfe3f2eSlogwang 		.next = NEXT(next_destroy_attr, NEXT_ENTRY(RULE_ID)),
20312bfe3f2eSlogwang 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer, args.destroy.rule)),
20322bfe3f2eSlogwang 		.call = parse_destroy,
20332bfe3f2eSlogwang 	},
20342bfe3f2eSlogwang 	/* Query arguments. */
20352bfe3f2eSlogwang 	[QUERY_ACTION] = {
20362bfe3f2eSlogwang 		.name = "{action}",
20372bfe3f2eSlogwang 		.type = "ACTION",
20382bfe3f2eSlogwang 		.help = "action to query, must be part of the rule",
20392bfe3f2eSlogwang 		.call = parse_action,
20402bfe3f2eSlogwang 		.comp = comp_action,
20412bfe3f2eSlogwang 	},
20422bfe3f2eSlogwang 	/* List arguments. */
20432bfe3f2eSlogwang 	[LIST_GROUP] = {
20442bfe3f2eSlogwang 		.name = "group",
20452bfe3f2eSlogwang 		.help = "specify a group",
20462bfe3f2eSlogwang 		.next = NEXT(next_list_attr, NEXT_ENTRY(GROUP_ID)),
20472bfe3f2eSlogwang 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer, args.list.group)),
20482bfe3f2eSlogwang 		.call = parse_list,
20492bfe3f2eSlogwang 	},
2050*2d9fd380Sjfb8856606 	[AGED_DESTROY] = {
2051*2d9fd380Sjfb8856606 		.name = "destroy",
2052*2d9fd380Sjfb8856606 		.help = "specify aged flows need be destroyed",
2053*2d9fd380Sjfb8856606 		.call = parse_aged,
2054*2d9fd380Sjfb8856606 		.comp = comp_none,
2055*2d9fd380Sjfb8856606 	},
20562bfe3f2eSlogwang 	/* Validate/create attributes. */
20572bfe3f2eSlogwang 	[GROUP] = {
20582bfe3f2eSlogwang 		.name = "group",
20592bfe3f2eSlogwang 		.help = "specify a group",
20602bfe3f2eSlogwang 		.next = NEXT(next_vc_attr, NEXT_ENTRY(GROUP_ID)),
20612bfe3f2eSlogwang 		.args = ARGS(ARGS_ENTRY(struct rte_flow_attr, group)),
20622bfe3f2eSlogwang 		.call = parse_vc,
20632bfe3f2eSlogwang 	},
20642bfe3f2eSlogwang 	[PRIORITY] = {
20652bfe3f2eSlogwang 		.name = "priority",
20662bfe3f2eSlogwang 		.help = "specify a priority level",
20672bfe3f2eSlogwang 		.next = NEXT(next_vc_attr, NEXT_ENTRY(PRIORITY_LEVEL)),
20682bfe3f2eSlogwang 		.args = ARGS(ARGS_ENTRY(struct rte_flow_attr, priority)),
20692bfe3f2eSlogwang 		.call = parse_vc,
20702bfe3f2eSlogwang 	},
20712bfe3f2eSlogwang 	[INGRESS] = {
20722bfe3f2eSlogwang 		.name = "ingress",
20732bfe3f2eSlogwang 		.help = "affect rule to ingress",
20742bfe3f2eSlogwang 		.next = NEXT(next_vc_attr),
20752bfe3f2eSlogwang 		.call = parse_vc,
20762bfe3f2eSlogwang 	},
20772bfe3f2eSlogwang 	[EGRESS] = {
20782bfe3f2eSlogwang 		.name = "egress",
20792bfe3f2eSlogwang 		.help = "affect rule to egress",
20802bfe3f2eSlogwang 		.next = NEXT(next_vc_attr),
20812bfe3f2eSlogwang 		.call = parse_vc,
20822bfe3f2eSlogwang 	},
2083d30ea906Sjfb8856606 	[TRANSFER] = {
2084d30ea906Sjfb8856606 		.name = "transfer",
2085d30ea906Sjfb8856606 		.help = "apply rule directly to endpoints found in pattern",
2086d30ea906Sjfb8856606 		.next = NEXT(next_vc_attr),
2087d30ea906Sjfb8856606 		.call = parse_vc,
2088d30ea906Sjfb8856606 	},
2089*2d9fd380Sjfb8856606 	[TUNNEL_SET] = {
2090*2d9fd380Sjfb8856606 		.name = "tunnel_set",
2091*2d9fd380Sjfb8856606 		.help = "tunnel steer rule",
2092*2d9fd380Sjfb8856606 		.next = NEXT(next_vc_attr, NEXT_ENTRY(UNSIGNED)),
2093*2d9fd380Sjfb8856606 		.args = ARGS(ARGS_ENTRY(struct tunnel_ops, id)),
2094*2d9fd380Sjfb8856606 		.call = parse_vc,
2095*2d9fd380Sjfb8856606 	},
2096*2d9fd380Sjfb8856606 	[TUNNEL_MATCH] = {
2097*2d9fd380Sjfb8856606 		.name = "tunnel_match",
2098*2d9fd380Sjfb8856606 		.help = "tunnel match rule",
2099*2d9fd380Sjfb8856606 		.next = NEXT(next_vc_attr, NEXT_ENTRY(UNSIGNED)),
2100*2d9fd380Sjfb8856606 		.args = ARGS(ARGS_ENTRY(struct tunnel_ops, id)),
2101*2d9fd380Sjfb8856606 		.call = parse_vc,
2102*2d9fd380Sjfb8856606 	},
21032bfe3f2eSlogwang 	/* Validate/create pattern. */
21042bfe3f2eSlogwang 	[PATTERN] = {
21052bfe3f2eSlogwang 		.name = "pattern",
21062bfe3f2eSlogwang 		.help = "submit a list of pattern items",
21072bfe3f2eSlogwang 		.next = NEXT(next_item),
21082bfe3f2eSlogwang 		.call = parse_vc,
21092bfe3f2eSlogwang 	},
21102bfe3f2eSlogwang 	[ITEM_PARAM_IS] = {
21112bfe3f2eSlogwang 		.name = "is",
21122bfe3f2eSlogwang 		.help = "match value perfectly (with full bit-mask)",
21132bfe3f2eSlogwang 		.call = parse_vc_spec,
21142bfe3f2eSlogwang 	},
21152bfe3f2eSlogwang 	[ITEM_PARAM_SPEC] = {
21162bfe3f2eSlogwang 		.name = "spec",
21172bfe3f2eSlogwang 		.help = "match value according to configured bit-mask",
21182bfe3f2eSlogwang 		.call = parse_vc_spec,
21192bfe3f2eSlogwang 	},
21202bfe3f2eSlogwang 	[ITEM_PARAM_LAST] = {
21212bfe3f2eSlogwang 		.name = "last",
21222bfe3f2eSlogwang 		.help = "specify upper bound to establish a range",
21232bfe3f2eSlogwang 		.call = parse_vc_spec,
21242bfe3f2eSlogwang 	},
21252bfe3f2eSlogwang 	[ITEM_PARAM_MASK] = {
21262bfe3f2eSlogwang 		.name = "mask",
21272bfe3f2eSlogwang 		.help = "specify bit-mask with relevant bits set to one",
21282bfe3f2eSlogwang 		.call = parse_vc_spec,
21292bfe3f2eSlogwang 	},
21302bfe3f2eSlogwang 	[ITEM_PARAM_PREFIX] = {
21312bfe3f2eSlogwang 		.name = "prefix",
21322bfe3f2eSlogwang 		.help = "generate bit-mask from a prefix length",
21332bfe3f2eSlogwang 		.call = parse_vc_spec,
21342bfe3f2eSlogwang 	},
21352bfe3f2eSlogwang 	[ITEM_NEXT] = {
21362bfe3f2eSlogwang 		.name = "/",
21372bfe3f2eSlogwang 		.help = "specify next pattern item",
21382bfe3f2eSlogwang 		.next = NEXT(next_item),
21392bfe3f2eSlogwang 	},
21402bfe3f2eSlogwang 	[ITEM_END] = {
21412bfe3f2eSlogwang 		.name = "end",
21422bfe3f2eSlogwang 		.help = "end list of pattern items",
21432bfe3f2eSlogwang 		.priv = PRIV_ITEM(END, 0),
21442bfe3f2eSlogwang 		.next = NEXT(NEXT_ENTRY(ACTIONS)),
21452bfe3f2eSlogwang 		.call = parse_vc,
21462bfe3f2eSlogwang 	},
21472bfe3f2eSlogwang 	[ITEM_VOID] = {
21482bfe3f2eSlogwang 		.name = "void",
21492bfe3f2eSlogwang 		.help = "no-op pattern item",
21502bfe3f2eSlogwang 		.priv = PRIV_ITEM(VOID, 0),
21512bfe3f2eSlogwang 		.next = NEXT(NEXT_ENTRY(ITEM_NEXT)),
21522bfe3f2eSlogwang 		.call = parse_vc,
21532bfe3f2eSlogwang 	},
21542bfe3f2eSlogwang 	[ITEM_INVERT] = {
21552bfe3f2eSlogwang 		.name = "invert",
21562bfe3f2eSlogwang 		.help = "perform actions when pattern does not match",
21572bfe3f2eSlogwang 		.priv = PRIV_ITEM(INVERT, 0),
21582bfe3f2eSlogwang 		.next = NEXT(NEXT_ENTRY(ITEM_NEXT)),
21592bfe3f2eSlogwang 		.call = parse_vc,
21602bfe3f2eSlogwang 	},
21612bfe3f2eSlogwang 	[ITEM_ANY] = {
21622bfe3f2eSlogwang 		.name = "any",
21632bfe3f2eSlogwang 		.help = "match any protocol for the current layer",
21642bfe3f2eSlogwang 		.priv = PRIV_ITEM(ANY, sizeof(struct rte_flow_item_any)),
21652bfe3f2eSlogwang 		.next = NEXT(item_any),
21662bfe3f2eSlogwang 		.call = parse_vc,
21672bfe3f2eSlogwang 	},
21682bfe3f2eSlogwang 	[ITEM_ANY_NUM] = {
21692bfe3f2eSlogwang 		.name = "num",
21702bfe3f2eSlogwang 		.help = "number of layers covered",
21712bfe3f2eSlogwang 		.next = NEXT(item_any, NEXT_ENTRY(UNSIGNED), item_param),
21722bfe3f2eSlogwang 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_any, num)),
21732bfe3f2eSlogwang 	},
21742bfe3f2eSlogwang 	[ITEM_PF] = {
21752bfe3f2eSlogwang 		.name = "pf",
2176d30ea906Sjfb8856606 		.help = "match traffic from/to the physical function",
21772bfe3f2eSlogwang 		.priv = PRIV_ITEM(PF, 0),
21782bfe3f2eSlogwang 		.next = NEXT(NEXT_ENTRY(ITEM_NEXT)),
21792bfe3f2eSlogwang 		.call = parse_vc,
21802bfe3f2eSlogwang 	},
21812bfe3f2eSlogwang 	[ITEM_VF] = {
21822bfe3f2eSlogwang 		.name = "vf",
2183d30ea906Sjfb8856606 		.help = "match traffic from/to a virtual function ID",
21842bfe3f2eSlogwang 		.priv = PRIV_ITEM(VF, sizeof(struct rte_flow_item_vf)),
21852bfe3f2eSlogwang 		.next = NEXT(item_vf),
21862bfe3f2eSlogwang 		.call = parse_vc,
21872bfe3f2eSlogwang 	},
21882bfe3f2eSlogwang 	[ITEM_VF_ID] = {
21892bfe3f2eSlogwang 		.name = "id",
2190d30ea906Sjfb8856606 		.help = "VF ID",
21912bfe3f2eSlogwang 		.next = NEXT(item_vf, NEXT_ENTRY(UNSIGNED), item_param),
21922bfe3f2eSlogwang 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_vf, id)),
21932bfe3f2eSlogwang 	},
2194d30ea906Sjfb8856606 	[ITEM_PHY_PORT] = {
2195d30ea906Sjfb8856606 		.name = "phy_port",
2196d30ea906Sjfb8856606 		.help = "match traffic from/to a specific physical port",
2197d30ea906Sjfb8856606 		.priv = PRIV_ITEM(PHY_PORT,
2198d30ea906Sjfb8856606 				  sizeof(struct rte_flow_item_phy_port)),
2199d30ea906Sjfb8856606 		.next = NEXT(item_phy_port),
22002bfe3f2eSlogwang 		.call = parse_vc,
22012bfe3f2eSlogwang 	},
2202d30ea906Sjfb8856606 	[ITEM_PHY_PORT_INDEX] = {
22032bfe3f2eSlogwang 		.name = "index",
22042bfe3f2eSlogwang 		.help = "physical port index",
2205d30ea906Sjfb8856606 		.next = NEXT(item_phy_port, NEXT_ENTRY(UNSIGNED), item_param),
2206d30ea906Sjfb8856606 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_phy_port, index)),
2207d30ea906Sjfb8856606 	},
2208d30ea906Sjfb8856606 	[ITEM_PORT_ID] = {
2209d30ea906Sjfb8856606 		.name = "port_id",
2210d30ea906Sjfb8856606 		.help = "match traffic from/to a given DPDK port ID",
2211d30ea906Sjfb8856606 		.priv = PRIV_ITEM(PORT_ID,
2212d30ea906Sjfb8856606 				  sizeof(struct rte_flow_item_port_id)),
2213d30ea906Sjfb8856606 		.next = NEXT(item_port_id),
2214d30ea906Sjfb8856606 		.call = parse_vc,
2215d30ea906Sjfb8856606 	},
2216d30ea906Sjfb8856606 	[ITEM_PORT_ID_ID] = {
2217d30ea906Sjfb8856606 		.name = "id",
2218d30ea906Sjfb8856606 		.help = "DPDK port ID",
2219d30ea906Sjfb8856606 		.next = NEXT(item_port_id, NEXT_ENTRY(UNSIGNED), item_param),
2220d30ea906Sjfb8856606 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_port_id, id)),
2221d30ea906Sjfb8856606 	},
2222d30ea906Sjfb8856606 	[ITEM_MARK] = {
2223d30ea906Sjfb8856606 		.name = "mark",
2224d30ea906Sjfb8856606 		.help = "match traffic against value set in previously matched rule",
2225d30ea906Sjfb8856606 		.priv = PRIV_ITEM(MARK, sizeof(struct rte_flow_item_mark)),
2226d30ea906Sjfb8856606 		.next = NEXT(item_mark),
2227d30ea906Sjfb8856606 		.call = parse_vc,
2228d30ea906Sjfb8856606 	},
2229d30ea906Sjfb8856606 	[ITEM_MARK_ID] = {
2230d30ea906Sjfb8856606 		.name = "id",
2231d30ea906Sjfb8856606 		.help = "Integer value to match against",
2232d30ea906Sjfb8856606 		.next = NEXT(item_mark, NEXT_ENTRY(UNSIGNED), item_param),
2233d30ea906Sjfb8856606 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_mark, id)),
22342bfe3f2eSlogwang 	},
22352bfe3f2eSlogwang 	[ITEM_RAW] = {
22362bfe3f2eSlogwang 		.name = "raw",
22372bfe3f2eSlogwang 		.help = "match an arbitrary byte string",
22382bfe3f2eSlogwang 		.priv = PRIV_ITEM(RAW, ITEM_RAW_SIZE),
22392bfe3f2eSlogwang 		.next = NEXT(item_raw),
22402bfe3f2eSlogwang 		.call = parse_vc,
22412bfe3f2eSlogwang 	},
22422bfe3f2eSlogwang 	[ITEM_RAW_RELATIVE] = {
22432bfe3f2eSlogwang 		.name = "relative",
22442bfe3f2eSlogwang 		.help = "look for pattern after the previous item",
22452bfe3f2eSlogwang 		.next = NEXT(item_raw, NEXT_ENTRY(BOOLEAN), item_param),
22462bfe3f2eSlogwang 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_raw,
22472bfe3f2eSlogwang 					   relative, 1)),
22482bfe3f2eSlogwang 	},
22492bfe3f2eSlogwang 	[ITEM_RAW_SEARCH] = {
22502bfe3f2eSlogwang 		.name = "search",
22512bfe3f2eSlogwang 		.help = "search pattern from offset (see also limit)",
22522bfe3f2eSlogwang 		.next = NEXT(item_raw, NEXT_ENTRY(BOOLEAN), item_param),
22532bfe3f2eSlogwang 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_raw,
22542bfe3f2eSlogwang 					   search, 1)),
22552bfe3f2eSlogwang 	},
22562bfe3f2eSlogwang 	[ITEM_RAW_OFFSET] = {
22572bfe3f2eSlogwang 		.name = "offset",
22582bfe3f2eSlogwang 		.help = "absolute or relative offset for pattern",
22592bfe3f2eSlogwang 		.next = NEXT(item_raw, NEXT_ENTRY(INTEGER), item_param),
22602bfe3f2eSlogwang 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, offset)),
22612bfe3f2eSlogwang 	},
22622bfe3f2eSlogwang 	[ITEM_RAW_LIMIT] = {
22632bfe3f2eSlogwang 		.name = "limit",
22642bfe3f2eSlogwang 		.help = "search area limit for start of pattern",
22652bfe3f2eSlogwang 		.next = NEXT(item_raw, NEXT_ENTRY(UNSIGNED), item_param),
22662bfe3f2eSlogwang 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, limit)),
22672bfe3f2eSlogwang 	},
22682bfe3f2eSlogwang 	[ITEM_RAW_PATTERN] = {
22692bfe3f2eSlogwang 		.name = "pattern",
22702bfe3f2eSlogwang 		.help = "byte string to look for",
22712bfe3f2eSlogwang 		.next = NEXT(item_raw,
22722bfe3f2eSlogwang 			     NEXT_ENTRY(STRING),
22732bfe3f2eSlogwang 			     NEXT_ENTRY(ITEM_PARAM_IS,
22742bfe3f2eSlogwang 					ITEM_PARAM_SPEC,
22752bfe3f2eSlogwang 					ITEM_PARAM_MASK)),
2276d30ea906Sjfb8856606 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, pattern),
2277d30ea906Sjfb8856606 			     ARGS_ENTRY(struct rte_flow_item_raw, length),
2278d30ea906Sjfb8856606 			     ARGS_ENTRY_ARB(sizeof(struct rte_flow_item_raw),
22792bfe3f2eSlogwang 					    ITEM_RAW_PATTERN_SIZE)),
22802bfe3f2eSlogwang 	},
22812bfe3f2eSlogwang 	[ITEM_ETH] = {
22822bfe3f2eSlogwang 		.name = "eth",
22832bfe3f2eSlogwang 		.help = "match Ethernet header",
22842bfe3f2eSlogwang 		.priv = PRIV_ITEM(ETH, sizeof(struct rte_flow_item_eth)),
22852bfe3f2eSlogwang 		.next = NEXT(item_eth),
22862bfe3f2eSlogwang 		.call = parse_vc,
22872bfe3f2eSlogwang 	},
22882bfe3f2eSlogwang 	[ITEM_ETH_DST] = {
22892bfe3f2eSlogwang 		.name = "dst",
22902bfe3f2eSlogwang 		.help = "destination MAC",
22912bfe3f2eSlogwang 		.next = NEXT(item_eth, NEXT_ENTRY(MAC_ADDR), item_param),
22922bfe3f2eSlogwang 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_eth, dst)),
22932bfe3f2eSlogwang 	},
22942bfe3f2eSlogwang 	[ITEM_ETH_SRC] = {
22952bfe3f2eSlogwang 		.name = "src",
22962bfe3f2eSlogwang 		.help = "source MAC",
22972bfe3f2eSlogwang 		.next = NEXT(item_eth, NEXT_ENTRY(MAC_ADDR), item_param),
22982bfe3f2eSlogwang 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_eth, src)),
22992bfe3f2eSlogwang 	},
23002bfe3f2eSlogwang 	[ITEM_ETH_TYPE] = {
23012bfe3f2eSlogwang 		.name = "type",
23022bfe3f2eSlogwang 		.help = "EtherType",
23032bfe3f2eSlogwang 		.next = NEXT(item_eth, NEXT_ENTRY(UNSIGNED), item_param),
23042bfe3f2eSlogwang 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_eth, type)),
23052bfe3f2eSlogwang 	},
2306*2d9fd380Sjfb8856606 	[ITEM_ETH_HAS_VLAN] = {
2307*2d9fd380Sjfb8856606 		.name = "has_vlan",
2308*2d9fd380Sjfb8856606 		.help = "packet header contains VLAN",
2309*2d9fd380Sjfb8856606 		.next = NEXT(item_eth, NEXT_ENTRY(UNSIGNED), item_param),
2310*2d9fd380Sjfb8856606 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_eth,
2311*2d9fd380Sjfb8856606 					   has_vlan, 1)),
2312*2d9fd380Sjfb8856606 	},
23132bfe3f2eSlogwang 	[ITEM_VLAN] = {
23142bfe3f2eSlogwang 		.name = "vlan",
23152bfe3f2eSlogwang 		.help = "match 802.1Q/ad VLAN tag",
23162bfe3f2eSlogwang 		.priv = PRIV_ITEM(VLAN, sizeof(struct rte_flow_item_vlan)),
23172bfe3f2eSlogwang 		.next = NEXT(item_vlan),
23182bfe3f2eSlogwang 		.call = parse_vc,
23192bfe3f2eSlogwang 	},
23202bfe3f2eSlogwang 	[ITEM_VLAN_TCI] = {
23212bfe3f2eSlogwang 		.name = "tci",
23222bfe3f2eSlogwang 		.help = "tag control information",
23232bfe3f2eSlogwang 		.next = NEXT(item_vlan, NEXT_ENTRY(UNSIGNED), item_param),
23242bfe3f2eSlogwang 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vlan, tci)),
23252bfe3f2eSlogwang 	},
23262bfe3f2eSlogwang 	[ITEM_VLAN_PCP] = {
23272bfe3f2eSlogwang 		.name = "pcp",
23282bfe3f2eSlogwang 		.help = "priority code point",
23292bfe3f2eSlogwang 		.next = NEXT(item_vlan, NEXT_ENTRY(UNSIGNED), item_param),
23302bfe3f2eSlogwang 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_vlan,
23312bfe3f2eSlogwang 						  tci, "\xe0\x00")),
23322bfe3f2eSlogwang 	},
23332bfe3f2eSlogwang 	[ITEM_VLAN_DEI] = {
23342bfe3f2eSlogwang 		.name = "dei",
23352bfe3f2eSlogwang 		.help = "drop eligible indicator",
23362bfe3f2eSlogwang 		.next = NEXT(item_vlan, NEXT_ENTRY(UNSIGNED), item_param),
23372bfe3f2eSlogwang 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_vlan,
23382bfe3f2eSlogwang 						  tci, "\x10\x00")),
23392bfe3f2eSlogwang 	},
23402bfe3f2eSlogwang 	[ITEM_VLAN_VID] = {
23412bfe3f2eSlogwang 		.name = "vid",
23422bfe3f2eSlogwang 		.help = "VLAN identifier",
23432bfe3f2eSlogwang 		.next = NEXT(item_vlan, NEXT_ENTRY(UNSIGNED), item_param),
23442bfe3f2eSlogwang 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_vlan,
23452bfe3f2eSlogwang 						  tci, "\x0f\xff")),
23462bfe3f2eSlogwang 	},
2347d30ea906Sjfb8856606 	[ITEM_VLAN_INNER_TYPE] = {
2348d30ea906Sjfb8856606 		.name = "inner_type",
2349d30ea906Sjfb8856606 		.help = "inner EtherType",
2350d30ea906Sjfb8856606 		.next = NEXT(item_vlan, NEXT_ENTRY(UNSIGNED), item_param),
2351d30ea906Sjfb8856606 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vlan,
2352d30ea906Sjfb8856606 					     inner_type)),
2353d30ea906Sjfb8856606 	},
2354*2d9fd380Sjfb8856606 	[ITEM_VLAN_HAS_MORE_VLAN] = {
2355*2d9fd380Sjfb8856606 		.name = "has_more_vlan",
2356*2d9fd380Sjfb8856606 		.help = "packet header contains another VLAN",
2357*2d9fd380Sjfb8856606 		.next = NEXT(item_vlan, NEXT_ENTRY(UNSIGNED), item_param),
2358*2d9fd380Sjfb8856606 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_vlan,
2359*2d9fd380Sjfb8856606 					   has_more_vlan, 1)),
2360*2d9fd380Sjfb8856606 	},
23612bfe3f2eSlogwang 	[ITEM_IPV4] = {
23622bfe3f2eSlogwang 		.name = "ipv4",
23632bfe3f2eSlogwang 		.help = "match IPv4 header",
23642bfe3f2eSlogwang 		.priv = PRIV_ITEM(IPV4, sizeof(struct rte_flow_item_ipv4)),
23652bfe3f2eSlogwang 		.next = NEXT(item_ipv4),
23662bfe3f2eSlogwang 		.call = parse_vc,
23672bfe3f2eSlogwang 	},
23682bfe3f2eSlogwang 	[ITEM_IPV4_TOS] = {
23692bfe3f2eSlogwang 		.name = "tos",
23702bfe3f2eSlogwang 		.help = "type of service",
23712bfe3f2eSlogwang 		.next = NEXT(item_ipv4, NEXT_ENTRY(UNSIGNED), item_param),
23722bfe3f2eSlogwang 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
23732bfe3f2eSlogwang 					     hdr.type_of_service)),
23742bfe3f2eSlogwang 	},
2375*2d9fd380Sjfb8856606 	[ITEM_IPV4_FRAGMENT_OFFSET] = {
2376*2d9fd380Sjfb8856606 		.name = "fragment_offset",
2377*2d9fd380Sjfb8856606 		.help = "fragmentation flags and fragment offset",
2378*2d9fd380Sjfb8856606 		.next = NEXT(item_ipv4, NEXT_ENTRY(UNSIGNED), item_param),
2379*2d9fd380Sjfb8856606 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
2380*2d9fd380Sjfb8856606 					     hdr.fragment_offset)),
2381*2d9fd380Sjfb8856606 	},
23822bfe3f2eSlogwang 	[ITEM_IPV4_TTL] = {
23832bfe3f2eSlogwang 		.name = "ttl",
23842bfe3f2eSlogwang 		.help = "time to live",
23852bfe3f2eSlogwang 		.next = NEXT(item_ipv4, NEXT_ENTRY(UNSIGNED), item_param),
23862bfe3f2eSlogwang 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
23872bfe3f2eSlogwang 					     hdr.time_to_live)),
23882bfe3f2eSlogwang 	},
23892bfe3f2eSlogwang 	[ITEM_IPV4_PROTO] = {
23902bfe3f2eSlogwang 		.name = "proto",
23912bfe3f2eSlogwang 		.help = "next protocol ID",
23922bfe3f2eSlogwang 		.next = NEXT(item_ipv4, NEXT_ENTRY(UNSIGNED), item_param),
23932bfe3f2eSlogwang 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
23942bfe3f2eSlogwang 					     hdr.next_proto_id)),
23952bfe3f2eSlogwang 	},
23962bfe3f2eSlogwang 	[ITEM_IPV4_SRC] = {
23972bfe3f2eSlogwang 		.name = "src",
23982bfe3f2eSlogwang 		.help = "source address",
23992bfe3f2eSlogwang 		.next = NEXT(item_ipv4, NEXT_ENTRY(IPV4_ADDR), item_param),
24002bfe3f2eSlogwang 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
24012bfe3f2eSlogwang 					     hdr.src_addr)),
24022bfe3f2eSlogwang 	},
24032bfe3f2eSlogwang 	[ITEM_IPV4_DST] = {
24042bfe3f2eSlogwang 		.name = "dst",
24052bfe3f2eSlogwang 		.help = "destination address",
24062bfe3f2eSlogwang 		.next = NEXT(item_ipv4, NEXT_ENTRY(IPV4_ADDR), item_param),
24072bfe3f2eSlogwang 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
24082bfe3f2eSlogwang 					     hdr.dst_addr)),
24092bfe3f2eSlogwang 	},
24102bfe3f2eSlogwang 	[ITEM_IPV6] = {
24112bfe3f2eSlogwang 		.name = "ipv6",
24122bfe3f2eSlogwang 		.help = "match IPv6 header",
24132bfe3f2eSlogwang 		.priv = PRIV_ITEM(IPV6, sizeof(struct rte_flow_item_ipv6)),
24142bfe3f2eSlogwang 		.next = NEXT(item_ipv6),
24152bfe3f2eSlogwang 		.call = parse_vc,
24162bfe3f2eSlogwang 	},
24172bfe3f2eSlogwang 	[ITEM_IPV6_TC] = {
24182bfe3f2eSlogwang 		.name = "tc",
24192bfe3f2eSlogwang 		.help = "traffic class",
24202bfe3f2eSlogwang 		.next = NEXT(item_ipv6, NEXT_ENTRY(UNSIGNED), item_param),
24212bfe3f2eSlogwang 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_ipv6,
24222bfe3f2eSlogwang 						  hdr.vtc_flow,
24232bfe3f2eSlogwang 						  "\x0f\xf0\x00\x00")),
24242bfe3f2eSlogwang 	},
24252bfe3f2eSlogwang 	[ITEM_IPV6_FLOW] = {
24262bfe3f2eSlogwang 		.name = "flow",
24272bfe3f2eSlogwang 		.help = "flow label",
24282bfe3f2eSlogwang 		.next = NEXT(item_ipv6, NEXT_ENTRY(UNSIGNED), item_param),
24292bfe3f2eSlogwang 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_ipv6,
24302bfe3f2eSlogwang 						  hdr.vtc_flow,
24312bfe3f2eSlogwang 						  "\x00\x0f\xff\xff")),
24322bfe3f2eSlogwang 	},
24332bfe3f2eSlogwang 	[ITEM_IPV6_PROTO] = {
24342bfe3f2eSlogwang 		.name = "proto",
24352bfe3f2eSlogwang 		.help = "protocol (next header)",
24362bfe3f2eSlogwang 		.next = NEXT(item_ipv6, NEXT_ENTRY(UNSIGNED), item_param),
24372bfe3f2eSlogwang 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
24382bfe3f2eSlogwang 					     hdr.proto)),
24392bfe3f2eSlogwang 	},
24402bfe3f2eSlogwang 	[ITEM_IPV6_HOP] = {
24412bfe3f2eSlogwang 		.name = "hop",
24422bfe3f2eSlogwang 		.help = "hop limit",
24432bfe3f2eSlogwang 		.next = NEXT(item_ipv6, NEXT_ENTRY(UNSIGNED), item_param),
24442bfe3f2eSlogwang 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
24452bfe3f2eSlogwang 					     hdr.hop_limits)),
24462bfe3f2eSlogwang 	},
24472bfe3f2eSlogwang 	[ITEM_IPV6_SRC] = {
24482bfe3f2eSlogwang 		.name = "src",
24492bfe3f2eSlogwang 		.help = "source address",
24502bfe3f2eSlogwang 		.next = NEXT(item_ipv6, NEXT_ENTRY(IPV6_ADDR), item_param),
24512bfe3f2eSlogwang 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
24522bfe3f2eSlogwang 					     hdr.src_addr)),
24532bfe3f2eSlogwang 	},
24542bfe3f2eSlogwang 	[ITEM_IPV6_DST] = {
24552bfe3f2eSlogwang 		.name = "dst",
24562bfe3f2eSlogwang 		.help = "destination address",
24572bfe3f2eSlogwang 		.next = NEXT(item_ipv6, NEXT_ENTRY(IPV6_ADDR), item_param),
24582bfe3f2eSlogwang 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
24592bfe3f2eSlogwang 					     hdr.dst_addr)),
24602bfe3f2eSlogwang 	},
2461*2d9fd380Sjfb8856606 	[ITEM_IPV6_HAS_FRAG_EXT] = {
2462*2d9fd380Sjfb8856606 		.name = "has_frag_ext",
2463*2d9fd380Sjfb8856606 		.help = "fragment packet attribute",
2464*2d9fd380Sjfb8856606 		.next = NEXT(item_ipv6, NEXT_ENTRY(UNSIGNED), item_param),
2465*2d9fd380Sjfb8856606 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_ipv6,
2466*2d9fd380Sjfb8856606 					   has_frag_ext, 1)),
2467*2d9fd380Sjfb8856606 	},
24682bfe3f2eSlogwang 	[ITEM_ICMP] = {
24692bfe3f2eSlogwang 		.name = "icmp",
24702bfe3f2eSlogwang 		.help = "match ICMP header",
24712bfe3f2eSlogwang 		.priv = PRIV_ITEM(ICMP, sizeof(struct rte_flow_item_icmp)),
24722bfe3f2eSlogwang 		.next = NEXT(item_icmp),
24732bfe3f2eSlogwang 		.call = parse_vc,
24742bfe3f2eSlogwang 	},
24752bfe3f2eSlogwang 	[ITEM_ICMP_TYPE] = {
24762bfe3f2eSlogwang 		.name = "type",
24772bfe3f2eSlogwang 		.help = "ICMP packet type",
24782bfe3f2eSlogwang 		.next = NEXT(item_icmp, NEXT_ENTRY(UNSIGNED), item_param),
24792bfe3f2eSlogwang 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp,
24802bfe3f2eSlogwang 					     hdr.icmp_type)),
24812bfe3f2eSlogwang 	},
24822bfe3f2eSlogwang 	[ITEM_ICMP_CODE] = {
24832bfe3f2eSlogwang 		.name = "code",
24842bfe3f2eSlogwang 		.help = "ICMP packet code",
24852bfe3f2eSlogwang 		.next = NEXT(item_icmp, NEXT_ENTRY(UNSIGNED), item_param),
24862bfe3f2eSlogwang 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp,
24872bfe3f2eSlogwang 					     hdr.icmp_code)),
24882bfe3f2eSlogwang 	},
2489*2d9fd380Sjfb8856606 	[ITEM_ICMP_IDENT] = {
2490*2d9fd380Sjfb8856606 		.name = "ident",
2491*2d9fd380Sjfb8856606 		.help = "ICMP packet identifier",
2492*2d9fd380Sjfb8856606 		.next = NEXT(item_icmp, NEXT_ENTRY(UNSIGNED), item_param),
2493*2d9fd380Sjfb8856606 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp,
2494*2d9fd380Sjfb8856606 					     hdr.icmp_ident)),
2495*2d9fd380Sjfb8856606 	},
2496*2d9fd380Sjfb8856606 	[ITEM_ICMP_SEQ] = {
2497*2d9fd380Sjfb8856606 		.name = "seq",
2498*2d9fd380Sjfb8856606 		.help = "ICMP packet sequence number",
2499*2d9fd380Sjfb8856606 		.next = NEXT(item_icmp, NEXT_ENTRY(UNSIGNED), item_param),
2500*2d9fd380Sjfb8856606 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp,
2501*2d9fd380Sjfb8856606 					     hdr.icmp_seq_nb)),
2502*2d9fd380Sjfb8856606 	},
25032bfe3f2eSlogwang 	[ITEM_UDP] = {
25042bfe3f2eSlogwang 		.name = "udp",
25052bfe3f2eSlogwang 		.help = "match UDP header",
25062bfe3f2eSlogwang 		.priv = PRIV_ITEM(UDP, sizeof(struct rte_flow_item_udp)),
25072bfe3f2eSlogwang 		.next = NEXT(item_udp),
25082bfe3f2eSlogwang 		.call = parse_vc,
25092bfe3f2eSlogwang 	},
25102bfe3f2eSlogwang 	[ITEM_UDP_SRC] = {
25112bfe3f2eSlogwang 		.name = "src",
25122bfe3f2eSlogwang 		.help = "UDP source port",
25132bfe3f2eSlogwang 		.next = NEXT(item_udp, NEXT_ENTRY(UNSIGNED), item_param),
25142bfe3f2eSlogwang 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_udp,
25152bfe3f2eSlogwang 					     hdr.src_port)),
25162bfe3f2eSlogwang 	},
25172bfe3f2eSlogwang 	[ITEM_UDP_DST] = {
25182bfe3f2eSlogwang 		.name = "dst",
25192bfe3f2eSlogwang 		.help = "UDP destination port",
25202bfe3f2eSlogwang 		.next = NEXT(item_udp, NEXT_ENTRY(UNSIGNED), item_param),
25212bfe3f2eSlogwang 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_udp,
25222bfe3f2eSlogwang 					     hdr.dst_port)),
25232bfe3f2eSlogwang 	},
25242bfe3f2eSlogwang 	[ITEM_TCP] = {
25252bfe3f2eSlogwang 		.name = "tcp",
25262bfe3f2eSlogwang 		.help = "match TCP header",
25272bfe3f2eSlogwang 		.priv = PRIV_ITEM(TCP, sizeof(struct rte_flow_item_tcp)),
25282bfe3f2eSlogwang 		.next = NEXT(item_tcp),
25292bfe3f2eSlogwang 		.call = parse_vc,
25302bfe3f2eSlogwang 	},
25312bfe3f2eSlogwang 	[ITEM_TCP_SRC] = {
25322bfe3f2eSlogwang 		.name = "src",
25332bfe3f2eSlogwang 		.help = "TCP source port",
25342bfe3f2eSlogwang 		.next = NEXT(item_tcp, NEXT_ENTRY(UNSIGNED), item_param),
25352bfe3f2eSlogwang 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_tcp,
25362bfe3f2eSlogwang 					     hdr.src_port)),
25372bfe3f2eSlogwang 	},
25382bfe3f2eSlogwang 	[ITEM_TCP_DST] = {
25392bfe3f2eSlogwang 		.name = "dst",
25402bfe3f2eSlogwang 		.help = "TCP destination port",
25412bfe3f2eSlogwang 		.next = NEXT(item_tcp, NEXT_ENTRY(UNSIGNED), item_param),
25422bfe3f2eSlogwang 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_tcp,
25432bfe3f2eSlogwang 					     hdr.dst_port)),
25442bfe3f2eSlogwang 	},
25452bfe3f2eSlogwang 	[ITEM_TCP_FLAGS] = {
25462bfe3f2eSlogwang 		.name = "flags",
25472bfe3f2eSlogwang 		.help = "TCP flags",
25482bfe3f2eSlogwang 		.next = NEXT(item_tcp, NEXT_ENTRY(UNSIGNED), item_param),
25492bfe3f2eSlogwang 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_tcp,
25502bfe3f2eSlogwang 					     hdr.tcp_flags)),
25512bfe3f2eSlogwang 	},
25522bfe3f2eSlogwang 	[ITEM_SCTP] = {
25532bfe3f2eSlogwang 		.name = "sctp",
25542bfe3f2eSlogwang 		.help = "match SCTP header",
25552bfe3f2eSlogwang 		.priv = PRIV_ITEM(SCTP, sizeof(struct rte_flow_item_sctp)),
25562bfe3f2eSlogwang 		.next = NEXT(item_sctp),
25572bfe3f2eSlogwang 		.call = parse_vc,
25582bfe3f2eSlogwang 	},
25592bfe3f2eSlogwang 	[ITEM_SCTP_SRC] = {
25602bfe3f2eSlogwang 		.name = "src",
25612bfe3f2eSlogwang 		.help = "SCTP source port",
25622bfe3f2eSlogwang 		.next = NEXT(item_sctp, NEXT_ENTRY(UNSIGNED), item_param),
25632bfe3f2eSlogwang 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
25642bfe3f2eSlogwang 					     hdr.src_port)),
25652bfe3f2eSlogwang 	},
25662bfe3f2eSlogwang 	[ITEM_SCTP_DST] = {
25672bfe3f2eSlogwang 		.name = "dst",
25682bfe3f2eSlogwang 		.help = "SCTP destination port",
25692bfe3f2eSlogwang 		.next = NEXT(item_sctp, NEXT_ENTRY(UNSIGNED), item_param),
25702bfe3f2eSlogwang 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
25712bfe3f2eSlogwang 					     hdr.dst_port)),
25722bfe3f2eSlogwang 	},
25732bfe3f2eSlogwang 	[ITEM_SCTP_TAG] = {
25742bfe3f2eSlogwang 		.name = "tag",
25752bfe3f2eSlogwang 		.help = "validation tag",
25762bfe3f2eSlogwang 		.next = NEXT(item_sctp, NEXT_ENTRY(UNSIGNED), item_param),
25772bfe3f2eSlogwang 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
25782bfe3f2eSlogwang 					     hdr.tag)),
25792bfe3f2eSlogwang 	},
25802bfe3f2eSlogwang 	[ITEM_SCTP_CKSUM] = {
25812bfe3f2eSlogwang 		.name = "cksum",
25822bfe3f2eSlogwang 		.help = "checksum",
25832bfe3f2eSlogwang 		.next = NEXT(item_sctp, NEXT_ENTRY(UNSIGNED), item_param),
25842bfe3f2eSlogwang 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
25852bfe3f2eSlogwang 					     hdr.cksum)),
25862bfe3f2eSlogwang 	},
25872bfe3f2eSlogwang 	[ITEM_VXLAN] = {
25882bfe3f2eSlogwang 		.name = "vxlan",
25892bfe3f2eSlogwang 		.help = "match VXLAN header",
25902bfe3f2eSlogwang 		.priv = PRIV_ITEM(VXLAN, sizeof(struct rte_flow_item_vxlan)),
25912bfe3f2eSlogwang 		.next = NEXT(item_vxlan),
25922bfe3f2eSlogwang 		.call = parse_vc,
25932bfe3f2eSlogwang 	},
25942bfe3f2eSlogwang 	[ITEM_VXLAN_VNI] = {
25952bfe3f2eSlogwang 		.name = "vni",
25962bfe3f2eSlogwang 		.help = "VXLAN identifier",
25972bfe3f2eSlogwang 		.next = NEXT(item_vxlan, NEXT_ENTRY(UNSIGNED), item_param),
25982bfe3f2eSlogwang 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan, vni)),
25992bfe3f2eSlogwang 	},
26002bfe3f2eSlogwang 	[ITEM_E_TAG] = {
26012bfe3f2eSlogwang 		.name = "e_tag",
26022bfe3f2eSlogwang 		.help = "match E-Tag header",
26032bfe3f2eSlogwang 		.priv = PRIV_ITEM(E_TAG, sizeof(struct rte_flow_item_e_tag)),
26042bfe3f2eSlogwang 		.next = NEXT(item_e_tag),
26052bfe3f2eSlogwang 		.call = parse_vc,
26062bfe3f2eSlogwang 	},
26072bfe3f2eSlogwang 	[ITEM_E_TAG_GRP_ECID_B] = {
26082bfe3f2eSlogwang 		.name = "grp_ecid_b",
26092bfe3f2eSlogwang 		.help = "GRP and E-CID base",
26102bfe3f2eSlogwang 		.next = NEXT(item_e_tag, NEXT_ENTRY(UNSIGNED), item_param),
26112bfe3f2eSlogwang 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_e_tag,
26122bfe3f2eSlogwang 						  rsvd_grp_ecid_b,
26132bfe3f2eSlogwang 						  "\x3f\xff")),
26142bfe3f2eSlogwang 	},
26152bfe3f2eSlogwang 	[ITEM_NVGRE] = {
26162bfe3f2eSlogwang 		.name = "nvgre",
26172bfe3f2eSlogwang 		.help = "match NVGRE header",
26182bfe3f2eSlogwang 		.priv = PRIV_ITEM(NVGRE, sizeof(struct rte_flow_item_nvgre)),
26192bfe3f2eSlogwang 		.next = NEXT(item_nvgre),
26202bfe3f2eSlogwang 		.call = parse_vc,
26212bfe3f2eSlogwang 	},
26222bfe3f2eSlogwang 	[ITEM_NVGRE_TNI] = {
26232bfe3f2eSlogwang 		.name = "tni",
26242bfe3f2eSlogwang 		.help = "virtual subnet ID",
26252bfe3f2eSlogwang 		.next = NEXT(item_nvgre, NEXT_ENTRY(UNSIGNED), item_param),
26262bfe3f2eSlogwang 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_nvgre, tni)),
26272bfe3f2eSlogwang 	},
26282bfe3f2eSlogwang 	[ITEM_MPLS] = {
26292bfe3f2eSlogwang 		.name = "mpls",
26302bfe3f2eSlogwang 		.help = "match MPLS header",
26312bfe3f2eSlogwang 		.priv = PRIV_ITEM(MPLS, sizeof(struct rte_flow_item_mpls)),
26322bfe3f2eSlogwang 		.next = NEXT(item_mpls),
26332bfe3f2eSlogwang 		.call = parse_vc,
26342bfe3f2eSlogwang 	},
26352bfe3f2eSlogwang 	[ITEM_MPLS_LABEL] = {
26362bfe3f2eSlogwang 		.name = "label",
26372bfe3f2eSlogwang 		.help = "MPLS label",
26382bfe3f2eSlogwang 		.next = NEXT(item_mpls, NEXT_ENTRY(UNSIGNED), item_param),
26392bfe3f2eSlogwang 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_mpls,
26402bfe3f2eSlogwang 						  label_tc_s,
26412bfe3f2eSlogwang 						  "\xff\xff\xf0")),
26422bfe3f2eSlogwang 	},
26434418919fSjohnjiang 	[ITEM_MPLS_TC] = {
26444418919fSjohnjiang 		.name = "tc",
26454418919fSjohnjiang 		.help = "MPLS Traffic Class",
26464418919fSjohnjiang 		.next = NEXT(item_mpls, NEXT_ENTRY(UNSIGNED), item_param),
26474418919fSjohnjiang 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_mpls,
26484418919fSjohnjiang 						  label_tc_s,
26494418919fSjohnjiang 						  "\x00\x00\x0e")),
26504418919fSjohnjiang 	},
26514418919fSjohnjiang 	[ITEM_MPLS_S] = {
26524418919fSjohnjiang 		.name = "s",
26534418919fSjohnjiang 		.help = "MPLS Bottom-of-Stack",
26544418919fSjohnjiang 		.next = NEXT(item_mpls, NEXT_ENTRY(UNSIGNED), item_param),
26554418919fSjohnjiang 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_mpls,
26564418919fSjohnjiang 						  label_tc_s,
26574418919fSjohnjiang 						  "\x00\x00\x01")),
26584418919fSjohnjiang 	},
26592bfe3f2eSlogwang 	[ITEM_GRE] = {
26602bfe3f2eSlogwang 		.name = "gre",
26612bfe3f2eSlogwang 		.help = "match GRE header",
26622bfe3f2eSlogwang 		.priv = PRIV_ITEM(GRE, sizeof(struct rte_flow_item_gre)),
26632bfe3f2eSlogwang 		.next = NEXT(item_gre),
26642bfe3f2eSlogwang 		.call = parse_vc,
26652bfe3f2eSlogwang 	},
26662bfe3f2eSlogwang 	[ITEM_GRE_PROTO] = {
26672bfe3f2eSlogwang 		.name = "protocol",
26682bfe3f2eSlogwang 		.help = "GRE protocol type",
26692bfe3f2eSlogwang 		.next = NEXT(item_gre, NEXT_ENTRY(UNSIGNED), item_param),
26702bfe3f2eSlogwang 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre,
26712bfe3f2eSlogwang 					     protocol)),
26722bfe3f2eSlogwang 	},
26734418919fSjohnjiang 	[ITEM_GRE_C_RSVD0_VER] = {
26744418919fSjohnjiang 		.name = "c_rsvd0_ver",
26754418919fSjohnjiang 		.help =
26764418919fSjohnjiang 			"checksum (1b), undefined (1b), key bit (1b),"
26774418919fSjohnjiang 			" sequence number (1b), reserved 0 (9b),"
26784418919fSjohnjiang 			" version (3b)",
26794418919fSjohnjiang 		.next = NEXT(item_gre, NEXT_ENTRY(UNSIGNED), item_param),
26804418919fSjohnjiang 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre,
26814418919fSjohnjiang 					     c_rsvd0_ver)),
26824418919fSjohnjiang 	},
26834418919fSjohnjiang 	[ITEM_GRE_C_BIT] = {
26844418919fSjohnjiang 		.name = "c_bit",
26854418919fSjohnjiang 		.help = "checksum bit (C)",
26864418919fSjohnjiang 		.next = NEXT(item_gre, NEXT_ENTRY(BOOLEAN), item_param),
26874418919fSjohnjiang 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_gre,
26884418919fSjohnjiang 						  c_rsvd0_ver,
26894418919fSjohnjiang 						  "\x80\x00\x00\x00")),
26904418919fSjohnjiang 	},
26914418919fSjohnjiang 	[ITEM_GRE_S_BIT] = {
26924418919fSjohnjiang 		.name = "s_bit",
26934418919fSjohnjiang 		.help = "sequence number bit (S)",
26944418919fSjohnjiang 		.next = NEXT(item_gre, NEXT_ENTRY(BOOLEAN), item_param),
26954418919fSjohnjiang 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_gre,
26964418919fSjohnjiang 						  c_rsvd0_ver,
26974418919fSjohnjiang 						  "\x10\x00\x00\x00")),
26984418919fSjohnjiang 	},
26994418919fSjohnjiang 	[ITEM_GRE_K_BIT] = {
27004418919fSjohnjiang 		.name = "k_bit",
27014418919fSjohnjiang 		.help = "key bit (K)",
27024418919fSjohnjiang 		.next = NEXT(item_gre, NEXT_ENTRY(BOOLEAN), item_param),
27034418919fSjohnjiang 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_gre,
27044418919fSjohnjiang 						  c_rsvd0_ver,
27054418919fSjohnjiang 						  "\x20\x00\x00\x00")),
27064418919fSjohnjiang 	},
27072bfe3f2eSlogwang 	[ITEM_FUZZY] = {
27082bfe3f2eSlogwang 		.name = "fuzzy",
27092bfe3f2eSlogwang 		.help = "fuzzy pattern match, expect faster than default",
27102bfe3f2eSlogwang 		.priv = PRIV_ITEM(FUZZY,
27112bfe3f2eSlogwang 				sizeof(struct rte_flow_item_fuzzy)),
27122bfe3f2eSlogwang 		.next = NEXT(item_fuzzy),
27132bfe3f2eSlogwang 		.call = parse_vc,
27142bfe3f2eSlogwang 	},
27152bfe3f2eSlogwang 	[ITEM_FUZZY_THRESH] = {
27162bfe3f2eSlogwang 		.name = "thresh",
27172bfe3f2eSlogwang 		.help = "match accuracy threshold",
27182bfe3f2eSlogwang 		.next = NEXT(item_fuzzy, NEXT_ENTRY(UNSIGNED), item_param),
27192bfe3f2eSlogwang 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_fuzzy,
27202bfe3f2eSlogwang 					thresh)),
27212bfe3f2eSlogwang 	},
27222bfe3f2eSlogwang 	[ITEM_GTP] = {
27232bfe3f2eSlogwang 		.name = "gtp",
27242bfe3f2eSlogwang 		.help = "match GTP header",
27252bfe3f2eSlogwang 		.priv = PRIV_ITEM(GTP, sizeof(struct rte_flow_item_gtp)),
27262bfe3f2eSlogwang 		.next = NEXT(item_gtp),
27272bfe3f2eSlogwang 		.call = parse_vc,
27282bfe3f2eSlogwang 	},
2729*2d9fd380Sjfb8856606 	[ITEM_GTP_FLAGS] = {
2730*2d9fd380Sjfb8856606 		.name = "v_pt_rsv_flags",
2731*2d9fd380Sjfb8856606 		.help = "GTP flags",
2732*2d9fd380Sjfb8856606 		.next = NEXT(item_gtp, NEXT_ENTRY(UNSIGNED), item_param),
2733*2d9fd380Sjfb8856606 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_gtp,
2734*2d9fd380Sjfb8856606 					v_pt_rsv_flags)),
2735*2d9fd380Sjfb8856606 	},
2736*2d9fd380Sjfb8856606 	[ITEM_GTP_MSG_TYPE] = {
2737*2d9fd380Sjfb8856606 		.name = "msg_type",
2738*2d9fd380Sjfb8856606 		.help = "GTP message type",
2739*2d9fd380Sjfb8856606 		.next = NEXT(item_gtp, NEXT_ENTRY(UNSIGNED), item_param),
2740*2d9fd380Sjfb8856606 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_gtp, msg_type)),
2741*2d9fd380Sjfb8856606 	},
27422bfe3f2eSlogwang 	[ITEM_GTP_TEID] = {
27432bfe3f2eSlogwang 		.name = "teid",
27442bfe3f2eSlogwang 		.help = "tunnel endpoint identifier",
27452bfe3f2eSlogwang 		.next = NEXT(item_gtp, NEXT_ENTRY(UNSIGNED), item_param),
27462bfe3f2eSlogwang 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gtp, teid)),
27472bfe3f2eSlogwang 	},
27482bfe3f2eSlogwang 	[ITEM_GTPC] = {
27492bfe3f2eSlogwang 		.name = "gtpc",
27502bfe3f2eSlogwang 		.help = "match GTP header",
27512bfe3f2eSlogwang 		.priv = PRIV_ITEM(GTPC, sizeof(struct rte_flow_item_gtp)),
27522bfe3f2eSlogwang 		.next = NEXT(item_gtp),
27532bfe3f2eSlogwang 		.call = parse_vc,
27542bfe3f2eSlogwang 	},
27552bfe3f2eSlogwang 	[ITEM_GTPU] = {
27562bfe3f2eSlogwang 		.name = "gtpu",
27572bfe3f2eSlogwang 		.help = "match GTP header",
27582bfe3f2eSlogwang 		.priv = PRIV_ITEM(GTPU, sizeof(struct rte_flow_item_gtp)),
27592bfe3f2eSlogwang 		.next = NEXT(item_gtp),
27602bfe3f2eSlogwang 		.call = parse_vc,
27612bfe3f2eSlogwang 	},
2762d30ea906Sjfb8856606 	[ITEM_GENEVE] = {
2763d30ea906Sjfb8856606 		.name = "geneve",
2764d30ea906Sjfb8856606 		.help = "match GENEVE header",
2765d30ea906Sjfb8856606 		.priv = PRIV_ITEM(GENEVE, sizeof(struct rte_flow_item_geneve)),
2766d30ea906Sjfb8856606 		.next = NEXT(item_geneve),
2767d30ea906Sjfb8856606 		.call = parse_vc,
2768d30ea906Sjfb8856606 	},
2769d30ea906Sjfb8856606 	[ITEM_GENEVE_VNI] = {
2770d30ea906Sjfb8856606 		.name = "vni",
2771d30ea906Sjfb8856606 		.help = "virtual network identifier",
2772d30ea906Sjfb8856606 		.next = NEXT(item_geneve, NEXT_ENTRY(UNSIGNED), item_param),
2773d30ea906Sjfb8856606 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_geneve, vni)),
2774d30ea906Sjfb8856606 	},
2775d30ea906Sjfb8856606 	[ITEM_GENEVE_PROTO] = {
2776d30ea906Sjfb8856606 		.name = "protocol",
2777d30ea906Sjfb8856606 		.help = "GENEVE protocol type",
2778d30ea906Sjfb8856606 		.next = NEXT(item_geneve, NEXT_ENTRY(UNSIGNED), item_param),
2779d30ea906Sjfb8856606 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_geneve,
2780d30ea906Sjfb8856606 					     protocol)),
2781d30ea906Sjfb8856606 	},
2782d30ea906Sjfb8856606 	[ITEM_VXLAN_GPE] = {
2783d30ea906Sjfb8856606 		.name = "vxlan-gpe",
2784d30ea906Sjfb8856606 		.help = "match VXLAN-GPE header",
2785d30ea906Sjfb8856606 		.priv = PRIV_ITEM(VXLAN_GPE,
2786d30ea906Sjfb8856606 				  sizeof(struct rte_flow_item_vxlan_gpe)),
2787d30ea906Sjfb8856606 		.next = NEXT(item_vxlan_gpe),
2788d30ea906Sjfb8856606 		.call = parse_vc,
2789d30ea906Sjfb8856606 	},
2790d30ea906Sjfb8856606 	[ITEM_VXLAN_GPE_VNI] = {
2791d30ea906Sjfb8856606 		.name = "vni",
2792d30ea906Sjfb8856606 		.help = "VXLAN-GPE identifier",
2793d30ea906Sjfb8856606 		.next = NEXT(item_vxlan_gpe, NEXT_ENTRY(UNSIGNED), item_param),
2794d30ea906Sjfb8856606 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan_gpe,
2795d30ea906Sjfb8856606 					     vni)),
2796d30ea906Sjfb8856606 	},
2797d30ea906Sjfb8856606 	[ITEM_ARP_ETH_IPV4] = {
2798d30ea906Sjfb8856606 		.name = "arp_eth_ipv4",
2799d30ea906Sjfb8856606 		.help = "match ARP header for Ethernet/IPv4",
2800d30ea906Sjfb8856606 		.priv = PRIV_ITEM(ARP_ETH_IPV4,
2801d30ea906Sjfb8856606 				  sizeof(struct rte_flow_item_arp_eth_ipv4)),
2802d30ea906Sjfb8856606 		.next = NEXT(item_arp_eth_ipv4),
2803d30ea906Sjfb8856606 		.call = parse_vc,
2804d30ea906Sjfb8856606 	},
2805d30ea906Sjfb8856606 	[ITEM_ARP_ETH_IPV4_SHA] = {
2806d30ea906Sjfb8856606 		.name = "sha",
2807d30ea906Sjfb8856606 		.help = "sender hardware address",
2808d30ea906Sjfb8856606 		.next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(MAC_ADDR),
2809d30ea906Sjfb8856606 			     item_param),
2810d30ea906Sjfb8856606 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4,
2811d30ea906Sjfb8856606 					     sha)),
2812d30ea906Sjfb8856606 	},
2813d30ea906Sjfb8856606 	[ITEM_ARP_ETH_IPV4_SPA] = {
2814d30ea906Sjfb8856606 		.name = "spa",
2815d30ea906Sjfb8856606 		.help = "sender IPv4 address",
2816d30ea906Sjfb8856606 		.next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(IPV4_ADDR),
2817d30ea906Sjfb8856606 			     item_param),
2818d30ea906Sjfb8856606 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4,
2819d30ea906Sjfb8856606 					     spa)),
2820d30ea906Sjfb8856606 	},
2821d30ea906Sjfb8856606 	[ITEM_ARP_ETH_IPV4_THA] = {
2822d30ea906Sjfb8856606 		.name = "tha",
2823d30ea906Sjfb8856606 		.help = "target hardware address",
2824d30ea906Sjfb8856606 		.next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(MAC_ADDR),
2825d30ea906Sjfb8856606 			     item_param),
2826d30ea906Sjfb8856606 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4,
2827d30ea906Sjfb8856606 					     tha)),
2828d30ea906Sjfb8856606 	},
2829d30ea906Sjfb8856606 	[ITEM_ARP_ETH_IPV4_TPA] = {
2830d30ea906Sjfb8856606 		.name = "tpa",
2831d30ea906Sjfb8856606 		.help = "target IPv4 address",
2832d30ea906Sjfb8856606 		.next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(IPV4_ADDR),
2833d30ea906Sjfb8856606 			     item_param),
2834d30ea906Sjfb8856606 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4,
2835d30ea906Sjfb8856606 					     tpa)),
2836d30ea906Sjfb8856606 	},
2837d30ea906Sjfb8856606 	[ITEM_IPV6_EXT] = {
2838d30ea906Sjfb8856606 		.name = "ipv6_ext",
2839d30ea906Sjfb8856606 		.help = "match presence of any IPv6 extension header",
2840d30ea906Sjfb8856606 		.priv = PRIV_ITEM(IPV6_EXT,
2841d30ea906Sjfb8856606 				  sizeof(struct rte_flow_item_ipv6_ext)),
2842d30ea906Sjfb8856606 		.next = NEXT(item_ipv6_ext),
2843d30ea906Sjfb8856606 		.call = parse_vc,
2844d30ea906Sjfb8856606 	},
2845d30ea906Sjfb8856606 	[ITEM_IPV6_EXT_NEXT_HDR] = {
2846d30ea906Sjfb8856606 		.name = "next_hdr",
2847d30ea906Sjfb8856606 		.help = "next header",
2848d30ea906Sjfb8856606 		.next = NEXT(item_ipv6_ext, NEXT_ENTRY(UNSIGNED), item_param),
2849d30ea906Sjfb8856606 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_ext,
2850d30ea906Sjfb8856606 					     next_hdr)),
2851d30ea906Sjfb8856606 	},
2852*2d9fd380Sjfb8856606 	[ITEM_IPV6_FRAG_EXT] = {
2853*2d9fd380Sjfb8856606 		.name = "ipv6_frag_ext",
2854*2d9fd380Sjfb8856606 		.help = "match presence of IPv6 fragment extension header",
2855*2d9fd380Sjfb8856606 		.priv = PRIV_ITEM(IPV6_FRAG_EXT,
2856*2d9fd380Sjfb8856606 				sizeof(struct rte_flow_item_ipv6_frag_ext)),
2857*2d9fd380Sjfb8856606 		.next = NEXT(item_ipv6_frag_ext),
2858*2d9fd380Sjfb8856606 		.call = parse_vc,
2859*2d9fd380Sjfb8856606 	},
2860*2d9fd380Sjfb8856606 	[ITEM_IPV6_FRAG_EXT_NEXT_HDR] = {
2861*2d9fd380Sjfb8856606 		.name = "next_hdr",
2862*2d9fd380Sjfb8856606 		.help = "next header",
2863*2d9fd380Sjfb8856606 		.next = NEXT(item_ipv6_frag_ext, NEXT_ENTRY(UNSIGNED),
2864*2d9fd380Sjfb8856606 			     item_param),
2865*2d9fd380Sjfb8856606 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_ipv6_frag_ext,
2866*2d9fd380Sjfb8856606 					hdr.next_header)),
2867*2d9fd380Sjfb8856606 	},
2868*2d9fd380Sjfb8856606 	[ITEM_IPV6_FRAG_EXT_FRAG_DATA] = {
2869*2d9fd380Sjfb8856606 		.name = "frag_data",
2870*2d9fd380Sjfb8856606 		.help = "Fragment flags and offset",
2871*2d9fd380Sjfb8856606 		.next = NEXT(item_ipv6_frag_ext, NEXT_ENTRY(UNSIGNED),
2872*2d9fd380Sjfb8856606 			     item_param),
2873*2d9fd380Sjfb8856606 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_frag_ext,
2874*2d9fd380Sjfb8856606 					     hdr.frag_data)),
2875*2d9fd380Sjfb8856606 	},
2876d30ea906Sjfb8856606 	[ITEM_ICMP6] = {
2877d30ea906Sjfb8856606 		.name = "icmp6",
2878d30ea906Sjfb8856606 		.help = "match any ICMPv6 header",
2879d30ea906Sjfb8856606 		.priv = PRIV_ITEM(ICMP6, sizeof(struct rte_flow_item_icmp6)),
2880d30ea906Sjfb8856606 		.next = NEXT(item_icmp6),
2881d30ea906Sjfb8856606 		.call = parse_vc,
2882d30ea906Sjfb8856606 	},
2883d30ea906Sjfb8856606 	[ITEM_ICMP6_TYPE] = {
2884d30ea906Sjfb8856606 		.name = "type",
2885d30ea906Sjfb8856606 		.help = "ICMPv6 type",
2886d30ea906Sjfb8856606 		.next = NEXT(item_icmp6, NEXT_ENTRY(UNSIGNED), item_param),
2887d30ea906Sjfb8856606 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6,
2888d30ea906Sjfb8856606 					     type)),
2889d30ea906Sjfb8856606 	},
2890d30ea906Sjfb8856606 	[ITEM_ICMP6_CODE] = {
2891d30ea906Sjfb8856606 		.name = "code",
2892d30ea906Sjfb8856606 		.help = "ICMPv6 code",
2893d30ea906Sjfb8856606 		.next = NEXT(item_icmp6, NEXT_ENTRY(UNSIGNED), item_param),
2894d30ea906Sjfb8856606 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6,
2895d30ea906Sjfb8856606 					     code)),
2896d30ea906Sjfb8856606 	},
2897d30ea906Sjfb8856606 	[ITEM_ICMP6_ND_NS] = {
2898d30ea906Sjfb8856606 		.name = "icmp6_nd_ns",
2899d30ea906Sjfb8856606 		.help = "match ICMPv6 neighbor discovery solicitation",
2900d30ea906Sjfb8856606 		.priv = PRIV_ITEM(ICMP6_ND_NS,
2901d30ea906Sjfb8856606 				  sizeof(struct rte_flow_item_icmp6_nd_ns)),
2902d30ea906Sjfb8856606 		.next = NEXT(item_icmp6_nd_ns),
2903d30ea906Sjfb8856606 		.call = parse_vc,
2904d30ea906Sjfb8856606 	},
2905d30ea906Sjfb8856606 	[ITEM_ICMP6_ND_NS_TARGET_ADDR] = {
2906d30ea906Sjfb8856606 		.name = "target_addr",
2907d30ea906Sjfb8856606 		.help = "target address",
2908d30ea906Sjfb8856606 		.next = NEXT(item_icmp6_nd_ns, NEXT_ENTRY(IPV6_ADDR),
2909d30ea906Sjfb8856606 			     item_param),
2910d30ea906Sjfb8856606 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_nd_ns,
2911d30ea906Sjfb8856606 					     target_addr)),
2912d30ea906Sjfb8856606 	},
2913d30ea906Sjfb8856606 	[ITEM_ICMP6_ND_NA] = {
2914d30ea906Sjfb8856606 		.name = "icmp6_nd_na",
2915d30ea906Sjfb8856606 		.help = "match ICMPv6 neighbor discovery advertisement",
2916d30ea906Sjfb8856606 		.priv = PRIV_ITEM(ICMP6_ND_NA,
2917d30ea906Sjfb8856606 				  sizeof(struct rte_flow_item_icmp6_nd_na)),
2918d30ea906Sjfb8856606 		.next = NEXT(item_icmp6_nd_na),
2919d30ea906Sjfb8856606 		.call = parse_vc,
2920d30ea906Sjfb8856606 	},
2921d30ea906Sjfb8856606 	[ITEM_ICMP6_ND_NA_TARGET_ADDR] = {
2922d30ea906Sjfb8856606 		.name = "target_addr",
2923d30ea906Sjfb8856606 		.help = "target address",
2924d30ea906Sjfb8856606 		.next = NEXT(item_icmp6_nd_na, NEXT_ENTRY(IPV6_ADDR),
2925d30ea906Sjfb8856606 			     item_param),
2926d30ea906Sjfb8856606 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_nd_na,
2927d30ea906Sjfb8856606 					     target_addr)),
2928d30ea906Sjfb8856606 	},
2929d30ea906Sjfb8856606 	[ITEM_ICMP6_ND_OPT] = {
2930d30ea906Sjfb8856606 		.name = "icmp6_nd_opt",
2931d30ea906Sjfb8856606 		.help = "match presence of any ICMPv6 neighbor discovery"
2932d30ea906Sjfb8856606 			" option",
2933d30ea906Sjfb8856606 		.priv = PRIV_ITEM(ICMP6_ND_OPT,
2934d30ea906Sjfb8856606 				  sizeof(struct rte_flow_item_icmp6_nd_opt)),
2935d30ea906Sjfb8856606 		.next = NEXT(item_icmp6_nd_opt),
2936d30ea906Sjfb8856606 		.call = parse_vc,
2937d30ea906Sjfb8856606 	},
2938d30ea906Sjfb8856606 	[ITEM_ICMP6_ND_OPT_TYPE] = {
2939d30ea906Sjfb8856606 		.name = "type",
2940d30ea906Sjfb8856606 		.help = "ND option type",
2941d30ea906Sjfb8856606 		.next = NEXT(item_icmp6_nd_opt, NEXT_ENTRY(UNSIGNED),
2942d30ea906Sjfb8856606 			     item_param),
2943d30ea906Sjfb8856606 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_nd_opt,
2944d30ea906Sjfb8856606 					     type)),
2945d30ea906Sjfb8856606 	},
2946d30ea906Sjfb8856606 	[ITEM_ICMP6_ND_OPT_SLA_ETH] = {
2947d30ea906Sjfb8856606 		.name = "icmp6_nd_opt_sla_eth",
2948d30ea906Sjfb8856606 		.help = "match ICMPv6 neighbor discovery source Ethernet"
2949d30ea906Sjfb8856606 			" link-layer address option",
2950d30ea906Sjfb8856606 		.priv = PRIV_ITEM
2951d30ea906Sjfb8856606 			(ICMP6_ND_OPT_SLA_ETH,
2952d30ea906Sjfb8856606 			 sizeof(struct rte_flow_item_icmp6_nd_opt_sla_eth)),
2953d30ea906Sjfb8856606 		.next = NEXT(item_icmp6_nd_opt_sla_eth),
2954d30ea906Sjfb8856606 		.call = parse_vc,
2955d30ea906Sjfb8856606 	},
2956d30ea906Sjfb8856606 	[ITEM_ICMP6_ND_OPT_SLA_ETH_SLA] = {
2957d30ea906Sjfb8856606 		.name = "sla",
2958d30ea906Sjfb8856606 		.help = "source Ethernet LLA",
2959d30ea906Sjfb8856606 		.next = NEXT(item_icmp6_nd_opt_sla_eth, NEXT_ENTRY(MAC_ADDR),
2960d30ea906Sjfb8856606 			     item_param),
2961d30ea906Sjfb8856606 		.args = ARGS(ARGS_ENTRY_HTON
2962d30ea906Sjfb8856606 			     (struct rte_flow_item_icmp6_nd_opt_sla_eth, sla)),
2963d30ea906Sjfb8856606 	},
2964d30ea906Sjfb8856606 	[ITEM_ICMP6_ND_OPT_TLA_ETH] = {
2965d30ea906Sjfb8856606 		.name = "icmp6_nd_opt_tla_eth",
2966d30ea906Sjfb8856606 		.help = "match ICMPv6 neighbor discovery target Ethernet"
2967d30ea906Sjfb8856606 			" link-layer address option",
2968d30ea906Sjfb8856606 		.priv = PRIV_ITEM
2969d30ea906Sjfb8856606 			(ICMP6_ND_OPT_TLA_ETH,
2970d30ea906Sjfb8856606 			 sizeof(struct rte_flow_item_icmp6_nd_opt_tla_eth)),
2971d30ea906Sjfb8856606 		.next = NEXT(item_icmp6_nd_opt_tla_eth),
2972d30ea906Sjfb8856606 		.call = parse_vc,
2973d30ea906Sjfb8856606 	},
2974d30ea906Sjfb8856606 	[ITEM_ICMP6_ND_OPT_TLA_ETH_TLA] = {
2975d30ea906Sjfb8856606 		.name = "tla",
2976d30ea906Sjfb8856606 		.help = "target Ethernet LLA",
2977d30ea906Sjfb8856606 		.next = NEXT(item_icmp6_nd_opt_tla_eth, NEXT_ENTRY(MAC_ADDR),
2978d30ea906Sjfb8856606 			     item_param),
2979d30ea906Sjfb8856606 		.args = ARGS(ARGS_ENTRY_HTON
2980d30ea906Sjfb8856606 			     (struct rte_flow_item_icmp6_nd_opt_tla_eth, tla)),
2981d30ea906Sjfb8856606 	},
2982d30ea906Sjfb8856606 	[ITEM_META] = {
2983d30ea906Sjfb8856606 		.name = "meta",
2984d30ea906Sjfb8856606 		.help = "match metadata header",
2985d30ea906Sjfb8856606 		.priv = PRIV_ITEM(META, sizeof(struct rte_flow_item_meta)),
2986d30ea906Sjfb8856606 		.next = NEXT(item_meta),
2987d30ea906Sjfb8856606 		.call = parse_vc,
2988d30ea906Sjfb8856606 	},
2989d30ea906Sjfb8856606 	[ITEM_META_DATA] = {
2990d30ea906Sjfb8856606 		.name = "data",
2991d30ea906Sjfb8856606 		.help = "metadata value",
2992d30ea906Sjfb8856606 		.next = NEXT(item_meta, NEXT_ENTRY(UNSIGNED), item_param),
29934418919fSjohnjiang 		.args = ARGS(ARGS_ENTRY_MASK(struct rte_flow_item_meta,
2994d30ea906Sjfb8856606 					     data, "\xff\xff\xff\xff")),
2995d30ea906Sjfb8856606 	},
29964418919fSjohnjiang 	[ITEM_GRE_KEY] = {
29974418919fSjohnjiang 		.name = "gre_key",
29984418919fSjohnjiang 		.help = "match GRE key",
29994418919fSjohnjiang 		.priv = PRIV_ITEM(GRE_KEY, sizeof(rte_be32_t)),
30004418919fSjohnjiang 		.next = NEXT(item_gre_key),
30014418919fSjohnjiang 		.call = parse_vc,
30024418919fSjohnjiang 	},
30034418919fSjohnjiang 	[ITEM_GRE_KEY_VALUE] = {
30044418919fSjohnjiang 		.name = "value",
30054418919fSjohnjiang 		.help = "key value",
30064418919fSjohnjiang 		.next = NEXT(item_gre_key, NEXT_ENTRY(UNSIGNED), item_param),
30074418919fSjohnjiang 		.args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
30084418919fSjohnjiang 	},
30094418919fSjohnjiang 	[ITEM_GTP_PSC] = {
30104418919fSjohnjiang 		.name = "gtp_psc",
30114418919fSjohnjiang 		.help = "match GTP extension header with type 0x85",
30124418919fSjohnjiang 		.priv = PRIV_ITEM(GTP_PSC,
30134418919fSjohnjiang 				sizeof(struct rte_flow_item_gtp_psc)),
30144418919fSjohnjiang 		.next = NEXT(item_gtp_psc),
30154418919fSjohnjiang 		.call = parse_vc,
30164418919fSjohnjiang 	},
30174418919fSjohnjiang 	[ITEM_GTP_PSC_QFI] = {
30184418919fSjohnjiang 		.name = "qfi",
30194418919fSjohnjiang 		.help = "QoS flow identifier",
30204418919fSjohnjiang 		.next = NEXT(item_gtp_psc, NEXT_ENTRY(UNSIGNED), item_param),
30214418919fSjohnjiang 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gtp_psc,
30224418919fSjohnjiang 					qfi)),
30234418919fSjohnjiang 	},
30244418919fSjohnjiang 	[ITEM_GTP_PSC_PDU_T] = {
30254418919fSjohnjiang 		.name = "pdu_t",
30264418919fSjohnjiang 		.help = "PDU type",
30274418919fSjohnjiang 		.next = NEXT(item_gtp_psc, NEXT_ENTRY(UNSIGNED), item_param),
30284418919fSjohnjiang 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gtp_psc,
30294418919fSjohnjiang 					pdu_type)),
30304418919fSjohnjiang 	},
30314418919fSjohnjiang 	[ITEM_PPPOES] = {
30324418919fSjohnjiang 		.name = "pppoes",
30334418919fSjohnjiang 		.help = "match PPPoE session header",
30344418919fSjohnjiang 		.priv = PRIV_ITEM(PPPOES, sizeof(struct rte_flow_item_pppoe)),
30354418919fSjohnjiang 		.next = NEXT(item_pppoes),
30364418919fSjohnjiang 		.call = parse_vc,
30374418919fSjohnjiang 	},
30384418919fSjohnjiang 	[ITEM_PPPOED] = {
30394418919fSjohnjiang 		.name = "pppoed",
30404418919fSjohnjiang 		.help = "match PPPoE discovery header",
30414418919fSjohnjiang 		.priv = PRIV_ITEM(PPPOED, sizeof(struct rte_flow_item_pppoe)),
30424418919fSjohnjiang 		.next = NEXT(item_pppoed),
30434418919fSjohnjiang 		.call = parse_vc,
30444418919fSjohnjiang 	},
30454418919fSjohnjiang 	[ITEM_PPPOE_SEID] = {
30464418919fSjohnjiang 		.name = "seid",
30474418919fSjohnjiang 		.help = "session identifier",
30484418919fSjohnjiang 		.next = NEXT(item_pppoes, NEXT_ENTRY(UNSIGNED), item_param),
30494418919fSjohnjiang 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_pppoe,
30504418919fSjohnjiang 					session_id)),
30514418919fSjohnjiang 	},
30524418919fSjohnjiang 	[ITEM_PPPOE_PROTO_ID] = {
30530c6bd470Sfengbojiang 		.name = "pppoe_proto_id",
30544418919fSjohnjiang 		.help = "match PPPoE session protocol identifier",
30554418919fSjohnjiang 		.priv = PRIV_ITEM(PPPOE_PROTO_ID,
30564418919fSjohnjiang 				sizeof(struct rte_flow_item_pppoe_proto_id)),
30570c6bd470Sfengbojiang 		.next = NEXT(item_pppoe_proto_id, NEXT_ENTRY(UNSIGNED),
30580c6bd470Sfengbojiang 			     item_param),
30590c6bd470Sfengbojiang 		.args = ARGS(ARGS_ENTRY_HTON
30600c6bd470Sfengbojiang 			     (struct rte_flow_item_pppoe_proto_id, proto_id)),
30614418919fSjohnjiang 		.call = parse_vc,
30624418919fSjohnjiang 	},
30634418919fSjohnjiang 	[ITEM_HIGIG2] = {
30644418919fSjohnjiang 		.name = "higig2",
30654418919fSjohnjiang 		.help = "matches higig2 header",
30664418919fSjohnjiang 		.priv = PRIV_ITEM(HIGIG2,
30674418919fSjohnjiang 				sizeof(struct rte_flow_item_higig2_hdr)),
30684418919fSjohnjiang 		.next = NEXT(item_higig2),
30694418919fSjohnjiang 		.call = parse_vc,
30704418919fSjohnjiang 	},
30714418919fSjohnjiang 	[ITEM_HIGIG2_CLASSIFICATION] = {
30724418919fSjohnjiang 		.name = "classification",
30734418919fSjohnjiang 		.help = "matches classification of higig2 header",
30744418919fSjohnjiang 		.next = NEXT(item_higig2, NEXT_ENTRY(UNSIGNED), item_param),
30754418919fSjohnjiang 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_higig2_hdr,
30764418919fSjohnjiang 					hdr.ppt1.classification)),
30774418919fSjohnjiang 	},
30784418919fSjohnjiang 	[ITEM_HIGIG2_VID] = {
30794418919fSjohnjiang 		.name = "vid",
30804418919fSjohnjiang 		.help = "matches vid of higig2 header",
30814418919fSjohnjiang 		.next = NEXT(item_higig2, NEXT_ENTRY(UNSIGNED), item_param),
30824418919fSjohnjiang 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_higig2_hdr,
30834418919fSjohnjiang 					hdr.ppt1.vid)),
30844418919fSjohnjiang 	},
30854418919fSjohnjiang 	[ITEM_TAG] = {
30864418919fSjohnjiang 		.name = "tag",
30874418919fSjohnjiang 		.help = "match tag value",
30884418919fSjohnjiang 		.priv = PRIV_ITEM(TAG, sizeof(struct rte_flow_item_tag)),
30894418919fSjohnjiang 		.next = NEXT(item_tag),
30904418919fSjohnjiang 		.call = parse_vc,
30914418919fSjohnjiang 	},
30924418919fSjohnjiang 	[ITEM_TAG_DATA] = {
30934418919fSjohnjiang 		.name = "data",
30944418919fSjohnjiang 		.help = "tag value to match",
30954418919fSjohnjiang 		.next = NEXT(item_tag, NEXT_ENTRY(UNSIGNED), item_param),
30964418919fSjohnjiang 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_tag, data)),
30974418919fSjohnjiang 	},
30984418919fSjohnjiang 	[ITEM_TAG_INDEX] = {
30994418919fSjohnjiang 		.name = "index",
31004418919fSjohnjiang 		.help = "index of tag array to match",
31014418919fSjohnjiang 		.next = NEXT(item_tag, NEXT_ENTRY(UNSIGNED),
31024418919fSjohnjiang 			     NEXT_ENTRY(ITEM_PARAM_IS)),
31034418919fSjohnjiang 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_tag, index)),
31044418919fSjohnjiang 	},
3105*2d9fd380Sjfb8856606 	[ITEM_L2TPV3OIP] = {
3106*2d9fd380Sjfb8856606 		.name = "l2tpv3oip",
3107*2d9fd380Sjfb8856606 		.help = "match L2TPv3 over IP header",
3108*2d9fd380Sjfb8856606 		.priv = PRIV_ITEM(L2TPV3OIP,
3109*2d9fd380Sjfb8856606 				  sizeof(struct rte_flow_item_l2tpv3oip)),
3110*2d9fd380Sjfb8856606 		.next = NEXT(item_l2tpv3oip),
3111*2d9fd380Sjfb8856606 		.call = parse_vc,
3112*2d9fd380Sjfb8856606 	},
3113*2d9fd380Sjfb8856606 	[ITEM_L2TPV3OIP_SESSION_ID] = {
3114*2d9fd380Sjfb8856606 		.name = "session_id",
3115*2d9fd380Sjfb8856606 		.help = "session identifier",
3116*2d9fd380Sjfb8856606 		.next = NEXT(item_l2tpv3oip, NEXT_ENTRY(UNSIGNED), item_param),
3117*2d9fd380Sjfb8856606 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv3oip,
3118*2d9fd380Sjfb8856606 					     session_id)),
3119*2d9fd380Sjfb8856606 	},
3120*2d9fd380Sjfb8856606 	[ITEM_ESP] = {
3121*2d9fd380Sjfb8856606 		.name = "esp",
3122*2d9fd380Sjfb8856606 		.help = "match ESP header",
3123*2d9fd380Sjfb8856606 		.priv = PRIV_ITEM(ESP, sizeof(struct rte_flow_item_esp)),
3124*2d9fd380Sjfb8856606 		.next = NEXT(item_esp),
3125*2d9fd380Sjfb8856606 		.call = parse_vc,
3126*2d9fd380Sjfb8856606 	},
3127*2d9fd380Sjfb8856606 	[ITEM_ESP_SPI] = {
3128*2d9fd380Sjfb8856606 		.name = "spi",
3129*2d9fd380Sjfb8856606 		.help = "security policy index",
3130*2d9fd380Sjfb8856606 		.next = NEXT(item_esp, NEXT_ENTRY(UNSIGNED), item_param),
3131*2d9fd380Sjfb8856606 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_esp,
3132*2d9fd380Sjfb8856606 				hdr.spi)),
3133*2d9fd380Sjfb8856606 	},
3134*2d9fd380Sjfb8856606 	[ITEM_AH] = {
3135*2d9fd380Sjfb8856606 		.name = "ah",
3136*2d9fd380Sjfb8856606 		.help = "match AH header",
3137*2d9fd380Sjfb8856606 		.priv = PRIV_ITEM(AH, sizeof(struct rte_flow_item_ah)),
3138*2d9fd380Sjfb8856606 		.next = NEXT(item_ah),
3139*2d9fd380Sjfb8856606 		.call = parse_vc,
3140*2d9fd380Sjfb8856606 	},
3141*2d9fd380Sjfb8856606 	[ITEM_AH_SPI] = {
3142*2d9fd380Sjfb8856606 		.name = "spi",
3143*2d9fd380Sjfb8856606 		.help = "security parameters index",
3144*2d9fd380Sjfb8856606 		.next = NEXT(item_ah, NEXT_ENTRY(UNSIGNED), item_param),
3145*2d9fd380Sjfb8856606 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ah, spi)),
3146*2d9fd380Sjfb8856606 	},
3147*2d9fd380Sjfb8856606 	[ITEM_PFCP] = {
3148*2d9fd380Sjfb8856606 		.name = "pfcp",
3149*2d9fd380Sjfb8856606 		.help = "match pfcp header",
3150*2d9fd380Sjfb8856606 		.priv = PRIV_ITEM(PFCP, sizeof(struct rte_flow_item_pfcp)),
3151*2d9fd380Sjfb8856606 		.next = NEXT(item_pfcp),
3152*2d9fd380Sjfb8856606 		.call = parse_vc,
3153*2d9fd380Sjfb8856606 	},
3154*2d9fd380Sjfb8856606 	[ITEM_PFCP_S_FIELD] = {
3155*2d9fd380Sjfb8856606 		.name = "s_field",
3156*2d9fd380Sjfb8856606 		.help = "S field",
3157*2d9fd380Sjfb8856606 		.next = NEXT(item_pfcp, NEXT_ENTRY(UNSIGNED), item_param),
3158*2d9fd380Sjfb8856606 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_pfcp,
3159*2d9fd380Sjfb8856606 				s_field)),
3160*2d9fd380Sjfb8856606 	},
3161*2d9fd380Sjfb8856606 	[ITEM_PFCP_SEID] = {
3162*2d9fd380Sjfb8856606 		.name = "seid",
3163*2d9fd380Sjfb8856606 		.help = "session endpoint identifier",
3164*2d9fd380Sjfb8856606 		.next = NEXT(item_pfcp, NEXT_ENTRY(UNSIGNED), item_param),
3165*2d9fd380Sjfb8856606 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_pfcp, seid)),
3166*2d9fd380Sjfb8856606 	},
3167*2d9fd380Sjfb8856606 	[ITEM_ECPRI] = {
3168*2d9fd380Sjfb8856606 		.name = "ecpri",
3169*2d9fd380Sjfb8856606 		.help = "match eCPRI header",
3170*2d9fd380Sjfb8856606 		.priv = PRIV_ITEM(ECPRI, sizeof(struct rte_flow_item_ecpri)),
3171*2d9fd380Sjfb8856606 		.next = NEXT(item_ecpri),
3172*2d9fd380Sjfb8856606 		.call = parse_vc,
3173*2d9fd380Sjfb8856606 	},
3174*2d9fd380Sjfb8856606 	[ITEM_ECPRI_COMMON] = {
3175*2d9fd380Sjfb8856606 		.name = "common",
3176*2d9fd380Sjfb8856606 		.help = "eCPRI common header",
3177*2d9fd380Sjfb8856606 		.next = NEXT(item_ecpri_common),
3178*2d9fd380Sjfb8856606 	},
3179*2d9fd380Sjfb8856606 	[ITEM_ECPRI_COMMON_TYPE] = {
3180*2d9fd380Sjfb8856606 		.name = "type",
3181*2d9fd380Sjfb8856606 		.help = "type of common header",
3182*2d9fd380Sjfb8856606 		.next = NEXT(item_ecpri_common_type),
3183*2d9fd380Sjfb8856606 		.args = ARGS(ARG_ENTRY_HTON(struct rte_flow_item_ecpri)),
3184*2d9fd380Sjfb8856606 	},
3185*2d9fd380Sjfb8856606 	[ITEM_ECPRI_COMMON_TYPE_IQ_DATA] = {
3186*2d9fd380Sjfb8856606 		.name = "iq_data",
3187*2d9fd380Sjfb8856606 		.help = "Type #0: IQ Data",
3188*2d9fd380Sjfb8856606 		.next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_IQ_DATA_PCID,
3189*2d9fd380Sjfb8856606 					ITEM_NEXT)),
3190*2d9fd380Sjfb8856606 		.call = parse_vc_item_ecpri_type,
3191*2d9fd380Sjfb8856606 	},
3192*2d9fd380Sjfb8856606 	[ITEM_ECPRI_MSG_IQ_DATA_PCID] = {
3193*2d9fd380Sjfb8856606 		.name = "pc_id",
3194*2d9fd380Sjfb8856606 		.help = "Physical Channel ID",
3195*2d9fd380Sjfb8856606 		.next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_IQ_DATA_PCID,
3196*2d9fd380Sjfb8856606 				ITEM_ECPRI_COMMON, ITEM_NEXT),
3197*2d9fd380Sjfb8856606 				NEXT_ENTRY(UNSIGNED), item_param),
3198*2d9fd380Sjfb8856606 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ecpri,
3199*2d9fd380Sjfb8856606 				hdr.type0.pc_id)),
3200*2d9fd380Sjfb8856606 	},
3201*2d9fd380Sjfb8856606 	[ITEM_ECPRI_COMMON_TYPE_RTC_CTRL] = {
3202*2d9fd380Sjfb8856606 		.name = "rtc_ctrl",
3203*2d9fd380Sjfb8856606 		.help = "Type #2: Real-Time Control Data",
3204*2d9fd380Sjfb8856606 		.next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_RTC_CTRL_RTCID,
3205*2d9fd380Sjfb8856606 					ITEM_NEXT)),
3206*2d9fd380Sjfb8856606 		.call = parse_vc_item_ecpri_type,
3207*2d9fd380Sjfb8856606 	},
3208*2d9fd380Sjfb8856606 	[ITEM_ECPRI_MSG_RTC_CTRL_RTCID] = {
3209*2d9fd380Sjfb8856606 		.name = "rtc_id",
3210*2d9fd380Sjfb8856606 		.help = "Real-Time Control Data ID",
3211*2d9fd380Sjfb8856606 		.next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_RTC_CTRL_RTCID,
3212*2d9fd380Sjfb8856606 				ITEM_ECPRI_COMMON, ITEM_NEXT),
3213*2d9fd380Sjfb8856606 				NEXT_ENTRY(UNSIGNED), item_param),
3214*2d9fd380Sjfb8856606 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ecpri,
3215*2d9fd380Sjfb8856606 				hdr.type2.rtc_id)),
3216*2d9fd380Sjfb8856606 	},
3217*2d9fd380Sjfb8856606 	[ITEM_ECPRI_COMMON_TYPE_DLY_MSR] = {
3218*2d9fd380Sjfb8856606 		.name = "delay_measure",
3219*2d9fd380Sjfb8856606 		.help = "Type #5: One-Way Delay Measurement",
3220*2d9fd380Sjfb8856606 		.next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_DLY_MSR_MSRID,
3221*2d9fd380Sjfb8856606 					ITEM_NEXT)),
3222*2d9fd380Sjfb8856606 		.call = parse_vc_item_ecpri_type,
3223*2d9fd380Sjfb8856606 	},
3224*2d9fd380Sjfb8856606 	[ITEM_ECPRI_MSG_DLY_MSR_MSRID] = {
3225*2d9fd380Sjfb8856606 		.name = "msr_id",
3226*2d9fd380Sjfb8856606 		.help = "Measurement ID",
3227*2d9fd380Sjfb8856606 		.next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_DLY_MSR_MSRID,
3228*2d9fd380Sjfb8856606 				ITEM_ECPRI_COMMON, ITEM_NEXT),
3229*2d9fd380Sjfb8856606 				NEXT_ENTRY(UNSIGNED), item_param),
3230*2d9fd380Sjfb8856606 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ecpri,
3231*2d9fd380Sjfb8856606 				hdr.type5.msr_id)),
3232*2d9fd380Sjfb8856606 	},
32332bfe3f2eSlogwang 	/* Validate/create actions. */
32342bfe3f2eSlogwang 	[ACTIONS] = {
32352bfe3f2eSlogwang 		.name = "actions",
32362bfe3f2eSlogwang 		.help = "submit a list of associated actions",
32372bfe3f2eSlogwang 		.next = NEXT(next_action),
32382bfe3f2eSlogwang 		.call = parse_vc,
32392bfe3f2eSlogwang 	},
32402bfe3f2eSlogwang 	[ACTION_NEXT] = {
32412bfe3f2eSlogwang 		.name = "/",
32422bfe3f2eSlogwang 		.help = "specify next action",
32432bfe3f2eSlogwang 		.next = NEXT(next_action),
32442bfe3f2eSlogwang 	},
32452bfe3f2eSlogwang 	[ACTION_END] = {
32462bfe3f2eSlogwang 		.name = "end",
32472bfe3f2eSlogwang 		.help = "end list of actions",
32482bfe3f2eSlogwang 		.priv = PRIV_ACTION(END, 0),
32492bfe3f2eSlogwang 		.call = parse_vc,
32502bfe3f2eSlogwang 	},
32512bfe3f2eSlogwang 	[ACTION_VOID] = {
32522bfe3f2eSlogwang 		.name = "void",
32532bfe3f2eSlogwang 		.help = "no-op action",
32542bfe3f2eSlogwang 		.priv = PRIV_ACTION(VOID, 0),
32552bfe3f2eSlogwang 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
32562bfe3f2eSlogwang 		.call = parse_vc,
32572bfe3f2eSlogwang 	},
32582bfe3f2eSlogwang 	[ACTION_PASSTHRU] = {
32592bfe3f2eSlogwang 		.name = "passthru",
32602bfe3f2eSlogwang 		.help = "let subsequent rule process matched packets",
32612bfe3f2eSlogwang 		.priv = PRIV_ACTION(PASSTHRU, 0),
32622bfe3f2eSlogwang 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
32632bfe3f2eSlogwang 		.call = parse_vc,
32642bfe3f2eSlogwang 	},
3265d30ea906Sjfb8856606 	[ACTION_JUMP] = {
3266d30ea906Sjfb8856606 		.name = "jump",
3267d30ea906Sjfb8856606 		.help = "redirect traffic to a given group",
3268d30ea906Sjfb8856606 		.priv = PRIV_ACTION(JUMP, sizeof(struct rte_flow_action_jump)),
3269d30ea906Sjfb8856606 		.next = NEXT(action_jump),
3270d30ea906Sjfb8856606 		.call = parse_vc,
3271d30ea906Sjfb8856606 	},
3272d30ea906Sjfb8856606 	[ACTION_JUMP_GROUP] = {
3273d30ea906Sjfb8856606 		.name = "group",
3274d30ea906Sjfb8856606 		.help = "group to redirect traffic to",
3275d30ea906Sjfb8856606 		.next = NEXT(action_jump, NEXT_ENTRY(UNSIGNED)),
3276d30ea906Sjfb8856606 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_jump, group)),
3277d30ea906Sjfb8856606 		.call = parse_vc_conf,
3278d30ea906Sjfb8856606 	},
32792bfe3f2eSlogwang 	[ACTION_MARK] = {
32802bfe3f2eSlogwang 		.name = "mark",
32812bfe3f2eSlogwang 		.help = "attach 32 bit value to packets",
32822bfe3f2eSlogwang 		.priv = PRIV_ACTION(MARK, sizeof(struct rte_flow_action_mark)),
32832bfe3f2eSlogwang 		.next = NEXT(action_mark),
32842bfe3f2eSlogwang 		.call = parse_vc,
32852bfe3f2eSlogwang 	},
32862bfe3f2eSlogwang 	[ACTION_MARK_ID] = {
32872bfe3f2eSlogwang 		.name = "id",
32882bfe3f2eSlogwang 		.help = "32 bit value to return with packets",
32892bfe3f2eSlogwang 		.next = NEXT(action_mark, NEXT_ENTRY(UNSIGNED)),
32902bfe3f2eSlogwang 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_mark, id)),
32912bfe3f2eSlogwang 		.call = parse_vc_conf,
32922bfe3f2eSlogwang 	},
32932bfe3f2eSlogwang 	[ACTION_FLAG] = {
32942bfe3f2eSlogwang 		.name = "flag",
32952bfe3f2eSlogwang 		.help = "flag packets",
32962bfe3f2eSlogwang 		.priv = PRIV_ACTION(FLAG, 0),
32972bfe3f2eSlogwang 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
32982bfe3f2eSlogwang 		.call = parse_vc,
32992bfe3f2eSlogwang 	},
33002bfe3f2eSlogwang 	[ACTION_QUEUE] = {
33012bfe3f2eSlogwang 		.name = "queue",
33022bfe3f2eSlogwang 		.help = "assign packets to a given queue index",
33032bfe3f2eSlogwang 		.priv = PRIV_ACTION(QUEUE,
33042bfe3f2eSlogwang 				    sizeof(struct rte_flow_action_queue)),
33052bfe3f2eSlogwang 		.next = NEXT(action_queue),
33062bfe3f2eSlogwang 		.call = parse_vc,
33072bfe3f2eSlogwang 	},
33082bfe3f2eSlogwang 	[ACTION_QUEUE_INDEX] = {
33092bfe3f2eSlogwang 		.name = "index",
33102bfe3f2eSlogwang 		.help = "queue index to use",
33112bfe3f2eSlogwang 		.next = NEXT(action_queue, NEXT_ENTRY(UNSIGNED)),
33122bfe3f2eSlogwang 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_queue, index)),
33132bfe3f2eSlogwang 		.call = parse_vc_conf,
33142bfe3f2eSlogwang 	},
33152bfe3f2eSlogwang 	[ACTION_DROP] = {
33162bfe3f2eSlogwang 		.name = "drop",
33172bfe3f2eSlogwang 		.help = "drop packets (note: passthru has priority)",
33182bfe3f2eSlogwang 		.priv = PRIV_ACTION(DROP, 0),
33192bfe3f2eSlogwang 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
33202bfe3f2eSlogwang 		.call = parse_vc,
33212bfe3f2eSlogwang 	},
33222bfe3f2eSlogwang 	[ACTION_COUNT] = {
33232bfe3f2eSlogwang 		.name = "count",
33242bfe3f2eSlogwang 		.help = "enable counters for this rule",
3325d30ea906Sjfb8856606 		.priv = PRIV_ACTION(COUNT,
3326d30ea906Sjfb8856606 				    sizeof(struct rte_flow_action_count)),
3327d30ea906Sjfb8856606 		.next = NEXT(action_count),
33282bfe3f2eSlogwang 		.call = parse_vc,
33292bfe3f2eSlogwang 	},
3330d30ea906Sjfb8856606 	[ACTION_COUNT_ID] = {
3331d30ea906Sjfb8856606 		.name = "identifier",
3332d30ea906Sjfb8856606 		.help = "counter identifier to use",
3333d30ea906Sjfb8856606 		.next = NEXT(action_count, NEXT_ENTRY(UNSIGNED)),
3334d30ea906Sjfb8856606 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_count, id)),
3335d30ea906Sjfb8856606 		.call = parse_vc_conf,
33362bfe3f2eSlogwang 	},
3337d30ea906Sjfb8856606 	[ACTION_COUNT_SHARED] = {
3338d30ea906Sjfb8856606 		.name = "shared",
3339d30ea906Sjfb8856606 		.help = "shared counter",
3340d30ea906Sjfb8856606 		.next = NEXT(action_count, NEXT_ENTRY(BOOLEAN)),
3341d30ea906Sjfb8856606 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_count,
3342d30ea906Sjfb8856606 					   shared, 1)),
33432bfe3f2eSlogwang 		.call = parse_vc_conf,
33442bfe3f2eSlogwang 	},
33452bfe3f2eSlogwang 	[ACTION_RSS] = {
33462bfe3f2eSlogwang 		.name = "rss",
33472bfe3f2eSlogwang 		.help = "spread packets among several queues",
3348d30ea906Sjfb8856606 		.priv = PRIV_ACTION(RSS, sizeof(struct action_rss_data)),
33492bfe3f2eSlogwang 		.next = NEXT(action_rss),
3350d30ea906Sjfb8856606 		.call = parse_vc_action_rss,
3351d30ea906Sjfb8856606 	},
3352d30ea906Sjfb8856606 	[ACTION_RSS_FUNC] = {
3353d30ea906Sjfb8856606 		.name = "func",
3354d30ea906Sjfb8856606 		.help = "RSS hash function to apply",
3355d30ea906Sjfb8856606 		.next = NEXT(action_rss,
3356d30ea906Sjfb8856606 			     NEXT_ENTRY(ACTION_RSS_FUNC_DEFAULT,
3357d30ea906Sjfb8856606 					ACTION_RSS_FUNC_TOEPLITZ,
33584418919fSjohnjiang 					ACTION_RSS_FUNC_SIMPLE_XOR,
33594418919fSjohnjiang 					ACTION_RSS_FUNC_SYMMETRIC_TOEPLITZ)),
3360d30ea906Sjfb8856606 	},
3361d30ea906Sjfb8856606 	[ACTION_RSS_FUNC_DEFAULT] = {
3362d30ea906Sjfb8856606 		.name = "default",
3363d30ea906Sjfb8856606 		.help = "default hash function",
3364d30ea906Sjfb8856606 		.call = parse_vc_action_rss_func,
3365d30ea906Sjfb8856606 	},
3366d30ea906Sjfb8856606 	[ACTION_RSS_FUNC_TOEPLITZ] = {
3367d30ea906Sjfb8856606 		.name = "toeplitz",
3368d30ea906Sjfb8856606 		.help = "Toeplitz hash function",
3369d30ea906Sjfb8856606 		.call = parse_vc_action_rss_func,
3370d30ea906Sjfb8856606 	},
3371d30ea906Sjfb8856606 	[ACTION_RSS_FUNC_SIMPLE_XOR] = {
3372d30ea906Sjfb8856606 		.name = "simple_xor",
3373d30ea906Sjfb8856606 		.help = "simple XOR hash function",
3374d30ea906Sjfb8856606 		.call = parse_vc_action_rss_func,
3375d30ea906Sjfb8856606 	},
33764418919fSjohnjiang 	[ACTION_RSS_FUNC_SYMMETRIC_TOEPLITZ] = {
33774418919fSjohnjiang 		.name = "symmetric_toeplitz",
33784418919fSjohnjiang 		.help = "Symmetric Toeplitz hash function",
33794418919fSjohnjiang 		.call = parse_vc_action_rss_func,
33804418919fSjohnjiang 	},
3381d30ea906Sjfb8856606 	[ACTION_RSS_LEVEL] = {
3382d30ea906Sjfb8856606 		.name = "level",
3383d30ea906Sjfb8856606 		.help = "encapsulation level for \"types\"",
3384d30ea906Sjfb8856606 		.next = NEXT(action_rss, NEXT_ENTRY(UNSIGNED)),
3385d30ea906Sjfb8856606 		.args = ARGS(ARGS_ENTRY_ARB
3386d30ea906Sjfb8856606 			     (offsetof(struct action_rss_data, conf) +
3387d30ea906Sjfb8856606 			      offsetof(struct rte_flow_action_rss, level),
3388d30ea906Sjfb8856606 			      sizeof(((struct rte_flow_action_rss *)0)->
3389d30ea906Sjfb8856606 				     level))),
3390d30ea906Sjfb8856606 	},
3391d30ea906Sjfb8856606 	[ACTION_RSS_TYPES] = {
3392d30ea906Sjfb8856606 		.name = "types",
3393d30ea906Sjfb8856606 		.help = "specific RSS hash types",
3394d30ea906Sjfb8856606 		.next = NEXT(action_rss, NEXT_ENTRY(ACTION_RSS_TYPE)),
3395d30ea906Sjfb8856606 	},
3396d30ea906Sjfb8856606 	[ACTION_RSS_TYPE] = {
3397d30ea906Sjfb8856606 		.name = "{type}",
3398d30ea906Sjfb8856606 		.help = "RSS hash type",
3399d30ea906Sjfb8856606 		.call = parse_vc_action_rss_type,
3400d30ea906Sjfb8856606 		.comp = comp_vc_action_rss_type,
3401d30ea906Sjfb8856606 	},
3402d30ea906Sjfb8856606 	[ACTION_RSS_KEY] = {
3403d30ea906Sjfb8856606 		.name = "key",
3404d30ea906Sjfb8856606 		.help = "RSS hash key",
34051646932aSjfb8856606 		.next = NEXT(action_rss, NEXT_ENTRY(HEX)),
3406d30ea906Sjfb8856606 		.args = ARGS(ARGS_ENTRY_ARB(0, 0),
3407d30ea906Sjfb8856606 			     ARGS_ENTRY_ARB
3408d30ea906Sjfb8856606 			     (offsetof(struct action_rss_data, conf) +
3409d30ea906Sjfb8856606 			      offsetof(struct rte_flow_action_rss, key_len),
3410d30ea906Sjfb8856606 			      sizeof(((struct rte_flow_action_rss *)0)->
3411d30ea906Sjfb8856606 				     key_len)),
3412d30ea906Sjfb8856606 			     ARGS_ENTRY(struct action_rss_data, key)),
3413d30ea906Sjfb8856606 	},
3414d30ea906Sjfb8856606 	[ACTION_RSS_KEY_LEN] = {
3415d30ea906Sjfb8856606 		.name = "key_len",
3416d30ea906Sjfb8856606 		.help = "RSS hash key length in bytes",
3417d30ea906Sjfb8856606 		.next = NEXT(action_rss, NEXT_ENTRY(UNSIGNED)),
3418d30ea906Sjfb8856606 		.args = ARGS(ARGS_ENTRY_ARB_BOUNDED
3419d30ea906Sjfb8856606 			     (offsetof(struct action_rss_data, conf) +
3420d30ea906Sjfb8856606 			      offsetof(struct rte_flow_action_rss, key_len),
3421d30ea906Sjfb8856606 			      sizeof(((struct rte_flow_action_rss *)0)->
3422d30ea906Sjfb8856606 				     key_len),
3423d30ea906Sjfb8856606 			      0,
3424d30ea906Sjfb8856606 			      RSS_HASH_KEY_LENGTH)),
34252bfe3f2eSlogwang 	},
34262bfe3f2eSlogwang 	[ACTION_RSS_QUEUES] = {
34272bfe3f2eSlogwang 		.name = "queues",
34282bfe3f2eSlogwang 		.help = "queue indices to use",
34292bfe3f2eSlogwang 		.next = NEXT(action_rss, NEXT_ENTRY(ACTION_RSS_QUEUE)),
34302bfe3f2eSlogwang 		.call = parse_vc_conf,
34312bfe3f2eSlogwang 	},
34322bfe3f2eSlogwang 	[ACTION_RSS_QUEUE] = {
34332bfe3f2eSlogwang 		.name = "{queue}",
34342bfe3f2eSlogwang 		.help = "queue index",
34352bfe3f2eSlogwang 		.call = parse_vc_action_rss_queue,
34362bfe3f2eSlogwang 		.comp = comp_vc_action_rss_queue,
34372bfe3f2eSlogwang 	},
34382bfe3f2eSlogwang 	[ACTION_PF] = {
34392bfe3f2eSlogwang 		.name = "pf",
3440d30ea906Sjfb8856606 		.help = "direct traffic to physical function",
34412bfe3f2eSlogwang 		.priv = PRIV_ACTION(PF, 0),
34422bfe3f2eSlogwang 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
34432bfe3f2eSlogwang 		.call = parse_vc,
34442bfe3f2eSlogwang 	},
34452bfe3f2eSlogwang 	[ACTION_VF] = {
34462bfe3f2eSlogwang 		.name = "vf",
3447d30ea906Sjfb8856606 		.help = "direct traffic to a virtual function ID",
34482bfe3f2eSlogwang 		.priv = PRIV_ACTION(VF, sizeof(struct rte_flow_action_vf)),
34492bfe3f2eSlogwang 		.next = NEXT(action_vf),
34502bfe3f2eSlogwang 		.call = parse_vc,
34512bfe3f2eSlogwang 	},
34522bfe3f2eSlogwang 	[ACTION_VF_ORIGINAL] = {
34532bfe3f2eSlogwang 		.name = "original",
34542bfe3f2eSlogwang 		.help = "use original VF ID if possible",
34552bfe3f2eSlogwang 		.next = NEXT(action_vf, NEXT_ENTRY(BOOLEAN)),
34562bfe3f2eSlogwang 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_vf,
34572bfe3f2eSlogwang 					   original, 1)),
34582bfe3f2eSlogwang 		.call = parse_vc_conf,
34592bfe3f2eSlogwang 	},
34602bfe3f2eSlogwang 	[ACTION_VF_ID] = {
34612bfe3f2eSlogwang 		.name = "id",
3462d30ea906Sjfb8856606 		.help = "VF ID",
34632bfe3f2eSlogwang 		.next = NEXT(action_vf, NEXT_ENTRY(UNSIGNED)),
34642bfe3f2eSlogwang 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_vf, id)),
34652bfe3f2eSlogwang 		.call = parse_vc_conf,
34662bfe3f2eSlogwang 	},
3467d30ea906Sjfb8856606 	[ACTION_PHY_PORT] = {
3468d30ea906Sjfb8856606 		.name = "phy_port",
3469d30ea906Sjfb8856606 		.help = "direct packets to physical port index",
3470d30ea906Sjfb8856606 		.priv = PRIV_ACTION(PHY_PORT,
3471d30ea906Sjfb8856606 				    sizeof(struct rte_flow_action_phy_port)),
3472d30ea906Sjfb8856606 		.next = NEXT(action_phy_port),
3473d30ea906Sjfb8856606 		.call = parse_vc,
3474d30ea906Sjfb8856606 	},
3475d30ea906Sjfb8856606 	[ACTION_PHY_PORT_ORIGINAL] = {
3476d30ea906Sjfb8856606 		.name = "original",
3477d30ea906Sjfb8856606 		.help = "use original port index if possible",
3478d30ea906Sjfb8856606 		.next = NEXT(action_phy_port, NEXT_ENTRY(BOOLEAN)),
3479d30ea906Sjfb8856606 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_phy_port,
3480d30ea906Sjfb8856606 					   original, 1)),
3481d30ea906Sjfb8856606 		.call = parse_vc_conf,
3482d30ea906Sjfb8856606 	},
3483d30ea906Sjfb8856606 	[ACTION_PHY_PORT_INDEX] = {
3484d30ea906Sjfb8856606 		.name = "index",
3485d30ea906Sjfb8856606 		.help = "physical port index",
3486d30ea906Sjfb8856606 		.next = NEXT(action_phy_port, NEXT_ENTRY(UNSIGNED)),
3487d30ea906Sjfb8856606 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_phy_port,
3488d30ea906Sjfb8856606 					index)),
3489d30ea906Sjfb8856606 		.call = parse_vc_conf,
3490d30ea906Sjfb8856606 	},
3491d30ea906Sjfb8856606 	[ACTION_PORT_ID] = {
3492d30ea906Sjfb8856606 		.name = "port_id",
3493d30ea906Sjfb8856606 		.help = "direct matching traffic to a given DPDK port ID",
3494d30ea906Sjfb8856606 		.priv = PRIV_ACTION(PORT_ID,
3495d30ea906Sjfb8856606 				    sizeof(struct rte_flow_action_port_id)),
3496d30ea906Sjfb8856606 		.next = NEXT(action_port_id),
3497d30ea906Sjfb8856606 		.call = parse_vc,
3498d30ea906Sjfb8856606 	},
3499d30ea906Sjfb8856606 	[ACTION_PORT_ID_ORIGINAL] = {
3500d30ea906Sjfb8856606 		.name = "original",
3501d30ea906Sjfb8856606 		.help = "use original DPDK port ID if possible",
3502d30ea906Sjfb8856606 		.next = NEXT(action_port_id, NEXT_ENTRY(BOOLEAN)),
3503d30ea906Sjfb8856606 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_port_id,
3504d30ea906Sjfb8856606 					   original, 1)),
3505d30ea906Sjfb8856606 		.call = parse_vc_conf,
3506d30ea906Sjfb8856606 	},
3507d30ea906Sjfb8856606 	[ACTION_PORT_ID_ID] = {
3508d30ea906Sjfb8856606 		.name = "id",
3509d30ea906Sjfb8856606 		.help = "DPDK port ID",
3510d30ea906Sjfb8856606 		.next = NEXT(action_port_id, NEXT_ENTRY(UNSIGNED)),
3511d30ea906Sjfb8856606 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_port_id, id)),
3512d30ea906Sjfb8856606 		.call = parse_vc_conf,
3513d30ea906Sjfb8856606 	},
35142bfe3f2eSlogwang 	[ACTION_METER] = {
35152bfe3f2eSlogwang 		.name = "meter",
35162bfe3f2eSlogwang 		.help = "meter the directed packets at given id",
35172bfe3f2eSlogwang 		.priv = PRIV_ACTION(METER,
35182bfe3f2eSlogwang 				    sizeof(struct rte_flow_action_meter)),
35192bfe3f2eSlogwang 		.next = NEXT(action_meter),
35202bfe3f2eSlogwang 		.call = parse_vc,
35212bfe3f2eSlogwang 	},
35222bfe3f2eSlogwang 	[ACTION_METER_ID] = {
35232bfe3f2eSlogwang 		.name = "mtr_id",
35242bfe3f2eSlogwang 		.help = "meter id to use",
35252bfe3f2eSlogwang 		.next = NEXT(action_meter, NEXT_ENTRY(UNSIGNED)),
35262bfe3f2eSlogwang 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_meter, mtr_id)),
35272bfe3f2eSlogwang 		.call = parse_vc_conf,
35282bfe3f2eSlogwang 	},
3529d30ea906Sjfb8856606 	[ACTION_OF_SET_MPLS_TTL] = {
3530d30ea906Sjfb8856606 		.name = "of_set_mpls_ttl",
3531d30ea906Sjfb8856606 		.help = "OpenFlow's OFPAT_SET_MPLS_TTL",
3532d30ea906Sjfb8856606 		.priv = PRIV_ACTION
3533d30ea906Sjfb8856606 			(OF_SET_MPLS_TTL,
3534d30ea906Sjfb8856606 			 sizeof(struct rte_flow_action_of_set_mpls_ttl)),
3535d30ea906Sjfb8856606 		.next = NEXT(action_of_set_mpls_ttl),
3536d30ea906Sjfb8856606 		.call = parse_vc,
3537d30ea906Sjfb8856606 	},
3538d30ea906Sjfb8856606 	[ACTION_OF_SET_MPLS_TTL_MPLS_TTL] = {
3539d30ea906Sjfb8856606 		.name = "mpls_ttl",
3540d30ea906Sjfb8856606 		.help = "MPLS TTL",
3541d30ea906Sjfb8856606 		.next = NEXT(action_of_set_mpls_ttl, NEXT_ENTRY(UNSIGNED)),
3542d30ea906Sjfb8856606 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_of_set_mpls_ttl,
3543d30ea906Sjfb8856606 					mpls_ttl)),
3544d30ea906Sjfb8856606 		.call = parse_vc_conf,
3545d30ea906Sjfb8856606 	},
3546d30ea906Sjfb8856606 	[ACTION_OF_DEC_MPLS_TTL] = {
3547d30ea906Sjfb8856606 		.name = "of_dec_mpls_ttl",
3548d30ea906Sjfb8856606 		.help = "OpenFlow's OFPAT_DEC_MPLS_TTL",
3549d30ea906Sjfb8856606 		.priv = PRIV_ACTION(OF_DEC_MPLS_TTL, 0),
3550d30ea906Sjfb8856606 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
3551d30ea906Sjfb8856606 		.call = parse_vc,
3552d30ea906Sjfb8856606 	},
3553d30ea906Sjfb8856606 	[ACTION_OF_SET_NW_TTL] = {
3554d30ea906Sjfb8856606 		.name = "of_set_nw_ttl",
3555d30ea906Sjfb8856606 		.help = "OpenFlow's OFPAT_SET_NW_TTL",
3556d30ea906Sjfb8856606 		.priv = PRIV_ACTION
3557d30ea906Sjfb8856606 			(OF_SET_NW_TTL,
3558d30ea906Sjfb8856606 			 sizeof(struct rte_flow_action_of_set_nw_ttl)),
3559d30ea906Sjfb8856606 		.next = NEXT(action_of_set_nw_ttl),
3560d30ea906Sjfb8856606 		.call = parse_vc,
3561d30ea906Sjfb8856606 	},
3562d30ea906Sjfb8856606 	[ACTION_OF_SET_NW_TTL_NW_TTL] = {
3563d30ea906Sjfb8856606 		.name = "nw_ttl",
3564d30ea906Sjfb8856606 		.help = "IP TTL",
3565d30ea906Sjfb8856606 		.next = NEXT(action_of_set_nw_ttl, NEXT_ENTRY(UNSIGNED)),
3566d30ea906Sjfb8856606 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_of_set_nw_ttl,
3567d30ea906Sjfb8856606 					nw_ttl)),
3568d30ea906Sjfb8856606 		.call = parse_vc_conf,
3569d30ea906Sjfb8856606 	},
3570d30ea906Sjfb8856606 	[ACTION_OF_DEC_NW_TTL] = {
3571d30ea906Sjfb8856606 		.name = "of_dec_nw_ttl",
3572d30ea906Sjfb8856606 		.help = "OpenFlow's OFPAT_DEC_NW_TTL",
3573d30ea906Sjfb8856606 		.priv = PRIV_ACTION(OF_DEC_NW_TTL, 0),
3574d30ea906Sjfb8856606 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
3575d30ea906Sjfb8856606 		.call = parse_vc,
3576d30ea906Sjfb8856606 	},
3577d30ea906Sjfb8856606 	[ACTION_OF_COPY_TTL_OUT] = {
3578d30ea906Sjfb8856606 		.name = "of_copy_ttl_out",
3579d30ea906Sjfb8856606 		.help = "OpenFlow's OFPAT_COPY_TTL_OUT",
3580d30ea906Sjfb8856606 		.priv = PRIV_ACTION(OF_COPY_TTL_OUT, 0),
3581d30ea906Sjfb8856606 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
3582d30ea906Sjfb8856606 		.call = parse_vc,
3583d30ea906Sjfb8856606 	},
3584d30ea906Sjfb8856606 	[ACTION_OF_COPY_TTL_IN] = {
3585d30ea906Sjfb8856606 		.name = "of_copy_ttl_in",
3586d30ea906Sjfb8856606 		.help = "OpenFlow's OFPAT_COPY_TTL_IN",
3587d30ea906Sjfb8856606 		.priv = PRIV_ACTION(OF_COPY_TTL_IN, 0),
3588d30ea906Sjfb8856606 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
3589d30ea906Sjfb8856606 		.call = parse_vc,
3590d30ea906Sjfb8856606 	},
3591d30ea906Sjfb8856606 	[ACTION_OF_POP_VLAN] = {
3592d30ea906Sjfb8856606 		.name = "of_pop_vlan",
3593d30ea906Sjfb8856606 		.help = "OpenFlow's OFPAT_POP_VLAN",
3594d30ea906Sjfb8856606 		.priv = PRIV_ACTION(OF_POP_VLAN, 0),
3595d30ea906Sjfb8856606 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
3596d30ea906Sjfb8856606 		.call = parse_vc,
3597d30ea906Sjfb8856606 	},
3598d30ea906Sjfb8856606 	[ACTION_OF_PUSH_VLAN] = {
3599d30ea906Sjfb8856606 		.name = "of_push_vlan",
3600d30ea906Sjfb8856606 		.help = "OpenFlow's OFPAT_PUSH_VLAN",
3601d30ea906Sjfb8856606 		.priv = PRIV_ACTION
3602d30ea906Sjfb8856606 			(OF_PUSH_VLAN,
3603d30ea906Sjfb8856606 			 sizeof(struct rte_flow_action_of_push_vlan)),
3604d30ea906Sjfb8856606 		.next = NEXT(action_of_push_vlan),
3605d30ea906Sjfb8856606 		.call = parse_vc,
3606d30ea906Sjfb8856606 	},
3607d30ea906Sjfb8856606 	[ACTION_OF_PUSH_VLAN_ETHERTYPE] = {
3608d30ea906Sjfb8856606 		.name = "ethertype",
3609d30ea906Sjfb8856606 		.help = "EtherType",
3610d30ea906Sjfb8856606 		.next = NEXT(action_of_push_vlan, NEXT_ENTRY(UNSIGNED)),
3611d30ea906Sjfb8856606 		.args = ARGS(ARGS_ENTRY_HTON
3612d30ea906Sjfb8856606 			     (struct rte_flow_action_of_push_vlan,
3613d30ea906Sjfb8856606 			      ethertype)),
3614d30ea906Sjfb8856606 		.call = parse_vc_conf,
3615d30ea906Sjfb8856606 	},
3616d30ea906Sjfb8856606 	[ACTION_OF_SET_VLAN_VID] = {
3617d30ea906Sjfb8856606 		.name = "of_set_vlan_vid",
3618d30ea906Sjfb8856606 		.help = "OpenFlow's OFPAT_SET_VLAN_VID",
3619d30ea906Sjfb8856606 		.priv = PRIV_ACTION
3620d30ea906Sjfb8856606 			(OF_SET_VLAN_VID,
3621d30ea906Sjfb8856606 			 sizeof(struct rte_flow_action_of_set_vlan_vid)),
3622d30ea906Sjfb8856606 		.next = NEXT(action_of_set_vlan_vid),
3623d30ea906Sjfb8856606 		.call = parse_vc,
3624d30ea906Sjfb8856606 	},
3625d30ea906Sjfb8856606 	[ACTION_OF_SET_VLAN_VID_VLAN_VID] = {
3626d30ea906Sjfb8856606 		.name = "vlan_vid",
3627d30ea906Sjfb8856606 		.help = "VLAN id",
3628d30ea906Sjfb8856606 		.next = NEXT(action_of_set_vlan_vid, NEXT_ENTRY(UNSIGNED)),
3629d30ea906Sjfb8856606 		.args = ARGS(ARGS_ENTRY_HTON
3630d30ea906Sjfb8856606 			     (struct rte_flow_action_of_set_vlan_vid,
3631d30ea906Sjfb8856606 			      vlan_vid)),
3632d30ea906Sjfb8856606 		.call = parse_vc_conf,
3633d30ea906Sjfb8856606 	},
3634d30ea906Sjfb8856606 	[ACTION_OF_SET_VLAN_PCP] = {
3635d30ea906Sjfb8856606 		.name = "of_set_vlan_pcp",
3636d30ea906Sjfb8856606 		.help = "OpenFlow's OFPAT_SET_VLAN_PCP",
3637d30ea906Sjfb8856606 		.priv = PRIV_ACTION
3638d30ea906Sjfb8856606 			(OF_SET_VLAN_PCP,
3639d30ea906Sjfb8856606 			 sizeof(struct rte_flow_action_of_set_vlan_pcp)),
3640d30ea906Sjfb8856606 		.next = NEXT(action_of_set_vlan_pcp),
3641d30ea906Sjfb8856606 		.call = parse_vc,
3642d30ea906Sjfb8856606 	},
3643d30ea906Sjfb8856606 	[ACTION_OF_SET_VLAN_PCP_VLAN_PCP] = {
3644d30ea906Sjfb8856606 		.name = "vlan_pcp",
3645d30ea906Sjfb8856606 		.help = "VLAN priority",
3646d30ea906Sjfb8856606 		.next = NEXT(action_of_set_vlan_pcp, NEXT_ENTRY(UNSIGNED)),
3647d30ea906Sjfb8856606 		.args = ARGS(ARGS_ENTRY_HTON
3648d30ea906Sjfb8856606 			     (struct rte_flow_action_of_set_vlan_pcp,
3649d30ea906Sjfb8856606 			      vlan_pcp)),
3650d30ea906Sjfb8856606 		.call = parse_vc_conf,
3651d30ea906Sjfb8856606 	},
3652d30ea906Sjfb8856606 	[ACTION_OF_POP_MPLS] = {
3653d30ea906Sjfb8856606 		.name = "of_pop_mpls",
3654d30ea906Sjfb8856606 		.help = "OpenFlow's OFPAT_POP_MPLS",
3655d30ea906Sjfb8856606 		.priv = PRIV_ACTION(OF_POP_MPLS,
3656d30ea906Sjfb8856606 				    sizeof(struct rte_flow_action_of_pop_mpls)),
3657d30ea906Sjfb8856606 		.next = NEXT(action_of_pop_mpls),
3658d30ea906Sjfb8856606 		.call = parse_vc,
3659d30ea906Sjfb8856606 	},
3660d30ea906Sjfb8856606 	[ACTION_OF_POP_MPLS_ETHERTYPE] = {
3661d30ea906Sjfb8856606 		.name = "ethertype",
3662d30ea906Sjfb8856606 		.help = "EtherType",
3663d30ea906Sjfb8856606 		.next = NEXT(action_of_pop_mpls, NEXT_ENTRY(UNSIGNED)),
3664d30ea906Sjfb8856606 		.args = ARGS(ARGS_ENTRY_HTON
3665d30ea906Sjfb8856606 			     (struct rte_flow_action_of_pop_mpls,
3666d30ea906Sjfb8856606 			      ethertype)),
3667d30ea906Sjfb8856606 		.call = parse_vc_conf,
3668d30ea906Sjfb8856606 	},
3669d30ea906Sjfb8856606 	[ACTION_OF_PUSH_MPLS] = {
3670d30ea906Sjfb8856606 		.name = "of_push_mpls",
3671d30ea906Sjfb8856606 		.help = "OpenFlow's OFPAT_PUSH_MPLS",
3672d30ea906Sjfb8856606 		.priv = PRIV_ACTION
3673d30ea906Sjfb8856606 			(OF_PUSH_MPLS,
3674d30ea906Sjfb8856606 			 sizeof(struct rte_flow_action_of_push_mpls)),
3675d30ea906Sjfb8856606 		.next = NEXT(action_of_push_mpls),
3676d30ea906Sjfb8856606 		.call = parse_vc,
3677d30ea906Sjfb8856606 	},
3678d30ea906Sjfb8856606 	[ACTION_OF_PUSH_MPLS_ETHERTYPE] = {
3679d30ea906Sjfb8856606 		.name = "ethertype",
3680d30ea906Sjfb8856606 		.help = "EtherType",
3681d30ea906Sjfb8856606 		.next = NEXT(action_of_push_mpls, NEXT_ENTRY(UNSIGNED)),
3682d30ea906Sjfb8856606 		.args = ARGS(ARGS_ENTRY_HTON
3683d30ea906Sjfb8856606 			     (struct rte_flow_action_of_push_mpls,
3684d30ea906Sjfb8856606 			      ethertype)),
3685d30ea906Sjfb8856606 		.call = parse_vc_conf,
3686d30ea906Sjfb8856606 	},
3687d30ea906Sjfb8856606 	[ACTION_VXLAN_ENCAP] = {
3688d30ea906Sjfb8856606 		.name = "vxlan_encap",
3689d30ea906Sjfb8856606 		.help = "VXLAN encapsulation, uses configuration set by \"set"
3690d30ea906Sjfb8856606 			" vxlan\"",
3691d30ea906Sjfb8856606 		.priv = PRIV_ACTION(VXLAN_ENCAP,
3692d30ea906Sjfb8856606 				    sizeof(struct action_vxlan_encap_data)),
3693d30ea906Sjfb8856606 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
3694d30ea906Sjfb8856606 		.call = parse_vc_action_vxlan_encap,
3695d30ea906Sjfb8856606 	},
3696d30ea906Sjfb8856606 	[ACTION_VXLAN_DECAP] = {
3697d30ea906Sjfb8856606 		.name = "vxlan_decap",
3698d30ea906Sjfb8856606 		.help = "Performs a decapsulation action by stripping all"
3699d30ea906Sjfb8856606 			" headers of the VXLAN tunnel network overlay from the"
3700d30ea906Sjfb8856606 			" matched flow.",
3701d30ea906Sjfb8856606 		.priv = PRIV_ACTION(VXLAN_DECAP, 0),
3702d30ea906Sjfb8856606 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
3703d30ea906Sjfb8856606 		.call = parse_vc,
3704d30ea906Sjfb8856606 	},
3705d30ea906Sjfb8856606 	[ACTION_NVGRE_ENCAP] = {
3706d30ea906Sjfb8856606 		.name = "nvgre_encap",
3707d30ea906Sjfb8856606 		.help = "NVGRE encapsulation, uses configuration set by \"set"
3708d30ea906Sjfb8856606 			" nvgre\"",
3709d30ea906Sjfb8856606 		.priv = PRIV_ACTION(NVGRE_ENCAP,
3710d30ea906Sjfb8856606 				    sizeof(struct action_nvgre_encap_data)),
3711d30ea906Sjfb8856606 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
3712d30ea906Sjfb8856606 		.call = parse_vc_action_nvgre_encap,
3713d30ea906Sjfb8856606 	},
3714d30ea906Sjfb8856606 	[ACTION_NVGRE_DECAP] = {
3715d30ea906Sjfb8856606 		.name = "nvgre_decap",
3716d30ea906Sjfb8856606 		.help = "Performs a decapsulation action by stripping all"
3717d30ea906Sjfb8856606 			" headers of the NVGRE tunnel network overlay from the"
3718d30ea906Sjfb8856606 			" matched flow.",
3719d30ea906Sjfb8856606 		.priv = PRIV_ACTION(NVGRE_DECAP, 0),
3720d30ea906Sjfb8856606 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
3721d30ea906Sjfb8856606 		.call = parse_vc,
3722d30ea906Sjfb8856606 	},
3723d30ea906Sjfb8856606 	[ACTION_L2_ENCAP] = {
3724d30ea906Sjfb8856606 		.name = "l2_encap",
3725d30ea906Sjfb8856606 		.help = "l2 encap, uses configuration set by"
3726d30ea906Sjfb8856606 			" \"set l2_encap\"",
3727d30ea906Sjfb8856606 		.priv = PRIV_ACTION(RAW_ENCAP,
3728d30ea906Sjfb8856606 				    sizeof(struct action_raw_encap_data)),
3729d30ea906Sjfb8856606 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
3730d30ea906Sjfb8856606 		.call = parse_vc_action_l2_encap,
3731d30ea906Sjfb8856606 	},
3732d30ea906Sjfb8856606 	[ACTION_L2_DECAP] = {
3733d30ea906Sjfb8856606 		.name = "l2_decap",
3734d30ea906Sjfb8856606 		.help = "l2 decap, uses configuration set by"
3735d30ea906Sjfb8856606 			" \"set l2_decap\"",
3736d30ea906Sjfb8856606 		.priv = PRIV_ACTION(RAW_DECAP,
3737d30ea906Sjfb8856606 				    sizeof(struct action_raw_decap_data)),
3738d30ea906Sjfb8856606 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
3739d30ea906Sjfb8856606 		.call = parse_vc_action_l2_decap,
3740d30ea906Sjfb8856606 	},
3741d30ea906Sjfb8856606 	[ACTION_MPLSOGRE_ENCAP] = {
3742d30ea906Sjfb8856606 		.name = "mplsogre_encap",
3743d30ea906Sjfb8856606 		.help = "mplsogre encapsulation, uses configuration set by"
3744d30ea906Sjfb8856606 			" \"set mplsogre_encap\"",
3745d30ea906Sjfb8856606 		.priv = PRIV_ACTION(RAW_ENCAP,
3746d30ea906Sjfb8856606 				    sizeof(struct action_raw_encap_data)),
3747d30ea906Sjfb8856606 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
3748d30ea906Sjfb8856606 		.call = parse_vc_action_mplsogre_encap,
3749d30ea906Sjfb8856606 	},
3750d30ea906Sjfb8856606 	[ACTION_MPLSOGRE_DECAP] = {
3751d30ea906Sjfb8856606 		.name = "mplsogre_decap",
3752d30ea906Sjfb8856606 		.help = "mplsogre decapsulation, uses configuration set by"
3753d30ea906Sjfb8856606 			" \"set mplsogre_decap\"",
3754d30ea906Sjfb8856606 		.priv = PRIV_ACTION(RAW_DECAP,
3755d30ea906Sjfb8856606 				    sizeof(struct action_raw_decap_data)),
3756d30ea906Sjfb8856606 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
3757d30ea906Sjfb8856606 		.call = parse_vc_action_mplsogre_decap,
3758d30ea906Sjfb8856606 	},
3759d30ea906Sjfb8856606 	[ACTION_MPLSOUDP_ENCAP] = {
3760d30ea906Sjfb8856606 		.name = "mplsoudp_encap",
3761d30ea906Sjfb8856606 		.help = "mplsoudp encapsulation, uses configuration set by"
3762d30ea906Sjfb8856606 			" \"set mplsoudp_encap\"",
3763d30ea906Sjfb8856606 		.priv = PRIV_ACTION(RAW_ENCAP,
3764d30ea906Sjfb8856606 				    sizeof(struct action_raw_encap_data)),
3765d30ea906Sjfb8856606 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
3766d30ea906Sjfb8856606 		.call = parse_vc_action_mplsoudp_encap,
3767d30ea906Sjfb8856606 	},
3768d30ea906Sjfb8856606 	[ACTION_MPLSOUDP_DECAP] = {
3769d30ea906Sjfb8856606 		.name = "mplsoudp_decap",
3770d30ea906Sjfb8856606 		.help = "mplsoudp decapsulation, uses configuration set by"
3771d30ea906Sjfb8856606 			" \"set mplsoudp_decap\"",
3772d30ea906Sjfb8856606 		.priv = PRIV_ACTION(RAW_DECAP,
3773d30ea906Sjfb8856606 				    sizeof(struct action_raw_decap_data)),
3774d30ea906Sjfb8856606 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
3775d30ea906Sjfb8856606 		.call = parse_vc_action_mplsoudp_decap,
3776d30ea906Sjfb8856606 	},
3777d30ea906Sjfb8856606 	[ACTION_SET_IPV4_SRC] = {
3778d30ea906Sjfb8856606 		.name = "set_ipv4_src",
3779d30ea906Sjfb8856606 		.help = "Set a new IPv4 source address in the outermost"
3780d30ea906Sjfb8856606 			" IPv4 header",
3781d30ea906Sjfb8856606 		.priv = PRIV_ACTION(SET_IPV4_SRC,
3782d30ea906Sjfb8856606 			sizeof(struct rte_flow_action_set_ipv4)),
3783d30ea906Sjfb8856606 		.next = NEXT(action_set_ipv4_src),
3784d30ea906Sjfb8856606 		.call = parse_vc,
3785d30ea906Sjfb8856606 	},
3786d30ea906Sjfb8856606 	[ACTION_SET_IPV4_SRC_IPV4_SRC] = {
3787d30ea906Sjfb8856606 		.name = "ipv4_addr",
3788d30ea906Sjfb8856606 		.help = "new IPv4 source address to set",
3789d30ea906Sjfb8856606 		.next = NEXT(action_set_ipv4_src, NEXT_ENTRY(IPV4_ADDR)),
3790d30ea906Sjfb8856606 		.args = ARGS(ARGS_ENTRY_HTON
3791d30ea906Sjfb8856606 			(struct rte_flow_action_set_ipv4, ipv4_addr)),
3792d30ea906Sjfb8856606 		.call = parse_vc_conf,
3793d30ea906Sjfb8856606 	},
3794d30ea906Sjfb8856606 	[ACTION_SET_IPV4_DST] = {
3795d30ea906Sjfb8856606 		.name = "set_ipv4_dst",
3796d30ea906Sjfb8856606 		.help = "Set a new IPv4 destination address in the outermost"
3797d30ea906Sjfb8856606 			" IPv4 header",
3798d30ea906Sjfb8856606 		.priv = PRIV_ACTION(SET_IPV4_DST,
3799d30ea906Sjfb8856606 			sizeof(struct rte_flow_action_set_ipv4)),
3800d30ea906Sjfb8856606 		.next = NEXT(action_set_ipv4_dst),
3801d30ea906Sjfb8856606 		.call = parse_vc,
3802d30ea906Sjfb8856606 	},
3803d30ea906Sjfb8856606 	[ACTION_SET_IPV4_DST_IPV4_DST] = {
3804d30ea906Sjfb8856606 		.name = "ipv4_addr",
3805d30ea906Sjfb8856606 		.help = "new IPv4 destination address to set",
3806d30ea906Sjfb8856606 		.next = NEXT(action_set_ipv4_dst, NEXT_ENTRY(IPV4_ADDR)),
3807d30ea906Sjfb8856606 		.args = ARGS(ARGS_ENTRY_HTON
3808d30ea906Sjfb8856606 			(struct rte_flow_action_set_ipv4, ipv4_addr)),
3809d30ea906Sjfb8856606 		.call = parse_vc_conf,
3810d30ea906Sjfb8856606 	},
3811d30ea906Sjfb8856606 	[ACTION_SET_IPV6_SRC] = {
3812d30ea906Sjfb8856606 		.name = "set_ipv6_src",
3813d30ea906Sjfb8856606 		.help = "Set a new IPv6 source address in the outermost"
3814d30ea906Sjfb8856606 			" IPv6 header",
3815d30ea906Sjfb8856606 		.priv = PRIV_ACTION(SET_IPV6_SRC,
3816d30ea906Sjfb8856606 			sizeof(struct rte_flow_action_set_ipv6)),
3817d30ea906Sjfb8856606 		.next = NEXT(action_set_ipv6_src),
3818d30ea906Sjfb8856606 		.call = parse_vc,
3819d30ea906Sjfb8856606 	},
3820d30ea906Sjfb8856606 	[ACTION_SET_IPV6_SRC_IPV6_SRC] = {
3821d30ea906Sjfb8856606 		.name = "ipv6_addr",
3822d30ea906Sjfb8856606 		.help = "new IPv6 source address to set",
3823d30ea906Sjfb8856606 		.next = NEXT(action_set_ipv6_src, NEXT_ENTRY(IPV6_ADDR)),
3824d30ea906Sjfb8856606 		.args = ARGS(ARGS_ENTRY_HTON
3825d30ea906Sjfb8856606 			(struct rte_flow_action_set_ipv6, ipv6_addr)),
3826d30ea906Sjfb8856606 		.call = parse_vc_conf,
3827d30ea906Sjfb8856606 	},
3828d30ea906Sjfb8856606 	[ACTION_SET_IPV6_DST] = {
3829d30ea906Sjfb8856606 		.name = "set_ipv6_dst",
3830d30ea906Sjfb8856606 		.help = "Set a new IPv6 destination address in the outermost"
3831d30ea906Sjfb8856606 			" IPv6 header",
3832d30ea906Sjfb8856606 		.priv = PRIV_ACTION(SET_IPV6_DST,
3833d30ea906Sjfb8856606 			sizeof(struct rte_flow_action_set_ipv6)),
3834d30ea906Sjfb8856606 		.next = NEXT(action_set_ipv6_dst),
3835d30ea906Sjfb8856606 		.call = parse_vc,
3836d30ea906Sjfb8856606 	},
3837d30ea906Sjfb8856606 	[ACTION_SET_IPV6_DST_IPV6_DST] = {
3838d30ea906Sjfb8856606 		.name = "ipv6_addr",
3839d30ea906Sjfb8856606 		.help = "new IPv6 destination address to set",
3840d30ea906Sjfb8856606 		.next = NEXT(action_set_ipv6_dst, NEXT_ENTRY(IPV6_ADDR)),
3841d30ea906Sjfb8856606 		.args = ARGS(ARGS_ENTRY_HTON
3842d30ea906Sjfb8856606 			(struct rte_flow_action_set_ipv6, ipv6_addr)),
3843d30ea906Sjfb8856606 		.call = parse_vc_conf,
3844d30ea906Sjfb8856606 	},
3845d30ea906Sjfb8856606 	[ACTION_SET_TP_SRC] = {
3846d30ea906Sjfb8856606 		.name = "set_tp_src",
3847d30ea906Sjfb8856606 		.help = "set a new source port number in the outermost"
3848d30ea906Sjfb8856606 			" TCP/UDP header",
3849d30ea906Sjfb8856606 		.priv = PRIV_ACTION(SET_TP_SRC,
3850d30ea906Sjfb8856606 			sizeof(struct rte_flow_action_set_tp)),
3851d30ea906Sjfb8856606 		.next = NEXT(action_set_tp_src),
3852d30ea906Sjfb8856606 		.call = parse_vc,
3853d30ea906Sjfb8856606 	},
3854d30ea906Sjfb8856606 	[ACTION_SET_TP_SRC_TP_SRC] = {
3855d30ea906Sjfb8856606 		.name = "port",
3856d30ea906Sjfb8856606 		.help = "new source port number to set",
3857d30ea906Sjfb8856606 		.next = NEXT(action_set_tp_src, NEXT_ENTRY(UNSIGNED)),
3858d30ea906Sjfb8856606 		.args = ARGS(ARGS_ENTRY_HTON
3859d30ea906Sjfb8856606 			     (struct rte_flow_action_set_tp, port)),
3860d30ea906Sjfb8856606 		.call = parse_vc_conf,
3861d30ea906Sjfb8856606 	},
3862d30ea906Sjfb8856606 	[ACTION_SET_TP_DST] = {
3863d30ea906Sjfb8856606 		.name = "set_tp_dst",
3864d30ea906Sjfb8856606 		.help = "set a new destination port number in the outermost"
3865d30ea906Sjfb8856606 			" TCP/UDP header",
3866d30ea906Sjfb8856606 		.priv = PRIV_ACTION(SET_TP_DST,
3867d30ea906Sjfb8856606 			sizeof(struct rte_flow_action_set_tp)),
3868d30ea906Sjfb8856606 		.next = NEXT(action_set_tp_dst),
3869d30ea906Sjfb8856606 		.call = parse_vc,
3870d30ea906Sjfb8856606 	},
3871d30ea906Sjfb8856606 	[ACTION_SET_TP_DST_TP_DST] = {
3872d30ea906Sjfb8856606 		.name = "port",
3873d30ea906Sjfb8856606 		.help = "new destination port number to set",
3874d30ea906Sjfb8856606 		.next = NEXT(action_set_tp_dst, NEXT_ENTRY(UNSIGNED)),
3875d30ea906Sjfb8856606 		.args = ARGS(ARGS_ENTRY_HTON
3876d30ea906Sjfb8856606 			     (struct rte_flow_action_set_tp, port)),
3877d30ea906Sjfb8856606 		.call = parse_vc_conf,
3878d30ea906Sjfb8856606 	},
3879d30ea906Sjfb8856606 	[ACTION_MAC_SWAP] = {
3880d30ea906Sjfb8856606 		.name = "mac_swap",
3881d30ea906Sjfb8856606 		.help = "Swap the source and destination MAC addresses"
3882d30ea906Sjfb8856606 			" in the outermost Ethernet header",
3883d30ea906Sjfb8856606 		.priv = PRIV_ACTION(MAC_SWAP, 0),
3884d30ea906Sjfb8856606 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
3885d30ea906Sjfb8856606 		.call = parse_vc,
3886d30ea906Sjfb8856606 	},
3887d30ea906Sjfb8856606 	[ACTION_DEC_TTL] = {
3888d30ea906Sjfb8856606 		.name = "dec_ttl",
3889d30ea906Sjfb8856606 		.help = "decrease network TTL if available",
3890d30ea906Sjfb8856606 		.priv = PRIV_ACTION(DEC_TTL, 0),
3891d30ea906Sjfb8856606 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
3892d30ea906Sjfb8856606 		.call = parse_vc,
3893d30ea906Sjfb8856606 	},
3894d30ea906Sjfb8856606 	[ACTION_SET_TTL] = {
3895d30ea906Sjfb8856606 		.name = "set_ttl",
3896d30ea906Sjfb8856606 		.help = "set ttl value",
3897d30ea906Sjfb8856606 		.priv = PRIV_ACTION(SET_TTL,
3898d30ea906Sjfb8856606 			sizeof(struct rte_flow_action_set_ttl)),
3899d30ea906Sjfb8856606 		.next = NEXT(action_set_ttl),
3900d30ea906Sjfb8856606 		.call = parse_vc,
3901d30ea906Sjfb8856606 	},
3902d30ea906Sjfb8856606 	[ACTION_SET_TTL_TTL] = {
3903d30ea906Sjfb8856606 		.name = "ttl_value",
3904d30ea906Sjfb8856606 		.help = "new ttl value to set",
3905d30ea906Sjfb8856606 		.next = NEXT(action_set_ttl, NEXT_ENTRY(UNSIGNED)),
3906d30ea906Sjfb8856606 		.args = ARGS(ARGS_ENTRY_HTON
3907d30ea906Sjfb8856606 			     (struct rte_flow_action_set_ttl, ttl_value)),
3908d30ea906Sjfb8856606 		.call = parse_vc_conf,
3909d30ea906Sjfb8856606 	},
3910d30ea906Sjfb8856606 	[ACTION_SET_MAC_SRC] = {
3911d30ea906Sjfb8856606 		.name = "set_mac_src",
3912d30ea906Sjfb8856606 		.help = "set source mac address",
3913d30ea906Sjfb8856606 		.priv = PRIV_ACTION(SET_MAC_SRC,
3914d30ea906Sjfb8856606 			sizeof(struct rte_flow_action_set_mac)),
3915d30ea906Sjfb8856606 		.next = NEXT(action_set_mac_src),
3916d30ea906Sjfb8856606 		.call = parse_vc,
3917d30ea906Sjfb8856606 	},
3918d30ea906Sjfb8856606 	[ACTION_SET_MAC_SRC_MAC_SRC] = {
3919d30ea906Sjfb8856606 		.name = "mac_addr",
3920d30ea906Sjfb8856606 		.help = "new source mac address",
3921d30ea906Sjfb8856606 		.next = NEXT(action_set_mac_src, NEXT_ENTRY(MAC_ADDR)),
3922d30ea906Sjfb8856606 		.args = ARGS(ARGS_ENTRY_HTON
3923d30ea906Sjfb8856606 			     (struct rte_flow_action_set_mac, mac_addr)),
3924d30ea906Sjfb8856606 		.call = parse_vc_conf,
3925d30ea906Sjfb8856606 	},
3926d30ea906Sjfb8856606 	[ACTION_SET_MAC_DST] = {
3927d30ea906Sjfb8856606 		.name = "set_mac_dst",
3928d30ea906Sjfb8856606 		.help = "set destination mac address",
3929d30ea906Sjfb8856606 		.priv = PRIV_ACTION(SET_MAC_DST,
3930d30ea906Sjfb8856606 			sizeof(struct rte_flow_action_set_mac)),
3931d30ea906Sjfb8856606 		.next = NEXT(action_set_mac_dst),
3932d30ea906Sjfb8856606 		.call = parse_vc,
3933d30ea906Sjfb8856606 	},
3934d30ea906Sjfb8856606 	[ACTION_SET_MAC_DST_MAC_DST] = {
3935d30ea906Sjfb8856606 		.name = "mac_addr",
3936d30ea906Sjfb8856606 		.help = "new destination mac address to set",
3937d30ea906Sjfb8856606 		.next = NEXT(action_set_mac_dst, NEXT_ENTRY(MAC_ADDR)),
3938d30ea906Sjfb8856606 		.args = ARGS(ARGS_ENTRY_HTON
3939d30ea906Sjfb8856606 			     (struct rte_flow_action_set_mac, mac_addr)),
3940d30ea906Sjfb8856606 		.call = parse_vc_conf,
3941d30ea906Sjfb8856606 	},
39424418919fSjohnjiang 	[ACTION_INC_TCP_SEQ] = {
39434418919fSjohnjiang 		.name = "inc_tcp_seq",
39444418919fSjohnjiang 		.help = "increase TCP sequence number",
39454418919fSjohnjiang 		.priv = PRIV_ACTION(INC_TCP_SEQ, sizeof(rte_be32_t)),
39464418919fSjohnjiang 		.next = NEXT(action_inc_tcp_seq),
39474418919fSjohnjiang 		.call = parse_vc,
39484418919fSjohnjiang 	},
39494418919fSjohnjiang 	[ACTION_INC_TCP_SEQ_VALUE] = {
39504418919fSjohnjiang 		.name = "value",
39514418919fSjohnjiang 		.help = "the value to increase TCP sequence number by",
39524418919fSjohnjiang 		.next = NEXT(action_inc_tcp_seq, NEXT_ENTRY(UNSIGNED)),
39534418919fSjohnjiang 		.args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
39544418919fSjohnjiang 		.call = parse_vc_conf,
39554418919fSjohnjiang 	},
39564418919fSjohnjiang 	[ACTION_DEC_TCP_SEQ] = {
39574418919fSjohnjiang 		.name = "dec_tcp_seq",
39584418919fSjohnjiang 		.help = "decrease TCP sequence number",
39594418919fSjohnjiang 		.priv = PRIV_ACTION(DEC_TCP_SEQ, sizeof(rte_be32_t)),
39604418919fSjohnjiang 		.next = NEXT(action_dec_tcp_seq),
39614418919fSjohnjiang 		.call = parse_vc,
39624418919fSjohnjiang 	},
39634418919fSjohnjiang 	[ACTION_DEC_TCP_SEQ_VALUE] = {
39644418919fSjohnjiang 		.name = "value",
39654418919fSjohnjiang 		.help = "the value to decrease TCP sequence number by",
39664418919fSjohnjiang 		.next = NEXT(action_dec_tcp_seq, NEXT_ENTRY(UNSIGNED)),
39674418919fSjohnjiang 		.args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
39684418919fSjohnjiang 		.call = parse_vc_conf,
39694418919fSjohnjiang 	},
39704418919fSjohnjiang 	[ACTION_INC_TCP_ACK] = {
39714418919fSjohnjiang 		.name = "inc_tcp_ack",
39724418919fSjohnjiang 		.help = "increase TCP acknowledgment number",
39734418919fSjohnjiang 		.priv = PRIV_ACTION(INC_TCP_ACK, sizeof(rte_be32_t)),
39744418919fSjohnjiang 		.next = NEXT(action_inc_tcp_ack),
39754418919fSjohnjiang 		.call = parse_vc,
39764418919fSjohnjiang 	},
39774418919fSjohnjiang 	[ACTION_INC_TCP_ACK_VALUE] = {
39784418919fSjohnjiang 		.name = "value",
39794418919fSjohnjiang 		.help = "the value to increase TCP acknowledgment number by",
39804418919fSjohnjiang 		.next = NEXT(action_inc_tcp_ack, NEXT_ENTRY(UNSIGNED)),
39814418919fSjohnjiang 		.args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
39824418919fSjohnjiang 		.call = parse_vc_conf,
39834418919fSjohnjiang 	},
39844418919fSjohnjiang 	[ACTION_DEC_TCP_ACK] = {
39854418919fSjohnjiang 		.name = "dec_tcp_ack",
39864418919fSjohnjiang 		.help = "decrease TCP acknowledgment number",
39874418919fSjohnjiang 		.priv = PRIV_ACTION(DEC_TCP_ACK, sizeof(rte_be32_t)),
39884418919fSjohnjiang 		.next = NEXT(action_dec_tcp_ack),
39894418919fSjohnjiang 		.call = parse_vc,
39904418919fSjohnjiang 	},
39914418919fSjohnjiang 	[ACTION_DEC_TCP_ACK_VALUE] = {
39924418919fSjohnjiang 		.name = "value",
39934418919fSjohnjiang 		.help = "the value to decrease TCP acknowledgment number by",
39944418919fSjohnjiang 		.next = NEXT(action_dec_tcp_ack, NEXT_ENTRY(UNSIGNED)),
39954418919fSjohnjiang 		.args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
39964418919fSjohnjiang 		.call = parse_vc_conf,
39974418919fSjohnjiang 	},
39984418919fSjohnjiang 	[ACTION_RAW_ENCAP] = {
39994418919fSjohnjiang 		.name = "raw_encap",
40004418919fSjohnjiang 		.help = "encapsulation data, defined by set raw_encap",
40014418919fSjohnjiang 		.priv = PRIV_ACTION(RAW_ENCAP,
40024418919fSjohnjiang 			sizeof(struct action_raw_encap_data)),
40034418919fSjohnjiang 		.next = NEXT(action_raw_encap),
40044418919fSjohnjiang 		.call = parse_vc_action_raw_encap,
40054418919fSjohnjiang 	},
40064418919fSjohnjiang 	[ACTION_RAW_ENCAP_INDEX] = {
40074418919fSjohnjiang 		.name = "index",
40084418919fSjohnjiang 		.help = "the index of raw_encap_confs",
40094418919fSjohnjiang 		.next = NEXT(NEXT_ENTRY(ACTION_RAW_ENCAP_INDEX_VALUE)),
40104418919fSjohnjiang 	},
40114418919fSjohnjiang 	[ACTION_RAW_ENCAP_INDEX_VALUE] = {
40124418919fSjohnjiang 		.name = "{index}",
40134418919fSjohnjiang 		.type = "UNSIGNED",
40144418919fSjohnjiang 		.help = "unsigned integer value",
40154418919fSjohnjiang 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
40164418919fSjohnjiang 		.call = parse_vc_action_raw_encap_index,
40174418919fSjohnjiang 		.comp = comp_set_raw_index,
40184418919fSjohnjiang 	},
40194418919fSjohnjiang 	[ACTION_RAW_DECAP] = {
40204418919fSjohnjiang 		.name = "raw_decap",
40214418919fSjohnjiang 		.help = "decapsulation data, defined by set raw_encap",
40224418919fSjohnjiang 		.priv = PRIV_ACTION(RAW_DECAP,
40234418919fSjohnjiang 			sizeof(struct action_raw_decap_data)),
40244418919fSjohnjiang 		.next = NEXT(action_raw_decap),
40254418919fSjohnjiang 		.call = parse_vc_action_raw_decap,
40264418919fSjohnjiang 	},
40274418919fSjohnjiang 	[ACTION_RAW_DECAP_INDEX] = {
40284418919fSjohnjiang 		.name = "index",
40294418919fSjohnjiang 		.help = "the index of raw_encap_confs",
40304418919fSjohnjiang 		.next = NEXT(NEXT_ENTRY(ACTION_RAW_DECAP_INDEX_VALUE)),
40314418919fSjohnjiang 	},
40324418919fSjohnjiang 	[ACTION_RAW_DECAP_INDEX_VALUE] = {
40334418919fSjohnjiang 		.name = "{index}",
40344418919fSjohnjiang 		.type = "UNSIGNED",
40354418919fSjohnjiang 		.help = "unsigned integer value",
40364418919fSjohnjiang 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
40374418919fSjohnjiang 		.call = parse_vc_action_raw_decap_index,
40384418919fSjohnjiang 		.comp = comp_set_raw_index,
40394418919fSjohnjiang 	},
40404418919fSjohnjiang 	/* Top level command. */
40414418919fSjohnjiang 	[SET] = {
40424418919fSjohnjiang 		.name = "set",
4043*2d9fd380Sjfb8856606 		.help = "set raw encap/decap/sample data",
4044*2d9fd380Sjfb8856606 		.type = "set raw_encap|raw_decap <index> <pattern>"
4045*2d9fd380Sjfb8856606 				" or set sample_actions <index> <action>",
40464418919fSjohnjiang 		.next = NEXT(NEXT_ENTRY
40474418919fSjohnjiang 			     (SET_RAW_ENCAP,
4048*2d9fd380Sjfb8856606 			      SET_RAW_DECAP,
4049*2d9fd380Sjfb8856606 			      SET_SAMPLE_ACTIONS)),
40504418919fSjohnjiang 		.call = parse_set_init,
40514418919fSjohnjiang 	},
40524418919fSjohnjiang 	/* Sub-level commands. */
40534418919fSjohnjiang 	[SET_RAW_ENCAP] = {
40544418919fSjohnjiang 		.name = "raw_encap",
40554418919fSjohnjiang 		.help = "set raw encap data",
40564418919fSjohnjiang 		.next = NEXT(next_set_raw),
40574418919fSjohnjiang 		.args = ARGS(ARGS_ENTRY_ARB_BOUNDED
40584418919fSjohnjiang 				(offsetof(struct buffer, port),
40594418919fSjohnjiang 				 sizeof(((struct buffer *)0)->port),
40604418919fSjohnjiang 				 0, RAW_ENCAP_CONFS_MAX_NUM - 1)),
40614418919fSjohnjiang 		.call = parse_set_raw_encap_decap,
40624418919fSjohnjiang 	},
40634418919fSjohnjiang 	[SET_RAW_DECAP] = {
40644418919fSjohnjiang 		.name = "raw_decap",
40654418919fSjohnjiang 		.help = "set raw decap data",
40664418919fSjohnjiang 		.next = NEXT(next_set_raw),
40674418919fSjohnjiang 		.args = ARGS(ARGS_ENTRY_ARB_BOUNDED
40684418919fSjohnjiang 				(offsetof(struct buffer, port),
40694418919fSjohnjiang 				 sizeof(((struct buffer *)0)->port),
40704418919fSjohnjiang 				 0, RAW_ENCAP_CONFS_MAX_NUM - 1)),
40714418919fSjohnjiang 		.call = parse_set_raw_encap_decap,
40724418919fSjohnjiang 	},
40734418919fSjohnjiang 	[SET_RAW_INDEX] = {
40744418919fSjohnjiang 		.name = "{index}",
40754418919fSjohnjiang 		.type = "UNSIGNED",
40764418919fSjohnjiang 		.help = "index of raw_encap/raw_decap data",
40774418919fSjohnjiang 		.next = NEXT(next_item),
40784418919fSjohnjiang 		.call = parse_port,
40794418919fSjohnjiang 	},
4080*2d9fd380Sjfb8856606 	[SET_SAMPLE_INDEX] = {
4081*2d9fd380Sjfb8856606 		.name = "{index}",
4082*2d9fd380Sjfb8856606 		.type = "UNSIGNED",
4083*2d9fd380Sjfb8856606 		.help = "index of sample actions",
4084*2d9fd380Sjfb8856606 		.next = NEXT(next_action_sample),
4085*2d9fd380Sjfb8856606 		.call = parse_port,
4086*2d9fd380Sjfb8856606 	},
4087*2d9fd380Sjfb8856606 	[SET_SAMPLE_ACTIONS] = {
4088*2d9fd380Sjfb8856606 		.name = "sample_actions",
4089*2d9fd380Sjfb8856606 		.help = "set sample actions list",
4090*2d9fd380Sjfb8856606 		.next = NEXT(NEXT_ENTRY(SET_SAMPLE_INDEX)),
4091*2d9fd380Sjfb8856606 		.args = ARGS(ARGS_ENTRY_ARB_BOUNDED
4092*2d9fd380Sjfb8856606 				(offsetof(struct buffer, port),
4093*2d9fd380Sjfb8856606 				 sizeof(((struct buffer *)0)->port),
4094*2d9fd380Sjfb8856606 				 0, RAW_SAMPLE_CONFS_MAX_NUM - 1)),
4095*2d9fd380Sjfb8856606 		.call = parse_set_sample_action,
4096*2d9fd380Sjfb8856606 	},
40974418919fSjohnjiang 	[ACTION_SET_TAG] = {
40984418919fSjohnjiang 		.name = "set_tag",
40994418919fSjohnjiang 		.help = "set tag",
41004418919fSjohnjiang 		.priv = PRIV_ACTION(SET_TAG,
41014418919fSjohnjiang 			sizeof(struct rte_flow_action_set_tag)),
41024418919fSjohnjiang 		.next = NEXT(action_set_tag),
41034418919fSjohnjiang 		.call = parse_vc,
41044418919fSjohnjiang 	},
41054418919fSjohnjiang 	[ACTION_SET_TAG_INDEX] = {
41064418919fSjohnjiang 		.name = "index",
41074418919fSjohnjiang 		.help = "index of tag array",
41084418919fSjohnjiang 		.next = NEXT(action_set_tag, NEXT_ENTRY(UNSIGNED)),
41094418919fSjohnjiang 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_set_tag, index)),
41104418919fSjohnjiang 		.call = parse_vc_conf,
41114418919fSjohnjiang 	},
41124418919fSjohnjiang 	[ACTION_SET_TAG_DATA] = {
41134418919fSjohnjiang 		.name = "data",
41144418919fSjohnjiang 		.help = "tag value",
41154418919fSjohnjiang 		.next = NEXT(action_set_tag, NEXT_ENTRY(UNSIGNED)),
41164418919fSjohnjiang 		.args = ARGS(ARGS_ENTRY
41174418919fSjohnjiang 			     (struct rte_flow_action_set_tag, data)),
41184418919fSjohnjiang 		.call = parse_vc_conf,
41194418919fSjohnjiang 	},
41204418919fSjohnjiang 	[ACTION_SET_TAG_MASK] = {
41214418919fSjohnjiang 		.name = "mask",
41224418919fSjohnjiang 		.help = "mask for tag value",
41234418919fSjohnjiang 		.next = NEXT(action_set_tag, NEXT_ENTRY(UNSIGNED)),
41244418919fSjohnjiang 		.args = ARGS(ARGS_ENTRY
41254418919fSjohnjiang 			     (struct rte_flow_action_set_tag, mask)),
41264418919fSjohnjiang 		.call = parse_vc_conf,
41274418919fSjohnjiang 	},
41284418919fSjohnjiang 	[ACTION_SET_META] = {
41294418919fSjohnjiang 		.name = "set_meta",
41304418919fSjohnjiang 		.help = "set metadata",
41314418919fSjohnjiang 		.priv = PRIV_ACTION(SET_META,
41324418919fSjohnjiang 			sizeof(struct rte_flow_action_set_meta)),
41334418919fSjohnjiang 		.next = NEXT(action_set_meta),
41344418919fSjohnjiang 		.call = parse_vc_action_set_meta,
41354418919fSjohnjiang 	},
41364418919fSjohnjiang 	[ACTION_SET_META_DATA] = {
41374418919fSjohnjiang 		.name = "data",
41384418919fSjohnjiang 		.help = "metadata value",
41394418919fSjohnjiang 		.next = NEXT(action_set_meta, NEXT_ENTRY(UNSIGNED)),
41404418919fSjohnjiang 		.args = ARGS(ARGS_ENTRY
41414418919fSjohnjiang 			     (struct rte_flow_action_set_meta, data)),
41424418919fSjohnjiang 		.call = parse_vc_conf,
41434418919fSjohnjiang 	},
41444418919fSjohnjiang 	[ACTION_SET_META_MASK] = {
41454418919fSjohnjiang 		.name = "mask",
41464418919fSjohnjiang 		.help = "mask for metadata value",
41474418919fSjohnjiang 		.next = NEXT(action_set_meta, NEXT_ENTRY(UNSIGNED)),
41484418919fSjohnjiang 		.args = ARGS(ARGS_ENTRY
41494418919fSjohnjiang 			     (struct rte_flow_action_set_meta, mask)),
41504418919fSjohnjiang 		.call = parse_vc_conf,
41514418919fSjohnjiang 	},
4152*2d9fd380Sjfb8856606 	[ACTION_SET_IPV4_DSCP] = {
4153*2d9fd380Sjfb8856606 		.name = "set_ipv4_dscp",
4154*2d9fd380Sjfb8856606 		.help = "set DSCP value",
4155*2d9fd380Sjfb8856606 		.priv = PRIV_ACTION(SET_IPV4_DSCP,
4156*2d9fd380Sjfb8856606 			sizeof(struct rte_flow_action_set_dscp)),
4157*2d9fd380Sjfb8856606 		.next = NEXT(action_set_ipv4_dscp),
4158*2d9fd380Sjfb8856606 		.call = parse_vc,
4159*2d9fd380Sjfb8856606 	},
4160*2d9fd380Sjfb8856606 	[ACTION_SET_IPV4_DSCP_VALUE] = {
4161*2d9fd380Sjfb8856606 		.name = "dscp_value",
4162*2d9fd380Sjfb8856606 		.help = "new IPv4 DSCP value to set",
4163*2d9fd380Sjfb8856606 		.next = NEXT(action_set_ipv4_dscp, NEXT_ENTRY(UNSIGNED)),
4164*2d9fd380Sjfb8856606 		.args = ARGS(ARGS_ENTRY
4165*2d9fd380Sjfb8856606 			     (struct rte_flow_action_set_dscp, dscp)),
4166*2d9fd380Sjfb8856606 		.call = parse_vc_conf,
4167*2d9fd380Sjfb8856606 	},
4168*2d9fd380Sjfb8856606 	[ACTION_SET_IPV6_DSCP] = {
4169*2d9fd380Sjfb8856606 		.name = "set_ipv6_dscp",
4170*2d9fd380Sjfb8856606 		.help = "set DSCP value",
4171*2d9fd380Sjfb8856606 		.priv = PRIV_ACTION(SET_IPV6_DSCP,
4172*2d9fd380Sjfb8856606 			sizeof(struct rte_flow_action_set_dscp)),
4173*2d9fd380Sjfb8856606 		.next = NEXT(action_set_ipv6_dscp),
4174*2d9fd380Sjfb8856606 		.call = parse_vc,
4175*2d9fd380Sjfb8856606 	},
4176*2d9fd380Sjfb8856606 	[ACTION_SET_IPV6_DSCP_VALUE] = {
4177*2d9fd380Sjfb8856606 		.name = "dscp_value",
4178*2d9fd380Sjfb8856606 		.help = "new IPv6 DSCP value to set",
4179*2d9fd380Sjfb8856606 		.next = NEXT(action_set_ipv6_dscp, NEXT_ENTRY(UNSIGNED)),
4180*2d9fd380Sjfb8856606 		.args = ARGS(ARGS_ENTRY
4181*2d9fd380Sjfb8856606 			     (struct rte_flow_action_set_dscp, dscp)),
4182*2d9fd380Sjfb8856606 		.call = parse_vc_conf,
4183*2d9fd380Sjfb8856606 	},
4184*2d9fd380Sjfb8856606 	[ACTION_AGE] = {
4185*2d9fd380Sjfb8856606 		.name = "age",
4186*2d9fd380Sjfb8856606 		.help = "set a specific metadata header",
4187*2d9fd380Sjfb8856606 		.next = NEXT(action_age),
4188*2d9fd380Sjfb8856606 		.priv = PRIV_ACTION(AGE,
4189*2d9fd380Sjfb8856606 			sizeof(struct rte_flow_action_age)),
4190*2d9fd380Sjfb8856606 		.call = parse_vc,
4191*2d9fd380Sjfb8856606 	},
4192*2d9fd380Sjfb8856606 	[ACTION_AGE_TIMEOUT] = {
4193*2d9fd380Sjfb8856606 		.name = "timeout",
4194*2d9fd380Sjfb8856606 		.help = "flow age timeout value",
4195*2d9fd380Sjfb8856606 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_age,
4196*2d9fd380Sjfb8856606 					   timeout, 24)),
4197*2d9fd380Sjfb8856606 		.next = NEXT(action_age, NEXT_ENTRY(UNSIGNED)),
4198*2d9fd380Sjfb8856606 		.call = parse_vc_conf,
4199*2d9fd380Sjfb8856606 	},
4200*2d9fd380Sjfb8856606 	[ACTION_SAMPLE] = {
4201*2d9fd380Sjfb8856606 		.name = "sample",
4202*2d9fd380Sjfb8856606 		.help = "set a sample action",
4203*2d9fd380Sjfb8856606 		.next = NEXT(action_sample),
4204*2d9fd380Sjfb8856606 		.priv = PRIV_ACTION(SAMPLE,
4205*2d9fd380Sjfb8856606 			sizeof(struct action_sample_data)),
4206*2d9fd380Sjfb8856606 		.call = parse_vc_action_sample,
4207*2d9fd380Sjfb8856606 	},
4208*2d9fd380Sjfb8856606 	[ACTION_SAMPLE_RATIO] = {
4209*2d9fd380Sjfb8856606 		.name = "ratio",
4210*2d9fd380Sjfb8856606 		.help = "flow sample ratio value",
4211*2d9fd380Sjfb8856606 		.next = NEXT(action_sample, NEXT_ENTRY(UNSIGNED)),
4212*2d9fd380Sjfb8856606 		.args = ARGS(ARGS_ENTRY_ARB
4213*2d9fd380Sjfb8856606 			     (offsetof(struct action_sample_data, conf) +
4214*2d9fd380Sjfb8856606 			      offsetof(struct rte_flow_action_sample, ratio),
4215*2d9fd380Sjfb8856606 			      sizeof(((struct rte_flow_action_sample *)0)->
4216*2d9fd380Sjfb8856606 				     ratio))),
4217*2d9fd380Sjfb8856606 	},
4218*2d9fd380Sjfb8856606 	[ACTION_SAMPLE_INDEX] = {
4219*2d9fd380Sjfb8856606 		.name = "index",
4220*2d9fd380Sjfb8856606 		.help = "the index of sample actions list",
4221*2d9fd380Sjfb8856606 		.next = NEXT(NEXT_ENTRY(ACTION_SAMPLE_INDEX_VALUE)),
4222*2d9fd380Sjfb8856606 	},
4223*2d9fd380Sjfb8856606 	[ACTION_SAMPLE_INDEX_VALUE] = {
4224*2d9fd380Sjfb8856606 		.name = "{index}",
4225*2d9fd380Sjfb8856606 		.type = "UNSIGNED",
4226*2d9fd380Sjfb8856606 		.help = "unsigned integer value",
4227*2d9fd380Sjfb8856606 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4228*2d9fd380Sjfb8856606 		.call = parse_vc_action_sample_index,
4229*2d9fd380Sjfb8856606 		.comp = comp_set_sample_index,
4230*2d9fd380Sjfb8856606 	},
4231*2d9fd380Sjfb8856606 	/* Shared action destroy arguments. */
4232*2d9fd380Sjfb8856606 	[SHARED_ACTION_DESTROY_ID] = {
4233*2d9fd380Sjfb8856606 		.name = "action_id",
4234*2d9fd380Sjfb8856606 		.help = "specify a shared action id to destroy",
4235*2d9fd380Sjfb8856606 		.next = NEXT(next_sa_destroy_attr,
4236*2d9fd380Sjfb8856606 			     NEXT_ENTRY(SHARED_ACTION_ID)),
4237*2d9fd380Sjfb8856606 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer,
4238*2d9fd380Sjfb8856606 					    args.sa_destroy.action_id)),
4239*2d9fd380Sjfb8856606 		.call = parse_sa_destroy,
4240*2d9fd380Sjfb8856606 	},
4241*2d9fd380Sjfb8856606 	/* Shared action create arguments. */
4242*2d9fd380Sjfb8856606 	[SHARED_ACTION_CREATE_ID] = {
4243*2d9fd380Sjfb8856606 		.name = "action_id",
4244*2d9fd380Sjfb8856606 		.help = "specify a shared action id to create",
4245*2d9fd380Sjfb8856606 		.next = NEXT(next_sa_create_attr,
4246*2d9fd380Sjfb8856606 			     NEXT_ENTRY(SHARED_ACTION_ID)),
4247*2d9fd380Sjfb8856606 		.args = ARGS(ARGS_ENTRY(struct buffer, args.vc.attr.group)),
4248*2d9fd380Sjfb8856606 	},
4249*2d9fd380Sjfb8856606 	[ACTION_SHARED] = {
4250*2d9fd380Sjfb8856606 		.name = "shared",
4251*2d9fd380Sjfb8856606 		.help = "apply shared action by id",
4252*2d9fd380Sjfb8856606 		.priv = PRIV_ACTION(SHARED, 0),
4253*2d9fd380Sjfb8856606 		.next = NEXT(NEXT_ENTRY(SHARED_ACTION_ID2PTR)),
4254*2d9fd380Sjfb8856606 		.args = ARGS(ARGS_ENTRY_ARB(0, sizeof(uint32_t))),
4255*2d9fd380Sjfb8856606 		.call = parse_vc,
4256*2d9fd380Sjfb8856606 	},
4257*2d9fd380Sjfb8856606 	[SHARED_ACTION_ID2PTR] = {
4258*2d9fd380Sjfb8856606 		.name = "{action_id}",
4259*2d9fd380Sjfb8856606 		.type = "SHARED_ACTION_ID",
4260*2d9fd380Sjfb8856606 		.help = "shared action id",
4261*2d9fd380Sjfb8856606 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4262*2d9fd380Sjfb8856606 		.call = parse_sa_id2ptr,
4263*2d9fd380Sjfb8856606 		.comp = comp_none,
4264*2d9fd380Sjfb8856606 	},
4265*2d9fd380Sjfb8856606 	[SHARED_ACTION_INGRESS] = {
4266*2d9fd380Sjfb8856606 		.name = "ingress",
4267*2d9fd380Sjfb8856606 		.help = "affect rule to ingress",
4268*2d9fd380Sjfb8856606 		.next = NEXT(next_sa_create_attr),
4269*2d9fd380Sjfb8856606 		.call = parse_sa,
4270*2d9fd380Sjfb8856606 	},
4271*2d9fd380Sjfb8856606 	[SHARED_ACTION_EGRESS] = {
4272*2d9fd380Sjfb8856606 		.name = "egress",
4273*2d9fd380Sjfb8856606 		.help = "affect rule to egress",
4274*2d9fd380Sjfb8856606 		.next = NEXT(next_sa_create_attr),
4275*2d9fd380Sjfb8856606 		.call = parse_sa,
4276*2d9fd380Sjfb8856606 	},
4277*2d9fd380Sjfb8856606 	[SHARED_ACTION_TRANSFER] = {
4278*2d9fd380Sjfb8856606 		.name = "transfer",
4279*2d9fd380Sjfb8856606 		.help = "affect rule to transfer",
4280*2d9fd380Sjfb8856606 		.next = NEXT(next_sa_create_attr),
4281*2d9fd380Sjfb8856606 		.call = parse_sa,
4282*2d9fd380Sjfb8856606 	},
4283*2d9fd380Sjfb8856606 	[SHARED_ACTION_SPEC] = {
4284*2d9fd380Sjfb8856606 		.name = "action",
4285*2d9fd380Sjfb8856606 		.help = "specify action to share",
4286*2d9fd380Sjfb8856606 		.next = NEXT(next_action),
4287*2d9fd380Sjfb8856606 	},
42882bfe3f2eSlogwang };
42892bfe3f2eSlogwang 
42902bfe3f2eSlogwang /** Remove and return last entry from argument stack. */
42912bfe3f2eSlogwang static const struct arg *
pop_args(struct context * ctx)42922bfe3f2eSlogwang pop_args(struct context *ctx)
42932bfe3f2eSlogwang {
42942bfe3f2eSlogwang 	return ctx->args_num ? ctx->args[--ctx->args_num] : NULL;
42952bfe3f2eSlogwang }
42962bfe3f2eSlogwang 
42972bfe3f2eSlogwang /** Add entry on top of the argument stack. */
42982bfe3f2eSlogwang static int
push_args(struct context * ctx,const struct arg * arg)42992bfe3f2eSlogwang push_args(struct context *ctx, const struct arg *arg)
43002bfe3f2eSlogwang {
43012bfe3f2eSlogwang 	if (ctx->args_num == CTX_STACK_SIZE)
43022bfe3f2eSlogwang 		return -1;
43032bfe3f2eSlogwang 	ctx->args[ctx->args_num++] = arg;
43042bfe3f2eSlogwang 	return 0;
43052bfe3f2eSlogwang }
43062bfe3f2eSlogwang 
43072bfe3f2eSlogwang /** Spread value into buffer according to bit-mask. */
43082bfe3f2eSlogwang static size_t
arg_entry_bf_fill(void * dst,uintmax_t val,const struct arg * arg)43092bfe3f2eSlogwang arg_entry_bf_fill(void *dst, uintmax_t val, const struct arg *arg)
43102bfe3f2eSlogwang {
43112bfe3f2eSlogwang 	uint32_t i = arg->size;
43122bfe3f2eSlogwang 	uint32_t end = 0;
43132bfe3f2eSlogwang 	int sub = 1;
43142bfe3f2eSlogwang 	int add = 0;
43152bfe3f2eSlogwang 	size_t len = 0;
43162bfe3f2eSlogwang 
43172bfe3f2eSlogwang 	if (!arg->mask)
43182bfe3f2eSlogwang 		return 0;
43192bfe3f2eSlogwang #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
43202bfe3f2eSlogwang 	if (!arg->hton) {
43212bfe3f2eSlogwang 		i = 0;
43222bfe3f2eSlogwang 		end = arg->size;
43232bfe3f2eSlogwang 		sub = 0;
43242bfe3f2eSlogwang 		add = 1;
43252bfe3f2eSlogwang 	}
43262bfe3f2eSlogwang #endif
43272bfe3f2eSlogwang 	while (i != end) {
43282bfe3f2eSlogwang 		unsigned int shift = 0;
43292bfe3f2eSlogwang 		uint8_t *buf = (uint8_t *)dst + arg->offset + (i -= sub);
43302bfe3f2eSlogwang 
43312bfe3f2eSlogwang 		for (shift = 0; arg->mask[i] >> shift; ++shift) {
43322bfe3f2eSlogwang 			if (!(arg->mask[i] & (1 << shift)))
43332bfe3f2eSlogwang 				continue;
43342bfe3f2eSlogwang 			++len;
43352bfe3f2eSlogwang 			if (!dst)
43362bfe3f2eSlogwang 				continue;
43372bfe3f2eSlogwang 			*buf &= ~(1 << shift);
43382bfe3f2eSlogwang 			*buf |= (val & 1) << shift;
43392bfe3f2eSlogwang 			val >>= 1;
43402bfe3f2eSlogwang 		}
43412bfe3f2eSlogwang 		i += add;
43422bfe3f2eSlogwang 	}
43432bfe3f2eSlogwang 	return len;
43442bfe3f2eSlogwang }
43452bfe3f2eSlogwang 
43462bfe3f2eSlogwang /** Compare a string with a partial one of a given length. */
43472bfe3f2eSlogwang static int
strcmp_partial(const char * full,const char * partial,size_t partial_len)43482bfe3f2eSlogwang strcmp_partial(const char *full, const char *partial, size_t partial_len)
43492bfe3f2eSlogwang {
43502bfe3f2eSlogwang 	int r = strncmp(full, partial, partial_len);
43512bfe3f2eSlogwang 
43522bfe3f2eSlogwang 	if (r)
43532bfe3f2eSlogwang 		return r;
43542bfe3f2eSlogwang 	if (strlen(full) <= partial_len)
43552bfe3f2eSlogwang 		return 0;
43562bfe3f2eSlogwang 	return full[partial_len];
43572bfe3f2eSlogwang }
43582bfe3f2eSlogwang 
43592bfe3f2eSlogwang /**
43602bfe3f2eSlogwang  * Parse a prefix length and generate a bit-mask.
43612bfe3f2eSlogwang  *
43622bfe3f2eSlogwang  * Last argument (ctx->args) is retrieved to determine mask size, storage
43632bfe3f2eSlogwang  * location and whether the result must use network byte ordering.
43642bfe3f2eSlogwang  */
43652bfe3f2eSlogwang static int
parse_prefix(struct context * ctx,const struct token * token,const char * str,unsigned int len,void * buf,unsigned int size)43662bfe3f2eSlogwang parse_prefix(struct context *ctx, const struct token *token,
43672bfe3f2eSlogwang 	     const char *str, unsigned int len,
43682bfe3f2eSlogwang 	     void *buf, unsigned int size)
43692bfe3f2eSlogwang {
43702bfe3f2eSlogwang 	const struct arg *arg = pop_args(ctx);
43712bfe3f2eSlogwang 	static const uint8_t conv[] = "\x00\x80\xc0\xe0\xf0\xf8\xfc\xfe\xff";
43722bfe3f2eSlogwang 	char *end;
43732bfe3f2eSlogwang 	uintmax_t u;
43742bfe3f2eSlogwang 	unsigned int bytes;
43752bfe3f2eSlogwang 	unsigned int extra;
43762bfe3f2eSlogwang 
43772bfe3f2eSlogwang 	(void)token;
43782bfe3f2eSlogwang 	/* Argument is expected. */
43792bfe3f2eSlogwang 	if (!arg)
43802bfe3f2eSlogwang 		return -1;
43812bfe3f2eSlogwang 	errno = 0;
43822bfe3f2eSlogwang 	u = strtoumax(str, &end, 0);
43832bfe3f2eSlogwang 	if (errno || (size_t)(end - str) != len)
43842bfe3f2eSlogwang 		goto error;
43852bfe3f2eSlogwang 	if (arg->mask) {
43862bfe3f2eSlogwang 		uintmax_t v = 0;
43872bfe3f2eSlogwang 
43882bfe3f2eSlogwang 		extra = arg_entry_bf_fill(NULL, 0, arg);
43892bfe3f2eSlogwang 		if (u > extra)
43902bfe3f2eSlogwang 			goto error;
43912bfe3f2eSlogwang 		if (!ctx->object)
43922bfe3f2eSlogwang 			return len;
43932bfe3f2eSlogwang 		extra -= u;
43942bfe3f2eSlogwang 		while (u--)
43952bfe3f2eSlogwang 			(v <<= 1, v |= 1);
43962bfe3f2eSlogwang 		v <<= extra;
43972bfe3f2eSlogwang 		if (!arg_entry_bf_fill(ctx->object, v, arg) ||
43982bfe3f2eSlogwang 		    !arg_entry_bf_fill(ctx->objmask, -1, arg))
43992bfe3f2eSlogwang 			goto error;
44002bfe3f2eSlogwang 		return len;
44012bfe3f2eSlogwang 	}
44022bfe3f2eSlogwang 	bytes = u / 8;
44032bfe3f2eSlogwang 	extra = u % 8;
44042bfe3f2eSlogwang 	size = arg->size;
44052bfe3f2eSlogwang 	if (bytes > size || bytes + !!extra > size)
44062bfe3f2eSlogwang 		goto error;
44072bfe3f2eSlogwang 	if (!ctx->object)
44082bfe3f2eSlogwang 		return len;
44092bfe3f2eSlogwang 	buf = (uint8_t *)ctx->object + arg->offset;
44102bfe3f2eSlogwang #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
44112bfe3f2eSlogwang 	if (!arg->hton) {
44122bfe3f2eSlogwang 		memset((uint8_t *)buf + size - bytes, 0xff, bytes);
44132bfe3f2eSlogwang 		memset(buf, 0x00, size - bytes);
44142bfe3f2eSlogwang 		if (extra)
44152bfe3f2eSlogwang 			((uint8_t *)buf)[size - bytes - 1] = conv[extra];
44162bfe3f2eSlogwang 	} else
44172bfe3f2eSlogwang #endif
44182bfe3f2eSlogwang 	{
44192bfe3f2eSlogwang 		memset(buf, 0xff, bytes);
44202bfe3f2eSlogwang 		memset((uint8_t *)buf + bytes, 0x00, size - bytes);
44212bfe3f2eSlogwang 		if (extra)
44222bfe3f2eSlogwang 			((uint8_t *)buf)[bytes] = conv[extra];
44232bfe3f2eSlogwang 	}
44242bfe3f2eSlogwang 	if (ctx->objmask)
44252bfe3f2eSlogwang 		memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
44262bfe3f2eSlogwang 	return len;
44272bfe3f2eSlogwang error:
44282bfe3f2eSlogwang 	push_args(ctx, arg);
44292bfe3f2eSlogwang 	return -1;
44302bfe3f2eSlogwang }
44312bfe3f2eSlogwang 
44322bfe3f2eSlogwang /** Default parsing function for token name matching. */
44332bfe3f2eSlogwang static int
parse_default(struct context * ctx,const struct token * token,const char * str,unsigned int len,void * buf,unsigned int size)44342bfe3f2eSlogwang parse_default(struct context *ctx, const struct token *token,
44352bfe3f2eSlogwang 	      const char *str, unsigned int len,
44362bfe3f2eSlogwang 	      void *buf, unsigned int size)
44372bfe3f2eSlogwang {
44382bfe3f2eSlogwang 	(void)ctx;
44392bfe3f2eSlogwang 	(void)buf;
44402bfe3f2eSlogwang 	(void)size;
44412bfe3f2eSlogwang 	if (strcmp_partial(token->name, str, len))
44422bfe3f2eSlogwang 		return -1;
44432bfe3f2eSlogwang 	return len;
44442bfe3f2eSlogwang }
44452bfe3f2eSlogwang 
44462bfe3f2eSlogwang /** Parse flow command, initialize output buffer for subsequent tokens. */
44472bfe3f2eSlogwang static int
parse_init(struct context * ctx,const struct token * token,const char * str,unsigned int len,void * buf,unsigned int size)44482bfe3f2eSlogwang parse_init(struct context *ctx, const struct token *token,
44492bfe3f2eSlogwang 	   const char *str, unsigned int len,
44502bfe3f2eSlogwang 	   void *buf, unsigned int size)
44512bfe3f2eSlogwang {
44522bfe3f2eSlogwang 	struct buffer *out = buf;
44532bfe3f2eSlogwang 
44542bfe3f2eSlogwang 	/* Token name must match. */
44552bfe3f2eSlogwang 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
44562bfe3f2eSlogwang 		return -1;
44572bfe3f2eSlogwang 	/* Nothing else to do if there is no buffer. */
44582bfe3f2eSlogwang 	if (!out)
44592bfe3f2eSlogwang 		return len;
44602bfe3f2eSlogwang 	/* Make sure buffer is large enough. */
44612bfe3f2eSlogwang 	if (size < sizeof(*out))
44622bfe3f2eSlogwang 		return -1;
44632bfe3f2eSlogwang 	/* Initialize buffer. */
44642bfe3f2eSlogwang 	memset(out, 0x00, sizeof(*out));
44652bfe3f2eSlogwang 	memset((uint8_t *)out + sizeof(*out), 0x22, size - sizeof(*out));
44662bfe3f2eSlogwang 	ctx->objdata = 0;
44672bfe3f2eSlogwang 	ctx->object = out;
44682bfe3f2eSlogwang 	ctx->objmask = NULL;
44692bfe3f2eSlogwang 	return len;
44702bfe3f2eSlogwang }
44712bfe3f2eSlogwang 
4472*2d9fd380Sjfb8856606 /** Parse tokens for shared action commands. */
4473*2d9fd380Sjfb8856606 static int
parse_sa(struct context * ctx,const struct token * token,const char * str,unsigned int len,void * buf,unsigned int size)4474*2d9fd380Sjfb8856606 parse_sa(struct context *ctx, const struct token *token,
4475*2d9fd380Sjfb8856606 	 const char *str, unsigned int len,
4476*2d9fd380Sjfb8856606 	 void *buf, unsigned int size)
4477*2d9fd380Sjfb8856606 {
4478*2d9fd380Sjfb8856606 	struct buffer *out = buf;
4479*2d9fd380Sjfb8856606 
4480*2d9fd380Sjfb8856606 	/* Token name must match. */
4481*2d9fd380Sjfb8856606 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
4482*2d9fd380Sjfb8856606 		return -1;
4483*2d9fd380Sjfb8856606 	/* Nothing else to do if there is no buffer. */
4484*2d9fd380Sjfb8856606 	if (!out)
4485*2d9fd380Sjfb8856606 		return len;
4486*2d9fd380Sjfb8856606 	if (!out->command) {
4487*2d9fd380Sjfb8856606 		if (ctx->curr != SHARED_ACTION)
4488*2d9fd380Sjfb8856606 			return -1;
4489*2d9fd380Sjfb8856606 		if (sizeof(*out) > size)
4490*2d9fd380Sjfb8856606 			return -1;
4491*2d9fd380Sjfb8856606 		out->command = ctx->curr;
4492*2d9fd380Sjfb8856606 		ctx->objdata = 0;
4493*2d9fd380Sjfb8856606 		ctx->object = out;
4494*2d9fd380Sjfb8856606 		ctx->objmask = NULL;
4495*2d9fd380Sjfb8856606 		out->args.vc.data = (uint8_t *)out + size;
4496*2d9fd380Sjfb8856606 		return len;
4497*2d9fd380Sjfb8856606 	}
4498*2d9fd380Sjfb8856606 	switch (ctx->curr) {
4499*2d9fd380Sjfb8856606 	case SHARED_ACTION_CREATE:
4500*2d9fd380Sjfb8856606 	case SHARED_ACTION_UPDATE:
4501*2d9fd380Sjfb8856606 		out->args.vc.actions =
4502*2d9fd380Sjfb8856606 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
4503*2d9fd380Sjfb8856606 					       sizeof(double));
4504*2d9fd380Sjfb8856606 		out->args.vc.attr.group = UINT32_MAX;
4505*2d9fd380Sjfb8856606 		/* fallthrough */
4506*2d9fd380Sjfb8856606 	case SHARED_ACTION_QUERY:
4507*2d9fd380Sjfb8856606 		out->command = ctx->curr;
4508*2d9fd380Sjfb8856606 		ctx->objdata = 0;
4509*2d9fd380Sjfb8856606 		ctx->object = out;
4510*2d9fd380Sjfb8856606 		ctx->objmask = NULL;
4511*2d9fd380Sjfb8856606 		return len;
4512*2d9fd380Sjfb8856606 	case SHARED_ACTION_EGRESS:
4513*2d9fd380Sjfb8856606 		out->args.vc.attr.egress = 1;
4514*2d9fd380Sjfb8856606 		return len;
4515*2d9fd380Sjfb8856606 	case SHARED_ACTION_INGRESS:
4516*2d9fd380Sjfb8856606 		out->args.vc.attr.ingress = 1;
4517*2d9fd380Sjfb8856606 		return len;
4518*2d9fd380Sjfb8856606 	case SHARED_ACTION_TRANSFER:
4519*2d9fd380Sjfb8856606 		out->args.vc.attr.transfer = 1;
4520*2d9fd380Sjfb8856606 		return len;
4521*2d9fd380Sjfb8856606 	default:
4522*2d9fd380Sjfb8856606 		return -1;
4523*2d9fd380Sjfb8856606 	}
4524*2d9fd380Sjfb8856606 }
4525*2d9fd380Sjfb8856606 
4526*2d9fd380Sjfb8856606 
4527*2d9fd380Sjfb8856606 /** Parse tokens for shared action destroy command. */
4528*2d9fd380Sjfb8856606 static int
parse_sa_destroy(struct context * ctx,const struct token * token,const char * str,unsigned int len,void * buf,unsigned int size)4529*2d9fd380Sjfb8856606 parse_sa_destroy(struct context *ctx, const struct token *token,
4530*2d9fd380Sjfb8856606 		 const char *str, unsigned int len,
4531*2d9fd380Sjfb8856606 		 void *buf, unsigned int size)
4532*2d9fd380Sjfb8856606 {
4533*2d9fd380Sjfb8856606 	struct buffer *out = buf;
4534*2d9fd380Sjfb8856606 	uint32_t *action_id;
4535*2d9fd380Sjfb8856606 
4536*2d9fd380Sjfb8856606 	/* Token name must match. */
4537*2d9fd380Sjfb8856606 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
4538*2d9fd380Sjfb8856606 		return -1;
4539*2d9fd380Sjfb8856606 	/* Nothing else to do if there is no buffer. */
4540*2d9fd380Sjfb8856606 	if (!out)
4541*2d9fd380Sjfb8856606 		return len;
4542*2d9fd380Sjfb8856606 	if (!out->command || out->command == SHARED_ACTION) {
4543*2d9fd380Sjfb8856606 		if (ctx->curr != SHARED_ACTION_DESTROY)
4544*2d9fd380Sjfb8856606 			return -1;
4545*2d9fd380Sjfb8856606 		if (sizeof(*out) > size)
4546*2d9fd380Sjfb8856606 			return -1;
4547*2d9fd380Sjfb8856606 		out->command = ctx->curr;
4548*2d9fd380Sjfb8856606 		ctx->objdata = 0;
4549*2d9fd380Sjfb8856606 		ctx->object = out;
4550*2d9fd380Sjfb8856606 		ctx->objmask = NULL;
4551*2d9fd380Sjfb8856606 		out->args.sa_destroy.action_id =
4552*2d9fd380Sjfb8856606 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
4553*2d9fd380Sjfb8856606 					       sizeof(double));
4554*2d9fd380Sjfb8856606 		return len;
4555*2d9fd380Sjfb8856606 	}
4556*2d9fd380Sjfb8856606 	action_id = out->args.sa_destroy.action_id
4557*2d9fd380Sjfb8856606 		    + out->args.sa_destroy.action_id_n++;
4558*2d9fd380Sjfb8856606 	if ((uint8_t *)action_id > (uint8_t *)out + size)
4559*2d9fd380Sjfb8856606 		return -1;
4560*2d9fd380Sjfb8856606 	ctx->objdata = 0;
4561*2d9fd380Sjfb8856606 	ctx->object = action_id;
4562*2d9fd380Sjfb8856606 	ctx->objmask = NULL;
4563*2d9fd380Sjfb8856606 	return len;
4564*2d9fd380Sjfb8856606 }
4565*2d9fd380Sjfb8856606 
45662bfe3f2eSlogwang /** Parse tokens for validate/create commands. */
45672bfe3f2eSlogwang static int
parse_vc(struct context * ctx,const struct token * token,const char * str,unsigned int len,void * buf,unsigned int size)45682bfe3f2eSlogwang parse_vc(struct context *ctx, const struct token *token,
45692bfe3f2eSlogwang 	 const char *str, unsigned int len,
45702bfe3f2eSlogwang 	 void *buf, unsigned int size)
45712bfe3f2eSlogwang {
45722bfe3f2eSlogwang 	struct buffer *out = buf;
45732bfe3f2eSlogwang 	uint8_t *data;
45742bfe3f2eSlogwang 	uint32_t data_size;
45752bfe3f2eSlogwang 
45762bfe3f2eSlogwang 	/* Token name must match. */
45772bfe3f2eSlogwang 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
45782bfe3f2eSlogwang 		return -1;
45792bfe3f2eSlogwang 	/* Nothing else to do if there is no buffer. */
45802bfe3f2eSlogwang 	if (!out)
45812bfe3f2eSlogwang 		return len;
45822bfe3f2eSlogwang 	if (!out->command) {
45832bfe3f2eSlogwang 		if (ctx->curr != VALIDATE && ctx->curr != CREATE)
45842bfe3f2eSlogwang 			return -1;
45852bfe3f2eSlogwang 		if (sizeof(*out) > size)
45862bfe3f2eSlogwang 			return -1;
45872bfe3f2eSlogwang 		out->command = ctx->curr;
45882bfe3f2eSlogwang 		ctx->objdata = 0;
45892bfe3f2eSlogwang 		ctx->object = out;
45902bfe3f2eSlogwang 		ctx->objmask = NULL;
45912bfe3f2eSlogwang 		out->args.vc.data = (uint8_t *)out + size;
45922bfe3f2eSlogwang 		return len;
45932bfe3f2eSlogwang 	}
45942bfe3f2eSlogwang 	ctx->objdata = 0;
4595*2d9fd380Sjfb8856606 	switch (ctx->curr) {
4596*2d9fd380Sjfb8856606 	default:
45972bfe3f2eSlogwang 		ctx->object = &out->args.vc.attr;
4598*2d9fd380Sjfb8856606 		break;
4599*2d9fd380Sjfb8856606 	case TUNNEL_SET:
4600*2d9fd380Sjfb8856606 	case TUNNEL_MATCH:
4601*2d9fd380Sjfb8856606 		ctx->object = &out->args.vc.tunnel_ops;
4602*2d9fd380Sjfb8856606 		break;
4603*2d9fd380Sjfb8856606 	}
46042bfe3f2eSlogwang 	ctx->objmask = NULL;
46052bfe3f2eSlogwang 	switch (ctx->curr) {
46062bfe3f2eSlogwang 	case GROUP:
46072bfe3f2eSlogwang 	case PRIORITY:
46082bfe3f2eSlogwang 		return len;
4609*2d9fd380Sjfb8856606 	case TUNNEL_SET:
4610*2d9fd380Sjfb8856606 		out->args.vc.tunnel_ops.enabled = 1;
4611*2d9fd380Sjfb8856606 		out->args.vc.tunnel_ops.actions = 1;
4612*2d9fd380Sjfb8856606 		return len;
4613*2d9fd380Sjfb8856606 	case TUNNEL_MATCH:
4614*2d9fd380Sjfb8856606 		out->args.vc.tunnel_ops.enabled = 1;
4615*2d9fd380Sjfb8856606 		out->args.vc.tunnel_ops.items = 1;
4616*2d9fd380Sjfb8856606 		return len;
46172bfe3f2eSlogwang 	case INGRESS:
46182bfe3f2eSlogwang 		out->args.vc.attr.ingress = 1;
46192bfe3f2eSlogwang 		return len;
46202bfe3f2eSlogwang 	case EGRESS:
46212bfe3f2eSlogwang 		out->args.vc.attr.egress = 1;
46222bfe3f2eSlogwang 		return len;
4623d30ea906Sjfb8856606 	case TRANSFER:
4624d30ea906Sjfb8856606 		out->args.vc.attr.transfer = 1;
4625d30ea906Sjfb8856606 		return len;
46262bfe3f2eSlogwang 	case PATTERN:
46272bfe3f2eSlogwang 		out->args.vc.pattern =
46282bfe3f2eSlogwang 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
46292bfe3f2eSlogwang 					       sizeof(double));
46302bfe3f2eSlogwang 		ctx->object = out->args.vc.pattern;
46312bfe3f2eSlogwang 		ctx->objmask = NULL;
46322bfe3f2eSlogwang 		return len;
46332bfe3f2eSlogwang 	case ACTIONS:
46342bfe3f2eSlogwang 		out->args.vc.actions =
46352bfe3f2eSlogwang 			(void *)RTE_ALIGN_CEIL((uintptr_t)
46362bfe3f2eSlogwang 					       (out->args.vc.pattern +
46372bfe3f2eSlogwang 						out->args.vc.pattern_n),
46382bfe3f2eSlogwang 					       sizeof(double));
46392bfe3f2eSlogwang 		ctx->object = out->args.vc.actions;
46402bfe3f2eSlogwang 		ctx->objmask = NULL;
46412bfe3f2eSlogwang 		return len;
46422bfe3f2eSlogwang 	default:
46432bfe3f2eSlogwang 		if (!token->priv)
46442bfe3f2eSlogwang 			return -1;
46452bfe3f2eSlogwang 		break;
46462bfe3f2eSlogwang 	}
46472bfe3f2eSlogwang 	if (!out->args.vc.actions) {
46482bfe3f2eSlogwang 		const struct parse_item_priv *priv = token->priv;
46492bfe3f2eSlogwang 		struct rte_flow_item *item =
46502bfe3f2eSlogwang 			out->args.vc.pattern + out->args.vc.pattern_n;
46512bfe3f2eSlogwang 
46522bfe3f2eSlogwang 		data_size = priv->size * 3; /* spec, last, mask */
46532bfe3f2eSlogwang 		data = (void *)RTE_ALIGN_FLOOR((uintptr_t)
46542bfe3f2eSlogwang 					       (out->args.vc.data - data_size),
46552bfe3f2eSlogwang 					       sizeof(double));
46562bfe3f2eSlogwang 		if ((uint8_t *)item + sizeof(*item) > data)
46572bfe3f2eSlogwang 			return -1;
46582bfe3f2eSlogwang 		*item = (struct rte_flow_item){
46592bfe3f2eSlogwang 			.type = priv->type,
46602bfe3f2eSlogwang 		};
46612bfe3f2eSlogwang 		++out->args.vc.pattern_n;
46622bfe3f2eSlogwang 		ctx->object = item;
46632bfe3f2eSlogwang 		ctx->objmask = NULL;
46642bfe3f2eSlogwang 	} else {
46652bfe3f2eSlogwang 		const struct parse_action_priv *priv = token->priv;
46662bfe3f2eSlogwang 		struct rte_flow_action *action =
46672bfe3f2eSlogwang 			out->args.vc.actions + out->args.vc.actions_n;
46682bfe3f2eSlogwang 
46692bfe3f2eSlogwang 		data_size = priv->size; /* configuration */
46702bfe3f2eSlogwang 		data = (void *)RTE_ALIGN_FLOOR((uintptr_t)
46712bfe3f2eSlogwang 					       (out->args.vc.data - data_size),
46722bfe3f2eSlogwang 					       sizeof(double));
46732bfe3f2eSlogwang 		if ((uint8_t *)action + sizeof(*action) > data)
46742bfe3f2eSlogwang 			return -1;
46752bfe3f2eSlogwang 		*action = (struct rte_flow_action){
46762bfe3f2eSlogwang 			.type = priv->type,
4677d30ea906Sjfb8856606 			.conf = data_size ? data : NULL,
46782bfe3f2eSlogwang 		};
46792bfe3f2eSlogwang 		++out->args.vc.actions_n;
46802bfe3f2eSlogwang 		ctx->object = action;
46812bfe3f2eSlogwang 		ctx->objmask = NULL;
46822bfe3f2eSlogwang 	}
46832bfe3f2eSlogwang 	memset(data, 0, data_size);
46842bfe3f2eSlogwang 	out->args.vc.data = data;
46852bfe3f2eSlogwang 	ctx->objdata = data_size;
46862bfe3f2eSlogwang 	return len;
46872bfe3f2eSlogwang }
46882bfe3f2eSlogwang 
46892bfe3f2eSlogwang /** Parse pattern item parameter type. */
46902bfe3f2eSlogwang static int
parse_vc_spec(struct context * ctx,const struct token * token,const char * str,unsigned int len,void * buf,unsigned int size)46912bfe3f2eSlogwang parse_vc_spec(struct context *ctx, const struct token *token,
46922bfe3f2eSlogwang 	      const char *str, unsigned int len,
46932bfe3f2eSlogwang 	      void *buf, unsigned int size)
46942bfe3f2eSlogwang {
46952bfe3f2eSlogwang 	struct buffer *out = buf;
46962bfe3f2eSlogwang 	struct rte_flow_item *item;
46972bfe3f2eSlogwang 	uint32_t data_size;
46982bfe3f2eSlogwang 	int index;
46992bfe3f2eSlogwang 	int objmask = 0;
47002bfe3f2eSlogwang 
47012bfe3f2eSlogwang 	(void)size;
47022bfe3f2eSlogwang 	/* Token name must match. */
47032bfe3f2eSlogwang 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
47042bfe3f2eSlogwang 		return -1;
47052bfe3f2eSlogwang 	/* Parse parameter types. */
47062bfe3f2eSlogwang 	switch (ctx->curr) {
47072bfe3f2eSlogwang 		static const enum index prefix[] = NEXT_ENTRY(PREFIX);
47082bfe3f2eSlogwang 
47092bfe3f2eSlogwang 	case ITEM_PARAM_IS:
47102bfe3f2eSlogwang 		index = 0;
47112bfe3f2eSlogwang 		objmask = 1;
47122bfe3f2eSlogwang 		break;
47132bfe3f2eSlogwang 	case ITEM_PARAM_SPEC:
47142bfe3f2eSlogwang 		index = 0;
47152bfe3f2eSlogwang 		break;
47162bfe3f2eSlogwang 	case ITEM_PARAM_LAST:
47172bfe3f2eSlogwang 		index = 1;
47182bfe3f2eSlogwang 		break;
47192bfe3f2eSlogwang 	case ITEM_PARAM_PREFIX:
47202bfe3f2eSlogwang 		/* Modify next token to expect a prefix. */
47212bfe3f2eSlogwang 		if (ctx->next_num < 2)
47222bfe3f2eSlogwang 			return -1;
47232bfe3f2eSlogwang 		ctx->next[ctx->next_num - 2] = prefix;
47242bfe3f2eSlogwang 		/* Fall through. */
47252bfe3f2eSlogwang 	case ITEM_PARAM_MASK:
47262bfe3f2eSlogwang 		index = 2;
47272bfe3f2eSlogwang 		break;
47282bfe3f2eSlogwang 	default:
47292bfe3f2eSlogwang 		return -1;
47302bfe3f2eSlogwang 	}
47312bfe3f2eSlogwang 	/* Nothing else to do if there is no buffer. */
47322bfe3f2eSlogwang 	if (!out)
47332bfe3f2eSlogwang 		return len;
47342bfe3f2eSlogwang 	if (!out->args.vc.pattern_n)
47352bfe3f2eSlogwang 		return -1;
47362bfe3f2eSlogwang 	item = &out->args.vc.pattern[out->args.vc.pattern_n - 1];
47372bfe3f2eSlogwang 	data_size = ctx->objdata / 3; /* spec, last, mask */
47382bfe3f2eSlogwang 	/* Point to selected object. */
47392bfe3f2eSlogwang 	ctx->object = out->args.vc.data + (data_size * index);
47402bfe3f2eSlogwang 	if (objmask) {
47412bfe3f2eSlogwang 		ctx->objmask = out->args.vc.data + (data_size * 2); /* mask */
47422bfe3f2eSlogwang 		item->mask = ctx->objmask;
47432bfe3f2eSlogwang 	} else
47442bfe3f2eSlogwang 		ctx->objmask = NULL;
47452bfe3f2eSlogwang 	/* Update relevant item pointer. */
47462bfe3f2eSlogwang 	*((const void **[]){ &item->spec, &item->last, &item->mask })[index] =
47472bfe3f2eSlogwang 		ctx->object;
47482bfe3f2eSlogwang 	return len;
47492bfe3f2eSlogwang }
47502bfe3f2eSlogwang 
47512bfe3f2eSlogwang /** Parse action configuration field. */
47522bfe3f2eSlogwang static int
parse_vc_conf(struct context * ctx,const struct token * token,const char * str,unsigned int len,void * buf,unsigned int size)47532bfe3f2eSlogwang parse_vc_conf(struct context *ctx, const struct token *token,
47542bfe3f2eSlogwang 	      const char *str, unsigned int len,
47552bfe3f2eSlogwang 	      void *buf, unsigned int size)
47562bfe3f2eSlogwang {
47572bfe3f2eSlogwang 	struct buffer *out = buf;
47582bfe3f2eSlogwang 
47592bfe3f2eSlogwang 	(void)size;
47602bfe3f2eSlogwang 	/* Token name must match. */
47612bfe3f2eSlogwang 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
47622bfe3f2eSlogwang 		return -1;
47632bfe3f2eSlogwang 	/* Nothing else to do if there is no buffer. */
47642bfe3f2eSlogwang 	if (!out)
47652bfe3f2eSlogwang 		return len;
4766d30ea906Sjfb8856606 	/* Point to selected object. */
4767d30ea906Sjfb8856606 	ctx->object = out->args.vc.data;
4768d30ea906Sjfb8856606 	ctx->objmask = NULL;
4769d30ea906Sjfb8856606 	return len;
4770d30ea906Sjfb8856606 }
4771d30ea906Sjfb8856606 
4772*2d9fd380Sjfb8856606 /** Parse eCPRI common header type field. */
4773*2d9fd380Sjfb8856606 static int
parse_vc_item_ecpri_type(struct context * ctx,const struct token * token,const char * str,unsigned int len,void * buf,unsigned int size)4774*2d9fd380Sjfb8856606 parse_vc_item_ecpri_type(struct context *ctx, const struct token *token,
4775*2d9fd380Sjfb8856606 			 const char *str, unsigned int len,
4776*2d9fd380Sjfb8856606 			 void *buf, unsigned int size)
4777*2d9fd380Sjfb8856606 {
4778*2d9fd380Sjfb8856606 	struct rte_flow_item_ecpri *ecpri;
4779*2d9fd380Sjfb8856606 	struct rte_flow_item_ecpri *ecpri_mask;
4780*2d9fd380Sjfb8856606 	struct rte_flow_item *item;
4781*2d9fd380Sjfb8856606 	uint32_t data_size;
4782*2d9fd380Sjfb8856606 	uint8_t msg_type;
4783*2d9fd380Sjfb8856606 	struct buffer *out = buf;
4784*2d9fd380Sjfb8856606 	const struct arg *arg;
4785*2d9fd380Sjfb8856606 
4786*2d9fd380Sjfb8856606 	(void)size;
4787*2d9fd380Sjfb8856606 	/* Token name must match. */
4788*2d9fd380Sjfb8856606 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
4789*2d9fd380Sjfb8856606 		return -1;
4790*2d9fd380Sjfb8856606 	switch (ctx->curr) {
4791*2d9fd380Sjfb8856606 	case ITEM_ECPRI_COMMON_TYPE_IQ_DATA:
4792*2d9fd380Sjfb8856606 		msg_type = RTE_ECPRI_MSG_TYPE_IQ_DATA;
4793*2d9fd380Sjfb8856606 		break;
4794*2d9fd380Sjfb8856606 	case ITEM_ECPRI_COMMON_TYPE_RTC_CTRL:
4795*2d9fd380Sjfb8856606 		msg_type = RTE_ECPRI_MSG_TYPE_RTC_CTRL;
4796*2d9fd380Sjfb8856606 		break;
4797*2d9fd380Sjfb8856606 	case ITEM_ECPRI_COMMON_TYPE_DLY_MSR:
4798*2d9fd380Sjfb8856606 		msg_type = RTE_ECPRI_MSG_TYPE_DLY_MSR;
4799*2d9fd380Sjfb8856606 		break;
4800*2d9fd380Sjfb8856606 	default:
4801*2d9fd380Sjfb8856606 		return -1;
4802*2d9fd380Sjfb8856606 	}
4803*2d9fd380Sjfb8856606 	if (!ctx->object)
4804*2d9fd380Sjfb8856606 		return len;
4805*2d9fd380Sjfb8856606 	arg = pop_args(ctx);
4806*2d9fd380Sjfb8856606 	if (!arg)
4807*2d9fd380Sjfb8856606 		return -1;
4808*2d9fd380Sjfb8856606 	ecpri = (struct rte_flow_item_ecpri *)out->args.vc.data;
4809*2d9fd380Sjfb8856606 	ecpri->hdr.common.type = msg_type;
4810*2d9fd380Sjfb8856606 	data_size = ctx->objdata / 3; /* spec, last, mask */
4811*2d9fd380Sjfb8856606 	ecpri_mask = (struct rte_flow_item_ecpri *)(out->args.vc.data +
4812*2d9fd380Sjfb8856606 						    (data_size * 2));
4813*2d9fd380Sjfb8856606 	ecpri_mask->hdr.common.type = 0xFF;
4814*2d9fd380Sjfb8856606 	if (arg->hton) {
4815*2d9fd380Sjfb8856606 		ecpri->hdr.common.u32 = rte_cpu_to_be_32(ecpri->hdr.common.u32);
4816*2d9fd380Sjfb8856606 		ecpri_mask->hdr.common.u32 =
4817*2d9fd380Sjfb8856606 				rte_cpu_to_be_32(ecpri_mask->hdr.common.u32);
4818*2d9fd380Sjfb8856606 	}
4819*2d9fd380Sjfb8856606 	item = &out->args.vc.pattern[out->args.vc.pattern_n - 1];
4820*2d9fd380Sjfb8856606 	item->spec = ecpri;
4821*2d9fd380Sjfb8856606 	item->mask = ecpri_mask;
4822*2d9fd380Sjfb8856606 	return len;
4823*2d9fd380Sjfb8856606 }
4824*2d9fd380Sjfb8856606 
4825d30ea906Sjfb8856606 /** Parse RSS action. */
4826d30ea906Sjfb8856606 static int
parse_vc_action_rss(struct context * ctx,const struct token * token,const char * str,unsigned int len,void * buf,unsigned int size)4827d30ea906Sjfb8856606 parse_vc_action_rss(struct context *ctx, const struct token *token,
4828d30ea906Sjfb8856606 		    const char *str, unsigned int len,
4829d30ea906Sjfb8856606 		    void *buf, unsigned int size)
4830d30ea906Sjfb8856606 {
4831d30ea906Sjfb8856606 	struct buffer *out = buf;
4832d30ea906Sjfb8856606 	struct rte_flow_action *action;
4833d30ea906Sjfb8856606 	struct action_rss_data *action_rss_data;
4834d30ea906Sjfb8856606 	unsigned int i;
4835d30ea906Sjfb8856606 	int ret;
4836d30ea906Sjfb8856606 
4837d30ea906Sjfb8856606 	ret = parse_vc(ctx, token, str, len, buf, size);
4838d30ea906Sjfb8856606 	if (ret < 0)
4839d30ea906Sjfb8856606 		return ret;
4840d30ea906Sjfb8856606 	/* Nothing else to do if there is no buffer. */
4841d30ea906Sjfb8856606 	if (!out)
4842d30ea906Sjfb8856606 		return ret;
48432bfe3f2eSlogwang 	if (!out->args.vc.actions_n)
48442bfe3f2eSlogwang 		return -1;
48452bfe3f2eSlogwang 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
48462bfe3f2eSlogwang 	/* Point to selected object. */
48472bfe3f2eSlogwang 	ctx->object = out->args.vc.data;
48482bfe3f2eSlogwang 	ctx->objmask = NULL;
4849d30ea906Sjfb8856606 	/* Set up default configuration. */
4850d30ea906Sjfb8856606 	action_rss_data = ctx->object;
4851d30ea906Sjfb8856606 	*action_rss_data = (struct action_rss_data){
4852d30ea906Sjfb8856606 		.conf = (struct rte_flow_action_rss){
4853d30ea906Sjfb8856606 			.func = RTE_ETH_HASH_FUNCTION_DEFAULT,
4854d30ea906Sjfb8856606 			.level = 0,
4855d30ea906Sjfb8856606 			.types = rss_hf,
48560c6bd470Sfengbojiang 			.key_len = 0,
4857d30ea906Sjfb8856606 			.queue_num = RTE_MIN(nb_rxq, ACTION_RSS_QUEUE_NUM),
48580c6bd470Sfengbojiang 			.key = NULL,
4859d30ea906Sjfb8856606 			.queue = action_rss_data->queue,
4860d30ea906Sjfb8856606 		},
4861d30ea906Sjfb8856606 		.queue = { 0 },
4862d30ea906Sjfb8856606 	};
4863d30ea906Sjfb8856606 	for (i = 0; i < action_rss_data->conf.queue_num; ++i)
4864d30ea906Sjfb8856606 		action_rss_data->queue[i] = i;
4865d30ea906Sjfb8856606 	action->conf = &action_rss_data->conf;
4866d30ea906Sjfb8856606 	return ret;
4867d30ea906Sjfb8856606 }
4868d30ea906Sjfb8856606 
4869d30ea906Sjfb8856606 /**
4870d30ea906Sjfb8856606  * Parse func field for RSS action.
4871d30ea906Sjfb8856606  *
4872d30ea906Sjfb8856606  * The RTE_ETH_HASH_FUNCTION_* value to assign is derived from the
4873d30ea906Sjfb8856606  * ACTION_RSS_FUNC_* index that called this function.
4874d30ea906Sjfb8856606  */
4875d30ea906Sjfb8856606 static int
parse_vc_action_rss_func(struct context * ctx,const struct token * token,const char * str,unsigned int len,void * buf,unsigned int size)4876d30ea906Sjfb8856606 parse_vc_action_rss_func(struct context *ctx, const struct token *token,
4877d30ea906Sjfb8856606 			 const char *str, unsigned int len,
4878d30ea906Sjfb8856606 			 void *buf, unsigned int size)
4879d30ea906Sjfb8856606 {
4880d30ea906Sjfb8856606 	struct action_rss_data *action_rss_data;
4881d30ea906Sjfb8856606 	enum rte_eth_hash_function func;
4882d30ea906Sjfb8856606 
4883d30ea906Sjfb8856606 	(void)buf;
4884d30ea906Sjfb8856606 	(void)size;
4885d30ea906Sjfb8856606 	/* Token name must match. */
4886d30ea906Sjfb8856606 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
4887d30ea906Sjfb8856606 		return -1;
4888d30ea906Sjfb8856606 	switch (ctx->curr) {
4889d30ea906Sjfb8856606 	case ACTION_RSS_FUNC_DEFAULT:
4890d30ea906Sjfb8856606 		func = RTE_ETH_HASH_FUNCTION_DEFAULT;
4891d30ea906Sjfb8856606 		break;
4892d30ea906Sjfb8856606 	case ACTION_RSS_FUNC_TOEPLITZ:
4893d30ea906Sjfb8856606 		func = RTE_ETH_HASH_FUNCTION_TOEPLITZ;
4894d30ea906Sjfb8856606 		break;
4895d30ea906Sjfb8856606 	case ACTION_RSS_FUNC_SIMPLE_XOR:
4896d30ea906Sjfb8856606 		func = RTE_ETH_HASH_FUNCTION_SIMPLE_XOR;
4897d30ea906Sjfb8856606 		break;
48984418919fSjohnjiang 	case ACTION_RSS_FUNC_SYMMETRIC_TOEPLITZ:
48994418919fSjohnjiang 		func = RTE_ETH_HASH_FUNCTION_SYMMETRIC_TOEPLITZ;
49004418919fSjohnjiang 		break;
4901d30ea906Sjfb8856606 	default:
4902d30ea906Sjfb8856606 		return -1;
4903d30ea906Sjfb8856606 	}
4904d30ea906Sjfb8856606 	if (!ctx->object)
4905d30ea906Sjfb8856606 		return len;
4906d30ea906Sjfb8856606 	action_rss_data = ctx->object;
4907d30ea906Sjfb8856606 	action_rss_data->conf.func = func;
4908d30ea906Sjfb8856606 	return len;
4909d30ea906Sjfb8856606 }
4910d30ea906Sjfb8856606 
4911d30ea906Sjfb8856606 /**
4912d30ea906Sjfb8856606  * Parse type field for RSS action.
4913d30ea906Sjfb8856606  *
4914d30ea906Sjfb8856606  * Valid tokens are type field names and the "end" token.
4915d30ea906Sjfb8856606  */
4916d30ea906Sjfb8856606 static int
parse_vc_action_rss_type(struct context * ctx,const struct token * token,const char * str,unsigned int len,void * buf,unsigned int size)4917d30ea906Sjfb8856606 parse_vc_action_rss_type(struct context *ctx, const struct token *token,
4918d30ea906Sjfb8856606 			  const char *str, unsigned int len,
4919d30ea906Sjfb8856606 			  void *buf, unsigned int size)
4920d30ea906Sjfb8856606 {
4921d30ea906Sjfb8856606 	static const enum index next[] = NEXT_ENTRY(ACTION_RSS_TYPE);
4922d30ea906Sjfb8856606 	struct action_rss_data *action_rss_data;
4923d30ea906Sjfb8856606 	unsigned int i;
4924d30ea906Sjfb8856606 
4925d30ea906Sjfb8856606 	(void)token;
4926d30ea906Sjfb8856606 	(void)buf;
4927d30ea906Sjfb8856606 	(void)size;
4928d30ea906Sjfb8856606 	if (ctx->curr != ACTION_RSS_TYPE)
4929d30ea906Sjfb8856606 		return -1;
4930d30ea906Sjfb8856606 	if (!(ctx->objdata >> 16) && ctx->object) {
4931d30ea906Sjfb8856606 		action_rss_data = ctx->object;
4932d30ea906Sjfb8856606 		action_rss_data->conf.types = 0;
4933d30ea906Sjfb8856606 	}
4934d30ea906Sjfb8856606 	if (!strcmp_partial("end", str, len)) {
4935d30ea906Sjfb8856606 		ctx->objdata &= 0xffff;
4936d30ea906Sjfb8856606 		return len;
4937d30ea906Sjfb8856606 	}
4938d30ea906Sjfb8856606 	for (i = 0; rss_type_table[i].str; ++i)
4939d30ea906Sjfb8856606 		if (!strcmp_partial(rss_type_table[i].str, str, len))
4940d30ea906Sjfb8856606 			break;
4941d30ea906Sjfb8856606 	if (!rss_type_table[i].str)
4942d30ea906Sjfb8856606 		return -1;
4943d30ea906Sjfb8856606 	ctx->objdata = 1 << 16 | (ctx->objdata & 0xffff);
4944d30ea906Sjfb8856606 	/* Repeat token. */
4945d30ea906Sjfb8856606 	if (ctx->next_num == RTE_DIM(ctx->next))
4946d30ea906Sjfb8856606 		return -1;
4947d30ea906Sjfb8856606 	ctx->next[ctx->next_num++] = next;
4948d30ea906Sjfb8856606 	if (!ctx->object)
4949d30ea906Sjfb8856606 		return len;
4950d30ea906Sjfb8856606 	action_rss_data = ctx->object;
4951d30ea906Sjfb8856606 	action_rss_data->conf.types |= rss_type_table[i].rss_type;
49522bfe3f2eSlogwang 	return len;
49532bfe3f2eSlogwang }
49542bfe3f2eSlogwang 
49552bfe3f2eSlogwang /**
49562bfe3f2eSlogwang  * Parse queue field for RSS action.
49572bfe3f2eSlogwang  *
49582bfe3f2eSlogwang  * Valid tokens are queue indices and the "end" token.
49592bfe3f2eSlogwang  */
49602bfe3f2eSlogwang static int
parse_vc_action_rss_queue(struct context * ctx,const struct token * token,const char * str,unsigned int len,void * buf,unsigned int size)49612bfe3f2eSlogwang parse_vc_action_rss_queue(struct context *ctx, const struct token *token,
49622bfe3f2eSlogwang 			  const char *str, unsigned int len,
49632bfe3f2eSlogwang 			  void *buf, unsigned int size)
49642bfe3f2eSlogwang {
49652bfe3f2eSlogwang 	static const enum index next[] = NEXT_ENTRY(ACTION_RSS_QUEUE);
4966d30ea906Sjfb8856606 	struct action_rss_data *action_rss_data;
49674b05018fSfengbojiang 	const struct arg *arg;
49682bfe3f2eSlogwang 	int ret;
49692bfe3f2eSlogwang 	int i;
49702bfe3f2eSlogwang 
49712bfe3f2eSlogwang 	(void)token;
49722bfe3f2eSlogwang 	(void)buf;
49732bfe3f2eSlogwang 	(void)size;
49742bfe3f2eSlogwang 	if (ctx->curr != ACTION_RSS_QUEUE)
49752bfe3f2eSlogwang 		return -1;
49762bfe3f2eSlogwang 	i = ctx->objdata >> 16;
49772bfe3f2eSlogwang 	if (!strcmp_partial("end", str, len)) {
49782bfe3f2eSlogwang 		ctx->objdata &= 0xffff;
4979579bf1e2Sjfb8856606 		goto end;
49802bfe3f2eSlogwang 	}
4981d30ea906Sjfb8856606 	if (i >= ACTION_RSS_QUEUE_NUM)
49822bfe3f2eSlogwang 		return -1;
49834b05018fSfengbojiang 	arg = ARGS_ENTRY_ARB(offsetof(struct action_rss_data, queue) +
4984d30ea906Sjfb8856606 			     i * sizeof(action_rss_data->queue[i]),
49854b05018fSfengbojiang 			     sizeof(action_rss_data->queue[i]));
49864b05018fSfengbojiang 	if (push_args(ctx, arg))
49872bfe3f2eSlogwang 		return -1;
49882bfe3f2eSlogwang 	ret = parse_int(ctx, token, str, len, NULL, 0);
49892bfe3f2eSlogwang 	if (ret < 0) {
49902bfe3f2eSlogwang 		pop_args(ctx);
49912bfe3f2eSlogwang 		return -1;
49922bfe3f2eSlogwang 	}
49932bfe3f2eSlogwang 	++i;
49942bfe3f2eSlogwang 	ctx->objdata = i << 16 | (ctx->objdata & 0xffff);
49952bfe3f2eSlogwang 	/* Repeat token. */
49962bfe3f2eSlogwang 	if (ctx->next_num == RTE_DIM(ctx->next))
49972bfe3f2eSlogwang 		return -1;
49982bfe3f2eSlogwang 	ctx->next[ctx->next_num++] = next;
4999579bf1e2Sjfb8856606 end:
50002bfe3f2eSlogwang 	if (!ctx->object)
50012bfe3f2eSlogwang 		return len;
5002d30ea906Sjfb8856606 	action_rss_data = ctx->object;
5003d30ea906Sjfb8856606 	action_rss_data->conf.queue_num = i;
5004d30ea906Sjfb8856606 	action_rss_data->conf.queue = i ? action_rss_data->queue : NULL;
50052bfe3f2eSlogwang 	return len;
50062bfe3f2eSlogwang }
50072bfe3f2eSlogwang 
5008d30ea906Sjfb8856606 /** Parse VXLAN encap action. */
5009d30ea906Sjfb8856606 static int
parse_vc_action_vxlan_encap(struct context * ctx,const struct token * token,const char * str,unsigned int len,void * buf,unsigned int size)5010d30ea906Sjfb8856606 parse_vc_action_vxlan_encap(struct context *ctx, const struct token *token,
5011d30ea906Sjfb8856606 			    const char *str, unsigned int len,
5012d30ea906Sjfb8856606 			    void *buf, unsigned int size)
5013d30ea906Sjfb8856606 {
5014d30ea906Sjfb8856606 	struct buffer *out = buf;
5015d30ea906Sjfb8856606 	struct rte_flow_action *action;
5016d30ea906Sjfb8856606 	struct action_vxlan_encap_data *action_vxlan_encap_data;
5017d30ea906Sjfb8856606 	int ret;
5018d30ea906Sjfb8856606 
5019d30ea906Sjfb8856606 	ret = parse_vc(ctx, token, str, len, buf, size);
5020d30ea906Sjfb8856606 	if (ret < 0)
5021d30ea906Sjfb8856606 		return ret;
5022d30ea906Sjfb8856606 	/* Nothing else to do if there is no buffer. */
5023d30ea906Sjfb8856606 	if (!out)
5024d30ea906Sjfb8856606 		return ret;
5025d30ea906Sjfb8856606 	if (!out->args.vc.actions_n)
5026d30ea906Sjfb8856606 		return -1;
5027d30ea906Sjfb8856606 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
5028d30ea906Sjfb8856606 	/* Point to selected object. */
5029d30ea906Sjfb8856606 	ctx->object = out->args.vc.data;
5030d30ea906Sjfb8856606 	ctx->objmask = NULL;
5031d30ea906Sjfb8856606 	/* Set up default configuration. */
5032d30ea906Sjfb8856606 	action_vxlan_encap_data = ctx->object;
5033d30ea906Sjfb8856606 	*action_vxlan_encap_data = (struct action_vxlan_encap_data){
5034d30ea906Sjfb8856606 		.conf = (struct rte_flow_action_vxlan_encap){
5035d30ea906Sjfb8856606 			.definition = action_vxlan_encap_data->items,
5036d30ea906Sjfb8856606 		},
5037d30ea906Sjfb8856606 		.items = {
5038d30ea906Sjfb8856606 			{
5039d30ea906Sjfb8856606 				.type = RTE_FLOW_ITEM_TYPE_ETH,
5040d30ea906Sjfb8856606 				.spec = &action_vxlan_encap_data->item_eth,
5041d30ea906Sjfb8856606 				.mask = &rte_flow_item_eth_mask,
5042d30ea906Sjfb8856606 			},
5043d30ea906Sjfb8856606 			{
5044d30ea906Sjfb8856606 				.type = RTE_FLOW_ITEM_TYPE_VLAN,
5045d30ea906Sjfb8856606 				.spec = &action_vxlan_encap_data->item_vlan,
5046d30ea906Sjfb8856606 				.mask = &rte_flow_item_vlan_mask,
5047d30ea906Sjfb8856606 			},
5048d30ea906Sjfb8856606 			{
5049d30ea906Sjfb8856606 				.type = RTE_FLOW_ITEM_TYPE_IPV4,
5050d30ea906Sjfb8856606 				.spec = &action_vxlan_encap_data->item_ipv4,
5051d30ea906Sjfb8856606 				.mask = &rte_flow_item_ipv4_mask,
5052d30ea906Sjfb8856606 			},
5053d30ea906Sjfb8856606 			{
5054d30ea906Sjfb8856606 				.type = RTE_FLOW_ITEM_TYPE_UDP,
5055d30ea906Sjfb8856606 				.spec = &action_vxlan_encap_data->item_udp,
5056d30ea906Sjfb8856606 				.mask = &rte_flow_item_udp_mask,
5057d30ea906Sjfb8856606 			},
5058d30ea906Sjfb8856606 			{
5059d30ea906Sjfb8856606 				.type = RTE_FLOW_ITEM_TYPE_VXLAN,
5060d30ea906Sjfb8856606 				.spec = &action_vxlan_encap_data->item_vxlan,
5061d30ea906Sjfb8856606 				.mask = &rte_flow_item_vxlan_mask,
5062d30ea906Sjfb8856606 			},
5063d30ea906Sjfb8856606 			{
5064d30ea906Sjfb8856606 				.type = RTE_FLOW_ITEM_TYPE_END,
5065d30ea906Sjfb8856606 			},
5066d30ea906Sjfb8856606 		},
5067d30ea906Sjfb8856606 		.item_eth.type = 0,
5068d30ea906Sjfb8856606 		.item_vlan = {
5069d30ea906Sjfb8856606 			.tci = vxlan_encap_conf.vlan_tci,
5070d30ea906Sjfb8856606 			.inner_type = 0,
5071d30ea906Sjfb8856606 		},
5072d30ea906Sjfb8856606 		.item_ipv4.hdr = {
5073d30ea906Sjfb8856606 			.src_addr = vxlan_encap_conf.ipv4_src,
5074d30ea906Sjfb8856606 			.dst_addr = vxlan_encap_conf.ipv4_dst,
5075d30ea906Sjfb8856606 		},
5076d30ea906Sjfb8856606 		.item_udp.hdr = {
5077d30ea906Sjfb8856606 			.src_port = vxlan_encap_conf.udp_src,
5078d30ea906Sjfb8856606 			.dst_port = vxlan_encap_conf.udp_dst,
5079d30ea906Sjfb8856606 		},
5080d30ea906Sjfb8856606 		.item_vxlan.flags = 0,
5081d30ea906Sjfb8856606 	};
5082d30ea906Sjfb8856606 	memcpy(action_vxlan_encap_data->item_eth.dst.addr_bytes,
50834418919fSjohnjiang 	       vxlan_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
5084d30ea906Sjfb8856606 	memcpy(action_vxlan_encap_data->item_eth.src.addr_bytes,
50854418919fSjohnjiang 	       vxlan_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
5086d30ea906Sjfb8856606 	if (!vxlan_encap_conf.select_ipv4) {
5087d30ea906Sjfb8856606 		memcpy(&action_vxlan_encap_data->item_ipv6.hdr.src_addr,
5088d30ea906Sjfb8856606 		       &vxlan_encap_conf.ipv6_src,
5089d30ea906Sjfb8856606 		       sizeof(vxlan_encap_conf.ipv6_src));
5090d30ea906Sjfb8856606 		memcpy(&action_vxlan_encap_data->item_ipv6.hdr.dst_addr,
5091d30ea906Sjfb8856606 		       &vxlan_encap_conf.ipv6_dst,
5092d30ea906Sjfb8856606 		       sizeof(vxlan_encap_conf.ipv6_dst));
5093d30ea906Sjfb8856606 		action_vxlan_encap_data->items[2] = (struct rte_flow_item){
5094d30ea906Sjfb8856606 			.type = RTE_FLOW_ITEM_TYPE_IPV6,
5095d30ea906Sjfb8856606 			.spec = &action_vxlan_encap_data->item_ipv6,
5096d30ea906Sjfb8856606 			.mask = &rte_flow_item_ipv6_mask,
5097d30ea906Sjfb8856606 		};
5098d30ea906Sjfb8856606 	}
5099d30ea906Sjfb8856606 	if (!vxlan_encap_conf.select_vlan)
5100d30ea906Sjfb8856606 		action_vxlan_encap_data->items[1].type =
5101d30ea906Sjfb8856606 			RTE_FLOW_ITEM_TYPE_VOID;
51024418919fSjohnjiang 	if (vxlan_encap_conf.select_tos_ttl) {
51034418919fSjohnjiang 		if (vxlan_encap_conf.select_ipv4) {
51044418919fSjohnjiang 			static struct rte_flow_item_ipv4 ipv4_mask_tos;
51054418919fSjohnjiang 
51064418919fSjohnjiang 			memcpy(&ipv4_mask_tos, &rte_flow_item_ipv4_mask,
51074418919fSjohnjiang 			       sizeof(ipv4_mask_tos));
51084418919fSjohnjiang 			ipv4_mask_tos.hdr.type_of_service = 0xff;
51094418919fSjohnjiang 			ipv4_mask_tos.hdr.time_to_live = 0xff;
51104418919fSjohnjiang 			action_vxlan_encap_data->item_ipv4.hdr.type_of_service =
51114418919fSjohnjiang 					vxlan_encap_conf.ip_tos;
51124418919fSjohnjiang 			action_vxlan_encap_data->item_ipv4.hdr.time_to_live =
51134418919fSjohnjiang 					vxlan_encap_conf.ip_ttl;
51144418919fSjohnjiang 			action_vxlan_encap_data->items[2].mask =
51154418919fSjohnjiang 							&ipv4_mask_tos;
51164418919fSjohnjiang 		} else {
51174418919fSjohnjiang 			static struct rte_flow_item_ipv6 ipv6_mask_tos;
51184418919fSjohnjiang 
51194418919fSjohnjiang 			memcpy(&ipv6_mask_tos, &rte_flow_item_ipv6_mask,
51204418919fSjohnjiang 			       sizeof(ipv6_mask_tos));
51214418919fSjohnjiang 			ipv6_mask_tos.hdr.vtc_flow |=
51224418919fSjohnjiang 				RTE_BE32(0xfful << RTE_IPV6_HDR_TC_SHIFT);
51234418919fSjohnjiang 			ipv6_mask_tos.hdr.hop_limits = 0xff;
51244418919fSjohnjiang 			action_vxlan_encap_data->item_ipv6.hdr.vtc_flow |=
51254418919fSjohnjiang 				rte_cpu_to_be_32
51264418919fSjohnjiang 					((uint32_t)vxlan_encap_conf.ip_tos <<
51274418919fSjohnjiang 					 RTE_IPV6_HDR_TC_SHIFT);
51284418919fSjohnjiang 			action_vxlan_encap_data->item_ipv6.hdr.hop_limits =
51294418919fSjohnjiang 					vxlan_encap_conf.ip_ttl;
51304418919fSjohnjiang 			action_vxlan_encap_data->items[2].mask =
51314418919fSjohnjiang 							&ipv6_mask_tos;
51324418919fSjohnjiang 		}
51334418919fSjohnjiang 	}
5134d30ea906Sjfb8856606 	memcpy(action_vxlan_encap_data->item_vxlan.vni, vxlan_encap_conf.vni,
5135d30ea906Sjfb8856606 	       RTE_DIM(vxlan_encap_conf.vni));
5136d30ea906Sjfb8856606 	action->conf = &action_vxlan_encap_data->conf;
5137d30ea906Sjfb8856606 	return ret;
5138d30ea906Sjfb8856606 }
5139d30ea906Sjfb8856606 
5140d30ea906Sjfb8856606 /** Parse NVGRE encap action. */
5141d30ea906Sjfb8856606 static int
parse_vc_action_nvgre_encap(struct context * ctx,const struct token * token,const char * str,unsigned int len,void * buf,unsigned int size)5142d30ea906Sjfb8856606 parse_vc_action_nvgre_encap(struct context *ctx, const struct token *token,
5143d30ea906Sjfb8856606 			    const char *str, unsigned int len,
5144d30ea906Sjfb8856606 			    void *buf, unsigned int size)
5145d30ea906Sjfb8856606 {
5146d30ea906Sjfb8856606 	struct buffer *out = buf;
5147d30ea906Sjfb8856606 	struct rte_flow_action *action;
5148d30ea906Sjfb8856606 	struct action_nvgre_encap_data *action_nvgre_encap_data;
5149d30ea906Sjfb8856606 	int ret;
5150d30ea906Sjfb8856606 
5151d30ea906Sjfb8856606 	ret = parse_vc(ctx, token, str, len, buf, size);
5152d30ea906Sjfb8856606 	if (ret < 0)
5153d30ea906Sjfb8856606 		return ret;
5154d30ea906Sjfb8856606 	/* Nothing else to do if there is no buffer. */
5155d30ea906Sjfb8856606 	if (!out)
5156d30ea906Sjfb8856606 		return ret;
5157d30ea906Sjfb8856606 	if (!out->args.vc.actions_n)
5158d30ea906Sjfb8856606 		return -1;
5159d30ea906Sjfb8856606 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
5160d30ea906Sjfb8856606 	/* Point to selected object. */
5161d30ea906Sjfb8856606 	ctx->object = out->args.vc.data;
5162d30ea906Sjfb8856606 	ctx->objmask = NULL;
5163d30ea906Sjfb8856606 	/* Set up default configuration. */
5164d30ea906Sjfb8856606 	action_nvgre_encap_data = ctx->object;
5165d30ea906Sjfb8856606 	*action_nvgre_encap_data = (struct action_nvgre_encap_data){
5166d30ea906Sjfb8856606 		.conf = (struct rte_flow_action_nvgre_encap){
5167d30ea906Sjfb8856606 			.definition = action_nvgre_encap_data->items,
5168d30ea906Sjfb8856606 		},
5169d30ea906Sjfb8856606 		.items = {
5170d30ea906Sjfb8856606 			{
5171d30ea906Sjfb8856606 				.type = RTE_FLOW_ITEM_TYPE_ETH,
5172d30ea906Sjfb8856606 				.spec = &action_nvgre_encap_data->item_eth,
5173d30ea906Sjfb8856606 				.mask = &rte_flow_item_eth_mask,
5174d30ea906Sjfb8856606 			},
5175d30ea906Sjfb8856606 			{
5176d30ea906Sjfb8856606 				.type = RTE_FLOW_ITEM_TYPE_VLAN,
5177d30ea906Sjfb8856606 				.spec = &action_nvgre_encap_data->item_vlan,
5178d30ea906Sjfb8856606 				.mask = &rte_flow_item_vlan_mask,
5179d30ea906Sjfb8856606 			},
5180d30ea906Sjfb8856606 			{
5181d30ea906Sjfb8856606 				.type = RTE_FLOW_ITEM_TYPE_IPV4,
5182d30ea906Sjfb8856606 				.spec = &action_nvgre_encap_data->item_ipv4,
5183d30ea906Sjfb8856606 				.mask = &rte_flow_item_ipv4_mask,
5184d30ea906Sjfb8856606 			},
5185d30ea906Sjfb8856606 			{
5186d30ea906Sjfb8856606 				.type = RTE_FLOW_ITEM_TYPE_NVGRE,
5187d30ea906Sjfb8856606 				.spec = &action_nvgre_encap_data->item_nvgre,
5188d30ea906Sjfb8856606 				.mask = &rte_flow_item_nvgre_mask,
5189d30ea906Sjfb8856606 			},
5190d30ea906Sjfb8856606 			{
5191d30ea906Sjfb8856606 				.type = RTE_FLOW_ITEM_TYPE_END,
5192d30ea906Sjfb8856606 			},
5193d30ea906Sjfb8856606 		},
5194d30ea906Sjfb8856606 		.item_eth.type = 0,
5195d30ea906Sjfb8856606 		.item_vlan = {
5196d30ea906Sjfb8856606 			.tci = nvgre_encap_conf.vlan_tci,
5197d30ea906Sjfb8856606 			.inner_type = 0,
5198d30ea906Sjfb8856606 		},
5199d30ea906Sjfb8856606 		.item_ipv4.hdr = {
5200d30ea906Sjfb8856606 		       .src_addr = nvgre_encap_conf.ipv4_src,
5201d30ea906Sjfb8856606 		       .dst_addr = nvgre_encap_conf.ipv4_dst,
5202d30ea906Sjfb8856606 		},
5203d30ea906Sjfb8856606 		.item_nvgre.flow_id = 0,
5204d30ea906Sjfb8856606 	};
5205d30ea906Sjfb8856606 	memcpy(action_nvgre_encap_data->item_eth.dst.addr_bytes,
52064418919fSjohnjiang 	       nvgre_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
5207d30ea906Sjfb8856606 	memcpy(action_nvgre_encap_data->item_eth.src.addr_bytes,
52084418919fSjohnjiang 	       nvgre_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
5209d30ea906Sjfb8856606 	if (!nvgre_encap_conf.select_ipv4) {
5210d30ea906Sjfb8856606 		memcpy(&action_nvgre_encap_data->item_ipv6.hdr.src_addr,
5211d30ea906Sjfb8856606 		       &nvgre_encap_conf.ipv6_src,
5212d30ea906Sjfb8856606 		       sizeof(nvgre_encap_conf.ipv6_src));
5213d30ea906Sjfb8856606 		memcpy(&action_nvgre_encap_data->item_ipv6.hdr.dst_addr,
5214d30ea906Sjfb8856606 		       &nvgre_encap_conf.ipv6_dst,
5215d30ea906Sjfb8856606 		       sizeof(nvgre_encap_conf.ipv6_dst));
5216d30ea906Sjfb8856606 		action_nvgre_encap_data->items[2] = (struct rte_flow_item){
5217d30ea906Sjfb8856606 			.type = RTE_FLOW_ITEM_TYPE_IPV6,
5218d30ea906Sjfb8856606 			.spec = &action_nvgre_encap_data->item_ipv6,
5219d30ea906Sjfb8856606 			.mask = &rte_flow_item_ipv6_mask,
5220d30ea906Sjfb8856606 		};
5221d30ea906Sjfb8856606 	}
5222d30ea906Sjfb8856606 	if (!nvgre_encap_conf.select_vlan)
5223d30ea906Sjfb8856606 		action_nvgre_encap_data->items[1].type =
5224d30ea906Sjfb8856606 			RTE_FLOW_ITEM_TYPE_VOID;
5225d30ea906Sjfb8856606 	memcpy(action_nvgre_encap_data->item_nvgre.tni, nvgre_encap_conf.tni,
5226d30ea906Sjfb8856606 	       RTE_DIM(nvgre_encap_conf.tni));
5227d30ea906Sjfb8856606 	action->conf = &action_nvgre_encap_data->conf;
5228d30ea906Sjfb8856606 	return ret;
5229d30ea906Sjfb8856606 }
5230d30ea906Sjfb8856606 
5231d30ea906Sjfb8856606 /** Parse l2 encap action. */
5232d30ea906Sjfb8856606 static int
parse_vc_action_l2_encap(struct context * ctx,const struct token * token,const char * str,unsigned int len,void * buf,unsigned int size)5233d30ea906Sjfb8856606 parse_vc_action_l2_encap(struct context *ctx, const struct token *token,
5234d30ea906Sjfb8856606 			 const char *str, unsigned int len,
5235d30ea906Sjfb8856606 			 void *buf, unsigned int size)
5236d30ea906Sjfb8856606 {
5237d30ea906Sjfb8856606 	struct buffer *out = buf;
5238d30ea906Sjfb8856606 	struct rte_flow_action *action;
5239d30ea906Sjfb8856606 	struct action_raw_encap_data *action_encap_data;
5240d30ea906Sjfb8856606 	struct rte_flow_item_eth eth = { .type = 0, };
5241d30ea906Sjfb8856606 	struct rte_flow_item_vlan vlan = {
5242d30ea906Sjfb8856606 		.tci = mplsoudp_encap_conf.vlan_tci,
5243d30ea906Sjfb8856606 		.inner_type = 0,
5244d30ea906Sjfb8856606 	};
5245d30ea906Sjfb8856606 	uint8_t *header;
5246d30ea906Sjfb8856606 	int ret;
5247d30ea906Sjfb8856606 
5248d30ea906Sjfb8856606 	ret = parse_vc(ctx, token, str, len, buf, size);
5249d30ea906Sjfb8856606 	if (ret < 0)
5250d30ea906Sjfb8856606 		return ret;
5251d30ea906Sjfb8856606 	/* Nothing else to do if there is no buffer. */
5252d30ea906Sjfb8856606 	if (!out)
5253d30ea906Sjfb8856606 		return ret;
5254d30ea906Sjfb8856606 	if (!out->args.vc.actions_n)
5255d30ea906Sjfb8856606 		return -1;
5256d30ea906Sjfb8856606 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
5257d30ea906Sjfb8856606 	/* Point to selected object. */
5258d30ea906Sjfb8856606 	ctx->object = out->args.vc.data;
5259d30ea906Sjfb8856606 	ctx->objmask = NULL;
5260d30ea906Sjfb8856606 	/* Copy the headers to the buffer. */
5261d30ea906Sjfb8856606 	action_encap_data = ctx->object;
5262d30ea906Sjfb8856606 	*action_encap_data = (struct action_raw_encap_data) {
5263d30ea906Sjfb8856606 		.conf = (struct rte_flow_action_raw_encap){
5264d30ea906Sjfb8856606 			.data = action_encap_data->data,
5265d30ea906Sjfb8856606 		},
5266d30ea906Sjfb8856606 		.data = {},
5267d30ea906Sjfb8856606 	};
5268d30ea906Sjfb8856606 	header = action_encap_data->data;
5269d30ea906Sjfb8856606 	if (l2_encap_conf.select_vlan)
52704418919fSjohnjiang 		eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
5271d30ea906Sjfb8856606 	else if (l2_encap_conf.select_ipv4)
52724418919fSjohnjiang 		eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
5273d30ea906Sjfb8856606 	else
52744418919fSjohnjiang 		eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
5275d30ea906Sjfb8856606 	memcpy(eth.dst.addr_bytes,
52764418919fSjohnjiang 	       l2_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
5277d30ea906Sjfb8856606 	memcpy(eth.src.addr_bytes,
52784418919fSjohnjiang 	       l2_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
5279d30ea906Sjfb8856606 	memcpy(header, &eth, sizeof(eth));
5280d30ea906Sjfb8856606 	header += sizeof(eth);
5281d30ea906Sjfb8856606 	if (l2_encap_conf.select_vlan) {
5282d30ea906Sjfb8856606 		if (l2_encap_conf.select_ipv4)
52834418919fSjohnjiang 			vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
5284d30ea906Sjfb8856606 		else
52854418919fSjohnjiang 			vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
5286d30ea906Sjfb8856606 		memcpy(header, &vlan, sizeof(vlan));
5287d30ea906Sjfb8856606 		header += sizeof(vlan);
5288d30ea906Sjfb8856606 	}
5289d30ea906Sjfb8856606 	action_encap_data->conf.size = header -
5290d30ea906Sjfb8856606 		action_encap_data->data;
5291d30ea906Sjfb8856606 	action->conf = &action_encap_data->conf;
5292d30ea906Sjfb8856606 	return ret;
5293d30ea906Sjfb8856606 }
5294d30ea906Sjfb8856606 
5295d30ea906Sjfb8856606 /** Parse l2 decap action. */
5296d30ea906Sjfb8856606 static int
parse_vc_action_l2_decap(struct context * ctx,const struct token * token,const char * str,unsigned int len,void * buf,unsigned int size)5297d30ea906Sjfb8856606 parse_vc_action_l2_decap(struct context *ctx, const struct token *token,
5298d30ea906Sjfb8856606 			 const char *str, unsigned int len,
5299d30ea906Sjfb8856606 			 void *buf, unsigned int size)
5300d30ea906Sjfb8856606 {
5301d30ea906Sjfb8856606 	struct buffer *out = buf;
5302d30ea906Sjfb8856606 	struct rte_flow_action *action;
5303d30ea906Sjfb8856606 	struct action_raw_decap_data *action_decap_data;
5304d30ea906Sjfb8856606 	struct rte_flow_item_eth eth = { .type = 0, };
5305d30ea906Sjfb8856606 	struct rte_flow_item_vlan vlan = {
5306d30ea906Sjfb8856606 		.tci = mplsoudp_encap_conf.vlan_tci,
5307d30ea906Sjfb8856606 		.inner_type = 0,
5308d30ea906Sjfb8856606 	};
5309d30ea906Sjfb8856606 	uint8_t *header;
5310d30ea906Sjfb8856606 	int ret;
5311d30ea906Sjfb8856606 
5312d30ea906Sjfb8856606 	ret = parse_vc(ctx, token, str, len, buf, size);
5313d30ea906Sjfb8856606 	if (ret < 0)
5314d30ea906Sjfb8856606 		return ret;
5315d30ea906Sjfb8856606 	/* Nothing else to do if there is no buffer. */
5316d30ea906Sjfb8856606 	if (!out)
5317d30ea906Sjfb8856606 		return ret;
5318d30ea906Sjfb8856606 	if (!out->args.vc.actions_n)
5319d30ea906Sjfb8856606 		return -1;
5320d30ea906Sjfb8856606 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
5321d30ea906Sjfb8856606 	/* Point to selected object. */
5322d30ea906Sjfb8856606 	ctx->object = out->args.vc.data;
5323d30ea906Sjfb8856606 	ctx->objmask = NULL;
5324d30ea906Sjfb8856606 	/* Copy the headers to the buffer. */
5325d30ea906Sjfb8856606 	action_decap_data = ctx->object;
5326d30ea906Sjfb8856606 	*action_decap_data = (struct action_raw_decap_data) {
5327d30ea906Sjfb8856606 		.conf = (struct rte_flow_action_raw_decap){
5328d30ea906Sjfb8856606 			.data = action_decap_data->data,
5329d30ea906Sjfb8856606 		},
5330d30ea906Sjfb8856606 		.data = {},
5331d30ea906Sjfb8856606 	};
5332d30ea906Sjfb8856606 	header = action_decap_data->data;
5333d30ea906Sjfb8856606 	if (l2_decap_conf.select_vlan)
53344418919fSjohnjiang 		eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
5335d30ea906Sjfb8856606 	memcpy(header, &eth, sizeof(eth));
5336d30ea906Sjfb8856606 	header += sizeof(eth);
5337d30ea906Sjfb8856606 	if (l2_decap_conf.select_vlan) {
5338d30ea906Sjfb8856606 		memcpy(header, &vlan, sizeof(vlan));
5339d30ea906Sjfb8856606 		header += sizeof(vlan);
5340d30ea906Sjfb8856606 	}
5341d30ea906Sjfb8856606 	action_decap_data->conf.size = header -
5342d30ea906Sjfb8856606 		action_decap_data->data;
5343d30ea906Sjfb8856606 	action->conf = &action_decap_data->conf;
5344d30ea906Sjfb8856606 	return ret;
5345d30ea906Sjfb8856606 }
5346d30ea906Sjfb8856606 
5347d30ea906Sjfb8856606 #define ETHER_TYPE_MPLS_UNICAST 0x8847
5348d30ea906Sjfb8856606 
5349d30ea906Sjfb8856606 /** Parse MPLSOGRE encap action. */
5350d30ea906Sjfb8856606 static int
parse_vc_action_mplsogre_encap(struct context * ctx,const struct token * token,const char * str,unsigned int len,void * buf,unsigned int size)5351d30ea906Sjfb8856606 parse_vc_action_mplsogre_encap(struct context *ctx, const struct token *token,
5352d30ea906Sjfb8856606 			       const char *str, unsigned int len,
5353d30ea906Sjfb8856606 			       void *buf, unsigned int size)
5354d30ea906Sjfb8856606 {
5355d30ea906Sjfb8856606 	struct buffer *out = buf;
5356d30ea906Sjfb8856606 	struct rte_flow_action *action;
5357d30ea906Sjfb8856606 	struct action_raw_encap_data *action_encap_data;
5358d30ea906Sjfb8856606 	struct rte_flow_item_eth eth = { .type = 0, };
5359d30ea906Sjfb8856606 	struct rte_flow_item_vlan vlan = {
5360d30ea906Sjfb8856606 		.tci = mplsogre_encap_conf.vlan_tci,
5361d30ea906Sjfb8856606 		.inner_type = 0,
5362d30ea906Sjfb8856606 	};
5363d30ea906Sjfb8856606 	struct rte_flow_item_ipv4 ipv4 = {
5364d30ea906Sjfb8856606 		.hdr =  {
5365d30ea906Sjfb8856606 			.src_addr = mplsogre_encap_conf.ipv4_src,
5366d30ea906Sjfb8856606 			.dst_addr = mplsogre_encap_conf.ipv4_dst,
5367d30ea906Sjfb8856606 			.next_proto_id = IPPROTO_GRE,
53684418919fSjohnjiang 			.version_ihl = RTE_IPV4_VHL_DEF,
53694b05018fSfengbojiang 			.time_to_live = IPDEFTTL,
5370d30ea906Sjfb8856606 		},
5371d30ea906Sjfb8856606 	};
5372d30ea906Sjfb8856606 	struct rte_flow_item_ipv6 ipv6 = {
5373d30ea906Sjfb8856606 		.hdr =  {
5374d30ea906Sjfb8856606 			.proto = IPPROTO_GRE,
53754418919fSjohnjiang 			.hop_limits = IPDEFTTL,
5376d30ea906Sjfb8856606 		},
5377d30ea906Sjfb8856606 	};
5378d30ea906Sjfb8856606 	struct rte_flow_item_gre gre = {
5379d30ea906Sjfb8856606 		.protocol = rte_cpu_to_be_16(ETHER_TYPE_MPLS_UNICAST),
5380d30ea906Sjfb8856606 	};
5381*2d9fd380Sjfb8856606 	struct rte_flow_item_mpls mpls = {
5382*2d9fd380Sjfb8856606 		.ttl = 0,
5383*2d9fd380Sjfb8856606 	};
5384d30ea906Sjfb8856606 	uint8_t *header;
5385d30ea906Sjfb8856606 	int ret;
5386d30ea906Sjfb8856606 
5387d30ea906Sjfb8856606 	ret = parse_vc(ctx, token, str, len, buf, size);
5388d30ea906Sjfb8856606 	if (ret < 0)
5389d30ea906Sjfb8856606 		return ret;
5390d30ea906Sjfb8856606 	/* Nothing else to do if there is no buffer. */
5391d30ea906Sjfb8856606 	if (!out)
5392d30ea906Sjfb8856606 		return ret;
5393d30ea906Sjfb8856606 	if (!out->args.vc.actions_n)
5394d30ea906Sjfb8856606 		return -1;
5395d30ea906Sjfb8856606 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
5396d30ea906Sjfb8856606 	/* Point to selected object. */
5397d30ea906Sjfb8856606 	ctx->object = out->args.vc.data;
5398d30ea906Sjfb8856606 	ctx->objmask = NULL;
5399d30ea906Sjfb8856606 	/* Copy the headers to the buffer. */
5400d30ea906Sjfb8856606 	action_encap_data = ctx->object;
5401d30ea906Sjfb8856606 	*action_encap_data = (struct action_raw_encap_data) {
5402d30ea906Sjfb8856606 		.conf = (struct rte_flow_action_raw_encap){
5403d30ea906Sjfb8856606 			.data = action_encap_data->data,
5404d30ea906Sjfb8856606 		},
5405d30ea906Sjfb8856606 		.data = {},
5406d30ea906Sjfb8856606 		.preserve = {},
5407d30ea906Sjfb8856606 	};
5408d30ea906Sjfb8856606 	header = action_encap_data->data;
5409d30ea906Sjfb8856606 	if (mplsogre_encap_conf.select_vlan)
54104418919fSjohnjiang 		eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
5411d30ea906Sjfb8856606 	else if (mplsogre_encap_conf.select_ipv4)
54124418919fSjohnjiang 		eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
5413d30ea906Sjfb8856606 	else
54144418919fSjohnjiang 		eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
5415d30ea906Sjfb8856606 	memcpy(eth.dst.addr_bytes,
54164418919fSjohnjiang 	       mplsogre_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
5417d30ea906Sjfb8856606 	memcpy(eth.src.addr_bytes,
54184418919fSjohnjiang 	       mplsogre_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
5419d30ea906Sjfb8856606 	memcpy(header, &eth, sizeof(eth));
5420d30ea906Sjfb8856606 	header += sizeof(eth);
5421d30ea906Sjfb8856606 	if (mplsogre_encap_conf.select_vlan) {
5422d30ea906Sjfb8856606 		if (mplsogre_encap_conf.select_ipv4)
54234418919fSjohnjiang 			vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
5424d30ea906Sjfb8856606 		else
54254418919fSjohnjiang 			vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
5426d30ea906Sjfb8856606 		memcpy(header, &vlan, sizeof(vlan));
5427d30ea906Sjfb8856606 		header += sizeof(vlan);
5428d30ea906Sjfb8856606 	}
5429d30ea906Sjfb8856606 	if (mplsogre_encap_conf.select_ipv4) {
5430d30ea906Sjfb8856606 		memcpy(header, &ipv4, sizeof(ipv4));
5431d30ea906Sjfb8856606 		header += sizeof(ipv4);
5432d30ea906Sjfb8856606 	} else {
5433d30ea906Sjfb8856606 		memcpy(&ipv6.hdr.src_addr,
5434d30ea906Sjfb8856606 		       &mplsogre_encap_conf.ipv6_src,
5435d30ea906Sjfb8856606 		       sizeof(mplsogre_encap_conf.ipv6_src));
5436d30ea906Sjfb8856606 		memcpy(&ipv6.hdr.dst_addr,
5437d30ea906Sjfb8856606 		       &mplsogre_encap_conf.ipv6_dst,
5438d30ea906Sjfb8856606 		       sizeof(mplsogre_encap_conf.ipv6_dst));
5439d30ea906Sjfb8856606 		memcpy(header, &ipv6, sizeof(ipv6));
5440d30ea906Sjfb8856606 		header += sizeof(ipv6);
5441d30ea906Sjfb8856606 	}
5442d30ea906Sjfb8856606 	memcpy(header, &gre, sizeof(gre));
5443d30ea906Sjfb8856606 	header += sizeof(gre);
5444d30ea906Sjfb8856606 	memcpy(mpls.label_tc_s, mplsogre_encap_conf.label,
5445d30ea906Sjfb8856606 	       RTE_DIM(mplsogre_encap_conf.label));
54461646932aSjfb8856606 	mpls.label_tc_s[2] |= 0x1;
5447d30ea906Sjfb8856606 	memcpy(header, &mpls, sizeof(mpls));
5448d30ea906Sjfb8856606 	header += sizeof(mpls);
5449d30ea906Sjfb8856606 	action_encap_data->conf.size = header -
5450d30ea906Sjfb8856606 		action_encap_data->data;
5451d30ea906Sjfb8856606 	action->conf = &action_encap_data->conf;
5452d30ea906Sjfb8856606 	return ret;
5453d30ea906Sjfb8856606 }
5454d30ea906Sjfb8856606 
5455d30ea906Sjfb8856606 /** Parse MPLSOGRE decap action. */
5456d30ea906Sjfb8856606 static int
parse_vc_action_mplsogre_decap(struct context * ctx,const struct token * token,const char * str,unsigned int len,void * buf,unsigned int size)5457d30ea906Sjfb8856606 parse_vc_action_mplsogre_decap(struct context *ctx, const struct token *token,
5458d30ea906Sjfb8856606 			       const char *str, unsigned int len,
5459d30ea906Sjfb8856606 			       void *buf, unsigned int size)
5460d30ea906Sjfb8856606 {
5461d30ea906Sjfb8856606 	struct buffer *out = buf;
5462d30ea906Sjfb8856606 	struct rte_flow_action *action;
5463d30ea906Sjfb8856606 	struct action_raw_decap_data *action_decap_data;
5464d30ea906Sjfb8856606 	struct rte_flow_item_eth eth = { .type = 0, };
5465d30ea906Sjfb8856606 	struct rte_flow_item_vlan vlan = {.tci = 0};
5466d30ea906Sjfb8856606 	struct rte_flow_item_ipv4 ipv4 = {
5467d30ea906Sjfb8856606 		.hdr =  {
5468d30ea906Sjfb8856606 			.next_proto_id = IPPROTO_GRE,
5469d30ea906Sjfb8856606 		},
5470d30ea906Sjfb8856606 	};
5471d30ea906Sjfb8856606 	struct rte_flow_item_ipv6 ipv6 = {
5472d30ea906Sjfb8856606 		.hdr =  {
5473d30ea906Sjfb8856606 			.proto = IPPROTO_GRE,
5474d30ea906Sjfb8856606 		},
5475d30ea906Sjfb8856606 	};
5476d30ea906Sjfb8856606 	struct rte_flow_item_gre gre = {
5477d30ea906Sjfb8856606 		.protocol = rte_cpu_to_be_16(ETHER_TYPE_MPLS_UNICAST),
5478d30ea906Sjfb8856606 	};
5479*2d9fd380Sjfb8856606 	struct rte_flow_item_mpls mpls;
5480d30ea906Sjfb8856606 	uint8_t *header;
5481d30ea906Sjfb8856606 	int ret;
5482d30ea906Sjfb8856606 
5483d30ea906Sjfb8856606 	ret = parse_vc(ctx, token, str, len, buf, size);
5484d30ea906Sjfb8856606 	if (ret < 0)
5485d30ea906Sjfb8856606 		return ret;
5486d30ea906Sjfb8856606 	/* Nothing else to do if there is no buffer. */
5487d30ea906Sjfb8856606 	if (!out)
5488d30ea906Sjfb8856606 		return ret;
5489d30ea906Sjfb8856606 	if (!out->args.vc.actions_n)
5490d30ea906Sjfb8856606 		return -1;
5491d30ea906Sjfb8856606 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
5492d30ea906Sjfb8856606 	/* Point to selected object. */
5493d30ea906Sjfb8856606 	ctx->object = out->args.vc.data;
5494d30ea906Sjfb8856606 	ctx->objmask = NULL;
5495d30ea906Sjfb8856606 	/* Copy the headers to the buffer. */
5496d30ea906Sjfb8856606 	action_decap_data = ctx->object;
5497d30ea906Sjfb8856606 	*action_decap_data = (struct action_raw_decap_data) {
5498d30ea906Sjfb8856606 		.conf = (struct rte_flow_action_raw_decap){
5499d30ea906Sjfb8856606 			.data = action_decap_data->data,
5500d30ea906Sjfb8856606 		},
5501d30ea906Sjfb8856606 		.data = {},
5502d30ea906Sjfb8856606 	};
5503d30ea906Sjfb8856606 	header = action_decap_data->data;
5504d30ea906Sjfb8856606 	if (mplsogre_decap_conf.select_vlan)
55054418919fSjohnjiang 		eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
5506d30ea906Sjfb8856606 	else if (mplsogre_encap_conf.select_ipv4)
55074418919fSjohnjiang 		eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
5508d30ea906Sjfb8856606 	else
55094418919fSjohnjiang 		eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
5510d30ea906Sjfb8856606 	memcpy(eth.dst.addr_bytes,
55114418919fSjohnjiang 	       mplsogre_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
5512d30ea906Sjfb8856606 	memcpy(eth.src.addr_bytes,
55134418919fSjohnjiang 	       mplsogre_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
5514d30ea906Sjfb8856606 	memcpy(header, &eth, sizeof(eth));
5515d30ea906Sjfb8856606 	header += sizeof(eth);
5516d30ea906Sjfb8856606 	if (mplsogre_encap_conf.select_vlan) {
5517d30ea906Sjfb8856606 		if (mplsogre_encap_conf.select_ipv4)
55184418919fSjohnjiang 			vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
5519d30ea906Sjfb8856606 		else
55204418919fSjohnjiang 			vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
5521d30ea906Sjfb8856606 		memcpy(header, &vlan, sizeof(vlan));
5522d30ea906Sjfb8856606 		header += sizeof(vlan);
5523d30ea906Sjfb8856606 	}
5524d30ea906Sjfb8856606 	if (mplsogre_encap_conf.select_ipv4) {
5525d30ea906Sjfb8856606 		memcpy(header, &ipv4, sizeof(ipv4));
5526d30ea906Sjfb8856606 		header += sizeof(ipv4);
5527d30ea906Sjfb8856606 	} else {
5528d30ea906Sjfb8856606 		memcpy(header, &ipv6, sizeof(ipv6));
5529d30ea906Sjfb8856606 		header += sizeof(ipv6);
5530d30ea906Sjfb8856606 	}
5531d30ea906Sjfb8856606 	memcpy(header, &gre, sizeof(gre));
5532d30ea906Sjfb8856606 	header += sizeof(gre);
5533d30ea906Sjfb8856606 	memset(&mpls, 0, sizeof(mpls));
5534d30ea906Sjfb8856606 	memcpy(header, &mpls, sizeof(mpls));
5535d30ea906Sjfb8856606 	header += sizeof(mpls);
5536d30ea906Sjfb8856606 	action_decap_data->conf.size = header -
5537d30ea906Sjfb8856606 		action_decap_data->data;
5538d30ea906Sjfb8856606 	action->conf = &action_decap_data->conf;
5539d30ea906Sjfb8856606 	return ret;
5540d30ea906Sjfb8856606 }
5541d30ea906Sjfb8856606 
5542d30ea906Sjfb8856606 /** Parse MPLSOUDP encap action. */
5543d30ea906Sjfb8856606 static int
parse_vc_action_mplsoudp_encap(struct context * ctx,const struct token * token,const char * str,unsigned int len,void * buf,unsigned int size)5544d30ea906Sjfb8856606 parse_vc_action_mplsoudp_encap(struct context *ctx, const struct token *token,
5545d30ea906Sjfb8856606 			       const char *str, unsigned int len,
5546d30ea906Sjfb8856606 			       void *buf, unsigned int size)
5547d30ea906Sjfb8856606 {
5548d30ea906Sjfb8856606 	struct buffer *out = buf;
5549d30ea906Sjfb8856606 	struct rte_flow_action *action;
5550d30ea906Sjfb8856606 	struct action_raw_encap_data *action_encap_data;
5551d30ea906Sjfb8856606 	struct rte_flow_item_eth eth = { .type = 0, };
5552d30ea906Sjfb8856606 	struct rte_flow_item_vlan vlan = {
5553d30ea906Sjfb8856606 		.tci = mplsoudp_encap_conf.vlan_tci,
5554d30ea906Sjfb8856606 		.inner_type = 0,
5555d30ea906Sjfb8856606 	};
5556d30ea906Sjfb8856606 	struct rte_flow_item_ipv4 ipv4 = {
5557d30ea906Sjfb8856606 		.hdr =  {
5558d30ea906Sjfb8856606 			.src_addr = mplsoudp_encap_conf.ipv4_src,
5559d30ea906Sjfb8856606 			.dst_addr = mplsoudp_encap_conf.ipv4_dst,
5560d30ea906Sjfb8856606 			.next_proto_id = IPPROTO_UDP,
55614418919fSjohnjiang 			.version_ihl = RTE_IPV4_VHL_DEF,
55624b05018fSfengbojiang 			.time_to_live = IPDEFTTL,
5563d30ea906Sjfb8856606 		},
5564d30ea906Sjfb8856606 	};
5565d30ea906Sjfb8856606 	struct rte_flow_item_ipv6 ipv6 = {
5566d30ea906Sjfb8856606 		.hdr =  {
5567d30ea906Sjfb8856606 			.proto = IPPROTO_UDP,
55684418919fSjohnjiang 			.hop_limits = IPDEFTTL,
5569d30ea906Sjfb8856606 		},
5570d30ea906Sjfb8856606 	};
5571d30ea906Sjfb8856606 	struct rte_flow_item_udp udp = {
5572d30ea906Sjfb8856606 		.hdr = {
5573d30ea906Sjfb8856606 			.src_port = mplsoudp_encap_conf.udp_src,
5574d30ea906Sjfb8856606 			.dst_port = mplsoudp_encap_conf.udp_dst,
5575d30ea906Sjfb8856606 		},
5576d30ea906Sjfb8856606 	};
5577d30ea906Sjfb8856606 	struct rte_flow_item_mpls mpls;
5578d30ea906Sjfb8856606 	uint8_t *header;
5579d30ea906Sjfb8856606 	int ret;
5580d30ea906Sjfb8856606 
5581d30ea906Sjfb8856606 	ret = parse_vc(ctx, token, str, len, buf, size);
5582d30ea906Sjfb8856606 	if (ret < 0)
5583d30ea906Sjfb8856606 		return ret;
5584d30ea906Sjfb8856606 	/* Nothing else to do if there is no buffer. */
5585d30ea906Sjfb8856606 	if (!out)
5586d30ea906Sjfb8856606 		return ret;
5587d30ea906Sjfb8856606 	if (!out->args.vc.actions_n)
5588d30ea906Sjfb8856606 		return -1;
5589d30ea906Sjfb8856606 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
5590d30ea906Sjfb8856606 	/* Point to selected object. */
5591d30ea906Sjfb8856606 	ctx->object = out->args.vc.data;
5592d30ea906Sjfb8856606 	ctx->objmask = NULL;
5593d30ea906Sjfb8856606 	/* Copy the headers to the buffer. */
5594d30ea906Sjfb8856606 	action_encap_data = ctx->object;
5595d30ea906Sjfb8856606 	*action_encap_data = (struct action_raw_encap_data) {
5596d30ea906Sjfb8856606 		.conf = (struct rte_flow_action_raw_encap){
5597d30ea906Sjfb8856606 			.data = action_encap_data->data,
5598d30ea906Sjfb8856606 		},
5599d30ea906Sjfb8856606 		.data = {},
5600d30ea906Sjfb8856606 		.preserve = {},
5601d30ea906Sjfb8856606 	};
5602d30ea906Sjfb8856606 	header = action_encap_data->data;
5603d30ea906Sjfb8856606 	if (mplsoudp_encap_conf.select_vlan)
56044418919fSjohnjiang 		eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
5605d30ea906Sjfb8856606 	else if (mplsoudp_encap_conf.select_ipv4)
56064418919fSjohnjiang 		eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
5607d30ea906Sjfb8856606 	else
56084418919fSjohnjiang 		eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
5609d30ea906Sjfb8856606 	memcpy(eth.dst.addr_bytes,
56104418919fSjohnjiang 	       mplsoudp_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
5611d30ea906Sjfb8856606 	memcpy(eth.src.addr_bytes,
56124418919fSjohnjiang 	       mplsoudp_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
5613d30ea906Sjfb8856606 	memcpy(header, &eth, sizeof(eth));
5614d30ea906Sjfb8856606 	header += sizeof(eth);
5615d30ea906Sjfb8856606 	if (mplsoudp_encap_conf.select_vlan) {
5616d30ea906Sjfb8856606 		if (mplsoudp_encap_conf.select_ipv4)
56174418919fSjohnjiang 			vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
5618d30ea906Sjfb8856606 		else
56194418919fSjohnjiang 			vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
5620d30ea906Sjfb8856606 		memcpy(header, &vlan, sizeof(vlan));
5621d30ea906Sjfb8856606 		header += sizeof(vlan);
5622d30ea906Sjfb8856606 	}
5623d30ea906Sjfb8856606 	if (mplsoudp_encap_conf.select_ipv4) {
5624d30ea906Sjfb8856606 		memcpy(header, &ipv4, sizeof(ipv4));
5625d30ea906Sjfb8856606 		header += sizeof(ipv4);
5626d30ea906Sjfb8856606 	} else {
5627d30ea906Sjfb8856606 		memcpy(&ipv6.hdr.src_addr,
5628d30ea906Sjfb8856606 		       &mplsoudp_encap_conf.ipv6_src,
5629d30ea906Sjfb8856606 		       sizeof(mplsoudp_encap_conf.ipv6_src));
5630d30ea906Sjfb8856606 		memcpy(&ipv6.hdr.dst_addr,
5631d30ea906Sjfb8856606 		       &mplsoudp_encap_conf.ipv6_dst,
5632d30ea906Sjfb8856606 		       sizeof(mplsoudp_encap_conf.ipv6_dst));
5633d30ea906Sjfb8856606 		memcpy(header, &ipv6, sizeof(ipv6));
5634d30ea906Sjfb8856606 		header += sizeof(ipv6);
5635d30ea906Sjfb8856606 	}
5636d30ea906Sjfb8856606 	memcpy(header, &udp, sizeof(udp));
5637d30ea906Sjfb8856606 	header += sizeof(udp);
5638d30ea906Sjfb8856606 	memcpy(mpls.label_tc_s, mplsoudp_encap_conf.label,
5639d30ea906Sjfb8856606 	       RTE_DIM(mplsoudp_encap_conf.label));
56401646932aSjfb8856606 	mpls.label_tc_s[2] |= 0x1;
5641d30ea906Sjfb8856606 	memcpy(header, &mpls, sizeof(mpls));
5642d30ea906Sjfb8856606 	header += sizeof(mpls);
5643d30ea906Sjfb8856606 	action_encap_data->conf.size = header -
5644d30ea906Sjfb8856606 		action_encap_data->data;
5645d30ea906Sjfb8856606 	action->conf = &action_encap_data->conf;
5646d30ea906Sjfb8856606 	return ret;
5647d30ea906Sjfb8856606 }
5648d30ea906Sjfb8856606 
5649d30ea906Sjfb8856606 /** Parse MPLSOUDP decap action. */
5650d30ea906Sjfb8856606 static int
parse_vc_action_mplsoudp_decap(struct context * ctx,const struct token * token,const char * str,unsigned int len,void * buf,unsigned int size)5651d30ea906Sjfb8856606 parse_vc_action_mplsoudp_decap(struct context *ctx, const struct token *token,
5652d30ea906Sjfb8856606 			       const char *str, unsigned int len,
5653d30ea906Sjfb8856606 			       void *buf, unsigned int size)
5654d30ea906Sjfb8856606 {
5655d30ea906Sjfb8856606 	struct buffer *out = buf;
5656d30ea906Sjfb8856606 	struct rte_flow_action *action;
5657d30ea906Sjfb8856606 	struct action_raw_decap_data *action_decap_data;
5658d30ea906Sjfb8856606 	struct rte_flow_item_eth eth = { .type = 0, };
5659d30ea906Sjfb8856606 	struct rte_flow_item_vlan vlan = {.tci = 0};
5660d30ea906Sjfb8856606 	struct rte_flow_item_ipv4 ipv4 = {
5661d30ea906Sjfb8856606 		.hdr =  {
5662d30ea906Sjfb8856606 			.next_proto_id = IPPROTO_UDP,
5663d30ea906Sjfb8856606 		},
5664d30ea906Sjfb8856606 	};
5665d30ea906Sjfb8856606 	struct rte_flow_item_ipv6 ipv6 = {
5666d30ea906Sjfb8856606 		.hdr =  {
5667d30ea906Sjfb8856606 			.proto = IPPROTO_UDP,
5668d30ea906Sjfb8856606 		},
5669d30ea906Sjfb8856606 	};
5670d30ea906Sjfb8856606 	struct rte_flow_item_udp udp = {
5671d30ea906Sjfb8856606 		.hdr = {
5672d30ea906Sjfb8856606 			.dst_port = rte_cpu_to_be_16(6635),
5673d30ea906Sjfb8856606 		},
5674d30ea906Sjfb8856606 	};
5675d30ea906Sjfb8856606 	struct rte_flow_item_mpls mpls;
5676d30ea906Sjfb8856606 	uint8_t *header;
5677d30ea906Sjfb8856606 	int ret;
5678d30ea906Sjfb8856606 
5679d30ea906Sjfb8856606 	ret = parse_vc(ctx, token, str, len, buf, size);
5680d30ea906Sjfb8856606 	if (ret < 0)
5681d30ea906Sjfb8856606 		return ret;
5682d30ea906Sjfb8856606 	/* Nothing else to do if there is no buffer. */
5683d30ea906Sjfb8856606 	if (!out)
5684d30ea906Sjfb8856606 		return ret;
5685d30ea906Sjfb8856606 	if (!out->args.vc.actions_n)
5686d30ea906Sjfb8856606 		return -1;
5687d30ea906Sjfb8856606 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
5688d30ea906Sjfb8856606 	/* Point to selected object. */
5689d30ea906Sjfb8856606 	ctx->object = out->args.vc.data;
5690d30ea906Sjfb8856606 	ctx->objmask = NULL;
5691d30ea906Sjfb8856606 	/* Copy the headers to the buffer. */
5692d30ea906Sjfb8856606 	action_decap_data = ctx->object;
5693d30ea906Sjfb8856606 	*action_decap_data = (struct action_raw_decap_data) {
5694d30ea906Sjfb8856606 		.conf = (struct rte_flow_action_raw_decap){
5695d30ea906Sjfb8856606 			.data = action_decap_data->data,
5696d30ea906Sjfb8856606 		},
5697d30ea906Sjfb8856606 		.data = {},
5698d30ea906Sjfb8856606 	};
5699d30ea906Sjfb8856606 	header = action_decap_data->data;
5700d30ea906Sjfb8856606 	if (mplsoudp_decap_conf.select_vlan)
57014418919fSjohnjiang 		eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
5702d30ea906Sjfb8856606 	else if (mplsoudp_encap_conf.select_ipv4)
57034418919fSjohnjiang 		eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
5704d30ea906Sjfb8856606 	else
57054418919fSjohnjiang 		eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
5706d30ea906Sjfb8856606 	memcpy(eth.dst.addr_bytes,
57074418919fSjohnjiang 	       mplsoudp_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
5708d30ea906Sjfb8856606 	memcpy(eth.src.addr_bytes,
57094418919fSjohnjiang 	       mplsoudp_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
5710d30ea906Sjfb8856606 	memcpy(header, &eth, sizeof(eth));
5711d30ea906Sjfb8856606 	header += sizeof(eth);
5712d30ea906Sjfb8856606 	if (mplsoudp_encap_conf.select_vlan) {
5713d30ea906Sjfb8856606 		if (mplsoudp_encap_conf.select_ipv4)
57144418919fSjohnjiang 			vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
5715d30ea906Sjfb8856606 		else
57164418919fSjohnjiang 			vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
5717d30ea906Sjfb8856606 		memcpy(header, &vlan, sizeof(vlan));
5718d30ea906Sjfb8856606 		header += sizeof(vlan);
5719d30ea906Sjfb8856606 	}
5720d30ea906Sjfb8856606 	if (mplsoudp_encap_conf.select_ipv4) {
5721d30ea906Sjfb8856606 		memcpy(header, &ipv4, sizeof(ipv4));
5722d30ea906Sjfb8856606 		header += sizeof(ipv4);
5723d30ea906Sjfb8856606 	} else {
5724d30ea906Sjfb8856606 		memcpy(header, &ipv6, sizeof(ipv6));
5725d30ea906Sjfb8856606 		header += sizeof(ipv6);
5726d30ea906Sjfb8856606 	}
5727d30ea906Sjfb8856606 	memcpy(header, &udp, sizeof(udp));
5728d30ea906Sjfb8856606 	header += sizeof(udp);
5729d30ea906Sjfb8856606 	memset(&mpls, 0, sizeof(mpls));
5730d30ea906Sjfb8856606 	memcpy(header, &mpls, sizeof(mpls));
5731d30ea906Sjfb8856606 	header += sizeof(mpls);
5732d30ea906Sjfb8856606 	action_decap_data->conf.size = header -
5733d30ea906Sjfb8856606 		action_decap_data->data;
5734d30ea906Sjfb8856606 	action->conf = &action_decap_data->conf;
5735d30ea906Sjfb8856606 	return ret;
5736d30ea906Sjfb8856606 }
5737d30ea906Sjfb8856606 
57384418919fSjohnjiang static int
parse_vc_action_raw_decap_index(struct context * ctx,const struct token * token,const char * str,unsigned int len,void * buf,unsigned int size)57394418919fSjohnjiang parse_vc_action_raw_decap_index(struct context *ctx, const struct token *token,
57404418919fSjohnjiang 				const char *str, unsigned int len, void *buf,
57414418919fSjohnjiang 				unsigned int size)
57424418919fSjohnjiang {
57434418919fSjohnjiang 	struct action_raw_decap_data *action_raw_decap_data;
57444418919fSjohnjiang 	struct rte_flow_action *action;
57454418919fSjohnjiang 	const struct arg *arg;
57464418919fSjohnjiang 	struct buffer *out = buf;
57474418919fSjohnjiang 	int ret;
57484418919fSjohnjiang 	uint16_t idx;
57494418919fSjohnjiang 
57504418919fSjohnjiang 	RTE_SET_USED(token);
57514418919fSjohnjiang 	RTE_SET_USED(buf);
57524418919fSjohnjiang 	RTE_SET_USED(size);
57534418919fSjohnjiang 	arg = ARGS_ENTRY_ARB_BOUNDED
57544418919fSjohnjiang 		(offsetof(struct action_raw_decap_data, idx),
57554418919fSjohnjiang 		 sizeof(((struct action_raw_decap_data *)0)->idx),
57564418919fSjohnjiang 		 0, RAW_ENCAP_CONFS_MAX_NUM - 1);
57574418919fSjohnjiang 	if (push_args(ctx, arg))
57584418919fSjohnjiang 		return -1;
57594418919fSjohnjiang 	ret = parse_int(ctx, token, str, len, NULL, 0);
57604418919fSjohnjiang 	if (ret < 0) {
57614418919fSjohnjiang 		pop_args(ctx);
57624418919fSjohnjiang 		return -1;
57634418919fSjohnjiang 	}
57644418919fSjohnjiang 	if (!ctx->object)
57654418919fSjohnjiang 		return len;
57664418919fSjohnjiang 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
57674418919fSjohnjiang 	action_raw_decap_data = ctx->object;
57684418919fSjohnjiang 	idx = action_raw_decap_data->idx;
57694418919fSjohnjiang 	action_raw_decap_data->conf.data = raw_decap_confs[idx].data;
57704418919fSjohnjiang 	action_raw_decap_data->conf.size = raw_decap_confs[idx].size;
57714418919fSjohnjiang 	action->conf = &action_raw_decap_data->conf;
57724418919fSjohnjiang 	return len;
57734418919fSjohnjiang }
57744418919fSjohnjiang 
57754418919fSjohnjiang 
57764418919fSjohnjiang static int
parse_vc_action_raw_encap_index(struct context * ctx,const struct token * token,const char * str,unsigned int len,void * buf,unsigned int size)57774418919fSjohnjiang parse_vc_action_raw_encap_index(struct context *ctx, const struct token *token,
57784418919fSjohnjiang 				const char *str, unsigned int len, void *buf,
57794418919fSjohnjiang 				unsigned int size)
57804418919fSjohnjiang {
57814418919fSjohnjiang 	struct action_raw_encap_data *action_raw_encap_data;
57824418919fSjohnjiang 	struct rte_flow_action *action;
57834418919fSjohnjiang 	const struct arg *arg;
57844418919fSjohnjiang 	struct buffer *out = buf;
57854418919fSjohnjiang 	int ret;
57864418919fSjohnjiang 	uint16_t idx;
57874418919fSjohnjiang 
57884418919fSjohnjiang 	RTE_SET_USED(token);
57894418919fSjohnjiang 	RTE_SET_USED(buf);
57904418919fSjohnjiang 	RTE_SET_USED(size);
57914418919fSjohnjiang 	if (ctx->curr != ACTION_RAW_ENCAP_INDEX_VALUE)
57924418919fSjohnjiang 		return -1;
57934418919fSjohnjiang 	arg = ARGS_ENTRY_ARB_BOUNDED
57944418919fSjohnjiang 		(offsetof(struct action_raw_encap_data, idx),
57954418919fSjohnjiang 		 sizeof(((struct action_raw_encap_data *)0)->idx),
57964418919fSjohnjiang 		 0, RAW_ENCAP_CONFS_MAX_NUM - 1);
57974418919fSjohnjiang 	if (push_args(ctx, arg))
57984418919fSjohnjiang 		return -1;
57994418919fSjohnjiang 	ret = parse_int(ctx, token, str, len, NULL, 0);
58004418919fSjohnjiang 	if (ret < 0) {
58014418919fSjohnjiang 		pop_args(ctx);
58024418919fSjohnjiang 		return -1;
58034418919fSjohnjiang 	}
58044418919fSjohnjiang 	if (!ctx->object)
58054418919fSjohnjiang 		return len;
58064418919fSjohnjiang 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
58074418919fSjohnjiang 	action_raw_encap_data = ctx->object;
58084418919fSjohnjiang 	idx = action_raw_encap_data->idx;
58094418919fSjohnjiang 	action_raw_encap_data->conf.data = raw_encap_confs[idx].data;
58104418919fSjohnjiang 	action_raw_encap_data->conf.size = raw_encap_confs[idx].size;
58114418919fSjohnjiang 	action_raw_encap_data->conf.preserve = NULL;
58124418919fSjohnjiang 	action->conf = &action_raw_encap_data->conf;
58134418919fSjohnjiang 	return len;
58144418919fSjohnjiang }
58154418919fSjohnjiang 
58164418919fSjohnjiang static int
parse_vc_action_raw_encap(struct context * ctx,const struct token * token,const char * str,unsigned int len,void * buf,unsigned int size)58174418919fSjohnjiang parse_vc_action_raw_encap(struct context *ctx, const struct token *token,
58184418919fSjohnjiang 			  const char *str, unsigned int len, void *buf,
58194418919fSjohnjiang 			  unsigned int size)
58204418919fSjohnjiang {
58214418919fSjohnjiang 	struct buffer *out = buf;
58224418919fSjohnjiang 	struct rte_flow_action *action;
58234418919fSjohnjiang 	struct action_raw_encap_data *action_raw_encap_data = NULL;
58244418919fSjohnjiang 	int ret;
58254418919fSjohnjiang 
58264418919fSjohnjiang 	ret = parse_vc(ctx, token, str, len, buf, size);
58274418919fSjohnjiang 	if (ret < 0)
58284418919fSjohnjiang 		return ret;
58294418919fSjohnjiang 	/* Nothing else to do if there is no buffer. */
58304418919fSjohnjiang 	if (!out)
58314418919fSjohnjiang 		return ret;
58324418919fSjohnjiang 	if (!out->args.vc.actions_n)
58334418919fSjohnjiang 		return -1;
58344418919fSjohnjiang 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
58354418919fSjohnjiang 	/* Point to selected object. */
58364418919fSjohnjiang 	ctx->object = out->args.vc.data;
58374418919fSjohnjiang 	ctx->objmask = NULL;
58384418919fSjohnjiang 	/* Copy the headers to the buffer. */
58394418919fSjohnjiang 	action_raw_encap_data = ctx->object;
58404418919fSjohnjiang 	action_raw_encap_data->conf.data = raw_encap_confs[0].data;
58414418919fSjohnjiang 	action_raw_encap_data->conf.preserve = NULL;
58424418919fSjohnjiang 	action_raw_encap_data->conf.size = raw_encap_confs[0].size;
58434418919fSjohnjiang 	action->conf = &action_raw_encap_data->conf;
58444418919fSjohnjiang 	return ret;
58454418919fSjohnjiang }
58464418919fSjohnjiang 
58474418919fSjohnjiang static int
parse_vc_action_raw_decap(struct context * ctx,const struct token * token,const char * str,unsigned int len,void * buf,unsigned int size)58484418919fSjohnjiang parse_vc_action_raw_decap(struct context *ctx, const struct token *token,
58494418919fSjohnjiang 			  const char *str, unsigned int len, void *buf,
58504418919fSjohnjiang 			  unsigned int size)
58514418919fSjohnjiang {
58524418919fSjohnjiang 	struct buffer *out = buf;
58534418919fSjohnjiang 	struct rte_flow_action *action;
58544418919fSjohnjiang 	struct action_raw_decap_data *action_raw_decap_data = NULL;
58554418919fSjohnjiang 	int ret;
58564418919fSjohnjiang 
58574418919fSjohnjiang 	ret = parse_vc(ctx, token, str, len, buf, size);
58584418919fSjohnjiang 	if (ret < 0)
58594418919fSjohnjiang 		return ret;
58604418919fSjohnjiang 	/* Nothing else to do if there is no buffer. */
58614418919fSjohnjiang 	if (!out)
58624418919fSjohnjiang 		return ret;
58634418919fSjohnjiang 	if (!out->args.vc.actions_n)
58644418919fSjohnjiang 		return -1;
58654418919fSjohnjiang 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
58664418919fSjohnjiang 	/* Point to selected object. */
58674418919fSjohnjiang 	ctx->object = out->args.vc.data;
58684418919fSjohnjiang 	ctx->objmask = NULL;
58694418919fSjohnjiang 	/* Copy the headers to the buffer. */
58704418919fSjohnjiang 	action_raw_decap_data = ctx->object;
58714418919fSjohnjiang 	action_raw_decap_data->conf.data = raw_decap_confs[0].data;
58724418919fSjohnjiang 	action_raw_decap_data->conf.size = raw_decap_confs[0].size;
58734418919fSjohnjiang 	action->conf = &action_raw_decap_data->conf;
58744418919fSjohnjiang 	return ret;
58754418919fSjohnjiang }
58764418919fSjohnjiang 
58774418919fSjohnjiang static int
parse_vc_action_set_meta(struct context * ctx,const struct token * token,const char * str,unsigned int len,void * buf,unsigned int size)58784418919fSjohnjiang parse_vc_action_set_meta(struct context *ctx, const struct token *token,
58794418919fSjohnjiang 			 const char *str, unsigned int len, void *buf,
58804418919fSjohnjiang 			 unsigned int size)
58814418919fSjohnjiang {
58824418919fSjohnjiang 	int ret;
58834418919fSjohnjiang 
58844418919fSjohnjiang 	ret = parse_vc(ctx, token, str, len, buf, size);
58854418919fSjohnjiang 	if (ret < 0)
58864418919fSjohnjiang 		return ret;
58874418919fSjohnjiang 	ret = rte_flow_dynf_metadata_register();
58884418919fSjohnjiang 	if (ret < 0)
58894418919fSjohnjiang 		return -1;
58904418919fSjohnjiang 	return len;
58914418919fSjohnjiang }
58924418919fSjohnjiang 
5893*2d9fd380Sjfb8856606 static int
parse_vc_action_sample(struct context * ctx,const struct token * token,const char * str,unsigned int len,void * buf,unsigned int size)5894*2d9fd380Sjfb8856606 parse_vc_action_sample(struct context *ctx, const struct token *token,
5895*2d9fd380Sjfb8856606 			 const char *str, unsigned int len, void *buf,
5896*2d9fd380Sjfb8856606 			 unsigned int size)
5897*2d9fd380Sjfb8856606 {
5898*2d9fd380Sjfb8856606 	struct buffer *out = buf;
5899*2d9fd380Sjfb8856606 	struct rte_flow_action *action;
5900*2d9fd380Sjfb8856606 	struct action_sample_data *action_sample_data = NULL;
5901*2d9fd380Sjfb8856606 	static struct rte_flow_action end_action = {
5902*2d9fd380Sjfb8856606 		RTE_FLOW_ACTION_TYPE_END, 0
5903*2d9fd380Sjfb8856606 	};
5904*2d9fd380Sjfb8856606 	int ret;
5905*2d9fd380Sjfb8856606 
5906*2d9fd380Sjfb8856606 	ret = parse_vc(ctx, token, str, len, buf, size);
5907*2d9fd380Sjfb8856606 	if (ret < 0)
5908*2d9fd380Sjfb8856606 		return ret;
5909*2d9fd380Sjfb8856606 	/* Nothing else to do if there is no buffer. */
5910*2d9fd380Sjfb8856606 	if (!out)
5911*2d9fd380Sjfb8856606 		return ret;
5912*2d9fd380Sjfb8856606 	if (!out->args.vc.actions_n)
5913*2d9fd380Sjfb8856606 		return -1;
5914*2d9fd380Sjfb8856606 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
5915*2d9fd380Sjfb8856606 	/* Point to selected object. */
5916*2d9fd380Sjfb8856606 	ctx->object = out->args.vc.data;
5917*2d9fd380Sjfb8856606 	ctx->objmask = NULL;
5918*2d9fd380Sjfb8856606 	/* Copy the headers to the buffer. */
5919*2d9fd380Sjfb8856606 	action_sample_data = ctx->object;
5920*2d9fd380Sjfb8856606 	action_sample_data->conf.actions = &end_action;
5921*2d9fd380Sjfb8856606 	action->conf = &action_sample_data->conf;
5922*2d9fd380Sjfb8856606 	return ret;
5923*2d9fd380Sjfb8856606 }
5924*2d9fd380Sjfb8856606 
5925*2d9fd380Sjfb8856606 static int
parse_vc_action_sample_index(struct context * ctx,const struct token * token,const char * str,unsigned int len,void * buf,unsigned int size)5926*2d9fd380Sjfb8856606 parse_vc_action_sample_index(struct context *ctx, const struct token *token,
5927*2d9fd380Sjfb8856606 				const char *str, unsigned int len, void *buf,
5928*2d9fd380Sjfb8856606 				unsigned int size)
5929*2d9fd380Sjfb8856606 {
5930*2d9fd380Sjfb8856606 	struct action_sample_data *action_sample_data;
5931*2d9fd380Sjfb8856606 	struct rte_flow_action *action;
5932*2d9fd380Sjfb8856606 	const struct arg *arg;
5933*2d9fd380Sjfb8856606 	struct buffer *out = buf;
5934*2d9fd380Sjfb8856606 	int ret;
5935*2d9fd380Sjfb8856606 	uint16_t idx;
5936*2d9fd380Sjfb8856606 
5937*2d9fd380Sjfb8856606 	RTE_SET_USED(token);
5938*2d9fd380Sjfb8856606 	RTE_SET_USED(buf);
5939*2d9fd380Sjfb8856606 	RTE_SET_USED(size);
5940*2d9fd380Sjfb8856606 	if (ctx->curr != ACTION_SAMPLE_INDEX_VALUE)
5941*2d9fd380Sjfb8856606 		return -1;
5942*2d9fd380Sjfb8856606 	arg = ARGS_ENTRY_ARB_BOUNDED
5943*2d9fd380Sjfb8856606 		(offsetof(struct action_sample_data, idx),
5944*2d9fd380Sjfb8856606 		 sizeof(((struct action_sample_data *)0)->idx),
5945*2d9fd380Sjfb8856606 		 0, RAW_SAMPLE_CONFS_MAX_NUM - 1);
5946*2d9fd380Sjfb8856606 	if (push_args(ctx, arg))
5947*2d9fd380Sjfb8856606 		return -1;
5948*2d9fd380Sjfb8856606 	ret = parse_int(ctx, token, str, len, NULL, 0);
5949*2d9fd380Sjfb8856606 	if (ret < 0) {
5950*2d9fd380Sjfb8856606 		pop_args(ctx);
5951*2d9fd380Sjfb8856606 		return -1;
5952*2d9fd380Sjfb8856606 	}
5953*2d9fd380Sjfb8856606 	if (!ctx->object)
5954*2d9fd380Sjfb8856606 		return len;
5955*2d9fd380Sjfb8856606 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
5956*2d9fd380Sjfb8856606 	action_sample_data = ctx->object;
5957*2d9fd380Sjfb8856606 	idx = action_sample_data->idx;
5958*2d9fd380Sjfb8856606 	action_sample_data->conf.actions = raw_sample_confs[idx].data;
5959*2d9fd380Sjfb8856606 	action->conf = &action_sample_data->conf;
5960*2d9fd380Sjfb8856606 	return len;
5961*2d9fd380Sjfb8856606 }
5962*2d9fd380Sjfb8856606 
59632bfe3f2eSlogwang /** Parse tokens for destroy command. */
59642bfe3f2eSlogwang static int
parse_destroy(struct context * ctx,const struct token * token,const char * str,unsigned int len,void * buf,unsigned int size)59652bfe3f2eSlogwang parse_destroy(struct context *ctx, const struct token *token,
59662bfe3f2eSlogwang 	      const char *str, unsigned int len,
59672bfe3f2eSlogwang 	      void *buf, unsigned int size)
59682bfe3f2eSlogwang {
59692bfe3f2eSlogwang 	struct buffer *out = buf;
59702bfe3f2eSlogwang 
59712bfe3f2eSlogwang 	/* Token name must match. */
59722bfe3f2eSlogwang 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
59732bfe3f2eSlogwang 		return -1;
59742bfe3f2eSlogwang 	/* Nothing else to do if there is no buffer. */
59752bfe3f2eSlogwang 	if (!out)
59762bfe3f2eSlogwang 		return len;
59772bfe3f2eSlogwang 	if (!out->command) {
59782bfe3f2eSlogwang 		if (ctx->curr != DESTROY)
59792bfe3f2eSlogwang 			return -1;
59802bfe3f2eSlogwang 		if (sizeof(*out) > size)
59812bfe3f2eSlogwang 			return -1;
59822bfe3f2eSlogwang 		out->command = ctx->curr;
59832bfe3f2eSlogwang 		ctx->objdata = 0;
59842bfe3f2eSlogwang 		ctx->object = out;
59852bfe3f2eSlogwang 		ctx->objmask = NULL;
59862bfe3f2eSlogwang 		out->args.destroy.rule =
59872bfe3f2eSlogwang 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
59882bfe3f2eSlogwang 					       sizeof(double));
59892bfe3f2eSlogwang 		return len;
59902bfe3f2eSlogwang 	}
59912bfe3f2eSlogwang 	if (((uint8_t *)(out->args.destroy.rule + out->args.destroy.rule_n) +
59922bfe3f2eSlogwang 	     sizeof(*out->args.destroy.rule)) > (uint8_t *)out + size)
59932bfe3f2eSlogwang 		return -1;
59942bfe3f2eSlogwang 	ctx->objdata = 0;
59952bfe3f2eSlogwang 	ctx->object = out->args.destroy.rule + out->args.destroy.rule_n++;
59962bfe3f2eSlogwang 	ctx->objmask = NULL;
59972bfe3f2eSlogwang 	return len;
59982bfe3f2eSlogwang }
59992bfe3f2eSlogwang 
60002bfe3f2eSlogwang /** Parse tokens for flush command. */
60012bfe3f2eSlogwang static int
parse_flush(struct context * ctx,const struct token * token,const char * str,unsigned int len,void * buf,unsigned int size)60022bfe3f2eSlogwang parse_flush(struct context *ctx, const struct token *token,
60032bfe3f2eSlogwang 	    const char *str, unsigned int len,
60042bfe3f2eSlogwang 	    void *buf, unsigned int size)
60052bfe3f2eSlogwang {
60062bfe3f2eSlogwang 	struct buffer *out = buf;
60072bfe3f2eSlogwang 
60082bfe3f2eSlogwang 	/* Token name must match. */
60092bfe3f2eSlogwang 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
60102bfe3f2eSlogwang 		return -1;
60112bfe3f2eSlogwang 	/* Nothing else to do if there is no buffer. */
60122bfe3f2eSlogwang 	if (!out)
60132bfe3f2eSlogwang 		return len;
60142bfe3f2eSlogwang 	if (!out->command) {
60152bfe3f2eSlogwang 		if (ctx->curr != FLUSH)
60162bfe3f2eSlogwang 			return -1;
60172bfe3f2eSlogwang 		if (sizeof(*out) > size)
60182bfe3f2eSlogwang 			return -1;
60192bfe3f2eSlogwang 		out->command = ctx->curr;
60202bfe3f2eSlogwang 		ctx->objdata = 0;
60212bfe3f2eSlogwang 		ctx->object = out;
60222bfe3f2eSlogwang 		ctx->objmask = NULL;
60232bfe3f2eSlogwang 	}
60242bfe3f2eSlogwang 	return len;
60252bfe3f2eSlogwang }
60262bfe3f2eSlogwang 
6027*2d9fd380Sjfb8856606 /** Parse tokens for dump command. */
6028*2d9fd380Sjfb8856606 static int
parse_dump(struct context * ctx,const struct token * token,const char * str,unsigned int len,void * buf,unsigned int size)6029*2d9fd380Sjfb8856606 parse_dump(struct context *ctx, const struct token *token,
6030*2d9fd380Sjfb8856606 	    const char *str, unsigned int len,
6031*2d9fd380Sjfb8856606 	    void *buf, unsigned int size)
6032*2d9fd380Sjfb8856606 {
6033*2d9fd380Sjfb8856606 	struct buffer *out = buf;
6034*2d9fd380Sjfb8856606 
6035*2d9fd380Sjfb8856606 	/* Token name must match. */
6036*2d9fd380Sjfb8856606 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
6037*2d9fd380Sjfb8856606 		return -1;
6038*2d9fd380Sjfb8856606 	/* Nothing else to do if there is no buffer. */
6039*2d9fd380Sjfb8856606 	if (!out)
6040*2d9fd380Sjfb8856606 		return len;
6041*2d9fd380Sjfb8856606 	if (!out->command) {
6042*2d9fd380Sjfb8856606 		if (ctx->curr != DUMP)
6043*2d9fd380Sjfb8856606 			return -1;
6044*2d9fd380Sjfb8856606 		if (sizeof(*out) > size)
6045*2d9fd380Sjfb8856606 			return -1;
6046*2d9fd380Sjfb8856606 		out->command = ctx->curr;
6047*2d9fd380Sjfb8856606 		ctx->objdata = 0;
6048*2d9fd380Sjfb8856606 		ctx->object = out;
6049*2d9fd380Sjfb8856606 		ctx->objmask = NULL;
6050*2d9fd380Sjfb8856606 	}
6051*2d9fd380Sjfb8856606 	return len;
6052*2d9fd380Sjfb8856606 }
6053*2d9fd380Sjfb8856606 
60542bfe3f2eSlogwang /** Parse tokens for query command. */
60552bfe3f2eSlogwang static int
parse_query(struct context * ctx,const struct token * token,const char * str,unsigned int len,void * buf,unsigned int size)60562bfe3f2eSlogwang parse_query(struct context *ctx, const struct token *token,
60572bfe3f2eSlogwang 	    const char *str, unsigned int len,
60582bfe3f2eSlogwang 	    void *buf, unsigned int size)
60592bfe3f2eSlogwang {
60602bfe3f2eSlogwang 	struct buffer *out = buf;
60612bfe3f2eSlogwang 
60622bfe3f2eSlogwang 	/* Token name must match. */
60632bfe3f2eSlogwang 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
60642bfe3f2eSlogwang 		return -1;
60652bfe3f2eSlogwang 	/* Nothing else to do if there is no buffer. */
60662bfe3f2eSlogwang 	if (!out)
60672bfe3f2eSlogwang 		return len;
60682bfe3f2eSlogwang 	if (!out->command) {
60692bfe3f2eSlogwang 		if (ctx->curr != QUERY)
60702bfe3f2eSlogwang 			return -1;
60712bfe3f2eSlogwang 		if (sizeof(*out) > size)
60722bfe3f2eSlogwang 			return -1;
60732bfe3f2eSlogwang 		out->command = ctx->curr;
60742bfe3f2eSlogwang 		ctx->objdata = 0;
60752bfe3f2eSlogwang 		ctx->object = out;
60762bfe3f2eSlogwang 		ctx->objmask = NULL;
60772bfe3f2eSlogwang 	}
60782bfe3f2eSlogwang 	return len;
60792bfe3f2eSlogwang }
60802bfe3f2eSlogwang 
60812bfe3f2eSlogwang /** Parse action names. */
60822bfe3f2eSlogwang static int
parse_action(struct context * ctx,const struct token * token,const char * str,unsigned int len,void * buf,unsigned int size)60832bfe3f2eSlogwang parse_action(struct context *ctx, const struct token *token,
60842bfe3f2eSlogwang 	     const char *str, unsigned int len,
60852bfe3f2eSlogwang 	     void *buf, unsigned int size)
60862bfe3f2eSlogwang {
60872bfe3f2eSlogwang 	struct buffer *out = buf;
60882bfe3f2eSlogwang 	const struct arg *arg = pop_args(ctx);
60892bfe3f2eSlogwang 	unsigned int i;
60902bfe3f2eSlogwang 
60912bfe3f2eSlogwang 	(void)size;
60922bfe3f2eSlogwang 	/* Argument is expected. */
60932bfe3f2eSlogwang 	if (!arg)
60942bfe3f2eSlogwang 		return -1;
60952bfe3f2eSlogwang 	/* Parse action name. */
60962bfe3f2eSlogwang 	for (i = 0; next_action[i]; ++i) {
60972bfe3f2eSlogwang 		const struct parse_action_priv *priv;
60982bfe3f2eSlogwang 
60992bfe3f2eSlogwang 		token = &token_list[next_action[i]];
61002bfe3f2eSlogwang 		if (strcmp_partial(token->name, str, len))
61012bfe3f2eSlogwang 			continue;
61022bfe3f2eSlogwang 		priv = token->priv;
61032bfe3f2eSlogwang 		if (!priv)
61042bfe3f2eSlogwang 			goto error;
61052bfe3f2eSlogwang 		if (out)
61062bfe3f2eSlogwang 			memcpy((uint8_t *)ctx->object + arg->offset,
61072bfe3f2eSlogwang 			       &priv->type,
61082bfe3f2eSlogwang 			       arg->size);
61092bfe3f2eSlogwang 		return len;
61102bfe3f2eSlogwang 	}
61112bfe3f2eSlogwang error:
61122bfe3f2eSlogwang 	push_args(ctx, arg);
61132bfe3f2eSlogwang 	return -1;
61142bfe3f2eSlogwang }
61152bfe3f2eSlogwang 
61162bfe3f2eSlogwang /** Parse tokens for list command. */
61172bfe3f2eSlogwang static int
parse_list(struct context * ctx,const struct token * token,const char * str,unsigned int len,void * buf,unsigned int size)61182bfe3f2eSlogwang parse_list(struct context *ctx, const struct token *token,
61192bfe3f2eSlogwang 	   const char *str, unsigned int len,
61202bfe3f2eSlogwang 	   void *buf, unsigned int size)
61212bfe3f2eSlogwang {
61222bfe3f2eSlogwang 	struct buffer *out = buf;
61232bfe3f2eSlogwang 
61242bfe3f2eSlogwang 	/* Token name must match. */
61252bfe3f2eSlogwang 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
61262bfe3f2eSlogwang 		return -1;
61272bfe3f2eSlogwang 	/* Nothing else to do if there is no buffer. */
61282bfe3f2eSlogwang 	if (!out)
61292bfe3f2eSlogwang 		return len;
61302bfe3f2eSlogwang 	if (!out->command) {
61312bfe3f2eSlogwang 		if (ctx->curr != LIST)
61322bfe3f2eSlogwang 			return -1;
61332bfe3f2eSlogwang 		if (sizeof(*out) > size)
61342bfe3f2eSlogwang 			return -1;
61352bfe3f2eSlogwang 		out->command = ctx->curr;
61362bfe3f2eSlogwang 		ctx->objdata = 0;
61372bfe3f2eSlogwang 		ctx->object = out;
61382bfe3f2eSlogwang 		ctx->objmask = NULL;
61392bfe3f2eSlogwang 		out->args.list.group =
61402bfe3f2eSlogwang 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
61412bfe3f2eSlogwang 					       sizeof(double));
61422bfe3f2eSlogwang 		return len;
61432bfe3f2eSlogwang 	}
61442bfe3f2eSlogwang 	if (((uint8_t *)(out->args.list.group + out->args.list.group_n) +
61452bfe3f2eSlogwang 	     sizeof(*out->args.list.group)) > (uint8_t *)out + size)
61462bfe3f2eSlogwang 		return -1;
61472bfe3f2eSlogwang 	ctx->objdata = 0;
61482bfe3f2eSlogwang 	ctx->object = out->args.list.group + out->args.list.group_n++;
61492bfe3f2eSlogwang 	ctx->objmask = NULL;
61502bfe3f2eSlogwang 	return len;
61512bfe3f2eSlogwang }
61522bfe3f2eSlogwang 
6153*2d9fd380Sjfb8856606 /** Parse tokens for list all aged flows command. */
6154*2d9fd380Sjfb8856606 static int
parse_aged(struct context * ctx,const struct token * token,const char * str,unsigned int len,void * buf,unsigned int size)6155*2d9fd380Sjfb8856606 parse_aged(struct context *ctx, const struct token *token,
6156*2d9fd380Sjfb8856606 	   const char *str, unsigned int len,
6157*2d9fd380Sjfb8856606 	   void *buf, unsigned int size)
6158*2d9fd380Sjfb8856606 {
6159*2d9fd380Sjfb8856606 	struct buffer *out = buf;
6160*2d9fd380Sjfb8856606 
6161*2d9fd380Sjfb8856606 	/* Token name must match. */
6162*2d9fd380Sjfb8856606 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
6163*2d9fd380Sjfb8856606 		return -1;
6164*2d9fd380Sjfb8856606 	/* Nothing else to do if there is no buffer. */
6165*2d9fd380Sjfb8856606 	if (!out)
6166*2d9fd380Sjfb8856606 		return len;
6167*2d9fd380Sjfb8856606 	if (!out->command) {
6168*2d9fd380Sjfb8856606 		if (ctx->curr != AGED)
6169*2d9fd380Sjfb8856606 			return -1;
6170*2d9fd380Sjfb8856606 		if (sizeof(*out) > size)
6171*2d9fd380Sjfb8856606 			return -1;
6172*2d9fd380Sjfb8856606 		out->command = ctx->curr;
6173*2d9fd380Sjfb8856606 		ctx->objdata = 0;
6174*2d9fd380Sjfb8856606 		ctx->object = out;
6175*2d9fd380Sjfb8856606 		ctx->objmask = NULL;
6176*2d9fd380Sjfb8856606 	}
6177*2d9fd380Sjfb8856606 	if (ctx->curr == AGED_DESTROY)
6178*2d9fd380Sjfb8856606 		out->args.aged.destroy = 1;
6179*2d9fd380Sjfb8856606 	return len;
6180*2d9fd380Sjfb8856606 }
6181*2d9fd380Sjfb8856606 
61822bfe3f2eSlogwang /** Parse tokens for isolate command. */
61832bfe3f2eSlogwang static int
parse_isolate(struct context * ctx,const struct token * token,const char * str,unsigned int len,void * buf,unsigned int size)61842bfe3f2eSlogwang parse_isolate(struct context *ctx, const struct token *token,
61852bfe3f2eSlogwang 	      const char *str, unsigned int len,
61862bfe3f2eSlogwang 	      void *buf, unsigned int size)
61872bfe3f2eSlogwang {
61882bfe3f2eSlogwang 	struct buffer *out = buf;
61892bfe3f2eSlogwang 
61902bfe3f2eSlogwang 	/* Token name must match. */
61912bfe3f2eSlogwang 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
61922bfe3f2eSlogwang 		return -1;
61932bfe3f2eSlogwang 	/* Nothing else to do if there is no buffer. */
61942bfe3f2eSlogwang 	if (!out)
61952bfe3f2eSlogwang 		return len;
61962bfe3f2eSlogwang 	if (!out->command) {
61972bfe3f2eSlogwang 		if (ctx->curr != ISOLATE)
61982bfe3f2eSlogwang 			return -1;
61992bfe3f2eSlogwang 		if (sizeof(*out) > size)
62002bfe3f2eSlogwang 			return -1;
62012bfe3f2eSlogwang 		out->command = ctx->curr;
62022bfe3f2eSlogwang 		ctx->objdata = 0;
62032bfe3f2eSlogwang 		ctx->object = out;
62042bfe3f2eSlogwang 		ctx->objmask = NULL;
62052bfe3f2eSlogwang 	}
62062bfe3f2eSlogwang 	return len;
62072bfe3f2eSlogwang }
62082bfe3f2eSlogwang 
6209*2d9fd380Sjfb8856606 static int
parse_tunnel(struct context * ctx,const struct token * token,const char * str,unsigned int len,void * buf,unsigned int size)6210*2d9fd380Sjfb8856606 parse_tunnel(struct context *ctx, const struct token *token,
6211*2d9fd380Sjfb8856606 	     const char *str, unsigned int len,
6212*2d9fd380Sjfb8856606 	     void *buf, unsigned int size)
6213*2d9fd380Sjfb8856606 {
6214*2d9fd380Sjfb8856606 	struct buffer *out = buf;
6215*2d9fd380Sjfb8856606 
6216*2d9fd380Sjfb8856606 	/* Token name must match. */
6217*2d9fd380Sjfb8856606 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
6218*2d9fd380Sjfb8856606 		return -1;
6219*2d9fd380Sjfb8856606 	/* Nothing else to do if there is no buffer. */
6220*2d9fd380Sjfb8856606 	if (!out)
6221*2d9fd380Sjfb8856606 		return len;
6222*2d9fd380Sjfb8856606 	if (!out->command) {
6223*2d9fd380Sjfb8856606 		if (ctx->curr != TUNNEL)
6224*2d9fd380Sjfb8856606 			return -1;
6225*2d9fd380Sjfb8856606 		if (sizeof(*out) > size)
6226*2d9fd380Sjfb8856606 			return -1;
6227*2d9fd380Sjfb8856606 		out->command = ctx->curr;
6228*2d9fd380Sjfb8856606 		ctx->objdata = 0;
6229*2d9fd380Sjfb8856606 		ctx->object = out;
6230*2d9fd380Sjfb8856606 		ctx->objmask = NULL;
6231*2d9fd380Sjfb8856606 	} else {
6232*2d9fd380Sjfb8856606 		switch (ctx->curr) {
6233*2d9fd380Sjfb8856606 		default:
6234*2d9fd380Sjfb8856606 			break;
6235*2d9fd380Sjfb8856606 		case TUNNEL_CREATE:
6236*2d9fd380Sjfb8856606 		case TUNNEL_DESTROY:
6237*2d9fd380Sjfb8856606 		case TUNNEL_LIST:
6238*2d9fd380Sjfb8856606 			out->command = ctx->curr;
6239*2d9fd380Sjfb8856606 			break;
6240*2d9fd380Sjfb8856606 		case TUNNEL_CREATE_TYPE:
6241*2d9fd380Sjfb8856606 		case TUNNEL_DESTROY_ID:
6242*2d9fd380Sjfb8856606 			ctx->object = &out->args.vc.tunnel_ops;
6243*2d9fd380Sjfb8856606 			break;
6244*2d9fd380Sjfb8856606 		}
6245*2d9fd380Sjfb8856606 	}
6246*2d9fd380Sjfb8856606 
6247*2d9fd380Sjfb8856606 	return len;
6248*2d9fd380Sjfb8856606 }
6249*2d9fd380Sjfb8856606 
62502bfe3f2eSlogwang /**
62512bfe3f2eSlogwang  * Parse signed/unsigned integers 8 to 64-bit long.
62522bfe3f2eSlogwang  *
62532bfe3f2eSlogwang  * Last argument (ctx->args) is retrieved to determine integer type and
62542bfe3f2eSlogwang  * storage location.
62552bfe3f2eSlogwang  */
62562bfe3f2eSlogwang static int
parse_int(struct context * ctx,const struct token * token,const char * str,unsigned int len,void * buf,unsigned int size)62572bfe3f2eSlogwang parse_int(struct context *ctx, const struct token *token,
62582bfe3f2eSlogwang 	  const char *str, unsigned int len,
62592bfe3f2eSlogwang 	  void *buf, unsigned int size)
62602bfe3f2eSlogwang {
62612bfe3f2eSlogwang 	const struct arg *arg = pop_args(ctx);
62622bfe3f2eSlogwang 	uintmax_t u;
62632bfe3f2eSlogwang 	char *end;
62642bfe3f2eSlogwang 
62652bfe3f2eSlogwang 	(void)token;
62662bfe3f2eSlogwang 	/* Argument is expected. */
62672bfe3f2eSlogwang 	if (!arg)
62682bfe3f2eSlogwang 		return -1;
62692bfe3f2eSlogwang 	errno = 0;
62702bfe3f2eSlogwang 	u = arg->sign ?
62712bfe3f2eSlogwang 		(uintmax_t)strtoimax(str, &end, 0) :
62722bfe3f2eSlogwang 		strtoumax(str, &end, 0);
62732bfe3f2eSlogwang 	if (errno || (size_t)(end - str) != len)
62742bfe3f2eSlogwang 		goto error;
6275d30ea906Sjfb8856606 	if (arg->bounded &&
6276d30ea906Sjfb8856606 	    ((arg->sign && ((intmax_t)u < (intmax_t)arg->min ||
6277d30ea906Sjfb8856606 			    (intmax_t)u > (intmax_t)arg->max)) ||
6278d30ea906Sjfb8856606 	     (!arg->sign && (u < arg->min || u > arg->max))))
6279d30ea906Sjfb8856606 		goto error;
62802bfe3f2eSlogwang 	if (!ctx->object)
62812bfe3f2eSlogwang 		return len;
62822bfe3f2eSlogwang 	if (arg->mask) {
62832bfe3f2eSlogwang 		if (!arg_entry_bf_fill(ctx->object, u, arg) ||
62842bfe3f2eSlogwang 		    !arg_entry_bf_fill(ctx->objmask, -1, arg))
62852bfe3f2eSlogwang 			goto error;
62862bfe3f2eSlogwang 		return len;
62872bfe3f2eSlogwang 	}
62882bfe3f2eSlogwang 	buf = (uint8_t *)ctx->object + arg->offset;
62892bfe3f2eSlogwang 	size = arg->size;
62904418919fSjohnjiang 	if (u > RTE_LEN2MASK(size * CHAR_BIT, uint64_t))
62914418919fSjohnjiang 		return -1;
62922bfe3f2eSlogwang objmask:
62932bfe3f2eSlogwang 	switch (size) {
62942bfe3f2eSlogwang 	case sizeof(uint8_t):
62952bfe3f2eSlogwang 		*(uint8_t *)buf = u;
62962bfe3f2eSlogwang 		break;
62972bfe3f2eSlogwang 	case sizeof(uint16_t):
62982bfe3f2eSlogwang 		*(uint16_t *)buf = arg->hton ? rte_cpu_to_be_16(u) : u;
62992bfe3f2eSlogwang 		break;
63002bfe3f2eSlogwang 	case sizeof(uint8_t [3]):
63012bfe3f2eSlogwang #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
63022bfe3f2eSlogwang 		if (!arg->hton) {
63032bfe3f2eSlogwang 			((uint8_t *)buf)[0] = u;
63042bfe3f2eSlogwang 			((uint8_t *)buf)[1] = u >> 8;
63052bfe3f2eSlogwang 			((uint8_t *)buf)[2] = u >> 16;
63062bfe3f2eSlogwang 			break;
63072bfe3f2eSlogwang 		}
63082bfe3f2eSlogwang #endif
63092bfe3f2eSlogwang 		((uint8_t *)buf)[0] = u >> 16;
63102bfe3f2eSlogwang 		((uint8_t *)buf)[1] = u >> 8;
63112bfe3f2eSlogwang 		((uint8_t *)buf)[2] = u;
63122bfe3f2eSlogwang 		break;
63132bfe3f2eSlogwang 	case sizeof(uint32_t):
63142bfe3f2eSlogwang 		*(uint32_t *)buf = arg->hton ? rte_cpu_to_be_32(u) : u;
63152bfe3f2eSlogwang 		break;
63162bfe3f2eSlogwang 	case sizeof(uint64_t):
63172bfe3f2eSlogwang 		*(uint64_t *)buf = arg->hton ? rte_cpu_to_be_64(u) : u;
63182bfe3f2eSlogwang 		break;
63192bfe3f2eSlogwang 	default:
63202bfe3f2eSlogwang 		goto error;
63212bfe3f2eSlogwang 	}
63222bfe3f2eSlogwang 	if (ctx->objmask && buf != (uint8_t *)ctx->objmask + arg->offset) {
63232bfe3f2eSlogwang 		u = -1;
63242bfe3f2eSlogwang 		buf = (uint8_t *)ctx->objmask + arg->offset;
63252bfe3f2eSlogwang 		goto objmask;
63262bfe3f2eSlogwang 	}
63272bfe3f2eSlogwang 	return len;
63282bfe3f2eSlogwang error:
63292bfe3f2eSlogwang 	push_args(ctx, arg);
63302bfe3f2eSlogwang 	return -1;
63312bfe3f2eSlogwang }
63322bfe3f2eSlogwang 
63332bfe3f2eSlogwang /**
63342bfe3f2eSlogwang  * Parse a string.
63352bfe3f2eSlogwang  *
6336d30ea906Sjfb8856606  * Three arguments (ctx->args) are retrieved from the stack to store data,
6337d30ea906Sjfb8856606  * its actual length and address (in that order).
63382bfe3f2eSlogwang  */
63392bfe3f2eSlogwang static int
parse_string(struct context * ctx,const struct token * token,const char * str,unsigned int len,void * buf,unsigned int size)63402bfe3f2eSlogwang parse_string(struct context *ctx, const struct token *token,
63412bfe3f2eSlogwang 	     const char *str, unsigned int len,
63422bfe3f2eSlogwang 	     void *buf, unsigned int size)
63432bfe3f2eSlogwang {
63442bfe3f2eSlogwang 	const struct arg *arg_data = pop_args(ctx);
63452bfe3f2eSlogwang 	const struct arg *arg_len = pop_args(ctx);
6346d30ea906Sjfb8856606 	const struct arg *arg_addr = pop_args(ctx);
63472bfe3f2eSlogwang 	char tmp[16]; /* Ought to be enough. */
63482bfe3f2eSlogwang 	int ret;
63492bfe3f2eSlogwang 
63502bfe3f2eSlogwang 	/* Arguments are expected. */
63512bfe3f2eSlogwang 	if (!arg_data)
63522bfe3f2eSlogwang 		return -1;
63532bfe3f2eSlogwang 	if (!arg_len) {
63542bfe3f2eSlogwang 		push_args(ctx, arg_data);
63552bfe3f2eSlogwang 		return -1;
63562bfe3f2eSlogwang 	}
6357d30ea906Sjfb8856606 	if (!arg_addr) {
6358d30ea906Sjfb8856606 		push_args(ctx, arg_len);
6359d30ea906Sjfb8856606 		push_args(ctx, arg_data);
6360d30ea906Sjfb8856606 		return -1;
6361d30ea906Sjfb8856606 	}
63622bfe3f2eSlogwang 	size = arg_data->size;
63632bfe3f2eSlogwang 	/* Bit-mask fill is not supported. */
63642bfe3f2eSlogwang 	if (arg_data->mask || size < len)
63652bfe3f2eSlogwang 		goto error;
63662bfe3f2eSlogwang 	if (!ctx->object)
63672bfe3f2eSlogwang 		return len;
63682bfe3f2eSlogwang 	/* Let parse_int() fill length information first. */
63692bfe3f2eSlogwang 	ret = snprintf(tmp, sizeof(tmp), "%u", len);
63702bfe3f2eSlogwang 	if (ret < 0)
63712bfe3f2eSlogwang 		goto error;
63722bfe3f2eSlogwang 	push_args(ctx, arg_len);
63732bfe3f2eSlogwang 	ret = parse_int(ctx, token, tmp, ret, NULL, 0);
63742bfe3f2eSlogwang 	if (ret < 0) {
63752bfe3f2eSlogwang 		pop_args(ctx);
63762bfe3f2eSlogwang 		goto error;
63772bfe3f2eSlogwang 	}
63782bfe3f2eSlogwang 	buf = (uint8_t *)ctx->object + arg_data->offset;
63792bfe3f2eSlogwang 	/* Output buffer is not necessarily NUL-terminated. */
63802bfe3f2eSlogwang 	memcpy(buf, str, len);
6381d30ea906Sjfb8856606 	memset((uint8_t *)buf + len, 0x00, size - len);
63822bfe3f2eSlogwang 	if (ctx->objmask)
63832bfe3f2eSlogwang 		memset((uint8_t *)ctx->objmask + arg_data->offset, 0xff, len);
6384d30ea906Sjfb8856606 	/* Save address if requested. */
6385d30ea906Sjfb8856606 	if (arg_addr->size) {
6386d30ea906Sjfb8856606 		memcpy((uint8_t *)ctx->object + arg_addr->offset,
6387d30ea906Sjfb8856606 		       (void *[]){
6388d30ea906Sjfb8856606 			(uint8_t *)ctx->object + arg_data->offset
6389d30ea906Sjfb8856606 		       },
6390d30ea906Sjfb8856606 		       arg_addr->size);
6391d30ea906Sjfb8856606 		if (ctx->objmask)
6392d30ea906Sjfb8856606 			memcpy((uint8_t *)ctx->objmask + arg_addr->offset,
6393d30ea906Sjfb8856606 			       (void *[]){
6394d30ea906Sjfb8856606 				(uint8_t *)ctx->objmask + arg_data->offset
6395d30ea906Sjfb8856606 			       },
6396d30ea906Sjfb8856606 			       arg_addr->size);
6397d30ea906Sjfb8856606 	}
63982bfe3f2eSlogwang 	return len;
63992bfe3f2eSlogwang error:
6400d30ea906Sjfb8856606 	push_args(ctx, arg_addr);
64012bfe3f2eSlogwang 	push_args(ctx, arg_len);
64022bfe3f2eSlogwang 	push_args(ctx, arg_data);
64032bfe3f2eSlogwang 	return -1;
64042bfe3f2eSlogwang }
64052bfe3f2eSlogwang 
64061646932aSjfb8856606 static int
parse_hex_string(const char * src,uint8_t * dst,uint32_t * size)64071646932aSjfb8856606 parse_hex_string(const char *src, uint8_t *dst, uint32_t *size)
64081646932aSjfb8856606 {
64091646932aSjfb8856606 	char *c = NULL;
64101646932aSjfb8856606 	uint32_t i, len;
64111646932aSjfb8856606 	char tmp[3];
64121646932aSjfb8856606 
64131646932aSjfb8856606 	/* Check input parameters */
64141646932aSjfb8856606 	if ((src == NULL) ||
64151646932aSjfb8856606 		(dst == NULL) ||
64161646932aSjfb8856606 		(size == NULL) ||
64171646932aSjfb8856606 		(*size == 0))
64181646932aSjfb8856606 		return -1;
64191646932aSjfb8856606 
64201646932aSjfb8856606 	/* Convert chars to bytes */
64211646932aSjfb8856606 	for (i = 0, len = 0; i < *size; i += 2) {
64221646932aSjfb8856606 		snprintf(tmp, 3, "%s", src + i);
64231646932aSjfb8856606 		dst[len++] = strtoul(tmp, &c, 16);
64241646932aSjfb8856606 		if (*c != 0) {
64251646932aSjfb8856606 			len--;
64261646932aSjfb8856606 			dst[len] = 0;
64271646932aSjfb8856606 			*size = len;
64281646932aSjfb8856606 			return -1;
64291646932aSjfb8856606 		}
64301646932aSjfb8856606 	}
64311646932aSjfb8856606 	dst[len] = 0;
64321646932aSjfb8856606 	*size = len;
64331646932aSjfb8856606 
64341646932aSjfb8856606 	return 0;
64351646932aSjfb8856606 }
64361646932aSjfb8856606 
64371646932aSjfb8856606 static int
parse_hex(struct context * ctx,const struct token * token,const char * str,unsigned int len,void * buf,unsigned int size)64381646932aSjfb8856606 parse_hex(struct context *ctx, const struct token *token,
64391646932aSjfb8856606 		const char *str, unsigned int len,
64401646932aSjfb8856606 		void *buf, unsigned int size)
64411646932aSjfb8856606 {
64421646932aSjfb8856606 	const struct arg *arg_data = pop_args(ctx);
64431646932aSjfb8856606 	const struct arg *arg_len = pop_args(ctx);
64441646932aSjfb8856606 	const struct arg *arg_addr = pop_args(ctx);
64451646932aSjfb8856606 	char tmp[16]; /* Ought to be enough. */
64461646932aSjfb8856606 	int ret;
64471646932aSjfb8856606 	unsigned int hexlen = len;
64481646932aSjfb8856606 	unsigned int length = 256;
64491646932aSjfb8856606 	uint8_t hex_tmp[length];
64501646932aSjfb8856606 
64511646932aSjfb8856606 	/* Arguments are expected. */
64521646932aSjfb8856606 	if (!arg_data)
64531646932aSjfb8856606 		return -1;
64541646932aSjfb8856606 	if (!arg_len) {
64551646932aSjfb8856606 		push_args(ctx, arg_data);
64561646932aSjfb8856606 		return -1;
64571646932aSjfb8856606 	}
64581646932aSjfb8856606 	if (!arg_addr) {
64591646932aSjfb8856606 		push_args(ctx, arg_len);
64601646932aSjfb8856606 		push_args(ctx, arg_data);
64611646932aSjfb8856606 		return -1;
64621646932aSjfb8856606 	}
64631646932aSjfb8856606 	size = arg_data->size;
64641646932aSjfb8856606 	/* Bit-mask fill is not supported. */
64651646932aSjfb8856606 	if (arg_data->mask)
64661646932aSjfb8856606 		goto error;
64671646932aSjfb8856606 	if (!ctx->object)
64681646932aSjfb8856606 		return len;
64691646932aSjfb8856606 
64701646932aSjfb8856606 	/* translate bytes string to array. */
64711646932aSjfb8856606 	if (str[0] == '0' && ((str[1] == 'x') ||
64721646932aSjfb8856606 			(str[1] == 'X'))) {
64731646932aSjfb8856606 		str += 2;
64741646932aSjfb8856606 		hexlen -= 2;
64751646932aSjfb8856606 	}
64761646932aSjfb8856606 	if (hexlen > length)
64771646932aSjfb8856606 		return -1;
64781646932aSjfb8856606 	ret = parse_hex_string(str, hex_tmp, &hexlen);
64791646932aSjfb8856606 	if (ret < 0)
64801646932aSjfb8856606 		goto error;
64811646932aSjfb8856606 	/* Let parse_int() fill length information first. */
64821646932aSjfb8856606 	ret = snprintf(tmp, sizeof(tmp), "%u", hexlen);
64831646932aSjfb8856606 	if (ret < 0)
64841646932aSjfb8856606 		goto error;
64851646932aSjfb8856606 	push_args(ctx, arg_len);
64861646932aSjfb8856606 	ret = parse_int(ctx, token, tmp, ret, NULL, 0);
64871646932aSjfb8856606 	if (ret < 0) {
64881646932aSjfb8856606 		pop_args(ctx);
64891646932aSjfb8856606 		goto error;
64901646932aSjfb8856606 	}
64911646932aSjfb8856606 	buf = (uint8_t *)ctx->object + arg_data->offset;
64921646932aSjfb8856606 	/* Output buffer is not necessarily NUL-terminated. */
64931646932aSjfb8856606 	memcpy(buf, hex_tmp, hexlen);
64941646932aSjfb8856606 	memset((uint8_t *)buf + hexlen, 0x00, size - hexlen);
64951646932aSjfb8856606 	if (ctx->objmask)
64961646932aSjfb8856606 		memset((uint8_t *)ctx->objmask + arg_data->offset,
64971646932aSjfb8856606 					0xff, hexlen);
64981646932aSjfb8856606 	/* Save address if requested. */
64991646932aSjfb8856606 	if (arg_addr->size) {
65001646932aSjfb8856606 		memcpy((uint8_t *)ctx->object + arg_addr->offset,
65011646932aSjfb8856606 		       (void *[]){
65021646932aSjfb8856606 			(uint8_t *)ctx->object + arg_data->offset
65031646932aSjfb8856606 		       },
65041646932aSjfb8856606 		       arg_addr->size);
65051646932aSjfb8856606 		if (ctx->objmask)
65061646932aSjfb8856606 			memcpy((uint8_t *)ctx->objmask + arg_addr->offset,
65071646932aSjfb8856606 			       (void *[]){
65081646932aSjfb8856606 				(uint8_t *)ctx->objmask + arg_data->offset
65091646932aSjfb8856606 			       },
65101646932aSjfb8856606 			       arg_addr->size);
65111646932aSjfb8856606 	}
65121646932aSjfb8856606 	return len;
65131646932aSjfb8856606 error:
65141646932aSjfb8856606 	push_args(ctx, arg_addr);
65151646932aSjfb8856606 	push_args(ctx, arg_len);
65161646932aSjfb8856606 	push_args(ctx, arg_data);
65171646932aSjfb8856606 	return -1;
65181646932aSjfb8856606 
65191646932aSjfb8856606 }
65201646932aSjfb8856606 
65212bfe3f2eSlogwang /**
6522*2d9fd380Sjfb8856606  * Parse a zero-ended string.
6523*2d9fd380Sjfb8856606  */
6524*2d9fd380Sjfb8856606 static int
parse_string0(struct context * ctx,const struct token * token __rte_unused,const char * str,unsigned int len,void * buf,unsigned int size)6525*2d9fd380Sjfb8856606 parse_string0(struct context *ctx, const struct token *token __rte_unused,
6526*2d9fd380Sjfb8856606 	     const char *str, unsigned int len,
6527*2d9fd380Sjfb8856606 	     void *buf, unsigned int size)
6528*2d9fd380Sjfb8856606 {
6529*2d9fd380Sjfb8856606 	const struct arg *arg_data = pop_args(ctx);
6530*2d9fd380Sjfb8856606 
6531*2d9fd380Sjfb8856606 	/* Arguments are expected. */
6532*2d9fd380Sjfb8856606 	if (!arg_data)
6533*2d9fd380Sjfb8856606 		return -1;
6534*2d9fd380Sjfb8856606 	size = arg_data->size;
6535*2d9fd380Sjfb8856606 	/* Bit-mask fill is not supported. */
6536*2d9fd380Sjfb8856606 	if (arg_data->mask || size < len + 1)
6537*2d9fd380Sjfb8856606 		goto error;
6538*2d9fd380Sjfb8856606 	if (!ctx->object)
6539*2d9fd380Sjfb8856606 		return len;
6540*2d9fd380Sjfb8856606 	buf = (uint8_t *)ctx->object + arg_data->offset;
6541*2d9fd380Sjfb8856606 	strncpy(buf, str, len);
6542*2d9fd380Sjfb8856606 	if (ctx->objmask)
6543*2d9fd380Sjfb8856606 		memset((uint8_t *)ctx->objmask + arg_data->offset, 0xff, len);
6544*2d9fd380Sjfb8856606 	return len;
6545*2d9fd380Sjfb8856606 error:
6546*2d9fd380Sjfb8856606 	push_args(ctx, arg_data);
6547*2d9fd380Sjfb8856606 	return -1;
6548*2d9fd380Sjfb8856606 }
6549*2d9fd380Sjfb8856606 
6550*2d9fd380Sjfb8856606 /**
65512bfe3f2eSlogwang  * Parse a MAC address.
65522bfe3f2eSlogwang  *
65532bfe3f2eSlogwang  * Last argument (ctx->args) is retrieved to determine storage size and
65542bfe3f2eSlogwang  * location.
65552bfe3f2eSlogwang  */
65562bfe3f2eSlogwang static int
parse_mac_addr(struct context * ctx,const struct token * token,const char * str,unsigned int len,void * buf,unsigned int size)65572bfe3f2eSlogwang parse_mac_addr(struct context *ctx, const struct token *token,
65582bfe3f2eSlogwang 	       const char *str, unsigned int len,
65592bfe3f2eSlogwang 	       void *buf, unsigned int size)
65602bfe3f2eSlogwang {
65612bfe3f2eSlogwang 	const struct arg *arg = pop_args(ctx);
65624418919fSjohnjiang 	struct rte_ether_addr tmp;
65632bfe3f2eSlogwang 	int ret;
65642bfe3f2eSlogwang 
65652bfe3f2eSlogwang 	(void)token;
65662bfe3f2eSlogwang 	/* Argument is expected. */
65672bfe3f2eSlogwang 	if (!arg)
65682bfe3f2eSlogwang 		return -1;
65692bfe3f2eSlogwang 	size = arg->size;
65702bfe3f2eSlogwang 	/* Bit-mask fill is not supported. */
65712bfe3f2eSlogwang 	if (arg->mask || size != sizeof(tmp))
65722bfe3f2eSlogwang 		goto error;
65732bfe3f2eSlogwang 	/* Only network endian is supported. */
65742bfe3f2eSlogwang 	if (!arg->hton)
65752bfe3f2eSlogwang 		goto error;
65762bfe3f2eSlogwang 	ret = cmdline_parse_etheraddr(NULL, str, &tmp, size);
65772bfe3f2eSlogwang 	if (ret < 0 || (unsigned int)ret != len)
65782bfe3f2eSlogwang 		goto error;
65792bfe3f2eSlogwang 	if (!ctx->object)
65802bfe3f2eSlogwang 		return len;
65812bfe3f2eSlogwang 	buf = (uint8_t *)ctx->object + arg->offset;
65822bfe3f2eSlogwang 	memcpy(buf, &tmp, size);
65832bfe3f2eSlogwang 	if (ctx->objmask)
65842bfe3f2eSlogwang 		memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
65852bfe3f2eSlogwang 	return len;
65862bfe3f2eSlogwang error:
65872bfe3f2eSlogwang 	push_args(ctx, arg);
65882bfe3f2eSlogwang 	return -1;
65892bfe3f2eSlogwang }
65902bfe3f2eSlogwang 
65912bfe3f2eSlogwang /**
65922bfe3f2eSlogwang  * Parse an IPv4 address.
65932bfe3f2eSlogwang  *
65942bfe3f2eSlogwang  * Last argument (ctx->args) is retrieved to determine storage size and
65952bfe3f2eSlogwang  * location.
65962bfe3f2eSlogwang  */
65972bfe3f2eSlogwang static int
parse_ipv4_addr(struct context * ctx,const struct token * token,const char * str,unsigned int len,void * buf,unsigned int size)65982bfe3f2eSlogwang parse_ipv4_addr(struct context *ctx, const struct token *token,
65992bfe3f2eSlogwang 		const char *str, unsigned int len,
66002bfe3f2eSlogwang 		void *buf, unsigned int size)
66012bfe3f2eSlogwang {
66022bfe3f2eSlogwang 	const struct arg *arg = pop_args(ctx);
66032bfe3f2eSlogwang 	char str2[len + 1];
66042bfe3f2eSlogwang 	struct in_addr tmp;
66052bfe3f2eSlogwang 	int ret;
66062bfe3f2eSlogwang 
66072bfe3f2eSlogwang 	/* Argument is expected. */
66082bfe3f2eSlogwang 	if (!arg)
66092bfe3f2eSlogwang 		return -1;
66102bfe3f2eSlogwang 	size = arg->size;
66112bfe3f2eSlogwang 	/* Bit-mask fill is not supported. */
66122bfe3f2eSlogwang 	if (arg->mask || size != sizeof(tmp))
66132bfe3f2eSlogwang 		goto error;
66142bfe3f2eSlogwang 	/* Only network endian is supported. */
66152bfe3f2eSlogwang 	if (!arg->hton)
66162bfe3f2eSlogwang 		goto error;
66172bfe3f2eSlogwang 	memcpy(str2, str, len);
66182bfe3f2eSlogwang 	str2[len] = '\0';
66192bfe3f2eSlogwang 	ret = inet_pton(AF_INET, str2, &tmp);
66202bfe3f2eSlogwang 	if (ret != 1) {
66212bfe3f2eSlogwang 		/* Attempt integer parsing. */
66222bfe3f2eSlogwang 		push_args(ctx, arg);
66232bfe3f2eSlogwang 		return parse_int(ctx, token, str, len, buf, size);
66242bfe3f2eSlogwang 	}
66252bfe3f2eSlogwang 	if (!ctx->object)
66262bfe3f2eSlogwang 		return len;
66272bfe3f2eSlogwang 	buf = (uint8_t *)ctx->object + arg->offset;
66282bfe3f2eSlogwang 	memcpy(buf, &tmp, size);
66292bfe3f2eSlogwang 	if (ctx->objmask)
66302bfe3f2eSlogwang 		memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
66312bfe3f2eSlogwang 	return len;
66322bfe3f2eSlogwang error:
66332bfe3f2eSlogwang 	push_args(ctx, arg);
66342bfe3f2eSlogwang 	return -1;
66352bfe3f2eSlogwang }
66362bfe3f2eSlogwang 
66372bfe3f2eSlogwang /**
66382bfe3f2eSlogwang  * Parse an IPv6 address.
66392bfe3f2eSlogwang  *
66402bfe3f2eSlogwang  * Last argument (ctx->args) is retrieved to determine storage size and
66412bfe3f2eSlogwang  * location.
66422bfe3f2eSlogwang  */
66432bfe3f2eSlogwang static int
parse_ipv6_addr(struct context * ctx,const struct token * token,const char * str,unsigned int len,void * buf,unsigned int size)66442bfe3f2eSlogwang parse_ipv6_addr(struct context *ctx, const struct token *token,
66452bfe3f2eSlogwang 		const char *str, unsigned int len,
66462bfe3f2eSlogwang 		void *buf, unsigned int size)
66472bfe3f2eSlogwang {
66482bfe3f2eSlogwang 	const struct arg *arg = pop_args(ctx);
66492bfe3f2eSlogwang 	char str2[len + 1];
66502bfe3f2eSlogwang 	struct in6_addr tmp;
66512bfe3f2eSlogwang 	int ret;
66522bfe3f2eSlogwang 
66532bfe3f2eSlogwang 	(void)token;
66542bfe3f2eSlogwang 	/* Argument is expected. */
66552bfe3f2eSlogwang 	if (!arg)
66562bfe3f2eSlogwang 		return -1;
66572bfe3f2eSlogwang 	size = arg->size;
66582bfe3f2eSlogwang 	/* Bit-mask fill is not supported. */
66592bfe3f2eSlogwang 	if (arg->mask || size != sizeof(tmp))
66602bfe3f2eSlogwang 		goto error;
66612bfe3f2eSlogwang 	/* Only network endian is supported. */
66622bfe3f2eSlogwang 	if (!arg->hton)
66632bfe3f2eSlogwang 		goto error;
66642bfe3f2eSlogwang 	memcpy(str2, str, len);
66652bfe3f2eSlogwang 	str2[len] = '\0';
66662bfe3f2eSlogwang 	ret = inet_pton(AF_INET6, str2, &tmp);
66672bfe3f2eSlogwang 	if (ret != 1)
66682bfe3f2eSlogwang 		goto error;
66692bfe3f2eSlogwang 	if (!ctx->object)
66702bfe3f2eSlogwang 		return len;
66712bfe3f2eSlogwang 	buf = (uint8_t *)ctx->object + arg->offset;
66722bfe3f2eSlogwang 	memcpy(buf, &tmp, size);
66732bfe3f2eSlogwang 	if (ctx->objmask)
66742bfe3f2eSlogwang 		memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
66752bfe3f2eSlogwang 	return len;
66762bfe3f2eSlogwang error:
66772bfe3f2eSlogwang 	push_args(ctx, arg);
66782bfe3f2eSlogwang 	return -1;
66792bfe3f2eSlogwang }
66802bfe3f2eSlogwang 
66812bfe3f2eSlogwang /** Boolean values (even indices stand for false). */
66822bfe3f2eSlogwang static const char *const boolean_name[] = {
66832bfe3f2eSlogwang 	"0", "1",
66842bfe3f2eSlogwang 	"false", "true",
66852bfe3f2eSlogwang 	"no", "yes",
66862bfe3f2eSlogwang 	"N", "Y",
6687d30ea906Sjfb8856606 	"off", "on",
66882bfe3f2eSlogwang 	NULL,
66892bfe3f2eSlogwang };
66902bfe3f2eSlogwang 
66912bfe3f2eSlogwang /**
66922bfe3f2eSlogwang  * Parse a boolean value.
66932bfe3f2eSlogwang  *
66942bfe3f2eSlogwang  * Last argument (ctx->args) is retrieved to determine storage size and
66952bfe3f2eSlogwang  * location.
66962bfe3f2eSlogwang  */
66972bfe3f2eSlogwang static int
parse_boolean(struct context * ctx,const struct token * token,const char * str,unsigned int len,void * buf,unsigned int size)66982bfe3f2eSlogwang parse_boolean(struct context *ctx, const struct token *token,
66992bfe3f2eSlogwang 	      const char *str, unsigned int len,
67002bfe3f2eSlogwang 	      void *buf, unsigned int size)
67012bfe3f2eSlogwang {
67022bfe3f2eSlogwang 	const struct arg *arg = pop_args(ctx);
67032bfe3f2eSlogwang 	unsigned int i;
67042bfe3f2eSlogwang 	int ret;
67052bfe3f2eSlogwang 
67062bfe3f2eSlogwang 	/* Argument is expected. */
67072bfe3f2eSlogwang 	if (!arg)
67082bfe3f2eSlogwang 		return -1;
67092bfe3f2eSlogwang 	for (i = 0; boolean_name[i]; ++i)
67102bfe3f2eSlogwang 		if (!strcmp_partial(boolean_name[i], str, len))
67112bfe3f2eSlogwang 			break;
67122bfe3f2eSlogwang 	/* Process token as integer. */
67132bfe3f2eSlogwang 	if (boolean_name[i])
67142bfe3f2eSlogwang 		str = i & 1 ? "1" : "0";
67152bfe3f2eSlogwang 	push_args(ctx, arg);
67162bfe3f2eSlogwang 	ret = parse_int(ctx, token, str, strlen(str), buf, size);
67172bfe3f2eSlogwang 	return ret > 0 ? (int)len : ret;
67182bfe3f2eSlogwang }
67192bfe3f2eSlogwang 
67202bfe3f2eSlogwang /** Parse port and update context. */
67212bfe3f2eSlogwang static int
parse_port(struct context * ctx,const struct token * token,const char * str,unsigned int len,void * buf,unsigned int size)67222bfe3f2eSlogwang parse_port(struct context *ctx, const struct token *token,
67232bfe3f2eSlogwang 	   const char *str, unsigned int len,
67242bfe3f2eSlogwang 	   void *buf, unsigned int size)
67252bfe3f2eSlogwang {
67262bfe3f2eSlogwang 	struct buffer *out = &(struct buffer){ .port = 0 };
67272bfe3f2eSlogwang 	int ret;
67282bfe3f2eSlogwang 
67292bfe3f2eSlogwang 	if (buf)
67302bfe3f2eSlogwang 		out = buf;
67312bfe3f2eSlogwang 	else {
67322bfe3f2eSlogwang 		ctx->objdata = 0;
67332bfe3f2eSlogwang 		ctx->object = out;
67342bfe3f2eSlogwang 		ctx->objmask = NULL;
67352bfe3f2eSlogwang 		size = sizeof(*out);
67362bfe3f2eSlogwang 	}
67372bfe3f2eSlogwang 	ret = parse_int(ctx, token, str, len, out, size);
67382bfe3f2eSlogwang 	if (ret >= 0)
67392bfe3f2eSlogwang 		ctx->port = out->port;
67402bfe3f2eSlogwang 	if (!buf)
67412bfe3f2eSlogwang 		ctx->object = NULL;
67422bfe3f2eSlogwang 	return ret;
67432bfe3f2eSlogwang }
67442bfe3f2eSlogwang 
6745*2d9fd380Sjfb8856606 static int
parse_sa_id2ptr(struct context * ctx,const struct token * token,const char * str,unsigned int len,void * buf,unsigned int size)6746*2d9fd380Sjfb8856606 parse_sa_id2ptr(struct context *ctx, const struct token *token,
6747*2d9fd380Sjfb8856606 		const char *str, unsigned int len,
6748*2d9fd380Sjfb8856606 		void *buf, unsigned int size)
6749*2d9fd380Sjfb8856606 {
6750*2d9fd380Sjfb8856606 	struct rte_flow_action *action = ctx->object;
6751*2d9fd380Sjfb8856606 	uint32_t id;
6752*2d9fd380Sjfb8856606 	int ret;
6753*2d9fd380Sjfb8856606 
6754*2d9fd380Sjfb8856606 	(void)buf;
6755*2d9fd380Sjfb8856606 	(void)size;
6756*2d9fd380Sjfb8856606 	ctx->objdata = 0;
6757*2d9fd380Sjfb8856606 	ctx->object = &id;
6758*2d9fd380Sjfb8856606 	ctx->objmask = NULL;
6759*2d9fd380Sjfb8856606 	ret = parse_int(ctx, token, str, len, ctx->object, sizeof(id));
6760*2d9fd380Sjfb8856606 	ctx->object = action;
6761*2d9fd380Sjfb8856606 	if (ret != (int)len)
6762*2d9fd380Sjfb8856606 		return ret;
6763*2d9fd380Sjfb8856606 	/* set shared action */
6764*2d9fd380Sjfb8856606 	if (action) {
6765*2d9fd380Sjfb8856606 		action->conf = port_shared_action_get_by_id(ctx->port, id);
6766*2d9fd380Sjfb8856606 		ret = (action->conf) ? ret : -1;
6767*2d9fd380Sjfb8856606 	}
6768*2d9fd380Sjfb8856606 	return ret;
6769*2d9fd380Sjfb8856606 }
6770*2d9fd380Sjfb8856606 
67714418919fSjohnjiang /** Parse set command, initialize output buffer for subsequent tokens. */
67724418919fSjohnjiang static int
parse_set_raw_encap_decap(struct context * ctx,const struct token * token,const char * str,unsigned int len,void * buf,unsigned int size)67734418919fSjohnjiang parse_set_raw_encap_decap(struct context *ctx, const struct token *token,
67744418919fSjohnjiang 			  const char *str, unsigned int len,
67754418919fSjohnjiang 			  void *buf, unsigned int size)
67764418919fSjohnjiang {
67774418919fSjohnjiang 	struct buffer *out = buf;
67784418919fSjohnjiang 
67794418919fSjohnjiang 	/* Token name must match. */
67804418919fSjohnjiang 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
67814418919fSjohnjiang 		return -1;
67824418919fSjohnjiang 	/* Nothing else to do if there is no buffer. */
67834418919fSjohnjiang 	if (!out)
67844418919fSjohnjiang 		return len;
67854418919fSjohnjiang 	/* Make sure buffer is large enough. */
67864418919fSjohnjiang 	if (size < sizeof(*out))
67874418919fSjohnjiang 		return -1;
67884418919fSjohnjiang 	ctx->objdata = 0;
67894418919fSjohnjiang 	ctx->objmask = NULL;
67904418919fSjohnjiang 	ctx->object = out;
67914418919fSjohnjiang 	if (!out->command)
67924418919fSjohnjiang 		return -1;
67934418919fSjohnjiang 	out->command = ctx->curr;
6794*2d9fd380Sjfb8856606 	/* For encap/decap we need is pattern */
6795*2d9fd380Sjfb8856606 	out->args.vc.pattern = (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
6796*2d9fd380Sjfb8856606 						       sizeof(double));
6797*2d9fd380Sjfb8856606 	return len;
6798*2d9fd380Sjfb8856606 }
6799*2d9fd380Sjfb8856606 
6800*2d9fd380Sjfb8856606 /** Parse set command, initialize output buffer for subsequent tokens. */
6801*2d9fd380Sjfb8856606 static int
parse_set_sample_action(struct context * ctx,const struct token * token,const char * str,unsigned int len,void * buf,unsigned int size)6802*2d9fd380Sjfb8856606 parse_set_sample_action(struct context *ctx, const struct token *token,
6803*2d9fd380Sjfb8856606 			  const char *str, unsigned int len,
6804*2d9fd380Sjfb8856606 			  void *buf, unsigned int size)
6805*2d9fd380Sjfb8856606 {
6806*2d9fd380Sjfb8856606 	struct buffer *out = buf;
6807*2d9fd380Sjfb8856606 
6808*2d9fd380Sjfb8856606 	/* Token name must match. */
6809*2d9fd380Sjfb8856606 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
6810*2d9fd380Sjfb8856606 		return -1;
6811*2d9fd380Sjfb8856606 	/* Nothing else to do if there is no buffer. */
6812*2d9fd380Sjfb8856606 	if (!out)
6813*2d9fd380Sjfb8856606 		return len;
6814*2d9fd380Sjfb8856606 	/* Make sure buffer is large enough. */
6815*2d9fd380Sjfb8856606 	if (size < sizeof(*out))
6816*2d9fd380Sjfb8856606 		return -1;
6817*2d9fd380Sjfb8856606 	ctx->objdata = 0;
6818*2d9fd380Sjfb8856606 	ctx->objmask = NULL;
6819*2d9fd380Sjfb8856606 	ctx->object = out;
6820*2d9fd380Sjfb8856606 	if (!out->command)
6821*2d9fd380Sjfb8856606 		return -1;
6822*2d9fd380Sjfb8856606 	out->command = ctx->curr;
6823*2d9fd380Sjfb8856606 	/* For sampler we need is actions */
6824*2d9fd380Sjfb8856606 	out->args.vc.actions = (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
6825*2d9fd380Sjfb8856606 						       sizeof(double));
68264418919fSjohnjiang 	return len;
68274418919fSjohnjiang }
68284418919fSjohnjiang 
68294418919fSjohnjiang /**
68304418919fSjohnjiang  * Parse set raw_encap/raw_decap command,
68314418919fSjohnjiang  * initialize output buffer for subsequent tokens.
68324418919fSjohnjiang  */
68334418919fSjohnjiang static int
parse_set_init(struct context * ctx,const struct token * token,const char * str,unsigned int len,void * buf,unsigned int size)68344418919fSjohnjiang parse_set_init(struct context *ctx, const struct token *token,
68354418919fSjohnjiang 	       const char *str, unsigned int len,
68364418919fSjohnjiang 	       void *buf, unsigned int size)
68374418919fSjohnjiang {
68384418919fSjohnjiang 	struct buffer *out = buf;
68394418919fSjohnjiang 
68404418919fSjohnjiang 	/* Token name must match. */
68414418919fSjohnjiang 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
68424418919fSjohnjiang 		return -1;
68434418919fSjohnjiang 	/* Nothing else to do if there is no buffer. */
68444418919fSjohnjiang 	if (!out)
68454418919fSjohnjiang 		return len;
68464418919fSjohnjiang 	/* Make sure buffer is large enough. */
68474418919fSjohnjiang 	if (size < sizeof(*out))
68484418919fSjohnjiang 		return -1;
68494418919fSjohnjiang 	/* Initialize buffer. */
68504418919fSjohnjiang 	memset(out, 0x00, sizeof(*out));
68514418919fSjohnjiang 	memset((uint8_t *)out + sizeof(*out), 0x22, size - sizeof(*out));
68524418919fSjohnjiang 	ctx->objdata = 0;
68534418919fSjohnjiang 	ctx->object = out;
68544418919fSjohnjiang 	ctx->objmask = NULL;
68554418919fSjohnjiang 	if (!out->command) {
68564418919fSjohnjiang 		if (ctx->curr != SET)
68574418919fSjohnjiang 			return -1;
68584418919fSjohnjiang 		if (sizeof(*out) > size)
68594418919fSjohnjiang 			return -1;
68604418919fSjohnjiang 		out->command = ctx->curr;
68614418919fSjohnjiang 		out->args.vc.data = (uint8_t *)out + size;
6862*2d9fd380Sjfb8856606 		ctx->object  = (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
68634418919fSjohnjiang 						       sizeof(double));
68644418919fSjohnjiang 	}
68654418919fSjohnjiang 	return len;
68664418919fSjohnjiang }
68674418919fSjohnjiang 
68682bfe3f2eSlogwang /** No completion. */
68692bfe3f2eSlogwang static int
comp_none(struct context * ctx,const struct token * token,unsigned int ent,char * buf,unsigned int size)68702bfe3f2eSlogwang comp_none(struct context *ctx, const struct token *token,
68712bfe3f2eSlogwang 	  unsigned int ent, char *buf, unsigned int size)
68722bfe3f2eSlogwang {
68732bfe3f2eSlogwang 	(void)ctx;
68742bfe3f2eSlogwang 	(void)token;
68752bfe3f2eSlogwang 	(void)ent;
68762bfe3f2eSlogwang 	(void)buf;
68772bfe3f2eSlogwang 	(void)size;
68782bfe3f2eSlogwang 	return 0;
68792bfe3f2eSlogwang }
68802bfe3f2eSlogwang 
68812bfe3f2eSlogwang /** Complete boolean values. */
68822bfe3f2eSlogwang static int
comp_boolean(struct context * ctx,const struct token * token,unsigned int ent,char * buf,unsigned int size)68832bfe3f2eSlogwang comp_boolean(struct context *ctx, const struct token *token,
68842bfe3f2eSlogwang 	     unsigned int ent, char *buf, unsigned int size)
68852bfe3f2eSlogwang {
68862bfe3f2eSlogwang 	unsigned int i;
68872bfe3f2eSlogwang 
68882bfe3f2eSlogwang 	(void)ctx;
68892bfe3f2eSlogwang 	(void)token;
68902bfe3f2eSlogwang 	for (i = 0; boolean_name[i]; ++i)
68912bfe3f2eSlogwang 		if (buf && i == ent)
68924418919fSjohnjiang 			return strlcpy(buf, boolean_name[i], size);
68932bfe3f2eSlogwang 	if (buf)
68942bfe3f2eSlogwang 		return -1;
68952bfe3f2eSlogwang 	return i;
68962bfe3f2eSlogwang }
68972bfe3f2eSlogwang 
68982bfe3f2eSlogwang /** Complete action names. */
68992bfe3f2eSlogwang static int
comp_action(struct context * ctx,const struct token * token,unsigned int ent,char * buf,unsigned int size)69002bfe3f2eSlogwang comp_action(struct context *ctx, const struct token *token,
69012bfe3f2eSlogwang 	    unsigned int ent, char *buf, unsigned int size)
69022bfe3f2eSlogwang {
69032bfe3f2eSlogwang 	unsigned int i;
69042bfe3f2eSlogwang 
69052bfe3f2eSlogwang 	(void)ctx;
69062bfe3f2eSlogwang 	(void)token;
69072bfe3f2eSlogwang 	for (i = 0; next_action[i]; ++i)
69082bfe3f2eSlogwang 		if (buf && i == ent)
69094418919fSjohnjiang 			return strlcpy(buf, token_list[next_action[i]].name,
69104418919fSjohnjiang 				       size);
69112bfe3f2eSlogwang 	if (buf)
69122bfe3f2eSlogwang 		return -1;
69132bfe3f2eSlogwang 	return i;
69142bfe3f2eSlogwang }
69152bfe3f2eSlogwang 
69162bfe3f2eSlogwang /** Complete available ports. */
69172bfe3f2eSlogwang static int
comp_port(struct context * ctx,const struct token * token,unsigned int ent,char * buf,unsigned int size)69182bfe3f2eSlogwang comp_port(struct context *ctx, const struct token *token,
69192bfe3f2eSlogwang 	  unsigned int ent, char *buf, unsigned int size)
69202bfe3f2eSlogwang {
69212bfe3f2eSlogwang 	unsigned int i = 0;
69222bfe3f2eSlogwang 	portid_t p;
69232bfe3f2eSlogwang 
69242bfe3f2eSlogwang 	(void)ctx;
69252bfe3f2eSlogwang 	(void)token;
69262bfe3f2eSlogwang 	RTE_ETH_FOREACH_DEV(p) {
69272bfe3f2eSlogwang 		if (buf && i == ent)
69282bfe3f2eSlogwang 			return snprintf(buf, size, "%u", p);
69292bfe3f2eSlogwang 		++i;
69302bfe3f2eSlogwang 	}
69312bfe3f2eSlogwang 	if (buf)
69322bfe3f2eSlogwang 		return -1;
69332bfe3f2eSlogwang 	return i;
69342bfe3f2eSlogwang }
69352bfe3f2eSlogwang 
69362bfe3f2eSlogwang /** Complete available rule IDs. */
69372bfe3f2eSlogwang static int
comp_rule_id(struct context * ctx,const struct token * token,unsigned int ent,char * buf,unsigned int size)69382bfe3f2eSlogwang comp_rule_id(struct context *ctx, const struct token *token,
69392bfe3f2eSlogwang 	     unsigned int ent, char *buf, unsigned int size)
69402bfe3f2eSlogwang {
69412bfe3f2eSlogwang 	unsigned int i = 0;
69422bfe3f2eSlogwang 	struct rte_port *port;
69432bfe3f2eSlogwang 	struct port_flow *pf;
69442bfe3f2eSlogwang 
69452bfe3f2eSlogwang 	(void)token;
69462bfe3f2eSlogwang 	if (port_id_is_invalid(ctx->port, DISABLED_WARN) ||
69472bfe3f2eSlogwang 	    ctx->port == (portid_t)RTE_PORT_ALL)
69482bfe3f2eSlogwang 		return -1;
69492bfe3f2eSlogwang 	port = &ports[ctx->port];
69502bfe3f2eSlogwang 	for (pf = port->flow_list; pf != NULL; pf = pf->next) {
69512bfe3f2eSlogwang 		if (buf && i == ent)
69522bfe3f2eSlogwang 			return snprintf(buf, size, "%u", pf->id);
69532bfe3f2eSlogwang 		++i;
69542bfe3f2eSlogwang 	}
69552bfe3f2eSlogwang 	if (buf)
69562bfe3f2eSlogwang 		return -1;
69572bfe3f2eSlogwang 	return i;
69582bfe3f2eSlogwang }
69592bfe3f2eSlogwang 
6960d30ea906Sjfb8856606 /** Complete type field for RSS action. */
6961d30ea906Sjfb8856606 static int
comp_vc_action_rss_type(struct context * ctx,const struct token * token,unsigned int ent,char * buf,unsigned int size)6962d30ea906Sjfb8856606 comp_vc_action_rss_type(struct context *ctx, const struct token *token,
6963d30ea906Sjfb8856606 			unsigned int ent, char *buf, unsigned int size)
6964d30ea906Sjfb8856606 {
6965d30ea906Sjfb8856606 	unsigned int i;
6966d30ea906Sjfb8856606 
6967d30ea906Sjfb8856606 	(void)ctx;
6968d30ea906Sjfb8856606 	(void)token;
6969d30ea906Sjfb8856606 	for (i = 0; rss_type_table[i].str; ++i)
6970d30ea906Sjfb8856606 		;
6971d30ea906Sjfb8856606 	if (!buf)
6972d30ea906Sjfb8856606 		return i + 1;
6973d30ea906Sjfb8856606 	if (ent < i)
69744418919fSjohnjiang 		return strlcpy(buf, rss_type_table[ent].str, size);
6975d30ea906Sjfb8856606 	if (ent == i)
6976d30ea906Sjfb8856606 		return snprintf(buf, size, "end");
6977d30ea906Sjfb8856606 	return -1;
6978d30ea906Sjfb8856606 }
6979d30ea906Sjfb8856606 
69802bfe3f2eSlogwang /** Complete queue field for RSS action. */
69812bfe3f2eSlogwang static int
comp_vc_action_rss_queue(struct context * ctx,const struct token * token,unsigned int ent,char * buf,unsigned int size)69822bfe3f2eSlogwang comp_vc_action_rss_queue(struct context *ctx, const struct token *token,
69832bfe3f2eSlogwang 			 unsigned int ent, char *buf, unsigned int size)
69842bfe3f2eSlogwang {
69852bfe3f2eSlogwang 	(void)ctx;
69862bfe3f2eSlogwang 	(void)token;
6987d30ea906Sjfb8856606 	if (!buf)
6988d30ea906Sjfb8856606 		return nb_rxq + 1;
6989d30ea906Sjfb8856606 	if (ent < nb_rxq)
6990d30ea906Sjfb8856606 		return snprintf(buf, size, "%u", ent);
6991d30ea906Sjfb8856606 	if (ent == nb_rxq)
6992d30ea906Sjfb8856606 		return snprintf(buf, size, "end");
69932bfe3f2eSlogwang 	return -1;
69942bfe3f2eSlogwang }
69952bfe3f2eSlogwang 
69964418919fSjohnjiang /** Complete index number for set raw_encap/raw_decap commands. */
69974418919fSjohnjiang static int
comp_set_raw_index(struct context * ctx,const struct token * token,unsigned int ent,char * buf,unsigned int size)69984418919fSjohnjiang comp_set_raw_index(struct context *ctx, const struct token *token,
69994418919fSjohnjiang 		   unsigned int ent, char *buf, unsigned int size)
70004418919fSjohnjiang {
70014418919fSjohnjiang 	uint16_t idx = 0;
70024418919fSjohnjiang 	uint16_t nb = 0;
70034418919fSjohnjiang 
70044418919fSjohnjiang 	RTE_SET_USED(ctx);
70054418919fSjohnjiang 	RTE_SET_USED(token);
70064418919fSjohnjiang 	for (idx = 0; idx < RAW_ENCAP_CONFS_MAX_NUM; ++idx) {
70074418919fSjohnjiang 		if (buf && idx == ent)
70084418919fSjohnjiang 			return snprintf(buf, size, "%u", idx);
70094418919fSjohnjiang 		++nb;
70104418919fSjohnjiang 	}
70114418919fSjohnjiang 	return nb;
70124418919fSjohnjiang }
70134418919fSjohnjiang 
7014*2d9fd380Sjfb8856606 /** Complete index number for set raw_encap/raw_decap commands. */
7015*2d9fd380Sjfb8856606 static int
comp_set_sample_index(struct context * ctx,const struct token * token,unsigned int ent,char * buf,unsigned int size)7016*2d9fd380Sjfb8856606 comp_set_sample_index(struct context *ctx, const struct token *token,
7017*2d9fd380Sjfb8856606 		   unsigned int ent, char *buf, unsigned int size)
7018*2d9fd380Sjfb8856606 {
7019*2d9fd380Sjfb8856606 	uint16_t idx = 0;
7020*2d9fd380Sjfb8856606 	uint16_t nb = 0;
7021*2d9fd380Sjfb8856606 
7022*2d9fd380Sjfb8856606 	RTE_SET_USED(ctx);
7023*2d9fd380Sjfb8856606 	RTE_SET_USED(token);
7024*2d9fd380Sjfb8856606 	for (idx = 0; idx < RAW_SAMPLE_CONFS_MAX_NUM; ++idx) {
7025*2d9fd380Sjfb8856606 		if (buf && idx == ent)
7026*2d9fd380Sjfb8856606 			return snprintf(buf, size, "%u", idx);
7027*2d9fd380Sjfb8856606 		++nb;
7028*2d9fd380Sjfb8856606 	}
7029*2d9fd380Sjfb8856606 	return nb;
7030*2d9fd380Sjfb8856606 }
7031*2d9fd380Sjfb8856606 
70322bfe3f2eSlogwang /** Internal context. */
70332bfe3f2eSlogwang static struct context cmd_flow_context;
70342bfe3f2eSlogwang 
70352bfe3f2eSlogwang /** Global parser instance (cmdline API). */
70362bfe3f2eSlogwang cmdline_parse_inst_t cmd_flow;
70374418919fSjohnjiang cmdline_parse_inst_t cmd_set_raw;
70382bfe3f2eSlogwang 
70392bfe3f2eSlogwang /** Initialize context. */
70402bfe3f2eSlogwang static void
cmd_flow_context_init(struct context * ctx)70412bfe3f2eSlogwang cmd_flow_context_init(struct context *ctx)
70422bfe3f2eSlogwang {
70432bfe3f2eSlogwang 	/* A full memset() is not necessary. */
70442bfe3f2eSlogwang 	ctx->curr = ZERO;
70452bfe3f2eSlogwang 	ctx->prev = ZERO;
70462bfe3f2eSlogwang 	ctx->next_num = 0;
70472bfe3f2eSlogwang 	ctx->args_num = 0;
70482bfe3f2eSlogwang 	ctx->eol = 0;
70492bfe3f2eSlogwang 	ctx->last = 0;
70502bfe3f2eSlogwang 	ctx->port = 0;
70512bfe3f2eSlogwang 	ctx->objdata = 0;
70522bfe3f2eSlogwang 	ctx->object = NULL;
70532bfe3f2eSlogwang 	ctx->objmask = NULL;
70542bfe3f2eSlogwang }
70552bfe3f2eSlogwang 
70562bfe3f2eSlogwang /** Parse a token (cmdline API). */
70572bfe3f2eSlogwang static int
cmd_flow_parse(cmdline_parse_token_hdr_t * hdr,const char * src,void * result,unsigned int size)70582bfe3f2eSlogwang cmd_flow_parse(cmdline_parse_token_hdr_t *hdr, const char *src, void *result,
70592bfe3f2eSlogwang 	       unsigned int size)
70602bfe3f2eSlogwang {
70612bfe3f2eSlogwang 	struct context *ctx = &cmd_flow_context;
70622bfe3f2eSlogwang 	const struct token *token;
70632bfe3f2eSlogwang 	const enum index *list;
70642bfe3f2eSlogwang 	int len;
70652bfe3f2eSlogwang 	int i;
70662bfe3f2eSlogwang 
70672bfe3f2eSlogwang 	(void)hdr;
70682bfe3f2eSlogwang 	token = &token_list[ctx->curr];
70692bfe3f2eSlogwang 	/* Check argument length. */
70702bfe3f2eSlogwang 	ctx->eol = 0;
70712bfe3f2eSlogwang 	ctx->last = 1;
70722bfe3f2eSlogwang 	for (len = 0; src[len]; ++len)
70732bfe3f2eSlogwang 		if (src[len] == '#' || isspace(src[len]))
70742bfe3f2eSlogwang 			break;
70752bfe3f2eSlogwang 	if (!len)
70762bfe3f2eSlogwang 		return -1;
70772bfe3f2eSlogwang 	/* Last argument and EOL detection. */
70782bfe3f2eSlogwang 	for (i = len; src[i]; ++i)
70792bfe3f2eSlogwang 		if (src[i] == '#' || src[i] == '\r' || src[i] == '\n')
70802bfe3f2eSlogwang 			break;
70812bfe3f2eSlogwang 		else if (!isspace(src[i])) {
70822bfe3f2eSlogwang 			ctx->last = 0;
70832bfe3f2eSlogwang 			break;
70842bfe3f2eSlogwang 		}
70852bfe3f2eSlogwang 	for (; src[i]; ++i)
70862bfe3f2eSlogwang 		if (src[i] == '\r' || src[i] == '\n') {
70872bfe3f2eSlogwang 			ctx->eol = 1;
70882bfe3f2eSlogwang 			break;
70892bfe3f2eSlogwang 		}
70902bfe3f2eSlogwang 	/* Initialize context if necessary. */
70912bfe3f2eSlogwang 	if (!ctx->next_num) {
70922bfe3f2eSlogwang 		if (!token->next)
70932bfe3f2eSlogwang 			return 0;
70942bfe3f2eSlogwang 		ctx->next[ctx->next_num++] = token->next[0];
70952bfe3f2eSlogwang 	}
70962bfe3f2eSlogwang 	/* Process argument through candidates. */
70972bfe3f2eSlogwang 	ctx->prev = ctx->curr;
70982bfe3f2eSlogwang 	list = ctx->next[ctx->next_num - 1];
70992bfe3f2eSlogwang 	for (i = 0; list[i]; ++i) {
71002bfe3f2eSlogwang 		const struct token *next = &token_list[list[i]];
71012bfe3f2eSlogwang 		int tmp;
71022bfe3f2eSlogwang 
71032bfe3f2eSlogwang 		ctx->curr = list[i];
71042bfe3f2eSlogwang 		if (next->call)
71052bfe3f2eSlogwang 			tmp = next->call(ctx, next, src, len, result, size);
71062bfe3f2eSlogwang 		else
71072bfe3f2eSlogwang 			tmp = parse_default(ctx, next, src, len, result, size);
71082bfe3f2eSlogwang 		if (tmp == -1 || tmp != len)
71092bfe3f2eSlogwang 			continue;
71102bfe3f2eSlogwang 		token = next;
71112bfe3f2eSlogwang 		break;
71122bfe3f2eSlogwang 	}
71132bfe3f2eSlogwang 	if (!list[i])
71142bfe3f2eSlogwang 		return -1;
71152bfe3f2eSlogwang 	--ctx->next_num;
71162bfe3f2eSlogwang 	/* Push subsequent tokens if any. */
71172bfe3f2eSlogwang 	if (token->next)
71182bfe3f2eSlogwang 		for (i = 0; token->next[i]; ++i) {
71192bfe3f2eSlogwang 			if (ctx->next_num == RTE_DIM(ctx->next))
71202bfe3f2eSlogwang 				return -1;
71212bfe3f2eSlogwang 			ctx->next[ctx->next_num++] = token->next[i];
71222bfe3f2eSlogwang 		}
71232bfe3f2eSlogwang 	/* Push arguments if any. */
71242bfe3f2eSlogwang 	if (token->args)
71252bfe3f2eSlogwang 		for (i = 0; token->args[i]; ++i) {
71262bfe3f2eSlogwang 			if (ctx->args_num == RTE_DIM(ctx->args))
71272bfe3f2eSlogwang 				return -1;
71282bfe3f2eSlogwang 			ctx->args[ctx->args_num++] = token->args[i];
71292bfe3f2eSlogwang 		}
71302bfe3f2eSlogwang 	return len;
71312bfe3f2eSlogwang }
71322bfe3f2eSlogwang 
71332bfe3f2eSlogwang /** Return number of completion entries (cmdline API). */
71342bfe3f2eSlogwang static int
cmd_flow_complete_get_nb(cmdline_parse_token_hdr_t * hdr)71352bfe3f2eSlogwang cmd_flow_complete_get_nb(cmdline_parse_token_hdr_t *hdr)
71362bfe3f2eSlogwang {
71372bfe3f2eSlogwang 	struct context *ctx = &cmd_flow_context;
71382bfe3f2eSlogwang 	const struct token *token = &token_list[ctx->curr];
71392bfe3f2eSlogwang 	const enum index *list;
71402bfe3f2eSlogwang 	int i;
71412bfe3f2eSlogwang 
71422bfe3f2eSlogwang 	(void)hdr;
71432bfe3f2eSlogwang 	/* Count number of tokens in current list. */
71442bfe3f2eSlogwang 	if (ctx->next_num)
71452bfe3f2eSlogwang 		list = ctx->next[ctx->next_num - 1];
71462bfe3f2eSlogwang 	else
71472bfe3f2eSlogwang 		list = token->next[0];
71482bfe3f2eSlogwang 	for (i = 0; list[i]; ++i)
71492bfe3f2eSlogwang 		;
71502bfe3f2eSlogwang 	if (!i)
71512bfe3f2eSlogwang 		return 0;
71522bfe3f2eSlogwang 	/*
71532bfe3f2eSlogwang 	 * If there is a single token, use its completion callback, otherwise
71542bfe3f2eSlogwang 	 * return the number of entries.
71552bfe3f2eSlogwang 	 */
71562bfe3f2eSlogwang 	token = &token_list[list[0]];
71572bfe3f2eSlogwang 	if (i == 1 && token->comp) {
71582bfe3f2eSlogwang 		/* Save index for cmd_flow_get_help(). */
71592bfe3f2eSlogwang 		ctx->prev = list[0];
71602bfe3f2eSlogwang 		return token->comp(ctx, token, 0, NULL, 0);
71612bfe3f2eSlogwang 	}
71622bfe3f2eSlogwang 	return i;
71632bfe3f2eSlogwang }
71642bfe3f2eSlogwang 
71652bfe3f2eSlogwang /** Return a completion entry (cmdline API). */
71662bfe3f2eSlogwang static int
cmd_flow_complete_get_elt(cmdline_parse_token_hdr_t * hdr,int index,char * dst,unsigned int size)71672bfe3f2eSlogwang cmd_flow_complete_get_elt(cmdline_parse_token_hdr_t *hdr, int index,
71682bfe3f2eSlogwang 			  char *dst, unsigned int size)
71692bfe3f2eSlogwang {
71702bfe3f2eSlogwang 	struct context *ctx = &cmd_flow_context;
71712bfe3f2eSlogwang 	const struct token *token = &token_list[ctx->curr];
71722bfe3f2eSlogwang 	const enum index *list;
71732bfe3f2eSlogwang 	int i;
71742bfe3f2eSlogwang 
71752bfe3f2eSlogwang 	(void)hdr;
71762bfe3f2eSlogwang 	/* Count number of tokens in current list. */
71772bfe3f2eSlogwang 	if (ctx->next_num)
71782bfe3f2eSlogwang 		list = ctx->next[ctx->next_num - 1];
71792bfe3f2eSlogwang 	else
71802bfe3f2eSlogwang 		list = token->next[0];
71812bfe3f2eSlogwang 	for (i = 0; list[i]; ++i)
71822bfe3f2eSlogwang 		;
71832bfe3f2eSlogwang 	if (!i)
71842bfe3f2eSlogwang 		return -1;
71852bfe3f2eSlogwang 	/* If there is a single token, use its completion callback. */
71862bfe3f2eSlogwang 	token = &token_list[list[0]];
71872bfe3f2eSlogwang 	if (i == 1 && token->comp) {
71882bfe3f2eSlogwang 		/* Save index for cmd_flow_get_help(). */
71892bfe3f2eSlogwang 		ctx->prev = list[0];
71902bfe3f2eSlogwang 		return token->comp(ctx, token, index, dst, size) < 0 ? -1 : 0;
71912bfe3f2eSlogwang 	}
71922bfe3f2eSlogwang 	/* Otherwise make sure the index is valid and use defaults. */
71932bfe3f2eSlogwang 	if (index >= i)
71942bfe3f2eSlogwang 		return -1;
71952bfe3f2eSlogwang 	token = &token_list[list[index]];
71964418919fSjohnjiang 	strlcpy(dst, token->name, size);
71972bfe3f2eSlogwang 	/* Save index for cmd_flow_get_help(). */
71982bfe3f2eSlogwang 	ctx->prev = list[index];
71992bfe3f2eSlogwang 	return 0;
72002bfe3f2eSlogwang }
72012bfe3f2eSlogwang 
72022bfe3f2eSlogwang /** Populate help strings for current token (cmdline API). */
72032bfe3f2eSlogwang static int
cmd_flow_get_help(cmdline_parse_token_hdr_t * hdr,char * dst,unsigned int size)72042bfe3f2eSlogwang cmd_flow_get_help(cmdline_parse_token_hdr_t *hdr, char *dst, unsigned int size)
72052bfe3f2eSlogwang {
72062bfe3f2eSlogwang 	struct context *ctx = &cmd_flow_context;
72072bfe3f2eSlogwang 	const struct token *token = &token_list[ctx->prev];
72082bfe3f2eSlogwang 
72092bfe3f2eSlogwang 	(void)hdr;
72102bfe3f2eSlogwang 	if (!size)
72112bfe3f2eSlogwang 		return -1;
72122bfe3f2eSlogwang 	/* Set token type and update global help with details. */
72134418919fSjohnjiang 	strlcpy(dst, (token->type ? token->type : "TOKEN"), size);
72142bfe3f2eSlogwang 	if (token->help)
72152bfe3f2eSlogwang 		cmd_flow.help_str = token->help;
72162bfe3f2eSlogwang 	else
72172bfe3f2eSlogwang 		cmd_flow.help_str = token->name;
72182bfe3f2eSlogwang 	return 0;
72192bfe3f2eSlogwang }
72202bfe3f2eSlogwang 
72212bfe3f2eSlogwang /** Token definition template (cmdline API). */
72222bfe3f2eSlogwang static struct cmdline_token_hdr cmd_flow_token_hdr = {
72232bfe3f2eSlogwang 	.ops = &(struct cmdline_token_ops){
72242bfe3f2eSlogwang 		.parse = cmd_flow_parse,
72252bfe3f2eSlogwang 		.complete_get_nb = cmd_flow_complete_get_nb,
72262bfe3f2eSlogwang 		.complete_get_elt = cmd_flow_complete_get_elt,
72272bfe3f2eSlogwang 		.get_help = cmd_flow_get_help,
72282bfe3f2eSlogwang 	},
72292bfe3f2eSlogwang 	.offset = 0,
72302bfe3f2eSlogwang };
72312bfe3f2eSlogwang 
72322bfe3f2eSlogwang /** Populate the next dynamic token. */
72332bfe3f2eSlogwang static void
cmd_flow_tok(cmdline_parse_token_hdr_t ** hdr,cmdline_parse_token_hdr_t ** hdr_inst)72342bfe3f2eSlogwang cmd_flow_tok(cmdline_parse_token_hdr_t **hdr,
72352bfe3f2eSlogwang 	     cmdline_parse_token_hdr_t **hdr_inst)
72362bfe3f2eSlogwang {
72372bfe3f2eSlogwang 	struct context *ctx = &cmd_flow_context;
72382bfe3f2eSlogwang 
72392bfe3f2eSlogwang 	/* Always reinitialize context before requesting the first token. */
72402bfe3f2eSlogwang 	if (!(hdr_inst - cmd_flow.tokens))
72412bfe3f2eSlogwang 		cmd_flow_context_init(ctx);
72422bfe3f2eSlogwang 	/* Return NULL when no more tokens are expected. */
72432bfe3f2eSlogwang 	if (!ctx->next_num && ctx->curr) {
72442bfe3f2eSlogwang 		*hdr = NULL;
72452bfe3f2eSlogwang 		return;
72462bfe3f2eSlogwang 	}
72472bfe3f2eSlogwang 	/* Determine if command should end here. */
72482bfe3f2eSlogwang 	if (ctx->eol && ctx->last && ctx->next_num) {
72492bfe3f2eSlogwang 		const enum index *list = ctx->next[ctx->next_num - 1];
72502bfe3f2eSlogwang 		int i;
72512bfe3f2eSlogwang 
72522bfe3f2eSlogwang 		for (i = 0; list[i]; ++i) {
72532bfe3f2eSlogwang 			if (list[i] != END)
72542bfe3f2eSlogwang 				continue;
72552bfe3f2eSlogwang 			*hdr = NULL;
72562bfe3f2eSlogwang 			return;
72572bfe3f2eSlogwang 		}
72582bfe3f2eSlogwang 	}
72592bfe3f2eSlogwang 	*hdr = &cmd_flow_token_hdr;
72602bfe3f2eSlogwang }
72612bfe3f2eSlogwang 
72622bfe3f2eSlogwang /** Dispatch parsed buffer to function calls. */
72632bfe3f2eSlogwang static void
cmd_flow_parsed(const struct buffer * in)72642bfe3f2eSlogwang cmd_flow_parsed(const struct buffer *in)
72652bfe3f2eSlogwang {
72662bfe3f2eSlogwang 	switch (in->command) {
7267*2d9fd380Sjfb8856606 	case SHARED_ACTION_CREATE:
7268*2d9fd380Sjfb8856606 		port_shared_action_create(
7269*2d9fd380Sjfb8856606 				in->port, in->args.vc.attr.group,
7270*2d9fd380Sjfb8856606 				&((const struct rte_flow_shared_action_conf) {
7271*2d9fd380Sjfb8856606 					.ingress = in->args.vc.attr.ingress,
7272*2d9fd380Sjfb8856606 					.egress = in->args.vc.attr.egress,
7273*2d9fd380Sjfb8856606 					.transfer = in->args.vc.attr.transfer,
7274*2d9fd380Sjfb8856606 				}),
7275*2d9fd380Sjfb8856606 				in->args.vc.actions);
7276*2d9fd380Sjfb8856606 		break;
7277*2d9fd380Sjfb8856606 	case SHARED_ACTION_DESTROY:
7278*2d9fd380Sjfb8856606 		port_shared_action_destroy(in->port,
7279*2d9fd380Sjfb8856606 					   in->args.sa_destroy.action_id_n,
7280*2d9fd380Sjfb8856606 					   in->args.sa_destroy.action_id);
7281*2d9fd380Sjfb8856606 		break;
7282*2d9fd380Sjfb8856606 	case SHARED_ACTION_UPDATE:
7283*2d9fd380Sjfb8856606 		port_shared_action_update(in->port, in->args.vc.attr.group,
7284*2d9fd380Sjfb8856606 					  in->args.vc.actions);
7285*2d9fd380Sjfb8856606 		break;
7286*2d9fd380Sjfb8856606 	case SHARED_ACTION_QUERY:
7287*2d9fd380Sjfb8856606 		port_shared_action_query(in->port, in->args.sa.action_id);
7288*2d9fd380Sjfb8856606 		break;
72892bfe3f2eSlogwang 	case VALIDATE:
72902bfe3f2eSlogwang 		port_flow_validate(in->port, &in->args.vc.attr,
7291*2d9fd380Sjfb8856606 				   in->args.vc.pattern, in->args.vc.actions,
7292*2d9fd380Sjfb8856606 				   &in->args.vc.tunnel_ops);
72932bfe3f2eSlogwang 		break;
72942bfe3f2eSlogwang 	case CREATE:
72952bfe3f2eSlogwang 		port_flow_create(in->port, &in->args.vc.attr,
7296*2d9fd380Sjfb8856606 				 in->args.vc.pattern, in->args.vc.actions,
7297*2d9fd380Sjfb8856606 				 &in->args.vc.tunnel_ops);
72982bfe3f2eSlogwang 		break;
72992bfe3f2eSlogwang 	case DESTROY:
73002bfe3f2eSlogwang 		port_flow_destroy(in->port, in->args.destroy.rule_n,
73012bfe3f2eSlogwang 				  in->args.destroy.rule);
73022bfe3f2eSlogwang 		break;
73032bfe3f2eSlogwang 	case FLUSH:
73042bfe3f2eSlogwang 		port_flow_flush(in->port);
73052bfe3f2eSlogwang 		break;
7306*2d9fd380Sjfb8856606 	case DUMP:
7307*2d9fd380Sjfb8856606 		port_flow_dump(in->port, in->args.dump.file);
7308*2d9fd380Sjfb8856606 		break;
73092bfe3f2eSlogwang 	case QUERY:
73102bfe3f2eSlogwang 		port_flow_query(in->port, in->args.query.rule,
7311d30ea906Sjfb8856606 				&in->args.query.action);
73122bfe3f2eSlogwang 		break;
73132bfe3f2eSlogwang 	case LIST:
73142bfe3f2eSlogwang 		port_flow_list(in->port, in->args.list.group_n,
73152bfe3f2eSlogwang 			       in->args.list.group);
73162bfe3f2eSlogwang 		break;
73172bfe3f2eSlogwang 	case ISOLATE:
73182bfe3f2eSlogwang 		port_flow_isolate(in->port, in->args.isolate.set);
73192bfe3f2eSlogwang 		break;
7320*2d9fd380Sjfb8856606 	case AGED:
7321*2d9fd380Sjfb8856606 		port_flow_aged(in->port, in->args.aged.destroy);
7322*2d9fd380Sjfb8856606 		break;
7323*2d9fd380Sjfb8856606 	case TUNNEL_CREATE:
7324*2d9fd380Sjfb8856606 		port_flow_tunnel_create(in->port, &in->args.vc.tunnel_ops);
7325*2d9fd380Sjfb8856606 		break;
7326*2d9fd380Sjfb8856606 	case TUNNEL_DESTROY:
7327*2d9fd380Sjfb8856606 		port_flow_tunnel_destroy(in->port, in->args.vc.tunnel_ops.id);
7328*2d9fd380Sjfb8856606 		break;
7329*2d9fd380Sjfb8856606 	case TUNNEL_LIST:
7330*2d9fd380Sjfb8856606 		port_flow_tunnel_list(in->port);
7331*2d9fd380Sjfb8856606 		break;
73322bfe3f2eSlogwang 	default:
73332bfe3f2eSlogwang 		break;
73342bfe3f2eSlogwang 	}
73352bfe3f2eSlogwang }
73362bfe3f2eSlogwang 
73372bfe3f2eSlogwang /** Token generator and output processing callback (cmdline API). */
73382bfe3f2eSlogwang static void
cmd_flow_cb(void * arg0,struct cmdline * cl,void * arg2)73392bfe3f2eSlogwang cmd_flow_cb(void *arg0, struct cmdline *cl, void *arg2)
73402bfe3f2eSlogwang {
73412bfe3f2eSlogwang 	if (cl == NULL)
73422bfe3f2eSlogwang 		cmd_flow_tok(arg0, arg2);
73432bfe3f2eSlogwang 	else
73442bfe3f2eSlogwang 		cmd_flow_parsed(arg0);
73452bfe3f2eSlogwang }
73462bfe3f2eSlogwang 
73472bfe3f2eSlogwang /** Global parser instance (cmdline API). */
73482bfe3f2eSlogwang cmdline_parse_inst_t cmd_flow = {
73492bfe3f2eSlogwang 	.f = cmd_flow_cb,
73502bfe3f2eSlogwang 	.data = NULL, /**< Unused. */
73512bfe3f2eSlogwang 	.help_str = NULL, /**< Updated by cmd_flow_get_help(). */
73522bfe3f2eSlogwang 	.tokens = {
73532bfe3f2eSlogwang 		NULL,
73542bfe3f2eSlogwang 	}, /**< Tokens are returned by cmd_flow_tok(). */
73552bfe3f2eSlogwang };
73564418919fSjohnjiang 
73574418919fSjohnjiang /** set cmd facility. Reuse cmd flow's infrastructure as much as possible. */
73584418919fSjohnjiang 
73594418919fSjohnjiang static void
update_fields(uint8_t * buf,struct rte_flow_item * item,uint16_t next_proto)73604418919fSjohnjiang update_fields(uint8_t *buf, struct rte_flow_item *item, uint16_t next_proto)
73614418919fSjohnjiang {
7362*2d9fd380Sjfb8856606 	struct rte_ipv4_hdr *ipv4;
7363*2d9fd380Sjfb8856606 	struct rte_ether_hdr *eth;
7364*2d9fd380Sjfb8856606 	struct rte_ipv6_hdr *ipv6;
7365*2d9fd380Sjfb8856606 	struct rte_vxlan_hdr *vxlan;
7366*2d9fd380Sjfb8856606 	struct rte_vxlan_gpe_hdr *gpe;
73674418919fSjohnjiang 	struct rte_flow_item_nvgre *nvgre;
73684418919fSjohnjiang 	uint32_t ipv6_vtc_flow;
73694418919fSjohnjiang 
73704418919fSjohnjiang 	switch (item->type) {
73714418919fSjohnjiang 	case RTE_FLOW_ITEM_TYPE_ETH:
7372*2d9fd380Sjfb8856606 		eth = (struct rte_ether_hdr *)buf;
73734418919fSjohnjiang 		if (next_proto)
7374*2d9fd380Sjfb8856606 			eth->ether_type = rte_cpu_to_be_16(next_proto);
73754418919fSjohnjiang 		break;
73764418919fSjohnjiang 	case RTE_FLOW_ITEM_TYPE_IPV4:
7377*2d9fd380Sjfb8856606 		ipv4 = (struct rte_ipv4_hdr *)buf;
7378*2d9fd380Sjfb8856606 		ipv4->version_ihl = 0x45;
7379*2d9fd380Sjfb8856606 		if (next_proto && ipv4->next_proto_id == 0)
7380*2d9fd380Sjfb8856606 			ipv4->next_proto_id = (uint8_t)next_proto;
73814418919fSjohnjiang 		break;
73824418919fSjohnjiang 	case RTE_FLOW_ITEM_TYPE_IPV6:
7383*2d9fd380Sjfb8856606 		ipv6 = (struct rte_ipv6_hdr *)buf;
7384*2d9fd380Sjfb8856606 		if (next_proto && ipv6->proto == 0)
7385*2d9fd380Sjfb8856606 			ipv6->proto = (uint8_t)next_proto;
7386*2d9fd380Sjfb8856606 		ipv6_vtc_flow = rte_be_to_cpu_32(ipv6->vtc_flow);
73874418919fSjohnjiang 		ipv6_vtc_flow &= 0x0FFFFFFF; /*< reset version bits. */
73884418919fSjohnjiang 		ipv6_vtc_flow |= 0x60000000; /*< set ipv6 version. */
7389*2d9fd380Sjfb8856606 		ipv6->vtc_flow = rte_cpu_to_be_32(ipv6_vtc_flow);
73904418919fSjohnjiang 		break;
73914418919fSjohnjiang 	case RTE_FLOW_ITEM_TYPE_VXLAN:
7392*2d9fd380Sjfb8856606 		vxlan = (struct rte_vxlan_hdr *)buf;
7393*2d9fd380Sjfb8856606 		vxlan->vx_flags = 0x08;
73944418919fSjohnjiang 		break;
73954418919fSjohnjiang 	case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
7396*2d9fd380Sjfb8856606 		gpe = (struct rte_vxlan_gpe_hdr *)buf;
7397*2d9fd380Sjfb8856606 		gpe->vx_flags = 0x0C;
73984418919fSjohnjiang 		break;
73994418919fSjohnjiang 	case RTE_FLOW_ITEM_TYPE_NVGRE:
74004418919fSjohnjiang 		nvgre = (struct rte_flow_item_nvgre *)buf;
74014418919fSjohnjiang 		nvgre->protocol = rte_cpu_to_be_16(0x6558);
74024418919fSjohnjiang 		nvgre->c_k_s_rsvd0_ver = rte_cpu_to_be_16(0x2000);
74034418919fSjohnjiang 		break;
74044418919fSjohnjiang 	default:
74054418919fSjohnjiang 		break;
74064418919fSjohnjiang 	}
74074418919fSjohnjiang }
74084418919fSjohnjiang 
74094418919fSjohnjiang /** Helper of get item's default mask. */
74104418919fSjohnjiang static const void *
flow_item_default_mask(const struct rte_flow_item * item)74114418919fSjohnjiang flow_item_default_mask(const struct rte_flow_item *item)
74124418919fSjohnjiang {
74134418919fSjohnjiang 	const void *mask = NULL;
74144418919fSjohnjiang 	static rte_be32_t gre_key_default_mask = RTE_BE32(UINT32_MAX);
74154418919fSjohnjiang 
74164418919fSjohnjiang 	switch (item->type) {
74174418919fSjohnjiang 	case RTE_FLOW_ITEM_TYPE_ANY:
74184418919fSjohnjiang 		mask = &rte_flow_item_any_mask;
74194418919fSjohnjiang 		break;
74204418919fSjohnjiang 	case RTE_FLOW_ITEM_TYPE_VF:
74214418919fSjohnjiang 		mask = &rte_flow_item_vf_mask;
74224418919fSjohnjiang 		break;
74234418919fSjohnjiang 	case RTE_FLOW_ITEM_TYPE_PORT_ID:
74244418919fSjohnjiang 		mask = &rte_flow_item_port_id_mask;
74254418919fSjohnjiang 		break;
74264418919fSjohnjiang 	case RTE_FLOW_ITEM_TYPE_RAW:
74274418919fSjohnjiang 		mask = &rte_flow_item_raw_mask;
74284418919fSjohnjiang 		break;
74294418919fSjohnjiang 	case RTE_FLOW_ITEM_TYPE_ETH:
74304418919fSjohnjiang 		mask = &rte_flow_item_eth_mask;
74314418919fSjohnjiang 		break;
74324418919fSjohnjiang 	case RTE_FLOW_ITEM_TYPE_VLAN:
74334418919fSjohnjiang 		mask = &rte_flow_item_vlan_mask;
74344418919fSjohnjiang 		break;
74354418919fSjohnjiang 	case RTE_FLOW_ITEM_TYPE_IPV4:
74364418919fSjohnjiang 		mask = &rte_flow_item_ipv4_mask;
74374418919fSjohnjiang 		break;
74384418919fSjohnjiang 	case RTE_FLOW_ITEM_TYPE_IPV6:
74394418919fSjohnjiang 		mask = &rte_flow_item_ipv6_mask;
74404418919fSjohnjiang 		break;
74414418919fSjohnjiang 	case RTE_FLOW_ITEM_TYPE_ICMP:
74424418919fSjohnjiang 		mask = &rte_flow_item_icmp_mask;
74434418919fSjohnjiang 		break;
74444418919fSjohnjiang 	case RTE_FLOW_ITEM_TYPE_UDP:
74454418919fSjohnjiang 		mask = &rte_flow_item_udp_mask;
74464418919fSjohnjiang 		break;
74474418919fSjohnjiang 	case RTE_FLOW_ITEM_TYPE_TCP:
74484418919fSjohnjiang 		mask = &rte_flow_item_tcp_mask;
74494418919fSjohnjiang 		break;
74504418919fSjohnjiang 	case RTE_FLOW_ITEM_TYPE_SCTP:
74514418919fSjohnjiang 		mask = &rte_flow_item_sctp_mask;
74524418919fSjohnjiang 		break;
74534418919fSjohnjiang 	case RTE_FLOW_ITEM_TYPE_VXLAN:
74544418919fSjohnjiang 		mask = &rte_flow_item_vxlan_mask;
74554418919fSjohnjiang 		break;
74564418919fSjohnjiang 	case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
74574418919fSjohnjiang 		mask = &rte_flow_item_vxlan_gpe_mask;
74584418919fSjohnjiang 		break;
74594418919fSjohnjiang 	case RTE_FLOW_ITEM_TYPE_E_TAG:
74604418919fSjohnjiang 		mask = &rte_flow_item_e_tag_mask;
74614418919fSjohnjiang 		break;
74624418919fSjohnjiang 	case RTE_FLOW_ITEM_TYPE_NVGRE:
74634418919fSjohnjiang 		mask = &rte_flow_item_nvgre_mask;
74644418919fSjohnjiang 		break;
74654418919fSjohnjiang 	case RTE_FLOW_ITEM_TYPE_MPLS:
74664418919fSjohnjiang 		mask = &rte_flow_item_mpls_mask;
74674418919fSjohnjiang 		break;
74684418919fSjohnjiang 	case RTE_FLOW_ITEM_TYPE_GRE:
74694418919fSjohnjiang 		mask = &rte_flow_item_gre_mask;
74704418919fSjohnjiang 		break;
74714418919fSjohnjiang 	case RTE_FLOW_ITEM_TYPE_GRE_KEY:
74724418919fSjohnjiang 		mask = &gre_key_default_mask;
74734418919fSjohnjiang 		break;
74744418919fSjohnjiang 	case RTE_FLOW_ITEM_TYPE_META:
74754418919fSjohnjiang 		mask = &rte_flow_item_meta_mask;
74764418919fSjohnjiang 		break;
74774418919fSjohnjiang 	case RTE_FLOW_ITEM_TYPE_FUZZY:
74784418919fSjohnjiang 		mask = &rte_flow_item_fuzzy_mask;
74794418919fSjohnjiang 		break;
74804418919fSjohnjiang 	case RTE_FLOW_ITEM_TYPE_GTP:
74814418919fSjohnjiang 		mask = &rte_flow_item_gtp_mask;
74824418919fSjohnjiang 		break;
74834418919fSjohnjiang 	case RTE_FLOW_ITEM_TYPE_GTP_PSC:
74844418919fSjohnjiang 		mask = &rte_flow_item_gtp_psc_mask;
74854418919fSjohnjiang 		break;
74864418919fSjohnjiang 	case RTE_FLOW_ITEM_TYPE_GENEVE:
74874418919fSjohnjiang 		mask = &rte_flow_item_geneve_mask;
74884418919fSjohnjiang 		break;
74894418919fSjohnjiang 	case RTE_FLOW_ITEM_TYPE_PPPOE_PROTO_ID:
74904418919fSjohnjiang 		mask = &rte_flow_item_pppoe_proto_id_mask;
7491*2d9fd380Sjfb8856606 		break;
7492*2d9fd380Sjfb8856606 	case RTE_FLOW_ITEM_TYPE_L2TPV3OIP:
7493*2d9fd380Sjfb8856606 		mask = &rte_flow_item_l2tpv3oip_mask;
7494*2d9fd380Sjfb8856606 		break;
7495*2d9fd380Sjfb8856606 	case RTE_FLOW_ITEM_TYPE_ESP:
7496*2d9fd380Sjfb8856606 		mask = &rte_flow_item_esp_mask;
7497*2d9fd380Sjfb8856606 		break;
7498*2d9fd380Sjfb8856606 	case RTE_FLOW_ITEM_TYPE_AH:
7499*2d9fd380Sjfb8856606 		mask = &rte_flow_item_ah_mask;
7500*2d9fd380Sjfb8856606 		break;
7501*2d9fd380Sjfb8856606 	case RTE_FLOW_ITEM_TYPE_PFCP:
7502*2d9fd380Sjfb8856606 		mask = &rte_flow_item_pfcp_mask;
7503*2d9fd380Sjfb8856606 		break;
75044418919fSjohnjiang 	default:
75054418919fSjohnjiang 		break;
75064418919fSjohnjiang 	}
75074418919fSjohnjiang 	return mask;
75084418919fSjohnjiang }
75094418919fSjohnjiang 
7510*2d9fd380Sjfb8856606 /** Dispatch parsed buffer to function calls. */
7511*2d9fd380Sjfb8856606 static void
cmd_set_raw_parsed_sample(const struct buffer * in)7512*2d9fd380Sjfb8856606 cmd_set_raw_parsed_sample(const struct buffer *in)
7513*2d9fd380Sjfb8856606 {
7514*2d9fd380Sjfb8856606 	uint32_t n = in->args.vc.actions_n;
7515*2d9fd380Sjfb8856606 	uint32_t i = 0;
7516*2d9fd380Sjfb8856606 	struct rte_flow_action *action = NULL;
7517*2d9fd380Sjfb8856606 	struct rte_flow_action *data = NULL;
7518*2d9fd380Sjfb8856606 	size_t size = 0;
7519*2d9fd380Sjfb8856606 	uint16_t idx = in->port; /* We borrow port field as index */
7520*2d9fd380Sjfb8856606 	uint32_t max_size = sizeof(struct rte_flow_action) *
7521*2d9fd380Sjfb8856606 						ACTION_SAMPLE_ACTIONS_NUM;
75224418919fSjohnjiang 
7523*2d9fd380Sjfb8856606 	RTE_ASSERT(in->command == SET_SAMPLE_ACTIONS);
7524*2d9fd380Sjfb8856606 	data = (struct rte_flow_action *)&raw_sample_confs[idx].data;
7525*2d9fd380Sjfb8856606 	memset(data, 0x00, max_size);
7526*2d9fd380Sjfb8856606 	for (; i <= n - 1; i++) {
7527*2d9fd380Sjfb8856606 		action = in->args.vc.actions + i;
7528*2d9fd380Sjfb8856606 		if (action->type == RTE_FLOW_ACTION_TYPE_END)
7529*2d9fd380Sjfb8856606 			break;
7530*2d9fd380Sjfb8856606 		switch (action->type) {
7531*2d9fd380Sjfb8856606 		case RTE_FLOW_ACTION_TYPE_MARK:
7532*2d9fd380Sjfb8856606 			size = sizeof(struct rte_flow_action_mark);
7533*2d9fd380Sjfb8856606 			rte_memcpy(&sample_mark[idx],
7534*2d9fd380Sjfb8856606 				(const void *)action->conf, size);
7535*2d9fd380Sjfb8856606 			action->conf = &sample_mark[idx];
7536*2d9fd380Sjfb8856606 			break;
7537*2d9fd380Sjfb8856606 		case RTE_FLOW_ACTION_TYPE_COUNT:
7538*2d9fd380Sjfb8856606 			size = sizeof(struct rte_flow_action_count);
7539*2d9fd380Sjfb8856606 			rte_memcpy(&sample_count[idx],
7540*2d9fd380Sjfb8856606 				(const void *)action->conf, size);
7541*2d9fd380Sjfb8856606 			action->conf = &sample_count[idx];
7542*2d9fd380Sjfb8856606 			break;
7543*2d9fd380Sjfb8856606 		case RTE_FLOW_ACTION_TYPE_QUEUE:
7544*2d9fd380Sjfb8856606 			size = sizeof(struct rte_flow_action_queue);
7545*2d9fd380Sjfb8856606 			rte_memcpy(&sample_queue[idx],
7546*2d9fd380Sjfb8856606 				(const void *)action->conf, size);
7547*2d9fd380Sjfb8856606 			action->conf = &sample_queue[idx];
7548*2d9fd380Sjfb8856606 			break;
7549*2d9fd380Sjfb8856606 		case RTE_FLOW_ACTION_TYPE_RAW_ENCAP:
7550*2d9fd380Sjfb8856606 			size = sizeof(struct rte_flow_action_raw_encap);
7551*2d9fd380Sjfb8856606 			rte_memcpy(&sample_encap[idx],
7552*2d9fd380Sjfb8856606 				(const void *)action->conf, size);
7553*2d9fd380Sjfb8856606 			action->conf = &sample_encap[idx];
7554*2d9fd380Sjfb8856606 			break;
7555*2d9fd380Sjfb8856606 		case RTE_FLOW_ACTION_TYPE_PORT_ID:
7556*2d9fd380Sjfb8856606 			size = sizeof(struct rte_flow_action_port_id);
7557*2d9fd380Sjfb8856606 			rte_memcpy(&sample_port_id[idx],
7558*2d9fd380Sjfb8856606 				(const void *)action->conf, size);
7559*2d9fd380Sjfb8856606 			action->conf = &sample_port_id[idx];
7560*2d9fd380Sjfb8856606 			break;
7561*2d9fd380Sjfb8856606 		default:
7562*2d9fd380Sjfb8856606 			printf("Error - Not supported action\n");
7563*2d9fd380Sjfb8856606 			return;
7564*2d9fd380Sjfb8856606 		}
7565*2d9fd380Sjfb8856606 		rte_memcpy(data, action, sizeof(struct rte_flow_action));
7566*2d9fd380Sjfb8856606 		data++;
7567*2d9fd380Sjfb8856606 	}
7568*2d9fd380Sjfb8856606 }
75694418919fSjohnjiang 
75704418919fSjohnjiang /** Dispatch parsed buffer to function calls. */
75714418919fSjohnjiang static void
cmd_set_raw_parsed(const struct buffer * in)75724418919fSjohnjiang cmd_set_raw_parsed(const struct buffer *in)
75734418919fSjohnjiang {
75744418919fSjohnjiang 	uint32_t n = in->args.vc.pattern_n;
75754418919fSjohnjiang 	int i = 0;
75764418919fSjohnjiang 	struct rte_flow_item *item = NULL;
75774418919fSjohnjiang 	size_t size = 0;
75784418919fSjohnjiang 	uint8_t *data = NULL;
75794418919fSjohnjiang 	uint8_t *data_tail = NULL;
75804418919fSjohnjiang 	size_t *total_size = NULL;
75814418919fSjohnjiang 	uint16_t upper_layer = 0;
75824418919fSjohnjiang 	uint16_t proto = 0;
75834418919fSjohnjiang 	uint16_t idx = in->port; /* We borrow port field as index */
75844418919fSjohnjiang 
7585*2d9fd380Sjfb8856606 	if (in->command == SET_SAMPLE_ACTIONS)
7586*2d9fd380Sjfb8856606 		return cmd_set_raw_parsed_sample(in);
75874418919fSjohnjiang 	RTE_ASSERT(in->command == SET_RAW_ENCAP ||
75884418919fSjohnjiang 		   in->command == SET_RAW_DECAP);
75894418919fSjohnjiang 	if (in->command == SET_RAW_ENCAP) {
75904418919fSjohnjiang 		total_size = &raw_encap_confs[idx].size;
75914418919fSjohnjiang 		data = (uint8_t *)&raw_encap_confs[idx].data;
75924418919fSjohnjiang 	} else {
75934418919fSjohnjiang 		total_size = &raw_decap_confs[idx].size;
75944418919fSjohnjiang 		data = (uint8_t *)&raw_decap_confs[idx].data;
75954418919fSjohnjiang 	}
75964418919fSjohnjiang 	*total_size = 0;
75974418919fSjohnjiang 	memset(data, 0x00, ACTION_RAW_ENCAP_MAX_DATA);
75984418919fSjohnjiang 	/* process hdr from upper layer to low layer (L3/L4 -> L2). */
75994418919fSjohnjiang 	data_tail = data + ACTION_RAW_ENCAP_MAX_DATA;
76004418919fSjohnjiang 	for (i = n - 1 ; i >= 0; --i) {
76014418919fSjohnjiang 		item = in->args.vc.pattern + i;
76024418919fSjohnjiang 		if (item->spec == NULL)
76034418919fSjohnjiang 			item->spec = flow_item_default_mask(item);
76044418919fSjohnjiang 		switch (item->type) {
76054418919fSjohnjiang 		case RTE_FLOW_ITEM_TYPE_ETH:
7606*2d9fd380Sjfb8856606 			size = sizeof(struct rte_ether_hdr);
76074418919fSjohnjiang 			break;
76084418919fSjohnjiang 		case RTE_FLOW_ITEM_TYPE_VLAN:
7609*2d9fd380Sjfb8856606 			size = sizeof(struct rte_vlan_hdr);
76104418919fSjohnjiang 			proto = RTE_ETHER_TYPE_VLAN;
76114418919fSjohnjiang 			break;
76124418919fSjohnjiang 		case RTE_FLOW_ITEM_TYPE_IPV4:
7613*2d9fd380Sjfb8856606 			size = sizeof(struct rte_ipv4_hdr);
76144418919fSjohnjiang 			proto = RTE_ETHER_TYPE_IPV4;
76154418919fSjohnjiang 			break;
76164418919fSjohnjiang 		case RTE_FLOW_ITEM_TYPE_IPV6:
7617*2d9fd380Sjfb8856606 			size = sizeof(struct rte_ipv6_hdr);
76184418919fSjohnjiang 			proto = RTE_ETHER_TYPE_IPV6;
76194418919fSjohnjiang 			break;
76204418919fSjohnjiang 		case RTE_FLOW_ITEM_TYPE_UDP:
7621*2d9fd380Sjfb8856606 			size = sizeof(struct rte_udp_hdr);
76224418919fSjohnjiang 			proto = 0x11;
76234418919fSjohnjiang 			break;
76244418919fSjohnjiang 		case RTE_FLOW_ITEM_TYPE_TCP:
7625*2d9fd380Sjfb8856606 			size = sizeof(struct rte_tcp_hdr);
76264418919fSjohnjiang 			proto = 0x06;
76274418919fSjohnjiang 			break;
76284418919fSjohnjiang 		case RTE_FLOW_ITEM_TYPE_VXLAN:
7629*2d9fd380Sjfb8856606 			size = sizeof(struct rte_vxlan_hdr);
76304418919fSjohnjiang 			break;
76314418919fSjohnjiang 		case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
7632*2d9fd380Sjfb8856606 			size = sizeof(struct rte_vxlan_gpe_hdr);
76334418919fSjohnjiang 			break;
76344418919fSjohnjiang 		case RTE_FLOW_ITEM_TYPE_GRE:
7635*2d9fd380Sjfb8856606 			size = sizeof(struct rte_gre_hdr);
76364418919fSjohnjiang 			proto = 0x2F;
76374418919fSjohnjiang 			break;
76384418919fSjohnjiang 		case RTE_FLOW_ITEM_TYPE_GRE_KEY:
76394418919fSjohnjiang 			size = sizeof(rte_be32_t);
76404418919fSjohnjiang 			proto = 0x0;
76414418919fSjohnjiang 			break;
76424418919fSjohnjiang 		case RTE_FLOW_ITEM_TYPE_MPLS:
7643*2d9fd380Sjfb8856606 			size = sizeof(struct rte_mpls_hdr);
76444418919fSjohnjiang 			proto = 0x0;
76454418919fSjohnjiang 			break;
76464418919fSjohnjiang 		case RTE_FLOW_ITEM_TYPE_NVGRE:
76474418919fSjohnjiang 			size = sizeof(struct rte_flow_item_nvgre);
76484418919fSjohnjiang 			proto = 0x2F;
76494418919fSjohnjiang 			break;
76504418919fSjohnjiang 		case RTE_FLOW_ITEM_TYPE_GENEVE:
7651*2d9fd380Sjfb8856606 			size = sizeof(struct rte_geneve_hdr);
7652*2d9fd380Sjfb8856606 			break;
7653*2d9fd380Sjfb8856606 		case RTE_FLOW_ITEM_TYPE_L2TPV3OIP:
7654*2d9fd380Sjfb8856606 			size = sizeof(rte_be32_t);
7655*2d9fd380Sjfb8856606 			proto = 0x73;
7656*2d9fd380Sjfb8856606 			break;
7657*2d9fd380Sjfb8856606 		case RTE_FLOW_ITEM_TYPE_ESP:
7658*2d9fd380Sjfb8856606 			size = sizeof(struct rte_esp_hdr);
7659*2d9fd380Sjfb8856606 			proto = 0x32;
7660*2d9fd380Sjfb8856606 			break;
7661*2d9fd380Sjfb8856606 		case RTE_FLOW_ITEM_TYPE_AH:
7662*2d9fd380Sjfb8856606 			size = sizeof(struct rte_flow_item_ah);
7663*2d9fd380Sjfb8856606 			proto = 0x33;
7664*2d9fd380Sjfb8856606 			break;
7665*2d9fd380Sjfb8856606 		case RTE_FLOW_ITEM_TYPE_GTP:
7666*2d9fd380Sjfb8856606 			size = sizeof(struct rte_gtp_hdr);
7667*2d9fd380Sjfb8856606 			break;
7668*2d9fd380Sjfb8856606 		case RTE_FLOW_ITEM_TYPE_PFCP:
7669*2d9fd380Sjfb8856606 			size = sizeof(struct rte_flow_item_pfcp);
76704418919fSjohnjiang 			break;
76714418919fSjohnjiang 		default:
76724418919fSjohnjiang 			printf("Error - Not supported item\n");
76734418919fSjohnjiang 			*total_size = 0;
76744418919fSjohnjiang 			memset(data, 0x00, ACTION_RAW_ENCAP_MAX_DATA);
76754418919fSjohnjiang 			return;
76764418919fSjohnjiang 		}
76774418919fSjohnjiang 		*total_size += size;
76784418919fSjohnjiang 		rte_memcpy(data_tail - (*total_size), item->spec, size);
76794418919fSjohnjiang 		/* update some fields which cannot be set by cmdline */
76804418919fSjohnjiang 		update_fields((data_tail - (*total_size)), item,
76814418919fSjohnjiang 			      upper_layer);
76824418919fSjohnjiang 		upper_layer = proto;
76834418919fSjohnjiang 	}
76844418919fSjohnjiang 	if (verbose_level & 0x1)
76854418919fSjohnjiang 		printf("total data size is %zu\n", (*total_size));
76864418919fSjohnjiang 	RTE_ASSERT((*total_size) <= ACTION_RAW_ENCAP_MAX_DATA);
76874418919fSjohnjiang 	memmove(data, (data_tail - (*total_size)), *total_size);
76884418919fSjohnjiang }
76894418919fSjohnjiang 
76904418919fSjohnjiang /** Populate help strings for current token (cmdline API). */
76914418919fSjohnjiang static int
cmd_set_raw_get_help(cmdline_parse_token_hdr_t * hdr,char * dst,unsigned int size)76924418919fSjohnjiang cmd_set_raw_get_help(cmdline_parse_token_hdr_t *hdr, char *dst,
76934418919fSjohnjiang 		     unsigned int size)
76944418919fSjohnjiang {
76954418919fSjohnjiang 	struct context *ctx = &cmd_flow_context;
76964418919fSjohnjiang 	const struct token *token = &token_list[ctx->prev];
76974418919fSjohnjiang 
76984418919fSjohnjiang 	(void)hdr;
76994418919fSjohnjiang 	if (!size)
77004418919fSjohnjiang 		return -1;
77014418919fSjohnjiang 	/* Set token type and update global help with details. */
77024418919fSjohnjiang 	snprintf(dst, size, "%s", (token->type ? token->type : "TOKEN"));
77034418919fSjohnjiang 	if (token->help)
77044418919fSjohnjiang 		cmd_set_raw.help_str = token->help;
77054418919fSjohnjiang 	else
77064418919fSjohnjiang 		cmd_set_raw.help_str = token->name;
77074418919fSjohnjiang 	return 0;
77084418919fSjohnjiang }
77094418919fSjohnjiang 
77104418919fSjohnjiang /** Token definition template (cmdline API). */
77114418919fSjohnjiang static struct cmdline_token_hdr cmd_set_raw_token_hdr = {
77124418919fSjohnjiang 	.ops = &(struct cmdline_token_ops){
77134418919fSjohnjiang 		.parse = cmd_flow_parse,
77144418919fSjohnjiang 		.complete_get_nb = cmd_flow_complete_get_nb,
77154418919fSjohnjiang 		.complete_get_elt = cmd_flow_complete_get_elt,
77164418919fSjohnjiang 		.get_help = cmd_set_raw_get_help,
77174418919fSjohnjiang 	},
77184418919fSjohnjiang 	.offset = 0,
77194418919fSjohnjiang };
77204418919fSjohnjiang 
77214418919fSjohnjiang /** Populate the next dynamic token. */
77224418919fSjohnjiang static void
cmd_set_raw_tok(cmdline_parse_token_hdr_t ** hdr,cmdline_parse_token_hdr_t ** hdr_inst)77234418919fSjohnjiang cmd_set_raw_tok(cmdline_parse_token_hdr_t **hdr,
77244418919fSjohnjiang 	     cmdline_parse_token_hdr_t **hdr_inst)
77254418919fSjohnjiang {
77264418919fSjohnjiang 	struct context *ctx = &cmd_flow_context;
77274418919fSjohnjiang 
77284418919fSjohnjiang 	/* Always reinitialize context before requesting the first token. */
77294418919fSjohnjiang 	if (!(hdr_inst - cmd_set_raw.tokens)) {
77304418919fSjohnjiang 		cmd_flow_context_init(ctx);
77314418919fSjohnjiang 		ctx->curr = START_SET;
77324418919fSjohnjiang 	}
77334418919fSjohnjiang 	/* Return NULL when no more tokens are expected. */
77344418919fSjohnjiang 	if (!ctx->next_num && (ctx->curr != START_SET)) {
77354418919fSjohnjiang 		*hdr = NULL;
77364418919fSjohnjiang 		return;
77374418919fSjohnjiang 	}
77384418919fSjohnjiang 	/* Determine if command should end here. */
77394418919fSjohnjiang 	if (ctx->eol && ctx->last && ctx->next_num) {
77404418919fSjohnjiang 		const enum index *list = ctx->next[ctx->next_num - 1];
77414418919fSjohnjiang 		int i;
77424418919fSjohnjiang 
77434418919fSjohnjiang 		for (i = 0; list[i]; ++i) {
77444418919fSjohnjiang 			if (list[i] != END)
77454418919fSjohnjiang 				continue;
77464418919fSjohnjiang 			*hdr = NULL;
77474418919fSjohnjiang 			return;
77484418919fSjohnjiang 		}
77494418919fSjohnjiang 	}
77504418919fSjohnjiang 	*hdr = &cmd_set_raw_token_hdr;
77514418919fSjohnjiang }
77524418919fSjohnjiang 
77534418919fSjohnjiang /** Token generator and output processing callback (cmdline API). */
77544418919fSjohnjiang static void
cmd_set_raw_cb(void * arg0,struct cmdline * cl,void * arg2)77554418919fSjohnjiang cmd_set_raw_cb(void *arg0, struct cmdline *cl, void *arg2)
77564418919fSjohnjiang {
77574418919fSjohnjiang 	if (cl == NULL)
77584418919fSjohnjiang 		cmd_set_raw_tok(arg0, arg2);
77594418919fSjohnjiang 	else
77604418919fSjohnjiang 		cmd_set_raw_parsed(arg0);
77614418919fSjohnjiang }
77624418919fSjohnjiang 
77634418919fSjohnjiang /** Global parser instance (cmdline API). */
77644418919fSjohnjiang cmdline_parse_inst_t cmd_set_raw = {
77654418919fSjohnjiang 	.f = cmd_set_raw_cb,
77664418919fSjohnjiang 	.data = NULL, /**< Unused. */
77674418919fSjohnjiang 	.help_str = NULL, /**< Updated by cmd_flow_get_help(). */
77684418919fSjohnjiang 	.tokens = {
77694418919fSjohnjiang 		NULL,
77704418919fSjohnjiang 	}, /**< Tokens are returned by cmd_flow_tok(). */
77714418919fSjohnjiang };
77724418919fSjohnjiang 
77734418919fSjohnjiang /* *** display raw_encap/raw_decap buf */
77744418919fSjohnjiang struct cmd_show_set_raw_result {
77754418919fSjohnjiang 	cmdline_fixed_string_t cmd_show;
77764418919fSjohnjiang 	cmdline_fixed_string_t cmd_what;
77774418919fSjohnjiang 	cmdline_fixed_string_t cmd_all;
77784418919fSjohnjiang 	uint16_t cmd_index;
77794418919fSjohnjiang };
77804418919fSjohnjiang 
77814418919fSjohnjiang static void
cmd_show_set_raw_parsed(void * parsed_result,struct cmdline * cl,void * data)77824418919fSjohnjiang cmd_show_set_raw_parsed(void *parsed_result, struct cmdline *cl, void *data)
77834418919fSjohnjiang {
77844418919fSjohnjiang 	struct cmd_show_set_raw_result *res = parsed_result;
77854418919fSjohnjiang 	uint16_t index = res->cmd_index;
77864418919fSjohnjiang 	uint8_t all = 0;
77874418919fSjohnjiang 	uint8_t *raw_data = NULL;
77884418919fSjohnjiang 	size_t raw_size = 0;
77894418919fSjohnjiang 	char title[16] = {0};
77904418919fSjohnjiang 
77914418919fSjohnjiang 	RTE_SET_USED(cl);
77924418919fSjohnjiang 	RTE_SET_USED(data);
77934418919fSjohnjiang 	if (!strcmp(res->cmd_all, "all")) {
77944418919fSjohnjiang 		all = 1;
77954418919fSjohnjiang 		index = 0;
77964418919fSjohnjiang 	} else if (index >= RAW_ENCAP_CONFS_MAX_NUM) {
77974418919fSjohnjiang 		printf("index should be 0-%u\n", RAW_ENCAP_CONFS_MAX_NUM - 1);
77984418919fSjohnjiang 		return;
77994418919fSjohnjiang 	}
78004418919fSjohnjiang 	do {
78014418919fSjohnjiang 		if (!strcmp(res->cmd_what, "raw_encap")) {
78024418919fSjohnjiang 			raw_data = (uint8_t *)&raw_encap_confs[index].data;
78034418919fSjohnjiang 			raw_size = raw_encap_confs[index].size;
78044418919fSjohnjiang 			snprintf(title, 16, "\nindex: %u", index);
78054418919fSjohnjiang 			rte_hexdump(stdout, title, raw_data, raw_size);
78064418919fSjohnjiang 		} else {
78074418919fSjohnjiang 			raw_data = (uint8_t *)&raw_decap_confs[index].data;
78084418919fSjohnjiang 			raw_size = raw_decap_confs[index].size;
78094418919fSjohnjiang 			snprintf(title, 16, "\nindex: %u", index);
78104418919fSjohnjiang 			rte_hexdump(stdout, title, raw_data, raw_size);
78114418919fSjohnjiang 		}
78124418919fSjohnjiang 	} while (all && ++index < RAW_ENCAP_CONFS_MAX_NUM);
78134418919fSjohnjiang }
78144418919fSjohnjiang 
78154418919fSjohnjiang cmdline_parse_token_string_t cmd_show_set_raw_cmd_show =
78164418919fSjohnjiang 	TOKEN_STRING_INITIALIZER(struct cmd_show_set_raw_result,
78174418919fSjohnjiang 			cmd_show, "show");
78184418919fSjohnjiang cmdline_parse_token_string_t cmd_show_set_raw_cmd_what =
78194418919fSjohnjiang 	TOKEN_STRING_INITIALIZER(struct cmd_show_set_raw_result,
78204418919fSjohnjiang 			cmd_what, "raw_encap#raw_decap");
78214418919fSjohnjiang cmdline_parse_token_num_t cmd_show_set_raw_cmd_index =
78224418919fSjohnjiang 	TOKEN_NUM_INITIALIZER(struct cmd_show_set_raw_result,
7823*2d9fd380Sjfb8856606 			cmd_index, RTE_UINT16);
78244418919fSjohnjiang cmdline_parse_token_string_t cmd_show_set_raw_cmd_all =
78254418919fSjohnjiang 	TOKEN_STRING_INITIALIZER(struct cmd_show_set_raw_result,
78264418919fSjohnjiang 			cmd_all, "all");
78274418919fSjohnjiang cmdline_parse_inst_t cmd_show_set_raw = {
78284418919fSjohnjiang 	.f = cmd_show_set_raw_parsed,
78294418919fSjohnjiang 	.data = NULL,
78304418919fSjohnjiang 	.help_str = "show <raw_encap|raw_decap> <index>",
78314418919fSjohnjiang 	.tokens = {
78324418919fSjohnjiang 		(void *)&cmd_show_set_raw_cmd_show,
78334418919fSjohnjiang 		(void *)&cmd_show_set_raw_cmd_what,
78344418919fSjohnjiang 		(void *)&cmd_show_set_raw_cmd_index,
78354418919fSjohnjiang 		NULL,
78364418919fSjohnjiang 	},
78374418919fSjohnjiang };
78384418919fSjohnjiang cmdline_parse_inst_t cmd_show_set_raw_all = {
78394418919fSjohnjiang 	.f = cmd_show_set_raw_parsed,
78404418919fSjohnjiang 	.data = NULL,
78414418919fSjohnjiang 	.help_str = "show <raw_encap|raw_decap> all",
78424418919fSjohnjiang 	.tokens = {
78434418919fSjohnjiang 		(void *)&cmd_show_set_raw_cmd_show,
78444418919fSjohnjiang 		(void *)&cmd_show_set_raw_cmd_what,
78454418919fSjohnjiang 		(void *)&cmd_show_set_raw_cmd_all,
78464418919fSjohnjiang 		NULL,
78474418919fSjohnjiang 	},
78484418919fSjohnjiang };
7849