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