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