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