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